@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.
- package/.eslintignore +3 -0
- package/.eslintrc.js +23 -23
- package/.github/dependabot.yml +11 -0
- package/.github/workflows/ci.yml +14 -12
- package/README.md +9 -2
- package/__tests__/stubs/commonExpectedXml.xml +14 -16
- package/__tests__/stubs/createDocument.data.ts +18 -1
- package/__tests__/stubs/frontendRequest.stub.ts +0 -1
- package/__tests__/stubs/token.stub.ts +9 -9
- package/__tests__/tests/ATV/__snapshots__/create-document.test.ts.snap +1 -1
- package/__tests__/tests/ATV/create-document.test.ts +8 -8
- package/__tests__/tests/ATV/create-receptor-message.test.ts +41 -36
- package/dist/src/ATV/core/CreateDocFactory.d.ts +11 -3
- package/dist/src/ATV/core/CreateDocFactory.js +3 -3
- package/dist/src/ATV/core/CreateDocFactory.js.map +1 -1
- package/dist/src/ATV/core/Document.d.ts +2 -2
- package/dist/src/ATV/core/Document.js +7 -4
- package/dist/src/ATV/core/Document.js.map +1 -1
- package/dist/src/ATV/core/DocumentType.d.ts +2 -3
- package/dist/src/ATV/core/DocumentType.js +1 -0
- package/dist/src/ATV/core/DocumentType.js.map +1 -1
- package/dist/src/ATV/core/FullConsecutive.d.ts +2 -1
- package/dist/src/ATV/core/FullConsecutive.js.map +1 -1
- package/dist/src/ATV/core/OrderLine.js +8 -1
- package/dist/src/ATV/core/OrderLine.js.map +1 -1
- package/dist/src/ATV/core/Person.d.ts +2 -2
- package/dist/src/ATV/core/ReceptorConsecutive.js.map +1 -1
- package/dist/src/ATV/core/ReferenceInformation.js.map +1 -1
- package/dist/src/ATV/core/types.d.ts +3 -2
- package/dist/src/ATV/core/types.js.map +1 -1
- package/dist/src/ATV/index.d.ts +2 -2
- package/dist/src/ATV/index.js +2 -2
- package/dist/src/ATV/mappers/billDocToAtv.js +32 -26
- package/dist/src/ATV/mappers/billDocToAtv.js.map +1 -1
- package/dist/src/ATV/types.d.ts +1 -1
- package/dist/src/ATV/useCases/createDocument/index.js +5 -9
- package/dist/src/ATV/useCases/createDocument/index.js.map +1 -1
- package/dist/src/ATV/useCases/createDocument/types.d.ts +4 -3
- package/dist/src/ATV/useCases/createReceptorMessage/index.d.ts +6 -5
- package/dist/src/ATV/useCases/createReceptorMessage/index.js +3 -3
- package/dist/src/ATV/useCases/createReceptorMessage/index.js.map +1 -1
- package/dist/src/helpers/comprobantes.js +10 -1
- package/dist/src/helpers/comprobantes.js.map +1 -1
- package/dist/src/lib/genClave/index.d.ts +8 -1
- package/dist/src/lib/genClave/index.js +5 -0
- package/dist/src/lib/genClave/index.js.map +1 -1
- package/dist/src/lib/genXML/index.js +6 -4
- package/dist/src/lib/genXML/index.js.map +1 -1
- package/dist/src/lib/genXML/sigXML/index.js +7 -4
- package/dist/src/lib/genXML/sigXML/index.js.map +1 -1
- package/dist/src/services/getToken/GetToken.js +0 -3
- package/dist/src/services/getToken/GetToken.js.map +1 -1
- package/dist/src/services/getToken/__tests__/GetToken.test.js +0 -1
- package/dist/src/services/getToken/__tests__/GetToken.test.js.map +1 -1
- package/dist/src/types/facturaInterfaces.d.ts +3 -3
- package/dist/src/xmlSchemaHeaderMap.d.ts +70 -0
- package/dist/src/xmlSchemaHeaderMap.js +30 -0
- package/dist/src/xmlSchemaHeaderMap.js.map +1 -0
- package/doc/atv-structures/4.3/FacturaElectronica_V4.3.xsd.xml +1633 -478
- package/doc/atv-structures/4.4/TiqueteElectronico_V4.4.xsd.xml +2817 -0
- package/doc/json-schemas/4.4/fe.json +544 -0
- package/doc/json-schemas/4.4/te.json +420 -0
- package/doc/testing.md +27 -0
- package/examples/README.md +10 -35
- package/examples/atvAccept.ts +18 -9
- package/examples/consultXML.ts +1 -0
- package/examples/{createAndSend.ts → createAndSendFE.ts} +11 -8
- package/examples/createAndSendTE.ts +73 -0
- package/examples/createCreditNote.ts +10 -6
- package/examples/createDebitNote.ts +2 -0
- package/examples/getToken.ts +2 -0
- package/package.json +3 -2
- package/src/ATV/core/CreateDocFactory.ts +32 -23
- package/src/ATV/core/Document.ts +7 -7
- package/src/ATV/core/DocumentType.ts +10 -3
- package/src/ATV/core/FullConsecutive.ts +2 -1
- package/src/ATV/core/OrderLine.ts +7 -1
- package/src/ATV/core/Person.ts +2 -2
- package/src/ATV/core/ReceptorConsecutive.ts +16 -16
- package/src/ATV/core/ReferenceInformation.ts +6 -6
- package/src/ATV/core/types.ts +7 -6
- package/src/ATV/index.ts +3 -3
- package/src/ATV/mappers/billDocToAtv.ts +35 -15
- package/src/ATV/types.ts +1 -1
- package/src/ATV/useCases/createDocument/index.ts +8 -8
- package/src/ATV/useCases/createDocument/types.ts +5 -6
- package/src/ATV/useCases/createReceptorMessage/index.ts +94 -93
- package/src/helpers/comprobantes.ts +10 -1
- package/src/lib/genClave/index.ts +10 -3
- package/src/lib/genXML/index.ts +3 -1
- package/src/lib/genXML/sigXML/index.ts +6 -3
- package/src/services/getToken/GetToken.ts +0 -3
- package/src/services/getToken/__tests__/GetToken.test.ts +0 -1
- package/src/types/facturaInterfaces.ts +3 -4
- package/src/xmlSchemaHeaderMap.ts +37 -0
- package/tools/readXML.ts +2 -0
- package/tools/xsdToJsonSchema.ts +1 -0
- package/tsconfig.json +1 -0
- package/dist/src/ATV/core/documentNames.types.d.ts +0 -1
- package/dist/src/ATV/core/documentNames.types.js +0 -3
- package/dist/src/ATV/core/documentNames.types.js.map +0 -1
- package/dist/src/lib/genXML/xmlConfig.d.ts +0 -55
- package/dist/src/lib/genXML/xmlConfig.js +0 -42
- package/dist/src/lib/genXML/xmlConfig.js.map +0 -1
- package/src/ATV/core/documentNames.types.ts +0 -6
- 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 {
|
|
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',
|
|
19
|
+
console.log('requestStub consecutivo', FEInputExample.consecutiveIdentifier)
|
|
21
20
|
|
|
22
21
|
// TODO: dynamic param --identifier 1 args[x]
|
|
23
|
-
|
|
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
|
-
...
|
|
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)
|
package/examples/getToken.ts
CHANGED
|
@@ -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.
|
|
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.
|
|
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
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
|
125
|
+
identifierType: dto.emitter.identifier.type || '01',
|
|
117
126
|
securityCode: dto.securityCode,
|
|
118
127
|
terminal: dto.terminal
|
|
119
128
|
})
|
package/src/ATV/core/Document.ts
CHANGED
|
@@ -11,7 +11,7 @@ export type InvoiceProps = {
|
|
|
11
11
|
fullConsecutive: FullConsecutive;
|
|
12
12
|
issueDate: Date; // FechaEmision
|
|
13
13
|
emitter: Person; // Emisor
|
|
14
|
-
receiver
|
|
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: '
|
|
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
|
|
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
|
|
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
|
|
150
|
+
totalTaxes: previousValue.totalTaxes + (currentValue.tax?.amount ?? 0)
|
|
151
151
|
}
|
|
152
152
|
}, { totalAmount: 0, totalTaxes: 0 })
|
|
153
153
|
}
|
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
|
|
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
|
|
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
|
|
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({
|
package/src/ATV/core/Person.ts
CHANGED
|
@@ -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(): '
|
|
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
|
-
|
|
9
|
+
private props: ReceptorConsecutiveProps
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
constructor(props: ReceptorConsecutiveProps) {
|
|
12
|
+
this.props = props
|
|
13
|
+
}
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
get value(): string {
|
|
16
|
+
return Object.values(this.props).join('')
|
|
17
|
+
}
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
}
|
package/src/ATV/core/types.ts
CHANGED
|
@@ -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:
|
|
12
|
+
emitterIdentifierType: PersonProps['identifier']['type'];
|
|
11
13
|
receptorIdentifier: string;
|
|
12
|
-
receptorIdentifierType:
|
|
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:
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|