UNPKG

@facturacr/atv-sdk

Version:

Librería (SDK) de Javascript/NodeJS para acceder al API de Administración Tributaria Virtual (ATV) del Ministerio de Hacienda.

132 lines (123 loc) 4.01 kB
import { ClientPayload } from '@src/types/globalInterfaces' import { InvoiceDocumentContainer, Resumen, Persona, Impuesto, LineaDetalle } from '@src/types/facturaInterfaces' import { genXML } from '@src/lib/genXML' // Default XML Values const DEFAULT_VALUES = { key: 0, message: 'Default msj', detailsMessage: 'Default details msj', tipoIdentificacion: '01' as Persona['Identificacion']['Tipo'] } function sumLines(lines: LineaDetalle[]): any { return lines.reduce((accumulator: any, currentValue: any) => { const prevTotal = accumulator.MontoTotal || 0 const prevTax = accumulator.Impuesto || { Impuesto: { Monto: 0 } } return { total: prevTotal + currentValue.MontoTotal, taxes: prevTax.Impuesto.Monto + currentValue.Impuesto.Monto } }, 0) } function getBillResum(lines: LineaDetalle[]): Resumen { const sum = sumLines(lines) return { CodigoTipoMoneda: { CodigoMoneda: 'CRC', TipoCambio: '585.69' }, TotalServGravados: 0, TotalServExentos: 0, // TotalServExonerado: 0, TotalMercanciasGravadas: sum.total, TotalMercanciasExentas: 0, TotalGravado: sum.total, TotalExento: 0, TotalExonerado: 0, TotalVenta: sum.total, TotalDescuentos: 0, TotalVentaNeta: sum.total, TotalImpuesto: sum.taxes, TotalComprobante: sum.total + sum.taxes } } function getSender(frontEndRequest: ClientPayload): Persona { const sender = frontEndRequest.Emisor return { Nombre: sender.Nombre, Identificacion: { Tipo: sender.Identificacion.Tipo || DEFAULT_VALUES.tipoIdentificacion, Numero: sender.Identificacion.Numero }, NombreComercial: sender.NombreComercial, Ubicacion: sender.Ubicacion, Telefono: sender.Telefono, Fax: sender.Fax, CorreoElectronico: sender.CorreoElectronico } } function setTaxObj(subtotal: number, taxObj: Impuesto): Impuesto { const tax = typeof taxObj.Tarifa === 'number' ? taxObj.Tarifa : 13 return { Codigo: taxObj.Codigo, CodigoTarifa: taxObj.CodigoTarifa, Tarifa: tax, Monto: subtotal * (tax / 100) } } export function setLinesDefaults(lines: LineaDetalle[]): LineaDetalle[] { return lines.map((line, index) => { const quantity = line.Cantidad || 1 const total = line.PrecioUnitario * quantity const subtotal = total // restar descuentos const taxObj = setTaxObj(subtotal, line.Impuesto) return { NumeroLinea: (index + 1).toString(), Codigo: line.Codigo, Cantidad: quantity, UnidadMedida: line.UnidadMedida || 'Sp', Detalle: line.Detalle, PrecioUnitario: line.PrecioUnitario, MontoTotal: total, SubTotal: subtotal, Impuesto: taxObj, MontoTotalLinea: subtotal + taxObj.Monto } }) } function getReceiver(frontEndRequest: ClientPayload): Persona { const receiver = frontEndRequest.Receptor return { Nombre: receiver.Nombre, Identificacion: { Tipo: receiver.Identificacion.Tipo || DEFAULT_VALUES.tipoIdentificacion, Numero: receiver.Identificacion.Numero }, NombreComercial: receiver.NombreComercial, Ubicacion: receiver.Ubicacion } } export default async (frontEndRequest: ClientPayload, date: any, clave: string, consecutivo: string, options: any): Promise<any> => { const receiver = getReceiver(frontEndRequest) const sender = getSender(frontEndRequest) const lines = setLinesDefaults(frontEndRequest.LineasDetalle) const key = frontEndRequest.facturaElectronicaType || 'FacturaElectronica' const body = { Clave: clave, CodigoActividad: frontEndRequest.actividad.padStart(6, '0'), NumeroConsecutivo: consecutivo, FechaEmision: date, Emisor: sender, Receptor: receiver, CondicionVenta: '01', MedioPago: '03', DetalleServicio: { LineaDetalle: lines }, ResumenFactura: getBillResum(lines) } const factura: InvoiceDocumentContainer = { [key]: body } const XML = await genXML(key, factura, options) return XML }