@facturacr/atv-sdk 2.0.0-alpha → 2.0.1-alpha

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 (106) hide show
  1. package/.eslintignore +3 -0
  2. package/.eslintrc.js +23 -23
  3. package/.github/dependabot.yml +11 -0
  4. package/.github/workflows/ci.yml +14 -12
  5. package/README.md +9 -2
  6. package/__tests__/stubs/commonExpectedXml.xml +14 -16
  7. package/__tests__/stubs/createDocument.data.ts +18 -1
  8. package/__tests__/stubs/frontendRequest.stub.ts +0 -1
  9. package/__tests__/stubs/token.stub.ts +9 -9
  10. package/__tests__/tests/ATV/__snapshots__/create-document.test.ts.snap +1 -1
  11. package/__tests__/tests/ATV/create-document.test.ts +8 -8
  12. package/__tests__/tests/ATV/create-receptor-message.test.ts +41 -36
  13. package/dist/src/ATV/core/CreateDocFactory.d.ts +11 -3
  14. package/dist/src/ATV/core/CreateDocFactory.js +3 -3
  15. package/dist/src/ATV/core/CreateDocFactory.js.map +1 -1
  16. package/dist/src/ATV/core/Document.d.ts +2 -2
  17. package/dist/src/ATV/core/Document.js +7 -4
  18. package/dist/src/ATV/core/Document.js.map +1 -1
  19. package/dist/src/ATV/core/DocumentType.d.ts +2 -3
  20. package/dist/src/ATV/core/DocumentType.js +1 -0
  21. package/dist/src/ATV/core/DocumentType.js.map +1 -1
  22. package/dist/src/ATV/core/FullConsecutive.d.ts +2 -1
  23. package/dist/src/ATV/core/FullConsecutive.js.map +1 -1
  24. package/dist/src/ATV/core/OrderLine.js +8 -1
  25. package/dist/src/ATV/core/OrderLine.js.map +1 -1
  26. package/dist/src/ATV/core/Person.d.ts +2 -2
  27. package/dist/src/ATV/core/ReceptorConsecutive.js.map +1 -1
  28. package/dist/src/ATV/core/ReferenceInformation.js.map +1 -1
  29. package/dist/src/ATV/core/types.d.ts +3 -2
  30. package/dist/src/ATV/core/types.js.map +1 -1
  31. package/dist/src/ATV/index.d.ts +2 -2
  32. package/dist/src/ATV/index.js +2 -2
  33. package/dist/src/ATV/mappers/billDocToAtv.js +32 -26
  34. package/dist/src/ATV/mappers/billDocToAtv.js.map +1 -1
  35. package/dist/src/ATV/types.d.ts +1 -1
  36. package/dist/src/ATV/useCases/createDocument/index.js +5 -9
  37. package/dist/src/ATV/useCases/createDocument/index.js.map +1 -1
  38. package/dist/src/ATV/useCases/createDocument/types.d.ts +4 -3
  39. package/dist/src/ATV/useCases/createReceptorMessage/index.d.ts +6 -5
  40. package/dist/src/ATV/useCases/createReceptorMessage/index.js +3 -3
  41. package/dist/src/ATV/useCases/createReceptorMessage/index.js.map +1 -1
  42. package/dist/src/helpers/comprobantes.js +10 -1
  43. package/dist/src/helpers/comprobantes.js.map +1 -1
  44. package/dist/src/lib/genClave/index.d.ts +8 -1
  45. package/dist/src/lib/genClave/index.js +5 -0
  46. package/dist/src/lib/genClave/index.js.map +1 -1
  47. package/dist/src/lib/genXML/index.js +6 -4
  48. package/dist/src/lib/genXML/index.js.map +1 -1
  49. package/dist/src/lib/genXML/sigXML/index.js +7 -4
  50. package/dist/src/lib/genXML/sigXML/index.js.map +1 -1
  51. package/dist/src/services/getToken/GetToken.js +0 -3
  52. package/dist/src/services/getToken/GetToken.js.map +1 -1
  53. package/dist/src/services/getToken/__tests__/GetToken.test.js +0 -1
  54. package/dist/src/services/getToken/__tests__/GetToken.test.js.map +1 -1
  55. package/dist/src/types/facturaInterfaces.d.ts +3 -3
  56. package/dist/src/xmlSchemaHeaderMap.d.ts +70 -0
  57. package/dist/src/xmlSchemaHeaderMap.js +30 -0
  58. package/dist/src/xmlSchemaHeaderMap.js.map +1 -0
  59. package/doc/atv-structures/4.3/FacturaElectronica_V4.3.xsd.xml +1633 -478
  60. package/doc/atv-structures/4.4/TiqueteElectronico_V4.4.xsd.xml +2817 -0
  61. package/doc/json-schemas/4.4/fe.json +544 -0
  62. package/doc/json-schemas/4.4/te.json +420 -0
  63. package/doc/testing.md +27 -0
  64. package/examples/README.md +10 -35
  65. package/examples/atvAccept.ts +18 -9
  66. package/examples/consultXML.ts +1 -0
  67. package/examples/{createAndSend.ts → createAndSendFE.ts} +11 -8
  68. package/examples/createAndSendTE.ts +73 -0
  69. package/examples/createCreditNote.ts +10 -6
  70. package/examples/createDebitNote.ts +2 -0
  71. package/examples/getToken.ts +2 -0
  72. package/package.json +3 -2
  73. package/src/ATV/core/CreateDocFactory.ts +32 -23
  74. package/src/ATV/core/Document.ts +7 -7
  75. package/src/ATV/core/DocumentType.ts +10 -3
  76. package/src/ATV/core/FullConsecutive.ts +2 -1
  77. package/src/ATV/core/OrderLine.ts +7 -1
  78. package/src/ATV/core/Person.ts +2 -2
  79. package/src/ATV/core/ReceptorConsecutive.ts +16 -16
  80. package/src/ATV/core/ReferenceInformation.ts +6 -6
  81. package/src/ATV/core/types.ts +7 -6
  82. package/src/ATV/index.ts +3 -3
  83. package/src/ATV/mappers/billDocToAtv.ts +35 -15
  84. package/src/ATV/types.ts +1 -1
  85. package/src/ATV/useCases/createDocument/index.ts +8 -8
  86. package/src/ATV/useCases/createDocument/types.ts +5 -6
  87. package/src/ATV/useCases/createReceptorMessage/index.ts +94 -93
  88. package/src/helpers/comprobantes.ts +10 -1
  89. package/src/lib/genClave/index.ts +10 -3
  90. package/src/lib/genXML/index.ts +3 -1
  91. package/src/lib/genXML/sigXML/index.ts +6 -3
  92. package/src/services/getToken/GetToken.ts +0 -3
  93. package/src/services/getToken/__tests__/GetToken.test.ts +0 -1
  94. package/src/types/facturaInterfaces.ts +3 -4
  95. package/src/xmlSchemaHeaderMap.ts +37 -0
  96. package/tools/readXML.ts +2 -0
  97. package/tools/xsdToJsonSchema.ts +1 -0
  98. package/tsconfig.json +1 -0
  99. package/dist/src/ATV/core/documentNames.types.d.ts +0 -1
  100. package/dist/src/ATV/core/documentNames.types.js +0 -3
  101. package/dist/src/ATV/core/documentNames.types.js.map +0 -1
  102. package/dist/src/lib/genXML/xmlConfig.d.ts +0 -55
  103. package/dist/src/lib/genXML/xmlConfig.js +0 -42
  104. package/dist/src/lib/genXML/xmlConfig.js.map +0 -1
  105. package/src/ATV/core/documentNames.types.ts +0 -6
  106. package/src/lib/genXML/xmlConfig.ts +0 -60
