From 8a0e776ce37645a31cdbe80f16daba5a2650586f Mon Sep 17 00:00:00 2001 From: david Date: Mon, 23 Mar 2026 18:51:49 +0100 Subject: [PATCH] . --- .../sequelize/sequelize-error-translator.ts | 2 - .../proformas/di/proforma-creator.di.ts | 3 - .../application/proformas/factories/index.ts | 2 - .../factories/proforma-factory.interface.ts | 17 ----- .../proformas/factories/proforma-factory.ts | 16 ---- .../mappers/create-proforma-input.mapper.ts | 6 +- .../proformas/services/proforma-creator.ts | 21 ++---- .../full/proforma-full-snapshot-builder.ts | 40 +++++----- .../aggregates/proforma.aggregate.ts | 75 ++++++++++--------- .../proforma-items/proforma-item.entity.ts | 19 +++-- .../proforma-items.collection.ts | 51 ++++++++----- .../mappers/create-proforma-request-mapper.ts | 6 +- .../sequelize-proforma-domain.mapper.ts | 53 ++++++------- .../sequelize-proforma-item-domain.mapper.ts | 15 ++-- .../repositories/proforma.repository.ts | 2 - ...ate-proforma-from-factuges-input.mapper.ts | 47 ++++-------- 16 files changed, 161 insertions(+), 214 deletions(-) delete mode 100644 modules/customer-invoices/src/api/application/proformas/factories/index.ts delete mode 100644 modules/customer-invoices/src/api/application/proformas/factories/proforma-factory.interface.ts delete mode 100644 modules/customer-invoices/src/api/application/proformas/factories/proforma-factory.ts diff --git a/modules/core/src/api/infrastructure/persistence/sequelize/sequelize-error-translator.ts b/modules/core/src/api/infrastructure/persistence/sequelize/sequelize-error-translator.ts index 333cffcc..f13649aa 100644 --- a/modules/core/src/api/infrastructure/persistence/sequelize/sequelize-error-translator.ts +++ b/modules/core/src/api/infrastructure/persistence/sequelize/sequelize-error-translator.ts @@ -18,8 +18,6 @@ import { InfrastructureUnavailableError } from "../../errors/infrastructure-unav * 馃憠 Este traductor pertenece a la infraestructura (persistencia) */ export function translateSequelizeError(err: unknown): Error { - console.error(err); - // 1) Duplicados (铆ndices 煤nicos) if (err instanceof UniqueConstraintError) { // Tomamos el primer detalle (puede haber varios) diff --git a/modules/customer-invoices/src/api/application/proformas/di/proforma-creator.di.ts b/modules/customer-invoices/src/api/application/proformas/di/proforma-creator.di.ts index dee9f3e2..c20d2565 100644 --- a/modules/customer-invoices/src/api/application/proformas/di/proforma-creator.di.ts +++ b/modules/customer-invoices/src/api/application/proformas/di/proforma-creator.di.ts @@ -1,4 +1,3 @@ -import { ProformaFactory } from "../factories"; import type { IProformaRepository } from "../repositories"; import { type IProformaCreator, type IProformaNumberGenerator, ProformaCreator } from "../services"; @@ -7,11 +6,9 @@ export const buildProformaCreator = (params: { repository: IProformaRepository; }): IProformaCreator => { const { numberService, repository } = params; - const factory = new ProformaFactory(); return new ProformaCreator({ numberService, - factory, repository, }); }; diff --git a/modules/customer-invoices/src/api/application/proformas/factories/index.ts b/modules/customer-invoices/src/api/application/proformas/factories/index.ts deleted file mode 100644 index 3ec988be..00000000 --- a/modules/customer-invoices/src/api/application/proformas/factories/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./proforma-factory"; -export * from "./proforma-factory.interface"; diff --git a/modules/customer-invoices/src/api/application/proformas/factories/proforma-factory.interface.ts b/modules/customer-invoices/src/api/application/proformas/factories/proforma-factory.interface.ts deleted file mode 100644 index 1eae2c5f..00000000 --- a/modules/customer-invoices/src/api/application/proformas/factories/proforma-factory.interface.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { UniqueID } from "@repo/rdx-ddd"; -import type { Result } from "@repo/rdx-utils"; - -import type { IProformaCreateProps, Proforma } from "../../../domain"; - -export interface IProformaFactory { - /** - * Crea una proforma v谩lida para una empresa a partir de props ya validadas. - * - * No persiste el agregado. - */ - createProforma( - companyId: UniqueID, - props: Omit, - proformaId?: UniqueID - ): Result; -} diff --git a/modules/customer-invoices/src/api/application/proformas/factories/proforma-factory.ts b/modules/customer-invoices/src/api/application/proformas/factories/proforma-factory.ts deleted file mode 100644 index 93f57405..00000000 --- a/modules/customer-invoices/src/api/application/proformas/factories/proforma-factory.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { UniqueID } from "@repo/rdx-ddd"; -import type { Result } from "@repo/rdx-utils"; - -import { type IProformaCreateProps, Proforma } from "../../../domain"; - -import type { IProformaFactory } from "./proforma-factory.interface"; - -export class ProformaFactory implements IProformaFactory { - createProforma( - companyId: UniqueID, - props: Omit, - proformaId?: UniqueID - ): Result { - return Proforma.create({ ...props, companyId }, proformaId); - } -} diff --git a/modules/customer-invoices/src/api/application/proformas/mappers/create-proforma-input.mapper.ts b/modules/customer-invoices/src/api/application/proformas/mappers/create-proforma-input.mapper.ts index 4d95eafe..d6d1cf22 100644 --- a/modules/customer-invoices/src/api/application/proformas/mappers/create-proforma-input.mapper.ts +++ b/modules/customer-invoices/src/api/application/proformas/mappers/create-proforma-input.mapper.ts @@ -18,7 +18,7 @@ import { Maybe, Result } from "@repo/rdx-utils"; import type { CreateProformaItemRequestDTO, CreateProformaRequestDTO } from "../../../../common"; import { type IProformaCreateProps, - type IProformaItemProps, + type IProformaItemCreateProps, InvoiceNumber, InvoicePaymentMethod, type InvoiceRecipient, @@ -210,8 +210,8 @@ export class CreateProformaInputMapper /*implements ICreateProformaInputMapper*/ globalDiscountPercentage: DiscountPercentage; errors: ValidationErrorDetail[]; } - ): IProformaItemProps[] { - const itemsProps: IProformaItemProps[] = []; + ): IProformaItemCreateProps[] { + const itemsProps: IProformaItemCreateProps[] = []; dto.items.forEach((item, index) => { const description = extractOrPushError( diff --git a/modules/customer-invoices/src/api/application/proformas/services/proforma-creator.ts b/modules/customer-invoices/src/api/application/proformas/services/proforma-creator.ts index a7f1a86b..d73bdbe4 100644 --- a/modules/customer-invoices/src/api/application/proformas/services/proforma-creator.ts +++ b/modules/customer-invoices/src/api/application/proformas/services/proforma-creator.ts @@ -2,8 +2,7 @@ import type { UniqueID } from "@repo/rdx-ddd"; import { Result } from "@repo/rdx-utils"; import type { Transaction } from "sequelize"; -import type { IProformaCreateProps, Proforma } from "../../../domain"; -import type { IProformaFactory } from "../factories"; +import { type IProformaCreateProps, Proforma } from "../../../domain"; import type { IProformaRepository } from "../repositories"; import type { IProformaNumberGenerator } from "./proforma-number-generator.interface"; @@ -21,18 +20,15 @@ export interface IProformaCreator { type ProformaCreatorDeps = { numberService: IProformaNumberGenerator; - factory: IProformaFactory; repository: IProformaRepository; }; export class ProformaCreator implements IProformaCreator { private readonly numberService: IProformaNumberGenerator; - private readonly factory: IProformaFactory; private readonly repository: IProformaRepository; constructor(deps: ProformaCreatorDeps) { this.numberService = deps.numberService; - this.factory = deps.factory; this.repository = deps.repository; } @@ -55,20 +51,13 @@ export class ProformaCreator implements IProformaCreator { const invoiceNumber = numberResult.data; // 2. Crear agregado - const buildResult = this.factory.createProforma( - companyId, - { - ...props, - invoiceNumber, - }, - id - ); + const proformaResult = Proforma.create({ ...props, invoiceNumber, companyId }, id); - if (buildResult.isFailure) { - return Result.fail(buildResult.error); + if (proformaResult.isFailure) { + return Result.fail(proformaResult.error); } - const proforma = buildResult.data; + const proforma = proformaResult.data; // 3. Persistir const saveResult = await this.repository.create(proforma, transaction); diff --git a/modules/customer-invoices/src/api/application/proformas/snapshot-builders/full/proforma-full-snapshot-builder.ts b/modules/customer-invoices/src/api/application/proformas/snapshot-builders/full/proforma-full-snapshot-builder.ts index b0685846..d8cdfd40 100644 --- a/modules/customer-invoices/src/api/application/proformas/snapshot-builders/full/proforma-full-snapshot-builder.ts +++ b/modules/customer-invoices/src/api/application/proformas/snapshot-builders/full/proforma-full-snapshot-builder.ts @@ -18,12 +18,12 @@ export class ProformaFullSnapshotBuilder implements IProformaFullSnapshotBuilder private readonly taxesBuilder: IProformaTaxesFullSnapshotBuilder ) {} - toOutput(invoice: Proforma): IProformaFullSnapshot { - const items = this.itemsBuilder.toOutput(invoice.items); - const recipient = this.recipientBuilder.toOutput(invoice); - const taxes = this.taxesBuilder.toOutput(invoice.taxes()); + toOutput(proforma: Proforma): IProformaFullSnapshot { + const items = this.itemsBuilder.toOutput(proforma.items); + const recipient = this.recipientBuilder.toOutput(proforma); + const taxes = this.taxesBuilder.toOutput(proforma.taxes()); - const payment = invoice.paymentMethod.match( + const payment = proforma.paymentMethod.match( (payment) => { const { id, payment_description } = payment.toObjectString(); return { @@ -34,27 +34,27 @@ export class ProformaFullSnapshotBuilder implements IProformaFullSnapshotBuilder () => undefined ); - const allTotals = invoice.totals(); + const allTotals = proforma.totals(); return { - id: invoice.id.toString(), - company_id: invoice.companyId.toString(), + id: proforma.id.toString(), + company_id: proforma.companyId.toString(), - invoice_number: invoice.invoiceNumber.toString(), - status: invoice.status.toPrimitive(), - series: maybeToEmptyString(invoice.series, (value) => value.toString()), + invoice_number: proforma.invoiceNumber.toString(), + status: proforma.status.toPrimitive(), + series: maybeToEmptyString(proforma.series, (value) => value.toString()), - invoice_date: invoice.invoiceDate.toDateString(), - operation_date: maybeToEmptyString(invoice.operationDate, (value) => value.toDateString()), + invoice_date: proforma.invoiceDate.toDateString(), + operation_date: maybeToEmptyString(proforma.operationDate, (value) => value.toDateString()), - reference: maybeToEmptyString(invoice.reference, (value) => value.toString()), - description: maybeToEmptyString(invoice.description, (value) => value.toString()), - notes: maybeToEmptyString(invoice.notes, (value) => value.toString()), + reference: maybeToEmptyString(proforma.reference, (value) => value.toString()), + description: maybeToEmptyString(proforma.description, (value) => value.toString()), + notes: maybeToEmptyString(proforma.notes, (value) => value.toString()), - language_code: invoice.languageCode.toString(), - currency_code: invoice.currencyCode.toString(), + language_code: proforma.languageCode.toString(), + currency_code: proforma.currencyCode.toString(), - customer_id: invoice.customerId.toString(), + customer_id: proforma.customerId.toString(), recipient, payment_method: payment, @@ -62,7 +62,7 @@ export class ProformaFullSnapshotBuilder implements IProformaFullSnapshotBuilder subtotal_amount: allTotals.subtotalAmount.toObjectString(), items_discount_amount: allTotals.itemDiscountAmount.toObjectString(), - global_discount_percentage: invoice.globalDiscountPercentage.toObjectString(), + global_discount_percentage: proforma.globalDiscountPercentage.toObjectString(), global_discount_amount: allTotals.globalDiscountAmount.toObjectString(), total_discount_amount: allTotals.totalDiscountAmount.toObjectString(), diff --git a/modules/customer-invoices/src/api/domain/proformas/aggregates/proforma.aggregate.ts b/modules/customer-invoices/src/api/domain/proformas/aggregates/proforma.aggregate.ts index dc4c8817..0eb47202 100644 --- a/modules/customer-invoices/src/api/domain/proformas/aggregates/proforma.aggregate.ts +++ b/modules/customer-invoices/src/api/domain/proformas/aggregates/proforma.aggregate.ts @@ -21,7 +21,7 @@ import { type ItemAmount, } from "../../common/value-objects"; import { - type IProformaItemProps, + type IProformaItemCreateProps, type IProformaItems, ProformaItem, ProformaItems, @@ -52,7 +52,7 @@ export interface IProformaCreateProps { paymentMethod: Maybe; - items: IProformaItemProps[]; + items: IProformaItemCreateProps[]; globalDiscountPercentage: DiscountPercentage; } @@ -104,18 +104,32 @@ export type ProformaPatchProps = Partial; +export type InternalProformaProps = Omit; export class Proforma extends AggregateRoot implements IProforma { + private readonly _items: ProformaItems; + + protected constructor(props: InternalProformaProps, items: ProformaItems, id?: UniqueID) { + super(props, id); + this._items = items; + } + // Creaci贸n funcional static create(props: IProformaCreateProps, id?: UniqueID): Result { + const internalItems = ProformaItems.create({ + items: [], + languageCode: props.languageCode, + currencyCode: props.currencyCode, + globalDiscountPercentage: props.globalDiscountPercentage, + }); + const { items, ...internalProps } = props; - const proforma = new Proforma(internalProps, id); + const proforma = new Proforma(internalProps, internalItems, id); - const addItemsResult = proforma.initializeItems(items); + const initializeResult = proforma.initializeItems(items); - if (addItemsResult.isFailure) { - return Result.fail(addItemsResult.error); + if (initializeResult.isFailure) { + return Result.fail(initializeResult.error); } // Reglas de negocio / validaciones @@ -128,21 +142,25 @@ export class Proforma extends AggregateRoot implements IP } // Rehidrataci贸n desde persistencia - static rehydrate(props: InternalProformaProps, id: UniqueID): Proforma { - return new Proforma(props, id); + static rehydrate(props: InternalProformaProps, items: ProformaItems, id: UniqueID): Proforma { + return new Proforma(props, items, id); } - private readonly _items: ProformaItems; + private initializeItems(itemsProps: IProformaItemCreateProps[]): Result { + for (const [index, itemProps] of itemsProps.entries()) { + const itemResult = ProformaItem.create(itemProps); - protected constructor(props: InternalProformaProps, id?: UniqueID) { - super(props, id); + if (itemResult.isFailure) { + return Result.fail(itemResult.error); + } - this._items = ProformaItems.create({ - languageCode: props.languageCode, - currencyCode: props.currencyCode, - globalDiscountPercentage: props.globalDiscountPercentage, - items: [], - }); + const added = this._items.add(itemResult.data); + + if (!added) { + return Result.fail(new ProformaItemMismatch(index)); + } + } + return Result.ok(); } // Getters @@ -206,7 +224,7 @@ export class Proforma extends AggregateRoot implements IP return this.props.globalDiscountPercentage; } - public get items(): IProformaItems { + public get items(): ProformaItems { return this._items; } @@ -277,7 +295,7 @@ export class Proforma extends AggregateRoot implements IP return new ProformaTaxesCalculator(this.items).calculate(); } - public addItem(props: IProformaItemProps): Result { + public addItem(props: IProformaItemCreateProps): Result { const taxesResult = ProformaItemTaxes.create(props.taxes); if (taxesResult.isFailure) return Result.fail(taxesResult.error); @@ -318,23 +336,6 @@ export class Proforma extends AggregateRoot implements IP // Helpers - private initializeItems(itemsProps: IProformaItemProps[]): Result { - for (const [index, itemProps] of itemsProps.entries()) { - const itemResult = ProformaItem.create(itemProps); - - if (itemResult.isFailure) { - return Result.fail(itemResult.error); - } - - const added = this._items.add(itemResult.data); - - if (!added) { - return Result.fail(new ProformaItemMismatch(index)); - } - } - return Result.ok(); - } - /** * @summary Convierte un ItemAmount a InvoiceAmount (mantiene moneda y escala homog茅nea). */ diff --git a/modules/customer-invoices/src/api/domain/proformas/entities/proforma-items/proforma-item.entity.ts b/modules/customer-invoices/src/api/domain/proformas/entities/proforma-items/proforma-item.entity.ts index b90ed4db..690bb48e 100644 --- a/modules/customer-invoices/src/api/domain/proformas/entities/proforma-items/proforma-item.entity.ts +++ b/modules/customer-invoices/src/api/domain/proformas/entities/proforma-items/proforma-item.entity.ts @@ -25,7 +25,7 @@ import { * */ -export interface IProformaItemProps { +export interface IProformaItemCreateProps { description: Maybe; quantity: Maybe; // Cantidad de unidades @@ -87,22 +87,25 @@ export interface IProformaItem { isValued(): boolean; // Indica si el item tiene cantidad o precio (o ambos) para ser considerado "valorizado" } -type CreateProformaItemProps = IProformaItemProps; - -type InternalProformaItemProps = Omit & { +type InternalProformaItemProps = Omit & { taxes: ProformaItemTaxes; }; export class ProformaItem extends DomainEntity implements IProformaItem { - public static create(props: CreateProformaItemProps, id?: UniqueID): Result { - const taxesResult = ProformaItemTaxes.create(props.taxes); + public static create( + props: IProformaItemCreateProps, + id?: UniqueID + ): Result { + const { taxes, ...internalProps } = props; + + const taxesResult = ProformaItemTaxes.create(taxes); if (taxesResult.isFailure) { return Result.fail(taxesResult.error); } const item = new ProformaItem( { - ...props, + ...internalProps, taxes: taxesResult.data, }, id @@ -155,7 +158,7 @@ export class ProformaItem extends DomainEntity implem return this.props.taxes; } - getProps(): IProformaItemProps { + getProps(): IProformaItemCreateProps { return this.props; } diff --git a/modules/customer-invoices/src/api/domain/proformas/entities/proforma-items/proforma-items.collection.ts b/modules/customer-invoices/src/api/domain/proformas/entities/proforma-items/proforma-items.collection.ts index bddde6d6..f07b86ed 100644 --- a/modules/customer-invoices/src/api/domain/proformas/entities/proforma-items/proforma-items.collection.ts +++ b/modules/customer-invoices/src/api/domain/proformas/entities/proforma-items/proforma-items.collection.ts @@ -5,15 +5,10 @@ import { Collection, Result } from "@repo/rdx-utils"; import { ProformaItemMismatch } from "../../errors"; import { ProformaItemsTotalsCalculator } from "../../services/proforma-items-totals-calculator"; -import type { - IProformaItem, - IProformaItemProps, - IProformaItemTotals, - ProformaItem, -} from "./proforma-item.entity"; +import type { IProformaItem, IProformaItemTotals, ProformaItem } from "./proforma-item.entity"; export interface IProformaItemsProps { - items: IProformaItemProps[]; + items?: ProformaItem[]; // Estos campos vienen de la cabecera, // pero se necesitan para c谩lculos y representaciones de la l铆nea. @@ -22,8 +17,19 @@ export interface IProformaItemsProps { currencyCode: CurrencyCode; // Para c谩lculos y formateos de moneda } -type CreateProformaProps = IProformaItemsProps; -type InternalProformaProps = Omit; +/*type ProformaItemCreateProps = { + items: IProformaItemCreateProps[]; + + // Estos campos vienen de la cabecera, + // pero se necesitan para c谩lculos y representaciones de la l铆nea. + globalDiscountPercentage: DiscountPercentage; // % descuento de la cabecera + languageCode: LanguageCode; // Para formateos espec铆ficos de idioma + currencyCode: CurrencyCode; // Para c谩lculos y formateos de moneda +}; + +type InternalProformaProps = Omit & { + items: ProformaItem[]; +};*/ export interface IProformaItems { // OJO, no extendemos de Collection para no exponer @@ -38,21 +44,23 @@ export interface IProformaItems { } export class ProformaItems extends Collection implements IProformaItems { - static create(props: CreateProformaProps): ProformaItems { - return new ProformaItems(props); - } - public readonly languageCode!: LanguageCode; public readonly currencyCode!: CurrencyCode; public readonly globalDiscountPercentage!: DiscountPercentage; - protected constructor(props: InternalProformaProps) { - super([]); + private constructor(props: IProformaItemsProps) { + super(props.items ?? []); this.languageCode = props.languageCode; this.currencyCode = props.currencyCode; this.globalDiscountPercentage = props.globalDiscountPercentage; - this.ensureSameCurrencyAndLanguage(this.items); + if (this.items.length > 0) { + this.ensureSameContext(this.items); + } + } + + static create(props: IProformaItemsProps): ProformaItems { + return new ProformaItems(props); } public add(item: ProformaItem): boolean { @@ -105,10 +113,15 @@ export class ProformaItems extends Collection implements IProforma return new ProformaItemsTotalsCalculator(this).calculate(); } - private ensureSameCurrencyAndLanguage(items: IProformaItem[]): void { + private ensureSameContext(items: IProformaItem[]): void { for (const item of items) { - if (!item.currencyCode.equals(this.currencyCode)) { - throw new Error("[ProformaItems] All items must share the same currency."); + const same = + item.languageCode.equals(this.languageCode) && + item.currencyCode.equals(this.currencyCode) && + item.globalDiscountPercentage.equals(this.globalDiscountPercentage); + + if (!same) { + throw new Error("[ProformaItems] All items must share the same context."); } } } diff --git a/modules/customer-invoices/src/api/infrastructure/proformas/express/mappers/create-proforma-request-mapper.ts b/modules/customer-invoices/src/api/infrastructure/proformas/express/mappers/create-proforma-request-mapper.ts index 7d16b0ff..97bb7798 100644 --- a/modules/customer-invoices/src/api/infrastructure/proformas/express/mappers/create-proforma-request-mapper.ts +++ b/modules/customer-invoices/src/api/infrastructure/proformas/express/mappers/create-proforma-request-mapper.ts @@ -17,7 +17,7 @@ import { Maybe, Result } from "@repo/rdx-utils"; import type { CreateProformaItemRequestDTO, CreateProformaRequestDTO } from "../../../../../common"; import { type IProformaCreateProps, - type IProformaItemProps, + type IProformaItemCreateProps, InvoiceNumber, InvoicePaymentMethod, type InvoiceRecipient, @@ -148,7 +148,7 @@ export class CreateProformaRequestMapper { ); } - const proformaProps: Omit & { items: IProformaItemProps[] } = { + const proformaProps: Omit & { items: IProformaItemCreateProps[] } = { companyId, status: defaultStatus!, @@ -181,7 +181,7 @@ export class CreateProformaRequestMapper { } } - private mapItems(items: CreateProformaItemRequestDTO[]): IProformaItemProps[] { + private mapItems(items: CreateProformaItemRequestDTO[]): IProformaItemCreateProps[] { const proformaItems = CustomerInvoiceItems.create({ currencyCode: this.currencyCode!, languageCode: this.languageCode!, diff --git a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/domain/sequelize-proforma-domain.mapper.ts b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/domain/sequelize-proforma-domain.mapper.ts index 32f8ee03..cf6849ae 100644 --- a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/domain/sequelize-proforma-domain.mapper.ts +++ b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/domain/sequelize-proforma-domain.mapper.ts @@ -14,7 +14,7 @@ import { import { Maybe, Result, isNullishOrEmpty } from "@repo/rdx-utils"; import { - type IProformaCreateProps, + type InternalProformaProps, InvoiceNumber, InvoicePaymentMethod, InvoiceSerie, @@ -67,7 +67,7 @@ export class SequelizeProformaDomainMapper extends SequelizeDomainMapper< const status = extractOrPushError(InvoiceStatus.create(raw.status), "status", errors); const series = extractOrPushError( - maybeFromNullableResult(raw.series, (v) => InvoiceSerie.create(v)), + maybeFromNullableResult(raw.series, (value) => InvoiceSerie.create(value)), "series", errors ); @@ -86,7 +86,7 @@ export class SequelizeProformaDomainMapper extends SequelizeDomainMapper< ); const operationDate = extractOrPushError( - maybeFromNullableResult(raw.operation_date, (v) => UtcDate.createFromISO(v)), + maybeFromNullableResult(raw.operation_date, (value) => UtcDate.createFromISO(value)), "operation_date", errors ); @@ -195,11 +195,15 @@ export class SequelizeProformaDomainMapper extends SequelizeDomainMapper< }); // 3) Items (colecci贸n) - const itemsResults = this._itemsMapper.mapToDomainCollection(raw.items, raw.items.length, { - errors, - parent: attributes, - ...params, - }); + const itemCollectionResults = this._itemsMapper.mapToDomainCollection( + raw.items, + raw.items.length, + { + errors, + parent: attributes, + ...params, + } + ); // 4) Si hubo errores de mapeo, devolvemos colecci贸n de validaci贸n if (errors.length > 0) { @@ -209,15 +213,14 @@ export class SequelizeProformaDomainMapper extends SequelizeDomainMapper< } // 6) Construcci贸n del agregado (Dominio) - const items = ProformaItems.create({ languageCode: attributes.languageCode!, currencyCode: attributes.currencyCode!, globalDiscountPercentage: attributes.globalDiscountPercentage!, - items: itemsResults.data.getAll(), + items: itemCollectionResults.data.getAll(), }); - const invoiceProps: IProformaCreateProps = { + const invoiceProps: InternalProformaProps = { companyId: attributes.companyId!, status: attributes.status!, @@ -239,21 +242,12 @@ export class SequelizeProformaDomainMapper extends SequelizeDomainMapper< globalDiscountPercentage: attributes.globalDiscountPercentage!, paymentMethod: attributes.paymentMethod!, - - items, }; - const createResult = Proforma.create(invoiceProps, attributes.invoiceId); + const invoiceId = attributes.invoiceId!; + const proforma = Proforma.rehydrate(invoiceProps, items, invoiceId); - if (createResult.isFailure) { - return Result.fail( - new ValidationErrorCollection("Customer invoice entity creation failed", [ - { path: "invoice", message: createResult.error.message }, - ]) - ); - } - - return Result.ok(createResult.data); + return Result.ok(proforma); } catch (err: unknown) { return Result.fail(err as Error); } @@ -312,7 +306,7 @@ export class SequelizeProformaDomainMapper extends SequelizeDomainMapper< const allAmounts = source.totals(); // Da los totales ya calculados - const invoiceValues: Partial = { + const proformaValues: Partial = { // Identificaci贸n id: source.id.toPrimitive(), company_id: source.companyId.toPrimitive(), @@ -360,6 +354,15 @@ export class SequelizeProformaDomainMapper extends SequelizeDomainMapper< taxable_amount_value: allAmounts.taxableAmount.value, taxable_amount_scale: allAmounts.taxableAmount.scale, + iva_amount_value: allAmounts.ivaAmount.value, + iva_amount_scale: allAmounts.ivaAmount.scale, + + rec_amount_value: allAmounts.recAmount.value, + rec_amount_scale: allAmounts.recAmount.scale, + + retention_amount_value: allAmounts.retentionAmount.value, + retention_amount_scale: allAmounts.retentionAmount.scale, + taxes_amount_value: allAmounts.taxesAmount.value, taxes_amount_scale: allAmounts.taxesAmount.scale, @@ -374,7 +377,7 @@ export class SequelizeProformaDomainMapper extends SequelizeDomainMapper< }; return Result.ok( - invoiceValues as CustomerInvoiceCreationAttributes + proformaValues as CustomerInvoiceCreationAttributes ); } } diff --git a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/domain/sequelize-proforma-item-domain.mapper.ts b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/domain/sequelize-proforma-item-domain.mapper.ts index df5c8989..59d5b33b 100644 --- a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/domain/sequelize-proforma-item-domain.mapper.ts +++ b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/domain/sequelize-proforma-item-domain.mapper.ts @@ -17,7 +17,7 @@ import { Result } from "@repo/rdx-utils"; import { type IProformaCreateProps, - type IProformaItemProps, + type IProformaItemCreateProps, ItemAmount, ItemDescription, ItemQuantity, @@ -54,7 +54,7 @@ export class SequelizeProformaItemDomainMapper extends SequelizeDomainMapper< private mapAttributesToDomain( raw: CustomerInvoiceItemModel, params?: MapperParamsType - ): Partial & { itemId?: UniqueID } { + ): Partial & { itemId?: UniqueID } { const { errors, index, parent } = params as { index: number; errors: ValidationErrorDetail[]; @@ -160,7 +160,8 @@ export class SequelizeProformaItemDomainMapper extends SequelizeDomainMapper< }); // 2) Construcci贸n del elemento de dominio - const createResult = ProformaItem.create( + const itemId = attributes.itemId!; + const newItem = ProformaItem.rehydrate( { languageCode: attributes.languageCode!, currencyCode: attributes.currencyCode!, @@ -171,18 +172,18 @@ export class SequelizeProformaItemDomainMapper extends SequelizeDomainMapper< globalDiscountPercentage: attributes.globalDiscountPercentage!, taxes: taxesResult.data, }, - attributes.itemId + itemId ); - if (createResult.isFailure) { + /*if (createResult.isFailure) { return Result.fail( new ValidationErrorCollection("Invoice item entity creation failed", [ { path: `items[${index}]`, message: createResult.error.message }, ]) ); - } + }*/ - return createResult; + return Result.ok(newItem); } public mapToPersistence( diff --git a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/repositories/proforma.repository.ts b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/repositories/proforma.repository.ts index 1f7f0538..35ccfb35 100644 --- a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/repositories/proforma.repository.ts +++ b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/repositories/proforma.repository.ts @@ -365,8 +365,6 @@ export class ProformaRepository ? [options.include] : []; - console.log(query.where); - query.where = { ...query.where, ...(options.where ?? {}), 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 efe80805..4b58cf84 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 @@ -1,7 +1,7 @@ import type { JsonTaxCatalogProvider } from "@erp/core"; import { DiscountPercentage, Tax } from "@erp/core/api"; import { - type IProformaItemProps, + type IProformaItemCreateProps, InvoicePaymentMethod, InvoiceSerie, ItemAmount, @@ -9,7 +9,6 @@ import { ItemQuantity, type ProformaItemTaxesProps, } from "@erp/customer-invoices/api/domain"; -import type { CustomerTaxesProps } from "@erp/customers/api/domain"; import { City, Country, @@ -91,7 +90,7 @@ export interface IProformaFromFactuGESProps { paymentMethod: Maybe; - items: IProformaItemProps[]; + items: IProformaItemCreateProps[]; globalDiscountPercentage: DiscountPercentage; }; } @@ -409,29 +408,6 @@ export class CreateProformaFromFactugesInputMapper return customerProps; } - private mapCustomerTaxesProps( - dto: CreateProformaFromFactugesRequestDTO["customer"], - params: { - errors: ValidationErrorDetail[]; - } - ): CustomerTaxesProps { - const { errors } = params; - - const iva = extractOrPushError( - maybeFromNullableResult("iva_21", (value) => Tax.createFromCode(value, this.taxCatalog)), - "iva_21", - errors - ); - - this.throwIfValidationErrors(errors); - - return { - iva: iva!, - rec: Maybe.none(), - retention: Maybe.none(), - }; - } - private mapItemsProps( dto: CreateProformaFromFactugesRequestDTO, params: { @@ -440,8 +416,8 @@ export class CreateProformaFromFactugesInputMapper globalDiscountPercentage: DiscountPercentage; errors: ValidationErrorDetail[]; } - ): IProformaItemProps[] { - const itemsProps: IProformaItemProps[] = []; + ): IProformaItemCreateProps[] { + const itemsProps: IProformaItemCreateProps[] = []; dto.items.forEach((item, index) => { const description = extractOrPushError( @@ -482,15 +458,18 @@ export class CreateProformaFromFactugesInputMapper this.throwIfValidationErrors(params.errors); itemsProps.push({ + description: description!, + + quantity: quantity!, + unitAmount: unitAmount!, + + itemDiscountPercentage: discountPercentage!, + + taxes, + globalDiscountPercentage: params.globalDiscountPercentage, languageCode: params.languageCode, currencyCode: params.currencyCode, - - description: description!, - quantity: quantity!, - unitAmount: unitAmount!, - itemDiscountPercentage: discountPercentage!, - taxes, }); });