calculateTotals()
Calcula los montos neto, exento, IVA y total en pesos chilenos enteros para un documento o una lista de líneas de detalle.
Pruébalo#
Pruébalo — arma un documento
Vista previa de toXml() — sin firma ni TED
<DTE version="1.0">
<Documento ID="F1024T33">
<Encabezado>
<IdDoc>
<TipoDTE>33</TipoDTE>
<Folio>1024</Folio>
<FchEmis>2026-10-30</FchEmis>
</IdDoc>
<Emisor>
<RUTEmisor>76123456-0</RUTEmisor>
<RznSoc>Arrow Software SpA</RznSoc>
</Emisor>
<Receptor>
<RUTRecep>77654321-7</RUTRecep>
</Receptor>
<Totales>
<MntNeto>120000</MntNeto>
<TasaIVA>19</TasaIVA>
<IVA>22800</IVA>
<MntTotal>142800</MntTotal>
</Totales>
</Encabezado>
<Detalle>
<NroLinDet>1</NroLinDet>
<NmbItem>Licencia anual</NmbItem>
<QtyItem>1</QtyItem>
<PrcItem>120000</PrcItem>
<MontoItem>120000</MontoItem>
</Detalle>
</Documento>
</DTE>Uso básico#
import { calculateTotals } from 'dte-sdk'
calculateTotals([{ name: 'Licencia anual', quantity: 1, unitPrice: 120000 }])
// { net: 120000, exempt: 0, vatRate: 19, vat: 22800, total: 142800 }Firma de tipo#
function calculateTotals(dte: Dte): Totals
function calculateTotals(
items: LineItem[],
options?: { type?: DteType; vatRate?: number; grossPrices?: boolean },
): Totals
interface Totals {
net: number
exempt: number
vatRate: number
vat: number
total: number
}Parámetros#
dte(Dte) - Un documento creado concreateDte(). Se usan su tipo y sus líneas, y el resultado es igual adte.totals.items(LineItem[]) - Las líneas de detalle a totalizar, con la misma forma que encreateDte().options(opcional, solo junto conitems)type(DteType) - Aplica las reglas de ese tipo de documento. Sin él, las líneas se totalizan como un documento afecto común: precios netos, IVA por encima.vatRate(number, por defecto:VAT_RATE, que es19) - Tasa de IVA como porcentaje.grossPrices(boolean) - Si los precios unitarios ya incluyen IVA. Por defecto estrueen boletas (tipo 39) yfalseen todo lo demás.
Valor de retorno#
Retorna un objeto Totals. Todos los montos son enteros en CLP:
net- Suma de las líneas afectas (antes de IVA)exempt- Suma de las líneas exentasvatRate- La tasa aplicada, como porcentajevat- El monto de IVAtotal-net + vat + exempt
Las líneas inválidas lanzan un DteError con código INVALID_AMOUNT, con las mismas reglas que createDte().
Reglas de redondeo#
El peso chileno no tiene decimales, así que cada monto se redondea al peso más cercano, con las mitades hacia arriba (half-up). El orden de las operaciones importa:
- Cada línea se redondea por separado. El monto de una línea es
round(quantity × unitPrice × (1 − discountPercent / 100)), redondeado antes de sumar las líneas. - El IVA se calcula una sola vez, sobre el neto ya sumado:
vat = round(net × vatRate / 100). - Las líneas exentas (
exempt: true) se suman aexempty nunca llevan IVA. - Los documentos exentos (tipos 34 y 41) tratan todas las líneas como exentas:
netyvatquedan en0. - Las boletas (tipo 39) usan precios brutos por defecto. Los precios ya incluyen IVA, así que el total es la suma de las líneas y el IVA se desglosa desde ahí:
net = round(total / 1.19)yvat = total − net. El neto más el IVA siempre suma lo que pagó el cliente.
Redondeo por línea#
Dos líneas de 1,5 × 999 dan 1498,5 cada una, y cada una se redondea hacia arriba a 1499 antes de sumarlas:
import { calculateTotals } from 'dte-sdk'
calculateTotals([
{ name: 'Cable UTP (m)', quantity: 1.5, unitPrice: 999 },
{ name: 'Cable HDMI (m)', quantity: 1.5, unitPrice: 999 },
])
// each line: 1.5 × 999 = 1498.5 → 1499
// net: 1499 + 1499 = 2998 (rounding the sum instead would give 2997)
// vat: round(2998 × 0.19) = round(569.62) = 570
// { net: 2998, exempt: 0, vatRate: 19, vat: 570, total: 3568 }Descuentos#
import { calculateTotals } from 'dte-sdk'
calculateTotals([
{ name: 'Soporte mensual', quantity: 3, unitPrice: 9990, discountPercent: 15 },
])
// line: 3 × 9990 × 0.85 = 25474.5 → 25475 (half-up)
// vat: round(25475 × 0.19) = round(4840.25) = 4840
// { net: 25475, exempt: 0, vatRate: 19, vat: 4840, total: 30315 }Líneas exentas#
import { calculateTotals } from 'dte-sdk'
calculateTotals([
{ name: 'Licencia anual', quantity: 1, unitPrice: 120000 },
{ name: 'Soporte mensual', quantity: 3, unitPrice: 9990, discountPercent: 15 },
{ name: 'Curso de capacitación', quantity: 2, unitPrice: 45000, exempt: true },
])
// net: 120000 + 25475 = 145475
// vat: round(145475 × 0.19) = round(27640.25) = 27640
// exempt: 2 × 45000 = 90000
// { net: 145475, exempt: 90000, vatRate: 19, vat: 27640, total: 263115 }Documentos exentos (34 y 41)#
import { calculateTotals } from 'dte-sdk'
const items = [{ name: 'Licencia anual', quantity: 1, unitPrice: 120000 }]
const totals = calculateTotals(items, { type: 34 })
totals.net // 0
totals.exempt // 120000
totals.vat // 0
totals.total // 120000Boletas (39)#
En una boleta ingresas el precio que ve el cliente, con IVA incluido:
import { calculateTotals } from 'dte-sdk'
calculateTotals([{ name: 'Licencia anual', quantity: 1, unitPrice: 142800 }], { type: 39 })
// net: round(142800 / 1.19) = 120000, vat: 142800 − 120000 = 22800
// { net: 120000, exempt: 0, vatRate: 19, vat: 22800, total: 142800 }
calculateTotals([{ name: 'Café de grano 250 g', quantity: 2, unitPrice: 4990 }], { type: 39 })
// total: 9980, net: round(8386.55) = 8387, vat: 9980 − 8387 = 1593
// { net: 8387, exempt: 0, vatRate: 19, vat: 1593, total: 9980 }Si tu catálogo guarda precios netos, desactiva los precios brutos:
calculateTotals([{ name: 'Licencia anual', quantity: 1, unitPrice: 120000 }], {
type: 39,
grossPrices: false,
})
// { net: 120000, exempt: 0, vatRate: 19, vat: 22800, total: 142800 }Desde un documento#
import { calculateTotals, createDte } from 'dte-sdk'
const dte = createDte(input)
calculateTotals(dte) // same values as dte.totalsPasar un Dte es útil en tests. Para mostrar un desglose antes de que exista el documento, como un carro de compras o una cotización, pasa las líneas directamente.
Funciones relacionadas#
createDte()- Construye un documento y calcula sus totales con estas reglastoXml()- Mira los totales tal como aparecen en el XML