@dwast/verifactu-lib 0.1.0-beta.0 → 0.1.0-beta.2

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 (249) hide show
  1. package/dist/cjs/aeat/client.d.ts +162 -0
  2. package/dist/cjs/aeat/client.d.ts.map +1 -0
  3. package/dist/cjs/aeat/client.js +267 -0
  4. package/dist/cjs/aeat/client.js.map +1 -0
  5. package/dist/cjs/aeat/index.d.ts +3 -0
  6. package/dist/cjs/aeat/index.d.ts.map +1 -0
  7. package/dist/cjs/aeat/index.js +19 -0
  8. package/dist/cjs/aeat/index.js.map +1 -0
  9. package/dist/cjs/aeat/response.d.ts +78 -0
  10. package/dist/cjs/aeat/response.d.ts.map +1 -0
  11. package/dist/cjs/aeat/response.js +117 -0
  12. package/dist/cjs/aeat/response.js.map +1 -0
  13. package/dist/{core → cjs/core}/hash/chain.d.ts +42 -0
  14. package/dist/cjs/core/hash/chain.d.ts.map +1 -0
  15. package/dist/cjs/core/hash/chain.js +167 -0
  16. package/dist/cjs/core/hash/chain.js.map +1 -0
  17. package/dist/cjs/core/hash/index.d.ts.map +1 -0
  18. package/dist/cjs/core/hash/index.js +18 -0
  19. package/dist/cjs/core/hash/index.js.map +1 -0
  20. package/dist/{core → cjs/core}/index.d.ts +2 -0
  21. package/dist/cjs/core/index.d.ts.map +1 -0
  22. package/dist/cjs/core/index.js +23 -0
  23. package/dist/cjs/core/index.js.map +1 -0
  24. package/dist/cjs/core/models/event.d.ts.map +1 -0
  25. package/dist/cjs/core/models/event.js +3 -0
  26. package/dist/{core → cjs/core}/models/event.js.map +1 -1
  27. package/dist/cjs/core/models/index.d.ts.map +1 -0
  28. package/dist/cjs/core/models/index.js +19 -0
  29. package/dist/cjs/core/models/index.js.map +1 -0
  30. package/dist/{core → cjs/core}/models/invoice.d.ts +42 -17
  31. package/dist/cjs/core/models/invoice.d.ts.map +1 -0
  32. package/dist/cjs/core/models/invoice.js +3 -0
  33. package/dist/{core → cjs/core}/models/invoice.js.map +1 -1
  34. package/dist/cjs/core/qr/index.d.ts.map +1 -0
  35. package/dist/cjs/core/qr/index.js +18 -0
  36. package/dist/cjs/core/qr/index.js.map +1 -0
  37. package/dist/cjs/core/qr/qr.d.ts.map +1 -0
  38. package/dist/cjs/core/qr/qr.js +19 -0
  39. package/dist/cjs/core/qr/qr.js.map +1 -0
  40. package/dist/cjs/core/utils/date.d.ts +16 -0
  41. package/dist/cjs/core/utils/date.d.ts.map +1 -0
  42. package/dist/cjs/core/utils/date.js +27 -0
  43. package/dist/cjs/core/utils/date.js.map +1 -0
  44. package/dist/cjs/core/utils/index.d.ts +2 -0
  45. package/dist/cjs/core/utils/index.d.ts.map +1 -0
  46. package/dist/cjs/core/utils/index.js +18 -0
  47. package/dist/cjs/core/utils/index.js.map +1 -0
  48. package/dist/cjs/core/validation/index.d.ts +2 -0
  49. package/dist/cjs/core/validation/index.d.ts.map +1 -0
  50. package/dist/cjs/core/validation/index.js +18 -0
  51. package/dist/cjs/core/validation/index.js.map +1 -0
  52. package/dist/cjs/core/validation/validate.d.ts +18 -0
  53. package/dist/cjs/core/validation/validate.d.ts.map +1 -0
  54. package/dist/cjs/core/validation/validate.js +65 -0
  55. package/dist/cjs/core/validation/validate.js.map +1 -0
  56. package/dist/cjs/core/xml/generator.d.ts +140 -0
  57. package/dist/cjs/core/xml/generator.d.ts.map +1 -0
  58. package/dist/cjs/core/xml/generator.js +269 -0
  59. package/dist/cjs/core/xml/generator.js.map +1 -0
  60. package/dist/cjs/core/xml/index.d.ts.map +1 -0
  61. package/dist/cjs/core/xml/index.js +18 -0
  62. package/dist/cjs/core/xml/index.js.map +1 -0
  63. package/dist/cjs/index.d.ts.map +1 -0
  64. package/dist/cjs/index.js +20 -0
  65. package/dist/cjs/index.js.map +1 -0
  66. package/dist/cjs/integration/accountability.d.ts +41 -0
  67. package/dist/cjs/integration/accountability.d.ts.map +1 -0
  68. package/dist/cjs/integration/accountability.js +92 -0
  69. package/dist/cjs/integration/accountability.js.map +1 -0
  70. package/dist/cjs/integration/index.d.ts +5 -0
  71. package/dist/cjs/integration/index.d.ts.map +1 -0
  72. package/dist/cjs/integration/index.js +21 -0
  73. package/dist/cjs/integration/index.js.map +1 -0
  74. package/dist/cjs/integration/p12.d.ts +58 -0
  75. package/dist/cjs/integration/p12.d.ts.map +1 -0
  76. package/dist/cjs/integration/p12.js +127 -0
  77. package/dist/cjs/integration/p12.js.map +1 -0
  78. package/dist/{integration → cjs/integration}/repository.d.ts +2 -0
  79. package/dist/cjs/integration/repository.d.ts.map +1 -0
  80. package/dist/cjs/integration/repository.js +3 -0
  81. package/dist/cjs/integration/repository.js.map +1 -0
  82. package/dist/{integration → cjs/integration}/service.d.ts +11 -2
  83. package/dist/cjs/integration/service.d.ts.map +1 -0
  84. package/dist/cjs/integration/service.js +230 -0
  85. package/dist/cjs/integration/service.js.map +1 -0
  86. package/dist/cjs/integration/tenant-credentials.d.ts +44 -0
  87. package/dist/cjs/integration/tenant-credentials.d.ts.map +1 -0
  88. package/dist/cjs/integration/tenant-credentials.js +62 -0
  89. package/dist/cjs/integration/tenant-credentials.js.map +1 -0
  90. package/dist/cjs/package.json +3 -0
  91. package/dist/esm/aeat/client.d.ts +162 -0
  92. package/dist/esm/aeat/client.d.ts.map +1 -0
  93. package/dist/esm/aeat/client.js +259 -0
  94. package/dist/esm/aeat/client.js.map +1 -0
  95. package/dist/esm/aeat/index.d.ts +3 -0
  96. package/dist/esm/aeat/index.d.ts.map +1 -0
  97. package/dist/esm/aeat/index.js +3 -0
  98. package/dist/esm/aeat/index.js.map +1 -0
  99. package/dist/esm/aeat/response.d.ts +78 -0
  100. package/dist/esm/aeat/response.d.ts.map +1 -0
  101. package/dist/esm/aeat/response.js +114 -0
  102. package/dist/esm/aeat/response.js.map +1 -0
  103. package/dist/esm/core/hash/chain.d.ts +139 -0
  104. package/dist/esm/core/hash/chain.d.ts.map +1 -0
  105. package/dist/{core → esm/core}/hash/chain.js +37 -0
  106. package/dist/esm/core/hash/chain.js.map +1 -0
  107. package/dist/esm/core/hash/index.d.ts +2 -0
  108. package/dist/esm/core/hash/index.d.ts.map +1 -0
  109. package/dist/esm/core/hash/index.js.map +1 -0
  110. package/dist/esm/core/index.d.ts +7 -0
  111. package/dist/esm/core/index.d.ts.map +1 -0
  112. package/dist/{core → esm/core}/index.js +2 -0
  113. package/dist/esm/core/index.js.map +1 -0
  114. package/dist/esm/core/models/event.d.ts +25 -0
  115. package/dist/esm/core/models/event.d.ts.map +1 -0
  116. package/dist/esm/core/models/event.js.map +1 -0
  117. package/dist/esm/core/models/index.d.ts +3 -0
  118. package/dist/esm/core/models/index.d.ts.map +1 -0
  119. package/dist/esm/core/models/index.js.map +1 -0
  120. package/dist/esm/core/models/invoice.d.ts +115 -0
  121. package/dist/esm/core/models/invoice.d.ts.map +1 -0
  122. package/dist/esm/core/models/invoice.js.map +1 -0
  123. package/dist/esm/core/qr/index.d.ts +2 -0
  124. package/dist/esm/core/qr/index.d.ts.map +1 -0
  125. package/dist/esm/core/qr/index.js.map +1 -0
  126. package/dist/esm/core/qr/qr.d.ts +13 -0
  127. package/dist/esm/core/qr/qr.d.ts.map +1 -0
  128. package/dist/esm/core/qr/qr.js.map +1 -0
  129. package/dist/esm/core/utils/date.d.ts +16 -0
  130. package/dist/esm/core/utils/date.d.ts.map +1 -0
  131. package/dist/esm/core/utils/date.js +24 -0
  132. package/dist/esm/core/utils/date.js.map +1 -0
  133. package/dist/esm/core/utils/index.d.ts +2 -0
  134. package/dist/esm/core/utils/index.d.ts.map +1 -0
  135. package/dist/esm/core/utils/index.js +2 -0
  136. package/dist/esm/core/utils/index.js.map +1 -0
  137. package/dist/esm/core/validation/index.d.ts +2 -0
  138. package/dist/esm/core/validation/index.d.ts.map +1 -0
  139. package/dist/esm/core/validation/index.js +2 -0
  140. package/dist/esm/core/validation/index.js.map +1 -0
  141. package/dist/esm/core/validation/validate.d.ts +18 -0
  142. package/dist/esm/core/validation/validate.d.ts.map +1 -0
  143. package/dist/esm/core/validation/validate.js +62 -0
  144. package/dist/esm/core/validation/validate.js.map +1 -0
  145. package/dist/esm/core/xml/generator.d.ts +140 -0
  146. package/dist/esm/core/xml/generator.d.ts.map +1 -0
  147. package/dist/esm/core/xml/generator.js +259 -0
  148. package/dist/esm/core/xml/generator.js.map +1 -0
  149. package/dist/esm/core/xml/index.d.ts +2 -0
  150. package/dist/esm/core/xml/index.d.ts.map +1 -0
  151. package/dist/esm/core/xml/index.js.map +1 -0
  152. package/dist/esm/index.d.ts +4 -0
  153. package/dist/esm/index.d.ts.map +1 -0
  154. package/dist/esm/index.js.map +1 -0
  155. package/dist/esm/integration/accountability.d.ts +41 -0
  156. package/dist/esm/integration/accountability.d.ts.map +1 -0
  157. package/dist/esm/integration/accountability.js +88 -0
  158. package/dist/esm/integration/accountability.js.map +1 -0
  159. package/dist/esm/integration/index.d.ts +5 -0
  160. package/dist/esm/integration/index.d.ts.map +1 -0
  161. package/dist/esm/integration/index.js +5 -0
  162. package/dist/esm/integration/index.js.map +1 -0
  163. package/dist/esm/integration/p12.d.ts +58 -0
  164. package/dist/esm/integration/p12.d.ts.map +1 -0
  165. package/dist/esm/integration/p12.js +119 -0
  166. package/dist/esm/integration/p12.js.map +1 -0
  167. package/dist/esm/integration/repository.d.ts +79 -0
  168. package/dist/esm/integration/repository.d.ts.map +1 -0
  169. package/dist/esm/integration/repository.js.map +1 -0
  170. package/dist/esm/integration/service.d.ts +45 -0
  171. package/dist/esm/integration/service.d.ts.map +1 -0
  172. package/dist/{integration → esm/integration}/service.js +101 -15
  173. package/dist/esm/integration/service.js.map +1 -0
  174. package/dist/esm/integration/tenant-credentials.d.ts +44 -0
  175. package/dist/esm/integration/tenant-credentials.d.ts.map +1 -0
  176. package/dist/esm/integration/tenant-credentials.js +58 -0
  177. package/dist/esm/integration/tenant-credentials.js.map +1 -0
  178. package/package.json +45 -13
  179. package/readme.md +566 -42
  180. package/src/aeat/client.ts +296 -55
  181. package/src/aeat/index.ts +1 -0
  182. package/src/aeat/response.ts +195 -0
  183. package/src/core/hash/chain.ts +68 -0
  184. package/src/core/index.ts +2 -0
  185. package/src/core/models/invoice.ts +40 -18
  186. package/src/core/utils/date.ts +27 -0
  187. package/src/core/utils/index.ts +1 -0
  188. package/src/core/validation/index.ts +1 -0
  189. package/src/core/validation/validate.ts +71 -0
  190. package/src/core/xml/generator.ts +306 -73
  191. package/src/integration/accountability.ts +125 -0
  192. package/src/integration/index.ts +2 -0
  193. package/src/integration/p12.ts +155 -0
  194. package/src/integration/repository.ts +2 -0
  195. package/src/integration/service.ts +113 -14
  196. package/dist/aeat/client.d.ts +0 -57
  197. package/dist/aeat/client.d.ts.map +0 -1
  198. package/dist/aeat/client.js +0 -87
  199. package/dist/aeat/client.js.map +0 -1
  200. package/dist/aeat/index.d.ts +0 -2
  201. package/dist/aeat/index.d.ts.map +0 -1
  202. package/dist/aeat/index.js +0 -2
  203. package/dist/aeat/index.js.map +0 -1
  204. package/dist/core/hash/chain.d.ts.map +0 -1
  205. package/dist/core/hash/chain.js.map +0 -1
  206. package/dist/core/hash/index.d.ts.map +0 -1
  207. package/dist/core/hash/index.js.map +0 -1
  208. package/dist/core/index.d.ts.map +0 -1
  209. package/dist/core/index.js.map +0 -1
  210. package/dist/core/models/event.d.ts.map +0 -1
  211. package/dist/core/models/index.d.ts.map +0 -1
  212. package/dist/core/models/index.js.map +0 -1
  213. package/dist/core/models/invoice.d.ts.map +0 -1
  214. package/dist/core/qr/index.d.ts.map +0 -1
  215. package/dist/core/qr/index.js.map +0 -1
  216. package/dist/core/qr/qr.d.ts.map +0 -1
  217. package/dist/core/qr/qr.js.map +0 -1
  218. package/dist/core/xml/generator.d.ts +0 -32
  219. package/dist/core/xml/generator.d.ts.map +0 -1
  220. package/dist/core/xml/generator.js +0 -103
  221. package/dist/core/xml/generator.js.map +0 -1
  222. package/dist/core/xml/index.d.ts.map +0 -1
  223. package/dist/core/xml/index.js.map +0 -1
  224. package/dist/index.d.ts.map +0 -1
  225. package/dist/index.js.map +0 -1
  226. package/dist/integration/index.d.ts +0 -3
  227. package/dist/integration/index.d.ts.map +0 -1
  228. package/dist/integration/index.js +0 -3
  229. package/dist/integration/index.js.map +0 -1
  230. package/dist/integration/repository.d.ts.map +0 -1
  231. package/dist/integration/repository.js.map +0 -1
  232. package/dist/integration/service.d.ts.map +0 -1
  233. package/dist/integration/service.js.map +0 -1
  234. /package/dist/{core → cjs/core}/hash/index.d.ts +0 -0
  235. /package/dist/{core → cjs/core}/models/event.d.ts +0 -0
  236. /package/dist/{core → cjs/core}/models/index.d.ts +0 -0
  237. /package/dist/{core → cjs/core}/qr/index.d.ts +0 -0
  238. /package/dist/{core → cjs/core}/qr/qr.d.ts +0 -0
  239. /package/dist/{core → cjs/core}/xml/index.d.ts +0 -0
  240. /package/dist/{index.d.ts → cjs/index.d.ts} +0 -0
  241. /package/dist/{core → esm/core}/hash/index.js +0 -0
  242. /package/dist/{core → esm/core}/models/event.js +0 -0
  243. /package/dist/{core → esm/core}/models/index.js +0 -0
  244. /package/dist/{core → esm/core}/models/invoice.js +0 -0
  245. /package/dist/{core → esm/core}/qr/index.js +0 -0
  246. /package/dist/{core → esm/core}/qr/qr.js +0 -0
  247. /package/dist/{core → esm/core}/xml/index.js +0 -0
  248. /package/dist/{index.js → esm/index.js} +0 -0
  249. /package/dist/{integration → esm/integration}/repository.js +0 -0
