209 lines
4.3 KiB
TypeScript
209 lines
4.3 KiB
TypeScript
|
|
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);
|
||
|
|
}
|
||
|
|
}
|