import { AggregateRoot, MoneyValue, UniqueID, UtcDate } from "@/core/common/domain"; import { Collection, Result } from "@/core/common/helpers"; import { InvoiceCustomer, InvoiceItem, InvoiceItems } from "../entities"; import { InvoiceNumber, InvoiceSerie, InvoiceStatus } from "../value-objects"; export interface IInvoiceProps { invoiceNumber: InvoiceNumber; invoiceSeries: InvoiceSerie; status: InvoiceStatus; issueDate: UtcDate; operationDate: UtcDate; //dueDate: UtcDate; // ? --> depende de la forma de pago //tax: Tax; // ? --> detalles? invoiceCurrency: string; //language: Language; //purchareOrderNumber: string; //notes: Note; //senderId: UniqueID; //paymentInstructions: Note; //paymentTerms: string; customer?: InvoiceCustomer; items?: InvoiceItems; } export interface IInvoice { id: UniqueID; invoiceNumber: InvoiceNumber; invoiceSeries: InvoiceSerie; status: InvoiceStatus; issueDate: UtcDate; operationDate: UtcDate; //senderId: UniqueID; customer?: InvoiceCustomer; //dueDate //tax: Tax; //language: Language; invoiceCurrency: string; //purchareOrderNumber: string; //notes: Note; //paymentInstructions: Note; //paymentTerms: string; items: InvoiceItems; calculateSubtotal: () => MoneyValue; calculateTaxTotal: () => MoneyValue; calculateTotal: () => MoneyValue; } export class Invoice extends AggregateRoot implements IInvoice { private _items!: Collection; //protected _status: InvoiceStatus; protected constructor(props: IInvoiceProps, id?: UniqueID) { super(props, id); this._items = props.items || InvoiceItems.create(); } static create(props: IInvoiceProps, id?: UniqueID): Result { const invoice = new Invoice(props, id); // Reglas de negocio / validaciones // ... // ... // 🔹 Disparar evento de dominio "InvoiceAuthenticatedEvent" //const { invoice } = props; //user.addDomainEvent(new InvoiceAuthenticatedEvent(id, invoice.toString())); return Result.ok(invoice); } get invoiceNumber() { return this.props.invoiceNumber; } get invoiceSeries() { return this.props.invoiceSeries; } get issueDate() { return this.props.issueDate; } /*get senderId(): UniqueID { return this.props.senderId; }*/ get customer(): InvoiceCustomer | undefined { return this.props.customer; } get operationDate() { return this.props.operationDate; } /*get language() { return this.props.language; }*/ get dueDate() { return undefined; } get tax() { return undefined; } get status() { return this.props.status; } get items() { return this._items; } /*get purchareOrderNumber() { return this.props.purchareOrderNumber; } get paymentInstructions() { return this.props.paymentInstructions; } get paymentTerms() { return this.props.paymentTerms; } get billTo() { return this.props.billTo; } get shipTo() { return this.props.shipTo; }*/ get invoiceCurrency() { return this.props.invoiceCurrency; } /*get notes() { return this.props.notes; }*/ // Method to get the complete list of line items /*get lineItems(): InvoiceLineItem[] { return this._lineItems; } addLineItem(lineItem: InvoiceLineItem, position?: number): void { if (position === undefined) { this._lineItems.push(lineItem); } else { this._lineItems.splice(position, 0, lineItem); } }*/ calculateSubtotal(): MoneyValue { const invoiceSubtotal = MoneyValue.create({ amount: 0, currency_code: this.props.invoiceCurrency, scale: 2, }).data; return this._items.getAll().reduce((subtotal, item) => { return subtotal.add(item.calculateTotal()); }, invoiceSubtotal); } // Method to calculate the total tax in the invoice calculateTaxTotal(): MoneyValue { const taxTotal = MoneyValue.create({ amount: 0, currency_code: this.props.invoiceCurrency, scale: 2, }).data; return taxTotal; } // Method to calculate the total invoice amount, including taxes calculateTotal(): MoneyValue { return this.calculateSubtotal().add(this.calculateTaxTotal()); } }