240 lines
5.6 KiB
TypeScript
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());
|
|
}*/
|
|
}
|