68 lines
2.2 KiB
TypeScript
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);
|
|
}
|
|
}
|