@@ -0,0 +1,73 @@
1
+ import fs from 'fs'
2
+ import { TEInputExample } from '@test/stubs/createDocument.data'
3
+ import { ATV } from '../dist/src'
4
+ import { PersonProps } from 'dist/src/ATV/core/Person'
5
+
6
+ const USERNAME_TEST = process.env.USERNAME_TEST
7
+ const PASSWORD_TEST = process.env.PASSWORD_TEST
8
+
9
+ const SOURCE_P12_URI = process.env.SOURCE_P12_URI
10
+ const SOURCE_P12_PASSPORT = process.env.SOURCE_P12_PASSPORT
11
+
12
+ if (!SOURCE_P12_PASSPORT || !SOURCE_P12_URI) {
13
+ throw new Error('No environment. For running examples set .env before.')
14
+ }
15
+
16
+ const pem = fs.readFileSync(SOURCE_P12_URI, 'binary')
17
+
18
+ const paramConsecutive = process.argv[2]
19
+ console.log('paramConsecutive', paramConsecutive)
20
+
21
+ // TODO: dynamic param --identifier 1 args[x]
22
+ // @ts-expect-error migration - for example purposes
23
+ TEInputExample.consecutiveIdentifier = paramConsecutive || process.env.TEST_CONSECUTIVE
24
+ TEInputExample.emitter.identifier.id = process.env.EMITTER_IDENTIFIER_ID as string
25
+ TEInputExample.emitter.identifier.type = process.env.EMITTER_IDENTIFIER_TYPE as PersonProps['identifier']['type']
26
+
27
+ console.log('requestStub consecutivo', TEInputExample.consecutiveIdentifier)
28
+
29
+ function getConfimation(atv: ATV, token: string, location: string, ms: number): Promise<any> {
30
+ return new Promise((resolve, reject): any => {
31
+ setTimeout(() => {
32
+ console.log('location', location)
33
+ atv.sendConfirmation({
34
+ url: location,
35
+ headers: {
36
+ 'Content-Type': 'application/json',
37
+ Authorization: 'bearer ' + token
38
+ }
39
+ }).then(data => resolve(data))
40
+ .catch(err => reject(err))
41
+ }, ms)
42
+ })
43
+ }
44
+
45
+ async function main(): Promise<void> {
46
+ const atv = new ATV({}, 'stg')
47
+ const tokenData = await atv.getToken({
48
+ // @ts-expect-error migration - for example purposes
49
+ username: USERNAME_TEST,
50
+ // @ts-expect-error migration - for example purposes
51
+ password: PASSWORD_TEST
52
+ })
53
+ const { command, extraData } = await atv.createDocumentCommand({
54
+ document: TEInputExample,
55
+ token: tokenData.accessToken,
56
+ signatureOptions: {
57
+ buffer: pem,
58
+ // @ts-expect-error migration - for example purposes
59
+ password: SOURCE_P12_PASSPORT
60
+ }
61
+ })
62
+ console.log('extraData', extraData)
63
+ const response = await atv.sendDocument(command)
64
+ if (response.errorCause) {
65
+ console.log('error response', response)
66
+ return
67
+ }
68
+ // @ts-expect-error pending-to-fix migration
69
+ const confirmationResponse = await getConfimation(atv, tokenData.accessToken, response.location, 2000)
70
+ console.log({ MensajeHacienda: confirmationResponse.confirmation })
71
+ }
72
+
73
+ main()
@@ -1,8 +1,7 @@
1
1
  import fs from 'fs'
