@facturacr/atv-sdk 0.0.7-beta → 0.0.9-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/.github/workflows/ci.yml +7 -4
  2. package/__tests__/stubs/commonExpectedXml.xml +94 -0
  3. package/__tests__/stubs/createDocument.stub.ts +80 -0
  4. package/__tests__/tests/ATV/__snapshots__/index.test.ts.snap +3 -0
  5. package/__tests__/tests/ATV/index.test.ts +50 -0
  6. package/doc/atv-structures/4.3/ANEXOS Y ESTRUCTURAS_V4.3.pdf +0 -0
  7. package/doc/atv-structures/4.3/API Ministerio de Hacienda /342/200/223 Dropbox Paper.pdf +0 -0
  8. package/doc/atv-structures/4.3/MensajeHacienda_V4.3.xsd.xml +179 -0
  9. package/doc/atv-structures/4.3/MensajeReceptor_V4.3.xsd.xml +163 -0
  10. package/doc/atv-structures/4.3/NotaCreditoElectronica_V4.3.xsd.xml +1804 -0
  11. package/doc/atv-structures/4.3/NotaDebitoElectronica_V4.3.xsd.xml +1804 -0
  12. package/examples/confirmXML.ts +1 -1
  13. package/examples/createAndSend.ts +27 -32
  14. package/examples/getToken.ts +3 -2
  15. package/jest-setup.js +5 -0
  16. package/jest.config.js +6 -5
  17. package/package.json +18 -14
  18. package/src/ATV/core/Clave.ts +41 -0
  19. package/src/ATV/core/Document.ts +123 -0
  20. package/src/ATV/core/DocumentType.ts +23 -0
  21. package/src/ATV/core/FullConsecutive.ts +29 -0
  22. package/src/ATV/core/OrderLine.ts +95 -0
  23. package/src/ATV/core/Person.ts +68 -0
  24. package/src/ATV/core/Summary.type.ts +20 -0
  25. package/src/ATV/core/documentNames.types.ts +5 -0
  26. package/src/ATV/index.ts +101 -0
  27. package/src/ATV/mappers/billDocToAtv.ts +103 -0
  28. package/src/ATV/types.ts +37 -0
  29. package/src/ATV/useCases/createDocument/index.ts +137 -0
  30. package/src/ATV/useCases/createDocument/types.ts +79 -0
  31. package/src/helpers/comprobantes.ts +1 -1
  32. package/src/lib/genJSON/confirmXML.ts +1 -1
  33. package/src/lib/genJSON/index.ts +2 -2
  34. package/src/lib/genXML/xmlConfig.ts +2 -2
  35. package/src/services/getToken/GetToken.ts +2 -2
  36. package/src/services/send/index.ts +1 -1
  37. package/src/types/facturaInterfaces.d.ts +27 -20
  38. package/tools/xsdToJsonSchema.ts +2 -2
  39. package/__tests__/tests/electronicBill.test.ts +0 -28
  40. package/dist/__tests__/stubs/frontendRequest.stub.d.ts +0 -3
  41. package/dist/__tests__/stubs/frontendRequest.stub.js +0 -61
  42. package/dist/__tests__/stubs/frontendRequest.stub.js.map +0 -1
  43. package/dist/__tests__/stubs/token.stub.d.ts +0 -17
  44. package/dist/__tests__/stubs/token.stub.js +0 -21
  45. package/dist/__tests__/stubs/token.stub.js.map +0 -1
  46. package/dist/__tests__/tests/electronicBill.test.d.ts +0 -1
  47. package/dist/__tests__/tests/electronicBill.test.js +0 -38
  48. package/dist/__tests__/tests/electronicBill.test.js.map +0 -1
  49. package/dist/__tests__/tests/getClave.test.d.ts +0 -1
  50. package/dist/__tests__/tests/getClave.test.js +0 -15
  51. package/dist/__tests__/tests/getClave.test.js.map +0 -1
  52. package/dist/__tests__/tests/getToken.test.d.ts +0 -0
  53. package/dist/__tests__/tests/getToken.test.js +0 -28
  54. package/dist/__tests__/tests/getToken.test.js.map +0 -1
  55. package/dist/__tests__/tests/lib/getClave.test.d.ts +0 -1
  56. package/dist/__tests__/tests/lib/getClave.test.js +0 -15
  57. package/dist/__tests__/tests/lib/getClave.test.js.map +0 -1
  58. package/dist/__tests__/tests/services/getToken.test.d.ts +0 -1
  59. package/dist/__tests__/tests/services/getToken.test.js +0 -27
  60. package/dist/__tests__/tests/services/getToken.test.js.map +0 -1
  61. package/dist/examples/confirmXML.d.ts +0 -1
  62. package/dist/examples/confirmXML.js +0 -89
  63. package/dist/examples/confirmXML.js.map +0 -1
  64. package/dist/examples/consultXML.d.ts +0 -1
  65. package/dist/examples/consultXML.js +0 -55
  66. package/dist/examples/consultXML.js.map +0 -1
  67. package/dist/examples/createAndSend.d.ts +0 -1
  68. package/dist/examples/createAndSend.js +0 -77
  69. package/dist/examples/createAndSend.js.map +0 -1
  70. package/dist/examples/createCreditNote.d.ts +0 -1
  71. package/dist/examples/createCreditNote.js +0 -52
  72. package/dist/examples/createCreditNote.js.map +0 -1
  73. package/dist/examples/createDebitNote.d.ts +0 -1
  74. package/dist/examples/createDebitNote.js +0 -52
  75. package/dist/examples/createDebitNote.js.map +0 -1
  76. package/dist/examples/genBasicXML.d.ts +0 -1
  77. package/dist/examples/genBasicXML.js +0 -44
  78. package/dist/examples/genBasicXML.js.map +0 -1
  79. package/dist/examples/getClave.d.ts +0 -1
  80. package/dist/examples/getClave.js +0 -12
  81. package/dist/examples/getClave.js.map +0 -1
  82. package/dist/examples/getToken.d.ts +0 -1
  83. package/dist/examples/getToken.js +0 -16
  84. package/dist/examples/getToken.js.map +0 -1
  85. package/dist/src/ATV.d.ts +0 -17
  86. package/dist/src/ATV.js +0 -16
  87. package/dist/src/ATV.js.map +0 -1
  88. package/dist/src/confirmXML.d.ts +0 -8
  89. package/dist/src/confirmXML.js +0 -44
  90. package/dist/src/confirmXML.js.map +0 -1
  91. package/dist/src/creditNote.d.ts +0 -14
  92. package/dist/src/creditNote.js +0 -77
  93. package/dist/src/creditNote.js.map +0 -1
  94. package/dist/src/data/codigoMoneda.d.ts +0 -1
  95. package/dist/src/data/codigoMoneda.js +0 -184
  96. package/dist/src/data/codigoMoneda.js.map +0 -1
  97. package/dist/src/data/exoneracion.d.ts +0 -1
  98. package/dist/src/data/exoneracion.js +0 -15
  99. package/dist/src/data/exoneracion.js.map +0 -1
  100. package/dist/src/data/impuestos.d.ts +0 -25
  101. package/dist/src/data/impuestos.js +0 -51
  102. package/dist/src/data/impuestos.js.map +0 -1
  103. package/dist/src/data/tipoCedula.d.ts +0 -7
  104. package/dist/src/data/tipoCedula.js +0 -17
  105. package/dist/src/data/tipoCedula.js.map +0 -1
  106. package/dist/src/data/tipoDocumento.d.ts +0 -26
  107. package/dist/src/data/tipoDocumento.js +0 -30
  108. package/dist/src/data/tipoDocumento.js.map +0 -1
  109. package/dist/src/data/unidadesMedida.d.ts +0 -5
  110. package/dist/src/data/unidadesMedida.js +0 -141
  111. package/dist/src/data/unidadesMedida.js.map +0 -1
  112. package/dist/src/debitNote.d.ts +0 -14
  113. package/dist/src/debitNote.js +0 -77
  114. package/dist/src/debitNote.js.map +0 -1
  115. package/dist/src/electronicBill.d.ts +0 -3
  116. package/dist/src/electronicBill.js +0 -61
  117. package/dist/src/electronicBill.js.map +0 -1
  118. package/dist/src/helpers/comprobantes.d.ts +0 -7
  119. package/dist/src/helpers/comprobantes.js +0 -92
  120. package/dist/src/helpers/comprobantes.js.map +0 -1
  121. package/dist/src/index.d.ts +0 -8
  122. package/dist/src/index.js.map +0 -1
  123. package/dist/src/lib/genClave/index.d.ts +0 -9
  124. package/dist/src/lib/genClave/index.js +0 -119
  125. package/dist/src/lib/genClave/index.js.map +0 -1
  126. package/dist/src/lib/genJSON/confirmXML.d.ts +0 -7
  127. package/dist/src/lib/genJSON/confirmXML.js +0 -46
  128. package/dist/src/lib/genJSON/confirmXML.js.map +0 -1
  129. package/dist/src/lib/genJSON/index.d.ts +0 -3
  130. package/dist/src/lib/genJSON/index.js +0 -133
  131. package/dist/src/lib/genJSON/index.js.map +0 -1
  132. package/dist/src/lib/genXML/index.d.ts +0 -7
  133. package/dist/src/lib/genXML/index.js +0 -51
  134. package/dist/src/lib/genXML/index.js.map +0 -1
  135. package/dist/src/lib/genXML/sigXML/genKeysAndCert.d.ts +0 -6
  136. package/dist/src/lib/genXML/sigXML/genKeysAndCert.js +0 -72
  137. package/dist/src/lib/genXML/sigXML/genKeysAndCert.js.map +0 -1
  138. package/dist/src/lib/genXML/sigXML/index.d.ts +0 -1
  139. package/dist/src/lib/genXML/sigXML/index.js +0 -86
  140. package/dist/src/lib/genXML/sigXML/index.js.map +0 -1
  141. package/dist/src/lib/genXML/xmlConfig.d.ts +0 -55
  142. package/dist/src/lib/genXML/xmlConfig.js +0 -36
  143. package/dist/src/lib/genXML/xmlConfig.js.map +0 -1
  144. package/dist/src/services/getToken/GetToken.d.ts +0 -8
  145. package/dist/src/services/getToken/GetToken.js +0 -66
  146. package/dist/src/services/getToken/GetToken.js.map +0 -1
  147. package/dist/src/services/getToken/__tests__/GetToken.test.d.ts +0 -1
  148. package/dist/src/services/getToken/__tests__/GetToken.test.js +0 -86
  149. package/dist/src/services/getToken/__tests__/GetToken.test.js.map +0 -1
  150. package/dist/src/services/getToken/index.d.ts +0 -3
  151. package/dist/src/services/getToken/index.js +0 -22
  152. package/dist/src/services/getToken/index.js.map +0 -1
  153. package/dist/src/services/getToken/types.d.ts +0 -27
  154. package/dist/src/services/getToken/types.js +0 -3
  155. package/dist/src/services/getToken/types.js.map +0 -1
  156. package/dist/src/services/send/index.d.ts +0 -2
  157. package/dist/src/services/send/index.js +0 -40
  158. package/dist/src/services/send/index.js.map +0 -1
  159. package/dist/src/types/xml/notaDeCredito.d.ts +0 -21
  160. package/dist/src/types/xml/notaDeCredito.js +0 -3
  161. package/dist/src/types/xml/notaDeCredito.js.map +0 -1
  162. package/dist/src/types/xml/notaDeDebito.d.ts +0 -21
  163. package/dist/src/types/xml/notaDeDebito.js +0 -3
  164. package/dist/src/types/xml/notaDeDebito.js.map +0 -1
  165. package/src/ATV.ts +0 -28
  166. /package/{atv-structures → doc/atv-structures}/4.3/FacturaElectronicaExportacion_V4.3.xsd.xml +0 -0
  167. /package/{atv-structures → doc/atv-structures}/4.3/FacturaElectronica_V4.3.xsd.xml +0 -0
