import { spainTaxCatalogProvider } from "@erp/core"; import { useMoney, usePercentage, useQuantity } from "@erp/core/hooks"; import { useMemo } from "react"; import { CustomerInvoiceItemFormData } from "../schemas"; /** * Recalcula todos los importes de una línea usando los hooks de escala. */ export function useCalculateItemAmounts() { const { multiply, percentage: moneyPct, sum } = useMoney(); const { toNumber: qtyToNumber } = useQuantity(); const { toNumber: pctToNumber } = usePercentage(); const taxCatalog = useMemo(() => spainTaxCatalogProvider, []); return (item: CustomerInvoiceItemFormData): CustomerInvoiceItemFormData => { const qty = qtyToNumber(item.quantity); const subtotal = multiply(item.unit_amount, qty); const discountPct = pctToNumber(item.discount_percentage); const discountAmount = discountPct > 0 ? moneyPct(subtotal, discountPct) : { ...subtotal, value: "0" }; const base = sum([ subtotal, { ...discountAmount, value: (-Number(discountAmount.value)).toString() }, ]); // Impuestos (cada uno es porcentaje sobre la base) const taxesBreakdown = item.tax_codes?.map((tax_code) => { const maybeTax = taxCatalog.findByCode(tax_code); if (maybeTax.isNone()) { throw Error(`Código de impuesto no encontrado en el catálogo: "${tax_code}"`); } const tax = maybeTax.unwrap()!; const percentage = pctToNumber({ value: tax.value, scale: tax.scale }); return { label: tax.name, percentage, amount: moneyPct(base, percentage), }; }) ?? []; const taxes = sum(taxesBreakdown.map((t) => t.amount)); const total = sum([base, taxes]); return { ...item, subtotal_amount: subtotal, discount_amount: discountAmount, taxable_amount: base, taxes_amount: taxes, total_amount: total, }; }; }