2
- import { createDocumentInputExample, creditNoteReferenceInfoExample } from '@test/stubs/createDocument.data'
2
+ import { FEInputExample, creditNoteReferenceInfoExample } from '@test/stubs/createDocument.data'
3
3
  import { ATV } from '../dist/src'
4
4
 
5
-
6
5
  const IS_STG = process.env.IS_STG
7
6
  const USERNAME_TEST = process.env.USERNAME_TEST
8
7
  const PASSWORD_TEST = process.env.PASSWORD_TEST
@@ -17,10 +16,10 @@ if (!SOURCE_P12_PASSPORT || !SOURCE_P12_URI) {
17
16
 
18
17
  const pem = fs.readFileSync(SOURCE_P12_URI, 'binary')
19
18
 
20
- console.log('requestStub consecutivo', createDocumentInputExample.consecutiveIdentifier)
19
+ console.log('requestStub consecutivo', FEInputExample.consecutiveIdentifier)
21
20
 
22
21
  // TODO: dynamic param --identifier 1 args[x]
23
- createDocumentInputExample.consecutiveIdentifier = '5'
22
+ FEInputExample.consecutiveIdentifier = '5'
24
23
 
25
24
  function getConfimation(atv: ATV, token: string, location: string, ms: number): Promise<any> {
26
25
  return new Promise((resolve, reject): any => {
@@ -41,18 +40,22 @@ function getConfimation(atv: ATV, token: string, location: string, ms: number):
41
40
  async function main(): Promise<void> {
42
41
  const atv = new ATV({}, 'stg')
43
42
  const tokenData = await atv.getToken({
43
+ // @ts-expect-error migration - for example purposes
44
44
  username: USERNAME_TEST,
45
+ // @ts-expect-error migration - for example purposes
45
46
  password: PASSWORD_TEST
46
47
  })
47
48
  const { command, extraData } = await atv.createDocumentCommand({
48
49
  document: {
49
- ...createDocumentInputExample,
50
+ ...FEInputExample,
50
51
  documentName: 'NotaCreditoElectronica',
51
- referenceInfo: creditNoteReferenceInfoExample
52
+ referenceInfo: creditNoteReferenceInfoExample,
53
+ receiver: FEInputExample.receiver // Ensure receiver is always present
52
54
  },
53
55
  token: tokenData.accessToken,
54
56
  signatureOptions: {
55
57
  buffer: pem,
58
+ // @ts-expect-error migration - for example purposes
56
59
  password: SOURCE_P12_PASSPORT
57
60
  }
58
61
  })
@@ -62,6 +65,7 @@ async function main(): Promise<void> {
62
65
  console.log('error response', response)
63
66
  return
64
67
  }
68
+ // @ts-expect-error pending-to-fix migration
65
69
  const confirmationResponse = await getConfimation(atv, tokenData.accessToken, response.location, 2000)
66
70
  console.log({ MensajeHacienda: confirmationResponse.confirmation })
67
71
  }
@@ -9,6 +9,7 @@ const USERNAME_TEST = process.env.USERNAME_TEST
9
9
  const PASSWORD_TEST = process.env.PASSWORD_TEST
10
10
  const SOURCE_P12_URI = process.env.SOURCE_P12_URI
11
11
  const SOURCE_P12_PASSPORT = process.env.SOURCE_P12_PASSPORT
12
+ // @ts-expect-error migration - for example purposes
12
13
  const pem = fs.readFileSync(SOURCE_P12_URI, 'binary')
13
14
 
14
15
  async function main(): Promise<void> {
@@ -28,6 +29,7 @@ async function main(): Promise<void> {
28
29
  const data = await debitNote({
29
30
  token,
30
31
  frontEndRequest,
32
+ // @ts-expect-error migration - for example purposes
31
33
  xmlOpt
32
34
  })
33
35
  console.log(typeof data)
@@ -8,7 +8,9 @@ console.log('password', PASSWORD_TEST)
8
8
  const mode = IS_STG ? 'stg' : undefined
9
9
  const atv = new ATV({}, mode)
10
10
  const tokenData = atv.getToken({
11
+ // @ts-expect-error migration - for example purposes
11
12
  username: USERNAME_TEST,
13
+ // @ts-expect-error migration - for example purposes
12
14
  password: PASSWORD_TEST
13
15
  })
14
16
  tokenData.then((resp) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@facturacr/atv-sdk",
3
- "version": "2.0.0-alpha",
3
+ "version": "2.0.1-alpha",
4
4
  "description": "Librería (SDK) de Javascript/NodeJS para acceder al API de Administración Tributaria Virtual (ATV) del Ministerio de Hacienda.",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -12,6 +12,7 @@
12
12
  "scripts": {
13
13
  "test": "npx jest --no-coverage",
14
14
  "test:cov": "npx jest",
15
+ "type:check": "tsc --noEmit",
15
16
  "dev": "dotenv -- nodemon -e ts,graphql -x 'yarn lint & ts-node -r tsconfig-paths/register src/index.ts'",
16
17
  "build": "rm -r dist; tspc -p tsconfig-prod.json",
17
18
  "lint": "eslint --ext .ts, --ignore-path .gitignore .",
@@ -56,7 +57,7 @@
56
57
  },
57
58
  "dependencies": {
58
59
  "@peculiar/webcrypto": "^1.1.6",
59
- "axios": "^0.28.0",
60
+ "axios": "^0.30.0",
60
61
  "fast-xml-parser": "^3.19.0",
61
62
  "node-forge": "^1.3.0",
62
63
  "xadesjs": "^2.1.2",
@@ -1,10 +1,9 @@
1
1
  import { Person, PersonProps } from '@src/ATV/core/Person'
2
- import { DocumentNames } from '@src/ATV/core/documentNames.types'
3
2
  import { OrderLine } from '@src/ATV/core/OrderLine'
4
3
  import { FullConsecutive } from '@src/ATV/core/FullConsecutive'
5
4
  import { Document } from '@src/ATV/core/Document'
6
5
  import { Clave } from '@src/ATV/core/Clave'
7
- import { DocumentType } from '@src/ATV/core/DocumentType'
6
+ import { DocumentNames, DocumentType } from '@src/ATV/core/DocumentType'
8
7
  import { ReferenceInformation, ReferenceInformationProps } from './ReferenceInformation'
9
8
  import { ReceptorMessageProps } from './types'
10
9
 
@@ -32,24 +31,34 @@ type OrderInput = {
32
31
  totalOrderLineAmount?: number;
33
32
  }
34
33
 
35
- type DocumentInput = {
36
- emitter: PersonInput;
37
- receiver: PersonInput;
38
- branch: string; // sucursal
39
- terminal: string; // terminal
40
- // documentType: DocumentTypes; // @deprecated
41
- documentName: DocumentNames;
42
- providerId: string;
43
- countryCode: string; // codigoPais
44
- securityCode: string; // codigoSeguridad
45
- activityCode: string;
46
- consecutiveIdentifier: string; // consecutivo
47
- ceSituation: string; // situacionCE
48
- orderLines: OrderInput[];
49
- referenceInfo?: ReferenceInfoInput;
50
- conditionSale: string
51
- paymentMethod: string;
52
- }
34
+ type DocumentInputBase = {
35
+ emitter: PersonInput;
36
+ branch: string;
37
+ terminal: string;
38
+ documentName: DocumentNames;
39
+ providerId: string;
40
+ countryCode: string;
41
+ securityCode: string;
42
+ activityCode: string;
43
+ consecutiveIdentifier: string;
44
+ ceSituation: string;
45
+ orderLines: OrderInput[];
46
+ referenceInfo?: ReferenceInfoInput;
47
+ conditionSale: string;
48
+ paymentMethod: string;
49
+ };
50
+
51
+ type DocumentInputTiquete = DocumentInputBase & {
52
+ documentName: 'TiqueteElectronico';
53
+ receiver?: PersonInput; // optional
54
+ };
55
+
56
+ export type DocumentInputWithReceiver = DocumentInputBase & {
57
+ documentName: Exclude<DocumentNames, 'TiqueteElectronico'>;
58
+ receiver: PersonInput; // required
59
+ };
60
+
61
+ type DocumentInput = DocumentInputTiquete | DocumentInputWithReceiver;
53
62
 
54
63
  export type CreateDocumentInput = {
55
64
  document: DocumentInput;
@@ -74,10 +83,10 @@ export class CreateDocFactory {
74
83
  providerId: document.providerId,
75
84
  issueDate: new Date(),
76
85
  emitter: Person.create(document.emitter),
77
- receiver: Person.create(document.receiver),
86
+ receiver: document.receiver ? Person.create(document.receiver) : undefined,
78
87
  conditionSale: document.conditionSale,
79
88
  paymentMethod: document.paymentMethod,
80
- referenceInformation: document.referenceInfo ? ReferenceInformation.create(document.referenceInfo) : undefined,
89
+ referenceInformation: document.referenceInfo ? ReferenceInformation.create(document.referenceInfo) : undefined
81
90
  })
82
91
  }
83
92
 
@@ -113,7 +122,7 @@ export class CreateDocFactory {
113
122
  countryCode: dto.countryCode,
114
123
  docKeyType: docType.value,
115
124
  emitterIdentifier: dto.emitter.identifier.id,
116
- identifierType: dto.emitter.identifier.type, // TODO add default
125
+ identifierType: dto.emitter.identifier.type || '01',
117
126
  securityCode: dto.securityCode,
118
127
  terminal: dto.terminal
119
128
  })
@@ -11,7 +11,7 @@ export type InvoiceProps = {
11
11
  fullConsecutive: FullConsecutive;
12
12
  issueDate: Date; // FechaEmision
13
13
  emitter: Person; // Emisor
14
- receiver: Person; // Receptor
14
+ receiver?: Person; // Receptor
15
15
  orderLines: OrderLine[];
16
16
  conditionSale?: string; // CondicionVenta
17
17
  deadlineCredit?: string; // PlazoCredito
@@ -58,7 +58,7 @@ export class Document {
58
58
  return this.props.emitter
59
59
  }
60
60
 
61
- get receiver(): Person {
61
+ get receiver(): Person | undefined {
62
62
  return this.props.receiver
63
63
  }
64
64
 
@@ -92,7 +92,7 @@ export class Document {
92
92
  const summary = {
93
93
  currency: {
94
94
  code: 'CRC',
95
- exchangeRate: '585.69'
95
+ exchangeRate: '1'
96
96
  },
97
97
  totalExemptServices: 0,
98
98
  totalEncumberedServices: servicesLineSumResult.totalAmount,
@@ -121,7 +121,7 @@ export class Document {
121
121
  }
122
122
 
123
123
  private isAService(orderLine: OrderLine): boolean {
124
- const servicesMeasurementUnits = ['Sp', 'St', 'Spe'];
124
+ const servicesMeasurementUnits = ['Sp', 'St', 'Spe']
125
125
  return servicesMeasurementUnits.includes(orderLine.measureUnit)
126
126
  }
127
127
 
@@ -129,7 +129,7 @@ export class Document {
129
129
  return this.orderLines.filter(this.isAService).reduce<OrderLineSum>((previousValue, currentValue) => {
130
130
  return {
131
131
  totalAmount: previousValue.totalAmount + currentValue.totalAmount,
132
- totalTaxes: previousValue.totalTaxes + currentValue.tax.amount
132
+ totalTaxes: previousValue.totalTaxes + (currentValue.tax?.amount ?? 0)
133
133
  }
134
134
  }, { totalAmount: 0, totalTaxes: 0 })
135
135
  }
@@ -138,7 +138,7 @@ export class Document {
138
138
  return this.orderLines.filter((ol) => !this.isAService(ol)).reduce<OrderLineSum>((previousValue, currentValue) => {
139
139
  return {
140
140
  totalAmount: previousValue.totalAmount + currentValue.totalAmount,
141
- totalTaxes: previousValue.totalTaxes + currentValue.tax.amount
141
+ totalTaxes: previousValue.totalTaxes + (currentValue.tax?.amount ?? 0)
142
142
  }
143
143
  }, { totalAmount: 0, totalTaxes: 0 })
144
144
  }
@@ -147,7 +147,7 @@ export class Document {
147
147
  return this.orderLines.reduce<OrderLineSum>((previousValue, currentValue) => {
148
148
  return {
149
149
  totalAmount: previousValue.totalAmount + currentValue.totalAmount,
150
- totalTaxes: previousValue.totalTaxes + currentValue.tax.amount
150
+ totalTaxes: previousValue.totalTaxes + (currentValue.tax?.amount ?? 0)
151
151
  }
152
152
  }, { totalAmount: 0, totalTaxes: 0 })
153
153
  }
@@ -1,14 +1,21 @@
1
- import { DocumentNames } from './documentNames.types'
1
+ export type DocumentNames =
2
+ 'FacturaElectronica' |
3
+ 'TiqueteElectronico' |
4
+ 'FacturaElectronicaExportacion' |
5
+ 'NotaCreditoElectronica' |
6
+ 'NotaDebitoElectronica' |
7
+ 'MensajeReceptor'
8
+
9
+ export type DocumentTypeValues = 'FE' | 'ND' | 'NC' | 'TE'
2
10
 
3
11
  const map: {[key: string]: DocumentTypeValues} = {
4
12
  FacturaElectronica: 'FE',
5
13
  FacturaElectronicaExportacion: 'FE',
14
+ TiqueteElectronico: 'TE',
6
15
  NotaCreditoElectronica: 'NC',
7
16
  NotaDebitoElectronica: 'NC'
8
17
  }
9
18
 
10
- type DocumentTypeValues = 'FE' | 'ND' | 'NC' | 'TE'
11
-
12
19
  export class DocumentType {
13
20
  value: DocumentTypeValues
14
21
 
@@ -1,8 +1,9 @@
1
1
  import { consecutivoStr } from '@src/lib/genClave'
2
+ import { DocumentTypeValues } from './DocumentType'
2
3
 
3
4
  type FullConsecutiveProps = {
4
5
  consecutiveIdentifier: string;
5
- documentType?: string;
6
+ documentType: DocumentTypeValues;
6
7
  branch?: string;
7
8
  terminal?: string;
8
9
  }
@@ -59,14 +59,17 @@ export class OrderLine {
59
59
  }
60
60
 
61
61
  get totalOrderLineAmount(): number {
62
- return this.props.totalOrderLineAmount || this.subTotal + this.tax.amount
62
+ return this.props.totalOrderLineAmount || this.subTotal + (this.tax?.amount ?? 0)
63
63
  }
64
64
 
65
65
  get tax(): TaxProps {
66
+ // @ts-expect-error pending-to-fix
66
67
  const rate = this.props.tax.rate
67
68
  return {
68
69
  rate,
70
+ // @ts-expect-error pending-to-fix
69
71
  code: this.props.tax.code,
72
+ // @ts-expect-error pending-to-fix
70
73
  rateCode: this.props.tax.rateCode,
71
74
  amount: this.subTotal * (rate / 100)
72
75
  }
@@ -83,8 +86,11 @@ export class OrderLine {
83
86
  totalAmount: props.totalAmount
84
87
  }
85
88
  const tax: TaxProps = {
89
+ // @ts-expect-error pending-to-fix
86
90
  code: props.tax.code,
91
+ // @ts-expect-error pending-to-fix
87
92
  rate: typeof props.tax.rate === 'number' ? props.tax.rate : 13,
93
+ // @ts-expect-error pending-to-fix
88
94
  rateCode: props.tax.rateCode
89
95
  }
90
96
  return new OrderLine({
@@ -14,7 +14,7 @@ export type PhoneProps = {
14
14
  export type PersonProps = {
15
15
  fullName: string;
16
16
  identifier: {
17
- type: '01' | '02';
17
+ type: '01' | '02' | undefined;
18
18
  id: string;
19
19
  };
20
20
  commercialName: string;
@@ -35,7 +35,7 @@ export class Person {
35
35
  return this.props.fullName
36
36
  }
37
37
 
38
- get identifierType(): '01' | '02' | undefined {
38
+ get identifierType(): PersonProps['identifier']['type'] {
39
39
  return this.props.identifier.type
40
40
  }
41
41
 
@@ -6,22 +6,22 @@ type ReceptorConsecutiveProps = {
6
6
  }
7
7
 
8
8
  export class ReceptorConsecutive {
9
- private props: ReceptorConsecutiveProps
9
+ private props: ReceptorConsecutiveProps
10
10
 
11
- constructor(props: ReceptorConsecutiveProps) {
12
- this.props = props
13
- }
11
+ constructor(props: ReceptorConsecutiveProps) {
12
+ this.props = props
13
+ }
14
14
 
15
- get value(): string {
16
- return Object.values(this.props).join('')
17
- }
15
+ get value(): string {
16
+ return Object.values(this.props).join('')
17
+ }
18
18
 
19
- public static create(props: ReceptorConsecutiveProps): ReceptorConsecutive {
20
- return new ReceptorConsecutive({
21
- branch: props.branch.padStart(3, '0'),
22
- terminal: props.terminal.padStart(5, '0'),
23
- documentType: props.documentType,
24
- consecutive: props.consecutive.padStart(10, '0')
25
- })
26
- }
27
- }
19
+ public static create(props: ReceptorConsecutiveProps): ReceptorConsecutive {
20
+ return new ReceptorConsecutive({
21
+ branch: props.branch.padStart(3, '0'),
22
+ terminal: props.terminal.padStart(5, '0'),
23
+ documentType: props.documentType,
24
+ consecutive: props.consecutive.padStart(10, '0')
25
+ })
26
+ }
27
+ }
@@ -14,28 +14,28 @@ export class ReferenceInformation {
14
14
  }
15
15
 
16
16
  get docType(): string {
17
- return this.props.docType;
17
+ return this.props.docType
18
18
  }
19
19
 
20
20
  get refNumber(): string {
21
- return this.props.refNumber;
21
+ return this.props.refNumber
22
22
  }
23
23
 
24
24
  get issueDate(): Date {
25
- return this.props.issueDate;
25
+ return this.props.issueDate
26
26
  }
27
27
 
28
28
  get code(): string {
29
- return this.props.code;
29
+ return this.props.code
30
30
  }
31
31
 
32
32
  get reason(): string {
33
- return this.props.reason;
33
+ return this.props.reason
34
34
  }
35
35
 
36
36
  public static create(props: ReferenceInformationProps): ReferenceInformation {
37
37
  return new ReferenceInformation({
38
- ...props,
38
+ ...props
39
39
  })
40
40
  }
41
41
  }
@@ -1,22 +1,23 @@
1
+ import { PersonProps } from './Person'
2
+
1
3
  export enum AceptationStates {
2
4
  ACCEPTED = 1,
3
5
  PARTIALLY_ACCEPTED = 2,
4
6
  DECLINED = 3
5
7
  }
6
-
8
+
7
9
  export type ReceptorMessageProps = {
8
10
  clave: string;
9
11
  emitterIdentifier: string;
10
- emitterIdentifierType: string;
12
+ emitterIdentifierType: PersonProps['identifier']['type'];
11
13
  receptorIdentifier: string;
12
- receptorIdentifierType: string;
14
+ receptorIdentifierType: PersonProps['identifier']['type'];
13
15
  documentIssueDate: Date;
14
16
  activityCode: string;
15
17
  aceptationState: AceptationStates
16
18
  aceptationDetailMessage: string;
17
19
  receptorConcecutive: string;
18
20
  taxCondition: string;
19
- totalTaxes: number;
20
- totalSale: number;
21
+ totalTaxes: number;
22
+ totalSale: number;
21
23
  }
22
-
package/src/ATV/index.ts CHANGED
@@ -11,7 +11,7 @@ import { CreateDocumentInput } from './core/CreateDocFactory'
11
11
  import { CreateReceptorMessageCommand, CreateReceptorMessageCommandInput } from './useCases/createReceptorMessage'
12
12
 
13
13
  export class ATV {
14
- public readonly options: ATVOptions
14
+ public readonly options: ATVOptions | undefined
15
15
  constructor(options?: ATVOptions, public readonly mode: Mode = 'prod') {
16
16
  this.options = options
17
17
  }
@@ -67,14 +67,14 @@ export class ATV {
67
67
  confirmation: this.parseConfirmationMessage(xmlString),
68
68
  xml: xmlString,
69
69
  rawResponse: response,
70
- errorCause: null,
70
+ errorCause: null
71
71
  }
72
72
  } catch (error) {
73
73
  const response = error.response || {}
74
74
  return {
75
75
  status: response.status || 500,
76
76
  errorCause: response.statusText || error.message,
77
- rawResponse: response,
77
+ rawResponse: response
78
78
  }
79
79
  }
80
80
  }
@@ -29,9 +29,11 @@ const mapOrderLinesToAtvFormat = (orderLines: OrderLine[]): DetalleServicio => {
29
29
  Impuesto: {
30
30
  Codigo: orderLine.tax.code,
31
31
  Tarifa: orderLine.tax.rate,
32
+ // @ts-expect-error pending-to-fix
32
33
  Monto: parseAtvMoneyFormat(orderLine.tax.amount)
33
34
  },
34
35
  ImpuestoAsumidoEmisorFabrica: 0,
36
+ // @ts-expect-error pending-to-fix
35
37
  ImpuestoNeto: parseAtvMoneyFormat(orderLine.tax.amount),
36
38
  MontoTotalLinea: parseAtvMoneyFormat(orderLine.totalOrderLineAmount)
37
39
  }
@@ -43,21 +45,28 @@ const mapSummaryInvoice = (document: DomainDocument): Resumen => {
43
45
  const summaryInvoice = document.summaryInvoice
44
46
  return {
45
47
  CodigoTipoMoneda: {
48
+ // @ts-expect-error pending-to-fix
46
49
  CodigoMoneda: summaryInvoice.currency.code,
50
+ // @ts-expect-error pending-to-fix
47
51
  TipoCambio: summaryInvoice.currency.exchangeRate
48
52
  },
49
53
  TotalServGravados: parseAtvMoneyFormat(summaryInvoice.totalEncumberedServices),
50
54
  TotalServExentos: parseAtvMoneyFormat(summaryInvoice.totalExemptServices),
55
+ // @ts-expect-error pending-to-fix
51
56
  TotalMercanciasGravadas: parseAtvMoneyFormat(summaryInvoice.totalEncumberedMerchandise),
57
+ // @ts-expect-error pending-to-fix
52
58
  TotalMercanciasExentas: parseAtvMoneyFormat(summaryInvoice.totalExemptMerchandise),
53
59
  TotalGravado: parseAtvMoneyFormat(summaryInvoice.totalEncumbered),
54
60
  TotalExento: parseAtvMoneyFormat(summaryInvoice.totalExempt),
55
61
  TotalExonerado: parseAtvMoneyFormat(summaryInvoice.totalExonerated),
56
62
  TotalVenta: parseAtvMoneyFormat(summaryInvoice.totalSale),
63
+ // @ts-expect-error pending-to-fix
57
64
  TotalDescuentos: parseAtvMoneyFormat(summaryInvoice.totalDiscounts),
65
+ // @ts-expect-error pending-to-fix
58
66
  TotalVentaNeta: parseAtvMoneyFormat(summaryInvoice.totalNetSale),
59
67
  TotalImpuesto: parseAtvMoneyFormat(summaryInvoice.totalTaxes),
60
68
  MedioPago: {
69
+ // @ts-expect-error pending-to-fix
61
70
  TipoMedioPago: document.paymentMethod
62
71
  },
63
72
  TotalComprobante: parseAtvMoneyFormat(summaryInvoice.totalVoucher)
@@ -76,17 +85,24 @@ const mapPerson = (person: Person): Persona => {
76
85
  Telefono: undefined,
77
86
  CorreoElectronico: undefined
78
87
  }
79
- atvPerson.Ubicacion = person.location ? {
80
- Provincia: person.location?.province,
81
- Canton: person.location?.canton?.padStart(2, '0'),
82
- Distrito: person.location?.district?.padStart(2, '0'),
83
- Barrio: person.location?.neighborhood?.padStart(5, '0'),
84
- OtrasSenas: person.location?.details
85
- } : undefined
86
- atvPerson.Telefono = person.phone ? {
87
- CodigoPais: person.phone?.countryCode,
88
- NumTelefono: person.phone?.number
89
- } : undefined
88
+ // @ts-expect-error pending-to-fix
89
+ atvPerson.Ubicacion = person.location
90
+ ? {
91
+ Provincia: person.location?.province,
92
+ Canton: person.location?.canton?.padStart(2, '0'),
93
+ Distrito: person.location?.district?.padStart(2, '0'),
94
+ Barrio: person.location?.neighborhood?.padStart(5, '0'),
95
+ OtrasSenas: person.location?.details
96
+ }
97
+ : undefined
98
+ // @ts-expect-error pending-to-fix
99
+ atvPerson.Telefono = person.phone
100
+ ? {
101
+ CodigoPais: person.phone?.countryCode,
102
+ NumTelefono: person.phone?.number
103
+ }
104
+ : undefined
105
+ // @ts-expect-error pending-to-fix
90
106
  atvPerson.CorreoElectronico = person.email
91
107
 
92
108
  return atvPerson
@@ -103,16 +119,20 @@ const mapReferenceInformation = (referenceInfo: ReferenceInformation): Informaci
103
119
  }
104
120
 
105
121
  export const mapDocumentToAtvFormat = (docName: string, document: DomainDocument): AtvFormat => {
106
- const key = docName;
122
+ const key = docName
107
123
  const doc: AtvDocument = {
108
124
  Clave: document.clave,
109
125
  ProveedorSistemas: document.providerId,
110
126
  CodigoActividadEmisor: document.emitter.activityCode.padStart(6, '0'),
111
- CodigoActividadReceptor: document.receiver.activityCode.padStart(6, '0'),
127
+ ...(document.receiver && { // TODO add && document.name === 'FacturaElectronica'
128
+ CodigoActividadReceptor: document.receiver.activityCode.padStart(6, '0')
129
+ }),
112
130
  NumeroConsecutivo: document.fullConsecutive,
113
131
  FechaEmision: document.issueDate.toISOString(),
114
132
  Emisor: mapPerson(document.emitter),
115
- Receptor: mapPerson(document.receiver),
133
+ ...(document.receiver && {
134
+ Receptor: mapPerson(document.receiver)
135
+ }),
116
136
  CondicionVenta: document.conditionSale,
117
137
  PlazoCredito: document.deadlineCredit,
118
138
  DetalleServicio: mapOrderLinesToAtvFormat(document.orderLines),
@@ -120,7 +140,7 @@ export const mapDocumentToAtvFormat = (docName: string, document: DomainDocument
120
140
  Otros: document.others
121
141
  }
122
142
  if (document.referenceInformation) {
123
- doc.InformacionReferencia = mapReferenceInformation(document.referenceInformation);
143
+ doc.InformacionReferencia = mapReferenceInformation(document.referenceInformation)
124
144
  }
125
145
  return {
126
146
  [key]: doc
package/src/ATV/types.ts CHANGED
@@ -13,7 +13,7 @@ export type TokenServiceProps = {
13
13
 
14
14
  export type SendResponse = {
15
15
  status: number;
16
- location: string;
16
+ location?: string | null;
17
17
  errorCause?: string | null;
18
18
  }
19
19