import { Tax } from "@erp/core/api"; import { CurrencyCode, LanguageCode } from "@repo/rdx-ddd"; import { Collection } from "@repo/rdx-utils"; import { ItemAmount } from "../../value-objects"; import { CustomerInvoiceItem } from "./customer-invoice-item"; export interface CustomerInvoiceItemsProps { items?: CustomerInvoiceItem[]; languageCode: LanguageCode; currencyCode: CurrencyCode; } export class CustomerInvoiceItems extends Collection { private _languageCode!: LanguageCode; private _currencyCode!: CurrencyCode; constructor(props: CustomerInvoiceItemsProps) { const { items = [], languageCode, currencyCode } = props; super(items); this._languageCode = languageCode; this._currencyCode = currencyCode; } public static create(props: CustomerInvoiceItemsProps): CustomerInvoiceItems { return new CustomerInvoiceItems(props); } add(item: CustomerInvoiceItem): boolean { // Antes de añadir un nuevo item, debo comprobar que el item a añadir // tiene el mismo "currencyCode" y "languageCode" que la colección de items. if ( !this._languageCode.equals(item.languageCode) || !this._currencyCode.equals(item.currencyCode) ) { return false; } return super.add(item); } public getSubtotalAmount(): ItemAmount { return this.getAll().reduce( (total, tax) => total.add(tax.getSubtotalAmount()), ItemAmount.zero(this._currencyCode.code) ); } public getDiscountAmount(): ItemAmount { return this.getAll().reduce( (total, item) => total.add(item.getDiscountAmount()), ItemAmount.zero(this._currencyCode.code) ); } public getTaxableAmount(): ItemAmount { return this.getAll().reduce( (total, item) => total.add(item.getTaxableAmount()), ItemAmount.zero(this._currencyCode.code) ); } public getTaxesAmount(): ItemAmount { return this.getAll().reduce( (total, item) => total.add(item.getTaxesAmount()), ItemAmount.zero(this._currencyCode.code) ); } public getTotalAmount(): ItemAmount { return this.getAll().reduce( (total, item) => total.add(item.getTotalAmount()), ItemAmount.zero(this._currencyCode.code) ); } public getTaxesAmountByTaxes() { const resultMap = new Map(); const currencyCode = this._currencyCode.code; for (const item of this.getAll()) { for (const { taxableAmount, tax, taxesAmount } of item.getTaxesAmountByTaxes()) { const { taxableAmount: taxableCurrent, taxesAmount: taxesCurrent } = resultMap.get(tax) ?? { taxableAmount: ItemAmount.zero(currencyCode), taxesAmount: ItemAmount.zero(currencyCode), }; resultMap.set(tax, { taxableAmount: taxableCurrent.add(taxableAmount), taxesAmount: taxesCurrent.add(taxesAmount), }); } } const items = []; for (const [tax, { taxableAmount, taxesAmount }] of resultMap) { items.push({ taxableAmount, tax, taxesAmount, }); } return items; } }