@@ -0,0 +1,101 @@
1
+ import axios from 'axios'
2
+ import { GetToken } from '../services/getToken/GetToken'
3
+ import { GetTokenDto, GetTokenResponse } from '../services/getToken/types'
4
+ import * as parser from 'fast-xml-parser'
5
+ import qs from 'querystring'
6
+ import { ConfirmationMessageRaw } from '@src/types/facturaInterfaces'
7
+ import { ATVOptions, ConfirmationMessage, Mode, SendConfirmationInput, SendResponse } from './types'
8
+ import { Command, CreateAndSendDocumentResponse, CreateDocumentInput } from './useCases/createDocument/types'
9
+ import { CreateDocumentCommand } from './useCases/createDocument'
10
+
11
+ export class ATV {
12
+ public readonly options: ATVOptions
13
+ constructor(options?: ATVOptions, public readonly mode: Mode = 'prod') {
14
+ this.options = options
15
+ }
16
+
17
+ public getToken(params: GetTokenDto): Promise<GetTokenResponse> {
18
+ const tokenService = new GetToken(this)
19
+ return tokenService.execute(params)
20
+ }
21
+
22
+ public createDocumentCommand(input: CreateDocumentInput): Promise<CreateAndSendDocumentResponse> {
23
+ const createDocument = new CreateDocumentCommand(this)
24
+ return createDocument.execute(input)
25
+ }
26
+
27
+ public async sendDocument(input: Command): Promise<SendResponse> {
28
+ try {
29
+ const response = await axios(input)
30
+ return {
31
+ status: response.status,
32
+ location: response.headers.location,
33
+ errorCause: null
34
+ }
35
+ } catch (error) {
36
+ const response = error.response || {}
37
+ const header = response.headers || {}
38
+ return {
39
+ status: error.response.status || 500,
40
+ errorCause: header['x-error-cause'],
41
+ location: null
42
+ }
43
+ }
44
+ }
45
+
46
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
47
+ public async sendConfirmation(input: SendConfirmationInput) {
48
+ try {
49
+ const response = await axios(input)
50
+ console.log('response', response)
51
+ const xmlResponse = response.data['respuesta-xml']
52
+ if (!xmlResponse) {
53
+ const state = response.data['ind-estado']
54
+ return {
55
+ status: response.status,
56
+ state,
57
+ errorCause: null
58
+ }
59
+ }
60
+ const xmlString = this.decodeBase64(xmlResponse)
61
+
62
+ return {
63
+ status: response.status,
64
+ confirmation: this.parseConfirmationMessage(xmlString),
65
+ xml: xmlString,
66
+ errorCause: null
67
+ }
68
+ } catch (error) {
69
+ const response = error.response || {}
70
+ return {
71
+ status: response.status || 500,
72
+ errorCause: response.statusText
73
+ }
74
+ }
75
+ }
76
+
77
+ private parseConfirmationMessage(xml: string): ConfirmationMessage {
78
+ const parsedXml: ConfirmationMessageRaw = parser.parse(xml, {
79
+ ignoreAttributes: false,
80
+ tagValueProcessor: a => qs.unescape(a.replace(/(\r\n|\n|\r)/gm, '')),
81
+ ignoreNameSpace: false,
82
+ parseNodeValue: false
83
+ })
84
+ const msj = parsedXml.MensajeHacienda
85
+ return {
86
+ clave: msj.Clave,
87
+ message: msj.Mensaje,
88
+ details: msj.DetalleMensaje,
89
+ emitterFullName: msj.NombreEmisor,
90
+ emitterIdentifierId: msj.NumeroCedulaEmisor,
91
+ receiverIdentifierId: msj.NumeroCedulaReceptor,
92
+ taxesTotalAmount: msj.MontoTotalImpuesto,
93
+ totalInvoiceAmount: msj.TotalFactura
94
+ }
95
+ }
96
+
97
+ private decodeBase64(encodedStr: string): string {
98
+ const buff = Buffer.from(encodedStr, 'base64')
99
+ return buff.toString('utf-8')
100
+ }
101
+ }
@@ -0,0 +1,103 @@
1
+ import { Document, FacturaElectronicaContenedor, DetalleServicio, Resumen, Persona } from '@src/types/facturaInterfaces'
2
+ import { Document as DomainDocument } from '../core/Document'
3
+ import { OrderLine } from '../core/OrderLine'
4
+ import { Person } from '../core/Person'
5
+
6
+ type AtvFormat = FacturaElectronicaContenedor
7
+
8
+ const mapOrderLinesToAtvFormat = (orderLines: OrderLine[]): DetalleServicio => {
9
+ const LineaDetalle = orderLines.map<DetalleServicio['LineaDetalle'][0]>((orderLine) => {
10
+ return {
11
+ NumeroLinea: orderLine.lineNumber,
12
+ Codigo: orderLine.code,
13
+ // CodigoComercial
14
+ Cantidad: orderLine.quantity,
15
+ UnidadMedida: orderLine.measureUnit,
16
+ // UnidadMedidaComercial
17
+ Detalle: orderLine.detail,
18
+ PrecioUnitario: orderLine.unitaryPrice,
19
+ MontoTotal: orderLine.totalAmount,
20
+ // Descuento
21
+ SubTotal: orderLine.subTotal,
22
+ // BaseImponible
23
+ Impuesto: {
24
+ Codigo: orderLine.tax.code,
25
+ CodigoTarifa: orderLine.tax.rateCode,
26
+ Tarifa: orderLine.tax.rate,
27
+ Monto: orderLine.tax.amount
28
+ },
29
+ // ImpuestoNeto
30
+ MontoTotalLinea: orderLine.totalOrderLineAmount
31
+ }
32
+ })
33
+ return { LineaDetalle }
34
+ }
35
+
36
+ const mapSummaryInvoice = (summaryInvoice: DomainDocument['summaryInvoice']): Resumen => {
37
+ return {
38
+ CodigoTipoMoneda: {
39
+ CodigoMoneda: summaryInvoice.currency.code,
40
+ TipoCambio: summaryInvoice.currency.exchangeRate
41
+ },
42
+ TotalServGravados: summaryInvoice.totalEncumberedServices,
43
+ TotalServExentos: summaryInvoice.totalExemptServices,
44
+ TotalMercanciasGravadas: summaryInvoice.totalEncumberedMerchandise,
45
+ TotalMercanciasExentas: summaryInvoice.totalExemptMerchandise,
46
+ TotalGravado: summaryInvoice.totalEncumbered,
47
+ TotalExento: summaryInvoice.totalExempt,
48
+ TotalExonerado: summaryInvoice.totalExonerated,
49
+ TotalVenta: summaryInvoice.totalSale,
50
+ TotalDescuentos: summaryInvoice.totalDiscounts,
51
+ TotalVentaNeta: summaryInvoice.totalNetSale,
52
+ TotalImpuesto: summaryInvoice.totalTaxes,
53
+ TotalComprobante: summaryInvoice.totalVoucher
54
+ }
55
+ }
56
+
57
+ const mapPerson = (person: Person): Persona => {
58
+ return {
59
+ Nombre: person.fullName,
60
+ Identificacion: {
61
+ Tipo: person.identifierType,
62
+ Numero: person.identifierId
63
+ },
64
+ NombreComercial: person.commercialName,
65
+ Ubicacion: {
66
+ Provincia: person.location?.province,
67
+ Canton: person.location?.canton.padStart(2, '0'),
68
+ Distrito: person.location?.district.padStart(2, '0'),
69
+ Barrio: person.location?.neighborhood.padStart(2, '0'),
70
+ OtrasSenas: person.location?.details
71
+ },
72
+ Telefono: {
73
+ CodigoPais: person.phone?.countryCode,
74
+ NumTelefono: person.phone?.number
75
+ },
76
+ Fax: {
77
+ CodigoPais: person.fax?.countryCode,
78
+ NumTelefono: person.fax?.number
79
+ },
80
+ CorreoElectronico: person.email
81
+ }
82
+ }
83
+
84
+ export const mapDocumentToAtvFormat = (docName: string, document: DomainDocument): AtvFormat => {
85
+ const key = docName
86
+ const doc: Document = {
87
+ Clave: document.clave,
88
+ CodigoActividad: document.activityCode.padStart(6, '0'),
89
+ NumeroConsecutivo: document.fullConsecutive,
90
+ FechaEmision: document.issueDate.toISOString(),
91
+ Emisor: mapPerson(document.emitter),
92
+ Receptor: mapPerson(document.receiver),
93
+ CondicionVenta: document.conditionSale,
94
+ PlazoCredito: document.deadlineCredit,
95
+ MedioPago: document.paymentMethod,
96
+ DetalleServicio: mapOrderLinesToAtvFormat(document.orderLines),
97
+ ResumenFactura: mapSummaryInvoice(document.summaryInvoice),
98
+ Otros: document.others
99
+ }
100
+ return {
101
+ [key]: doc
102
+ }
103
+ }
@@ -0,0 +1,37 @@
1
+ export type Mode = 'prod' | 'stg' | 'custom';
2
+
3
+ export type ATVOptions = {
4
+ defaultOverwrites?: {
5
+ tokenServiceUrl: string;
6
+ };
7
+ }
8
+
9
+ export type TokenServiceProps = {
10
+ serviceUrl: string;
11
+ clientId: string;
12
+ }
13
+
14
+ export type SendResponse = {
15
+ status: number;
16
+ location: string;
17
+ errorCause?: string | null;
18
+ }
19
+
20
+ export type SendConfirmationInput = {
21
+ url: string;
22
+ headers: {
23
+ Authorization: string;
24
+ 'Content-Type': string;
25
+ };
26
+ }
27
+
28
+ export type ConfirmationMessage = {
29
+ clave: string;
30
+ message: string;
31
+ details: string;
32
+ emitterFullName: string;
33
+ emitterIdentifierId: string;
34
+ receiverIdentifierId: string;
35
+ taxesTotalAmount: string;
36
+ totalInvoiceAmount: string;
37
+ }
@@ -0,0 +1,137 @@
1
+ import { Person } from '@src/ATV/core/Person'
2
+ import { OrderLine } from '@src/ATV/core/OrderLine'
3
+ import { FullConsecutive } from '@src/ATV/core/FullConsecutive'
4
+ import { Document } from '@src/ATV/core/Document'
5
+ import { Clave } from '@src/ATV/core/Clave'
6
+ import { mapDocumentToAtvFormat as mapBillToAtvFormat } from '@src/ATV/mappers/billDocToAtv'
7
+ import { genXML } from '@src/lib/genXML'
8
+ import { CreateAndSendDocumentResponse, CreateDocumentInput, Command } from './types'
9
+ import { ATV } from '@src/ATV'
10
+ import { DocumentType } from '@src/ATV/core/DocumentType'
11
+ export type { CreateDocumentInput as CreateBillInput } from './types'
12
+
13
+ const options: { [key: string]: { serviceUrl: string}} = {
14
+ prod: {
15
+ serviceUrl: 'https://api.comprobanteselectronicos.go.cr/v1/recepcion'
16
+ },
17
+ stg: {
18
+ serviceUrl: 'https://api-sandbox.comprobanteselectronicos.go.cr/recepcion/v1/recepcion'
19
+ }
20
+ }
21
+
22
+ export class CreateDocumentCommand {
23
+ private readonly serviceUrl: string
24
+
25
+ constructor(scope: ATV) {
26
+ this.serviceUrl = options[scope.mode].serviceUrl
27
+ }
28
+
29
+ public async execute(dto: CreateDocumentInput): Promise<CreateAndSendDocumentResponse> {
30
+ const documentName = dto.document.documentName || 'FacturaElectronica'
31
+ const document = this.createDocument(dto.document)
32
+ const atvDocument = mapBillToAtvFormat(documentName, document)
33
+ const xml = await genXML(documentName, atvDocument, dto.signatureOptions)
34
+ const command = await this.createDocumentCommand(document, xml, dto.token)
35
+ return {
36
+ command,
37
+ extraData: {
38
+ xml
39
+ }
40
+ }
41
+ }
42
+
43
+ private async createDocumentCommand(document: Document, xml: string, token: string): Promise<Command> {
44
+ return {
45
+ url: this.serviceUrl,
46
+ method: 'post',
47
+ data: {
48
+ clave: document.clave,
49
+ fecha: document.issueDate.toISOString(),
50
+ emisor: {
51
+ tipoIdentificacion: document.emitter.identifierType,
52
+ numeroIdentificacion: document.emitter.identifierId
53
+ },
54
+ receptor: {
55
+ tipoIdentificacion: document.receiver.identifierType,
56
+ numeroIdentificacion: document.receiver.identifierId
57
+ },
58
+ comprobanteXml: this.encodeXML(xml)
59
+ },
60
+ headers: {
61
+ Authorization: 'bearer ' + token,
62
+ 'Content-Type': 'application/json'
63
+ }
64
+ }
65
+ }
66
+
67
+ private createDocument(document: CreateDocumentInput['document']): Document {
68
+ const documentType = DocumentType.create(document.documentName)
69
+ const emitter = this.createEmitter(document.emitter)
70
+ const receiver = this.createReceiver(document.receiver)
71
+ const clave = this.createClave(document, documentType)
72
+ const fullConsective = this.createFullConsecutive(document, documentType)
73
+ const orderLines = this.createOrderLines(document)
74
+ return Document.create({
75
+ clave,
76
+ fullConsecutive: fullConsective,
77
+ orderLines,
78
+ activityCode: document.activityCode,
79
+ issueDate: new Date(),
80
+ emitter,
81
+ receiver,
82
+ conditionSale: '01',
83
+ paymentMethod: '01'
84
+ })
85
+ }
86
+
87
+ private createEmitter(emitterInput: CreateDocumentInput['document']['emitter']): Person {
88
+ return Person.create(emitterInput)
89
+ }
90
+
91
+ private createReceiver(receiverInput: CreateDocumentInput['document']['receiver']): Person {
92
+ return Person.create(receiverInput)
93
+ }
94
+
95
+ private createOrderLines(dto: CreateDocumentInput['document']): OrderLine[] {
96
+ return dto.orderLines.map((orderLine, index) => {
97
+ return OrderLine.create({
98
+ detail: orderLine.detail,
99
+ unitaryPrice: orderLine.unitaryPrice,
100
+ lineNumber: orderLine.lineNumber || (index + 1).toString(),
101
+ code: orderLine.code,
102
+ quantity: orderLine.quantity,
103
+ measureUnit: orderLine.measureUnit,
104
+ totalAmount: orderLine.totalAmount,
105
+ tax: orderLine.tax
106
+ })
107
+ })
108
+ }
109
+
110
+ private createFullConsecutive(dto: CreateDocumentInput['document'], docType: DocumentType): FullConsecutive {
111
+ return FullConsecutive.create({
112
+ consecutiveIdentifier: dto.consecutiveIdentifier,
113
+ branch: dto.branch,
114
+ terminal: dto.terminal,
115
+ documentType: docType.value
116
+ })
117
+ }
118
+
119
+ private createClave(dto: CreateDocumentInput['document'], docType: DocumentType): Clave {
120
+ return Clave.create({
121
+ branch: dto.branch,
122
+ ceSituation: dto.ceSituation,
123
+ consecutiveIdentifier: dto.consecutiveIdentifier,
124
+ countryCode: dto.countryCode,
125
+ docKeyType: docType.value,
126
+ emitterIdentifier: dto.emitter.identifier.id,
127
+ identifierType: dto.emitter.identifier.type, // TODO add default
128
+ securityCode: dto.securityCode,
129
+ terminal: dto.terminal
130
+ })
131
+ }
132
+
133
+ private encodeXML(xmlStr: string): string {
134
+ const buffer = Buffer.from(xmlStr)
135
+ return buffer.toString('base64')
136
+ }
137
+ }
@@ -0,0 +1,79 @@
1
+ import { PersonProps } from '@src/ATV/core/Person'
2
+ import { DocumentNames } from '@src/ATV/core/documentNames.types'
3
+ import { Method } from 'axios'
4
+
5
+ type PersonInput = PersonProps;
6
+
7
+ type TaxInput = {
8
+ code: string;
9
+ rateCode: string;
10
+ rate: number;
11
+ amount?: number;
12
+ }
13
+
14
+ type OrderInput = {
15
+ detail: string;
16
+ unitaryPrice: number;
17
+ lineNumber?: string;
18
+ code?: string;
19
+ quantity?: number;
20
+ measureUnit?: string;
21
+ totalAmount?: number;
22
+ subTotal?: number;
23
+ tax?: TaxInput;
24
+ totalOrderLineAmount?: number;
25
+ }
26
+
27
+ export type DocumentTypes = 'FE'
28
+
29
+ type DocumentInput = {
30
+ emitter: PersonInput;
31
+ receiver: PersonInput;
32
+ branch: string; // sucursal
33
+ terminal: string; // terminal
34
+ // documentType: DocumentTypes; // @deprecated
35
+ documentName: DocumentNames;
36
+ countryCode: string; // codigoPais
37
+ securityCode: string; // codigoSeguridad
38
+ activityCode: string;
39
+ consecutiveIdentifier: string; // consecutivo
40
+ ceSituation: string; // situacionCE
41
+ orderLines: OrderInput[];
42
+ }
43
+
44
+ export type CreateDocumentInput = {
45
+ document: DocumentInput;
46
+ token: string;
47
+ signatureOptions: {
48
+ buffer: string;
49
+ password: string;
50
+ };
51
+ }
52
+
53
+ export type Command = {
54
+ url: string;
55
+ method: Method;
56
+ data: {
57
+ clave: string;
58
+ fecha: string;
59
+ emisor: {
60
+ tipoIdentificacion: string;
61
+ numeroIdentificacion: string;
62
+ };
63
+ receptor: {
64
+ tipoIdentificacion: string;
65
+ numeroIdentificacion: string;
66
+ };
67
+ comprobanteXml: string;
68
+ };
69
+ headers: {
70
+ Authorization: string;
71
+ 'Content-Type': string;
72
+ };
73
+ }
74
+ export type CreateAndSendDocumentResponse = {
75
+ command: Command;
76
+ extraData: {
77
+ xml: string;
78
+ };
79
+ }
@@ -39,7 +39,7 @@ export function getBillResum(frontEndRequest: ClientPayload): Resumen {
39
39
  },
