Uecko_ERP/modules/customer-invoices/src/api/domain/issued-invoices/aggregates/issued-invoice.aggregate.ts
2026-02-17 11:35:07 +01:00

226 lines
5.0 KiB
TypeScript

import {
AggregateRoot,
type CurrencyCode,
DomainValidationError,
type LanguageCode,
type Percentage,
type TextValue,
type UniqueID,
type UtcDate,
} from "@repo/rdx-ddd";
import { type Maybe, Result } from "@repo/rdx-utils";
import type { InvoicePaymentMethod } from "../common/entities";
import type {
InvoiceAmount,
InvoiceNumber,
InvoiceRecipient,
InvoiceSerie,
InvoiceStatus,
} from "../common/value-objects";
import { IssuedInvoiceItems, type IssuedInvoiceTaxes, type VerifactuRecord } from "./entities";
export type IssuedInvoiceProps = {
companyId: UniqueID;
status: InvoiceStatus;
proformaId: Maybe<UniqueID>; // <- proforma padre en caso de issue
series: Maybe<InvoiceSerie>;
invoiceNumber: InvoiceNumber;
invoiceDate: UtcDate;
operationDate: Maybe<UtcDate>;
customerId: UniqueID;
recipient: Maybe<InvoiceRecipient>;
reference: Maybe<string>;
description: Maybe<string>;
notes: Maybe<TextValue>;
languageCode: LanguageCode;
currencyCode: CurrencyCode;
paymentMethod: Maybe<InvoicePaymentMethod>;
items: IssuedInvoiceItems;
taxes: IssuedInvoiceTaxes;
subtotalAmount: InvoiceAmount;
itemDiscountAmount: InvoiceAmount;
globalDiscountPercentage: Percentage;
globalDiscountAmount: InvoiceAmount;
totalDiscountAmount: InvoiceAmount;
taxableAmount: InvoiceAmount;
ivaAmount: InvoiceAmount;
recAmount: InvoiceAmount;
retentionAmount: InvoiceAmount;
taxesAmount: InvoiceAmount;
totalAmount: InvoiceAmount;
verifactu: Maybe<VerifactuRecord>;
};
export class IssuedInvoice extends AggregateRoot<IssuedInvoiceProps> {
private _items!: IssuedInvoiceItems;
protected constructor(props: IssuedInvoiceProps, id?: UniqueID) {
super(props, id);
this._items =
props.items ||
IssuedInvoiceItems.create({
languageCode: props.languageCode,
currencyCode: props.currencyCode,
globalDiscountPercentage: props.globalDiscountPercentage,
});
}
static create(props: IssuedInvoiceProps, id?: UniqueID): Result<IssuedInvoice, Error> {
if (!props.recipient) {
return Result.fail(
new DomainValidationError(
"MISSING_RECIPIENT",
"recipient",
"Issued invoice requires recipient"
)
);
}
const issuedInvoice = new IssuedInvoice(props, id);
// Reglas de negocio / validaciones
// ...
// 🔹 Disparar evento de dominio "IssuedInvoiceAuthenticatedEvent"
//const { customerInvoice } = props;
//user.addDomainEvent(new IssuedInvoiceAuthenticatedEvent(id, customerInvoice.toString()));
return Result.ok(issuedInvoice);
}
// Getters
public get companyId(): UniqueID {
return this.props.companyId;
}
public get customerId(): UniqueID {
return this.props.customerId;
}
public get proformaId(): Maybe<UniqueID> {
return this.props.proformaId;
}
public get status(): InvoiceStatus {
return this.props.status;
}
public get series(): Maybe<InvoiceSerie> {
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 reference(): Maybe<string> {
return this.props.reference;
}
public get description(): Maybe<string> {
return this.props.description;
}
public get notes(): Maybe<TextValue> {
return this.props.notes;
}
public get recipient(): Maybe<InvoiceRecipient> {
return this.props.recipient;
}
public get paymentMethod(): Maybe<InvoicePaymentMethod> {
return this.props.paymentMethod;
}
public get languageCode(): LanguageCode {
return this.props.languageCode;
}
public get currencyCode(): CurrencyCode {
return this.props.currencyCode;
}
public get verifactu(): Maybe<VerifactuRecord> {
return this.props.verifactu;
}
public get subtotalAmount(): InvoiceAmount {
return this.props.subtotalAmount;
}
public get itemDiscountAmount(): InvoiceAmount {
return this.props.itemDiscountAmount;
}
public get globalDiscountPercentage(): Percentage {
return this.props.globalDiscountPercentage;
}
public get globalDiscountAmount(): InvoiceAmount {
return this.props.globalDiscountAmount;
}
public get totalDiscountAmount(): InvoiceAmount {
return this.props.totalDiscountAmount;
}
public get taxableAmount(): InvoiceAmount {
return this.props.taxableAmount;
}
public get taxesAmount(): InvoiceAmount {
return this.props.taxesAmount;
}
public get totalAmount(): InvoiceAmount {
return this.props.totalAmount;
}
public get taxes(): IssuedInvoiceTaxes {
return this.props.taxes;
}
// Method to get the complete list of line items
public get items(): IssuedInvoiceItems {
return this._items;
}
public get hasRecipient() {
return this.recipient.isSome();
}
public get hasPaymentMethod() {
return this.paymentMethod.isSome();
}
public getProps(): IssuedInvoiceProps {
return this.props;
}
}