import { DomainEntity, MoneyValue, Percentage, UniqueID } from "@/core/common/domain"; import { Quantity } from "@/core/common/domain/value-objects/quantity"; import { Maybe, Result } from "@repo/rdx-utils"; export interface ICustomerInvoiceItemProps { description: Maybe; // Descripción del artículo o servicio quantity: Maybe; // Cantidad de unidades unitPrice: Maybe; // Precio unitario en la moneda de la factura // subtotalPrice: MoneyValue; // Precio unitario * Cantidad discount: Maybe; // % descuento // totalPrice: MoneyValue; } export interface ICustomerInvoiceItem { description: Maybe; quantity: Maybe; unitPrice: Maybe; subtotalPrice: Maybe; discount: Maybe; totalPrice: Maybe; isEmptyLine(): boolean; } export class CustomerInvoiceItem extends DomainEntity implements ICustomerInvoiceItem { private readonly _subtotalPrice!: Maybe; private readonly _totalPrice!: Maybe; static validate(props: ICustomerInvoiceItemProps) { return Result.ok(props); } static create( props: ICustomerInvoiceItemProps, id?: UniqueID ): Result { const validation = CustomerInvoiceItem.validate(props); if (!validation.isSuccess) { Result.fail(new Error("Invalid invoice line data")); } return Result.ok(new CustomerInvoiceItem(props, id)); } private constructor(props: ICustomerInvoiceItemProps, id?: UniqueID) { super(props, id); this._subtotalPrice = this.calculateSubtotal(); this._totalPrice = this.calculateTotal(); } isEmptyLine(): boolean { return this.quantity.isNone() && this.unitPrice.isNone() && this.discount.isNone(); } calculateSubtotal(): Maybe { if (this.quantity.isNone() || this.unitPrice.isNone()) { return Maybe.none(); } const _quantity = this.quantity.getOrUndefined()!; const _unitPrice = this.unitPrice.getOrUndefined()!; const _subtotal = _unitPrice.multiply(_quantity); return Maybe.some(_subtotal); } calculateTotal(): Maybe { const subtotal = this.calculateSubtotal(); if (subtotal.isNone()) { return Maybe.none(); } const _subtotal = subtotal.getOrUndefined()!; const _discount = this.discount.getOrUndefined()!; const _total = _subtotal.subtract(_subtotal.percentage(_discount)); return Maybe.some(_total); } get description(): Maybe { return this.props.description; } get quantity(): Maybe { return this.props.quantity; } get unitPrice(): Maybe { return this.props.unitPrice; } get subtotalPrice(): Maybe { return this._subtotalPrice; } get discount(): Maybe { return this.props.discount; } get totalPrice(): Maybe { return this._totalPrice; } }