95 lines
2.5 KiB
TypeScript
95 lines
2.5 KiB
TypeScript
import { DomainEntity, MoneyValue, Percentage, Quantity, UniqueID } from "core/common/domain";
|
|
import { Result } from "core/common/helpers";
|
|
import { InvoiceItemDescription } from "../../value-objects";
|
|
|
|
export interface IInvoiceItemProps {
|
|
description: InvoiceItemDescription;
|
|
quantity: Quantity; // Cantidad de unidades
|
|
unitPrice: MoneyValue; // Precio unitario en la moneda de la factura
|
|
//subtotalPrice?: MoneyValue; // Precio unitario * Cantidad
|
|
discount: Percentage; // % descuento
|
|
//totalPrice?: MoneyValue;
|
|
}
|
|
|
|
export interface IInvoiceItem {
|
|
id: UniqueID;
|
|
description: InvoiceItemDescription;
|
|
quantity: Quantity;
|
|
unitPrice: MoneyValue;
|
|
subtotalPrice: MoneyValue;
|
|
discount: Percentage;
|
|
totalPrice: MoneyValue;
|
|
}
|
|
|
|
export class InvoiceItem extends DomainEntity<IInvoiceItemProps> implements IInvoiceItem {
|
|
private _subtotalPrice!: MoneyValue;
|
|
private _totalPrice!: MoneyValue;
|
|
|
|
public static create(props: IInvoiceItemProps, id?: UniqueID): Result<InvoiceItem, Error> {
|
|
const item = new InvoiceItem(props, id);
|
|
|
|
// Reglas de negocio / validaciones
|
|
// ...
|
|
// ...
|
|
|
|
// 🔹 Disparar evento de dominio "InvoiceItemCreatedEvent"
|
|
//const { invoice } = props;
|
|
//user.addDomainEvent(new InvoiceAuthenticatedEvent(id, invoice.toString()));
|
|
|
|
return Result.ok(item);
|
|
}
|
|
|
|
get description(): InvoiceItemDescription {
|
|
return this.props.description;
|
|
}
|
|
|
|
get quantity(): Quantity {
|
|
return this.props.quantity;
|
|
}
|
|
|
|
get unitPrice(): MoneyValue {
|
|
return this.props.unitPrice;
|
|
}
|
|
|
|
get subtotalPrice(): MoneyValue {
|
|
if (!this._subtotalPrice) {
|
|
this._subtotalPrice = this.calculateSubtotal();
|
|
}
|
|
return this._subtotalPrice;
|
|
}
|
|
|
|
get discount(): Percentage {
|
|
return this.props.discount;
|
|
}
|
|
|
|
get totalPrice(): MoneyValue {
|
|
if (!this._totalPrice) {
|
|
this._totalPrice = this.calculateTotal();
|
|
}
|
|
return this._totalPrice;
|
|
}
|
|
|
|
getValue() {
|
|
return this.props;
|
|
}
|
|
|
|
toPrimitive() {
|
|
return {
|
|
description: this.description.toPrimitive(),
|
|
quantity: this.quantity.toPrimitive(),
|
|
unit_price: this.unitPrice.toPrimitive(),
|
|
subtotal_price: this.subtotalPrice.toPrimitive(),
|
|
discount: this.discount.toPrimitive(),
|
|
total_price: this.totalPrice.toPrimitive(),
|
|
};
|
|
}
|
|
|
|
calculateSubtotal(): MoneyValue {
|
|
return this.unitPrice.multiply(this.quantity.toNumber()); // Precio unitario * Cantidad
|
|
}
|
|
|
|
calculateTotal(): MoneyValue {
|
|
return this.subtotalPrice.subtract(this.subtotalPrice.percentage(this.discount.toNumber()));
|
|
}
|
|
}
|