@facturacr/atv-sdk
Version:
Librería (SDK) de Javascript/NodeJS para acceder al API de Administración Tributaria Virtual (ATV) del Ministerio de Hacienda.
121 lines (114 loc) • 4.36 kB
text/typescript
import { Document, InvoiceDocumentContainer, DetalleServicio, Resumen, Persona, InformacionReferencia } from '@src/types/facturaInterfaces'
import { Document as DomainDocument } from '../core/Document'
import { OrderLine } from '../core/OrderLine'
import { Person } from '../core/Person'
import { ReferenceInformation } from '../core/ReferenceInformation'
type AtvFormat = InvoiceDocumentContainer
const mapOrderLinesToAtvFormat = (orderLines: OrderLine[]): DetalleServicio => {
const LineaDetalle = orderLines.map<DetalleServicio['LineaDetalle'][0]>((orderLine) => {
return {
NumeroLinea: orderLine.lineNumber,
Codigo: orderLine.code,
// CodigoComercial
Cantidad: orderLine.quantity,
UnidadMedida: orderLine.measureUnit,
// UnidadMedidaComercial
Detalle: orderLine.detail,
PrecioUnitario: orderLine.unitaryPrice,
MontoTotal: orderLine.totalAmount,
// Descuento
SubTotal: orderLine.subTotal,
// BaseImponible
Impuesto: {
Codigo: orderLine.tax.code,
CodigoTarifa: orderLine.tax.rateCode,
Tarifa: orderLine.tax.rate,
Monto: orderLine.tax.amount
},
// ImpuestoNeto
MontoTotalLinea: orderLine.totalOrderLineAmount
}
})
return { LineaDetalle }
}
const mapSummaryInvoice = (summaryInvoice: DomainDocument['summaryInvoice']): Resumen => {
return {
CodigoTipoMoneda: {
CodigoMoneda: summaryInvoice.currency.code,
TipoCambio: summaryInvoice.currency.exchangeRate
},
TotalServGravados: summaryInvoice.totalEncumberedServices,
TotalServExentos: summaryInvoice.totalExemptServices,
TotalMercanciasGravadas: summaryInvoice.totalEncumberedMerchandise,
TotalMercanciasExentas: summaryInvoice.totalExemptMerchandise,
TotalGravado: summaryInvoice.totalEncumbered,
TotalExento: summaryInvoice.totalExempt,
TotalExonerado: summaryInvoice.totalExonerated,
TotalVenta: summaryInvoice.totalSale,
TotalDescuentos: summaryInvoice.totalDiscounts,
TotalVentaNeta: summaryInvoice.totalNetSale,
TotalImpuesto: summaryInvoice.totalTaxes,
TotalComprobante: summaryInvoice.totalVoucher
}
}
const mapPerson = (person: Person): Persona => {
const atvPerson = {
Nombre: person.fullName,
Identificacion: {
Tipo: person.identifierType,
Numero: person.identifierId
},
NombreComercial: person.commercialName,
Ubicacion: undefined,
Telefono: undefined,
Fax: undefined,
CorreoElectronico: undefined
}
atvPerson.Ubicacion = person.location ? {
Provincia: person.location?.province,
Canton: person.location?.canton?.padStart(2, '0'),
Distrito: person.location?.district?.padStart(2, '0'),
Barrio: person.location?.neighborhood?.padStart(2, '0'),
OtrasSenas: person.location?.details
} : undefined
atvPerson.Telefono = person.phone ? {
CodigoPais: person.phone?.countryCode,
NumTelefono: person.phone?.number
} : undefined
atvPerson.Fax = person.fax ? {
CodigoPais: person.fax?.countryCode,
NumTelefono: person.fax?.number
} : undefined
atvPerson.CorreoElectronico = person.email
return atvPerson;
}
const mapReferenceInformation = (referenceInfo: ReferenceInformation): InformacionReferencia => {
return {
TipoDoc: referenceInfo.docType,
Numero: referenceInfo.refNumber,
FechaEmision: referenceInfo.issueDate.toISOString(),
Codigo: referenceInfo.code,
Razon: referenceInfo.reason
}
}
export const mapDocumentToAtvFormat = (docName: string, document: DomainDocument): AtvFormat => {
const key = docName
const doc: Document = {
Clave: document.clave,
CodigoActividad: document.activityCode.padStart(6, '0'),
NumeroConsecutivo: document.fullConsecutive,
FechaEmision: document.issueDate.toISOString(),
Emisor: mapPerson(document.emitter),
Receptor: mapPerson(document.receiver),
CondicionVenta: document.conditionSale,
PlazoCredito: document.deadlineCredit,
MedioPago: document.paymentMethod,
DetalleServicio: mapOrderLinesToAtvFormat(document.orderLines),
ResumenFactura: mapSummaryInvoice(document.summaryInvoice),
Otros: document.others
}
doc.InformacionReferencia = document.referenceInformation ? mapReferenceInformation(document.referenceInformation ) : undefined
return {
[key]: doc
}
}