kassza 0.12.0 → 0.13.0
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/README.md +283 -18
- package/agents/README.md +20 -5
- package/agents/api.md +165 -2
- package/agents/pitfalls.md +16 -3
- package/agents/recipes.md +215 -45
- package/agents/skills/kassza/SKILL.md +11 -8
- package/dist/cli.cjs +552 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +552 -0
- package/dist/client-6MkeuFqD.d.ts +268 -0
- package/dist/client-B5FryKxJ.d.cts +268 -0
- package/dist/{client-CsmGIFRS.cjs → client-C-PdfL_P.cjs} +235 -597
- package/dist/{client-CL3fuH6A.js → client-CfaS1-Jx.js} +35 -403
- package/dist/context-BxQlIlug.d.ts +425 -0
- package/dist/context-DXNbTPwz.d.cts +425 -0
- package/dist/{create-once-CqdYmQD8.js → create-once-Cz621l8r.js} +3 -3
- package/dist/{create-once-D0pwuenl.cjs → create-once-DgMtKKcG.cjs} +8 -2
- package/dist/{crypto-B8lERvR1.cjs → crypto-Dpn4FHQ6.cjs} +9 -0
- package/dist/{crypto-DK_osBVy.js → crypto-usDg8L2K.js} +4 -1
- package/dist/data-link/index.cjs +232 -0
- package/dist/data-link/index.d.cts +79 -0
- package/dist/data-link/index.d.ts +79 -0
- package/dist/data-link/index.js +224 -0
- package/dist/delegation/index.cjs +34 -33
- package/dist/delegation/index.d.cts +2 -1
- package/dist/delegation/index.d.ts +2 -1
- package/dist/delegation/index.js +3 -2
- package/dist/get-Byc9T5WO.d.cts +151 -0
- package/dist/get-Byc9T5WO.d.ts +151 -0
- package/dist/get-Csm2n0rZ.cjs +445 -0
- package/dist/get-DT3JEgQ6.js +380 -0
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +3 -3
- package/dist/{issue-BsyYdrIG.cjs → issue-AGRohSm7.cjs} +48 -665
- package/dist/{issue-C6Fcjvln.js → issue-DtSLpVdJ.js} +5 -502
- package/dist/mcp/index.cjs +10 -0
- package/dist/mcp/index.d.cts +71 -0
- package/dist/mcp/index.d.ts +71 -0
- package/dist/mcp/index.js +2 -0
- package/dist/money/index.cjs +1 -1
- package/dist/money/index.js +1 -1
- package/dist/{money-DrhGkWHW.cjs → money-BxytJW6f.cjs} +25 -9
- package/dist/{money-DAA7OwiO.js → money-t7uy1n91.js} +25 -9
- package/dist/nav/index.cjs +1046 -0
- package/dist/nav/index.d.cts +247 -0
- package/dist/nav/index.d.ts +247 -0
- package/dist/nav/index.js +1012 -0
- package/dist/nav-BEwcX7-N.cjs +203 -0
- package/dist/nav-CK1WgYo7.js +156 -0
- package/dist/parse-BJj-aqKy.cjs +380 -0
- package/dist/parse-C608ehqM.js +291 -0
- package/dist/payments/barion.cjs +1 -1
- package/dist/payments/barion.d.cts +2 -2
- package/dist/payments/barion.d.ts +2 -2
- package/dist/payments/barion.js +1 -1
- package/dist/payments/index.cjs +2 -2
- package/dist/payments/index.d.cts +3 -3
- package/dist/payments/index.d.ts +3 -3
- package/dist/payments/index.js +2 -2
- package/dist/payments/paypal.cjs +1 -1
- package/dist/payments/paypal.d.cts +2 -2
- package/dist/payments/paypal.d.ts +2 -2
- package/dist/payments/paypal.js +1 -1
- package/dist/payments/revolut.cjs +2 -2
- package/dist/payments/revolut.d.cts +2 -2
- package/dist/payments/revolut.d.ts +2 -2
- package/dist/payments/revolut.js +2 -2
- package/dist/payments/simplepay.cjs +2 -2
- package/dist/payments/simplepay.d.cts +2 -2
- package/dist/payments/simplepay.d.ts +2 -2
- package/dist/payments/simplepay.js +2 -2
- package/dist/payments/stripe.cjs +2 -2
- package/dist/payments/stripe.d.cts +2 -2
- package/dist/payments/stripe.d.ts +2 -2
- package/dist/payments/stripe.js +2 -2
- package/dist/reports/index.cjs +11 -164
- package/dist/reports/index.js +1 -154
- package/dist/request-body-CH6ZGOrq.cjs +34 -0
- package/dist/request-body-uZHMRlQr.js +29 -0
- package/dist/serialize-BXOww1Uq.cjs +286 -0
- package/dist/serialize-DSE_o9RK.js +215 -0
- package/dist/server-C6PoNkdD.cjs +1557 -0
- package/dist/server-Cd8HB661.js +1504 -0
- package/dist/testing/index.cjs +1476 -3
- package/dist/testing/index.d.cts +194 -2
- package/dist/testing/index.d.ts +194 -2
- package/dist/testing/index.js +1477 -6
- package/dist/{types-COf1LAD-.d.cts → types-BVeR7KyU.d.cts} +1 -1
- package/dist/{types-COf1LAD-.d.ts → types-BVeR7KyU.d.ts} +1 -1
- package/dist/{webhook-C76bV-4R.cjs → webhook-81giRMdQ.cjs} +3 -25
- package/dist/{webhook-q2OzNwd7.d.ts → webhook-CpCMHhn2.d.ts} +1 -1
- package/dist/{webhook-CfaDgcL0.d.cts → webhook-CpMJuP6c.d.cts} +1 -1
- package/dist/{webhook-D4lvtex1.js → webhook-CrEGohbg.js} +3 -25
- package/llms.txt +4 -4
- package/package.json +43 -1
- package/dist/client-CickRRFr.d.ts +0 -838
- package/dist/client-DvWZoX_E.d.cts +0 -838
package/dist/testing/index.js
CHANGED
|
@@ -1,8 +1,1479 @@
|
|
|
1
|
-
import { i as resolveInvoice,
|
|
2
|
-
import { n as SzamlazzError } from "../errors-DLrb0g64.js";
|
|
3
|
-
import {
|
|
4
|
-
import { n as
|
|
5
|
-
import {
|
|
1
|
+
import { c as emitDocumentEvent, i as resolveInvoice, l as AGENT_ACTIONS, t as createReceiptOnce } from "../create-once-Cz621l8r.js";
|
|
2
|
+
import { n as SzamlazzError, t as AGENT_ERROR_CODES } from "../errors-DLrb0g64.js";
|
|
3
|
+
import { i as encodeUtf8, n as bytesToBase64 } from "../binary-D0M9U2MD.js";
|
|
4
|
+
import { a as optionalEl, c as childNumber, d as findChildren, f as parseXml, i as formatXmlNumber, l as childText, n as buildXmlDocument, r as el, s as childBoolean, u as findChild } from "../serialize-DSE_o9RK.js";
|
|
5
|
+
import { n as toAgentDate, r as toBudapestDate } from "../dates-CXyj7Azy.js";
|
|
6
|
+
import { n as decimalPlaces, r as roundMoney } from "../rounding-BLyHjjI5.js";
|
|
7
|
+
import { i as isHuf, t as NUMERIC_VAT_RATES } from "../vat-v_dcWCto.js";
|
|
8
|
+
import { i as summarizeItems } from "../money-t7uy1n91.js";
|
|
9
|
+
import { _ as createInvoiceOnce, a as calculateReceiptItems, i as buildCreateReceiptXml, n as issueForPayment, p as convertReceiptToInvoice } from "../issue-DtSLpVdJ.js";
|
|
10
|
+
//#region src/testing/fake-agent-http.ts
|
|
11
|
+
const XML_CONTENT_TYPE = "application/xml; charset=UTF-8";
|
|
12
|
+
const TEXT_CONTENT_TYPE = "text/plain; charset=UTF-8";
|
|
13
|
+
const PDF_CONTENT_TYPE = "application/pdf";
|
|
14
|
+
const ERROR_ROOTS = {
|
|
15
|
+
invoice: "xmlszamlavalasz",
|
|
16
|
+
receipt: "xmlnyugtavalasz",
|
|
17
|
+
"receipt-send": "xmlnyugtasendvalasz",
|
|
18
|
+
proforma: "xmlszamladbkdelvalasz"
|
|
19
|
+
};
|
|
20
|
+
function encodeHeaderValue(value) {
|
|
21
|
+
return encodeURIComponent(value).replace(/%20/g, "+");
|
|
22
|
+
}
|
|
23
|
+
function xmlResponse(xml, headers = {}) {
|
|
24
|
+
return {
|
|
25
|
+
status: 200,
|
|
26
|
+
headers: {
|
|
27
|
+
"content-type": XML_CONTENT_TYPE,
|
|
28
|
+
...headers
|
|
29
|
+
},
|
|
30
|
+
body: xml
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function textResponse(text, headers = {}, status = 200) {
|
|
34
|
+
return {
|
|
35
|
+
status,
|
|
36
|
+
headers: {
|
|
37
|
+
"content-type": TEXT_CONTENT_TYPE,
|
|
38
|
+
...headers
|
|
39
|
+
},
|
|
40
|
+
body: text
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function pdfResponse(pdf, headers = {}) {
|
|
44
|
+
return {
|
|
45
|
+
status: 200,
|
|
46
|
+
headers: {
|
|
47
|
+
"content-type": PDF_CONTENT_TYPE,
|
|
48
|
+
...headers
|
|
49
|
+
},
|
|
50
|
+
body: pdf
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function serverErrorResponse() {
|
|
54
|
+
return {
|
|
55
|
+
status: 500,
|
|
56
|
+
headers: { "content-type": "text/html; charset=UTF-8" },
|
|
57
|
+
body: "<!DOCTYPE html><html><body><h1>500 Internal Server Error</h1></body></html>"
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function namespaceOf(root) {
|
|
61
|
+
return `http://www.szamlazz.hu/${root}`;
|
|
62
|
+
}
|
|
63
|
+
function xmlDocument(root, children) {
|
|
64
|
+
return buildXmlDocument({
|
|
65
|
+
root,
|
|
66
|
+
namespace: namespaceOf(root),
|
|
67
|
+
children
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function errorHeaders(failure) {
|
|
71
|
+
return {
|
|
72
|
+
szlahu_error: encodeHeaderValue(failure.message),
|
|
73
|
+
...failure.code === void 0 ? {} : { szlahu_error_code: String(failure.code) }
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function errorText(failure) {
|
|
77
|
+
return `[ERR] ${failure.code === void 0 ? "" : `[${failure.code}] `}${failure.message}\n----------\nkassza hamis Agent\n`;
|
|
78
|
+
}
|
|
79
|
+
function errorResponse(style, failure) {
|
|
80
|
+
if (style === "text") return textResponse(errorText(failure), errorHeaders(failure));
|
|
81
|
+
return xmlResponse(xmlDocument(ERROR_ROOTS[style], [
|
|
82
|
+
el("sikeres", false),
|
|
83
|
+
optionalEl("hibakod", failure.code),
|
|
84
|
+
el("hibauzenet", failure.message)
|
|
85
|
+
]), style === "invoice" ? errorHeaders(failure) : {});
|
|
86
|
+
}
|
|
87
|
+
function invoiceResultHeaders(fields) {
|
|
88
|
+
const headers = {};
|
|
89
|
+
if (fields.number !== void 0) headers.szlahu_szamlaszam = encodeHeaderValue(fields.number);
|
|
90
|
+
if (fields.netTotal !== void 0) headers.szlahu_nettovegosszeg = formatXmlNumber(fields.netTotal);
|
|
91
|
+
if (fields.grossTotal !== void 0) headers.szlahu_bruttovegosszeg = formatXmlNumber(fields.grossTotal);
|
|
92
|
+
if (fields.outstanding !== void 0) headers.szlahu_kintlevoseg = formatXmlNumber(fields.outstanding);
|
|
93
|
+
if (fields.paymentMethod !== void 0) headers.szlahu_fizetesmod = encodeHeaderValue(fields.paymentMethod);
|
|
94
|
+
return headers;
|
|
95
|
+
}
|
|
96
|
+
function invoiceResultResponse(fields, version) {
|
|
97
|
+
const headers = invoiceResultHeaders(fields);
|
|
98
|
+
if (version === 2) return xmlResponse(xmlDocument("xmlszamlavalasz", [
|
|
99
|
+
el("sikeres", true),
|
|
100
|
+
optionalEl("szamlaszam", fields.number),
|
|
101
|
+
optionalEl("szamlanetto", fields.netTotal),
|
|
102
|
+
optionalEl("szamlabrutto", fields.grossTotal),
|
|
103
|
+
optionalEl("kintlevoseg", fields.outstanding),
|
|
104
|
+
optionalEl("pdf", fields.pdf && bytesToBase64(fields.pdf))
|
|
105
|
+
]), headers);
|
|
106
|
+
if (fields.pdf) return pdfResponse(fields.pdf, headers);
|
|
107
|
+
return textResponse(`xmlagentresponse=DONE${fields.number === void 0 ? "" : `;${fields.number}`}\n`, headers);
|
|
108
|
+
}
|
|
109
|
+
function toFetchResponse(response) {
|
|
110
|
+
const body = typeof response.body === "string" ? response.body : new Blob([response.body]);
|
|
111
|
+
return new Response(body, {
|
|
112
|
+
status: response.status,
|
|
113
|
+
headers: response.headers
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
//#endregion
|
|
117
|
+
//#region src/testing/fake-agent-state.ts
|
|
118
|
+
var FakeAgentFailure = class extends Error {
|
|
119
|
+
name = "FakeAgentFailure";
|
|
120
|
+
code;
|
|
121
|
+
constructor(code, message) {
|
|
122
|
+
super(message);
|
|
123
|
+
this.code = code;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
function agentFailure(code, message) {
|
|
127
|
+
return new FakeAgentFailure(code, message ?? AGENT_ERROR_CODES[code]?.message ?? `Hiba (${code}).`);
|
|
128
|
+
}
|
|
129
|
+
function nextCounter(state, key) {
|
|
130
|
+
const next = (state.counters.get(key) ?? 0) + 1;
|
|
131
|
+
state.counters.set(key, next);
|
|
132
|
+
return next;
|
|
133
|
+
}
|
|
134
|
+
function today(state) {
|
|
135
|
+
return toBudapestDate(state.now());
|
|
136
|
+
}
|
|
137
|
+
function nextDocumentNumber(state, series) {
|
|
138
|
+
const year = today(state).slice(0, 4);
|
|
139
|
+
return `${series}-${year}-${nextCounter(state, `${series}|${year}`)}`;
|
|
140
|
+
}
|
|
141
|
+
function nextDocumentId(state) {
|
|
142
|
+
return nextCounter(state, "#id");
|
|
143
|
+
}
|
|
144
|
+
function fakePdf(label) {
|
|
145
|
+
return encodeUtf8(`%PDF-1.4\n%kassza hamis Agent: ${label}\n%%EOF\n`);
|
|
146
|
+
}
|
|
147
|
+
function taxpayerKey(value) {
|
|
148
|
+
return value.replace(/\D/g, "").slice(0, 8);
|
|
149
|
+
}
|
|
150
|
+
//#endregion
|
|
151
|
+
//#region src/testing/fake-agent-items.ts
|
|
152
|
+
const SERVER_VAT_CODES = /* @__PURE__ */ new Set([
|
|
153
|
+
"TAM",
|
|
154
|
+
"AAM",
|
|
155
|
+
"EU",
|
|
156
|
+
"EUK",
|
|
157
|
+
"MAA",
|
|
158
|
+
"F.AFA",
|
|
159
|
+
"K.AFA",
|
|
160
|
+
"ÁKK",
|
|
161
|
+
"TAHK",
|
|
162
|
+
"TEHK",
|
|
163
|
+
"EUT",
|
|
164
|
+
"EUKT",
|
|
165
|
+
"HO",
|
|
166
|
+
"EUE",
|
|
167
|
+
"EUFADE",
|
|
168
|
+
"EUFAD37",
|
|
169
|
+
"ATK",
|
|
170
|
+
"NAM",
|
|
171
|
+
"EAM",
|
|
172
|
+
"KBAUK",
|
|
173
|
+
"KBAET"
|
|
174
|
+
]);
|
|
175
|
+
const NUMERIC_RATES = new Set(NUMERIC_VAT_RATES);
|
|
176
|
+
const AMOUNT_FIELDS = {
|
|
177
|
+
invoice: {
|
|
178
|
+
net: "nettoErtek",
|
|
179
|
+
vat: "afaErtek",
|
|
180
|
+
gross: "bruttoErtek"
|
|
181
|
+
},
|
|
182
|
+
receipt: {
|
|
183
|
+
net: "netto",
|
|
184
|
+
vat: "afa",
|
|
185
|
+
gross: "brutto"
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
const HUF_TOLERANCE = 2;
|
|
189
|
+
const FOREIGN_TOLERANCE = .02;
|
|
190
|
+
const SUM_EPSILON = 1e-6;
|
|
191
|
+
const RECEIPT_DECIMALS = 2;
|
|
192
|
+
const TOTAL_DECIMALS = 6;
|
|
193
|
+
function xmlFailure(detail) {
|
|
194
|
+
return new FakeAgentFailure(57, `XML beolvasási hiba: ${detail}`);
|
|
195
|
+
}
|
|
196
|
+
function requiredText$2(element, name, position) {
|
|
197
|
+
const value = childText(element, name);
|
|
198
|
+
if (value === void 0) throw xmlFailure(`hiányzik a(z) ${position}. tétel <${name}> eleme.`);
|
|
199
|
+
return value;
|
|
200
|
+
}
|
|
201
|
+
function requiredNumber(element, name, position) {
|
|
202
|
+
const value = childNumber(element, name);
|
|
203
|
+
if (value === void 0) throw xmlFailure(`a(z) ${position}. tétel <${name}> eleme hiányzik vagy nem szám.`);
|
|
204
|
+
return value;
|
|
205
|
+
}
|
|
206
|
+
function parseVat(raw, itemName) {
|
|
207
|
+
const numeric = Number(raw.replace(",", "."));
|
|
208
|
+
if (Number.isFinite(numeric) && NUMERIC_RATES.has(numeric)) return { rate: numeric };
|
|
209
|
+
if (SERVER_VAT_CODES.has(raw)) return {
|
|
210
|
+
rate: 0,
|
|
211
|
+
code: raw
|
|
212
|
+
};
|
|
213
|
+
throw new FakeAgentFailure(395, `Érvénytelen áfakulcs: ${raw}. Termék: ${itemName}`);
|
|
214
|
+
}
|
|
215
|
+
function ledgerOf(element) {
|
|
216
|
+
const revenue = childText(element, "arbevetel");
|
|
217
|
+
const vat = childText(element, "afa");
|
|
218
|
+
return revenue === void 0 && vat === void 0 ? void 0 : {
|
|
219
|
+
revenue,
|
|
220
|
+
vat
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function parseItem(element, kind, position) {
|
|
224
|
+
const fields = AMOUNT_FIELDS[kind];
|
|
225
|
+
const name = requiredText$2(element, "megnevezes", position);
|
|
226
|
+
const vat = parseVat(requiredText$2(element, "afakulcs", position), name);
|
|
227
|
+
return {
|
|
228
|
+
name,
|
|
229
|
+
identifier: childText(element, "azonosito"),
|
|
230
|
+
quantity: requiredNumber(element, "mennyiseg", position),
|
|
231
|
+
unit: requiredText$2(element, "mennyisegiEgyseg", position),
|
|
232
|
+
netUnitPrice: requiredNumber(element, "nettoEgysegar", position),
|
|
233
|
+
vatRate: vat.rate,
|
|
234
|
+
vatCode: vat.code,
|
|
235
|
+
netAmount: requiredNumber(element, fields.net, position),
|
|
236
|
+
vatAmount: requiredNumber(element, fields.vat, position),
|
|
237
|
+
grossAmount: requiredNumber(element, fields.gross, position),
|
|
238
|
+
comment: childText(element, "megjegyzes"),
|
|
239
|
+
ledger: kind === "receipt" ? ledgerOf(findChild(element, "fokonyv")) : void 0
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
function parseItems(root, kind) {
|
|
243
|
+
const elements = findChildren(findChild(root, "tetelek"), "tetel");
|
|
244
|
+
if (elements.length === 0) throw xmlFailure("legalább egy tételt (<tetel>) meg kell adni.");
|
|
245
|
+
return elements.map((element, index) => parseItem(element, kind, index + 1));
|
|
246
|
+
}
|
|
247
|
+
function amountFailure(code, item) {
|
|
248
|
+
return new FakeAgentFailure(code, `${{
|
|
249
|
+
259: "A tétel nettó értéke nem megfelelő; nettó érték = nettó egységár x mennyiség.",
|
|
250
|
+
260: "A tétel áfa értéke nem megfelelő; áfa érték = tétel nettó értéke x áfakulcs mértéke / 100.",
|
|
251
|
+
261: "A tétel bruttó értéke nem megfelelő; bruttó érték = tétel nettó értéke + tétel áfa értéke.",
|
|
252
|
+
363: "A tétel bruttó értékének egész számnak kell lennie.",
|
|
253
|
+
364: "A tétel nettó értéke maximum 2 tizedes jegyet tartalmazhat.",
|
|
254
|
+
365: "A tétel áfa értéke maximum 2 tizedes jegyet tartalmazhat."
|
|
255
|
+
}[code] ?? "Hibás tételösszeg."} Termék: ${item.name}`);
|
|
256
|
+
}
|
|
257
|
+
function netMismatch(item, tolerance) {
|
|
258
|
+
return Math.abs(item.netUnitPrice * item.quantity - item.netAmount) > tolerance;
|
|
259
|
+
}
|
|
260
|
+
function vatMismatch(item, tolerance) {
|
|
261
|
+
return Math.abs(item.netAmount * item.vatRate / 100 - item.vatAmount) > tolerance;
|
|
262
|
+
}
|
|
263
|
+
function grossMismatch(item) {
|
|
264
|
+
return Math.abs(item.netAmount + item.vatAmount - item.grossAmount) > SUM_EPSILON;
|
|
265
|
+
}
|
|
266
|
+
function assertInvoiceItems(items, currency, hasMarginVat) {
|
|
267
|
+
const tolerance = isHuf(currency) ? HUF_TOLERANCE : FOREIGN_TOLERANCE;
|
|
268
|
+
items.forEach((item, index) => {
|
|
269
|
+
if (netMismatch(item, tolerance)) throw amountFailure(259, item);
|
|
270
|
+
if (!hasMarginVat(index) && vatMismatch(item, tolerance)) throw amountFailure(260, item);
|
|
271
|
+
if (grossMismatch(item)) throw amountFailure(261, item);
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
function assertReceiptItems(items, currency) {
|
|
275
|
+
if (!isHuf(currency)) return;
|
|
276
|
+
for (const item of items) {
|
|
277
|
+
if (grossMismatch(item)) throw amountFailure(261, item);
|
|
278
|
+
if (!Number.isInteger(item.grossAmount)) throw amountFailure(363, item);
|
|
279
|
+
if (decimalPlaces(item.netAmount) > RECEIPT_DECIMALS) throw amountFailure(364, item);
|
|
280
|
+
if (decimalPlaces(item.vatAmount) > RECEIPT_DECIMALS) throw amountFailure(365, item);
|
|
281
|
+
if (netMismatch(item, HUF_TOLERANCE)) throw amountFailure(259, item);
|
|
282
|
+
if (vatMismatch(item, HUF_TOLERANCE)) throw amountFailure(260, item);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
function sum(values) {
|
|
286
|
+
return roundMoney(values.reduce((total, value) => total + value, 0), TOTAL_DECIMALS);
|
|
287
|
+
}
|
|
288
|
+
function totalsOf(items) {
|
|
289
|
+
return {
|
|
290
|
+
net: sum(items.map((item) => item.netAmount)),
|
|
291
|
+
vat: sum(items.map((item) => item.vatAmount)),
|
|
292
|
+
gross: sum(items.map((item) => item.grossAmount))
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
function vatGroupsOf(items) {
|
|
296
|
+
const groups = /* @__PURE__ */ new Map();
|
|
297
|
+
for (const item of items) {
|
|
298
|
+
const key = `${item.vatCode ?? ""}|${item.vatRate}`;
|
|
299
|
+
groups.set(key, [...groups.get(key) ?? [], item]);
|
|
300
|
+
}
|
|
301
|
+
return [...groups.values()].flatMap((group) => {
|
|
302
|
+
const [first] = group;
|
|
303
|
+
if (!first) return [];
|
|
304
|
+
const totals = totalsOf(group);
|
|
305
|
+
return [{
|
|
306
|
+
vatRate: first.vatRate,
|
|
307
|
+
vatCode: first.vatCode,
|
|
308
|
+
net: totals.net,
|
|
309
|
+
vat: totals.vat,
|
|
310
|
+
gross: totals.gross
|
|
311
|
+
}];
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
function negateItem(item) {
|
|
315
|
+
return {
|
|
316
|
+
...item,
|
|
317
|
+
quantity: -item.quantity,
|
|
318
|
+
netAmount: -item.netAmount,
|
|
319
|
+
vatAmount: -item.vatAmount,
|
|
320
|
+
grossAmount: -item.grossAmount
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
function negateTotals(totals) {
|
|
324
|
+
return {
|
|
325
|
+
net: -totals.net,
|
|
326
|
+
vat: -totals.vat,
|
|
327
|
+
gross: -totals.gross
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
function outstandingOf(gross, paid) {
|
|
331
|
+
return gross > 0 ? Math.max(0, sum([gross, -paid])) : 0;
|
|
332
|
+
}
|
|
333
|
+
//#endregion
|
|
334
|
+
//#region src/testing/fake-agent-account.ts
|
|
335
|
+
const NAV_API_NAMESPACE = "http://schemas.nav.gov.hu/OSA/3.0/api";
|
|
336
|
+
const TAXPAYER_ID_PATTERN = /^\d{8}$/;
|
|
337
|
+
const CONNECT_PRINCIPAL_MESSAGES = {
|
|
338
|
+
created: "DONE",
|
|
339
|
+
ownerInviteResent: "Már létező fiók, nincs fiókgazdája. Fiókgazdai meghívó (megbízott számlakibocsátás) email újraküldve.",
|
|
340
|
+
joinRequestSent: "Már létező fiók fiókgazdával. Csatlakozási kérelmet küldtünk a fiókgazdának.",
|
|
341
|
+
joinRequestResent: "Már létező fiók fiókgazdával. A csatlakozási kérelem emailt újraküldtük a fiókgazdának."
|
|
342
|
+
};
|
|
343
|
+
function authenticateDelegate(state, username, password) {
|
|
344
|
+
const delegate = state.delegates.get(username);
|
|
345
|
+
if (!delegate) return false;
|
|
346
|
+
if (delegate.password !== password || !delegate.approved) throw agentFailure(3);
|
|
347
|
+
if (state.principals.get(delegate.taxpayerId)?.state !== "owned") throw agentFailure(250);
|
|
348
|
+
return true;
|
|
349
|
+
}
|
|
350
|
+
function authenticate(state, credentials) {
|
|
351
|
+
const { agentKey, username, password } = credentials;
|
|
352
|
+
if (agentKey !== void 0) {
|
|
353
|
+
if (!state.config.strictAuth || state.config.agentKeys.has(agentKey)) return;
|
|
354
|
+
throw agentFailure(3);
|
|
355
|
+
}
|
|
356
|
+
if (username === void 0 || password === void 0) throw agentFailure(3);
|
|
357
|
+
if (authenticateDelegate(state, username, password)) return;
|
|
358
|
+
if (!state.config.strictAuth || state.users.get(username) === password) return;
|
|
359
|
+
throw agentFailure(3);
|
|
360
|
+
}
|
|
361
|
+
function acceptDelegation(state, taxNumber) {
|
|
362
|
+
const key = taxpayerKey(taxNumber);
|
|
363
|
+
const principal = state.principals.get(key);
|
|
364
|
+
if (!principal) throw new TypeError(`Nincs ilyen megbízói fiók a hamis Agentben: ${taxNumber}`);
|
|
365
|
+
state.principals.set(key, {
|
|
366
|
+
...principal,
|
|
367
|
+
state: "owned"
|
|
368
|
+
});
|
|
369
|
+
for (const [email, delegate] of state.delegates) if (delegate.taxpayerId === key) state.delegates.set(email, {
|
|
370
|
+
...delegate,
|
|
371
|
+
approved: true
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
function addressNode(taxpayer) {
|
|
375
|
+
const { address } = taxpayer;
|
|
376
|
+
if (!address) return void 0;
|
|
377
|
+
return el("taxpayerAddressList", [el("taxpayerAddressItem", [el("taxpayerAddressType", "HQ"), el("taxpayerAddress", [
|
|
378
|
+
el("countryCode", "HU"),
|
|
379
|
+
el("postalCode", address.postalCode),
|
|
380
|
+
el("city", address.city),
|
|
381
|
+
optionalEl("streetName", address.streetName),
|
|
382
|
+
optionalEl("publicPlaceCategory", address.publicPlaceCategory),
|
|
383
|
+
optionalEl("number", address.number)
|
|
384
|
+
])])]);
|
|
385
|
+
}
|
|
386
|
+
function taxpayerDataNode(taxpayerId, taxpayer) {
|
|
387
|
+
return el("taxpayerData", [
|
|
388
|
+
el("taxpayerName", taxpayer.name),
|
|
389
|
+
optionalEl("taxpayerShortName", taxpayer.shortName),
|
|
390
|
+
el("taxNumberDetail", [
|
|
391
|
+
el("taxpayerId", taxpayerId),
|
|
392
|
+
optionalEl("vatCode", taxpayer.vatCode),
|
|
393
|
+
optionalEl("countyCode", taxpayer.countyCode)
|
|
394
|
+
]),
|
|
395
|
+
optionalEl("incorporation", taxpayer.incorporation),
|
|
396
|
+
addressNode(taxpayer)
|
|
397
|
+
]);
|
|
398
|
+
}
|
|
399
|
+
function handleQueryTaxpayer(state, request) {
|
|
400
|
+
const taxpayerId = childText(request.root, "torzsszam");
|
|
401
|
+
if (taxpayerId === void 0 || !TAXPAYER_ID_PATTERN.test(taxpayerId)) throw xmlFailure("a <torzsszam> elemben 8 jegyű adószám-törzsszám kell.");
|
|
402
|
+
const taxpayer = state.config.taxpayers[taxpayerId];
|
|
403
|
+
const valid = taxpayer !== void 0 && taxpayer.valid !== false;
|
|
404
|
+
const timestamp = state.now().toISOString();
|
|
405
|
+
return xmlResponse(buildXmlDocument({
|
|
406
|
+
root: "QueryTaxpayerResponse",
|
|
407
|
+
namespace: NAV_API_NAMESPACE,
|
|
408
|
+
children: [
|
|
409
|
+
el("header", [
|
|
410
|
+
el("requestId", `KASSZAFAKE${nextCounter(state, "#nav")}`),
|
|
411
|
+
el("timestamp", timestamp),
|
|
412
|
+
el("requestVersion", "3.0"),
|
|
413
|
+
el("headerVersion", "1.0")
|
|
414
|
+
]),
|
|
415
|
+
el("result", [el("funcCode", "OK")]),
|
|
416
|
+
el("infoDate", timestamp),
|
|
417
|
+
el("taxpayerValidity", valid),
|
|
418
|
+
valid && taxpayer && taxpayerDataNode(taxpayerId, taxpayer)
|
|
419
|
+
]
|
|
420
|
+
}));
|
|
421
|
+
}
|
|
422
|
+
function connectResponse(message) {
|
|
423
|
+
const encoded = encodeHeaderValue(message);
|
|
424
|
+
return textResponse(`xmlagentresponse=${encoded}\n`, { XML_AGENT_RESPONSE: encoded });
|
|
425
|
+
}
|
|
426
|
+
function handleConnectPrincipal(state, request) {
|
|
427
|
+
const company = findChild(request.root, "cegMb");
|
|
428
|
+
const user = findChild(request.root, "usrMb");
|
|
429
|
+
const taxNumber = childText(company, "cegtaxnumber");
|
|
430
|
+
if (taxNumber === void 0) throw xmlFailure("hiányzik a(z) <cegMb/cegtaxnumber> elem.");
|
|
431
|
+
const key = taxpayerKey(taxNumber);
|
|
432
|
+
const principal = state.principals.get(key);
|
|
433
|
+
const email = childText(user, "usremail");
|
|
434
|
+
const password = childText(user, "usrpassword");
|
|
435
|
+
if (email === void 0 || password === void 0) throw xmlFailure("hiányzik a(z) <usrMb/usremail> vagy <usrMb/usrpassword> elem.");
|
|
436
|
+
if (!principal) {
|
|
437
|
+
state.principals.set(key, {
|
|
438
|
+
state: "unowned",
|
|
439
|
+
joinRequests: 0
|
|
440
|
+
});
|
|
441
|
+
state.delegates.set(email, {
|
|
442
|
+
taxpayerId: key,
|
|
443
|
+
password,
|
|
444
|
+
approved: true
|
|
445
|
+
});
|
|
446
|
+
return connectResponse(CONNECT_PRINCIPAL_MESSAGES.created);
|
|
447
|
+
}
|
|
448
|
+
if (principal.state === "unowned") return connectResponse(CONNECT_PRINCIPAL_MESSAGES.ownerInviteResent);
|
|
449
|
+
if (!state.delegates.has(email)) state.delegates.set(email, {
|
|
450
|
+
taxpayerId: key,
|
|
451
|
+
password,
|
|
452
|
+
approved: false
|
|
453
|
+
});
|
|
454
|
+
state.principals.set(key, {
|
|
455
|
+
...principal,
|
|
456
|
+
joinRequests: principal.joinRequests + 1
|
|
457
|
+
});
|
|
458
|
+
return connectResponse(principal.joinRequests === 0 ? CONNECT_PRINCIPAL_MESSAGES.joinRequestSent : CONNECT_PRINCIPAL_MESSAGES.joinRequestResent);
|
|
459
|
+
}
|
|
460
|
+
//#endregion
|
|
461
|
+
//#region src/testing/fake-agent-invoice-xml.ts
|
|
462
|
+
const UNIFIED_PAYMENT_METHODS = [
|
|
463
|
+
"átutalás",
|
|
464
|
+
"készpénz",
|
|
465
|
+
"bankkártya",
|
|
466
|
+
"csekk",
|
|
467
|
+
"utánvét",
|
|
468
|
+
"ajándékutalvány",
|
|
469
|
+
"barion",
|
|
470
|
+
"barter",
|
|
471
|
+
"csoportos beszedés",
|
|
472
|
+
"OTP Simple",
|
|
473
|
+
"kompenzáció",
|
|
474
|
+
"kupon",
|
|
475
|
+
"PayPal",
|
|
476
|
+
"PayU",
|
|
477
|
+
"SZÉP kártya",
|
|
478
|
+
"utalvány",
|
|
479
|
+
"MasterCard Mobile",
|
|
480
|
+
"Borgun",
|
|
481
|
+
"EP kártya",
|
|
482
|
+
"térítésmentes",
|
|
483
|
+
"egyéb"
|
|
484
|
+
];
|
|
485
|
+
const OTHER_PAYMENT_METHOD = "egyéb";
|
|
486
|
+
const CASH_PAYMENT_METHOD = "készpénz";
|
|
487
|
+
const SELLER_ID = 1;
|
|
488
|
+
const DOMESTIC_LOCATION = 1;
|
|
489
|
+
const PAPER_APPEARANCE = 0;
|
|
490
|
+
const E_INVOICE_APPEARANCE = 2;
|
|
491
|
+
function unifiedPaymentMethod(method) {
|
|
492
|
+
const normalized = method.trim().toLowerCase();
|
|
493
|
+
return UNIFIED_PAYMENT_METHODS.find((candidate) => candidate.toLowerCase() === normalized) ?? OTHER_PAYMENT_METHOD;
|
|
494
|
+
}
|
|
495
|
+
function sellerNode(invoice) {
|
|
496
|
+
const { seller } = invoice;
|
|
497
|
+
return el("szallito", [
|
|
498
|
+
el("id", SELLER_ID),
|
|
499
|
+
el("nev", seller.name),
|
|
500
|
+
el("cim", [
|
|
501
|
+
optionalEl("orszag", seller.country),
|
|
502
|
+
el("irsz", seller.zip),
|
|
503
|
+
el("telepules", seller.city),
|
|
504
|
+
el("cim", seller.address)
|
|
505
|
+
]),
|
|
506
|
+
el("adoszam", seller.taxNumber),
|
|
507
|
+
optionalEl("bank", [optionalEl("nev", seller.bankName), optionalEl("bankszamla", seller.bankAccount)])
|
|
508
|
+
]);
|
|
509
|
+
}
|
|
510
|
+
function headerNode(invoice, testAccount) {
|
|
511
|
+
const unified = unifiedPaymentMethod(invoice.paymentMethod);
|
|
512
|
+
return el("alap", [
|
|
513
|
+
el("id", invoice.id),
|
|
514
|
+
el("szamlaszam", invoice.number),
|
|
515
|
+
el("gazdEsemAzon", invoice.id),
|
|
516
|
+
el("tipus", invoice.typeCode),
|
|
517
|
+
el("eszamla", invoice.eInvoice ? E_INVOICE_APPEARANCE : PAPER_APPEARANCE),
|
|
518
|
+
optionalEl("hivszamlaszam", invoice.referencedInvoiceNumber),
|
|
519
|
+
optionalEl("hivdijbekszam", invoice.referencedProformaNumber),
|
|
520
|
+
el("kelt", invoice.issueDate),
|
|
521
|
+
el("telj", invoice.fulfillmentDate),
|
|
522
|
+
el("fizh", invoice.dueDate),
|
|
523
|
+
el("fizmod", invoice.paymentMethod),
|
|
524
|
+
el("fizmodunified", unified),
|
|
525
|
+
el("keszpenz", unified === CASH_PAYMENT_METHOD),
|
|
526
|
+
optionalEl("rendelesszam", invoice.orderNumber),
|
|
527
|
+
el("nyelv", invoice.language),
|
|
528
|
+
el("devizanem", invoice.currency),
|
|
529
|
+
optionalEl("devizabank", invoice.exchangeBank),
|
|
530
|
+
optionalEl("devizaarf", invoice.exchangeRate),
|
|
531
|
+
optionalEl("megjegyzes", invoice.comment),
|
|
532
|
+
el("penzforg", false),
|
|
533
|
+
el("kata", false),
|
|
534
|
+
el("katafokonyv", false),
|
|
535
|
+
optionalEl("email", invoice.buyer.email),
|
|
536
|
+
el("teszt", testAccount),
|
|
537
|
+
el("sztornozott", invoice.reversed)
|
|
538
|
+
]);
|
|
539
|
+
}
|
|
540
|
+
function buyerNode(invoice) {
|
|
541
|
+
const { buyer } = invoice;
|
|
542
|
+
return el("vevo", [
|
|
543
|
+
el("nev", buyer.name),
|
|
544
|
+
optionalEl("azonosito", buyer.identifier),
|
|
545
|
+
el("cim", [
|
|
546
|
+
optionalEl("orszag", buyer.country),
|
|
547
|
+
el("irsz", buyer.zip),
|
|
548
|
+
el("telepules", buyer.city),
|
|
549
|
+
el("cim", buyer.address)
|
|
550
|
+
]),
|
|
551
|
+
optionalEl("email", buyer.email),
|
|
552
|
+
el("adoszam", buyer.taxNumber ?? ""),
|
|
553
|
+
optionalEl("csoportazonosito", buyer.groupTaxNumber),
|
|
554
|
+
optionalEl("adoszameu", buyer.euTaxNumber),
|
|
555
|
+
el("lokacio", DOMESTIC_LOCATION),
|
|
556
|
+
el("privatePersonIndicator", buyer.taxNumber === void 0 && buyer.euTaxNumber === void 0)
|
|
557
|
+
]);
|
|
558
|
+
}
|
|
559
|
+
function itemNode$1(item, index) {
|
|
560
|
+
return el("tetel", [
|
|
561
|
+
el("nev", item.name),
|
|
562
|
+
optionalEl("azonosito", item.identifier),
|
|
563
|
+
el("mennyiseg", item.quantity),
|
|
564
|
+
el("mennyisegiegyseg", item.unit),
|
|
565
|
+
el("nettoegysegar", item.netUnitPrice),
|
|
566
|
+
optionalEl("afatipus", item.vatCode),
|
|
567
|
+
el("afakulcs", item.vatRate),
|
|
568
|
+
el("netto", item.netAmount),
|
|
569
|
+
el("afa", item.vatAmount),
|
|
570
|
+
el("brutto", item.grossAmount),
|
|
571
|
+
optionalEl("megjegyzes", item.comment),
|
|
572
|
+
el("sztetordering", index + 1)
|
|
573
|
+
]);
|
|
574
|
+
}
|
|
575
|
+
function vatGroupNode(group) {
|
|
576
|
+
return el("afakulcsossz", [
|
|
577
|
+
optionalEl("afatipus", group.vatCode),
|
|
578
|
+
el("afakulcs", group.vatRate),
|
|
579
|
+
el("netto", group.net),
|
|
580
|
+
el("afa", group.vat),
|
|
581
|
+
el("brutto", group.gross)
|
|
582
|
+
]);
|
|
583
|
+
}
|
|
584
|
+
function totalNode(totals) {
|
|
585
|
+
return el("totalossz", [
|
|
586
|
+
el("netto", totals.net),
|
|
587
|
+
el("afa", totals.vat),
|
|
588
|
+
el("brutto", totals.gross)
|
|
589
|
+
]);
|
|
590
|
+
}
|
|
591
|
+
function paymentNode$1(payment) {
|
|
592
|
+
return el("kifizetes", [
|
|
593
|
+
el("datum", payment.date),
|
|
594
|
+
el("jogcim", payment.method),
|
|
595
|
+
el("osszeg", payment.amount),
|
|
596
|
+
optionalEl("megjegyzes", payment.comment)
|
|
597
|
+
]);
|
|
598
|
+
}
|
|
599
|
+
function renderInvoiceXml(invoice, testAccount, includePdf) {
|
|
600
|
+
return buildXmlDocument({
|
|
601
|
+
root: "szamla",
|
|
602
|
+
namespace: "http://www.szamlazz.hu/szamla",
|
|
603
|
+
children: [
|
|
604
|
+
sellerNode(invoice),
|
|
605
|
+
headerNode(invoice, testAccount),
|
|
606
|
+
buyerNode(invoice),
|
|
607
|
+
el("tetelek", invoice.items.map(itemNode$1)),
|
|
608
|
+
el("osszegek", [...vatGroupsOf(invoice.items).map(vatGroupNode), totalNode(invoice.totals)]),
|
|
609
|
+
invoice.payments.length > 0 && el("kifizetesek", invoice.payments.map(paymentNode$1)),
|
|
610
|
+
includePdf && el("pdf", bytesToBase64(fakePdf(invoice.number)))
|
|
611
|
+
]
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
//#endregion
|
|
615
|
+
//#region src/testing/fake-agent-request.ts
|
|
616
|
+
const REQUEST_ROOTS = {
|
|
617
|
+
createInvoice: "xmlszamla",
|
|
618
|
+
reverseInvoice: "xmlszamlast",
|
|
619
|
+
registerPayment: "xmlszamlakifiz",
|
|
620
|
+
getInvoicePdf: "xmlszamlapdf",
|
|
621
|
+
getInvoiceXml: "xmlszamlaxml",
|
|
622
|
+
deleteProforma: "xmlszamladbkdel",
|
|
623
|
+
createReceipt: "xmlnyugtacreate",
|
|
624
|
+
reverseReceipt: "xmlnyugtast",
|
|
625
|
+
getReceipt: "xmlnyugtaget",
|
|
626
|
+
sendReceipt: "xmlnyugtasend",
|
|
627
|
+
queryTaxpayer: "xmltaxpayer",
|
|
628
|
+
connectPrincipal: "XmlCegMb"
|
|
629
|
+
};
|
|
630
|
+
const MAX_ATTACHMENTS = 5;
|
|
631
|
+
const ACTION_FIELDS = Object.entries(AGENT_ACTIONS);
|
|
632
|
+
async function readForm(input, init) {
|
|
633
|
+
if (init?.body instanceof FormData) return init.body;
|
|
634
|
+
try {
|
|
635
|
+
return await (input instanceof Request && init === void 0 ? input : new Request(input, init)).formData();
|
|
636
|
+
} catch {
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
async function entryText(value) {
|
|
641
|
+
return typeof value === "string" ? value : value.text();
|
|
642
|
+
}
|
|
643
|
+
function attachmentsOf(form) {
|
|
644
|
+
const attachments = [];
|
|
645
|
+
for (let index = 1; index <= MAX_ATTACHMENTS; index++) {
|
|
646
|
+
const value = form.get(`attachfile${index}`);
|
|
647
|
+
if (value instanceof Blob) attachments.push({
|
|
648
|
+
filename: value instanceof File ? value.name : "",
|
|
649
|
+
size: value.size
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
return attachments;
|
|
653
|
+
}
|
|
654
|
+
async function readFakeAgentForm(input, init) {
|
|
655
|
+
const form = await readForm(input, init);
|
|
656
|
+
if (!form) return {
|
|
657
|
+
action: void 0,
|
|
658
|
+
xml: void 0,
|
|
659
|
+
attachments: []
|
|
660
|
+
};
|
|
661
|
+
for (const [action, field] of ACTION_FIELDS) {
|
|
662
|
+
const value = form.get(field);
|
|
663
|
+
if (value !== null) return {
|
|
664
|
+
action,
|
|
665
|
+
xml: await entryText(value),
|
|
666
|
+
attachments: attachmentsOf(form)
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
return {
|
|
670
|
+
action: void 0,
|
|
671
|
+
xml: void 0,
|
|
672
|
+
attachments: attachmentsOf(form)
|
|
673
|
+
};
|
|
674
|
+
}
|
|
675
|
+
function parseFakeAgentRequest(action, xml, attachments) {
|
|
676
|
+
let root;
|
|
677
|
+
try {
|
|
678
|
+
root = parseXml(xml);
|
|
679
|
+
} catch (error) {
|
|
680
|
+
throw new FakeAgentFailure(57, `XML beolvasási hiba.${error instanceof Error ? ` ${error.message}` : ""}`);
|
|
681
|
+
}
|
|
682
|
+
const expected = REQUEST_ROOTS[action];
|
|
683
|
+
if (root.name !== expected) throw new FakeAgentFailure(57, `XML beolvasási hiba. A(z) ${action} művelethez <${expected}> gyökérelem kell, érkezett: <${root.name}>.`);
|
|
684
|
+
return {
|
|
685
|
+
action,
|
|
686
|
+
xml,
|
|
687
|
+
root,
|
|
688
|
+
attachments
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
function credentialsOf(root) {
|
|
692
|
+
for (const holder of [
|
|
693
|
+
findChild(root, "login"),
|
|
694
|
+
findChild(root, "beallitasok"),
|
|
695
|
+
root
|
|
696
|
+
]) {
|
|
697
|
+
const agentKey = childText(holder, "szamlaagentkulcs");
|
|
698
|
+
const username = childText(holder, "felhasznalo") ?? childText(holder, "loginname");
|
|
699
|
+
const password = childText(holder, "jelszo") ?? childText(holder, "password");
|
|
700
|
+
if (agentKey !== void 0 || username !== void 0 || password !== void 0) return {
|
|
701
|
+
agentKey,
|
|
702
|
+
username,
|
|
703
|
+
password
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
return {};
|
|
707
|
+
}
|
|
708
|
+
function responseVersion(root) {
|
|
709
|
+
return childNumber(findChild(root, "beallitasok"), "valaszVerzio") ?? childNumber(root, "valaszVerzio") ?? 1;
|
|
710
|
+
}
|
|
711
|
+
function errorStyleFor(action, root) {
|
|
712
|
+
switch (action) {
|
|
713
|
+
case "createInvoice":
|
|
714
|
+
case "reverseInvoice":
|
|
715
|
+
case "registerPayment":
|
|
716
|
+
case "getInvoicePdf": return root !== void 0 && responseVersion(root) === 2 ? "invoice" : "text";
|
|
717
|
+
case "getInvoiceXml": return "invoice";
|
|
718
|
+
case "deleteProforma": return "proforma";
|
|
719
|
+
case "createReceipt":
|
|
720
|
+
case "reverseReceipt":
|
|
721
|
+
case "getReceipt": return "receipt";
|
|
722
|
+
case "sendReceipt": return "receipt-send";
|
|
723
|
+
case "queryTaxpayer":
|
|
724
|
+
case "connectPrincipal": return "text";
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
//#endregion
|
|
728
|
+
//#region src/testing/fake-agent-invoices.ts
|
|
729
|
+
const LANGUAGES = /* @__PURE__ */ new Set([
|
|
730
|
+
"hu",
|
|
731
|
+
"en",
|
|
732
|
+
"de",
|
|
733
|
+
"it",
|
|
734
|
+
"ro",
|
|
735
|
+
"sk",
|
|
736
|
+
"hr",
|
|
737
|
+
"fr",
|
|
738
|
+
"es",
|
|
739
|
+
"cz",
|
|
740
|
+
"pl",
|
|
741
|
+
"bg",
|
|
742
|
+
"nl",
|
|
743
|
+
"ru",
|
|
744
|
+
"si"
|
|
745
|
+
]);
|
|
746
|
+
const DUPLICATE_WINDOW_MS = 1728e5;
|
|
747
|
+
const MAX_PAYMENTS = 5;
|
|
748
|
+
const DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
749
|
+
function requiredText$1(parent, name, path) {
|
|
750
|
+
const value = childText(parent, name);
|
|
751
|
+
if (value === void 0) throw xmlFailure(`hiányzik a(z) <${path}/${name}> elem.`);
|
|
752
|
+
return value;
|
|
753
|
+
}
|
|
754
|
+
function checkedDate(value, name, path) {
|
|
755
|
+
if (!DATE_PATTERN.test(value)) throw xmlFailure(`a(z) <${path}/${name}> nem ÉÉÉÉ-HH-NN formátumú dátum: ${value}.`);
|
|
756
|
+
return value;
|
|
757
|
+
}
|
|
758
|
+
function requiredDate(parent, name, path) {
|
|
759
|
+
return checkedDate(requiredText$1(parent, name, path), name, path);
|
|
760
|
+
}
|
|
761
|
+
function optionalDate(parent, name, path) {
|
|
762
|
+
const value = childText(parent, name);
|
|
763
|
+
return value === void 0 ? void 0 : checkedDate(value, name, path);
|
|
764
|
+
}
|
|
765
|
+
function typeCodeOf(header) {
|
|
766
|
+
if (childBoolean(header, "dijbekero") === true) return "D";
|
|
767
|
+
if (childBoolean(header, "elolegszamla") === true) return "ES";
|
|
768
|
+
if (childBoolean(header, "vegszamla") === true) return "VS";
|
|
769
|
+
if (childBoolean(header, "helyesbitoszamla") === true) return "HS";
|
|
770
|
+
if (childBoolean(header, "szallitolevel") === true) return "SL";
|
|
771
|
+
return "SZ";
|
|
772
|
+
}
|
|
773
|
+
function seriesOf(typeCode, prefix, eInvoice) {
|
|
774
|
+
if (typeCode === "D") return `D-${prefix}`;
|
|
775
|
+
if (typeCode === "SL") return `SZL-${prefix}`;
|
|
776
|
+
return eInvoice ? `E-${prefix}` : prefix;
|
|
777
|
+
}
|
|
778
|
+
function buyerOf(root) {
|
|
779
|
+
const buyer = findChild(root, "vevo");
|
|
780
|
+
return {
|
|
781
|
+
name: requiredText$1(buyer, "nev", "vevo"),
|
|
782
|
+
identifier: childText(buyer, "azonosito"),
|
|
783
|
+
country: childText(buyer, "orszag"),
|
|
784
|
+
zip: requiredText$1(buyer, "irsz", "vevo"),
|
|
785
|
+
city: requiredText$1(buyer, "telepules", "vevo"),
|
|
786
|
+
address: requiredText$1(buyer, "cim", "vevo"),
|
|
787
|
+
email: childText(buyer, "email"),
|
|
788
|
+
taxNumber: childText(buyer, "adoszam"),
|
|
789
|
+
groupTaxNumber: childText(buyer, "csoportazonosito"),
|
|
790
|
+
euTaxNumber: childText(buyer, "adoszamEU")
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
function sellerOf(state, root) {
|
|
794
|
+
const seller = findChild(root, "elado");
|
|
795
|
+
const defaults = state.config.seller;
|
|
796
|
+
return {
|
|
797
|
+
...defaults,
|
|
798
|
+
bankName: childText(seller, "bank") ?? defaults.bankName,
|
|
799
|
+
bankAccount: childText(seller, "bankszamlaszam") ?? defaults.bankAccount
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
function resolvePrefix$1(state, header) {
|
|
803
|
+
const prefix = childText(header, "szamlaszamElotag") ?? state.config.defaultInvoicePrefix;
|
|
804
|
+
const allowed = state.config.invoicePrefixes;
|
|
805
|
+
if (allowed !== void 0 && !allowed.has(prefix)) throw agentFailure(202);
|
|
806
|
+
return prefix;
|
|
807
|
+
}
|
|
808
|
+
function marginVatOf(root, header) {
|
|
809
|
+
const wholeInvoice = childBoolean(header, "arresAfa") === true;
|
|
810
|
+
const items = findChildren(findChild(root, "tetelek"), "tetel");
|
|
811
|
+
return (index) => wholeInvoice || childText(items[index], "arresAfaAlap") !== void 0;
|
|
812
|
+
}
|
|
813
|
+
function readInvoiceRequest(state, root) {
|
|
814
|
+
const settings = findChild(root, "beallitasok");
|
|
815
|
+
const header = findChild(root, "fejlec");
|
|
816
|
+
if (!header) throw xmlFailure("hiányzik a <fejlec> blokk.");
|
|
817
|
+
const currency = requiredText$1(header, "penznem", "fejlec");
|
|
818
|
+
const language = requiredText$1(header, "szamlaNyelve", "fejlec");
|
|
819
|
+
if (!LANGUAGES.has(language)) throw xmlFailure(`ismeretlen számlanyelv: ${language}.`);
|
|
820
|
+
const issueDate = requiredDate(header, "keltDatum", "fejlec");
|
|
821
|
+
const fulfillmentDate = requiredDate(header, "teljesitesDatum", "fejlec");
|
|
822
|
+
const dueDate = requiredDate(header, "fizetesiHataridoDatum", "fejlec");
|
|
823
|
+
const paymentMethod = requiredText$1(header, "fizmod", "fejlec");
|
|
824
|
+
const buyer = buyerOf(root);
|
|
825
|
+
const items = parseItems(root, "invoice");
|
|
826
|
+
const prefix = resolvePrefix$1(state, header);
|
|
827
|
+
assertInvoiceItems(items, currency, marginVatOf(root, header));
|
|
828
|
+
const typeCode = typeCodeOf(header);
|
|
829
|
+
const eInvoice = childBoolean(settings, "eszamla") === true;
|
|
830
|
+
const totals = totalsOf(items);
|
|
831
|
+
const foreign = !isHuf(currency);
|
|
832
|
+
return {
|
|
833
|
+
preview: childBoolean(header, "elonezetpdf") === true,
|
|
834
|
+
downloadPdf: childBoolean(settings, "szamlaLetoltes") === true,
|
|
835
|
+
fields: {
|
|
836
|
+
prefix,
|
|
837
|
+
series: seriesOf(typeCode, prefix, eInvoice),
|
|
838
|
+
typeCode,
|
|
839
|
+
eInvoice,
|
|
840
|
+
issueDate,
|
|
841
|
+
fulfillmentDate,
|
|
842
|
+
dueDate,
|
|
843
|
+
paymentMethod,
|
|
844
|
+
language,
|
|
845
|
+
currency,
|
|
846
|
+
exchangeBank: foreign ? childText(header, "arfolyamBank") : void 0,
|
|
847
|
+
exchangeRate: foreign ? childNumber(header, "arfolyam") : void 0,
|
|
848
|
+
comment: childText(header, "megjegyzes"),
|
|
849
|
+
orderNumber: childText(header, "rendelesSzam"),
|
|
850
|
+
externalId: childText(settings, "szamlaKulsoAzon"),
|
|
851
|
+
referencedInvoiceNumber: childText(header, "helyesbitettSzamlaszam") ?? childText(header, "elolegSzamlaszam"),
|
|
852
|
+
referencedProformaNumber: childText(header, "dijbekeroSzamlaszam"),
|
|
853
|
+
seller: sellerOf(state, root),
|
|
854
|
+
buyer,
|
|
855
|
+
items,
|
|
856
|
+
totals,
|
|
857
|
+
payments: childBoolean(header, "fizetve") === true ? [{
|
|
858
|
+
date: issueDate,
|
|
859
|
+
method: paymentMethod,
|
|
860
|
+
amount: totals.gross
|
|
861
|
+
}] : [],
|
|
862
|
+
reversed: false,
|
|
863
|
+
deleted: false
|
|
864
|
+
}
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
function activeInvoice(state, number) {
|
|
868
|
+
const invoice = state.invoices.get(number);
|
|
869
|
+
return invoice && !invoice.deleted ? invoice : void 0;
|
|
870
|
+
}
|
|
871
|
+
function paidAmount(invoice) {
|
|
872
|
+
return invoice.payments.reduce((sum, payment) => sum + payment.amount, 0);
|
|
873
|
+
}
|
|
874
|
+
function resultFields(invoice, pdf) {
|
|
875
|
+
return {
|
|
876
|
+
number: invoice.number,
|
|
877
|
+
netTotal: invoice.totals.net,
|
|
878
|
+
grossTotal: invoice.totals.gross,
|
|
879
|
+
outstanding: invoice.typeCode === "SS" ? void 0 : outstandingOf(invoice.totals.gross, paidAmount(invoice)),
|
|
880
|
+
paymentMethod: invoice.paymentMethod,
|
|
881
|
+
pdf: pdf ? fakePdf(invoice.number) : void 0
|
|
882
|
+
};
|
|
883
|
+
}
|
|
884
|
+
function invoiceResult(invoice, version, downloadPdf) {
|
|
885
|
+
return invoiceResultResponse(resultFields(invoice, downloadPdf), version);
|
|
886
|
+
}
|
|
887
|
+
function isSameInvoice(existing, fields) {
|
|
888
|
+
return existing.buyer.name === fields.buyer.name && existing.totals.gross === fields.totals.gross && existing.issueDate === fields.issueDate && existing.dueDate === fields.dueDate && existing.fulfillmentDate === fields.fulfillmentDate;
|
|
889
|
+
}
|
|
890
|
+
function findOrderDuplicate(state, fields) {
|
|
891
|
+
const { orderNumber, typeCode } = fields;
|
|
892
|
+
if (!state.config.uniqueInvoiceOrderNumbers || orderNumber === void 0 || typeCode === "HS") return;
|
|
893
|
+
return [...state.invoices.values()].findLast((invoice) => invoice.typeCode === typeCode && invoice.orderNumber === orderNumber && !invoice.reversed && !invoice.deleted);
|
|
894
|
+
}
|
|
895
|
+
function handleCreateInvoice(state, request) {
|
|
896
|
+
const version = responseVersion(request.root);
|
|
897
|
+
const { fields, preview, downloadPdf } = readInvoiceRequest(state, request.root);
|
|
898
|
+
if (preview) return invoiceResultResponse({
|
|
899
|
+
netTotal: fields.totals.net,
|
|
900
|
+
grossTotal: fields.totals.gross,
|
|
901
|
+
pdf: fakePdf("előnézet")
|
|
902
|
+
}, version);
|
|
903
|
+
const duplicate = findOrderDuplicate(state, fields);
|
|
904
|
+
if (duplicate) {
|
|
905
|
+
if (!(state.now().getTime() - duplicate.createdAt <= DUPLICATE_WINDOW_MS) || !isSameInvoice(duplicate, fields)) throw agentFailure(152, `Már létező rendelésszám: ${fields.orderNumber}. Az ismétlődés engedélyezhető a Beállítások oldalon.`);
|
|
906
|
+
return invoiceResult(duplicate, version, downloadPdf);
|
|
907
|
+
}
|
|
908
|
+
const invoice = {
|
|
909
|
+
...fields,
|
|
910
|
+
id: nextDocumentId(state),
|
|
911
|
+
number: nextDocumentNumber(state, fields.series),
|
|
912
|
+
createdAt: state.now().getTime()
|
|
913
|
+
};
|
|
914
|
+
state.invoices.set(invoice.number, invoice);
|
|
915
|
+
return invoiceResult(invoice, version, downloadPdf);
|
|
916
|
+
}
|
|
917
|
+
function reversalOf(state, original, root) {
|
|
918
|
+
const settings = findChild(root, "beallitasok");
|
|
919
|
+
const header = findChild(root, "fejlec");
|
|
920
|
+
const buyer = findChild(root, "vevo");
|
|
921
|
+
const issueDate = optionalDate(header, "keltDatum", "fejlec") ?? today(state);
|
|
922
|
+
return {
|
|
923
|
+
...original,
|
|
924
|
+
id: nextDocumentId(state),
|
|
925
|
+
number: nextDocumentNumber(state, original.series),
|
|
926
|
+
typeCode: "SS",
|
|
927
|
+
createdAt: state.now().getTime(),
|
|
928
|
+
eInvoice: original.eInvoice || childBoolean(settings, "eszamla") === true,
|
|
929
|
+
issueDate,
|
|
930
|
+
fulfillmentDate: optionalDate(header, "teljesitesDatum", "fejlec") ?? original.fulfillmentDate,
|
|
931
|
+
dueDate: issueDate,
|
|
932
|
+
comment: childText(header, "megjegyzes"),
|
|
933
|
+
externalId: childText(settings, "szamlaKulsoAzon"),
|
|
934
|
+
referencedInvoiceNumber: original.number,
|
|
935
|
+
referencedProformaNumber: void 0,
|
|
936
|
+
buyer: {
|
|
937
|
+
...original.buyer,
|
|
938
|
+
email: childText(buyer, "email") ?? original.buyer.email,
|
|
939
|
+
taxNumber: childText(buyer, "adoszam") ?? original.buyer.taxNumber
|
|
940
|
+
},
|
|
941
|
+
items: original.items.map(negateItem),
|
|
942
|
+
totals: negateTotals(original.totals),
|
|
943
|
+
payments: [],
|
|
944
|
+
reversed: false,
|
|
945
|
+
deleted: false
|
|
946
|
+
};
|
|
947
|
+
}
|
|
948
|
+
function handleReverseInvoice(state, request) {
|
|
949
|
+
const { root } = request;
|
|
950
|
+
const version = responseVersion(root);
|
|
951
|
+
const downloadPdf = childBoolean(findChild(root, "beallitasok"), "szamlaLetoltes") === true;
|
|
952
|
+
const number = requiredText$1(findChild(root, "fejlec"), "szamlaszam", "fejlec");
|
|
953
|
+
const original = activeInvoice(state, number);
|
|
954
|
+
if (!original) throw agentFailure(7, `Hiányzó adat: sztornózandó számla (ismeretlen számlaszám: ${number}).`);
|
|
955
|
+
if (original.typeCode === "D" || original.typeCode === "SL") return invoiceResult(original, version, downloadPdf);
|
|
956
|
+
if (original.typeCode === "SS") throw new FakeAgentFailure(void 0, `A(z) ${number} sztornó számla, nem sztornózható.`);
|
|
957
|
+
if (original.reversed) throw new FakeAgentFailure(void 0, `A(z) ${number} számlát már sztornózták.`);
|
|
958
|
+
const reversal = reversalOf(state, original, root);
|
|
959
|
+
state.invoices.set(original.number, {
|
|
960
|
+
...original,
|
|
961
|
+
reversed: true
|
|
962
|
+
});
|
|
963
|
+
state.invoices.set(reversal.number, reversal);
|
|
964
|
+
return invoiceResult(reversal, version, downloadPdf);
|
|
965
|
+
}
|
|
966
|
+
function paymentOf$1(element, index) {
|
|
967
|
+
const path = `kifizetes[${index + 1}]`;
|
|
968
|
+
const amount = childNumber(element, "osszeg");
|
|
969
|
+
if (amount === void 0) throw xmlFailure(`a(z) <${path}/osszeg> hiányzik vagy nem szám.`);
|
|
970
|
+
return {
|
|
971
|
+
date: requiredDate(element, "datum", path),
|
|
972
|
+
method: requiredText$1(element, "jogcim", path),
|
|
973
|
+
amount,
|
|
974
|
+
comment: childText(element, "leiras")
|
|
975
|
+
};
|
|
976
|
+
}
|
|
977
|
+
function handleRegisterPayment(state, request) {
|
|
978
|
+
const { root } = request;
|
|
979
|
+
const settings = findChild(root, "beallitasok");
|
|
980
|
+
const number = requiredText$1(settings, "szamlaszam", "beallitasok");
|
|
981
|
+
const additive = childBoolean(settings, "additiv");
|
|
982
|
+
if (additive === void 0) throw xmlFailure("hiányzik a(z) <beallitasok/additiv> elem.");
|
|
983
|
+
const elements = findChildren(root, "kifizetes");
|
|
984
|
+
if (elements.length > MAX_PAYMENTS) throw xmlFailure(`egy kérésben legfeljebb ${MAX_PAYMENTS} <kifizetes> elem lehet.`);
|
|
985
|
+
const entries = elements.map(paymentOf$1);
|
|
986
|
+
const invoice = activeInvoice(state, number);
|
|
987
|
+
if (!invoice) throw agentFailure(7, `Hiányzó adat: ismeretlen számlaszám (${number}).`);
|
|
988
|
+
const updated = {
|
|
989
|
+
...invoice,
|
|
990
|
+
payments: additive ? [...invoice.payments, ...entries] : entries
|
|
991
|
+
};
|
|
992
|
+
state.invoices.set(number, updated);
|
|
993
|
+
const fields = {
|
|
994
|
+
...resultFields(updated, false),
|
|
995
|
+
paymentMethod: void 0
|
|
996
|
+
};
|
|
997
|
+
if (responseVersion(root) === 2) return invoiceResultResponse(fields, 2);
|
|
998
|
+
return textResponse("xmlagentresponse=DONE\n", invoiceResultHeaders(fields));
|
|
999
|
+
}
|
|
1000
|
+
function lookupInvoice(state, root) {
|
|
1001
|
+
const number = childText(root, "szamlaszam");
|
|
1002
|
+
if (number !== void 0) return activeInvoice(state, number);
|
|
1003
|
+
const orderNumber = childText(root, "rendelesSzam");
|
|
1004
|
+
const externalId = childText(root, "szamlaKulsoAzon");
|
|
1005
|
+
if (orderNumber === void 0 && externalId === void 0) throw xmlFailure("add meg a számlaszámot, a rendelésszámot vagy a külső azonosítót.");
|
|
1006
|
+
return [...state.invoices.values()].findLast((invoice) => !invoice.deleted && (orderNumber !== void 0 ? invoice.orderNumber === orderNumber : invoice.externalId === externalId));
|
|
1007
|
+
}
|
|
1008
|
+
function handleGetInvoicePdf(state, request) {
|
|
1009
|
+
const invoice = lookupInvoice(state, request.root);
|
|
1010
|
+
if (!invoice) throw agentFailure(7, "Hiányzó adat: számla pdf (ismeretlen számlaszám, rendelésszám vagy külső azonosító).");
|
|
1011
|
+
return invoiceResult(invoice, responseVersion(request.root), true);
|
|
1012
|
+
}
|
|
1013
|
+
function handleGetInvoiceXml(state, request) {
|
|
1014
|
+
const invoice = lookupInvoice(state, request.root);
|
|
1015
|
+
if (!invoice) throw agentFailure(7, "Hiányzó adat: számla xml (ismeretlen számlaszám, rendelésszám vagy külső azonosító).");
|
|
1016
|
+
const includePdf = childBoolean(request.root, "pdf") === true;
|
|
1017
|
+
return xmlResponse(renderInvoiceXml(invoice, state.config.testAccount, includePdf));
|
|
1018
|
+
}
|
|
1019
|
+
function handleDeleteProforma(state, request) {
|
|
1020
|
+
const header = findChild(request.root, "fejlec");
|
|
1021
|
+
const number = childText(header, "szamlaszam");
|
|
1022
|
+
const orderNumber = childText(header, "rendelesszam");
|
|
1023
|
+
if (number === void 0 && orderNumber === void 0) throw xmlFailure("add meg a díjbekérő számát vagy a rendelésszámot.");
|
|
1024
|
+
const targets = [...state.invoices.values()].filter((invoice) => invoice.typeCode === "D" && !invoice.deleted && (number !== void 0 ? invoice.number === number : invoice.orderNumber === orderNumber));
|
|
1025
|
+
if (targets.length === 0) throw agentFailure(335);
|
|
1026
|
+
for (const target of targets) state.invoices.set(target.number, {
|
|
1027
|
+
...target,
|
|
1028
|
+
deleted: true
|
|
1029
|
+
});
|
|
1030
|
+
return xmlResponse(xmlDocument("xmlszamladbkdelvalasz", [el("sikeres", true)]));
|
|
1031
|
+
}
|
|
1032
|
+
//#endregion
|
|
1033
|
+
//#region src/testing/fake-agent-receipts.ts
|
|
1034
|
+
const PREFIX_PATTERN = /^[A-Z0-9]+$/;
|
|
1035
|
+
const MONEY_DECIMALS = 2;
|
|
1036
|
+
function requiredText(parent, name, path) {
|
|
1037
|
+
const value = childText(parent, name);
|
|
1038
|
+
if (value === void 0) throw xmlFailure(`hiányzik a(z) <${path}/${name}> elem.`);
|
|
1039
|
+
return value;
|
|
1040
|
+
}
|
|
1041
|
+
function assertUnusedCallId(state, callId) {
|
|
1042
|
+
if (callId === void 0) return;
|
|
1043
|
+
if ([...state.receipts.values()].some((receipt) => receipt.callId === callId)) throw agentFailure(338, `A hívásazonosító már létezik: ${callId}.`);
|
|
1044
|
+
}
|
|
1045
|
+
function isInvoicePrefix(state, prefix) {
|
|
1046
|
+
if (state.config.invoicePrefixes?.has(prefix)) return true;
|
|
1047
|
+
return [...state.invoices.values()].some((invoice) => invoice.prefix === prefix);
|
|
1048
|
+
}
|
|
1049
|
+
function resolvePrefix(state, header) {
|
|
1050
|
+
const prefix = requiredText(header, "elotag", "fejlec");
|
|
1051
|
+
if (!PREFIX_PATTERN.test(prefix)) throw agentFailure(337);
|
|
1052
|
+
if (isInvoicePrefix(state, prefix)) throw agentFailure(336);
|
|
1053
|
+
const enabled = state.config.receiptPrefixes;
|
|
1054
|
+
if (enabled !== void 0 && !enabled.has(prefix)) throw agentFailure(524);
|
|
1055
|
+
return prefix;
|
|
1056
|
+
}
|
|
1057
|
+
function paymentOf(element, index) {
|
|
1058
|
+
const path = `kifizetesek/kifizetes[${index + 1}]`;
|
|
1059
|
+
const amount = childNumber(element, "osszeg");
|
|
1060
|
+
if (amount === void 0) throw xmlFailure(`a(z) <${path}/osszeg> hiányzik vagy nem szám.`);
|
|
1061
|
+
return {
|
|
1062
|
+
method: requiredText(element, "fizetoeszkoz", path),
|
|
1063
|
+
amount,
|
|
1064
|
+
description: childText(element, "leiras")
|
|
1065
|
+
};
|
|
1066
|
+
}
|
|
1067
|
+
function assertPaymentsMatch(payments, gross) {
|
|
1068
|
+
if (payments.length === 0) return;
|
|
1069
|
+
const paid = roundMoney(payments.reduce((sum, payment) => sum + payment.amount, 0), MONEY_DECIMALS);
|
|
1070
|
+
if (paid !== roundMoney(gross, MONEY_DECIMALS)) throw agentFailure(340, `A kifizetett összeg (${paid}) eltér a bruttó végösszegtől (${gross}).`);
|
|
1071
|
+
}
|
|
1072
|
+
function assertUniqueOrderNumber(state, orderNumber) {
|
|
1073
|
+
if (!state.config.uniqueReceiptOrderNumbers || orderNumber === void 0) return;
|
|
1074
|
+
if ([...state.receipts.values()].some((receipt) => receipt.type === "NY" && receipt.orderNumber === orderNumber && !receipt.reversed)) throw agentFailure(152, `Már létező rendelésszám: ${orderNumber}. Az ismétlődés engedélyezhető a Beállítások oldalon.`);
|
|
1075
|
+
}
|
|
1076
|
+
function exchangeOf(header, currency) {
|
|
1077
|
+
if (isHuf(currency)) return {
|
|
1078
|
+
exchangeBank: void 0,
|
|
1079
|
+
exchangeRate: void 0
|
|
1080
|
+
};
|
|
1081
|
+
const exchangeRate = childNumber(header, "devizaarf");
|
|
1082
|
+
const exchangeBank = childText(header, "devizabank");
|
|
1083
|
+
if (exchangeRate === void 0 || exchangeRate <= 0 || exchangeBank === void 0) throw xmlFailure(`devizás (${currency}) nyugtánál az árfolyam (devizaarf) és a bank (devizabank) megadása kötelező.`);
|
|
1084
|
+
return {
|
|
1085
|
+
exchangeBank,
|
|
1086
|
+
exchangeRate
|
|
1087
|
+
};
|
|
1088
|
+
}
|
|
1089
|
+
function itemNode(item) {
|
|
1090
|
+
return el("tetel", [
|
|
1091
|
+
el("megnevezes", item.name),
|
|
1092
|
+
optionalEl("azonosito", item.identifier),
|
|
1093
|
+
el("nettoEgysegar", item.netUnitPrice),
|
|
1094
|
+
el("mennyiseg", item.quantity),
|
|
1095
|
+
el("mennyisegiEgyseg", item.unit),
|
|
1096
|
+
el("netto", item.netAmount),
|
|
1097
|
+
optionalEl("afatipus", item.vatCode),
|
|
1098
|
+
el("afakulcs", item.vatRate),
|
|
1099
|
+
el("afa", item.vatAmount),
|
|
1100
|
+
el("brutto", item.grossAmount),
|
|
1101
|
+
item.ledger && optionalEl("fokonyv", [optionalEl("arbevetel", item.ledger.revenue), optionalEl("afa", item.ledger.vat)])
|
|
1102
|
+
]);
|
|
1103
|
+
}
|
|
1104
|
+
function paymentNode(payment) {
|
|
1105
|
+
return el("kifizetes", [
|
|
1106
|
+
el("fizetoeszkoz", payment.method),
|
|
1107
|
+
el("osszeg", payment.amount),
|
|
1108
|
+
optionalEl("leiras", payment.description)
|
|
1109
|
+
]);
|
|
1110
|
+
}
|
|
1111
|
+
function receiptNode(receipt, testAccount) {
|
|
1112
|
+
return el("nyugta", [
|
|
1113
|
+
el("alap", [
|
|
1114
|
+
el("id", receipt.id),
|
|
1115
|
+
optionalEl("hivasAzonosito", receipt.callId),
|
|
1116
|
+
el("nyugtaszam", receipt.number),
|
|
1117
|
+
el("tipus", receipt.type),
|
|
1118
|
+
el("stornozott", receipt.reversed),
|
|
1119
|
+
optionalEl("stornozottNyugtaszam", receipt.reversedNumber),
|
|
1120
|
+
el("kelt", receipt.issueDate),
|
|
1121
|
+
el("fizmod", receipt.paymentMethod),
|
|
1122
|
+
el("penznem", receipt.currency),
|
|
1123
|
+
optionalEl("devizabank", receipt.exchangeBank),
|
|
1124
|
+
optionalEl("devizaarf", receipt.exchangeRate),
|
|
1125
|
+
optionalEl("megjegyzes", receipt.comment),
|
|
1126
|
+
optionalEl("fokonyvVevo", receipt.customerLedgerId),
|
|
1127
|
+
el("teszt", testAccount),
|
|
1128
|
+
optionalEl("rendelesSzam", receipt.orderNumber)
|
|
1129
|
+
]),
|
|
1130
|
+
el("tetelek", receipt.items.map(itemNode)),
|
|
1131
|
+
receipt.payments.length > 0 && el("kifizetesek", receipt.payments.map(paymentNode)),
|
|
1132
|
+
el("osszegek", [...vatGroupsOf(receipt.items).map(vatGroupNode), totalNode(receipt.totals)])
|
|
1133
|
+
]);
|
|
1134
|
+
}
|
|
1135
|
+
function receiptResponse(state, receipt, includePdf) {
|
|
1136
|
+
return xmlResponse(xmlDocument("xmlnyugtavalasz", [
|
|
1137
|
+
el("sikeres", true),
|
|
1138
|
+
includePdf && el("nyugtaPdf", bytesToBase64(fakePdf(receipt.number))),
|
|
1139
|
+
receiptNode(receipt, state.config.testAccount)
|
|
1140
|
+
]));
|
|
1141
|
+
}
|
|
1142
|
+
function downloadPdfOf(root) {
|
|
1143
|
+
return childBoolean(findChild(root, "beallitasok"), "pdfLetoltes") === true;
|
|
1144
|
+
}
|
|
1145
|
+
function handleCreateReceipt(state, request) {
|
|
1146
|
+
const { root } = request;
|
|
1147
|
+
const header = findChild(root, "fejlec");
|
|
1148
|
+
if (!header) throw xmlFailure("hiányzik a <fejlec> blokk.");
|
|
1149
|
+
const callId = childText(header, "hivasAzonosito");
|
|
1150
|
+
assertUnusedCallId(state, callId);
|
|
1151
|
+
const prefix = resolvePrefix(state, header);
|
|
1152
|
+
const paymentMethod = requiredText(header, "fizmod", "fejlec");
|
|
1153
|
+
const currency = childText(header, "penznem") ?? "HUF";
|
|
1154
|
+
const exchange = exchangeOf(header, currency);
|
|
1155
|
+
const items = parseItems(root, "receipt");
|
|
1156
|
+
assertReceiptItems(items, currency);
|
|
1157
|
+
const totals = totalsOf(items);
|
|
1158
|
+
const payments = findChildren(findChild(root, "kifizetesek"), "kifizetes").map(paymentOf);
|
|
1159
|
+
assertPaymentsMatch(payments, totals.gross);
|
|
1160
|
+
const orderNumber = childText(header, "rendelesSzam");
|
|
1161
|
+
assertUniqueOrderNumber(state, orderNumber);
|
|
1162
|
+
const receipt = {
|
|
1163
|
+
id: nextDocumentId(state),
|
|
1164
|
+
number: nextDocumentNumber(state, prefix),
|
|
1165
|
+
prefix,
|
|
1166
|
+
callId,
|
|
1167
|
+
type: "NY",
|
|
1168
|
+
reversed: false,
|
|
1169
|
+
issueDate: today(state),
|
|
1170
|
+
paymentMethod,
|
|
1171
|
+
currency,
|
|
1172
|
+
...exchange,
|
|
1173
|
+
comment: childText(header, "megjegyzes"),
|
|
1174
|
+
customerLedgerId: childText(header, "fokonyvVevo"),
|
|
1175
|
+
orderNumber,
|
|
1176
|
+
items,
|
|
1177
|
+
payments,
|
|
1178
|
+
totals,
|
|
1179
|
+
sentTo: []
|
|
1180
|
+
};
|
|
1181
|
+
state.receipts.set(receipt.number, receipt);
|
|
1182
|
+
return receiptResponse(state, receipt, downloadPdfOf(root));
|
|
1183
|
+
}
|
|
1184
|
+
function handleReverseReceipt(state, request) {
|
|
1185
|
+
const { root } = request;
|
|
1186
|
+
const header = findChild(root, "fejlec");
|
|
1187
|
+
const number = requiredText(header, "nyugtaszam", "fejlec");
|
|
1188
|
+
const callId = childText(header, "hivasAzonosito");
|
|
1189
|
+
assertUnusedCallId(state, callId);
|
|
1190
|
+
const original = state.receipts.get(number);
|
|
1191
|
+
if (!original) throw agentFailure(339, "Hiányzó adat: sztornózandó nyugta (nincs ilyen nyugtaszám)");
|
|
1192
|
+
if (original.type === "SN") throw new FakeAgentFailure(void 0, "Hiányzó adat: sztornózandó nyugta (ez a nyugta egy sztornónyugta)");
|
|
1193
|
+
if (original.reversed) throw new FakeAgentFailure(void 0, `Hiányzó adat: sztornózandó nyugta (ezt a nyugtát már sztornózták: ${number})`);
|
|
1194
|
+
const reversal = {
|
|
1195
|
+
...original,
|
|
1196
|
+
id: nextDocumentId(state),
|
|
1197
|
+
number: nextDocumentNumber(state, original.prefix),
|
|
1198
|
+
callId,
|
|
1199
|
+
type: "SN",
|
|
1200
|
+
reversed: false,
|
|
1201
|
+
reversedNumber: original.number,
|
|
1202
|
+
issueDate: today(state),
|
|
1203
|
+
items: original.items.map(negateItem),
|
|
1204
|
+
payments: original.payments.map((payment) => ({
|
|
1205
|
+
...payment,
|
|
1206
|
+
amount: -payment.amount
|
|
1207
|
+
})),
|
|
1208
|
+
totals: negateTotals(original.totals),
|
|
1209
|
+
sentTo: []
|
|
1210
|
+
};
|
|
1211
|
+
state.receipts.set(original.number, {
|
|
1212
|
+
...original,
|
|
1213
|
+
reversed: true
|
|
1214
|
+
});
|
|
1215
|
+
state.receipts.set(reversal.number, reversal);
|
|
1216
|
+
return receiptResponse(state, reversal, downloadPdfOf(root));
|
|
1217
|
+
}
|
|
1218
|
+
function handleGetReceipt(state, request) {
|
|
1219
|
+
const { root } = request;
|
|
1220
|
+
const header = findChild(root, "fejlec");
|
|
1221
|
+
const number = childText(header, "nyugtaszam");
|
|
1222
|
+
const orderNumber = childText(header, "rendelesSzam");
|
|
1223
|
+
if (number === void 0 && orderNumber === void 0) throw xmlFailure("add meg a nyugtaszámot (nyugtaszam) vagy a rendelésszámot (rendelesSzam).");
|
|
1224
|
+
const receipt = number !== void 0 ? state.receipts.get(number) : [...state.receipts.values()].findLast((candidate) => candidate.orderNumber === orderNumber);
|
|
1225
|
+
if (!receipt) throw agentFailure(339);
|
|
1226
|
+
return receiptResponse(state, receipt, downloadPdfOf(root));
|
|
1227
|
+
}
|
|
1228
|
+
function handleSendReceipt(state, request) {
|
|
1229
|
+
const { root } = request;
|
|
1230
|
+
const number = requiredText(findChild(root, "fejlec"), "nyugtaszam", "fejlec");
|
|
1231
|
+
const email = findChild(root, "emailKuldes");
|
|
1232
|
+
const recipients = childText(email, "email");
|
|
1233
|
+
if (recipients === void 0) throw agentFailure(7, "Hiányzó adat: email elem.");
|
|
1234
|
+
if (childText(email, "emailTargy") === void 0) throw agentFailure(7, "Hiányzó adat: emailtargy elem.");
|
|
1235
|
+
const receipt = state.receipts.get(number);
|
|
1236
|
+
if (!receipt) throw agentFailure(339);
|
|
1237
|
+
const addresses = recipients.split(/[,;]/).map((address) => address.trim()).filter((address) => address !== "");
|
|
1238
|
+
state.receipts.set(number, {
|
|
1239
|
+
...receipt,
|
|
1240
|
+
sentTo: [...receipt.sentTo, addresses]
|
|
1241
|
+
});
|
|
1242
|
+
return xmlResponse(xmlDocument("xmlnyugtasendvalasz", [el("sikeres", true)]));
|
|
1243
|
+
}
|
|
1244
|
+
//#endregion
|
|
1245
|
+
//#region src/testing/fake-agent.ts
|
|
1246
|
+
const HANDLERS = {
|
|
1247
|
+
createInvoice: handleCreateInvoice,
|
|
1248
|
+
reverseInvoice: handleReverseInvoice,
|
|
1249
|
+
registerPayment: handleRegisterPayment,
|
|
1250
|
+
getInvoicePdf: handleGetInvoicePdf,
|
|
1251
|
+
getInvoiceXml: handleGetInvoiceXml,
|
|
1252
|
+
deleteProforma: handleDeleteProforma,
|
|
1253
|
+
createReceipt: handleCreateReceipt,
|
|
1254
|
+
reverseReceipt: handleReverseReceipt,
|
|
1255
|
+
getReceipt: handleGetReceipt,
|
|
1256
|
+
sendReceipt: handleSendReceipt,
|
|
1257
|
+
queryTaxpayer: handleQueryTaxpayer,
|
|
1258
|
+
connectPrincipal: handleConnectPrincipal
|
|
1259
|
+
};
|
|
1260
|
+
const NAMED_FAULTS = {
|
|
1261
|
+
ghostSuccess: {
|
|
1262
|
+
stage: "after",
|
|
1263
|
+
effect: "timeout"
|
|
1264
|
+
},
|
|
1265
|
+
timeout: {
|
|
1266
|
+
stage: "before",
|
|
1267
|
+
effect: "timeout"
|
|
1268
|
+
},
|
|
1269
|
+
networkError: {
|
|
1270
|
+
stage: "before",
|
|
1271
|
+
effect: "network"
|
|
1272
|
+
},
|
|
1273
|
+
serverError: {
|
|
1274
|
+
stage: "before",
|
|
1275
|
+
effect: "server-error"
|
|
1276
|
+
},
|
|
1277
|
+
maintenance: {
|
|
1278
|
+
stage: "before",
|
|
1279
|
+
effect: "code",
|
|
1280
|
+
code: 1
|
|
1281
|
+
},
|
|
1282
|
+
partialSuccess: {
|
|
1283
|
+
stage: "after",
|
|
1284
|
+
effect: "code",
|
|
1285
|
+
code: 56
|
|
1286
|
+
},
|
|
1287
|
+
testAccountLimit: {
|
|
1288
|
+
stage: "before",
|
|
1289
|
+
effect: "code",
|
|
1290
|
+
code: 167
|
|
1291
|
+
},
|
|
1292
|
+
duplicateCallId: {
|
|
1293
|
+
stage: "before",
|
|
1294
|
+
effect: "code",
|
|
1295
|
+
code: 338
|
|
1296
|
+
},
|
|
1297
|
+
duplicateOrderNumber: {
|
|
1298
|
+
stage: "before",
|
|
1299
|
+
effect: "code",
|
|
1300
|
+
code: 152
|
|
1301
|
+
}
|
|
1302
|
+
};
|
|
1303
|
+
const DEFAULT_SELLER = {
|
|
1304
|
+
name: "Kassza Teszt Kft.",
|
|
1305
|
+
taxNumber: "12345676-2-42",
|
|
1306
|
+
zip: "1111",
|
|
1307
|
+
city: "Budapest",
|
|
1308
|
+
address: "Teszt utca 1."
|
|
1309
|
+
};
|
|
1310
|
+
const DEFAULT_INVOICE_PREFIX = "KASSZA";
|
|
1311
|
+
const KNOWN_ACTIONS = new Set(Object.keys(AGENT_ACTIONS));
|
|
1312
|
+
function behaviorOf(fault) {
|
|
1313
|
+
if (typeof fault === "string") {
|
|
1314
|
+
const behavior = NAMED_FAULTS[fault];
|
|
1315
|
+
if (!behavior) throw new TypeError(`Ismeretlen hamis Agent hiba: ${String(fault)}`);
|
|
1316
|
+
return behavior;
|
|
1317
|
+
}
|
|
1318
|
+
if (!Number.isInteger(fault.code) || fault.code < 1) throw new TypeError(`A hibakód pozitív egész szám legyen, kapott: ${String(fault.code)}`);
|
|
1319
|
+
return {
|
|
1320
|
+
stage: fault.afterSuccess === true ? "after" : "before",
|
|
1321
|
+
effect: "code",
|
|
1322
|
+
code: fault.code,
|
|
1323
|
+
message: fault.message
|
|
1324
|
+
};
|
|
1325
|
+
}
|
|
1326
|
+
function pendingFault(fault, options) {
|
|
1327
|
+
const times = options.times ?? 1;
|
|
1328
|
+
if (!Number.isInteger(times) || times < 1) throw new TypeError(`A times értéke legalább 1 egész szám legyen, kapott: ${String(times)}`);
|
|
1329
|
+
if (options.action !== void 0 && !KNOWN_ACTIONS.has(options.action)) throw new TypeError(`Ismeretlen Agent művelet: ${String(options.action)}`);
|
|
1330
|
+
return {
|
|
1331
|
+
behavior: behaviorOf(fault),
|
|
1332
|
+
action: options.action,
|
|
1333
|
+
remaining: times
|
|
1334
|
+
};
|
|
1335
|
+
}
|
|
1336
|
+
function duplicateFlags(value) {
|
|
1337
|
+
if (typeof value === "boolean") return {
|
|
1338
|
+
invoices: value,
|
|
1339
|
+
receipts: value
|
|
1340
|
+
};
|
|
1341
|
+
return {
|
|
1342
|
+
invoices: value?.invoices === true,
|
|
1343
|
+
receipts: value?.receipts === true
|
|
1344
|
+
};
|
|
1345
|
+
}
|
|
1346
|
+
function normalizedTaxpayers(taxpayers) {
|
|
1347
|
+
return Object.fromEntries(Object.entries(taxpayers ?? {}).map(([taxNumber, taxpayer]) => [taxpayerKey(taxNumber), taxpayer]));
|
|
1348
|
+
}
|
|
1349
|
+
function seededPrincipals(options) {
|
|
1350
|
+
return new Map(Object.entries(options.principals ?? {}).map(([taxNumber, state]) => [taxpayerKey(taxNumber), {
|
|
1351
|
+
state,
|
|
1352
|
+
joinRequests: 0
|
|
1353
|
+
}]));
|
|
1354
|
+
}
|
|
1355
|
+
function createState(options) {
|
|
1356
|
+
const duplicates = duplicateFlags(options.rejectDuplicateOrderNumbers);
|
|
1357
|
+
return {
|
|
1358
|
+
now: options.now ?? (() => /* @__PURE__ */ new Date()),
|
|
1359
|
+
config: {
|
|
1360
|
+
seller: {
|
|
1361
|
+
...DEFAULT_SELLER,
|
|
1362
|
+
...options.seller
|
|
1363
|
+
},
|
|
1364
|
+
testAccount: options.testAccount ?? true,
|
|
1365
|
+
defaultInvoicePrefix: options.defaultInvoicePrefix ?? options.invoicePrefixes?.[0] ?? DEFAULT_INVOICE_PREFIX,
|
|
1366
|
+
invoicePrefixes: options.invoicePrefixes && new Set(options.invoicePrefixes),
|
|
1367
|
+
receiptPrefixes: options.receiptPrefixes && new Set(options.receiptPrefixes),
|
|
1368
|
+
uniqueInvoiceOrderNumbers: duplicates.invoices,
|
|
1369
|
+
uniqueReceiptOrderNumbers: duplicates.receipts,
|
|
1370
|
+
strictAuth: options.agentKeys !== void 0 || options.users !== void 0,
|
|
1371
|
+
agentKeys: new Set(options.agentKeys ?? []),
|
|
1372
|
+
taxpayers: normalizedTaxpayers(options.taxpayers)
|
|
1373
|
+
},
|
|
1374
|
+
invoices: /* @__PURE__ */ new Map(),
|
|
1375
|
+
receipts: /* @__PURE__ */ new Map(),
|
|
1376
|
+
counters: /* @__PURE__ */ new Map(),
|
|
1377
|
+
principals: seededPrincipals(options),
|
|
1378
|
+
delegates: /* @__PURE__ */ new Map(),
|
|
1379
|
+
users: new Map(Object.entries(options.users ?? {}))
|
|
1380
|
+
};
|
|
1381
|
+
}
|
|
1382
|
+
function timeoutError() {
|
|
1383
|
+
return new DOMException("A hamis Agent nem küldött választ (időtúllépés).", "TimeoutError");
|
|
1384
|
+
}
|
|
1385
|
+
function orderNumberOf(root) {
|
|
1386
|
+
return childText(findChild(root, "fejlec"), "rendelesSzam");
|
|
1387
|
+
}
|
|
1388
|
+
function faultFailure(behavior, root) {
|
|
1389
|
+
const code = behavior.code ?? 1;
|
|
1390
|
+
if (behavior.message !== void 0) return new FakeAgentFailure(code, behavior.message);
|
|
1391
|
+
if (code === 152) return agentFailure(152, `Már létező rendelésszám: ${orderNumberOf(root) ?? "XXX"}. Az ismétlődés engedélyezhető a Beállítások oldalon.`);
|
|
1392
|
+
return agentFailure(code);
|
|
1393
|
+
}
|
|
1394
|
+
function respondBefore(behavior, request) {
|
|
1395
|
+
if (behavior.effect === "timeout") throw timeoutError();
|
|
1396
|
+
if (behavior.effect === "network") throw new TypeError("fetch failed");
|
|
1397
|
+
if (behavior.effect === "server-error") return serverErrorResponse();
|
|
1398
|
+
return errorResponse(errorStyleFor(request.action, request.root), faultFailure(behavior, request.root));
|
|
1399
|
+
}
|
|
1400
|
+
function createFakeAgentFetch(options = {}) {
|
|
1401
|
+
let state = createState(options);
|
|
1402
|
+
const requests = [];
|
|
1403
|
+
const faults = [];
|
|
1404
|
+
const scheduleInitialFaults = () => {
|
|
1405
|
+
for (const scheduled of options.faults ?? []) faults.push(pendingFault(scheduled.fault, scheduled));
|
|
1406
|
+
};
|
|
1407
|
+
scheduleInitialFaults();
|
|
1408
|
+
const takeFault = (action) => {
|
|
1409
|
+
const index = faults.findIndex((fault) => fault.action === void 0 || fault.action === action);
|
|
1410
|
+
const fault = faults[index];
|
|
1411
|
+
if (!fault) return void 0;
|
|
1412
|
+
fault.remaining -= 1;
|
|
1413
|
+
if (fault.remaining === 0) faults.splice(index, 1);
|
|
1414
|
+
return fault.behavior;
|
|
1415
|
+
};
|
|
1416
|
+
const perform = (request) => {
|
|
1417
|
+
try {
|
|
1418
|
+
authenticate(state, credentialsOf(request.root));
|
|
1419
|
+
return {
|
|
1420
|
+
response: HANDLERS[request.action](state, request),
|
|
1421
|
+
ok: true
|
|
1422
|
+
};
|
|
1423
|
+
} catch (error) {
|
|
1424
|
+
if (!(error instanceof FakeAgentFailure)) throw error;
|
|
1425
|
+
return {
|
|
1426
|
+
response: errorResponse(errorStyleFor(request.action, request.root), error),
|
|
1427
|
+
ok: false
|
|
1428
|
+
};
|
|
1429
|
+
}
|
|
1430
|
+
};
|
|
1431
|
+
const handle = (action, xml, attachments) => {
|
|
1432
|
+
let request;
|
|
1433
|
+
try {
|
|
1434
|
+
request = parseFakeAgentRequest(action, xml, attachments);
|
|
1435
|
+
} catch (error) {
|
|
1436
|
+
if (!(error instanceof FakeAgentFailure)) throw error;
|
|
1437
|
+
return errorResponse(errorStyleFor(action, void 0), error);
|
|
1438
|
+
}
|
|
1439
|
+
const fault = takeFault(action);
|
|
1440
|
+
if (fault?.stage === "before") return respondBefore(fault, request);
|
|
1441
|
+
const { response, ok } = perform(request);
|
|
1442
|
+
if (fault?.effect === "timeout") throw timeoutError();
|
|
1443
|
+
if (fault && ok) return errorResponse(errorStyleFor(action, request.root), faultFailure(fault, request.root));
|
|
1444
|
+
return response;
|
|
1445
|
+
};
|
|
1446
|
+
const fakeFetch = async (input, init) => {
|
|
1447
|
+
init?.signal?.throwIfAborted();
|
|
1448
|
+
const record = await readFakeAgentForm(input, init);
|
|
1449
|
+
requests.push(record);
|
|
1450
|
+
if (record.action === void 0 || record.xml === void 0) return toFetchResponse(errorResponse("text", agentFailure(53)));
|
|
1451
|
+
return toFetchResponse(handle(record.action, record.xml, record.attachments));
|
|
1452
|
+
};
|
|
1453
|
+
return {
|
|
1454
|
+
fetch: fakeFetch,
|
|
1455
|
+
requests,
|
|
1456
|
+
get invoices() {
|
|
1457
|
+
return state.invoices;
|
|
1458
|
+
},
|
|
1459
|
+
get receipts() {
|
|
1460
|
+
return state.receipts;
|
|
1461
|
+
},
|
|
1462
|
+
fail(fault, faultOptions = {}) {
|
|
1463
|
+
faults.push(pendingFault(fault, faultOptions));
|
|
1464
|
+
},
|
|
1465
|
+
acceptDelegation(taxNumber) {
|
|
1466
|
+
acceptDelegation(state, taxNumber);
|
|
1467
|
+
},
|
|
1468
|
+
reset() {
|
|
1469
|
+
state = createState(options);
|
|
1470
|
+
requests.length = 0;
|
|
1471
|
+
faults.length = 0;
|
|
1472
|
+
scheduleInitialFaults();
|
|
1473
|
+
}
|
|
1474
|
+
};
|
|
1475
|
+
}
|
|
1476
|
+
//#endregion
|
|
6
1477
|
//#region src/testing/index.ts
|
|
7
1478
|
const MOCK_PDF = new TextEncoder().encode("%PDF-1.4\n1 0 obj << /Type /Catalog >> endobj\ntrailer << /Root 1 0 R >>\n%%EOF\n");
|
|
8
1479
|
function notFound(code, message) {
|
|
@@ -503,4 +1974,4 @@ function createMockKassza(options = {}) {
|
|
|
503
1974
|
};
|
|
504
1975
|
}
|
|
505
1976
|
//#endregion
|
|
506
|
-
export { MOCK_PDF, createMockKassza };
|
|
1977
|
+
export { CONNECT_PRINCIPAL_MESSAGES, MOCK_PDF, createFakeAgentFetch, createMockKassza };
|