From 167eaff171ac0224b27193a341a289be67313d89 Mon Sep 17 00:00:00 2001 From: david Date: Sat, 21 Feb 2026 22:11:18 +0100 Subject: [PATCH] . --- .../aggregates/proforma.aggregate.ts | 4 +- .../proforma-items.collection.ts | 60 +------------ .../api/domain/proformas/services/index.ts | 2 +- .../services/proforma-compare-tax-totals.ts | 2 +- .../proforma-items-totals-calculator.ts | 89 +++++++++++++++++++ ...ulator.ts => proforma-taxes-calculator.ts} | 2 +- .../rdx-ddd/src/value-objects/money-value.ts | 2 - 7 files changed, 96 insertions(+), 65 deletions(-) create mode 100644 modules/customer-invoices/src/api/domain/proformas/services/proforma-items-totals-calculator.ts rename modules/customer-invoices/src/api/domain/proformas/services/{proforma-tax-calculator.ts => proforma-taxes-calculator.ts} (98%) 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 5a530662..6522eb56 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 { ProformaItems } from "../entities/proforma-items"; -import { type IProformaTaxTotals, ProformaTaxCalculator } from "../services"; +import { type IProformaTaxTotals, ProformaTaxesCalculator } from "../services"; export type ProformaProps = { companyId: UniqueID; @@ -255,7 +255,7 @@ export class Proforma extends AggregateRoot implements IProforma } public taxes(): Collection { - return new ProformaTaxCalculator(this.items).calculate(); + return new ProformaTaxesCalculator(this.items).calculate(); } public getProps(): ProformaProps { 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 a0cecb80..1bed806a 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 @@ -2,7 +2,7 @@ import type { DiscountPercentage } from "@erp/core/api"; import type { CurrencyCode, LanguageCode } from "@repo/rdx-ddd"; import { Collection } from "@repo/rdx-utils"; -import { ItemAmount } from "../../../common"; +import { ProformaItemsTotalsCalculator } from "../../services/proforma-items-totals-calculator"; import type { IProformaItem, IProformaItemTotals, ProformaItem } from "./proforma-item.entity"; @@ -77,63 +77,7 @@ export class ProformaItems extends Collection implements IProforma * Delega en los ítems individuales (DDD correcto) pero evita múltiples recorridos. */ public totals(): IProformaItemTotals { - let subtotalAmount = ItemAmount.zero(this.currencyCode.code); - - let itemDiscountAmount = ItemAmount.zero(this.currencyCode.code); - let globalDiscountAmount = ItemAmount.zero(this.currencyCode.code); - let totalDiscountAmount = ItemAmount.zero(this.currencyCode.code); - - let taxableAmount = ItemAmount.zero(this.currencyCode.code); - - let ivaAmount = ItemAmount.zero(this.currencyCode.code); - let recAmount = ItemAmount.zero(this.currencyCode.code); - let retentionAmount = ItemAmount.zero(this.currencyCode.code); - - let taxesAmount = ItemAmount.zero(this.currencyCode.code); - let totalAmount = ItemAmount.zero(this.currencyCode.code); - - for (const item of this.getAll()) { - const amounts = item.totals(); - - // Subtotales - subtotalAmount = subtotalAmount.add(amounts.subtotalAmount); - - // Descuentos - itemDiscountAmount = itemDiscountAmount.add(amounts.itemDiscountAmount); - globalDiscountAmount = globalDiscountAmount.add(amounts.globalDiscountAmount); - totalDiscountAmount = totalDiscountAmount.add(amounts.totalDiscountAmount); - - // Base imponible - taxableAmount = taxableAmount.add(amounts.taxableAmount); - - // Impuestos individuales - ivaAmount = ivaAmount.add(amounts.ivaAmount); - recAmount = recAmount.add(amounts.recAmount); - retentionAmount = retentionAmount.add(amounts.retentionAmount); - - // Total impuestos del ítem - taxesAmount = taxesAmount.add(amounts.taxesAmount); - - // Total final del ítem - totalAmount = totalAmount.add(amounts.totalAmount); - } - - return { - subtotalAmount, - - itemDiscountAmount, - globalDiscountAmount, - totalDiscountAmount, - - taxableAmount, - - ivaAmount, - recAmount, - retentionAmount, - - taxesAmount, - totalAmount, - } as const; + return new ProformaItemsTotalsCalculator(this).calculate(); } private ensureSameCurrencyAndLanguage(items: IProformaItem[]): void { diff --git a/modules/customer-invoices/src/api/domain/proformas/services/index.ts b/modules/customer-invoices/src/api/domain/proformas/services/index.ts index c42288b1..f76afc95 100644 --- a/modules/customer-invoices/src/api/domain/proformas/services/index.ts +++ b/modules/customer-invoices/src/api/domain/proformas/services/index.ts @@ -1 +1 @@ -export * from "./proforma-tax-calculator"; +export * from "./proforma-taxes-calculator"; diff --git a/modules/customer-invoices/src/api/domain/proformas/services/proforma-compare-tax-totals.ts b/modules/customer-invoices/src/api/domain/proformas/services/proforma-compare-tax-totals.ts index b28e0645..68eadcfa 100644 --- a/modules/customer-invoices/src/api/domain/proformas/services/proforma-compare-tax-totals.ts +++ b/modules/customer-invoices/src/api/domain/proformas/services/proforma-compare-tax-totals.ts @@ -1,7 +1,7 @@ import type { TaxPercentage } from "@erp/core/api"; import type { Maybe } from "@repo/rdx-utils"; -import type { IProformaTaxTotals } from "./proforma-tax-calculator"; +import type { IProformaTaxTotals } from "./proforma-taxes-calculator"; /** * Orden determinista: diff --git a/modules/customer-invoices/src/api/domain/proformas/services/proforma-items-totals-calculator.ts b/modules/customer-invoices/src/api/domain/proformas/services/proforma-items-totals-calculator.ts new file mode 100644 index 00000000..7d8fea22 --- /dev/null +++ b/modules/customer-invoices/src/api/domain/proformas/services/proforma-items-totals-calculator.ts @@ -0,0 +1,89 @@ +import { ItemAmount } from "../../common"; +import type { IProformaItems } from "../entities"; + +export interface IProformaItemsTotals { + subtotalAmount: ItemAmount; + + itemDiscountAmount: ItemAmount; + globalDiscountAmount: ItemAmount; + totalDiscountAmount: ItemAmount; + + taxableAmount: ItemAmount; + + ivaAmount: ItemAmount; + recAmount: ItemAmount; + retentionAmount: ItemAmount; + + taxesAmount: ItemAmount; + totalAmount: ItemAmount; +} + +/** + * Calcula los totales (scale 4) a partir de las líneas valoradas. + * La lógica fiscal está en ProformaItem; aquí solo se agregan resultados. + */ +export class ProformaItemsTotalsCalculator { + constructor(private readonly items: IProformaItems) {} + + public calculate(): IProformaItemsTotals { + const zero = ItemAmount.zero(this.items.currencyCode.code); + + let subtotalAmount = zero; + + let itemDiscountAmount = zero; + let globalDiscountAmount = zero; + let totalDiscountAmount = zero; + + let taxableAmount = zero; + + let ivaAmount = zero; + let recAmount = zero; + let retentionAmount = zero; + + let taxesAmount = zero; + let totalAmount = zero; + + for (const item of this.items.getAll()) { + const amounts = item.totals(); + + // Subtotales + subtotalAmount = subtotalAmount.add(amounts.subtotalAmount); + + // Descuentos + itemDiscountAmount = itemDiscountAmount.add(amounts.itemDiscountAmount); + globalDiscountAmount = globalDiscountAmount.add(amounts.globalDiscountAmount); + totalDiscountAmount = totalDiscountAmount.add(amounts.totalDiscountAmount); + + // Base imponible + taxableAmount = taxableAmount.add(amounts.taxableAmount); + + // Impuestos individuales + ivaAmount = ivaAmount.add(amounts.ivaAmount); + recAmount = recAmount.add(amounts.recAmount); + retentionAmount = retentionAmount.add(amounts.retentionAmount); + + // Total impuestos del ítem + taxesAmount = taxesAmount.add(amounts.taxesAmount); + + // Total final del ítem + totalAmount = totalAmount.add(amounts.totalAmount); + } + + return { + subtotalAmount, + + itemDiscountAmount, + globalDiscountAmount, + totalDiscountAmount, + + taxableAmount, + + ivaAmount, + recAmount, + retentionAmount, + + taxesAmount, + totalAmount, + } as const; + } +} diff --git a/modules/customer-invoices/src/api/domain/proformas/services/proforma-tax-calculator.ts b/modules/customer-invoices/src/api/domain/proformas/services/proforma-taxes-calculator.ts similarity index 98% rename from modules/customer-invoices/src/api/domain/proformas/services/proforma-tax-calculator.ts rename to modules/customer-invoices/src/api/domain/proformas/services/proforma-taxes-calculator.ts index 8f0eed87..9a4a6b5e 100644 --- a/modules/customer-invoices/src/api/domain/proformas/services/proforma-tax-calculator.ts +++ b/modules/customer-invoices/src/api/domain/proformas/services/proforma-taxes-calculator.ts @@ -25,7 +25,7 @@ export interface IProformaTaxTotals { taxesAmount: InvoiceAmount; } -export class ProformaTaxCalculator { +export class ProformaTaxesCalculator { constructor(private readonly items: IProformaItems) {} public calculate(): Collection { diff --git a/packages/rdx-ddd/src/value-objects/money-value.ts b/packages/rdx-ddd/src/value-objects/money-value.ts index 339ae14b..595049dd 100644 --- a/packages/rdx-ddd/src/value-objects/money-value.ts +++ b/packages/rdx-ddd/src/value-objects/money-value.ts @@ -8,8 +8,6 @@ import { ValueObject } from "./value-object"; const DEFAULT_SCALE = 2; const DEFAULT_CURRENCY_CODE = "EUR"; -type CurrencyData = Currency; - export type RoundingMode = | "HALF_ODD" | "HALF_EVEN"