almeira-web/facturacion-dian-hub/backend/src/domain/entities/ItemFactura.ts

68 lines
2.2 KiB
TypeScript

import { Money } from '../value-objects/Money.js';
import { TipoTributo } from '../value-objects/FiscalEnums.js';
import { ValidacionFiscalException } from '../exceptions/ValidacionFiscalException.js';
export interface ItemFacturaProps {
id?: string;
lineNumber: number;
sku: string;
description: string;
quantity: number;
unitCode?: string;
unitPrice: number;
taxPercentage?: number;
taxTypeCode?: TipoTributo;
discountAmount?: number;
}
export class ItemFactura {
public readonly id?: string;
public readonly lineNumber: number;
public readonly sku: string;
public readonly description: string;
public readonly quantity: number;
public readonly unitCode: string;
public readonly unitPrice: Money;
public readonly totalCost: Money;
public readonly taxPercentage: number;
public readonly taxAmount: Money;
public readonly taxTypeCode: TipoTributo;
public readonly discountAmount: Money;
constructor(props: ItemFacturaProps) {
if (props.quantity <= 0) {
throw new ValidacionFiscalException(`La cantidad del item ${props.sku} debe ser mayor a 0.`);
}
if (props.unitPrice < 0) {
throw new ValidacionFiscalException(`El precio unitario del item ${props.sku} no puede ser negativo.`);
}
this.id = props.id;
this.lineNumber = props.lineNumber;
this.sku = props.sku.trim();
this.description = props.description.trim();
this.quantity = props.quantity;
this.unitCode = props.unitCode || 'EA'; // EA: Cada / Unidad
this.unitPrice = Money.from(props.unitPrice);
// Subtotal línea = cantidad * precio unitario
this.totalCost = this.unitPrice.multiply(this.quantity);
this.discountAmount = Money.from(props.discountAmount || 0);
this.taxPercentage = props.taxPercentage ?? 19.0;
this.taxTypeCode = props.taxTypeCode || TipoTributo.IVA;
// Base imponible = totalCost - discountAmount
const baseImponible = this.totalCost.subtract(this.discountAmount);
this.taxAmount = baseImponible.calculateTax(this.taxPercentage);
}
public get subtotalNeto(): Money {
return this.totalCost.subtract(this.discountAmount);
}
public get totalConImpuesto(): Money {
return this.subtotalNeto.add(this.taxAmount);
}
}