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 { InvoiceTax, InvoiceTaxes } from "../invoice-taxes"; 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(): InvoiceTaxes { InvoiceTaxes.create({}); const taxesMap = new Map(); const currencyCode = this._currencyCode.code; for (const item of this.getAll()) { for (const { tax, taxesAmount } of item.getTaxesAmountByTaxes()) { const current = taxesMap.get(tax) ?? ItemAmount.zero(currencyCode); taxesMap.set(tax, current.add(taxesAmount)); } } const items: InvoiceTax[] = []; for (const [tax, taxesAmount] of taxesMap) { items.push( InvoiceTax.create({ tax, taxesAmount, }).data ); } return InvoiceTaxes.create({ items: items, }); } }