@facturacr/atv-sdk 0.0.25-beta → 1.0.1

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 (38) hide show
  1. package/.github/workflows/ci.yml +2 -2
  2. package/.github/workflows/publish.yml +27 -0
  3. package/CHANGELOG.md +29 -0
  4. package/__tests__/stubs/commonExpectedXml.xml +13 -13
  5. package/__tests__/stubs/{createDocument.stub.ts → createDocument.data.ts} +23 -15
  6. package/__tests__/tests/ATV/__snapshots__/index.test.ts.snap +1 -1
  7. package/__tests__/tests/ATV/index.test.ts +5 -5
  8. package/dist/src/ATV/core/CreateDocFactory.d.ts +53 -0
  9. package/dist/src/ATV/core/CreateDocFactory.js +67 -0
  10. package/dist/src/ATV/core/CreateDocFactory.js.map +1 -0
  11. package/dist/src/ATV/core/Document.d.ts +3 -0
  12. package/dist/src/ATV/core/Document.js +3 -0
  13. package/dist/src/ATV/core/Document.js.map +1 -1
  14. package/dist/src/ATV/core/ReferenceInformation.d.ts +17 -0
  15. package/dist/src/ATV/core/ReferenceInformation.js +28 -0
  16. package/dist/src/ATV/core/ReferenceInformation.js.map +1 -0
  17. package/dist/src/ATV/index.d.ts +2 -1
  18. package/dist/src/ATV/index.js.map +1 -1
  19. package/dist/src/ATV/mappers/billDocToAtv.js +12 -0
  20. package/dist/src/ATV/mappers/billDocToAtv.js.map +1 -1
  21. package/dist/src/ATV/useCases/createDocument/index.d.ts +3 -8
  22. package/dist/src/ATV/useCases/createDocument/index.js +4 -68
  23. package/dist/src/ATV/useCases/createDocument/index.js.map +1 -1
  24. package/dist/src/ATV/useCases/createDocument/types.d.ts +0 -43
  25. package/dist/src/index.d.ts +1 -1
  26. package/dist/src/types/facturaInterfaces.d.ts +8 -0
  27. package/examples/createAndSend.ts +8 -5
  28. package/examples/createCreditNote.ts +52 -22
  29. package/package.json +1 -1
  30. package/src/ATV/core/CreateDocFactory.ts +117 -0
  31. package/src/ATV/core/Document.ts +6 -0
  32. package/src/ATV/core/ReferenceInformation.ts +41 -0
  33. package/src/ATV/index.ts +2 -1
  34. package/src/ATV/mappers/billDocToAtv.ts +15 -1
  35. package/src/ATV/useCases/createDocument/index.ts +9 -74
  36. package/src/ATV/useCases/createDocument/types.ts +2 -48
  37. package/src/index.ts +1 -1
  38. package/src/types/facturaInterfaces.ts +9 -0
@@ -10,14 +10,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.CreateDocumentCommand = void 0;
13
- const Person_1 = require("../../core/Person");
14
- const OrderLine_1 = require("../../core/OrderLine");
15
- const FullConsecutive_1 = require("../../core/FullConsecutive");
16
- const Document_1 = require("../../core/Document");
17
- const Clave_1 = require("../../core/Clave");
18
13
  const billDocToAtv_1 = require("../../mappers/billDocToAtv");
19
14
  const genXML_1 = require("../../../lib/genXML");
