From 2c6cac485987049869b7a01c0bc1fc58bca9d9dc Mon Sep 17 00:00:00 2001 From: david Date: Wed, 6 May 2026 13:10:47 +0200 Subject: [PATCH] . --- .../payments/factuges-payment-catalog.json | 7 ++ .../src/common/helpers/money-dto-helper.ts | 8 ++ .../common/helpers/percentage-dto-helper.ts | 8 ++ .../src/common/helpers/quantity-dto-helper.ts | 8 ++ .../use-issued-invoice-list.controller.ts | 2 +- .../adapters/get-proforma-by-id.adapter.ts | 36 +++--- .../proforma-to-list-row-patch.adapter.ts | 3 +- .../shared/entities/proforma-item.entity.ts | 12 +- .../entities/proforma-tax-summary.entity.ts | 4 +- .../shared/entities/proforma.entity.ts | 13 +-- ...s-to-proforma-items-update-form.adapter.ts | 1 + .../use-update-proforma-controller.ts | 2 + .../update/ui/blocks/line-editor.tsx | 2 +- .../build-proforma-item-update-default.ts | 2 +- .../application/di/factuges-use-cases.di.ts | 9 +- .../factuges/src/api/application/di/index.ts | 2 +- modules/factuges/src/api/application/index.ts | 1 - ...ate-proforma-from-factuges-input.mapper.ts | 22 ++-- .../create-proforma-from-factuges.use-case.ts | 106 +++++++++++------- .../api/application/use-cases/payments.json | 23 ---- modules/factuges/src/api/index.ts | 4 +- .../src/api/infraestructure/di/factuges.di.ts | 5 +- ...reate-proforma-from-factuges.controller.ts | 5 + .../infraestructure/express/mappers/index.ts | 1 + .../src/helpers/extract-or-push-error.ts | 2 +- packages/rdx-utils/src/helpers/collection.ts | 2 +- 26 files changed, 171 insertions(+), 119 deletions(-) delete mode 100644 modules/factuges/src/api/application/use-cases/payments.json create mode 100644 modules/factuges/src/api/infraestructure/express/mappers/index.ts diff --git a/modules/core/src/common/catalogs/payments/factuges-payment-catalog.json b/modules/core/src/common/catalogs/payments/factuges-payment-catalog.json index 896dc5f7..23bc0c43 100644 --- a/modules/core/src/common/catalogs/payments/factuges-payment-catalog.json +++ b/modules/core/src/common/catalogs/payments/factuges-payment-catalog.json @@ -19,5 +19,12 @@ "factuges_id": "15", "description": "TRANSFERENCIA BANCARIA", "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" } ] \ No newline at end of file diff --git a/modules/core/src/common/helpers/money-dto-helper.ts b/modules/core/src/common/helpers/money-dto-helper.ts index 040c03bb..72ebf1da 100644 --- a/modules/core/src/common/helpers/money-dto-helper.ts +++ b/modules/core/src/common/helpers/money-dto-helper.ts @@ -29,6 +29,13 @@ const toNumericString = (dto?: MoneyDTO | null, fallbackScale = 2): string => { 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. * @@ -117,6 +124,7 @@ export const MoneyDTOHelper = { isEmpty: isEmptyMoneyDTO, toNumber, toNumericString, + toNumericNulleable, fromNumber, fromNumericString, format, diff --git a/modules/core/src/common/helpers/percentage-dto-helper.ts b/modules/core/src/common/helpers/percentage-dto-helper.ts index 2df94612..3f0fe8de 100644 --- a/modules/core/src/common/helpers/percentage-dto-helper.ts +++ b/modules/core/src/common/helpers/percentage-dto-helper.ts @@ -25,6 +25,13 @@ const toNumericString = (dto?: PercentageDTO | null, fallbackScale = 2): string 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. * @@ -97,6 +104,7 @@ export const PercentageDTOHelper = { isEmpty: isEmptyPercentageDTO, toNumber, toNumericString, + toNumericNulleable, fromNumber, fromNumericString, format, diff --git a/modules/core/src/common/helpers/quantity-dto-helper.ts b/modules/core/src/common/helpers/quantity-dto-helper.ts index c82aaa5e..d6dcb378 100644 --- a/modules/core/src/common/helpers/quantity-dto-helper.ts +++ b/modules/core/src/common/helpers/quantity-dto-helper.ts @@ -25,6 +25,13 @@ const toNumericString = (dto?: QuantityDTO | null, fallbackScale = 2): string => 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. * @@ -91,6 +98,7 @@ export const QuantityDTOHelper = { isEmpty: isEmptyQuantityDTO, toNumber, toNumericString, + toNumericNulleable, fromNumber, fromNumericString, format, diff --git a/modules/customer-invoices/src/web/issued-invoices/list/controllers/use-issued-invoice-list.controller.ts b/modules/customer-invoices/src/web/issued-invoices/list/controllers/use-issued-invoice-list.controller.ts index e864f6f9..17321055 100644 --- a/modules/customer-invoices/src/web/issued-invoices/list/controllers/use-issued-invoice-list.controller.ts +++ b/modules/customer-invoices/src/web/issued-invoices/list/controllers/use-issued-invoice-list.controller.ts @@ -1,4 +1,4 @@ -import { useDebounce } from "@repo/rdx-ui/components"; +import { useDebounce } from "@erp/core/hooks"; import { useMemo, useState } from "react"; import type { diff --git a/modules/customer-invoices/src/web/proformas/shared/adapters/get-proforma-by-id.adapter.ts b/modules/customer-invoices/src/web/proformas/shared/adapters/get-proforma-by-id.adapter.ts index ea241916..10fbbe18 100644 --- a/modules/customer-invoices/src/web/proformas/shared/adapters/get-proforma-by-id.adapter.ts +++ b/modules/customer-invoices/src/web/proformas/shared/adapters/get-proforma-by-id.adapter.ts @@ -40,7 +40,7 @@ export const GetProformaByIdAdapter = { currencyCode: dto.currency_code, customerId: dto.customer_id, - recipient: mapRecipient(dto.recipient), + recipient: mapRecipient(dto), taxes: dto.taxes.map(mapTaxSummary), paymentMethod: dto.payment_method?.id, @@ -48,8 +48,8 @@ export const GetProformaByIdAdapter = { subtotalAmount: MoneyDTOHelper.toNumber(dto.subtotal_amount), itemsDiscountAmount: MoneyDTOHelper.toNumber(dto.items_discount_amount), - globalDiscountPercentage: PercentageDTOHelper.toNumber(dto.discount_percentage), - discountAmount: MoneyDTOHelper.toNumber(dto.discount_amount), + globalDiscountPercentage: PercentageDTOHelper.toNumber(dto.global_discount_percentage), + totalDiscountAmount: MoneyDTOHelper.toNumber(dto.total_discount_amount), taxableAmount: MoneyDTOHelper.toNumber(dto.taxable_amount), ivaAmount: MoneyDTOHelper.toNumber(dto.iva_amount), @@ -65,19 +65,19 @@ export const GetProformaByIdAdapter = { }; const mapItem = (dto: GetProformaByIdResponseDTO["items"][number]): ProformaItem => { - return { + const item: ProformaItem = { id: dto.id, position: Number(dto.position), isValued: dto.is_valued, description: dto.description, - quantity: QuantityDTOHelper.toNumber(dto.quantity), - unitAmount: MoneyDTOHelper.toNumber(dto.unit_amount), + quantity: QuantityDTOHelper.toNumericNulleable(dto.quantity), + unitAmount: MoneyDTOHelper.toNumericNulleable(dto.unit_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), 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. taxes: "", }; + + return item; }; -const mapRecipient = (dto: GetProformaByIdResponseDTO["recipient"]): ProformaRecipient => { +const mapRecipient = (dto: GetProformaByIdResponseDTO): ProformaRecipient => { return { - id: dto.id, - name: dto.name, - tin: dto.tin, - street: dto.street, - street2: dto.street2, - city: dto.city, - province: dto.province, - postalCode: dto.postal_code, - country: dto.country, + id: dto.customer_id, + name: dto.recipient.name, + tin: dto.recipient.tin, + street: dto.recipient.street, + street2: dto.recipient.street2, + city: dto.recipient.city, + province: dto.recipient.province, + postalCode: dto.recipient.postal_code, + country: dto.recipient.country, }; }; diff --git a/modules/customer-invoices/src/web/proformas/shared/adapters/proforma-to-list-row-patch.adapter.ts b/modules/customer-invoices/src/web/proformas/shared/adapters/proforma-to-list-row-patch.adapter.ts index 217b25a0..3e97d3c1 100644 --- a/modules/customer-invoices/src/web/proformas/shared/adapters/proforma-to-list-row-patch.adapter.ts +++ b/modules/customer-invoices/src/web/proformas/shared/adapters/proforma-to-list-row-patch.adapter.ts @@ -40,8 +40,7 @@ export const ProformaToListRowPatchAdapter = { country: proforma.recipient.country, }, subtotalAmount: proforma.subtotalAmount, - discountPercentage: proforma.globalDiscountPercentage, - discountAmount: proforma.discountAmount, + totalDiscountAmount: proforma.totalDiscountAmount, taxableAmount: proforma.taxableAmount, taxesAmount: proforma.taxesAmount, totalAmount: proforma.totalAmount, diff --git a/modules/customer-invoices/src/web/proformas/shared/entities/proforma-item.entity.ts b/modules/customer-invoices/src/web/proformas/shared/entities/proforma-item.entity.ts index c155f927..d4b00d1a 100644 --- a/modules/customer-invoices/src/web/proformas/shared/entities/proforma-item.entity.ts +++ b/modules/customer-invoices/src/web/proformas/shared/entities/proforma-item.entity.ts @@ -9,14 +9,14 @@ export interface ProformaItem { position: number; isValued: boolean; - description: string; + description: string | null; - quantity: number; - unitAmount: number; + quantity: number | null; + unitAmount: number | null; subtotalAmount: number; - itemDiscountPercentage: number; + itemDiscountPercentage: number | null; itemDiscountAmount: number; globalDiscountPercentage: number; @@ -28,11 +28,11 @@ export interface ProformaItem { ivaPercentage: number; ivaAmount: number; - recCode: string; + recCode: string | null; recPercentage: number; recAmount: number; - retentionCode: string; + retentionCode: string | null; retentionPercentage: number; retentionAmount: number; diff --git a/modules/customer-invoices/src/web/proformas/shared/entities/proforma-tax-summary.entity.ts b/modules/customer-invoices/src/web/proformas/shared/entities/proforma-tax-summary.entity.ts index 9803974f..4a976fde 100644 --- a/modules/customer-invoices/src/web/proformas/shared/entities/proforma-tax-summary.entity.ts +++ b/modules/customer-invoices/src/web/proformas/shared/entities/proforma-tax-summary.entity.ts @@ -11,11 +11,11 @@ export interface ProformaTaxSummary { ivaPercentage: number; ivaAmount: number; - recCode: string; + recCode: string | null; recPercentage: number; recAmount: number; - retentionCode: string; + retentionCode: string | null; retentionPercentage: number; retentionAmount: number; diff --git a/modules/customer-invoices/src/web/proformas/shared/entities/proforma.entity.ts b/modules/customer-invoices/src/web/proformas/shared/entities/proforma.entity.ts index 679258bd..a87b6314 100644 --- a/modules/customer-invoices/src/web/proformas/shared/entities/proforma.entity.ts +++ b/modules/customer-invoices/src/web/proformas/shared/entities/proforma.entity.ts @@ -13,18 +13,17 @@ import type { ProformaTaxSummary } from "./proforma-tax-summary.entity"; export interface Proforma { id: string; companyId: string; - isProforma: boolean; invoiceNumber: string; status: ProformaStatus; - series: string; + series: string | null; invoiceDate: string; - operationDate: string; + operationDate: string | null; - reference: string; - description: string; - notes: string; + reference: string | null; + description: string | null; + notes: string | null; languageCode: string; currencyCode: string; @@ -40,7 +39,7 @@ export interface Proforma { itemsDiscountAmount: number; globalDiscountPercentage: number; - discountAmount: number; + totalDiscountAmount: number; taxableAmount: number; ivaAmount: number; diff --git a/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-items-to-proforma-items-update-form.adapter.ts b/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-items-to-proforma-items-update-form.adapter.ts index e5aa0317..8f2bb6ef 100644 --- a/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-items-to-proforma-items-update-form.adapter.ts +++ b/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-items-to-proforma-items-update-form.adapter.ts @@ -11,6 +11,7 @@ import type { ProformaItemUpdateForm } from "../entities"; export const mapProformaItemsToProformaItemsUpdateForm = ( item: ProformaItem ): ProformaItemUpdateForm => { + console.log(item); return { id: item.id, position: item.position, diff --git a/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-controller.ts b/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-controller.ts index 3eee858c..c283bf8b 100644 --- a/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-controller.ts +++ b/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-controller.ts @@ -74,6 +74,8 @@ export const useUpdateProformaController = ( const initialValues = useMemo(() => { if (!proformaData) return buildProformaUpdateDefault(); + console.log("initialValues", proformaData); + return mapProformaToProformaUpdateForm(proformaData); }, [proformaData]); diff --git a/modules/customer-invoices/src/web/proformas/update/ui/blocks/line-editor.tsx b/modules/customer-invoices/src/web/proformas/update/ui/blocks/line-editor.tsx index 524fd92f..b52ca175 100644 --- a/modules/customer-invoices/src/web/proformas/update/ui/blocks/line-editor.tsx +++ b/modules/customer-invoices/src/web/proformas/update/ui/blocks/line-editor.tsx @@ -178,7 +178,7 @@ export const LineEditor = ({ } /> - + onAddBefore(index)}> {insertBeforeLabel} diff --git a/modules/customer-invoices/src/web/proformas/update/utils/build-proforma-item-update-default.ts b/modules/customer-invoices/src/web/proformas/update/utils/build-proforma-item-update-default.ts index d96d6cef..a5a24286 100644 --- a/modules/customer-invoices/src/web/proformas/update/utils/build-proforma-item-update-default.ts +++ b/modules/customer-invoices/src/web/proformas/update/utils/build-proforma-item-update-default.ts @@ -8,7 +8,7 @@ export const buildProformaItemUpdateDefault = (position: number): ProformaItemUp position, isValued: false, - description: "", + description: null, quantity: null, unitAmount: null, diff --git a/modules/factuges/src/api/application/di/factuges-use-cases.di.ts b/modules/factuges/src/api/application/di/factuges-use-cases.di.ts index b308c82c..d5b3fea1 100644 --- a/modules/factuges/src/api/application/di/factuges-use-cases.di.ts +++ b/modules/factuges/src/api/application/di/factuges-use-cases.di.ts @@ -1,4 +1,5 @@ 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 { ICreateProformaFromFactugesInputMapper } from "../mappers"; @@ -10,6 +11,7 @@ export function buildCreateProformaFromFactugesUseCase(deps: { finder: IFactuGESProformaFinder; publicServices: { customerServices: ICustomerPublicServices; + proformaServices: IProformaPublicServices; }; dtoMapper: ICreateProformaFromFactugesInputMapper; catalogs: ICatalogs; @@ -17,18 +19,21 @@ export function buildCreateProformaFromFactugesUseCase(deps: { }) { const { linker, + finder, dtoMapper, transactionManager, - publicServices: { customerServices }, + publicServices: { customerServices, proformaServices }, } = deps; - const { taxCatalog } = deps.catalogs; + const { taxCatalog, paymentCatalog } = deps.catalogs; return new CreateProformaFromFactugesUseCase({ linker, finder, customerServices, + proformaServices, dtoMapper, taxCatalog, + paymentCatalog, transactionManager, }); } diff --git a/modules/factuges/src/api/application/di/index.ts b/modules/factuges/src/api/application/di/index.ts index b20e0e8d..f6e16200 100644 --- a/modules/factuges/src/api/application/di/index.ts +++ b/modules/factuges/src/api/application/di/index.ts @@ -1,2 +1,2 @@ +export * from "./factuges-input-mappers.di"; export * from "./factuges-use-cases.di"; -export * from "./factuges-input-mappers.di" \ No newline at end of file diff --git a/modules/factuges/src/api/application/index.ts b/modules/factuges/src/api/application/index.ts index 9c08d30c..0ee361e3 100644 --- a/modules/factuges/src/api/application/index.ts +++ b/modules/factuges/src/api/application/index.ts @@ -1,3 +1,2 @@ -export * from "./mappers"; export * from "./repositories"; export * from "./use-cases"; diff --git a/modules/factuges/src/api/application/mappers/create-proforma-from-factuges-input.mapper.ts b/modules/factuges/src/api/application/mappers/create-proforma-from-factuges-input.mapper.ts index 088627cd..6ecc57ad 100644 --- a/modules/factuges/src/api/application/mappers/create-proforma-from-factuges-input.mapper.ts +++ b/modules/factuges/src/api/application/mappers/create-proforma-from-factuges-input.mapper.ts @@ -164,8 +164,6 @@ export class CreateProformaFromFactugesInputMapper errors, }); - console.log(paymentProps); - this.throwIfValidationErrors(errors); return Result.ok({ @@ -173,7 +171,7 @@ export class CreateProformaFromFactugesInputMapper tin: customerProps.tin, }, paymentLookup: { - factuges_id: paymentProps.factuges_id, + factuges_id: paymentProps?.factuges_id, }, customerDraft: customerProps, proformaDraft: proformaProps, @@ -195,25 +193,25 @@ export class CreateProformaFromFactugesInputMapper currencyCode: CurrencyCode; errors: ValidationErrorDetail[]; } - ): ProformaPaymentDraft { + ): ProformaPaymentDraft | undefined { const errors: ValidationErrorDetail[] = []; const { companyId } = params; - const factuges_id = String(dto.payment_method_id); - const paymentOrNot = this.paymentCatalog.findByFactuGESId(factuges_id); + const payment_method_id = String(dto.payment_method_id); + const paymentOrNot = this.paymentCatalog.findByFactuGESId(payment_method_id); if (paymentOrNot.isNone()) { errors.push({ path: "payment_method_id", 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( diff --git a/modules/factuges/src/api/application/use-cases/create-proforma-from-factuges.use-case.ts b/modules/factuges/src/api/application/use-cases/create-proforma-from-factuges.use-case.ts index cd6f68d7..b778cbc2 100644 --- a/modules/factuges/src/api/application/use-cases/create-proforma-from-factuges.use-case.ts +++ b/modules/factuges/src/api/application/use-cases/create-proforma-from-factuges.use-case.ts @@ -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 { IProformaPublicServices } from "@erp/customer-invoices/api"; import { @@ -30,19 +30,31 @@ import type { CreateProformaFromFactugesRequestDTO } from "../../../common"; import type { FactugesProformaPayload, ICreateProformaFromFactugesInputMapper } from "../mappers"; import type { IFactuGESProformaFinder, IFactuGESProformaLinker } from "../services"; -import paymentsCatalog from "./payments.json"; - -type FakePaymentMethod = { - id: UniqueID; - description: string; - factuges_id: string; -}; - type CreateProformaFromFactugesUseCaseInput = { companyId: UniqueID; 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>; +} + type CreateProformaFromFactugesUseCaseDeps = { linker: IFactuGESProformaLinker; finder: IFactuGESProformaFinder; @@ -50,17 +62,19 @@ type CreateProformaFromFactugesUseCaseDeps = { proformaServices: IProformaPublicServices; dtoMapper: ICreateProformaFromFactugesInputMapper; taxCatalog: JsonTaxCatalogProvider; + paymentCatalog: JsonPaymentCatalogProvider; transactionManager: ITransactionManager; }; type CreateProformaProps = Parameters["1"]; export class CreateProformaFromFactugesUseCase { - private readonly dtoMapper: ICreateProformaFromFactugesInputMapper; private readonly linker: IFactuGESProformaLinker; private readonly finder: IFactuGESProformaFinder; + private readonly dtoMapper: ICreateProformaFromFactugesInputMapper; private readonly customerServices: ICustomerPublicServices; private readonly proformaServices: IProformaPublicServices; + private readonly paymentCatalog: JsonPaymentCatalogProvider; private readonly taxCatalog: JsonTaxCatalogProvider; private readonly transactionManager: ITransactionManager; @@ -70,11 +84,14 @@ export class CreateProformaFromFactugesUseCase { this.customerServices = deps.customerServices; this.proformaServices = deps.proformaServices; this.dtoMapper = deps.dtoMapper; + this.paymentCatalog = deps.paymentCatalog; this.taxCatalog = deps.taxCatalog; this.transactionManager = deps.transactionManager; } - public async execute(params: CreateProformaFromFactugesUseCaseInput) { + public async execute( + params: CreateProformaFromFactugesUseCaseInput + ): Promise> { const { dto, companyId } = params; // 1) Mapear DTO → props @@ -87,16 +104,25 @@ export class CreateProformaFromFactugesUseCase { mappedPropsResult.data; // 2) Comprobar si la proforma ya existe (idempotencia) - const proformaIdResult = await this.finder.findProformaIdByFactuGESId( + const proformaExists = await this.finder.existsProformaByFactuGESId( companyId, proformaDraft.factugesID ); - if (proformaIdResult.isSuccess) { - const existingProforma = proformaIdResult.data; + if (proformaExists.isSuccess && proformaExists.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({ - proforma_id: existingProforma.toString(), + proforma_id: proformaId.toString(), }); } @@ -113,7 +139,7 @@ export class CreateProformaFromFactugesUseCase { const customer = customerResult.data; - const paymentResult = await this.resolvePayment(paymentLookup, paymentDraft, { + const paymentResult = await this.resolvePayment(paymentLookup, { companyId, transaction, }); @@ -338,7 +364,7 @@ export class CreateProformaFromFactugesUseCase { private buildProformaCreateProps(deps: { proformaDraft: FactugesProformaPayload["proformaDraft"]; customerId: UniqueID; - payment: FakePaymentMethod; + payment: ResolvedPaymentMethod; context: { companyId: UniqueID; transaction: Transaction; @@ -410,31 +436,35 @@ export class CreateProformaFromFactugesUseCase { }); } - private async resolvePayment( + private resolvePayment( paymentLookup: FactugesProformaPayload["paymentLookup"], - paymentDraft: FactugesProformaPayload["paymentDraft"], - context: { - companyId: UniqueID; - transaction: Transaction; - } - ): Promise> { - const { companyId, transaction } = context; + context: { companyId: UniqueID; transaction: Transaction } + ): Result { + const payment = this.paymentCatalog.findByFactuGESId(paymentLookup.factuges_id); - const existingPaymentResult = paymentsCatalog.find( - (payment) => - 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, - }); + if (payment.isNone()) { + return Result.fail(new Error("La forma de pago de FactuGES no existe.")); } - 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( diff --git a/modules/factuges/src/api/application/use-cases/payments.json b/modules/factuges/src/api/application/use-cases/payments.json deleted file mode 100644 index 95b5bc20..00000000 --- a/modules/factuges/src/api/application/use-cases/payments.json +++ /dev/null @@ -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" - } -] \ No newline at end of file diff --git a/modules/factuges/src/api/index.ts b/modules/factuges/src/api/index.ts index e76ae8b0..0a04c0a3 100644 --- a/modules/factuges/src/api/index.ts +++ b/modules/factuges/src/api/index.ts @@ -1,6 +1,6 @@ import type { IModuleServer } from "@erp/core/api"; -import { factugesRouter } from "./infraestructure"; +import { factugesRouter, models } from "./infraestructure"; import { buildFactugesDependencies } from "./infraestructure/di"; export const factugesAPIModule: IModuleServer = { @@ -28,7 +28,7 @@ export const factugesAPIModule: IModuleServer = { return { // Modelos Sequelize del módulo - models: [], + models, // Servicios expuestos a otros módulos services: {}, diff --git a/modules/factuges/src/api/infraestructure/di/factuges.di.ts b/modules/factuges/src/api/infraestructure/di/factuges.di.ts index 0fbdf708..fcb3f078 100644 --- a/modules/factuges/src/api/infraestructure/di/factuges.di.ts +++ b/modules/factuges/src/api/infraestructure/di/factuges.di.ts @@ -41,7 +41,10 @@ export function buildFactugesDependencies(params: SetupParams): FactugesInternal // Internal use cases (factories) return { useCases: { - createProforma: (publicServices: { customerServices: ICustomerPublicServices }) => + createProforma: (publicServices: { + customerServices: ICustomerPublicServices; + proformaServices: IProformaPublicServices; + }) => buildCreateProformaFromFactugesUseCase({ linker, finder, diff --git a/modules/factuges/src/api/infraestructure/express/controllers/create-proforma-from-factuges.controller.ts b/modules/factuges/src/api/infraestructure/express/controllers/create-proforma-from-factuges.controller.ts index a1782108..0bb7810d 100644 --- a/modules/factuges/src/api/infraestructure/express/controllers/create-proforma-from-factuges.controller.ts +++ b/modules/factuges/src/api/infraestructure/express/controllers/create-proforma-from-factuges.controller.ts @@ -29,6 +29,11 @@ export class CreateProformaFromFactugesController extends ExpressController { } const dto = this.req.body as CreateProformaFromFactugesRequestDTO; + // Request mapper + + // Command for use case + + // Execute use case const result = await this.useCase.execute({ dto, companyId }); return result.match( diff --git a/modules/factuges/src/api/infraestructure/express/mappers/index.ts b/modules/factuges/src/api/infraestructure/express/mappers/index.ts new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/modules/factuges/src/api/infraestructure/express/mappers/index.ts @@ -0,0 +1 @@ + diff --git a/packages/rdx-ddd/src/helpers/extract-or-push-error.ts b/packages/rdx-ddd/src/helpers/extract-or-push-error.ts index b9902d91..807e6402 100644 --- a/packages/rdx-ddd/src/helpers/extract-or-push-error.ts +++ b/packages/rdx-ddd/src/helpers/extract-or-push-error.ts @@ -40,7 +40,7 @@ export function extractOrPushError( if (isValidationErrorCollection(error)) { // Copiar todos los detalles, rellenando path si falta - console.log(error); + error.details?.forEach((detail) => { errors.push({ ...detail, diff --git a/packages/rdx-utils/src/helpers/collection.ts b/packages/rdx-utils/src/helpers/collection.ts index e6ee80eb..00ce3d80 100644 --- a/packages/rdx-utils/src/helpers/collection.ts +++ b/packages/rdx-utils/src/helpers/collection.ts @@ -99,7 +99,7 @@ export class Collection { * @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. */ - forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void { + forEach(callbackfn: (value: T, index: number, array: T[]) => void, _thisArg?: unknown): void { this.items.forEach(callbackfn); }