Uecko_ERP/apps/server/src/contexts/invoicing/domain/aggregates/invoice.ts

209 lines
4.3 KiB
TypeScript
Raw Normal View History

2025-03-18 08:05:00 +00:00
import { AggregateRoot, MoneyValue, UniqueID, UtcDate } from "@common/domain";
import { Collection, Result } from "@common/helpers";
import { Currency } from "dinero.js";
import { InvoiceStatus } from "../value-objects";
export interface IInvoiceProps {
invoiceNumber: InvoiceNumber;
invoiceSeries: InvoiceSeries;
issueDate: UtcDate;
operationDate: UtcDate;
//dueDate: UtcDate; // ? --> depende de la forma de pago
//tax: Tax; // ? --> detalles?
invoiceCurrency: Currency;
language: Language;
//purchareOrderNumber: string;
//notes: Note;
//senderId: UniqueID;
recipient: InvoiceParticipant;
//paymentInstructions: Note;
//paymentTerms: string;
items: Collection<InvoiceItem>;
}
export interface IInvoice {
id: UniqueID;
invoiceNumber: InvoiceNumber;
invoiceSeries: InvoiceSeries;
status: InvoiceStatus;
issueDate: UtcDate;
operationDate: UtcDate;
//senderId: UniqueID;
recipient: InvoiceParticipant;
//dueDate
//tax: Tax;
language: Language;
currency: Currency;
//purchareOrderNumber: string;
//notes: Note;
//paymentInstructions: Note;
//paymentTerms: string;
items: Collection<InvoiceItem>;
calculateSubtotal: () => MoneyValue;
calculateTaxTotal: () => MoneyValue;
calculateTotal: () => MoneyValue;
}
export class Invoice extends AggregateRoot<IInvoiceProps> implements IInvoice {
private _items: Collection<InvoiceItem>;
protected _status: InvoiceStatus;
static create(props: IInvoiceProps, id?: UniqueID): Result<Invoice, Error> {
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 recipient(): InvoiceParticipant {
return this.props.recipient;
}
get operationDate() {
return this.props.operationDate;
}
get language() {
return this.props.language;
}
get dueDate() {
return undefined;
}
get tax() {
return undefined;
}
get status() {
return this._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 currency() {
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 {
let subtotal: MoneyValue | null = null;
for (const item of this._items.items) {
if (!subtotal) {
subtotal = item.calculateSubtotal();
} else {
subtotal = subtotal.add(item.calculateSubtotal());
}
}
return subtotal
? subtotal.convertPrecision(2)
: MoneyValue.create({
amount: 0,
currencyCode: this.props.invoiceCurrency.code,
precision: 2,
}).object;
}
// Method to calculate the total tax in the invoice
calculateTaxTotal(): MoneyValue {
let taxTotal = MoneyValue.create({
amount: 0,
currencyCode: this.props.invoiceCurrency.code,
precision: 2,
}).object;
for (const item of this._items.items) {
taxTotal = taxTotal.add(item.calculateTaxAmount());
}
return taxTotal.convertPrecision(2);
}
// Method to calculate the total invoice amount, including taxes
calculateTotal(): MoneyValue {
return this.calculateSubtotal().add(this.calculateTaxTotal()).convertPrecision(2);
}
}