20
- const DocumentType_1 = require("../../core/DocumentType");
15
+ const CreateDocFactory_1 = require("../../core/CreateDocFactory");
21
16
  const options = {
22
17
  prod: {
23
18
  serviceUrl: 'https://api.comprobanteselectronicos.go.cr/v1/recepcion'
@@ -29,11 +24,12 @@ const options = {
29
24
  class CreateDocumentCommand {
30
25
  constructor(scope) {
31
26
  this.serviceUrl = options[scope.mode].serviceUrl;
27
+ this.createDoc = new CreateDocFactory_1.CreateDocFactory();
32
28
  }
33
29
  execute(dto) {
34
30
  return __awaiter(this, void 0, void 0, function* () {
35
- const documentName = dto.document.documentName || 'FacturaElectronica';
36
- const document = this.createDocument(dto.document);
31
+ const documentName = dto.document.documentName || 'FacturaElectronica'; //TODO NotaDebitoElectronica
32
+ const document = this.createDoc.createDocument(dto.document);
37
33
  const atvDocument = (0, billDocToAtv_1.mapDocumentToAtvFormat)(documentName, document);
38
34
  const xml = yield (0, genXML_1.genXML)(documentName, atvDocument, dto.signatureOptions);
39
35
  const command = yield this.createDocumentCommand(document, xml, dto.token);
@@ -71,66 +67,6 @@ class CreateDocumentCommand {
71
67
  };
72
68
  });
73
69
  }
74
- createDocument(document) {
75
- const documentType = DocumentType_1.DocumentType.create(document.documentName);
76
- const emitter = this.createEmitter(document.emitter);
77
- const receiver = this.createReceiver(document.receiver);
78
- const clave = this.createClave(document, documentType);
79
- const fullConsective = this.createFullConsecutive(document, documentType);
80
- const orderLines = this.createOrderLines(document);
81
- return Document_1.Document.create({
82
- clave,
83
- fullConsecutive: fullConsective,
84
- orderLines,
85
- activityCode: document.activityCode,
86
- issueDate: new Date(),
87
- emitter,
88
- receiver,
89
- conditionSale: '01',
90
- paymentMethod: '01'
91
- });
92
- }
93
- createEmitter(emitterInput) {
94
- return Person_1.Person.create(emitterInput);
95
- }
96
- createReceiver(receiverInput) {
97
- return Person_1.Person.create(receiverInput);
98
- }
99
- createOrderLines(dto) {
100
- return dto.orderLines.map((orderLine, index) => {
101
- return OrderLine_1.OrderLine.create({
102
- detail: orderLine.detail,
103
- unitaryPrice: orderLine.unitaryPrice,
104
- lineNumber: orderLine.lineNumber || (index + 1).toString(),
105
- code: orderLine.code,
106
- quantity: orderLine.quantity,
107
- measureUnit: orderLine.measureUnit,
108
- totalAmount: orderLine.totalAmount,
109
- tax: orderLine.tax
110
- });
111
- });
112
- }
113
- createFullConsecutive(dto, docType) {
114
- return FullConsecutive_1.FullConsecutive.create({
115
- consecutiveIdentifier: dto.consecutiveIdentifier,
116
- branch: dto.branch.padStart(3, '0'),
117
- terminal: dto.terminal.padStart(5, '0'),
118
- documentType: docType.value
119
- });
120
- }
121
- createClave(dto, docType) {
122
- return Clave_1.Clave.create({
123
- branch: dto.branch,
124
- ceSituation: dto.ceSituation,
125
- consecutiveIdentifier: dto.consecutiveIdentifier,
126
- countryCode: dto.countryCode,
127
- docKeyType: docType.value,
128
- emitterIdentifier: dto.emitter.identifier.id,
129
- identifierType: dto.emitter.identifier.type, // TODO add default
130
- securityCode: dto.securityCode,
131
- terminal: dto.terminal
132
- });
133
- }
134
70
  encodeXML(xmlStr) {
135
71
  const buffer = Buffer.from(xmlStr);
136
72
  return buffer.toString('base64');
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/ATV/useCases/createDocument/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAA6C;AAC7C,oDAAmD;AACnD,gEAA+D;AAC/D,kDAAiD;AACjD,4CAA2C;AAC3C,6DAA4F;AAC5F,gDAAwC;AAGxC,0DAAyD;AAGzD,MAAM,OAAO,GAA4C;IACvD,IAAI,EAAE;QACJ,UAAU,EAAE,yDAAyD;KACtE;IACD,GAAG,EAAE;QACH,UAAU,EAAE,2EAA2E;KACxF;CACF,CAAA;AAED,MAAa,qBAAqB;IAGhC,YAAY,KAAU;QACpB,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,UAAU,CAAA;IAClD,CAAC;IAEY,OAAO,CAAC,GAAwB;;YAC3C,MAAM,YAAY,GAAG,GAAG,CAAC,QAAQ,CAAC,YAAY,IAAI,oBAAoB,CAAA;YACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;YAClD,MAAM,WAAW,GAAG,IAAA,qCAAkB,EAAC,YAAY,EAAE,QAAQ,CAAC,CAAA;YAC9D,MAAM,GAAG,GAAG,MAAM,IAAA,eAAM,EAAC,YAAY,EAAE,WAAW,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAA;YACzE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,CAAA;YAC1E,OAAO;gBACL,OAAO;gBACP,SAAS,EAAE;oBACT,GAAG;oBACH,QAAQ,EAAE,WAAW;iBACtB;aACF,CAAA;QACH,CAAC;KAAA;IAEa,qBAAqB,CAAC,QAAkB,EAAE,GAAW,EAAE,KAAa;;YAChF,OAAO;gBACL,GAAG,EAAE,IAAI,CAAC,UAAU;gBACpB,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE;oBACJ,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,WAAW,EAAE;oBACvC,MAAM,EAAE;wBACN,kBAAkB,EAAE,QAAQ,CAAC,OAAO,CAAC,cAAc;wBACnD,oBAAoB,EAAE,QAAQ,CAAC,OAAO,CAAC,YAAY;qBACpD;oBACD,QAAQ,EAAE;wBACR,kBAAkB,EAAE,QAAQ,CAAC,QAAQ,CAAC,cAAc;wBACpD,oBAAoB,EAAE,QAAQ,CAAC,QAAQ,CAAC,YAAY;qBACrD;oBACD,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;iBACpC;gBACD,OAAO,EAAE;oBACP,aAAa,EAAE,SAAS,GAAG,KAAK;oBAChC,cAAc,EAAE,kBAAkB;iBACnC;aACF,CAAA;QACH,CAAC;KAAA;IAEO,cAAc,CAAC,QAAyC;QAC9D,MAAM,YAAY,GAAG,2BAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAA;QAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QACvD,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAA;QACtD,MAAM,cAAc,GAAG,IAAI,CAAC,qBAAqB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAA;QACzE,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAA;QAClD,OAAO,mBAAQ,CAAC,MAAM,CAAC;YACrB,KAAK;YACL,eAAe,EAAE,cAAc;YAC/B,UAAU;YACV,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,SAAS,EAAE,IAAI,IAAI,EAAE;YACrB,OAAO;YACP,QAAQ;YACR,aAAa,EAAE,IAAI;YACnB,aAAa,EAAE,IAAI;SACpB,CAAC,CAAA;IACJ,CAAC;IAEO,aAAa,CAAC,YAAwD;QAC5E,OAAO,eAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;IACpC,CAAC;IAEO,cAAc,CAAC,aAA0D;QAC/E,OAAO,eAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;IACrC,CAAC;IAEO,gBAAgB,CAAC,GAAoC;QAC3D,OAAO,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE;YAC7C,OAAO,qBAAS,CAAC,MAAM,CAAC;gBACtB,MAAM,EAAE,SAAS,CAAC,MAAM;gBACxB,YAAY,EAAE,SAAS,CAAC,YAAY;gBACpC,UAAU,EAAE,SAAS,CAAC,UAAU,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE;gBAC1D,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,QAAQ,EAAE,SAAS,CAAC,QAAQ;gBAC5B,WAAW,EAAE,SAAS,CAAC,WAAW;gBAClC,WAAW,EAAE,SAAS,CAAC,WAAW;gBAClC,GAAG,EAAE,SAAS,CAAC,GAAG;aACnB,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,qBAAqB,CAAC,GAAoC,EAAE,OAAqB;QACvF,OAAO,iCAAe,CAAC,MAAM,CAAC;YAC5B,qBAAqB,EAAE,GAAG,CAAC,qBAAqB;YAChD,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC;YACnC,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC;YACvC,YAAY,EAAE,OAAO,CAAC,KAAK;SAC5B,CAAC,CAAA;IACJ,CAAC;IAEO,WAAW,CAAC,GAAoC,EAAE,OAAqB;QAC7E,OAAO,aAAK,CAAC,MAAM,CAAC;YAClB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,qBAAqB,EAAE,GAAG,CAAC,qBAAqB;YAChD,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,UAAU,EAAE,OAAO,CAAC,KAAK;YACzB,iBAAiB,EAAE,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;YAC5C,cAAc,EAAE,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,mBAAmB;YAChE,YAAY,EAAE,GAAG,CAAC,YAAY;YAC9B,QAAQ,EAAE,GAAG,CAAC,QAAQ;SACvB,CAAC,CAAA;IACJ,CAAC;IAEO,SAAS,CAAC,MAAc;QAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAClC,OAAO,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAClC,CAAC;CACF;AApHD,sDAoHC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/ATV/useCases/createDocument/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEA,6DAA4F;AAC5F,gDAAwC;AAGxC,kEAAsF;AAEtF,MAAM,OAAO,GAA4C;IACvD,IAAI,EAAE;QACJ,UAAU,EAAE,yDAAyD;KACtE;IACD,GAAG,EAAE;QACH,UAAU,EAAE,2EAA2E;KACxF;CACF,CAAA;AAED,MAAa,qBAAqB;IAKhC,YAAY,KAAU;QACpB,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,UAAU,CAAA;QAChD,IAAI,CAAC,SAAS,GAAG,IAAI,mCAAgB,EAAE,CAAA;IACzC,CAAC;IAEY,OAAO,CAAC,GAAwB;;YAC3C,MAAM,YAAY,GAAG,GAAG,CAAC,QAAQ,CAAC,YAAY,IAAI,oBAAoB,CAAA,CAAC,4BAA4B;YACnG,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;YAC5D,MAAM,WAAW,GAAG,IAAA,qCAAkB,EAAC,YAAY,EAAE,QAAQ,CAAC,CAAA;YAC9D,MAAM,GAAG,GAAG,MAAM,IAAA,eAAM,EAAC,YAAY,EAAE,WAAW,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAA;YACzE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,CAAA;YAC1E,OAAO;gBACL,OAAO;gBACP,SAAS,EAAE;oBACT,GAAG;oBACH,QAAQ,EAAE,WAAW;iBACtB;aACF,CAAA;QACH,CAAC;KAAA;IAEa,qBAAqB,CAAC,QAAkB,EAAE,GAAW,EAAE,KAAa;;YAChF,OAAO;gBACL,GAAG,EAAE,IAAI,CAAC,UAAU;gBACpB,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE;oBACJ,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,WAAW,EAAE;oBACvC,MAAM,EAAE;wBACN,kBAAkB,EAAE,QAAQ,CAAC,OAAO,CAAC,cAAc;wBACnD,oBAAoB,EAAE,QAAQ,CAAC,OAAO,CAAC,YAAY;qBACpD;oBACD,QAAQ,EAAE;wBACR,kBAAkB,EAAE,QAAQ,CAAC,QAAQ,CAAC,cAAc;wBACpD,oBAAoB,EAAE,QAAQ,CAAC,QAAQ,CAAC,YAAY;qBACrD;oBACD,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;iBACpC;gBACD,OAAO,EAAE;oBACP,aAAa,EAAE,SAAS,GAAG,KAAK;oBAChC,cAAc,EAAE,kBAAkB;iBACnC;aACF,CAAA;QACH,CAAC;KAAA;IAIO,SAAS,CAAC,MAAc;QAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAClC,OAAO,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAClC,CAAC;CACF;AAvDD,sDAuDC"}
@@ -1,48 +1,6 @@
1
- import { PersonProps } from '@src/ATV/core/Person';
2
- import { DocumentNames } from '@src/ATV/core/documentNames.types';
3
1
  import { InvoiceDocumentContainer } from '@src/types/facturaInterfaces';
4
2
  import { Method } from 'axios';
5
- type PersonInput = PersonProps;
6
- type TaxInput = {
7
- code: string;
8
- rateCode: string;
9
- rate: number;
10
- amount?: number;
11
- };
12
- type OrderInput = {
13
- detail: string;
14
- unitaryPrice: number;
15
- lineNumber?: string;
16
- code?: string;
17
- quantity?: number;
18
- measureUnit?: string;
19
- totalAmount?: number;
20
- subTotal?: number;
21
- tax?: TaxInput;
22
- totalOrderLineAmount?: number;
23
- };
24
3
  export type DocumentTypes = 'FE';
25
- type DocumentInput = {
26
- emitter: PersonInput;
27
- receiver: PersonInput;
28
- branch: string;
29
- terminal: string;
30
- documentName: DocumentNames;
31
- countryCode: string;
32
- securityCode: string;
33
- activityCode: string;
34
- consecutiveIdentifier: string;
35
- ceSituation: string;
36
- orderLines: OrderInput[];
37
- };
38
- export type CreateDocumentInput = {
39
- document: DocumentInput;
40
- token: string;
41
- signatureOptions: {
42
- buffer: string;
43
- password: string;
44
- };
45
- };
46
4
  export type Command = {
47
5
  url: string;
48
6
  method: Method;
@@ -71,4 +29,3 @@ export type CreateAndSendDocumentResponse = {
71
29
  document: InvoiceDocumentContainer;
72
30
  };
73
31
  };
74
- export {};
@@ -1,3 +1,3 @@
1
1
  export { Document, InvoiceDocumentContainer, DetalleServicio, Resumen, Persona } from './types/facturaInterfaces';
2
- export { CreateDocumentInput } from './ATV/useCases/createDocument/types';
2
+ export { CreateDocumentInput } from './ATV/core/CreateDocFactory';
3
3
  export { ATV } from './ATV';
@@ -66,6 +66,13 @@ export interface Message {
66
66
  Mensaje: string;
67
67
  DetalleMensaje: string;
68
68
  }
69
+ export interface InformacionReferencia {
70
+ TipoDoc: string;
71
+ Numero: string;
72
+ FechaEmision: string;
73
+ Codigo: string;
74
+ Razon: string;
75
+ }
69
76
  export interface Document {
70
77
  Clave: string;
71
78
  CodigoActividad: string;
@@ -81,6 +88,7 @@ export interface Document {
81
88
  Otros?: {
82
89
  OtroTexto: string;
83
90
  };
91
+ InformacionReferencia?: InformacionReferencia;
84
92
  }
85
93
  export interface InvoiceDocumentContainer {
86
94
  [key: string]: Document;
@@ -1,6 +1,7 @@
1
1
  import fs from 'fs'
2
- import { createDocumentInputStub } from '@test/stubs/createDocument.stub'
2
+ import { createDocumentInputExample } from '@test/stubs/createDocument.data'
3
3
  import { ATV } from '../dist/src'
4
+ import { PersonProps } from 'dist/src/ATV/core/Person'
4
5
 
5
6
 
6
7
  const IS_STG = process.env.IS_STG
@@ -17,10 +18,12 @@ if (!SOURCE_P12_PASSPORT || !SOURCE_P12_URI) {
17
18
 
18
19
  const pem = fs.readFileSync(SOURCE_P12_URI, 'binary')
19
20
 
20
- console.log('requestStub consecutivo', createDocumentInputStub.consecutiveIdentifier)
21
-
22
21
  // TODO: dynamic param --identifier 1 args[x]
23
- createDocumentInputStub.consecutiveIdentifier = '4'
22
+ createDocumentInputExample.consecutiveIdentifier = process.env.TEST_CONSECUTIVE
23
+ createDocumentInputExample.emitter.identifier.id = process.env.EMITTER_IDENTIFIER_ID as string;
24
+ createDocumentInputExample.emitter.identifier.type = process.env.EMITTER_IDENTIFIER_TYPE as PersonProps['identifier']['type'];
25
+
26
+ console.log('requestStub consecutivo', createDocumentInputExample.consecutiveIdentifier)
24
27
 
25
28
  function getConfimation(atv: ATV, token: string, location: string, ms: number): Promise<any> {
26
29
  return new Promise((resolve, reject): any => {
@@ -45,7 +48,7 @@ async function main(): Promise<void> {
45
48
  password: PASSWORD_TEST
46
49
  })
47
50
  const { command, extraData } = await atv.createDocumentCommand({
48
- document: createDocumentInputStub,
51
+ document: createDocumentInputExample,
49
52
  token: tokenData.accessToken,
50
53
  signatureOptions: {
51
54
  buffer: pem,
@@ -1,39 +1,69 @@
1
- import { ClientPayload } from '@src/types/globalInterfaces'
2
- import creditNote from '@src/creditNote'
3
- import getToken from '@src/services/getToken'
4
- import requestStub from '@test/stubs/frontendRequest.stub'
5
1
  import fs from 'fs'
2
+ import { createDocumentInputExample, creditNoteReferenceInfoExample } from '@test/stubs/createDocument.data'
3
+ import { ATV } from '../dist/src'
6
4
 
7
- const frontEndRequest: ClientPayload = requestStub
5
+
6
+ const IS_STG = process.env.IS_STG
8
7
  const USERNAME_TEST = process.env.USERNAME_TEST
9
8
  const PASSWORD_TEST = process.env.PASSWORD_TEST
9
+ console.log('process.env.IS_STG', IS_STG)
10
+
10
11
  const SOURCE_P12_URI = process.env.SOURCE_P12_URI
11
12
  const SOURCE_P12_PASSPORT = process.env.SOURCE_P12_PASSPORT
13
+
14
+ if (!SOURCE_P12_PASSPORT || !SOURCE_P12_URI) {
15
+ throw new Error('No environment. For running examples set .env before.')
16
+ }
17
+
12
18
  const pem = fs.readFileSync(SOURCE_P12_URI, 'binary')
13
19
 
20
+ console.log('requestStub consecutivo', createDocumentInputExample.consecutiveIdentifier)
21
+
22
+ // TODO: dynamic param --identifier 1 args[x]
23
+ createDocumentInputExample.consecutiveIdentifier = '5'
24
+
25
+ function getConfimation(atv: ATV, token: string, location: string, ms: number): Promise<any> {
26
+ return new Promise((resolve, reject): any => {
27
+ setTimeout(() => {
28
+ console.log('location', location)
29
+ atv.sendConfirmation({
30
+ url: location,
31
+ headers: {
32
+ 'Content-Type': 'application/json',
33
+ Authorization: 'bearer ' + token
34
+ }
35
+ }).then(data => resolve(data))
36
+ .catch(err => reject(err))
37
+ }, ms)
38
+ })
39
+ }
40
+
14
41
  async function main(): Promise<void> {
15
- const tokenObj = await getToken({
16
- client_id: 'api-stag', // eslint-disable-line
17
- client_secret: '', // eslint-disable-line
18
- grant_type: 'password', // eslint-disable-line
42
+ const atv = new ATV({}, 'stg')
43
+ const tokenData = await atv.getToken({
19
44
  username: USERNAME_TEST,
20
45
  password: PASSWORD_TEST
21
46
  })
22
- const token = tokenObj.data.access_token
23
- const xmlOpt = {
24
- buffer: pem,
25
- password: SOURCE_P12_PASSPORT,
26
- base64: false
27
- }
28
- const data = await creditNote({
29
- token,
30
- frontEndRequest,
31
- xmlOpt
47
+ const { command, extraData } = await atv.createDocumentCommand({
48
+ document: {
49
+ ...createDocumentInputExample,
50
+ documentName: 'NotaCreditoElectronica',
51
+ referenceInfo: creditNoteReferenceInfoExample
52
+ },
53
+ token: tokenData.accessToken,
54
+ signatureOptions: {
55
+ buffer: pem,
56
+ password: SOURCE_P12_PASSPORT
57
+ }
32
58
  })
33
- console.log(typeof data)
34
- if (data) {
35
- console.log(data)
59
+ console.log('extraData', extraData.xml)
60
+ const response = await atv.sendDocument(command)
61
+ if (response.errorCause) {
62
+ console.log('error response', response)
63
+ return
36
64
  }
65
+ const confirmationResponse = await getConfimation(atv, tokenData.accessToken, response.location, 2000)
66
+ console.log({ MensajeHacienda: confirmationResponse.confirmation })
37
67
  }
38
68
 
39
69
  main()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@facturacr/atv-sdk",
3
- "version": "0.0.25-beta",
3
+ "version": "1.0.1",
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",
@@ -0,0 +1,117 @@
1
+ import { PersonProps } from '@src/ATV/core/Person'
2
+ import { DocumentNames } from '@src/ATV/core/documentNames.types'
3
+ import { Person } from '@src/ATV/core/Person'
4
+ import { OrderLine } from '@src/ATV/core/OrderLine'
5
+ import { FullConsecutive } from '@src/ATV/core/FullConsecutive'
6
+ import { Document } from '@src/ATV/core/Document'
7
+ import { Clave } from '@src/ATV/core/Clave'
8
+ import { DocumentType } from '@src/ATV/core/DocumentType'
9
+ import { ReferenceInformation, ReferenceInformationProps } from './ReferenceInformation'
10
+
11
+ type PersonInput = PersonProps;
12
+
13
+ type TaxInput = {
14
+ code: string;
15
+ rateCode: string;
16
+ rate: number;
17
+ amount?: number;
18
+ }
19
+
20
+ type OrderInput = {
21
+ detail: string;
22
+ unitaryPrice: number;
23
+ lineNumber?: string;
24
+ code?: string;
25
+ quantity?: number;
26
+ measureUnit?: string;
27
+ totalAmount?: number;
28
+ subTotal?: number;
29
+ tax?: TaxInput;
30
+ totalOrderLineAmount?: number;
31
+ }
32
+
33
+ type DocumentInput = {
34
+ emitter: PersonInput;
35
+ receiver: PersonInput;
36
+ branch: string; // sucursal
37
+ terminal: string; // terminal
38
+ // documentType: DocumentTypes; // @deprecated
39
+ documentName: DocumentNames;
40
+ countryCode: string; // codigoPais
41
+ securityCode: string; // codigoSeguridad
42
+ activityCode: string;
43
+ consecutiveIdentifier: string; // consecutivo
44
+ ceSituation: string; // situacionCE
45
+ orderLines: OrderInput[];
46
+ referenceInfo?: ReferenceInfoInput;
47
+ }
48
+
49
+ type ReferenceInfoInput = ReferenceInformationProps;
50
+
51
+ export type CreateDocumentInput = {
52
+ document: DocumentInput;
53
+ token: string;
54
+ signatureOptions: {
55
+ buffer: string;
56
+ password: string;
57
+ };
58
+ }
59
+
60
+ export class CreateDocFactory {
61
+ public createDocument(document: CreateDocumentInput['document']): Document {
62
+ const documentType = DocumentType.create(document.documentName)
63
+ const clave = this.createClave(document, documentType)
64
+ const fullConsective = this.createFullConsecutive(document, documentType)
65
+ const orderLines = this.createOrderLines(document)
66
+ return Document.create({
67
+ clave,
68
+ fullConsecutive: fullConsective,
69
+ orderLines,
70
+ activityCode: document.activityCode,
71
+ issueDate: new Date(),
72
+ emitter: Person.create(document.emitter),
73
+ receiver: Person.create(document.receiver),
74
+ conditionSale: '01',
75
+ paymentMethod: '01',
76
+ referenceInformation: document.referenceInfo ? ReferenceInformation.create(document.referenceInfo) : undefined,
77
+ })
78
+ }
79
+
80
+ private createOrderLines(dto: CreateDocumentInput['document']): OrderLine[] {
81
+ return dto.orderLines.map((orderLine, index) => {
82
+ return OrderLine.create({
83
+ detail: orderLine.detail,
84
+ unitaryPrice: orderLine.unitaryPrice,
85
+ lineNumber: orderLine.lineNumber || (index + 1).toString(),
86
+ code: orderLine.code,
87
+ quantity: orderLine.quantity,
88
+ measureUnit: orderLine.measureUnit,
89
+ totalAmount: orderLine.totalAmount,
90
+ tax: orderLine.tax
91
+ })
92
+ })
93
+ }
94
+
95
+ private createFullConsecutive(dto: CreateDocumentInput['document'], docType: DocumentType): FullConsecutive {
96
+ return FullConsecutive.create({
97
+ consecutiveIdentifier: dto.consecutiveIdentifier,
98
+ branch: dto.branch.padStart(3, '0'),
99
+ terminal: dto.terminal.padStart(5, '0'),
100
+ documentType: docType.value
101
+ })
102
+ }
103
+
104
+ private createClave(dto: CreateDocumentInput['document'], docType: DocumentType): Clave {
105
+ return Clave.create({
106
+ branch: dto.branch,
107
+ ceSituation: dto.ceSituation,
108
+ consecutiveIdentifier: dto.consecutiveIdentifier,
109
+ countryCode: dto.countryCode,
110
+ docKeyType: docType.value,
111
+ emitterIdentifier: dto.emitter.identifier.id,
112
+ identifierType: dto.emitter.identifier.type, // TODO add default
113
+ securityCode: dto.securityCode,
114
+ terminal: dto.terminal
115
+ })
116
+ }
117
+ }
@@ -2,6 +2,7 @@ import { Clave } from './Clave'
2
2
  import { FullConsecutive } from './FullConsecutive'
3
3
  import { OrderLine } from './OrderLine'
4
4
  import { Person } from './Person'
5
+ import { ReferenceInformation } from './ReferenceInformation'
5
6
  import { SummaryProps } from './Summary.type'
6
7
 
7
8
  export type InvoiceProps = {
@@ -16,6 +17,7 @@ export type InvoiceProps = {
16
17
  deadlineCredit?: string; // PlazoCredito
17
18
  paymentMethod?: string; // MedioPago
18
19
  summaryInvoice?: SummaryProps; // ResumenFactura
20
+ referenceInformation?: ReferenceInformation; // InformaciónReferencia
19
21
  others?: { // Otros
20
22
  OtroTexto: string;
21
23
  };
@@ -110,6 +112,10 @@ export class Document {
110
112
  }
111
113
  }
112
114
 
115
+ get referenceInformation(): ReferenceInformation | undefined {
116
+ return this.props.referenceInformation
117
+ }
118
+
113
119
  private isAService(orderLine: OrderLine): boolean {
114
120
  const servicesMeasurementUnits = ['Sp', 'St', 'Spe'];
115
121
  return servicesMeasurementUnits.includes(orderLine.measureUnit)
@@ -0,0 +1,41 @@
1
+ export type ReferenceInformationProps = {
2
+ docType: string;
3
+ refNumber: string;
4
+ issueDate: Date;
5
+ code: string;
6
+ reason: string;
7
+ }
8
+
9
+ export class ReferenceInformation {
10
+ private props: ReferenceInformationProps
11
+
12
+ constructor(props: ReferenceInformationProps) {
13
+ this.props = props
14
+ }
15
+
16
+ get docType(): string {
17
+ return this.props.docType;
18
+ }
19
+
20
+ get refNumber(): string {
21
+ return this.props.refNumber;
22
+ }
23
+
24
+ get issueDate(): Date {
25
+ return this.props.issueDate;
26
+ }
27
+
28
+ get code(): string {
29
+ return this.props.code;
30
+ }
31
+
32
+ get reason(): string {
33
+ return this.props.reason;
34
+ }
35
+
36
+ public static create(props: ReferenceInformationProps): ReferenceInformation {
37
+ return new ReferenceInformation({
38
+ ...props,
39
+ })
40
+ }
41
+ }
package/src/ATV/index.ts CHANGED
@@ -5,8 +5,9 @@ import * as parser from 'fast-xml-parser'
5
5
  import qs from 'querystring'
6
6
  import { ConfirmationMessageRaw } from '@src/types/facturaInterfaces'
7
7
  import { ATVOptions, ConfirmationMessage, Mode, SendConfirmationInput, SendResponse } from './types'
8
- import { Command, CreateAndSendDocumentResponse, CreateDocumentInput } from './useCases/createDocument/types'
8
+ import { Command, CreateAndSendDocumentResponse } from './useCases/createDocument/types'
9
9
  import { CreateDocumentCommand } from './useCases/createDocument'
10
+ import { CreateDocumentInput } from './core/CreateDocFactory'
10
11
 
11
12
  export class ATV {
12
13
  public readonly options: ATVOptions
@@ -1,7 +1,8 @@
1
- import { Document, InvoiceDocumentContainer, DetalleServicio, Resumen, Persona } from '@src/types/facturaInterfaces'
1
+ import { Document, InvoiceDocumentContainer, DetalleServicio, Resumen, Persona, InformacionReferencia } from '@src/types/facturaInterfaces'
2
2
  import { Document as DomainDocument } from '../core/Document'
3
3
  import { OrderLine } from '../core/OrderLine'
4
4
  import { Person } from '../core/Person'
5
+ import { ReferenceInformation } from '../core/ReferenceInformation'
5
6
 
6
7
  type AtvFormat = InvoiceDocumentContainer
7
8
 
@@ -86,6 +87,16 @@ const mapPerson = (person: Person): Persona => {
86
87
  return atvPerson;
87
88
  }
88
89
 
90
+ const mapReferenceInformation = (referenceInfo: ReferenceInformation): InformacionReferencia => {
91
+ return {
92
+ TipoDoc: referenceInfo.docType,
93
+ Numero: referenceInfo.refNumber,
94
+ FechaEmision: referenceInfo.issueDate.toISOString(),
95
+ Codigo: referenceInfo.code,
96
+ Razon: referenceInfo.reason
97
+ }
98
+ }
99
+
89
100
  export const mapDocumentToAtvFormat = (docName: string, document: DomainDocument): AtvFormat => {
90
101
  const key = docName
91
102
  const doc: Document = {
@@ -102,6 +113,9 @@ export const mapDocumentToAtvFormat = (docName: string, document: DomainDocument
102
113
  ResumenFactura: mapSummaryInvoice(document.summaryInvoice),
103
114
  Otros: document.others
104
115
  }
116
+ if (document.referenceInformation) {
117
+ doc.InformacionReferencia = mapReferenceInformation(document.referenceInformation);
118
+ }
105
119
  return {
106
120
  [key]: doc
107
121
  }
@@ -1,14 +1,10 @@
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
1
  import { Document } from '@src/ATV/core/Document'
5
- import { Clave } from '@src/ATV/core/Clave'
2
+
6
3
  import { mapDocumentToAtvFormat as mapBillToAtvFormat } from '@src/ATV/mappers/billDocToAtv'
7
4
  import { genXML } from '@src/lib/genXML'
8
- import { CreateAndSendDocumentResponse, CreateDocumentInput, Command } from './types'
5
+ import { CreateAndSendDocumentResponse, Command } from './types'
9
6
  import { ATV } from '@src/ATV'
10
- import { DocumentType } from '@src/ATV/core/DocumentType'
11
- export type { CreateDocumentInput as CreateBillInput } from './types'
7
+ import { CreateDocFactory, CreateDocumentInput } from '@src/ATV/core/CreateDocFactory'
12
8
 
13
9
  const options: { [key: string]: { serviceUrl: string}} = {
14
10
  prod: {
@@ -22,13 +18,16 @@ const options: { [key: string]: { serviceUrl: string}} = {
22
18
  export class CreateDocumentCommand {
23
19
  private readonly serviceUrl: string
24
20
 
21
+ private readonly createDoc: CreateDocFactory;
22
+
25
23
  constructor(scope: ATV) {
26
24
  this.serviceUrl = options[scope.mode].serviceUrl
25
+ this.createDoc = new CreateDocFactory()
27
26
  }
28
27
 
29
28
  public async execute(dto: CreateDocumentInput): Promise<CreateAndSendDocumentResponse> {
30
- const documentName = dto.document.documentName || 'FacturaElectronica'
31
- const document = this.createDocument(dto.document)
29
+ const documentName = dto.document.documentName || 'FacturaElectronica' //TODO NotaDebitoElectronica
30
+ const document = this.createDoc.createDocument(dto.document)
32
31
  const atvDocument = mapBillToAtvFormat(documentName, document)
33
32
  const xml = await genXML(documentName, atvDocument, dto.signatureOptions)
34
33
  const command = await this.createDocumentCommand(document, xml, dto.token)
@@ -65,71 +64,7 @@ export class CreateDocumentCommand {
65
64
  }
66
65
  }
67
66
 
68
- private createDocument(document: CreateDocumentInput['document']): Document {
69
- const documentType = DocumentType.create(document.documentName)
70
- const emitter = this.createEmitter(document.emitter)
71
- const receiver = this.createReceiver(document.receiver)
72
- const clave = this.createClave(document, documentType)
73
- const fullConsective = this.createFullConsecutive(document, documentType)
74
- const orderLines = this.createOrderLines(document)
75
- return Document.create({
76
- clave,
77
- fullConsecutive: fullConsective,
78
- orderLines,
79
- activityCode: document.activityCode,
80
- issueDate: new Date(),
81
- emitter,
82
- receiver,
83
- conditionSale: '01',
84
- paymentMethod: '01'
85
- })
86
- }
87
-
88
- private createEmitter(emitterInput: CreateDocumentInput['document']['emitter']): Person {
89
- return Person.create(emitterInput)
90
- }
91
-
92
- private createReceiver(receiverInput: CreateDocumentInput['document']['receiver']): Person {
93
- return Person.create(receiverInput)
94
- }
95
-
96
- private createOrderLines(dto: CreateDocumentInput['document']): OrderLine[] {
97
- return dto.orderLines.map((orderLine, index) => {
98
- return OrderLine.create({
99
- detail: orderLine.detail,
100
- unitaryPrice: orderLine.unitaryPrice,
101
- lineNumber: orderLine.lineNumber || (index + 1).toString(),
102
- code: orderLine.code,
103
- quantity: orderLine.quantity,
104
- measureUnit: orderLine.measureUnit,
105
- totalAmount: orderLine.totalAmount,
106
- tax: orderLine.tax
107
- })
108
- })
109
- }
110
-
111
- private createFullConsecutive(dto: CreateDocumentInput['document'], docType: DocumentType): FullConsecutive {
112
- return FullConsecutive.create({
113
- consecutiveIdentifier: dto.consecutiveIdentifier,
114
- branch: dto.branch.padStart(3, '0'),
115
- terminal: dto.terminal.padStart(5, '0'),
116
- documentType: docType.value
117
- })
118
- }
119
-
120
- private createClave(dto: CreateDocumentInput['document'], docType: DocumentType): Clave {
121
- return Clave.create({
122
- branch: dto.branch,
123
- ceSituation: dto.ceSituation,
124
- consecutiveIdentifier: dto.consecutiveIdentifier,
125
- countryCode: dto.countryCode,
126
- docKeyType: docType.value,
127
- emitterIdentifier: dto.emitter.identifier.id,
128
- identifierType: dto.emitter.identifier.type, // TODO add default
129
- securityCode: dto.securityCode,
130
- terminal: dto.terminal
131
- })
132
- }
67
+
133
68
 
134
69
  private encodeXML(xmlStr: string): string {
135
70
  const buffer = Buffer.from(xmlStr)