40
40
  TotalServGravados: 0,
41
41
  TotalServExentos: 0,
42
- TotalServExonerado: 0,
42
+ // TotalServExonerado: 0,
43
43
  TotalMercanciasGravadas: frontEndRequest.total,
44
44
  TotalMercanciasExentas: 0,
45
45
  TotalGravado: frontEndRequest.total,
@@ -41,7 +41,7 @@ export function getFinalMessage(fullInvoice: any, consecutivoReceptor: string, x
41
41
  tipoIdentificacion: fullInvoice.Emisor.Identificacion.Tipo,
42
42
  numeroIdentificacion: fullInvoice.Emisor.Identificacion.Numero
43
43
  },
44
- consecutivoReceptor: consecutivoReceptor,
44
+ consecutivoReceptor,
45
45
  comprobanteXml: xmlBase64
46
46
  }
47
47
  }
@@ -30,7 +30,7 @@ function getBillResum(lines: LineaDetalle[]): Resumen {
30
30
  },
31
31
  TotalServGravados: 0,
32
32
  TotalServExentos: 0,
33
- TotalServExonerado: 0,
33
+ // TotalServExonerado: 0,
34
34
  TotalMercanciasGravadas: sum.total,
35
35
  TotalMercanciasExentas: 0,
36
36
  TotalGravado: sum.total,
