This commit is contained in:
David Arranz 2026-05-06 13:10:47 +02:00
parent 0fc0717822
commit 2c6cac4859
26 changed files with 171 additions and 119 deletions

View File

@ -19,5 +19,12 @@
"factuges_id": "15", "factuges_id": "15",
"description": "TRANSFERENCIA BANCARIA", "description": "TRANSFERENCIA BANCARIA",
"group": "General" "group": "General"
},
{
"id": "126e477f-9260-4cb7-b6fd-76f3b088a395",
"company_id": "5e4dc5b3-96b9-4968-9490-14bd032fec5f",
"factuges_id": "21",
"description": "30/60/90/120",
"group": "General"
} }
] ]

View File

@ -29,6 +29,13 @@ const toNumericString = (dto?: MoneyDTO | null, fallbackScale = 2): string => {
return toNumber(dto, fallbackScale).toString(); return toNumber(dto, fallbackScale).toString();
}; };
const toNumericNulleable = (dto?: MoneyDTO | null, fallbackScale = 2): number | null => {
if (isEmptyMoneyDTO(dto)) {
return null;
}
return toNumber(dto, fallbackScale);
};
/** /**
* Formatea un MoneyDTO según un locale. * Formatea un MoneyDTO según un locale.
* *
@ -117,6 +124,7 @@ export const MoneyDTOHelper = {
isEmpty: isEmptyMoneyDTO, isEmpty: isEmptyMoneyDTO,
toNumber, toNumber,
toNumericString, toNumericString,
toNumericNulleable,
fromNumber, fromNumber,
fromNumericString, fromNumericString,
format, format,

View File

@ -25,6 +25,13 @@ const toNumericString = (dto?: PercentageDTO | null, fallbackScale = 2): string
return toNumber(dto, fallbackScale).toString(); return toNumber(dto, fallbackScale).toString();
}; };
const toNumericNulleable = (dto?: PercentageDTO | null, fallbackScale = 2): number | null => {
if (isEmptyPercentageDTO(dto)) {
return null;
}
return toNumber(dto, fallbackScale);
};
/** /**
* Formatea un PercentageDTO según un locale. * Formatea un PercentageDTO según un locale.
* *
@ -97,6 +104,7 @@ export const PercentageDTOHelper = {
isEmpty: isEmptyPercentageDTO, isEmpty: isEmptyPercentageDTO,
toNumber, toNumber,
toNumericString, toNumericString,
toNumericNulleable,
fromNumber, fromNumber,
fromNumericString, fromNumericString,
format, format,

View File

@ -25,6 +25,13 @@ const toNumericString = (dto?: QuantityDTO | null, fallbackScale = 2): string =>
return toNumber(dto, fallbackScale).toString(); return toNumber(dto, fallbackScale).toString();
}; };
const toNumericNulleable = (dto?: QuantityDTO | null, fallbackScale = 2): number | null => {
if (isEmptyQuantityDTO(dto)) {
return null;
}
return toNumber(dto, fallbackScale);
};
/** /**
* Formatea un QuantityDTO según un locale. * Formatea un QuantityDTO según un locale.
* *
@ -91,6 +98,7 @@ export const QuantityDTOHelper = {
isEmpty: isEmptyQuantityDTO, isEmpty: isEmptyQuantityDTO,
toNumber, toNumber,
toNumericString, toNumericString,
toNumericNulleable,
fromNumber, fromNumber,
fromNumericString, fromNumericString,
format, format,

View File

@ -1,4 +1,4 @@
import { useDebounce } from "@repo/rdx-ui/components"; import { useDebounce } from "@erp/core/hooks";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import type { import type {

View File

@ -40,7 +40,7 @@ export const GetProformaByIdAdapter = {
currencyCode: dto.currency_code, currencyCode: dto.currency_code,
customerId: dto.customer_id, customerId: dto.customer_id,
recipient: mapRecipient(dto.recipient), recipient: mapRecipient(dto),
taxes: dto.taxes.map(mapTaxSummary), taxes: dto.taxes.map(mapTaxSummary),
paymentMethod: dto.payment_method?.id, paymentMethod: dto.payment_method?.id,
@ -48,8 +48,8 @@ export const GetProformaByIdAdapter = {
subtotalAmount: MoneyDTOHelper.toNumber(dto.subtotal_amount), subtotalAmount: MoneyDTOHelper.toNumber(dto.subtotal_amount),
itemsDiscountAmount: MoneyDTOHelper.toNumber(dto.items_discount_amount), itemsDiscountAmount: MoneyDTOHelper.toNumber(dto.items_discount_amount),
globalDiscountPercentage: PercentageDTOHelper.toNumber(dto.discount_percentage), globalDiscountPercentage: PercentageDTOHelper.toNumber(dto.global_discount_percentage),
discountAmount: MoneyDTOHelper.toNumber(dto.discount_amount), totalDiscountAmount: MoneyDTOHelper.toNumber(dto.total_discount_amount),
taxableAmount: MoneyDTOHelper.toNumber(dto.taxable_amount), taxableAmount: MoneyDTOHelper.toNumber(dto.taxable_amount),
ivaAmount: MoneyDTOHelper.toNumber(dto.iva_amount), ivaAmount: MoneyDTOHelper.toNumber(dto.iva_amount),
@ -65,19 +65,19 @@ export const GetProformaByIdAdapter = {
}; };
const mapItem = (dto: GetProformaByIdResponseDTO["items"][number]): ProformaItem => { const mapItem = (dto: GetProformaByIdResponseDTO["items"][number]): ProformaItem => {
return { const item: ProformaItem = {
id: dto.id, id: dto.id,
position: Number(dto.position), position: Number(dto.position),
isValued: dto.is_valued, isValued: dto.is_valued,
description: dto.description, description: dto.description,
quantity: QuantityDTOHelper.toNumber(dto.quantity), quantity: QuantityDTOHelper.toNumericNulleable(dto.quantity),
unitAmount: MoneyDTOHelper.toNumber(dto.unit_amount), unitAmount: MoneyDTOHelper.toNumericNulleable(dto.unit_amount),
subtotalAmount: MoneyDTOHelper.toNumber(dto.subtotal_amount), subtotalAmount: MoneyDTOHelper.toNumber(dto.subtotal_amount),
itemDiscountPercentage: PercentageDTOHelper.toNumber(dto.item_discount_percentage), itemDiscountPercentage: PercentageDTOHelper.toNumericNulleable(dto.item_discount_percentage),
itemDiscountAmount: MoneyDTOHelper.toNumber(dto.item_discount_amount), itemDiscountAmount: MoneyDTOHelper.toNumber(dto.item_discount_amount),
globalDiscountPercentage: PercentageDTOHelper.toNumber(dto.global_discount_percentage), globalDiscountPercentage: PercentageDTOHelper.toNumber(dto.global_discount_percentage),
@ -104,18 +104,20 @@ const mapItem = (dto: GetProformaByIdResponseDTO["items"][number]): ProformaItem
// Dejamos fallback explícito para no inventar parseos. // Dejamos fallback explícito para no inventar parseos.
taxes: "", taxes: "",
}; };
return item;
}; };
const mapRecipient = (dto: GetProformaByIdResponseDTO["recipient"]): ProformaRecipient => { const mapRecipient = (dto: GetProformaByIdResponseDTO): ProformaRecipient => {
return { return {
id: dto.id, id: dto.customer_id,
name: dto.name, name: dto.recipient.name,
tin: dto.tin, tin: dto.recipient.tin,
street: dto.street, street: dto.recipient.street,
street2: dto.street2, street2: dto.recipient.street2,
city: dto.city, city: dto.recipient.city,
province: dto.province, province: dto.recipient.province,
postalCode: dto.postal_code, postalCode: dto.recipient.postal_code,
country: dto.country, country: dto.recipient.country,
}; };
}; };

View File

@ -40,8 +40,7 @@ export const ProformaToListRowPatchAdapter = {
country: proforma.recipient.country, country: proforma.recipient.country,
}, },
subtotalAmount: proforma.subtotalAmount, subtotalAmount: proforma.subtotalAmount,
discountPercentage: proforma.globalDiscountPercentage, totalDiscountAmount: proforma.totalDiscountAmount,
discountAmount: proforma.discountAmount,
taxableAmount: proforma.taxableAmount, taxableAmount: proforma.taxableAmount,
taxesAmount: proforma.taxesAmount, taxesAmount: proforma.taxesAmount,
totalAmount: proforma.totalAmount, totalAmount: proforma.totalAmount,

View File

@ -9,14 +9,14 @@ export interface ProformaItem {
position: number; position: number;
isValued: boolean; isValued: boolean;
description: string; description: string | null;
quantity: number; quantity: number | null;
unitAmount: number; unitAmount: number | null;
subtotalAmount: number; subtotalAmount: number;
itemDiscountPercentage: number; itemDiscountPercentage: number | null;
itemDiscountAmount: number; itemDiscountAmount: number;
globalDiscountPercentage: number; globalDiscountPercentage: number;
@ -28,11 +28,11 @@ export interface ProformaItem {
ivaPercentage: number; ivaPercentage: number;
ivaAmount: number; ivaAmount: number;
recCode: string; recCode: string | null;
recPercentage: number; recPercentage: number;
recAmount: number; recAmount: number;
retentionCode: string; retentionCode: string | null;
retentionPercentage: number; retentionPercentage: number;
retentionAmount: number; retentionAmount: number;

View File

@ -11,11 +11,11 @@ export interface ProformaTaxSummary {
ivaPercentage: number; ivaPercentage: number;
ivaAmount: number; ivaAmount: number;
recCode: string; recCode: string | null;
recPercentage: number; recPercentage: number;
recAmount: number; recAmount: number;
retentionCode: string; retentionCode: string | null;
retentionPercentage: number; retentionPercentage: number;
retentionAmount: number; retentionAmount: number;

View File

@ -13,18 +13,17 @@ import type { ProformaTaxSummary } from "./proforma-tax-summary.entity";
export interface Proforma { export interface Proforma {
id: string; id: string;
companyId: string; companyId: string;
isProforma: boolean;
invoiceNumber: string; invoiceNumber: string;
status: ProformaStatus; status: ProformaStatus;
series: string; series: string | null;
invoiceDate: string; invoiceDate: string;
operationDate: string; operationDate: string | null;
reference: string; reference: string | null;
description: string; description: string | null;
notes: string; notes: string | null;
languageCode: string; languageCode: string;
currencyCode: string; currencyCode: string;
@ -40,7 +39,7 @@ export interface Proforma {
itemsDiscountAmount: number; itemsDiscountAmount: number;
globalDiscountPercentage: number; globalDiscountPercentage: number;
discountAmount: number; totalDiscountAmount: number;
taxableAmount: number; taxableAmount: number;
ivaAmount: number; ivaAmount: number;

View File

@ -11,6 +11,7 @@ import type { ProformaItemUpdateForm } from "../entities";
export const mapProformaItemsToProformaItemsUpdateForm = ( export const mapProformaItemsToProformaItemsUpdateForm = (
item: ProformaItem item: ProformaItem
): ProformaItemUpdateForm => { ): ProformaItemUpdateForm => {
console.log(item);
return { return {
id: item.id, id: item.id,
position: item.position, position: item.position,

View File

@ -74,6 +74,8 @@ export const useUpdateProformaController = (
const initialValues = useMemo<ProformaUpdateForm>(() => { const initialValues = useMemo<ProformaUpdateForm>(() => {
if (!proformaData) return buildProformaUpdateDefault(); if (!proformaData) return buildProformaUpdateDefault();
console.log("initialValues", proformaData);
return mapProformaToProformaUpdateForm(proformaData); return mapProformaToProformaUpdateForm(proformaData);
}, [proformaData]); }, [proformaData]);

View File

@ -178,7 +178,7 @@ export const LineEditor = <TLine,>({
} }
/> />
<DropdownMenuContent align="end"> <DropdownMenuContent align="end" className="min-w-48">
<DropdownMenuItem onClick={() => onAddBefore(index)}> <DropdownMenuItem onClick={() => onAddBefore(index)}>
<PlusCircle className="mr-2 h-4 w-4" /> <PlusCircle className="mr-2 h-4 w-4" />
{insertBeforeLabel} {insertBeforeLabel}

View File

@ -8,7 +8,7 @@ export const buildProformaItemUpdateDefault = (position: number): ProformaItemUp
position, position,
isValued: false, isValued: false,
description: "", description: null,
quantity: null, quantity: null,
unitAmount: null, unitAmount: null,

View File

@ -1,4 +1,5 @@
import type { ICatalogs, ITransactionManager } from "@erp/core/api"; import type { ICatalogs, ITransactionManager } from "@erp/core/api";
import type { IProformaPublicServices } from "@erp/customer-invoices/api";
import type { ICustomerPublicServices } from "@erp/customers/api"; import type { ICustomerPublicServices } from "@erp/customers/api";
import type { ICreateProformaFromFactugesInputMapper } from "../mappers"; import type { ICreateProformaFromFactugesInputMapper } from "../mappers";
@ -10,6 +11,7 @@ export function buildCreateProformaFromFactugesUseCase(deps: {
finder: IFactuGESProformaFinder; finder: IFactuGESProformaFinder;
publicServices: { publicServices: {
customerServices: ICustomerPublicServices; customerServices: ICustomerPublicServices;
proformaServices: IProformaPublicServices;
}; };
dtoMapper: ICreateProformaFromFactugesInputMapper; dtoMapper: ICreateProformaFromFactugesInputMapper;
catalogs: ICatalogs; catalogs: ICatalogs;
@ -17,18 +19,21 @@ export function buildCreateProformaFromFactugesUseCase(deps: {
}) { }) {
const { const {
linker, linker,
finder,
dtoMapper, dtoMapper,
transactionManager, transactionManager,
publicServices: { customerServices }, publicServices: { customerServices, proformaServices },
} = deps; } = deps;
const { taxCatalog } = deps.catalogs; const { taxCatalog, paymentCatalog } = deps.catalogs;
return new CreateProformaFromFactugesUseCase({ return new CreateProformaFromFactugesUseCase({
linker, linker,
finder, finder,
customerServices, customerServices,
proformaServices,
dtoMapper, dtoMapper,
taxCatalog, taxCatalog,
paymentCatalog,
transactionManager, transactionManager,
}); });
} }

View File

@ -1,2 +1,2 @@
export * from "./factuges-input-mappers.di";
export * from "./factuges-use-cases.di"; export * from "./factuges-use-cases.di";
export * from "./factuges-input-mappers.di"

View File

@ -1,3 +1,2 @@
export * from "./mappers";
export * from "./repositories"; export * from "./repositories";
export * from "./use-cases"; export * from "./use-cases";

View File

@ -164,8 +164,6 @@ export class CreateProformaFromFactugesInputMapper
errors, errors,
}); });
console.log(paymentProps);
this.throwIfValidationErrors(errors); this.throwIfValidationErrors(errors);
return Result.ok({ return Result.ok({
@ -173,7 +171,7 @@ export class CreateProformaFromFactugesInputMapper
tin: customerProps.tin, tin: customerProps.tin,
}, },
paymentLookup: { paymentLookup: {
factuges_id: paymentProps.factuges_id, factuges_id: paymentProps?.factuges_id,
}, },
customerDraft: customerProps, customerDraft: customerProps,
proformaDraft: proformaProps, proformaDraft: proformaProps,
@ -195,25 +193,25 @@ export class CreateProformaFromFactugesInputMapper
currencyCode: CurrencyCode; currencyCode: CurrencyCode;
errors: ValidationErrorDetail[]; errors: ValidationErrorDetail[];
} }
): ProformaPaymentDraft { ): ProformaPaymentDraft | undefined {
const errors: ValidationErrorDetail[] = []; const errors: ValidationErrorDetail[] = [];
const { companyId } = params; const { companyId } = params;
const factuges_id = String(dto.payment_method_id); const payment_method_id = String(dto.payment_method_id);
const paymentOrNot = this.paymentCatalog.findByFactuGESId(factuges_id); const paymentOrNot = this.paymentCatalog.findByFactuGESId(payment_method_id);
if (paymentOrNot.isNone()) { if (paymentOrNot.isNone()) {
errors.push({ errors.push({
path: "payment_method_id", path: "payment_method_id",
message: "Forma de pago no encontrada", message: "Forma de pago no encontrada",
}); });
} else {
return {
payment_id: paymentOrNot.unwrap().id,
factuges_id: paymentOrNot.unwrap().factuges_id,
description: paymentOrNot.unwrap().description,
};
} }
return {
payment_id: paymentOrNot.unwrap().id,
factuges_id: paymentOrNot.unwrap().factuges_id,
description: paymentOrNot.unwrap().description,
};
} }
private mapProformaProps( private mapProformaProps(

View File

@ -1,4 +1,4 @@
import type { JsonTaxCatalogProvider } from "@erp/core"; import type { JsonPaymentCatalogProvider, JsonTaxCatalogProvider } from "@erp/core";
import { type ITransactionManager, isEntityNotFoundError } from "@erp/core/api"; import { type ITransactionManager, isEntityNotFoundError } from "@erp/core/api";
import type { IProformaPublicServices } from "@erp/customer-invoices/api"; import type { IProformaPublicServices } from "@erp/customer-invoices/api";
import { import {
@ -30,19 +30,31 @@ import type { CreateProformaFromFactugesRequestDTO } from "../../../common";
import type { FactugesProformaPayload, ICreateProformaFromFactugesInputMapper } from "../mappers"; import type { FactugesProformaPayload, ICreateProformaFromFactugesInputMapper } from "../mappers";
import type { IFactuGESProformaFinder, IFactuGESProformaLinker } from "../services"; import type { IFactuGESProformaFinder, IFactuGESProformaLinker } from "../services";
import paymentsCatalog from "./payments.json";
type FakePaymentMethod = {
id: UniqueID;
description: string;
factuges_id: string;
};
type CreateProformaFromFactugesUseCaseInput = { type CreateProformaFromFactugesUseCaseInput = {
companyId: UniqueID; companyId: UniqueID;
dto: CreateProformaFromFactugesRequestDTO; dto: CreateProformaFromFactugesRequestDTO;
}; };
export type CreateProformaFromFactugesResponseDTO = {
proforma_id: string;
};
export type ResolvedPaymentMethod = {
id: UniqueID;
description: string;
factugesId: string;
};
export interface IFactugesPaymentMethodResolver {
resolve(
lookup: FactugesProformaPayload["paymentLookup"],
context: {
companyId: UniqueID;
transaction: Transaction;
}
): Promise<Result<ResolvedPaymentMethod, Error>>;
}
type CreateProformaFromFactugesUseCaseDeps = { type CreateProformaFromFactugesUseCaseDeps = {
linker: IFactuGESProformaLinker; linker: IFactuGESProformaLinker;
finder: IFactuGESProformaFinder; finder: IFactuGESProformaFinder;
@ -50,17 +62,19 @@ type CreateProformaFromFactugesUseCaseDeps = {
proformaServices: IProformaPublicServices; proformaServices: IProformaPublicServices;
dtoMapper: ICreateProformaFromFactugesInputMapper; dtoMapper: ICreateProformaFromFactugesInputMapper;
taxCatalog: JsonTaxCatalogProvider; taxCatalog: JsonTaxCatalogProvider;
paymentCatalog: JsonPaymentCatalogProvider;
transactionManager: ITransactionManager; transactionManager: ITransactionManager;
}; };
type CreateProformaProps = Parameters<IProformaPublicServices["createProforma"]>["1"]; type CreateProformaProps = Parameters<IProformaPublicServices["createProforma"]>["1"];
export class CreateProformaFromFactugesUseCase { export class CreateProformaFromFactugesUseCase {
private readonly dtoMapper: ICreateProformaFromFactugesInputMapper;
private readonly linker: IFactuGESProformaLinker; private readonly linker: IFactuGESProformaLinker;
private readonly finder: IFactuGESProformaFinder; private readonly finder: IFactuGESProformaFinder;
private readonly dtoMapper: ICreateProformaFromFactugesInputMapper;
private readonly customerServices: ICustomerPublicServices; private readonly customerServices: ICustomerPublicServices;
private readonly proformaServices: IProformaPublicServices; private readonly proformaServices: IProformaPublicServices;
private readonly paymentCatalog: JsonPaymentCatalogProvider;
private readonly taxCatalog: JsonTaxCatalogProvider; private readonly taxCatalog: JsonTaxCatalogProvider;
private readonly transactionManager: ITransactionManager; private readonly transactionManager: ITransactionManager;
@ -70,11 +84,14 @@ export class CreateProformaFromFactugesUseCase {
this.customerServices = deps.customerServices; this.customerServices = deps.customerServices;
this.proformaServices = deps.proformaServices; this.proformaServices = deps.proformaServices;
this.dtoMapper = deps.dtoMapper; this.dtoMapper = deps.dtoMapper;
this.paymentCatalog = deps.paymentCatalog;
this.taxCatalog = deps.taxCatalog; this.taxCatalog = deps.taxCatalog;
this.transactionManager = deps.transactionManager; this.transactionManager = deps.transactionManager;
} }
public async execute(params: CreateProformaFromFactugesUseCaseInput) { public async execute(
params: CreateProformaFromFactugesUseCaseInput
): Promise<Result<CreateProformaFromFactugesResponseDTO, Error>> {
const { dto, companyId } = params; const { dto, companyId } = params;
// 1) Mapear DTO → props // 1) Mapear DTO → props
@ -87,16 +104,25 @@ export class CreateProformaFromFactugesUseCase {
mappedPropsResult.data; mappedPropsResult.data;
// 2) Comprobar si la proforma ya existe (idempotencia) // 2) Comprobar si la proforma ya existe (idempotencia)
const proformaIdResult = await this.finder.findProformaIdByFactuGESId( const proformaExists = await this.finder.existsProformaByFactuGESId(
companyId, companyId,
proformaDraft.factugesID proformaDraft.factugesID
); );
if (proformaIdResult.isSuccess) { if (proformaExists.isSuccess && proformaExists.data) {
const existingProforma = proformaIdResult.data; // 2.1) Recuperar el ID de la proforma que ya existe
const proformaIdResult = await this.finder.findProformaIdByFactuGESId(
companyId,
proformaDraft.factugesID
);
if (proformaIdResult.isFailure) {
return Result.fail(proformaIdResult.error);
}
const proformaId = proformaIdResult.data;
return Result.ok({ return Result.ok({
proforma_id: existingProforma.toString(), proforma_id: proformaId.toString(),
}); });
} }
@ -113,7 +139,7 @@ export class CreateProformaFromFactugesUseCase {
const customer = customerResult.data; const customer = customerResult.data;
const paymentResult = await this.resolvePayment(paymentLookup, paymentDraft, { const paymentResult = await this.resolvePayment(paymentLookup, {
companyId, companyId,
transaction, transaction,
}); });
@ -338,7 +364,7 @@ export class CreateProformaFromFactugesUseCase {
private buildProformaCreateProps(deps: { private buildProformaCreateProps(deps: {
proformaDraft: FactugesProformaPayload["proformaDraft"]; proformaDraft: FactugesProformaPayload["proformaDraft"];
customerId: UniqueID; customerId: UniqueID;
payment: FakePaymentMethod; payment: ResolvedPaymentMethod;
context: { context: {
companyId: UniqueID; companyId: UniqueID;
transaction: Transaction; transaction: Transaction;
@ -410,31 +436,35 @@ export class CreateProformaFromFactugesUseCase {
}); });
} }
private async resolvePayment( private resolvePayment(
paymentLookup: FactugesProformaPayload["paymentLookup"], paymentLookup: FactugesProformaPayload["paymentLookup"],
paymentDraft: FactugesProformaPayload["paymentDraft"], context: { companyId: UniqueID; transaction: Transaction }
context: { ): Result<ResolvedPaymentMethod, Error> {
companyId: UniqueID; const payment = this.paymentCatalog.findByFactuGESId(paymentLookup.factuges_id);
transaction: Transaction;
}
): Promise<Result<FakePaymentMethod, Error>> {
const { companyId, transaction } = context;
const existingPaymentResult = paymentsCatalog.find( if (payment.isNone()) {
(payment) => return Result.fail(new Error("La forma de pago de FactuGES no existe."));
payment.factuges_id === paymentLookup.factuges_id &&
payment.company_id === companyId.toString()
);
if (existingPaymentResult) {
return Result.ok({
id: UniqueID.create(existingPaymentResult.id).data,
description: existingPaymentResult.description,
factuges_id: existingPaymentResult.factuges_id,
});
} }
return Result.fail(new Error("Forma de pago no existe!!!")); const paymentItem = payment.unwrap();
if (paymentItem.company_id !== context.companyId.toString()) {
return Result.fail(
new Error("La forma de pago de FactuGES no pertenece a la compañía actual.")
);
}
const idResult = UniqueID.create(paymentItem.id);
if (idResult.isFailure) {
return Result.fail(idResult.error);
}
return Result.ok({
id: idResult.data,
description: paymentItem.description,
factugesId: paymentItem.factuges_id,
});
} }
private buildCustomerCreateProps( private buildCustomerCreateProps(

View File

@ -1,23 +0,0 @@
[
{
"id": "019c2834-a766-7787-a626-fa89cac3a8a1",
"company_id": "5e4dc5b3-96b9-4968-9490-14bd032fec5f",
"factuges_id": "6",
"description": "TRANSFERENCIA",
"group": "General"
},
{
"id": "57ed228f-88bd-431d-b5e6-0ed9cff01684",
"company_id": "5e4dc5b3-96b9-4968-9490-14bd032fec5f",
"factuges_id": "14",
"description": "DOMICILIACION BANCARIA",
"group": "General"
},
{
"id": "336e477f-9260-4cb7-b6fd-76f3b088a395",
"company_id": "5e4dc5b3-96b9-4968-9490-14bd032fec5f",
"factuges_id": "15",
"description": "TRANSFERENCIA BANCARIA",
"group": "General"
}
]

View File

@ -1,6 +1,6 @@
import type { IModuleServer } from "@erp/core/api"; import type { IModuleServer } from "@erp/core/api";
import { factugesRouter } from "./infraestructure"; import { factugesRouter, models } from "./infraestructure";
import { buildFactugesDependencies } from "./infraestructure/di"; import { buildFactugesDependencies } from "./infraestructure/di";
export const factugesAPIModule: IModuleServer = { export const factugesAPIModule: IModuleServer = {
@ -28,7 +28,7 @@ export const factugesAPIModule: IModuleServer = {
return { return {
// Modelos Sequelize del módulo // Modelos Sequelize del módulo
models: [], models,
// Servicios expuestos a otros módulos // Servicios expuestos a otros módulos
services: {}, services: {},

View File

@ -41,7 +41,10 @@ export function buildFactugesDependencies(params: SetupParams): FactugesInternal
// Internal use cases (factories) // Internal use cases (factories)
return { return {
useCases: { useCases: {
createProforma: (publicServices: { customerServices: ICustomerPublicServices }) => createProforma: (publicServices: {
customerServices: ICustomerPublicServices;
proformaServices: IProformaPublicServices;
}) =>
buildCreateProformaFromFactugesUseCase({ buildCreateProformaFromFactugesUseCase({
linker, linker,
finder, finder,

View File

@ -29,6 +29,11 @@ export class CreateProformaFromFactugesController extends ExpressController {
} }
const dto = this.req.body as CreateProformaFromFactugesRequestDTO; const dto = this.req.body as CreateProformaFromFactugesRequestDTO;
// Request mapper
// Command for use case
// Execute use case
const result = await this.useCase.execute({ dto, companyId }); const result = await this.useCase.execute({ dto, companyId });
return result.match( return result.match(

View File

@ -40,7 +40,7 @@ export function extractOrPushError<T>(
if (isValidationErrorCollection(error)) { if (isValidationErrorCollection(error)) {
// Copiar todos los detalles, rellenando path si falta // Copiar todos los detalles, rellenando path si falta
console.log(error);
error.details?.forEach((detail) => { error.details?.forEach((detail) => {
errors.push({ errors.push({
...detail, ...detail,

View File

@ -99,7 +99,7 @@ export class Collection<T> {
* @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array. * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/ */
forEach<U>(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void { forEach<U>(callbackfn: (value: T, index: number, array: T[]) => void, _thisArg?: unknown): void {
this.items.forEach(callbackfn); this.items.forEach(callbackfn);
} }