@@ -0,0 +1,155 @@
1
+ import forge from 'node-forge';
2
+
3
+ /**
4
+ * Un campo (bag) del `.p12`.
5
+ */
6
+ export interface P12Bag {
7
+ /** Tipo del bag (certBag, keyBag, pkcs8ShroudedKeyBag, ...). */
8
+ type: string;
9
+ /** Contenido en formato PEM (si es un certificado o clave). */
10
+ pem?: string;
11
+ /** Valor en bruto (si no es PEM). */
12
+ value?: unknown;
13
+ }
14
+
15
+ /**
16
+ * Contenido completo de un `.p12`, con todos sus campos.
17
+ */
18
+ export interface P12Content {
19
+ /** Todos los bags encontrados, en orden. */
20
+ bags: P12Bag[];
21
+ /** Certificados en PEM (conveniencia). */
22
+ certificates: string[];
23
+ /** Claves privadas en PEM (conveniencia). */
24
+ keys: string[];
25
+ }
26
+
27
+ /**
28
+ * Lee un certificado `.p12`/`.pfx` e itera todos sus campos (bags),
29
+ * devolviéndolos todos. La librería no interpreta qué campo es cada cosa:
30
+ * simplemente expone el contenido para que la aplicación lo use.
31
+ *
32
+ * @param buffer Contenido del archivo `.p12`/`.pfx`.
33
+ * @param password Contraseña del `.p12`.
34
+ */
35
+ export function readP12(buffer: Buffer, password: string): P12Content {
36
+ const asn1 = forge.asn1.fromDer(forge.util.createBuffer(new Uint8Array(buffer)));
37
+ const p12 = forge.pkcs12.pkcs12FromAsn1(asn1, password);
38
+
39
+ const bags: P12Bag[] = [];
40
+ const certificates: string[] = [];
41
+ const keys: string[] = [];
42
+
43
+ p12.safeContents.forEach((safe) => {
44
+ safe.safeBags.forEach((bag) => {
45
+ const type = bag.type ?? 'unknown';
46
+ let pem: string | undefined;
47
+ let value: unknown;
48
+
49
+ if (bag.cert) {
50
+ pem = forge.pki.certificateToPem(bag.cert);
51
+ certificates.push(pem);
52
+ } else if (bag.key) {
53
+ pem = forge.pki.privateKeyToPem(bag.key);
54
+ keys.push(pem);
55
+ } else {
56
+ value = bag.attributes;
57
+ }
58
+
59
+ bags.push({ type, pem, value });
60
+ });
61
+ });
62
+
63
+ return { bags, certificates, keys };
64
+ }
65
+
66
+ /**
67
+ * Extrae el NIF de un certificado en PEM.
68
+ *
69
+ * El NIF suele aparecer en el `serialNumber` (p. ej. `IDCES-74654958V`) o como
70
+ * primer token del `commonName` (p. ej. `74654958V ANTONIO JOSE RECHE`).
71
+ * Devuelve `null` si no se puede determinar.
72
+ */
73
+ export function extractNifFromCertificate(pem: string): string | null {
74
+ try {
75
+ const cert = forge.pki.certificateFromPem(pem);
76
+ const attrs = cert.subject.attributes;
77
+
78
+ // serialNumber: "IDCES-74654958V" o directamente "B12345678"
79
+ const serial = attrs.find((a) => a.name === 'serialNumber')?.value;
80
+ if (serial) {
81
+ const m = String(serial).match(/IDCES-(\S+)/i) ?? String(serial).match(/^([A-Z0-9]{8,9})/i);
82
+ if (m && m[1]) return m[1];
83
+ }
84
+
85
+ // commonName: "74654958V ANTONIO JOSE RECHE (R: B18579458)"
86
+ const cn = attrs.find((a) => a.name === 'commonName')?.value;
87
+ if (cn) {
88
+ const m = String(cn).match(/^([A-Z0-9]{8,9})/i);
89
+ if (m && m[1]) return m[1];
90
+ }
91
+
92
+ return null;
93
+ } catch {
94
+ return null;
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Información de un certificado en PEM: NIF y nombre/razón del titular.
100
+ */
101
+ export interface CertificateInfo {
102
+ /** NIF del titular del certificado. */
103
+ nif: string;
104
+ /** Nombre o razón social del titular. */
105
+ nombreRazon: string;
106
+ }
107
+
108
+ /**
109
+ * Extrae el NIF y el nombre/razón del titular de un certificado en PEM.
110
+ *
111
+ * El NIF se obtiene del `serialNumber` (p. ej. `IDCES-74654958V`) o del primer
112
+ * token del `commonName`. El nombre se compone de `givenName` + `surname`, o
113
+ * del `commonName` sin el prefijo de NIF. Devuelve `null` si no se puede
114
+ * determinar el NIF.
115
+ */
116
+ export function extractCertificateInfo(pem: string): CertificateInfo | null {
117
+ try {
118
+ const cert = forge.pki.certificateFromPem(pem);
119
+ const attrs = cert.subject.attributes;
120
+
121
+ // NIF
122
+ const serial = attrs.find((a) => a.name === 'serialNumber')?.value;
123
+ let nif: string | null = null;
124
+ if (serial) {
125
+ const m = String(serial).match(/IDCES-(\S+)/i) ?? String(serial).match(/^([A-Z0-9]{8,9})/i);
126
+ if (m && m[1]) nif = m[1];
127
+ }
128
+ if (!nif) {
129
+ const cn = attrs.find((a) => a.name === 'commonName')?.value;
130
+ if (cn) {
131
+ const m = String(cn).match(/^([A-Z0-9]{8,9})/i);
132
+ if (m && m[1]) nif = m[1];
133
+ }
134
+ }
135
+ if (!nif) return null;
136
+
137
+ // Nombre: givenName + surname, o commonName sin el NIF.
138
+ const given = attrs.find((a) => a.name === 'givenName')?.value;
139
+ const surname = attrs.find((a) => a.name === 'surname')?.value;
140
+ let nombreRazon = '';
141
+ if (given) nombreRazon += given;
142
+ if (surname) nombreRazon += (nombreRazon ? ' ' : '') + surname;
143
+ nombreRazon = nombreRazon.trim();
144
+ if (!nombreRazon) {
145
+ const cn = attrs.find((a) => a.name === 'commonName')?.value;
146
+ if (cn) {
147
+ nombreRazon = String(cn!).replace(/^[A-Z0-9]{8,9}\s*/, '').split(' (R:')[0]?.trim() ?? '';
148
+ }
149
+ }
150
+
151
+ return { nif, nombreRazon };
152
+ } catch {
153
+ return null;
154
+ }
155
+ }
@@ -19,6 +19,8 @@ export interface StoredRecord {
19
19
  id: string;
20
20
  /** Referencia a la factura (serie + número). */
21
21
  invoiceId: string;
22
+ /** NIF del emisor de la factura. */
23
+ emisorNif: string;
22
24
  /** XML Verifactu generado. */
23
25
  xml: string;
24
26
  /** Hash del propio registro (huella). */
@@ -1,10 +1,19 @@
1
1
  import type { Invoice } from '../core/models/invoice.js';
2
- import { generateInvoiceXml, generateAnulacionXml } from '../core/xml/generator.js';
3
- import { computeRegistroAlta, computeRegistroAnulacion } from '../core/hash/chain.js';
2
+ import { generateInvoiceXml, generateSuministroXml, buildCabecera, generateAnulacionXml, generateEventoXml, type EventoInput } from '../core/xml/generator.js';
3
+ import { computeRegistroAlta, computeRegistroAnulacion, computeRegistroEvento } from '../core/hash/chain.js';
4
4
  import { buildQrPayload } from '../core/qr/qr.js';
5
+ import { nowIsoWithOffset } from '../core/utils/date.js';
6
+ import { validateInvoice } from '../core/validation/validate.js';
7
+ import { extractCertificateInfo } from './p12.js';
5
8
  import type { VerifactuClient } from '../aeat/client.js';
6
9
  import type { VerifactuRepository, StoredRecord } from './repository.js';
7
10
 
11
+ /** Convierte `YYYY-MM-DD` a `DD-MM-YYYY` (formato XSD `fecha` de AEAT). */
12
+ function toDdMmYyyy(iso: string): string {
13
+ const [y, m, d] = iso.split('-');
14
+ return `${d}-${m}-${y}`;
15
+ }
16
+
8
17
  /**
9
18
  * Servicio de orquestación de Verifactu.
10
19
  *
@@ -16,6 +25,7 @@ export class VerifactuService {
16
25
  constructor(
17
26
  private readonly repository: VerifactuRepository,
18
27
  private readonly client: VerifactuClient,
28
+ private readonly certificatePem?: string,
19
29
  ) {}
20
30
 
21
31
  /**
@@ -23,12 +33,25 @@ export class VerifactuService {
23
33
  * el registro y lo envía a AEAT, persistiendo la respuesta.
24
34
  */
25
35
  async registerInvoice(invoice: Invoice): Promise<StoredRecord> {
36
+ // 0. Validar la factura antes de generar el XML.
37
+ const validation = validateInvoice(invoice);
38
+ if (!validation.valid) {
39
+ throw new Error(`Factura inválida: ${validation.errors.join('; ')}`);
40
+ }
41
+
26
42
  // 1. Obtener el hash del último registro para encadenar.
27
43
  const last = await this.repository.getLastRecord();
28
44
  const previousHash = last?.hash ?? null;
29
45
 
30
46
  // 2. Generar XML y calcular la huella (hash) del registro.
31
- const xml = generateInvoiceXml(invoice, previousHash);
47
+ const registroAltaXml = generateInvoiceXml(invoice, previousHash);
48
+ const cabecera = buildCabecera(
49
+ { nombreRazon: invoice.emisor.nombreRazon, nif: invoice.emisor.nif },
50
+ this.certificatePem,
51
+ extractCertificateInfo,
52
+ );
53
+ const xml = generateSuministroXml(registroAltaXml, cabecera);
54
+ const fechaHoraHusoGenRegistro = nowIsoWithOffset();
32
55
  const hash = computeRegistroAlta({
33
56
  idEmisorFactura: invoice.emisor.nif,
34
57
  numSerieFactura: `${invoice.id.serie ?? ''}${invoice.id.numero}`,
@@ -37,7 +60,7 @@ export class VerifactuService {
37
60
  cuotaTotal: invoice.desglose.cuotaTotal.toFixed(2),
38
61
  importeTotal: invoice.desglose.importeTotal.toFixed(2),
39
62
  huellaAnterior: previousHash,
40
- fechaHoraHusoGenRegistro: new Date().toISOString(),
63
+ fechaHoraHusoGenRegistro,
41
64
  });
42
65
 
43
66
  // 3. Persistir el registro como PENDING.
@@ -45,6 +68,7 @@ export class VerifactuService {
45
68
  const record: StoredRecord = {
46
69
  id: `${invoice.id.serie ?? ''}${invoice.id.numero}`,
47
70
  invoiceId: `${invoice.id.serie ?? ''}${invoice.id.numero}`,
71
+ emisorNif: invoice.emisor.nif,
48
72
  xml,
49
73
  hash,
50
74
  previousHash,
@@ -79,7 +103,7 @@ export class VerifactuService {
79
103
  * Genera un registro de anulación que referencia la factura anulada,
80
104
  * lo envía a AEAT y marca la factura original como ANNULLED.
81
105
  */
82
- async annulInvoice(invoiceId: string): Promise<StoredRecord> {
106
+ async annulInvoice(invoiceId: string, invoice?: Invoice): Promise<StoredRecord> {
83
107
  // 1. Obtener la factura original (para su huella) y el último registro.
84
108
  const original = await this.repository.getRecord(invoiceId);
85
109
  if (!original) {
@@ -87,30 +111,46 @@ export class VerifactuService {
87
111
  }
88
112
  const last = await this.repository.getLastRecord();
89
113
  const previousHash = last?.hash ?? null;
114
+ const fechaHoraHusoGenRegistro = nowIsoWithOffset();
115
+ const fechaExpedicionFacturaAnulada = toDdMmYyyy(
116
+ invoice?.id.fechaExpedicion ?? new Date().toISOString().slice(0, 10),
117
+ );
118
+ const sistemaInformatico = invoice?.sistemaInformatico ?? {
119
+ nombreRazon: 'Sistema',
120
+ nif: original.emisorNif,
121
+ nombreSistemaInformatico: 'SIF',
122
+ idSistemaInformatico: '01',
123
+ version: '1.0',
124
+ numeroInstalacion: '1',
125
+ };
90
126
 
91
127
  // 2. Generar XML de anulación y calcular la huella.
128
+ const hash = computeRegistroAnulacion({
129
+ idEmisorFacturaAnulada: original.emisorNif,
130
+ numSerieFacturaAnulada: original.invoiceId,
131
+ fechaExpedicionFacturaAnulada,
132
+ huellaAnterior: previousHash,
133
+ fechaHoraHusoGenRegistro,
134
+ });
92
135
  const xml = generateAnulacionXml(
93
136
  {
94
- idEmisorFacturaAnulada: original.invoiceId,
137
+ idEmisorFacturaAnulada: original.emisorNif,
95
138
  numSerieFacturaAnulada: original.invoiceId,
96
- fechaExpedicionFacturaAnulada: new Date().toISOString().slice(0, 10),
139
+ fechaExpedicionFacturaAnulada,
97
140
  huellaFacturaAnulada: original.hash,
141
+ sistemaInformatico,
142
+ fechaHoraHusoGenRegistro,
143
+ huella: hash,
98
144
  },
99
145
  previousHash,
100
146
  );
101
- const hash = computeRegistroAnulacion({
102
- idEmisorFacturaAnulada: original.invoiceId,
103
- numSerieFacturaAnulada: original.invoiceId,
104
- fechaExpedicionFacturaAnulada: new Date().toISOString().slice(0, 10),
105
- huellaAnterior: previousHash,
106
- fechaHoraHusoGenRegistro: new Date().toISOString(),
107
- });
108
147
 
109
148
  // 3. Persistir el registro de anulación como PENDING.
110
149
  const now = new Date().toISOString();
111
150
  const record: StoredRecord = {
112
151
  id: `${invoiceId}-ANUL`,
113
152
  invoiceId,
153
+ emisorNif: original.emisorNif,
114
154
  xml,
115
155
  hash,
116
156
  previousHash,
@@ -155,4 +195,63 @@ export class VerifactuService {
155
195
  // 2. Emitir la factura corregida como un nuevo alta.
156
196
  return this.registerInvoice(correctedInvoice);
157
197
  }
198
+
199
+ /**
200
+ * Registra un evento (RegistroEvento) ante AEAT.
201
+ *
202
+ * Genera el XML del evento, calcula su huella encadenada con el último
203
+ * registro, persiste el evento y lo envía a AEAT.
204
+ */
205
+ async registerEvent(evento: EventoInput): Promise<StoredRecord> {
206
+ // 1. Obtener el hash del último registro para encadenar.
207
+ const last = await this.repository.getLastRecord();
208
+ const previousHash = last?.hash ?? null;
209
+
210
+ // 2. Generar XML y calcular la huella del evento.
211
+ const si = evento.sistemaInformatico;
212
+ const hash = computeRegistroEvento({
213
+ nifSistemaInformatico: si.nif,
214
+ id: '',
215
+ idSistemaInformatico: si.idSistemaInformatico,
216
+ version: si.version,
217
+ numeroInstalacion: si.numeroInstalacion,
218
+ nifObligado: evento.obligadoEmision.nif,
219
+ tipoEvento: evento.tipoEvento,
220
+ huellaAnterior: previousHash,
221
+ fechaHoraHusoGenEvento: evento.fechaHoraHusoGenEvento,
222
+ });
223
+ const xml = generateEventoXml({ ...evento, huellaEvento: hash });
224
+
225
+ // 3. Persistir el evento.
226
+ const now = new Date().toISOString();
227
+ const record: StoredRecord = {
228
+ id: `EV-${evento.tipoEvento}-${Date.now()}`,
229
+ invoiceId: evento.obligadoEmision.nif,
230
+ emisorNif: evento.obligadoEmision.nif,
231
+ xml,
232
+ hash,
233
+ previousHash,
234
+ status: 'PENDING',
235
+ createdAt: now,
236
+ updatedAt: now,
237
+ };
238
+ await this.repository.saveRecord(record);
239
+
240
+ // 4. Enviar a AEAT y persistir la respuesta.
241
+ const result = await this.client.sendRecord(xml);
242
+ await this.repository.saveResponse({
243
+ id: `${record.id}-${Date.now()}`,
244
+ recordId: record.id,
245
+ operationId: result.operationId,
246
+ status: result.status,
247
+ message: result.message,
248
+ receivedAt: new Date().toISOString(),
249
+ });
250
+
251
+ // 5. Actualizar el estado.
252
+ const status = result.status === 'OK' ? 'CONFIRMED' : 'REJECTED';
253
+ await this.repository.updateRecordStatus(record.id, status);
254
+
255
+ return { ...record, status };
256
+ }
158
257
  }
@@ -1,57 +0,0 @@
1
- /**
2
- * Cliente para los servicios web de AEAT (Verifactu).
3
- *
4
- * Capa de red, separada del núcleo puro. Depende de credenciales y entornos
5
- * (producción vs. pruebas), por lo que no debe acoplarse a la lógica de
6
- * negocio.
7
- *
8
- * NOTA: los endpoints y el formato de petición/respuesta deben ajustarse a
9
- * la documentación oficial de la AEAT (remisión voluntaria / bajo
10
- * requerimiento). Este cliente expone una implementación base con `fetch`
11
- * y rutas configurables.
12
- */
13
- export interface VerifactuClientConfig {
14
- /** URL base del servicio AEAT. */
15
- baseUrl: string;
16
- /** Token de autenticación (OAuth) o certificado. */
17
- authToken?: string;
18
- /** Ruta del endpoint de envío de registros. */
19
- sendPath?: string;
20
- /** Ruta del endpoint de consulta de estado. */
21
- statusPath?: string;
22
- /** Timeout de petición en ms. */
23
- timeoutMs?: number;
24
- }
25
- export interface SendResult {
26
- /** Identificador de la operación devuelto por AEAT. */
27
- operationId: string;
28
- /** Estado de la respuesta. */
29
- status: 'OK' | 'ERROR';
30
- /** Mensaje de la AEAT. */
31
- message?: string;
32
- /** Código de error de AEAT (si lo hay). */
33
- errorCode?: string;
34
- /** Cuerpo completo de la respuesta (para auditoría). */
35
- rawResponse?: string;
36
- }
37
- /**
38
- * Cliente de servicios AEAT para Verifactu.
39
- */
40
- export declare class VerifactuClient {
41
- private readonly config;
42
- constructor(config: VerifactuClientConfig);
43
- /**
44
- * Envía un registro (factura o evento) a AEAT.
45
- */
46
- sendRecord(xml: string): Promise<SendResult>;
47
- /**
48
- * Consulta el estado de una operación enviada.
49
- */
50
- getOperationStatus(operationId: string): Promise<SendResult>;
51
- /**
52
- * Parsea la respuesta de AEAT. La estructura exacta depende del servicio;
53
- * este es un mapeo base que el consumidor puede sobrescribir.
54
- */
55
- protected parseResponse(raw: string, httpStatus: number): SendResult;
56
- }
57
- //# sourceMappingURL=client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/aeat/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,qBAAqB;IACpC,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC;IACvB,0BAA0B;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAUD;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;gBAE5B,MAAM,EAAE,qBAAqB;IASzC;;OAEG;IACG,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IA0BlD;;OAEG;IACG,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAkBlE;;;OAGG;IACH,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,UAAU;CAqBrE"}
@@ -1,87 +0,0 @@
1
- /**
2
- * Cliente de servicios AEAT para Verifactu.
3
- */
4
- export class VerifactuClient {
5
- config;
6
- constructor(config) {
7
- this.config = {
8
- sendPath: '/verifactu/registro',
9
- statusPath: '/verifactu/estado',
10
- timeoutMs: 10_000,
11
- ...config,
12
- };
13
- }
14
- /**
15
- * Envía un registro (factura o evento) a AEAT.
16
- */
17
- async sendRecord(xml) {
18
- const url = `${this.config.baseUrl}${this.config.sendPath}`;
19
- const headers = {
20
- 'Content-Type': 'application/xml',
21
- Accept: 'application/json',
22
- };
23
- if (this.config.authToken) {
24
- headers.Authorization = `Bearer ${this.config.authToken}`;
25
- }
26
- const controller = new AbortController();
27
- const timer = setTimeout(() => controller.abort(), this.config.timeoutMs);
28
- try {
29
- const res = await fetch(url, {
30
- method: 'POST',
31
- headers,
32
- body: xml,
33
- signal: controller.signal,
34
- });
35
- const raw = await res.text();
36
- return this.parseResponse(raw, res.status);
37
- }
38
- finally {
39
- clearTimeout(timer);
40
- }
41
- }
42
- /**
43
- * Consulta el estado de una operación enviada.
44
- */
45
- async getOperationStatus(operationId) {
46
- const url = `${this.config.baseUrl}${this.config.statusPath}/${encodeURIComponent(operationId)}`;
47
- const headers = { Accept: 'application/json' };
48
- if (this.config.authToken) {
49
- headers.Authorization = `Bearer ${this.config.authToken}`;
50
- }
51
- const controller = new AbortController();
52
- const timer = setTimeout(() => controller.abort(), this.config.timeoutMs);
53
- try {
54
- const res = await fetch(url, { method: 'GET', headers, signal: controller.signal });
55
- const raw = await res.text();
56
- return this.parseResponse(raw, res.status);
57
- }
58
- finally {
59
- clearTimeout(timer);
60
- }
61
- }
62
- /**
63
- * Parsea la respuesta de AEAT. La estructura exacta depende del servicio;
64
- * este es un mapeo base que el consumidor puede sobrescribir.
65
- */
66
- parseResponse(raw, httpStatus) {
67
- let operationId = '';
68
- let status = httpStatus >= 200 && httpStatus < 300 ? 'OK' : 'ERROR';
69
- let message;
70
- let errorCode;
71
- try {
72
- const json = JSON.parse(raw);
73
- operationId = String(json.operationId ?? json.id ?? '');
74
- if (json.status === 'OK' || json.status === 'ERROR') {
75
- status = json.status;
76
- }
77
- message = json.message;
78
- errorCode = json.errorCode;
79
- }
80
- catch {
81
- // Respuesta no JSON: se conserva el cuerpo como mensaje.
82
- message = raw;
83
- }
84
- return { operationId, status, message, errorCode, rawResponse: raw };
85
- }
86
- }
87
- //# sourceMappingURL=client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/aeat/client.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export * from './client.js';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/aeat/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
@@ -1,2 +0,0 @@
1
- export * from './client.js';
2
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/aeat/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"chain.d.ts","sourceRoot":"","sources":["../../../src/core/hash/chain.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAEpD;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC,GAAG,MAAM,CAO5F;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,sCAAsC;IACtC,eAAe,EAAE,MAAM,CAAC;IACxB,oCAAoC;IACpC,eAAe,EAAE,MAAM,CAAC;IACxB,yCAAyC;IACzC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iDAAiD;IACjD,wBAAwB,EAAE,MAAM,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,sDAAsD;IACtD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,4CAA4C;IAC5C,sBAAsB,EAAE,MAAM,CAAC;IAC/B,iDAAiD;IACjD,6BAA6B,EAAE,MAAM,CAAC;IACtC,2CAA2C;IAC3C,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iDAAiD;IACjD,wBAAwB,EAAE,MAAM,CAAC;CAClC;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAWxE;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,sBAAsB,GAAG,MAAM,CAQlF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAEpE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,sBAAsB,GAAG,MAAM,CAE9E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAE1F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,sBAAsB,EAC7B,YAAY,EAAE,MAAM,GACnB,OAAO,CAET;AAED;;GAEG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,MAAM,CAAK;IAEnB,2EAA2E;IAC3E,IAAI,QAAQ,IAAI,MAAM,GAAG,IAAI,CAE5B;IAED,mDAAmD;IACnD,IAAI,KAAK,IAAI,MAAM,CAElB;IAED;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,GAAG,MAAM;IAOlE;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,sBAAsB,EAAE,gBAAgB,CAAC,GAAG,MAAM;IAO5E,0BAA0B;IAC1B,KAAK,IAAI,IAAI;CAId"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"chain.js","sourceRoot":"","sources":["../../../src/core/hash/chain.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/hash/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/hash/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../../src/core/models/event.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,WAAW,GAAG,cAAc,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB,sBAAsB;IACtB,IAAI,EAAE,SAAS,CAAC;IAChB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/models/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/models/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"invoice.d.ts","sourceRoot":"","sources":["../../../src/core/models/invoice.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,sBAAsB;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,eAAe,EAAE,MAAM,CAAC;IACxB,qCAAqC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GACnB,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,IAAI,CAAC;AAET;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,2BAA2B;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,sBAAsB;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,yBAAyB;IACzB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,gDAAgD;IAChD,aAAa,EAAE,MAAM,CAAC;IACtB,uBAAuB;IACvB,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,sCAAsC;IACtC,eAAe,EAAE,qBAAqB,EAAE,CAAC;IACzC,iCAAiC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,oCAAoC;IACpC,EAAE,EAAE,SAAS,CAAC;IACd,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,QAAQ,EAAE,QAAQ,CAAC;IACnB,uBAAuB;IACvB,WAAW,EAAE,WAAW,CAAC;IACzB,wBAAwB;IACxB,YAAY,EAAE,YAAY,CAAC;IAC3B,mCAAmC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/qr/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/qr/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"qr.d.ts","sourceRoot":"","sources":["../../../src/core/qr/qr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,SAA8D,EACrE,WAAW,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACvC,MAAM,CAGR"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"qr.js","sourceRoot":"","sources":["../../../src/core/qr/qr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAY,EACZ,OAAO,GAAG,2DAA2D,EACrE,cAAsC,EAAE;IAExC,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,IAAI,EAAE,GAAG,WAAW,EAAE,CAAC,CAAC;IAC7D,OAAO,GAAG,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;AAC3C,CAAC"}
@@ -1,32 +0,0 @@
1
- import type { Invoice } from '../models/invoice.js';
2
- /**
3
- * Datos de la factura que se anula.
4
- */
5
- export interface AnulacionInput {
6
- /** NIF del emisor de la factura anulada. */
7
- idEmisorFacturaAnulada: string;
8
- /** Número y serie de la factura anulada. */
9
- numSerieFacturaAnulada: string;
10
- /** Fecha de expedición de la factura anulada. */
11
- fechaExpedicionFacturaAnulada: string;
12
- /** Huella (hash) de la factura anulada. */
13
- huellaFacturaAnulada: string;
14
- }
15
- /**
16
- * Genera el XML Verifactu de una factura (registro de alta).
17
- *
18
- * Estructura basada en el RD 1007/2023 y la documentación técnica de la
19
- * AEAT. NOTA: el esquema XSD oficial debe validarse antes de producción;
20
- * este esqueleto refleja los bloques principales (IDFactura, IDEmisorFactura,
21
- * TipoFactura, TipoDesglose, Desglose, CuotaTotal, Encadenamiento, Huella).
22
- */
23
- export declare function generateInvoiceXml(invoice: Invoice, previousHash: string | null): string;
24
- /**
25
- * Genera el XML Verifactu de un registro de anulación.
26
- *
27
- * Referencia la factura anulada (IDFactura + Huella) y encadena con el hash
28
- * anterior. Estructura basada en el RD 1007/2023; validar contra el XSD
29
- * oficial antes de producción.
30
- */
31
- export declare function generateAnulacionXml(anulacion: AnulacionInput, previousHash: string | null): string;
32
- //# sourceMappingURL=generator.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../../src/core/xml/generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,sBAAsB,EAAE,MAAM,CAAC;IAC/B,4CAA4C;IAC5C,sBAAsB,EAAE,MAAM,CAAC;IAC/B,iDAAiD;IACjD,6BAA6B,EAAE,MAAM,CAAC;IACtC,2CAA2C;IAC3C,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAqBD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAwDxF;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,cAAc,EACzB,YAAY,EAAE,MAAM,GAAG,IAAI,GAC1B,MAAM,CAqBR"}