xml-generator.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import type { InfoTributaria, InfoFactura, DetalleItem, TotalImpuesto } from "@/types/factura"
  2. import { formatDateForSRI } from "@/utils/factura/validations"
  3. export class XmlGenerator {
  4. static generateFacturaXml(
  5. infoTributaria: InfoTributaria,
  6. infoFactura: InfoFactura,
  7. detalles: DetalleItem[],
  8. totalesImpuestos: TotalImpuesto[]
  9. ): string {
  10. let xml = `<?xml version="1.0" encoding="UTF-8"?>
  11. <factura id="comprobante" version="1.1.0">
  12. <infoTributaria>
  13. <ambiente>${infoTributaria.ambiente}</ambiente>
  14. <tipoEmision>${infoTributaria.tipoEmision}</tipoEmision>
  15. <razonSocial>${infoTributaria.razonSocial}</razonSocial>
  16. <nombreComercial>${infoTributaria.nombreComercial}</nombreComercial>
  17. <ruc>${infoTributaria.ruc}</ruc>
  18. <claveAcceso>${infoTributaria.claveAcceso}</claveAcceso>
  19. <codDoc>01</codDoc>
  20. <estab>${infoTributaria.estab}</estab>
  21. <ptoEmi>${infoTributaria.ptoEmi}</ptoEmi>
  22. <secuencial>${infoTributaria.secuencial}</secuencial>
  23. <dirMatriz>${infoTributaria.dirMatriz}</dirMatriz>
  24. </infoTributaria>
  25. <infoFactura>
  26. <fechaEmision>${formatDateForSRI(infoFactura.fechaEmision)}</fechaEmision>
  27. <dirEstablecimiento>${infoFactura.dirEstablecimiento}</dirEstablecimiento>
  28. <obligadoContabilidad>${infoTributaria.obligadoContabilidad}</obligadoContabilidad>
  29. <tipoIdentificacionComprador>${infoFactura.tipoIdentificacionComprador}</tipoIdentificacionComprador>
  30. <razonSocialComprador>${infoFactura.razonSocialComprador}</razonSocialComprador>
  31. <identificacionComprador>${infoFactura.identificacionComprador}</identificacionComprador>
  32. <totalSinImpuestos>${infoFactura.totalSinImpuestos}</totalSinImpuestos>
  33. <totalDescuento>${infoFactura.totalDescuento}</totalDescuento>
  34. <totalConImpuestos>`
  35. // Agregar múltiples impuestos según los detalles
  36. totalesImpuestos.forEach(impuesto => {
  37. xml += `
  38. <totalImpuesto>
  39. <codigo>${impuesto.codigo}</codigo>
  40. <codigoPorcentaje>${impuesto.codigoPorcentaje}</codigoPorcentaje>
  41. <baseImponible>${impuesto.baseImponible}</baseImponible>
  42. <valor>${impuesto.valor}</valor>
  43. </totalImpuesto>`
  44. })
  45. xml += `
  46. </totalConImpuestos>
  47. <propina>0.00</propina>
  48. <importeTotal>${infoFactura.importeTotal}</importeTotal>
  49. <moneda>DOLAR</moneda>
  50. <pagos>
  51. <pago>
  52. <formaPago>${infoFactura.formaPago}</formaPago>
  53. <total>${infoFactura.importeTotal}</total>
  54. <plazo>${infoFactura.plazo}</plazo>
  55. <unidadTiempo>${infoFactura.unidadTiempo}</unidadTiempo>
  56. </pago>
  57. </pagos>
  58. </infoFactura>
  59. <detalles>`
  60. detalles.forEach(item => {
  61. // Si codigoAuxiliar está vacío, usar el codigoPrincipal como fallback
  62. const codigoAux = item.codigoAuxiliar?.trim() || item.codigoPrincipal || '001'
  63. xml += `
  64. <detalle>
  65. <codigoPrincipal>${item.codigoPrincipal}</codigoPrincipal>
  66. <codigoAuxiliar>${codigoAux}</codigoAuxiliar>
  67. <descripcion>${item.descripcion}</descripcion>
  68. <cantidad>${item.cantidad}</cantidad>
  69. <precioUnitario>${parseFloat(item.precioUnitario).toFixed(6)}</precioUnitario>
  70. <descuento>${item.descuento}</descuento>
  71. <precioTotalSinImpuesto>${item.precioTotalSinImpuesto}</precioTotalSinImpuesto>
  72. <impuestos>
  73. <impuesto>
  74. <codigo>2</codigo>
  75. <codigoPorcentaje>${item.codigoPorcentaje}</codigoPorcentaje>
  76. <tarifa>${item.tarifa}</tarifa>
  77. <baseImponible>${item.baseImponible}</baseImponible>
  78. <valor>${item.valorImpuesto}</valor>
  79. </impuesto>
  80. </impuestos>
  81. </detalle>`
  82. })
  83. xml += `
  84. </detalles>
  85. <infoAdicional>
  86. <campoAdicional nombre="Direccion">${infoFactura.direccionComprador}</campoAdicional>
  87. <campoAdicional nombre="Email">${infoFactura.emailComprador}</campoAdicional>
  88. <campoAdicional nombre="Telefono">${infoFactura.telefonoComprador}</campoAdicional>
  89. </infoAdicional>
  90. </factura>`
  91. return xml
  92. }
  93. }