Uecko_ERP/apps/server/archive/contexts/customer-billing/domain/entities/customer-invoice-item.ts
2025-05-09 12:45:32 +02:00

108 lines
2.9 KiB
TypeScript

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<string>; // Descripción del artículo o servicio
quantity: Maybe<Quantity>; // Cantidad de unidades
unitPrice: Maybe<MoneyValue>; // Precio unitario en la moneda de la factura
// subtotalPrice: MoneyValue; // Precio unitario * Cantidad
discount: Maybe<Percentage>; // % descuento
// totalPrice: MoneyValue;
}
export interface ICustomerInvoiceItem {
description: Maybe<string>;
quantity: Maybe<Quantity>;
unitPrice: Maybe<MoneyValue>;
subtotalPrice: Maybe<MoneyValue>;
discount: Maybe<Percentage>;
totalPrice: Maybe<MoneyValue>;
isEmptyLine(): boolean;
}
export class CustomerInvoiceItem
extends DomainEntity<ICustomerInvoiceItemProps>
implements ICustomerInvoiceItem
{
private readonly _subtotalPrice!: Maybe<MoneyValue>;
private readonly _totalPrice!: Maybe<MoneyValue>;
static validate(props: ICustomerInvoiceItemProps) {
return Result.ok(props);
}
static create(
props: ICustomerInvoiceItemProps,
id?: UniqueID
): Result<CustomerInvoiceItem, Error> {
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<MoneyValue> {
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<MoneyValue> {
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<string> {
return this.props.description;
}
get quantity(): Maybe<Quantity> {
return this.props.quantity;
}
get unitPrice(): Maybe<MoneyValue> {
return this.props.unitPrice;
}
get subtotalPrice(): Maybe<MoneyValue> {
return this._subtotalPrice;
}
get discount(): Maybe<Percentage> {
return this.props.discount;
}
get totalPrice(): Maybe<MoneyValue> {
return this._totalPrice;
}
}