@@ -70,7 +70,7 @@ function setTaxObj(subtotal: number, taxObj: Impuesto): Impuesto {
70
70
  }
71
71
  }
72
72
 
73
- function setLinesDefaults(lines: LineaDetalle[]): LineaDetalle[] {
73
+ export function setLinesDefaults(lines: LineaDetalle[]): LineaDetalle[] {
74
74
  return lines.map((line, index) => {
75
75
  const quantity = line.Cantidad || 1
76
76
  const total = line.PrecioUnitario * quantity
@@ -57,8 +57,8 @@ const MR_XML_ATTRS = { // Mensaje Receptor
57
57
  export const xmlExtructures = {
58
58
  FacturaElectronica: FE_XML_ATTRS,
59
59
  FacturaElectronicaExportacion: FEE_XML_ATTRS,
60
- NC: NC_XML_ATTRS,
61
- ND: ND_XML_ATTRS,
60
+ NotaCreditoElectronica: NC_XML_ATTRS,
61
+ NotaDebitoElectronica: ND_XML_ATTRS,
62
62
  CCE: MR_XML_ATTRS,
63
63
  CPCE: MR_XML_ATTRS,
64
64
  RCE: MR_XML_ATTRS
@@ -7,7 +7,7 @@ const MAIN_DOMAIN = 'https://idp.comprobanteselectronicos.go.cr'
7
7
  const options: { [key: string]: GetTokenInternalProps} = {
8
8
  prod: {
9
9
  serviceUrl: `${MAIN_DOMAIN}/auth/realms/rut/protocol/openid-connect/token`,
10
- clientId: 'api'
10
+ clientId: 'api-prod'
11
11
  },
12
12
  stg: {
13
13
  serviceUrl: `${MAIN_DOMAIN}/auth/realms/rut-stag/protocol/openid-connect/token`,
@@ -16,7 +16,7 @@ const options: { [key: string]: GetTokenInternalProps} = {
16
16
  }
17
17
 
18
18
  export class GetToken {
19
- private readonly props: GetTokenInternalProps;
19
+ private readonly props: GetTokenInternalProps
20
20
  constructor(scope: ATV) {
21
21
  this.props = this.initProps(scope.mode)
22
22
  }
@@ -20,7 +20,7 @@ export function send(token: string, postOptions: any): Record<string, any> {
20
20
 
21
21
  export function sendToCustomURL(token: string, url: string): Record<string, any> {
22
22
  return axios({
23
- url: url,
23
+ url,
24
24
  method: 'get',
25
25
  headers: {
26
26
  Authorization: 'bearer ' + token,
@@ -35,7 +35,7 @@ export interface Resumen {
35
35
  };
36
36
  TotalServGravados: number;
37
37
  TotalServExentos: number;
38
- TotalServExonerado: number;
38
+ // TotalServExonerado: number;
39
39
  TotalMercanciasGravadas?: number;
40
40
  TotalMercanciasExentas?: number;
41
41
  TotalGravado?: number;
@@ -78,11 +78,11 @@ export interface Message {
78
78
  DetalleMensaje: string;
79
79
  }
80
80
 
81
- export interface FacturaElectronica {
81
+ export interface Document {
82
82
  Clave: string;
83
83
  CodigoActividad: string;
84
84
  NumeroConsecutivo: string;
85
- FechaEmision?: Date;
85
+ FechaEmision?: string;
86
86
  Emisor: Persona;
87
87
  Receptor: Persona;
88
88
  CondicionVenta?: string;
@@ -95,23 +95,30 @@ export interface FacturaElectronica {
95
95
  };
96
96
  }
97
97
 
98
- export interface FacturaElectronicaExportacion {
99
- Clave: string;
100
- CodigoActividad: string;
101
- NumeroConsecutivo: string;
102
- FechaEmision?: Date;
103
- Emisor: Persona;
104
- Receptor: Persona;
105
- CondicionVenta?: string;
106
- PlazoCredito?: string;
107
- MedioPago?: string;
108
- DetalleServicio?: DetalleServicio;
109
- ResumenFactura: Resumen;
110
- Otros?: {
111
- OtroTexto: string;
112
- };
98
+ export interface FacturaElectronicaContenedor {
99
+ [key: 'FacturaElectronica' | 'FacturaElectronicaExportacion']: Document | FacturaElectronicaExportacion;
113
100
  }
114
101
 
115
- export interface FacturaElectronicaContenedor {
116
- [key: 'FacturaElectronica' | 'FacturaElectronicaExportacion']: FacturaElectronica | FacturaElectronicaExportacion;
102
+ export type ConfirmationMessageRaw = {
103
+ MensajeHacienda: {
104
+ Clave: string;
105
+ NombreEmisor: string;
106
+ TipoIdentificacionEmisor: string;
107
+ NumeroCedulaEmisor: string;
108
+ TipoIdentificacionReceptor: string;
109
+ NumeroCedulaReceptor: string;
110
+ Mensaje: string;
111
+ DetalleMensaje: string;
112
+ MontoTotalImpuesto: string;
113
+ TotalFactura: string;
114
+ '@_xmlns': string;
115
+ 'ds:Signature': {
116
+ '@_xmlns:ds': string;
117
+ '@_Id': string;
118
+ 'ds:SignedInfo': unknown;
119
+ 'ds:SignatureValue': unknown;
120
+ 'ds:KeyInfo': unknown;
121
+ 'ds:Object': unknown;
122
+ };
123
+ };
117
124
  }
@@ -73,7 +73,7 @@ function processElementsFromComplexType(array: Array<any>): any {
73
73
  if (propKey) {
74
74
  newObj[propKey] = {
75
75
  description: element?.annotation?.documentation,
76
- simpleType: simpleType
76
+ simpleType
77
77
  }
78
78
  }
79
79
  }
@@ -84,7 +84,7 @@ function processComplexType(object: any): any {
84
84
  const elements = processElementsFromComplexType(object?.sequence?.element)
85
85
  const newObject = {}
86
86
  newObject[object?.attributes?.name] = {
87
- elements: elements
87
+ elements
88
88
  }
89
89
  return newObject
90
90
  }
@@ -1,28 +0,0 @@
1
- import { tokenStub } from '@test/stubs/token.stub'
2
- import requestStub from '@test/stubs/frontendRequest.stub'
3
- import eletronicBill from '@src/electronicBill'
4
- import { send } from '@src/services/send/index'
5
- import fs from 'fs'
6
- import path from 'path'
7
- const SOURCE_P12_URI = path.join(__dirname, '../stubs/dummyKeys/client-identity.p12')
8
-
9
- jest.mock('@src/services/send/index')
10
-
11
- const mockedSend = send as jest.MockedFunction<typeof send>
12
- const pem = fs.readFileSync(SOURCE_P12_URI, 'binary')
13
-
14
- describe('Get Token', () => {
15
- it('should return a valid token', async () => {
16
- mockedSend.mockImplementation(() => {
17
- return Promise.resolve('')
18
- })
19
- const bill = await eletronicBill(tokenStub, requestStub, {
20
- buffer: pem,
21
- password: '1234'
22
- })
23
-
24
- console.log('bill', bill)
25
-
26
- expect(bill).toEqual('')
27
- })
28
- })
@@ -1,3 +0,0 @@
1
- import { ClientPayload } from '@src/types/globalInterfaces';
2
- declare const requestStub: ClientPayload;
3
- export default requestStub;