Uecko_ERP/modules/customer-invoices/src/api/domain/aggregates/customer-invoice.ts
2025-09-10 18:06:29 +02:00

240 lines
5.6 KiB
TypeScript

import { DomainValidationError } from "@erp/core/api";
import {
AggregateRoot,
CurrencyCode,
LanguageCode,
MoneyValue,
Percentage,
TextValue,
UniqueID,
UtcDate,
} from "@repo/rdx-ddd";
import { Maybe, Result } from "@repo/rdx-utils";
import { CustomerInvoiceItems } from "../entities";
import { InvoiceTaxes } from "../entities/invoice-taxes";
import {
CustomerInvoiceNumber,
CustomerInvoiceSerie,
CustomerInvoiceStatus,
InvoiceRecipient,
} from "../value-objects";
export interface CustomerInvoiceProps {
companyId: UniqueID;
isProforma: boolean;
invoiceNumber: CustomerInvoiceNumber;
status: CustomerInvoiceStatus;
series: Maybe<CustomerInvoiceSerie>;
invoiceDate: UtcDate;
operationDate: Maybe<UtcDate>;
customerId: UniqueID;
recipient: Maybe<InvoiceRecipient>;
notes: Maybe<TextValue>;
languageCode: LanguageCode;
currencyCode: CurrencyCode;
//subtotalAmount: MoneyValue;
discountPercentage: Percentage;
//discountAmount: MoneyValue;
taxes: InvoiceTaxes;
//totalAmount: MoneyValue;
items: CustomerInvoiceItems;
}
export type CustomerInvoicePatchProps = Partial<Omit<CustomerInvoiceProps, "companyId">>;
export class CustomerInvoice extends AggregateRoot<CustomerInvoiceProps> {
private _items!: CustomerInvoiceItems;
protected constructor(props: CustomerInvoiceProps, id?: UniqueID) {
super(props, id);
this._items =
props.items ||
CustomerInvoiceItems.create({
languageCode: props.languageCode,
currencyCode: props.currencyCode,
});
}
static create(props: CustomerInvoiceProps, id?: UniqueID): Result<CustomerInvoice, Error> {
const customerInvoice = new CustomerInvoice(props, id);
// Reglas de negocio / validaciones
if (!customerInvoice.isProforma && !customerInvoice.hasRecipient) {
return Result.fail(
new DomainValidationError(
"MISSING_CUSTOMER_DATA",
"recipient",
"Customer data must be provided for non-proforma invoices"
)
);
}
// 🔹 Disparar evento de dominio "CustomerInvoiceAuthenticatedEvent"
//const { customerInvoice } = props;
//user.addDomainEvent(new CustomerInvoiceAuthenticatedEvent(id, customerInvoice.toString()));
return Result.ok(customerInvoice);
}
public update(partialInvoice: CustomerInvoicePatchProps): Result<CustomerInvoice, Error> {
throw new Error("Not implemented");
}
public get companyId(): UniqueID {
return this.props.companyId;
}
public get customerId(): UniqueID {
return this.props.customerId;
}
public get isProforma(): boolean {
return this.props.isProforma;
}
public get status(): CustomerInvoiceStatus {
return this.props.status;
}
public get series(): Maybe<CustomerInvoiceSerie> {
return this.props.series;
}
public get invoiceNumber() {
return this.props.invoiceNumber;
}
public get invoiceDate(): UtcDate {
return this.props.invoiceDate;
}
public get operationDate(): Maybe<UtcDate> {
return this.props.operationDate;
}
public get notes(): Maybe<TextValue> {
return this.props.notes;
}
public get recipient(): Maybe<InvoiceRecipient> {
return this.props.recipient;
}
public get languageCode(): LanguageCode {
return this.props.languageCode;
}
public get currencyCode(): CurrencyCode {
return this.props.currencyCode;
}
public get subtotalAmount(): MoneyValue {
throw new Error("discountAmount not implemented");
}
public get discountPercentage(): Percentage {
return this.props.discountPercentage;
}
public get discountAmount(): MoneyValue {
throw new Error("discountAmount not implemented");
}
public get taxableAmount(): MoneyValue {
throw new Error("taxableAmount not implemented");
}
public get taxAmount(): MoneyValue {
throw new Error("discountAmount not implemented");
}
public get totalAmount(): MoneyValue {
throw new Error("totalAmount not implemented");
}
// Method to get the complete list of line items
get items(): CustomerInvoiceItems {
return this._items;
}
get hasRecipient() {
return this.recipient.isSome();
}
/*get senderId(): UniqueID {
return this.props.senderId;
}*/
/* get customer(): CustomerInvoiceCustomer | undefined {
return this.props.customer;
}*/
/*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;
}*/
/*
addLineItem(lineItem: CustomerInvoiceLineItem, position?: number): void {
if (position === undefined) {
this._lineItems.push(lineItem);
} else {
this._lineItems.splice(position, 0, lineItem);
}
}*/
/*calculateSubtotal(): MoneyValue {
const customerInvoiceSubtotal = MoneyValue.create({
amount: 0,
currency_code: this.props.currency,
scale: 2,
}).data;
return this._items.getAll().reduce((subtotal, item) => {
return subtotal.add(item.calculateTotal());
}, customerInvoiceSubtotal);
}*/
// Method to calculate the total tax in the customerInvoice
/*calculateTaxTotal(): MoneyValue {
const taxTotal = MoneyValue.create({
amount: 0,
currency_code: this.props.currency,
scale: 2,
}).data;
return taxTotal;
}*/
// Method to calculate the total customerInvoice amount, including taxes
/*calculateTotal(): MoneyValue {
return this.calculateSubtotal().add(this.calculateTaxTotal());
}*/
}