kassza 0.12.0 → 0.14.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.en.md +48 -0
- package/README.md +427 -32
- package/agents/README.md +26 -6
- package/agents/api.md +218 -3
- package/agents/pitfalls.md +27 -3
- package/agents/recipes.md +280 -51
- package/agents/skills/kassza/SKILL.md +14 -8
- package/agents/skills/migrate-from-szamlazz-js/SKILL.md +39 -0
- package/dist/batch/index.cjs +346 -0
- package/dist/batch/index.d.cts +91 -0
- package/dist/batch/index.d.ts +91 -0
- package/dist/batch/index.js +339 -0
- package/dist/cli.cjs +643 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +643 -0
- package/dist/client-CLFvJCVW.cjs +1452 -0
- package/dist/{client-CL3fuH6A.js → client-Cvf-hTz_.js} +306 -515
- package/dist/client-DeWWQ-RZ.d.ts +341 -0
- package/dist/client-SVZu25MB.d.cts +341 -0
- package/dist/context-CFNKzStE.d.cts +449 -0
- package/dist/context-kb33TgzE.d.ts +449 -0
- package/dist/cookie-stores/index.cjs +21 -150
- package/dist/cookie-stores/index.d.cts +4 -63
- package/dist/cookie-stores/index.d.ts +4 -63
- package/dist/cookie-stores/index.js +3 -144
- package/dist/create-CflXrPip.js +204 -0
- package/dist/create-CvUvLUaT.cjs +257 -0
- package/dist/{create-once-D0pwuenl.cjs → create-once-9yxR_Er_.cjs} +291 -33
- package/dist/create-once-Bh6fOWkW.d.cts +20 -0
- package/dist/{create-once-CqdYmQD8.js → create-once-Ca2gMk1h.js} +250 -34
- package/dist/create-once-VKp0tVow.d.ts +20 -0
- 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 +29 -0
- package/dist/data-link/index.d.ts +29 -0
- package/dist/data-link/index.js +224 -0
- package/dist/delegation/index.cjs +35 -34
- package/dist/delegation/index.d.cts +2 -1
- package/dist/delegation/index.d.ts +2 -1
- package/dist/delegation/index.js +4 -3
- package/dist/{errors-DLrb0g64.js → errors-DtN4g5Z9.js} +9 -1
- package/dist/{errors-DxeuTslP.cjs → errors-EE96_6D_.cjs} +20 -0
- package/dist/get-BdMTseh4.cjs +271 -0
- package/dist/get-Byc9T5WO.d.cts +151 -0
- package/dist/get-Byc9T5WO.d.ts +151 -0
- package/dist/get-CZEShCcj.js +260 -0
- package/dist/index-BhUPY_EH.d.cts +109 -0
- package/dist/index-BqGgQ4t3.d.ts +109 -0
- package/dist/{index-CYAGCdKJ.d.cts → index-C-7yWV7L.d.cts} +24 -1
- package/dist/{index-CYAGCdKJ.d.ts → index-C-7yWV7L.d.ts} +24 -1
- package/dist/index.cjs +19 -5
- package/dist/index.d.cts +11 -19
- package/dist/index.d.ts +11 -19
- package/dist/index.js +6 -6
- package/dist/ipn/index.cjs +26 -5
- package/dist/ipn/index.d.cts +12 -1
- package/dist/ipn/index.d.ts +12 -1
- package/dist/ipn/index.js +26 -6
- package/dist/issue-Bin4tKD_.cjs +988 -0
- package/dist/issue-DMA1Nbr1.js +905 -0
- package/dist/journal/index.cjs +454 -0
- package/dist/journal/index.d.cts +18 -0
- package/dist/journal/index.d.ts +18 -0
- package/dist/journal/index.js +445 -0
- package/dist/journal-DvI81Kt7.d.cts +114 -0
- package/dist/journal-Y9qrIB8G.d.ts +114 -0
- 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 +2 -1
- package/dist/money/index.d.cts +2 -2
- package/dist/money/index.d.ts +2 -2
- package/dist/money/index.js +2 -2
- package/dist/{money-DAA7OwiO.js → money-Cw457SD6.js} +120 -12
- package/dist/{money-DrhGkWHW.cjs → money-K9j0wPit.cjs} +124 -10
- 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-BNbc8U0R.cjs +203 -0
- package/dist/nav-BcCerwWS.js +156 -0
- package/dist/node/index.cjs +124 -0
- package/dist/node/index.d.cts +35 -0
- package/dist/node/index.d.ts +35 -0
- package/dist/node/index.js +120 -0
- package/dist/observe/index.cjs +311 -0
- package/dist/observe/index.d.cts +53 -0
- package/dist/observe/index.d.ts +53 -0
- package/dist/observe/index.js +303 -0
- package/dist/once-BN_3B5OF.cjs +103 -0
- package/dist/once-CqqZxsXG.js +74 -0
- package/dist/parse-Cr7yQ3_z.js +291 -0
- package/dist/parse-DOA2XQ3e.cjs +380 -0
- package/dist/payments/barion.cjs +26 -2
- package/dist/payments/barion.d.cts +2 -2
- package/dist/payments/barion.d.ts +2 -2
- package/dist/payments/barion.js +26 -2
- package/dist/payments/index.cjs +7 -2
- package/dist/payments/index.d.cts +4 -4
- package/dist/payments/index.d.ts +4 -4
- package/dist/payments/index.js +3 -3
- package/dist/payments/paypal.cjs +16 -2
- package/dist/payments/paypal.d.cts +2 -2
- package/dist/payments/paypal.d.ts +2 -2
- package/dist/payments/paypal.js +16 -2
- package/dist/payments/revolut.cjs +17 -3
- package/dist/payments/revolut.d.cts +2 -2
- package/dist/payments/revolut.d.ts +2 -2
- package/dist/payments/revolut.js +17 -3
- package/dist/payments/simplepay.cjs +37 -5
- package/dist/payments/simplepay.d.cts +2 -2
- package/dist/payments/simplepay.d.ts +2 -2
- package/dist/payments/simplepay.js +37 -5
- package/dist/payments/stripe.cjs +20 -3
- package/dist/payments/stripe.d.cts +2 -2
- package/dist/payments/stripe.d.ts +2 -2
- package/dist/payments/stripe.js +20 -3
- package/dist/push-BXj0Sf0Z.d.ts +52 -0
- package/dist/push-D4nNbCNV.d.cts +52 -0
- package/dist/reference-B5TATqb5.js +124 -0
- package/dist/reference-BIdYMK0t.cjs +183 -0
- package/dist/reports/index.cjs +11 -164
- package/dist/reports/index.d.cts +1 -1
- package/dist/reports/index.d.ts +1 -1
- 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-B2eFh3D-.js +219 -0
- package/dist/serialize-CquIsxA-.cjs +290 -0
- package/dist/server-BrJUbXs7.js +1505 -0
- package/dist/server-Dw9j8Mnd.cjs +1558 -0
- package/dist/session-Ckl5eJhV.d.ts +7 -0
- package/dist/{session-CKOuE6Jc.cjs → session-DeM5vjvC.cjs} +69 -13
- package/dist/{session-rMKaJcmq.js → session-SaEEXu2N.js} +58 -14
- package/dist/session-YbChChx7.d.cts +7 -0
- package/dist/storage/fs.cjs +1 -1
- package/dist/storage/fs.js +1 -1
- package/dist/storage/index.cjs +1 -1
- package/dist/storage/index.js +1 -1
- package/dist/store-C1rHd9DB.d.cts +19 -0
- package/dist/store-C1rHd9DB.d.ts +19 -0
- package/dist/stores/index.cjs +24 -0
- package/dist/stores/index.d.cts +4 -0
- package/dist/stores/index.d.ts +4 -0
- package/dist/stores/index.js +3 -0
- package/dist/stores-BNrS0dWl.cjs +506 -0
- package/dist/stores-DhjGBrl_.js +441 -0
- package/dist/testing/index.cjs +1500 -15
- package/dist/testing/index.d.cts +198 -3
- package/dist/testing/index.d.ts +198 -3
- package/dist/testing/index.js +1498 -15
- package/dist/{types-COf1LAD-.d.ts → types-B1A8mUIE.d.cts} +14 -2
- package/dist/{types-COf1LAD-.d.cts → types-ByAEvGsZ.d.ts} +14 -2
- package/dist/{types-k--zHf4l.d.ts → types-D1zDOH_F.d.ts} +1 -1
- package/dist/{types-DH8QoNZK.d.cts → types-lnKkQdot.d.cts} +1 -1
- package/dist/warnings-B3DXnveC.d.cts +31 -0
- package/dist/warnings-B3DXnveC.d.ts +31 -0
- package/dist/warnings-DeIw5RFj.cjs +20 -0
- package/dist/warnings-DwTl5J-2.js +15 -0
- package/dist/{webhook-D4lvtex1.js → webhook-CQVShAfI.js} +47 -26
- package/dist/{webhook-C76bV-4R.cjs → webhook-Ckj-_hPD.cjs} +70 -25
- package/dist/webhook-CmdhGiH5.d.cts +11 -0
- package/dist/webhook-D6lEejob.d.ts +11 -0
- package/llms.txt +6 -5
- package/package.json +134 -4
- package/dist/client-CickRRFr.d.ts +0 -838
- package/dist/client-CsmGIFRS.cjs +0 -1637
- package/dist/client-DvWZoX_E.d.cts +0 -838
- package/dist/issue-BsyYdrIG.cjs +0 -1531
- package/dist/issue-C6Fcjvln.js +0 -1274
- package/dist/session-Dm_45x8K.d.cts +0 -11
- package/dist/session-Dm_45x8K.d.ts +0 -11
- package/dist/webhook-CfaDgcL0.d.cts +0 -6
- package/dist/webhook-q2OzNwd7.d.ts +0 -6
|
@@ -0,0 +1,1452 @@
|
|
|
1
|
+
const require_create_once = require("./create-once-9yxR_Er_.cjs");
|
|
2
|
+
const require_errors = require("./errors-EE96_6D_.cjs");
|
|
3
|
+
const require_binary = require("./binary-B89HM03_.cjs");
|
|
4
|
+
const require_serialize = require("./serialize-CquIsxA-.cjs");
|
|
5
|
+
const require_parse = require("./parse-DOA2XQ3e.cjs");
|
|
6
|
+
const require_session = require("./session-DeM5vjvC.cjs");
|
|
7
|
+
const require_warnings = require("./warnings-DeIw5RFj.cjs");
|
|
8
|
+
const require_issue = require("./issue-Bin4tKD_.cjs");
|
|
9
|
+
const require_vat = require("./vat-g35srbNG.cjs");
|
|
10
|
+
const require_money = require("./money-K9j0wPit.cjs");
|
|
11
|
+
const require_reference = require("./reference-BIdYMK0t.cjs");
|
|
12
|
+
const require_get = require("./get-BdMTseh4.cjs");
|
|
13
|
+
const require_create = require("./create-CvUvLUaT.cjs");
|
|
14
|
+
//#region src/core/attempt-ledger.ts
|
|
15
|
+
const ATTEMPT_LEDGER_TTL_SECONDS = 86400;
|
|
16
|
+
const ATTEMPT_LEDGER_KEY_PREFIX = "szamlazz:attempts:";
|
|
17
|
+
const COUNTED_CATEGORIES = /* @__PURE__ */ new Set([
|
|
18
|
+
"auth",
|
|
19
|
+
"account",
|
|
20
|
+
"validation",
|
|
21
|
+
"maintenance",
|
|
22
|
+
"rate_limit",
|
|
23
|
+
"network",
|
|
24
|
+
"timeout",
|
|
25
|
+
"unexpected_response",
|
|
26
|
+
"unknown"
|
|
27
|
+
]);
|
|
28
|
+
function countsAsFailedAttempt(error) {
|
|
29
|
+
return COUNTED_CATEGORIES.has(error.category);
|
|
30
|
+
}
|
|
31
|
+
const encoder = new TextEncoder();
|
|
32
|
+
async function attemptLedgerKey(request) {
|
|
33
|
+
const attachments = (request.attachments ?? []).map((attachment) => `${attachment.filename}:${attachment.size}`).join("|");
|
|
34
|
+
const digest = await crypto.subtle.digest("SHA-256", encoder.encode(`${request.action}\n${request.xml}\n${attachments}`));
|
|
35
|
+
const hex = Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0"));
|
|
36
|
+
return `${ATTEMPT_LEDGER_KEY_PREFIX}${hex.join("")}`;
|
|
37
|
+
}
|
|
38
|
+
function parseCount(value) {
|
|
39
|
+
if (value === void 0 || value === null) return 0;
|
|
40
|
+
const parsed = Number.parseInt(value, 10);
|
|
41
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : 0;
|
|
42
|
+
}
|
|
43
|
+
function createLocalCounter() {
|
|
44
|
+
const counts = /* @__PURE__ */ new Map();
|
|
45
|
+
const get = (key) => {
|
|
46
|
+
const entry = counts.get(key);
|
|
47
|
+
if (!entry) return 0;
|
|
48
|
+
if (entry.expiresAt <= Date.now()) {
|
|
49
|
+
counts.delete(key);
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
return entry.count;
|
|
53
|
+
};
|
|
54
|
+
return {
|
|
55
|
+
get,
|
|
56
|
+
bump(key) {
|
|
57
|
+
const count = get(key) + 1;
|
|
58
|
+
counts.delete(key);
|
|
59
|
+
counts.set(key, {
|
|
60
|
+
count,
|
|
61
|
+
expiresAt: Date.now() + ATTEMPT_LEDGER_TTL_SECONDS * 1e3
|
|
62
|
+
});
|
|
63
|
+
if (counts.size > 1e3) {
|
|
64
|
+
const oldest = counts.keys().next().value;
|
|
65
|
+
if (oldest !== void 0) counts.delete(oldest);
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
clear(key) {
|
|
69
|
+
counts.delete(key);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function createAttemptLedger(store) {
|
|
74
|
+
const local = createLocalCounter();
|
|
75
|
+
const unpersisted = createLocalCounter();
|
|
76
|
+
return {
|
|
77
|
+
async failures(key) {
|
|
78
|
+
return parseCount(await store.get(key)) + unpersisted.get(key);
|
|
79
|
+
},
|
|
80
|
+
fallbackFailures(key) {
|
|
81
|
+
return local.get(key);
|
|
82
|
+
},
|
|
83
|
+
async recordFailure(key) {
|
|
84
|
+
local.bump(key);
|
|
85
|
+
try {
|
|
86
|
+
if (store.increment) {
|
|
87
|
+
await store.increment(key, ATTEMPT_LEDGER_TTL_SECONDS);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const current = parseCount(await store.get(key));
|
|
91
|
+
await store.set(key, String(current + 1), ATTEMPT_LEDGER_TTL_SECONDS);
|
|
92
|
+
} catch (error) {
|
|
93
|
+
unpersisted.bump(key);
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
async reset(key) {
|
|
98
|
+
local.clear(key);
|
|
99
|
+
unpersisted.clear(key);
|
|
100
|
+
await store.delete(key);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function attemptLimitError(action, key, failures) {
|
|
105
|
+
return new require_errors.SzamlazzError(`Ezt a kérést már ${failures} alkalommal sikertelenül küldtük el, ezért a kassza nem küldi el újra.`, {
|
|
106
|
+
category: "attempt_limit",
|
|
107
|
+
action,
|
|
108
|
+
details: { attemptKey: key },
|
|
109
|
+
hint: "A Számlázz.hu szabályai szerint öt sikertelen próbálkozás után emberi beavatkozás kell, különben kitiltás jöhet. Javítsd a hibát, majd a kassza.resetAttempts(error) hívással töröld a számlálót."
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
const DEFAULT_SAFE_ATTEMPTS = 3;
|
|
113
|
+
const DEFAULT_RETRY_DELAY_MS = 1e3;
|
|
114
|
+
const RETRY_JITTER = .2;
|
|
115
|
+
function readEnv(name) {
|
|
116
|
+
const value = (globalThis.process?.env)?.[name]?.trim();
|
|
117
|
+
return value ? value : void 0;
|
|
118
|
+
}
|
|
119
|
+
function configurationError(message) {
|
|
120
|
+
return new require_errors.SzamlazzError(message, { category: "configuration" });
|
|
121
|
+
}
|
|
122
|
+
function resolveCredentials(options) {
|
|
123
|
+
const agentKey = options.agentKey?.trim() || (options.username ? void 0 : readEnv("SZAMLAZZ_AGENT_KEY"));
|
|
124
|
+
if (agentKey) {
|
|
125
|
+
if (agentKey !== agentKey.toLowerCase()) throw configurationError("Az Agent kulcs nagybetűt tartalmaz. A Számlázz.hu csak kisbetűs kulcsot fogad el, másold ki újra a kulcsot.");
|
|
126
|
+
return [require_serialize.el("szamlaagentkulcs", agentKey)];
|
|
127
|
+
}
|
|
128
|
+
if (options.username && options.password) return [require_serialize.el("felhasznalo", options.username), require_serialize.el("jelszo", options.password)];
|
|
129
|
+
throw configurationError("Hiányzik az Agent kulcs. Add meg az agentKey opciót, vagy állítsd be a SZAMLAZZ_AGENT_KEY környezeti változót.");
|
|
130
|
+
}
|
|
131
|
+
function toBlob(attachment) {
|
|
132
|
+
const type = attachment.contentType ?? "application/octet-stream";
|
|
133
|
+
if (attachment.content instanceof Blob) return attachment.content;
|
|
134
|
+
return new Blob([attachment.content], { type });
|
|
135
|
+
}
|
|
136
|
+
function buildFormData(request) {
|
|
137
|
+
const form = new FormData();
|
|
138
|
+
form.append(require_create_once.AGENT_ACTIONS[request.action], new Blob([request.xml], { type: "text/xml; charset=UTF-8" }), "request.xml");
|
|
139
|
+
request.attachments?.forEach((attachment, index) => {
|
|
140
|
+
form.append(`attachfile${index + 1}`, toBlob(attachment), attachment.filename);
|
|
141
|
+
});
|
|
142
|
+
return form;
|
|
143
|
+
}
|
|
144
|
+
function isAbortError(error) {
|
|
145
|
+
return error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError");
|
|
146
|
+
}
|
|
147
|
+
function sleep(ms, signal) {
|
|
148
|
+
return new Promise((resolve, reject) => {
|
|
149
|
+
if (signal?.aborted) {
|
|
150
|
+
reject(signal.reason);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const timer = setTimeout(() => {
|
|
154
|
+
signal?.removeEventListener("abort", onAbort);
|
|
155
|
+
resolve();
|
|
156
|
+
}, ms);
|
|
157
|
+
const onAbort = () => {
|
|
158
|
+
clearTimeout(timer);
|
|
159
|
+
reject(signal?.reason);
|
|
160
|
+
};
|
|
161
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
function hookWarning(name, action, error) {
|
|
165
|
+
return {
|
|
166
|
+
kind: "hook",
|
|
167
|
+
message: `A(z) ${name} hook hibát dobott, a kassza figyelmen kívül hagyta.`,
|
|
168
|
+
error,
|
|
169
|
+
action,
|
|
170
|
+
operation: name
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function callHook(hooks, name, event) {
|
|
174
|
+
const hook = hooks[name];
|
|
175
|
+
if (!hook) return;
|
|
176
|
+
try {
|
|
177
|
+
const result = hook(event);
|
|
178
|
+
if (result instanceof Promise) result.catch((error) => require_warnings.emitWarning(hooks.onWarning, hookWarning(name, event.action, error)));
|
|
179
|
+
} catch (error) {
|
|
180
|
+
require_warnings.emitWarning(hooks.onWarning, hookWarning(name, event.action, error));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function parseRetryAfter(value, now) {
|
|
184
|
+
if (value === null) return void 0;
|
|
185
|
+
const trimmed = value.trim();
|
|
186
|
+
if (/^\d+$/.test(trimmed)) return Number(trimmed) * 1e3;
|
|
187
|
+
const date = Date.parse(trimmed);
|
|
188
|
+
if (Number.isNaN(date)) return void 0;
|
|
189
|
+
return Math.max(0, date - now);
|
|
190
|
+
}
|
|
191
|
+
function retryDelay(baseMs, attempt, random = Math.random()) {
|
|
192
|
+
const backoff = baseMs * 2 ** (attempt - 1);
|
|
193
|
+
return Math.round(backoff * (.8 + 2 * RETRY_JITTER * random));
|
|
194
|
+
}
|
|
195
|
+
function resolveLedgerMode(value) {
|
|
196
|
+
if (value === void 0 || value === "fail-open" || value === "fail-closed") return value ?? "fail-open";
|
|
197
|
+
throw configurationError(`Az attemptLedgerMode értéke 'fail-open' vagy 'fail-closed' lehet, kapott: ${String(value)}`);
|
|
198
|
+
}
|
|
199
|
+
function storeUnavailableError(action, error) {
|
|
200
|
+
return new require_errors.SzamlazzError("A próbálkozás-napló tárolója nem érhető el, ezért a kassza nem küldte el a kérést.", {
|
|
201
|
+
category: "store_unavailable",
|
|
202
|
+
action,
|
|
203
|
+
cause: error,
|
|
204
|
+
hint: "Az attemptLedgerMode: 'fail-closed' beállítás miatt a kassza nem küld kérést, amíg a napló (például a Redis) nem elérhető. Állítsd helyre a tárolót, vagy válts 'fail-open' módra."
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
function clampAttempts(value) {
|
|
208
|
+
if (value === void 0) return DEFAULT_SAFE_ATTEMPTS;
|
|
209
|
+
if (!Number.isInteger(value) || value < 1) throw configurationError(`A maxAttempts értéke legalább 1 egész szám legyen, kapott: ${value}`);
|
|
210
|
+
return Math.min(value, 5);
|
|
211
|
+
}
|
|
212
|
+
function resolveCooldown(value) {
|
|
213
|
+
if (value === void 0) return 0;
|
|
214
|
+
if (!Number.isFinite(value) || value < 0) throw configurationError(`A maintenanceCooldownMs értéke nemnegatív szám legyen, kapott: ${value}`);
|
|
215
|
+
return value;
|
|
216
|
+
}
|
|
217
|
+
function attachmentSize(attachment) {
|
|
218
|
+
const { content } = attachment;
|
|
219
|
+
if (typeof content === "string") return new TextEncoder().encode(content).byteLength;
|
|
220
|
+
if (content instanceof Blob) return content.size;
|
|
221
|
+
return content.byteLength;
|
|
222
|
+
}
|
|
223
|
+
function maintenanceCooldownError(action, remainingMs) {
|
|
224
|
+
return new require_errors.SzamlazzError(`A Számlázz.hu karbantartás miatt nem érhető el, a kassza még ${Math.ceil(remainingMs / 1e3)} másodpercig nem küld kérést.`, {
|
|
225
|
+
category: "maintenance",
|
|
226
|
+
action,
|
|
227
|
+
hint: "A maintenanceCooldownMs beállítás miatt a kérés el sem indult. Válts tartalék folyamatra (például kézi nyugtatömbre), vagy próbáld később."
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
function createAgentContext(options = {}) {
|
|
231
|
+
const credentials = resolveCredentials(options);
|
|
232
|
+
const endpoint = options.endpoint ?? "https://www.szamlazz.hu/szamla/";
|
|
233
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
234
|
+
if (typeof fetchImpl !== "function") throw configurationError("Nem található fetch implementáció. Add meg a fetch opciót.");
|
|
235
|
+
const timeoutMs = options.timeoutMs ?? 6e4;
|
|
236
|
+
const safeAttempts = clampAttempts(options.maxAttempts);
|
|
237
|
+
const retryDelayMs = options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;
|
|
238
|
+
const cookieStore = options.cookieStore === false ? void 0 : options.cookieStore ?? require_session.memoryCookieStore();
|
|
239
|
+
const sessionSecret = credentials.map((node) => String(node.content)).join("|");
|
|
240
|
+
let sessionKeyPromise;
|
|
241
|
+
const resolveSessionKey = () => {
|
|
242
|
+
sessionKeyPromise ??= require_session.sessionKeyFor(sessionSecret);
|
|
243
|
+
return sessionKeyPromise;
|
|
244
|
+
};
|
|
245
|
+
const hooks = options.hooks ?? {};
|
|
246
|
+
const warn = (warning) => require_warnings.emitWarning(hooks.onWarning, warning);
|
|
247
|
+
const ledger = options.attemptLedger ? createAttemptLedger(options.attemptLedger) : void 0;
|
|
248
|
+
const ledgerMode = resolveLedgerMode(options.attemptLedgerMode);
|
|
249
|
+
async function ignoreStoreFailure(operation, action, run) {
|
|
250
|
+
try {
|
|
251
|
+
return await run();
|
|
252
|
+
} catch (error) {
|
|
253
|
+
warn({
|
|
254
|
+
kind: "session",
|
|
255
|
+
message: `A session cookie tároló "${operation}" művelete sikertelen, a kérés session nélkül folytatódik.`,
|
|
256
|
+
error,
|
|
257
|
+
action,
|
|
258
|
+
operation
|
|
259
|
+
});
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
const cooldownMs = resolveCooldown(options.maintenanceCooldownMs);
|
|
264
|
+
let blockedUntil = 0;
|
|
265
|
+
async function send(request) {
|
|
266
|
+
const cookie = cookieStore ? await ignoreStoreFailure("get", request.action, async () => cookieStore.get(await resolveSessionKey())) : void 0;
|
|
267
|
+
request.signal?.throwIfAborted();
|
|
268
|
+
const headers = new Headers({ Accept: "application/xml, application/pdf, text/plain, */*" });
|
|
269
|
+
if (cookie) headers.set("Cookie", cookie);
|
|
270
|
+
const timeoutSignal = AbortSignal.timeout(timeoutMs);
|
|
271
|
+
const signal = request.signal ? AbortSignal.any([request.signal, timeoutSignal]) : timeoutSignal;
|
|
272
|
+
let response;
|
|
273
|
+
let body;
|
|
274
|
+
try {
|
|
275
|
+
response = await fetchImpl(endpoint, {
|
|
276
|
+
method: "POST",
|
|
277
|
+
headers,
|
|
278
|
+
body: buildFormData(request),
|
|
279
|
+
signal
|
|
280
|
+
});
|
|
281
|
+
body = new Uint8Array(await response.arrayBuffer());
|
|
282
|
+
} catch (error) {
|
|
283
|
+
if (request.signal?.aborted) throw request.signal.reason;
|
|
284
|
+
if (timeoutSignal.aborted || isAbortError(error)) throw new require_errors.SzamlazzError(`A Számlázz.hu nem válaszolt ${timeoutMs} ms alatt.`, {
|
|
285
|
+
category: "timeout",
|
|
286
|
+
action: request.action,
|
|
287
|
+
cause: error
|
|
288
|
+
});
|
|
289
|
+
throw new require_errors.SzamlazzError("Hálózati hiba a Számlázz.hu elérésekor.", {
|
|
290
|
+
category: "network",
|
|
291
|
+
action: request.action,
|
|
292
|
+
cause: error
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
if (cookieStore) {
|
|
296
|
+
const merged = require_session.mergeSetCookies(cookie, response.headers);
|
|
297
|
+
if (merged) await ignoreStoreFailure("set", request.action, async () => cookieStore.set(await resolveSessionKey(), merged, require_session.SESSION_TTL_SECONDS));
|
|
298
|
+
}
|
|
299
|
+
return {
|
|
300
|
+
response: require_parse.createAgentResponse(request.action, response.status, response.headers, body),
|
|
301
|
+
sessionReused: Boolean(cookie)
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
async function resetSession() {
|
|
305
|
+
if (cookieStore) await ignoreStoreFailure("delete", void 0, async () => cookieStore.delete(await resolveSessionKey()));
|
|
306
|
+
}
|
|
307
|
+
async function resetAttempts(key) {
|
|
308
|
+
if (ledger) await ledger.reset(key);
|
|
309
|
+
}
|
|
310
|
+
async function ledgerKeyFor(request) {
|
|
311
|
+
if (!ledger) return void 0;
|
|
312
|
+
return attemptLedgerKey({
|
|
313
|
+
action: request.action,
|
|
314
|
+
xml: request.xml,
|
|
315
|
+
attachments: (request.attachments ?? []).map((attachment) => ({
|
|
316
|
+
filename: attachment.filename,
|
|
317
|
+
size: attachmentSize(attachment)
|
|
318
|
+
}))
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
function ledgerWarning(operation, action, error) {
|
|
322
|
+
warn({
|
|
323
|
+
kind: "ledger",
|
|
324
|
+
message: `A próbálkozás-napló tárolójának "${operation}" művelete sikertelen. A kassza a folyamaton belüli számlálót használja, a folyamatok közötti védelem most nem él.`,
|
|
325
|
+
error,
|
|
326
|
+
action,
|
|
327
|
+
operation
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
async function readFailures(action, key) {
|
|
331
|
+
if (!ledger || key === void 0) return 0;
|
|
332
|
+
try {
|
|
333
|
+
return await ledger.failures(key);
|
|
334
|
+
} catch (error) {
|
|
335
|
+
if (ledgerMode === "fail-closed") throw storeUnavailableError(action, error);
|
|
336
|
+
ledgerWarning("get", action, error);
|
|
337
|
+
return ledger.fallbackFailures(key);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
async function recordFailure(action, key) {
|
|
341
|
+
if (!ledger || key === void 0) return;
|
|
342
|
+
try {
|
|
343
|
+
await ledger.recordFailure(key);
|
|
344
|
+
} catch (error) {
|
|
345
|
+
ledgerWarning("increment", action, error);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
async function clearFailures(action, key) {
|
|
349
|
+
if (!ledger || key === void 0) return;
|
|
350
|
+
try {
|
|
351
|
+
await ledger.reset(key);
|
|
352
|
+
} catch (error) {
|
|
353
|
+
ledgerWarning("delete", action, error);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
function assertNoCooldown(action) {
|
|
357
|
+
const remainingMs = blockedUntil - Date.now();
|
|
358
|
+
if (remainingMs > 0) throw maintenanceCooldownError(action, remainingMs);
|
|
359
|
+
}
|
|
360
|
+
async function execute(request, parse) {
|
|
361
|
+
const maxAttempts = request.safeToRetry ? safeAttempts : 1;
|
|
362
|
+
const ledgerKey = await ledgerKeyFor(request);
|
|
363
|
+
const requestId = crypto.randomUUID();
|
|
364
|
+
for (let attempt = 1;; attempt++) {
|
|
365
|
+
assertNoCooldown(request.action);
|
|
366
|
+
const failures = await readFailures(request.action, ledgerKey);
|
|
367
|
+
if (ledgerKey !== void 0 && failures >= 5) throw attemptLimitError(request.action, ledgerKey, failures);
|
|
368
|
+
const startedAt = Date.now();
|
|
369
|
+
let retryAfterMs;
|
|
370
|
+
const base = {
|
|
371
|
+
action: request.action,
|
|
372
|
+
attempt,
|
|
373
|
+
requestId
|
|
374
|
+
};
|
|
375
|
+
callHook(hooks, "onRequest", base);
|
|
376
|
+
try {
|
|
377
|
+
const { response, sessionReused } = await send(request);
|
|
378
|
+
retryAfterMs = parseRetryAfter(response.headers.get("retry-after"), Date.now());
|
|
379
|
+
callHook(hooks, "onResponse", {
|
|
380
|
+
...base,
|
|
381
|
+
status: response.status,
|
|
382
|
+
durationMs: Date.now() - startedAt,
|
|
383
|
+
responseBytes: response.body.byteLength,
|
|
384
|
+
sessionReused
|
|
385
|
+
});
|
|
386
|
+
const result = await parse(response);
|
|
387
|
+
if (failures > 0) await clearFailures(request.action, ledgerKey);
|
|
388
|
+
callHook(hooks, "onComplete", {
|
|
389
|
+
...base,
|
|
390
|
+
outcome: "success",
|
|
391
|
+
durationMs: Date.now() - startedAt,
|
|
392
|
+
willRetry: false
|
|
393
|
+
});
|
|
394
|
+
return result;
|
|
395
|
+
} catch (error) {
|
|
396
|
+
if (!(error instanceof require_errors.SzamlazzError)) {
|
|
397
|
+
callHook(hooks, "onComplete", {
|
|
398
|
+
...base,
|
|
399
|
+
outcome: "error",
|
|
400
|
+
durationMs: Date.now() - startedAt,
|
|
401
|
+
willRetry: false
|
|
402
|
+
});
|
|
403
|
+
throw error;
|
|
404
|
+
}
|
|
405
|
+
if (countsAsFailedAttempt(error)) await recordFailure(request.action, ledgerKey);
|
|
406
|
+
if (error.category === "maintenance" && cooldownMs > 0) blockedUntil = Date.now() + cooldownMs;
|
|
407
|
+
const willRetry = error.retryable && attempt < maxAttempts && !(error.category === "maintenance" && cooldownMs > 0) && (retryAfterMs === void 0 || retryAfterMs <= 6e4);
|
|
408
|
+
callHook(hooks, "onError", {
|
|
409
|
+
...base,
|
|
410
|
+
error,
|
|
411
|
+
willRetry
|
|
412
|
+
});
|
|
413
|
+
callHook(hooks, "onComplete", {
|
|
414
|
+
...base,
|
|
415
|
+
outcome: "error",
|
|
416
|
+
durationMs: Date.now() - startedAt,
|
|
417
|
+
error,
|
|
418
|
+
willRetry
|
|
419
|
+
});
|
|
420
|
+
if (error.category === "auth") await resetSession();
|
|
421
|
+
if (!willRetry) throw error;
|
|
422
|
+
await sleep(Math.max(retryDelay(retryDelayMs, attempt), retryAfterMs ?? 0), request.signal);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
return {
|
|
427
|
+
credentials,
|
|
428
|
+
warn,
|
|
429
|
+
execute,
|
|
430
|
+
resetSession,
|
|
431
|
+
resetAttempts
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
//#endregion
|
|
435
|
+
//#region src/invoices/create-response.ts
|
|
436
|
+
function readRawResponse(response) {
|
|
437
|
+
require_parse.throwIfAnyError(response);
|
|
438
|
+
const headers = require_parse.readDocumentHeaders(response.headers);
|
|
439
|
+
const fromHeaders = {
|
|
440
|
+
number: headers.number,
|
|
441
|
+
netTotal: headers.netTotal,
|
|
442
|
+
grossTotal: headers.grossTotal,
|
|
443
|
+
outstanding: void 0,
|
|
444
|
+
buyerAccountUrl: headers.buyerAccountUrl,
|
|
445
|
+
pdf: void 0
|
|
446
|
+
};
|
|
447
|
+
if (response.isPdf) return {
|
|
448
|
+
...fromHeaders,
|
|
449
|
+
pdf: response.body
|
|
450
|
+
};
|
|
451
|
+
if (require_parse.looksLikeXml(response)) {
|
|
452
|
+
const root = require_parse.parseResponseXml(response);
|
|
453
|
+
require_parse.throwIfXmlFailure(root, response);
|
|
454
|
+
const pdfBase64 = require_serialize.childText(root, "pdf");
|
|
455
|
+
return {
|
|
456
|
+
number: require_serialize.childText(root, "szamlaszam") ?? headers.number,
|
|
457
|
+
netTotal: require_serialize.childNumber(root, "szamlanetto") ?? headers.netTotal,
|
|
458
|
+
grossTotal: require_serialize.childNumber(root, "szamlabrutto") ?? headers.grossTotal,
|
|
459
|
+
outstanding: require_serialize.childNumber(root, "kintlevoseg"),
|
|
460
|
+
buyerAccountUrl: require_serialize.childText(root, "vevoifiokurl") ?? headers.buyerAccountUrl,
|
|
461
|
+
pdf: pdfBase64 === void 0 ? void 0 : require_binary.base64ToBytes(pdfBase64)
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
const done = require_parse.parseDoneText(response.text());
|
|
465
|
+
if (done) return {
|
|
466
|
+
...fromHeaders,
|
|
467
|
+
number: done.number ?? headers.number
|
|
468
|
+
};
|
|
469
|
+
if (headers.number !== void 0) return fromHeaders;
|
|
470
|
+
throw require_parse.unexpectedResponse(response, "Számlaszámot vagy PDF-et vártunk.");
|
|
471
|
+
}
|
|
472
|
+
function totalsFor(raw, items) {
|
|
473
|
+
if (raw.netTotal !== void 0 && raw.grossTotal !== void 0) return {
|
|
474
|
+
netTotal: raw.netTotal,
|
|
475
|
+
grossTotal: raw.grossTotal
|
|
476
|
+
};
|
|
477
|
+
const computed = require_money.summarizeItems(items);
|
|
478
|
+
return {
|
|
479
|
+
netTotal: raw.netTotal ?? computed.netAmount,
|
|
480
|
+
grossTotal: raw.grossTotal ?? computed.grossAmount
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
function parseCreateInvoiceResponse(response, items = []) {
|
|
484
|
+
const raw = readRawResponse(response);
|
|
485
|
+
if (raw.number === void 0) throw require_parse.unexpectedResponse(response, "A sikeres válaszból hiányzik a számlaszám.");
|
|
486
|
+
return {
|
|
487
|
+
number: raw.number,
|
|
488
|
+
...totalsFor(raw, items),
|
|
489
|
+
outstanding: raw.outstanding,
|
|
490
|
+
buyerAccountUrl: raw.buyerAccountUrl,
|
|
491
|
+
pdf: raw.pdf,
|
|
492
|
+
items
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
function parseInvoicePreviewResponse(response, items = []) {
|
|
496
|
+
const raw = readRawResponse(response);
|
|
497
|
+
if (raw.pdf === void 0) throw require_parse.unexpectedResponse(response, "Az előnézeti válaszból hiányzik a PDF.");
|
|
498
|
+
return {
|
|
499
|
+
pdf: raw.pdf,
|
|
500
|
+
...totalsFor(raw, items),
|
|
501
|
+
items
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
//#endregion
|
|
505
|
+
//#region src/invoices/create-xml.ts
|
|
506
|
+
const INVOICE_XML_NAMESPACE = "http://www.szamlazz.hu/xmlszamla";
|
|
507
|
+
const INVOICE_XML_SCHEMA_LOCATION = "https://www.szamlazz.hu/szamla/docs/xsds/agent/xmlszamla.xsd";
|
|
508
|
+
const RESPONSE_VERSION_XML = 2;
|
|
509
|
+
function textEl(name, value) {
|
|
510
|
+
return require_serialize.optionalEl(name, require_create_once.presentText(value));
|
|
511
|
+
}
|
|
512
|
+
function settingsNode(credentials, invoice, preview) {
|
|
513
|
+
return require_serialize.el("beallitasok", [
|
|
514
|
+
...credentials,
|
|
515
|
+
require_serialize.el("eszamla", invoice.eInvoice),
|
|
516
|
+
require_serialize.el("szamlaLetoltes", preview || invoice.downloadPdf),
|
|
517
|
+
require_serialize.el("valaszVerzio", RESPONSE_VERSION_XML),
|
|
518
|
+
textEl("aggregator", invoice.aggregator),
|
|
519
|
+
require_serialize.optionalEl("guardian", invoice.guardian),
|
|
520
|
+
require_serialize.optionalEl("cikkazoninvoice", invoice.articleIdentifierInvoice),
|
|
521
|
+
textEl("szamlaKulsoAzon", invoice.input.externalId)
|
|
522
|
+
]);
|
|
523
|
+
}
|
|
524
|
+
function documentTypeNodes(invoice) {
|
|
525
|
+
const { input, type } = invoice;
|
|
526
|
+
return [
|
|
527
|
+
type === "advance" && require_serialize.el("elolegszamla", true),
|
|
528
|
+
type === "final" && require_serialize.el("vegszamla", true),
|
|
529
|
+
input.type === "final" && textEl("elolegSzamlaszam", input.advanceInvoiceNumber),
|
|
530
|
+
type === "corrective" && require_serialize.el("helyesbitoszamla", true),
|
|
531
|
+
input.type === "corrective" && textEl("helyesbitettSzamlaszam", input.correctedInvoiceNumber),
|
|
532
|
+
type === "proforma" && require_serialize.el("dijbekero", true),
|
|
533
|
+
type === "deliveryNote" && require_serialize.el("szallitolevel", true)
|
|
534
|
+
];
|
|
535
|
+
}
|
|
536
|
+
function headerNode(invoice, preview) {
|
|
537
|
+
const { input } = invoice;
|
|
538
|
+
return require_serialize.el("fejlec", [
|
|
539
|
+
require_serialize.el("keltDatum", invoice.issueDate),
|
|
540
|
+
require_serialize.el("teljesitesDatum", invoice.fulfillmentDate),
|
|
541
|
+
require_serialize.el("fizetesiHataridoDatum", invoice.dueDate),
|
|
542
|
+
require_serialize.el("fizmod", invoice.paymentMethod),
|
|
543
|
+
require_serialize.el("penznem", invoice.currency),
|
|
544
|
+
require_serialize.el("szamlaNyelve", invoice.language),
|
|
545
|
+
textEl("megjegyzes", input.comment),
|
|
546
|
+
textEl("arfolyamBank", invoice.exchangeBank),
|
|
547
|
+
require_serialize.optionalEl("arfolyam", invoice.exchangeRate),
|
|
548
|
+
textEl("rendelesSzam", input.orderNumber),
|
|
549
|
+
textEl("dijbekeroSzamlaszam", input.proformaNumber),
|
|
550
|
+
...documentTypeNodes(invoice),
|
|
551
|
+
textEl("logoExtra", invoice.logoExtra),
|
|
552
|
+
textEl("szamlaszamElotag", invoice.prefix),
|
|
553
|
+
require_serialize.optionalEl("fizetendoKorrekcio", input.paymentCorrection),
|
|
554
|
+
require_serialize.optionalEl("fizetve", input.paid),
|
|
555
|
+
require_serialize.optionalEl("arresAfa", input.marginVat),
|
|
556
|
+
require_serialize.optionalEl("eusAfa", invoice.euVat),
|
|
557
|
+
require_serialize.optionalEl("szamlaSablon", invoice.template),
|
|
558
|
+
preview && require_serialize.el("elonezetpdf", true),
|
|
559
|
+
require_serialize.optionalEl("simpleItems", invoice.simpleItems)
|
|
560
|
+
]);
|
|
561
|
+
}
|
|
562
|
+
function sellerNode(seller) {
|
|
563
|
+
return require_serialize.el("elado", [
|
|
564
|
+
textEl("bank", seller.bank),
|
|
565
|
+
textEl("bankszamlaszam", seller.bankAccount),
|
|
566
|
+
textEl("emailReplyto", seller.emailReplyTo),
|
|
567
|
+
textEl("emailTargy", seller.emailSubject),
|
|
568
|
+
textEl("emailSzoveg", seller.emailText),
|
|
569
|
+
textEl("alairoNeve", seller.signatoryName)
|
|
570
|
+
]);
|
|
571
|
+
}
|
|
572
|
+
function buyerLedgerNode(ledger) {
|
|
573
|
+
if (!ledger) return void 0;
|
|
574
|
+
return require_serialize.optionalEl("vevoFokonyv", [
|
|
575
|
+
require_serialize.optionalEl("konyvelesDatum", require_create_once.optionalAgentDate(ledger.bookingDate, "buyer.ledger.bookingDate")),
|
|
576
|
+
textEl("vevoAzonosito", ledger.buyerId),
|
|
577
|
+
textEl("vevoFokonyviSzam", ledger.ledgerAccount),
|
|
578
|
+
require_serialize.optionalEl("folyamatosTelj", ledger.continuousFulfillment),
|
|
579
|
+
require_serialize.optionalEl("elszDatumTol", require_create_once.optionalAgentDate(ledger.settlementPeriodStart, "buyer.ledger.settlementPeriodStart")),
|
|
580
|
+
require_serialize.optionalEl("elszDatumIg", require_create_once.optionalAgentDate(ledger.settlementPeriodEnd, "buyer.ledger.settlementPeriodEnd"))
|
|
581
|
+
]);
|
|
582
|
+
}
|
|
583
|
+
function buyerNode(buyer, sendEmail) {
|
|
584
|
+
const taxpayerType = buyer.taxpayerType;
|
|
585
|
+
return require_serialize.el("vevo", [
|
|
586
|
+
require_serialize.el("nev", buyer.name),
|
|
587
|
+
textEl("orszag", buyer.country),
|
|
588
|
+
require_serialize.el("irsz", buyer.zip),
|
|
589
|
+
require_serialize.el("telepules", buyer.city),
|
|
590
|
+
require_serialize.el("cim", buyer.address),
|
|
591
|
+
textEl("email", buyer.email),
|
|
592
|
+
require_serialize.el("sendEmail", sendEmail),
|
|
593
|
+
require_serialize.optionalEl("adoalany", taxpayerType === void 0 ? void 0 : require_create_once.TAXPAYER_TYPE_CODES[taxpayerType]),
|
|
594
|
+
textEl("adoszam", buyer.taxNumber),
|
|
595
|
+
textEl("csoportazonosito", buyer.groupTaxNumber),
|
|
596
|
+
textEl("adoszamEU", buyer.euTaxNumber),
|
|
597
|
+
textEl("postazasiNev", buyer.postal?.name),
|
|
598
|
+
textEl("postazasiOrszag", buyer.postal?.country),
|
|
599
|
+
textEl("postazasiIrsz", buyer.postal?.zip),
|
|
600
|
+
textEl("postazasiTelepules", buyer.postal?.city),
|
|
601
|
+
textEl("postazasiCim", buyer.postal?.address),
|
|
602
|
+
buyerLedgerNode(buyer.ledger),
|
|
603
|
+
textEl("azonosito", buyer.identifier),
|
|
604
|
+
textEl("alairoNeve", buyer.signatoryName),
|
|
605
|
+
textEl("telefonszam", buyer.phone),
|
|
606
|
+
textEl("megjegyzes", buyer.comment)
|
|
607
|
+
]);
|
|
608
|
+
}
|
|
609
|
+
function waybillNode(waybill) {
|
|
610
|
+
if (!waybill) return void 0;
|
|
611
|
+
const { transOFlex: tof, pickPackPoint: ppp, sprinter, mpl } = waybill;
|
|
612
|
+
return require_serialize.el("fuvarlevel", [
|
|
613
|
+
textEl("futarSzolgalat", waybill.courier),
|
|
614
|
+
textEl("vonalkod", waybill.barcode),
|
|
615
|
+
textEl("megjegyzes", waybill.comment),
|
|
616
|
+
tof && require_serialize.el("tof", [
|
|
617
|
+
textEl("azonosito", tof.id),
|
|
618
|
+
textEl("shipmentID", tof.shipmentId),
|
|
619
|
+
require_serialize.optionalEl("csomagszam", tof.packageCount),
|
|
620
|
+
textEl("countryCode", tof.countryCode),
|
|
621
|
+
textEl("zip", tof.zip),
|
|
622
|
+
textEl("service", tof.service)
|
|
623
|
+
]),
|
|
624
|
+
ppp && require_serialize.el("ppp", [textEl("vonalkodPrefix", ppp.barcodePrefix), textEl("vonalkodPostfix", ppp.barcodePostfix)]),
|
|
625
|
+
sprinter && require_serialize.el("sprinter", [
|
|
626
|
+
textEl("azonosito", sprinter.id),
|
|
627
|
+
textEl("feladokod", sprinter.senderCode),
|
|
628
|
+
textEl("iranykod", sprinter.directionCode),
|
|
629
|
+
require_serialize.optionalEl("csomagszam", sprinter.packageCount),
|
|
630
|
+
textEl("vonalkodPostfix", sprinter.barcodePostfix),
|
|
631
|
+
textEl("szallitasiIdo", sprinter.deliveryTime)
|
|
632
|
+
]),
|
|
633
|
+
mpl && require_serialize.el("mpl", [
|
|
634
|
+
require_serialize.el("vevokod", mpl.customerCode),
|
|
635
|
+
require_serialize.el("vonalkod", mpl.barcode),
|
|
636
|
+
require_serialize.el("tomeg", String(mpl.weight)),
|
|
637
|
+
textEl("kulonszolgaltatasok", mpl.services),
|
|
638
|
+
require_serialize.optionalEl("erteknyilvanitas", mpl.declaredValue)
|
|
639
|
+
])
|
|
640
|
+
]);
|
|
641
|
+
}
|
|
642
|
+
function itemLedgerNode(ledger, label) {
|
|
643
|
+
if (!ledger) return void 0;
|
|
644
|
+
return require_serialize.optionalEl("tetelFokonyv", [
|
|
645
|
+
textEl("gazdasagiEsem", ledger.economicEvent),
|
|
646
|
+
textEl("gazdasagiEsemAfa", ledger.vatEconomicEvent),
|
|
647
|
+
textEl("arbevetelFokonyviSzam", ledger.revenueLedgerAccount),
|
|
648
|
+
textEl("afaFokonyviSzam", ledger.vatLedgerAccount),
|
|
649
|
+
require_serialize.optionalEl("elszDatumTol", require_create_once.optionalAgentDate(ledger.settlementPeriodStart, `${label} settlementPeriodStart`)),
|
|
650
|
+
require_serialize.optionalEl("elszDatumIg", require_create_once.optionalAgentDate(ledger.settlementPeriodEnd, `${label} settlementPeriodEnd`))
|
|
651
|
+
]);
|
|
652
|
+
}
|
|
653
|
+
function itemNode(item, index) {
|
|
654
|
+
const { input, amounts } = item;
|
|
655
|
+
return require_serialize.el("tetel", [
|
|
656
|
+
require_serialize.el("megnevezes", input.name),
|
|
657
|
+
textEl("azonosito", input.identifier),
|
|
658
|
+
require_serialize.el("mennyiseg", amounts.quantity),
|
|
659
|
+
require_serialize.el("mennyisegiEgyseg", item.unit),
|
|
660
|
+
require_serialize.el("nettoEgysegar", amounts.netUnitPrice),
|
|
661
|
+
require_serialize.el("afakulcs", require_vat.formatVatRate(amounts.vat)),
|
|
662
|
+
require_serialize.optionalEl("arresAfaAlap", input.marginVatBase),
|
|
663
|
+
require_serialize.el("nettoErtek", amounts.netAmount),
|
|
664
|
+
require_serialize.el("afaErtek", amounts.vatAmount),
|
|
665
|
+
require_serialize.el("bruttoErtek", amounts.grossAmount),
|
|
666
|
+
textEl("megjegyzes", input.comment),
|
|
667
|
+
itemLedgerNode(input.ledger, `${index + 1}. tétel ledger`),
|
|
668
|
+
require_serialize.optionalEl("torloKod", input.dataDeletionCode)
|
|
669
|
+
]);
|
|
670
|
+
}
|
|
671
|
+
function renderInvoiceXml(credentials, invoice, options = {}) {
|
|
672
|
+
const preview = options.preview === true;
|
|
673
|
+
return require_serialize.buildXmlDocument({
|
|
674
|
+
root: "xmlszamla",
|
|
675
|
+
namespace: INVOICE_XML_NAMESPACE,
|
|
676
|
+
schemaLocation: INVOICE_XML_SCHEMA_LOCATION,
|
|
677
|
+
children: [
|
|
678
|
+
settingsNode(credentials, invoice, preview),
|
|
679
|
+
headerNode(invoice, preview),
|
|
680
|
+
sellerNode(invoice.seller),
|
|
681
|
+
buyerNode(invoice.input.buyer, invoice.sendEmail),
|
|
682
|
+
waybillNode(invoice.input.waybill),
|
|
683
|
+
require_serialize.el("tetelek", invoice.items.map(itemNode))
|
|
684
|
+
]
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
function buildCreateInvoiceXml(credentials, defaults, input, now = /* @__PURE__ */ new Date()) {
|
|
688
|
+
return renderInvoiceXml(credentials, require_create_once.resolveInvoice(defaults, input, now));
|
|
689
|
+
}
|
|
690
|
+
//#endregion
|
|
691
|
+
//#region src/invoices/create.ts
|
|
692
|
+
function buildRequest(ctx, invoice, preview, options) {
|
|
693
|
+
const xml = renderInvoiceXml(ctx.credentials, invoice, { preview });
|
|
694
|
+
const attachments = preview ? [] : invoice.attachments;
|
|
695
|
+
return {
|
|
696
|
+
action: "createInvoice",
|
|
697
|
+
xml,
|
|
698
|
+
signal: options.signal,
|
|
699
|
+
...attachments.length > 0 ? { attachments } : {}
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
function itemsOf(invoice) {
|
|
703
|
+
return invoice.items.map((item) => item.amounts);
|
|
704
|
+
}
|
|
705
|
+
async function createInvoice(ctx, defaults, input, options = {}) {
|
|
706
|
+
const invoice = require_create_once.resolveInvoice(defaults, input, /* @__PURE__ */ new Date());
|
|
707
|
+
const items = itemsOf(invoice);
|
|
708
|
+
return ctx.execute(buildRequest(ctx, invoice, false, options), (response) => parseCreateInvoiceResponse(response, items));
|
|
709
|
+
}
|
|
710
|
+
async function previewInvoice(ctx, defaults, input, options = {}) {
|
|
711
|
+
const invoice = require_create_once.resolveInvoice(defaults, input, /* @__PURE__ */ new Date());
|
|
712
|
+
const items = itemsOf(invoice);
|
|
713
|
+
return ctx.execute(buildRequest(ctx, invoice, true, options), (response) => parseInvoicePreviewResponse(response, items));
|
|
714
|
+
}
|
|
715
|
+
//#endregion
|
|
716
|
+
//#region src/invoices/pdf.ts
|
|
717
|
+
function buildInvoicePdfXml(credentials, reference) {
|
|
718
|
+
const resolved = require_reference.resolveInvoiceReference(reference);
|
|
719
|
+
return require_serialize.buildXmlDocument({
|
|
720
|
+
root: "xmlszamlapdf",
|
|
721
|
+
namespace: "http://www.szamlazz.hu/xmlszamlapdf",
|
|
722
|
+
schemaLocation: `${require_reference.AGENT_XSD_BASE_URL}agentpdf/xmlszamlapdf.xsd`,
|
|
723
|
+
children: [
|
|
724
|
+
...credentials,
|
|
725
|
+
require_serialize.optionalEl("szamlaszam", require_reference.referenceValue(resolved, "invoiceNumber")),
|
|
726
|
+
require_serialize.optionalEl("rendelesSzam", require_reference.referenceValue(resolved, "orderNumber")),
|
|
727
|
+
require_serialize.el("valaszVerzio", 2),
|
|
728
|
+
require_serialize.optionalEl("szamlaKulsoAzon", require_reference.referenceValue(resolved, "externalId"))
|
|
729
|
+
]
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
function parseInvoicePdfResponse(response) {
|
|
733
|
+
const { pdf, ...rest } = require_reference.parseInvoiceResult(response);
|
|
734
|
+
if (pdf === void 0 || pdf.length === 0) throw require_parse.unexpectedResponse(response, "A válasz nem tartalmaz PDF-et.");
|
|
735
|
+
return {
|
|
736
|
+
...rest,
|
|
737
|
+
pdf
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
async function getInvoicePdf(ctx, reference, options = {}) {
|
|
741
|
+
const xml = buildInvoicePdfXml(ctx.credentials, reference);
|
|
742
|
+
return ctx.execute({
|
|
743
|
+
action: "getInvoicePdf",
|
|
744
|
+
xml,
|
|
745
|
+
signal: options.signal,
|
|
746
|
+
safeToRetry: true
|
|
747
|
+
}, parseInvoicePdfResponse);
|
|
748
|
+
}
|
|
749
|
+
const RESPONSE_ROOTS = /* @__PURE__ */ new Set(["xmlszamladbkdelvalasz", "xmlszamlavalasz"]);
|
|
750
|
+
const REFERENCE_HINT = "Add meg a díjbekérő számát szövegként, vagy pontosan egyet ezek közül: { proformaNumber }, { orderNumber }.";
|
|
751
|
+
function resolveProformaReference(reference) {
|
|
752
|
+
if (typeof reference === "string") return { proformaNumber: require_reference.requireText(reference, `Üres díjbekérőszám. ${REFERENCE_HINT}`) };
|
|
753
|
+
if (typeof reference !== "object" || reference === null) throw require_reference.validationError(`Érvénytelen díjbekérő-hivatkozás. ${REFERENCE_HINT}`);
|
|
754
|
+
const record = reference;
|
|
755
|
+
const hasNumber = record.proformaNumber !== void 0;
|
|
756
|
+
if (hasNumber === (record.orderNumber !== void 0)) throw require_reference.validationError(`Érvénytelen díjbekérő-hivatkozás. ${REFERENCE_HINT}`);
|
|
757
|
+
return hasNumber ? { proformaNumber: require_reference.requireText(record.proformaNumber, `Üres proformaNumber. ${REFERENCE_HINT}`) } : { orderNumber: require_reference.requireText(record.orderNumber, `Üres orderNumber. ${REFERENCE_HINT}`) };
|
|
758
|
+
}
|
|
759
|
+
function buildDeleteProformaXml(credentials, reference) {
|
|
760
|
+
const resolved = resolveProformaReference(reference);
|
|
761
|
+
return require_serialize.buildXmlDocument({
|
|
762
|
+
root: "xmlszamladbkdel",
|
|
763
|
+
namespace: "http://www.szamlazz.hu/xmlszamladbkdel",
|
|
764
|
+
schemaLocation: "http://www.szamlazz.hu/docs/xsds/szamladbkdel/xmlszamladbkdel.xsd",
|
|
765
|
+
children: [require_serialize.el("beallitasok", [...credentials]), require_serialize.el("fejlec", [require_serialize.optionalEl("szamlaszam", resolved.proformaNumber), require_serialize.optionalEl("rendelesszam", resolved.orderNumber)])]
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
function withProformaCategory(error) {
|
|
769
|
+
if (!(error instanceof require_errors.SzamlazzError) || error.code !== 335) return error;
|
|
770
|
+
return new require_errors.SzamlazzError(error.message, {
|
|
771
|
+
category: "not_found",
|
|
772
|
+
code: error.code,
|
|
773
|
+
hint: "A díjbekérő nem létezik, vagy már törölték.",
|
|
774
|
+
action: error.action,
|
|
775
|
+
httpStatus: error.httpStatus,
|
|
776
|
+
rawResponse: error.rawResponse,
|
|
777
|
+
cause: error
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
function parseDeleteProformaResponse(response) {
|
|
781
|
+
try {
|
|
782
|
+
require_parse.throwIfHeaderError(response);
|
|
783
|
+
require_parse.throwIfTextError(response);
|
|
784
|
+
require_parse.throwIfHttpError(response);
|
|
785
|
+
const root = require_parse.parseResponseXml(response);
|
|
786
|
+
require_parse.throwIfXmlFailure(root, response);
|
|
787
|
+
if (!RESPONSE_ROOTS.has(root.name) || require_serialize.childText(root, "sikeres")?.toLowerCase() !== "true") throw require_parse.unexpectedResponse(response, "xmlszamladbkdelvalasz XML választ vártunk.");
|
|
788
|
+
} catch (error) {
|
|
789
|
+
throw withProformaCategory(error);
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
async function deleteProforma(ctx, reference, options = {}) {
|
|
793
|
+
const xml = buildDeleteProformaXml(ctx.credentials, reference);
|
|
794
|
+
await ctx.execute({
|
|
795
|
+
action: "deleteProforma",
|
|
796
|
+
xml,
|
|
797
|
+
signal: options.signal
|
|
798
|
+
}, parseDeleteProformaResponse);
|
|
799
|
+
}
|
|
800
|
+
const templates = new Set(require_create_once.INVOICE_TEMPLATES);
|
|
801
|
+
function normalizeInput$2(input) {
|
|
802
|
+
return typeof input === "string" ? { invoiceNumber: input } : input;
|
|
803
|
+
}
|
|
804
|
+
function validateTemplate(template) {
|
|
805
|
+
if (template === void 0 || templates.has(template)) return template;
|
|
806
|
+
throw require_reference.validationError(`Ismeretlen számlasablon: ${String(template)}. Lehetséges értékek: ${require_create_once.INVOICE_TEMPLATES.join(", ")}.`);
|
|
807
|
+
}
|
|
808
|
+
function buildReverseInvoiceXml(credentials, input) {
|
|
809
|
+
const options = normalizeInput$2(input);
|
|
810
|
+
const invoiceNumber = require_reference.requireText(options.invoiceNumber, "Add meg a sztornózandó számla számát (invoiceNumber).");
|
|
811
|
+
const email = options.email;
|
|
812
|
+
const buyer = options.buyer;
|
|
813
|
+
return require_serialize.buildXmlDocument({
|
|
814
|
+
root: "xmlszamlast",
|
|
815
|
+
namespace: "http://www.szamlazz.hu/xmlszamlast",
|
|
816
|
+
schemaLocation: `${require_reference.AGENT_XSD_BASE_URL}agentst/xmlszamlast.xsd`,
|
|
817
|
+
children: [
|
|
818
|
+
require_serialize.el("beallitasok", [
|
|
819
|
+
...credentials,
|
|
820
|
+
require_serialize.el("eszamla", options.eInvoice ?? false),
|
|
821
|
+
require_serialize.el("szamlaLetoltes", options.downloadPdf ?? true),
|
|
822
|
+
require_serialize.el("valaszVerzio", 2),
|
|
823
|
+
require_serialize.optionalEl("szamlaKulsoAzon", require_reference.optionalText(options.externalId))
|
|
824
|
+
]),
|
|
825
|
+
require_serialize.el("fejlec", [
|
|
826
|
+
require_serialize.el("szamlaszam", invoiceNumber),
|
|
827
|
+
require_serialize.optionalEl("keltDatum", require_reference.optionalAgentDate(options.issueDate, "issueDate")),
|
|
828
|
+
require_serialize.optionalEl("teljesitesDatum", require_reference.optionalAgentDate(options.fulfillmentDate, "fulfillmentDate")),
|
|
829
|
+
require_serialize.optionalEl("megjegyzes", require_reference.optionalText(options.comment)),
|
|
830
|
+
require_serialize.el("tipus", "SS"),
|
|
831
|
+
require_serialize.optionalEl("szamlaSablon", validateTemplate(options.template))
|
|
832
|
+
]),
|
|
833
|
+
require_serialize.optionalEl("elado", [
|
|
834
|
+
require_serialize.optionalEl("emailReplyto", require_reference.optionalText(email?.replyTo)),
|
|
835
|
+
require_serialize.optionalEl("emailTargy", require_reference.optionalText(email?.subject)),
|
|
836
|
+
require_serialize.optionalEl("emailSzoveg", require_reference.optionalText(email?.text))
|
|
837
|
+
]),
|
|
838
|
+
require_serialize.optionalEl("vevo", [
|
|
839
|
+
require_serialize.optionalEl("email", require_reference.optionalText(buyer?.email)),
|
|
840
|
+
require_serialize.optionalEl("adoszam", require_reference.optionalText(buyer?.taxNumber)),
|
|
841
|
+
require_serialize.optionalEl("adoszamEU", require_reference.optionalText(buyer?.euTaxNumber))
|
|
842
|
+
])
|
|
843
|
+
]
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
function parseReverseInvoiceResponse(response, originalInvoiceNumber) {
|
|
847
|
+
const result = require_reference.parseInvoiceResult(response);
|
|
848
|
+
if (result.number === void 0) throw require_parse.unexpectedResponse(response, "A válaszban nincs sztornó számlaszám.");
|
|
849
|
+
if (originalInvoiceNumber !== void 0 && result.number === originalInvoiceNumber.trim()) throw new require_errors.SzamlazzError(`A(z) ${result.number} bizonylat nem lett sztornózva: a Számlázz.hu az eredeti bizonylatot adta vissza.`, {
|
|
850
|
+
category: "validation",
|
|
851
|
+
action: response.action,
|
|
852
|
+
httpStatus: response.status,
|
|
853
|
+
hint: "Díjbekérő és szállítólevél nem sztornózható. Díjbekérőt a deleteProforma függvénnyel törölhetsz."
|
|
854
|
+
});
|
|
855
|
+
return {
|
|
856
|
+
...result,
|
|
857
|
+
number: result.number
|
|
858
|
+
};
|
|
859
|
+
}
|
|
860
|
+
async function reverseInvoice(ctx, input, options = {}) {
|
|
861
|
+
const invoiceNumber = normalizeInput$2(input).invoiceNumber;
|
|
862
|
+
const xml = buildReverseInvoiceXml(ctx.credentials, input);
|
|
863
|
+
return ctx.execute({
|
|
864
|
+
action: "reverseInvoice",
|
|
865
|
+
xml,
|
|
866
|
+
signal: options.signal
|
|
867
|
+
}, (response) => parseReverseInvoiceResponse(response, invoiceNumber));
|
|
868
|
+
}
|
|
869
|
+
//#endregion
|
|
870
|
+
//#region src/receipts/get.ts
|
|
871
|
+
const GET_RECEIPT_NAMESPACE = "http://www.szamlazz.hu/xmlnyugtaget";
|
|
872
|
+
function normalizeInput$1(input) {
|
|
873
|
+
return typeof input === "string" ? { receiptNumber: input } : input;
|
|
874
|
+
}
|
|
875
|
+
function resolveIdentifier(input) {
|
|
876
|
+
const receiptNumber = require_create.optionalText(input.receiptNumber);
|
|
877
|
+
const orderNumber = require_create.optionalText(input.orderNumber);
|
|
878
|
+
if (receiptNumber === void 0 && orderNumber === void 0) throw require_create.receiptValidationError("A nyugta lekérdezéséhez add meg a nyugtaszámot (receiptNumber) vagy a rendelésszámot (orderNumber).");
|
|
879
|
+
if (receiptNumber !== void 0 && orderNumber !== void 0) throw require_create.receiptValidationError("A nyugta lekérdezéséhez a nyugtaszám (receiptNumber) és a rendelésszám (orderNumber) közül csak az egyiket add meg.");
|
|
880
|
+
return {
|
|
881
|
+
receiptNumber,
|
|
882
|
+
orderNumber
|
|
883
|
+
};
|
|
884
|
+
}
|
|
885
|
+
function buildGetReceiptXml(credentials, input) {
|
|
886
|
+
const normalized = normalizeInput$1(input);
|
|
887
|
+
const { receiptNumber, orderNumber } = resolveIdentifier(normalized);
|
|
888
|
+
return require_serialize.buildXmlDocument({
|
|
889
|
+
root: "xmlnyugtaget",
|
|
890
|
+
namespace: GET_RECEIPT_NAMESPACE,
|
|
891
|
+
schemaLocation: `${require_create.RECEIPT_XSD_BASE_URL}nyugtaget/xmlnyugtaget.xsd`,
|
|
892
|
+
children: [require_serialize.el("beallitasok", [...credentials, require_serialize.el("pdfLetoltes", normalized.downloadPdf ?? true)]), require_serialize.el("fejlec", [
|
|
893
|
+
require_serialize.optionalEl("nyugtaszam", receiptNumber),
|
|
894
|
+
require_serialize.optionalEl("rendelesSzam", orderNumber),
|
|
895
|
+
require_serialize.optionalEl("hivasAzonosito", require_create.optionalText(normalized.callId)),
|
|
896
|
+
require_serialize.optionalEl("pdfSablon", require_create.validateTemplate(normalized.template))
|
|
897
|
+
])]
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
function getReceipt(ctx, input, options = {}) {
|
|
901
|
+
const xml = buildGetReceiptXml(ctx.credentials, input);
|
|
902
|
+
return ctx.execute({
|
|
903
|
+
action: "getReceipt",
|
|
904
|
+
xml,
|
|
905
|
+
signal: options.signal,
|
|
906
|
+
safeToRetry: true
|
|
907
|
+
}, require_parse.parseReceiptResponse);
|
|
908
|
+
}
|
|
909
|
+
//#endregion
|
|
910
|
+
//#region src/receipts/reverse.ts
|
|
911
|
+
const REVERSE_RECEIPT_NAMESPACE = "http://www.szamlazz.hu/xmlnyugtast";
|
|
912
|
+
function normalizeInput(input) {
|
|
913
|
+
return typeof input === "string" ? { receiptNumber: input } : input;
|
|
914
|
+
}
|
|
915
|
+
function buildReverseReceiptXml(credentials, input) {
|
|
916
|
+
const normalized = normalizeInput(input);
|
|
917
|
+
return require_serialize.buildXmlDocument({
|
|
918
|
+
root: "xmlnyugtast",
|
|
919
|
+
namespace: REVERSE_RECEIPT_NAMESPACE,
|
|
920
|
+
schemaLocation: `${require_create.RECEIPT_XSD_BASE_URL}nyugtast/xmlnyugtast.xsd`,
|
|
921
|
+
children: [require_serialize.el("beallitasok", [...credentials, require_serialize.el("pdfLetoltes", normalized.downloadPdf ?? true)]), require_serialize.el("fejlec", [
|
|
922
|
+
require_serialize.el("nyugtaszam", require_create.requireReceiptNumber(normalized.receiptNumber)),
|
|
923
|
+
require_serialize.optionalEl("pdfSablon", require_create.validateTemplate(normalized.template)),
|
|
924
|
+
require_serialize.optionalEl("hivasAzonosito", require_create.optionalText(normalized.callId))
|
|
925
|
+
])]
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
function reverseReceipt(ctx, input, options = {}) {
|
|
929
|
+
const normalized = normalizeInput(input);
|
|
930
|
+
const xml = buildReverseReceiptXml(ctx.credentials, normalized);
|
|
931
|
+
return ctx.execute({
|
|
932
|
+
action: "reverseReceipt",
|
|
933
|
+
xml,
|
|
934
|
+
signal: options.signal,
|
|
935
|
+
safeToRetry: require_create.optionalText(normalized.callId) !== void 0
|
|
936
|
+
}, require_parse.parseReceiptResponse);
|
|
937
|
+
}
|
|
938
|
+
//#endregion
|
|
939
|
+
//#region src/receipts/send.ts
|
|
940
|
+
const SEND_RECEIPT_NAMESPACE = "http://www.szamlazz.hu/xmlnyugtasend";
|
|
941
|
+
const EMAIL_PATTERN = /^[^\s@,;<>]+@[^\s@,;<>]+\.[^\s@,;<>]+$/;
|
|
942
|
+
function isValidEmail(value) {
|
|
943
|
+
return EMAIL_PATTERN.test(value);
|
|
944
|
+
}
|
|
945
|
+
function assertEmail(value, field) {
|
|
946
|
+
if (!isValidEmail(value)) throw require_create.receiptValidationError(`Érvénytelen e-mail cím a(z) ${field} mezőben: ${value}`);
|
|
947
|
+
return value;
|
|
948
|
+
}
|
|
949
|
+
function normalizeEmails(emails) {
|
|
950
|
+
const list = (typeof emails === "string" ? [emails] : [...emails]).flatMap((entry) => entry.split(/[,;]/)).map((entry) => entry.trim()).filter((entry) => entry !== "");
|
|
951
|
+
if (list.length === 0) throw require_create.receiptValidationError("Adj meg legalább egy címzett e-mail címet (emails).");
|
|
952
|
+
return list.map((email) => assertEmail(email, "emails"));
|
|
953
|
+
}
|
|
954
|
+
function buildSendReceiptXml(credentials, input) {
|
|
955
|
+
const receiptNumber = require_create.requireReceiptNumber(input.receiptNumber);
|
|
956
|
+
const emails = normalizeEmails(input.emails);
|
|
957
|
+
const replyTo = require_create.optionalText(input.replyTo);
|
|
958
|
+
if (replyTo !== void 0) assertEmail(replyTo, "replyTo");
|
|
959
|
+
return require_serialize.buildXmlDocument({
|
|
960
|
+
root: "xmlnyugtasend",
|
|
961
|
+
namespace: SEND_RECEIPT_NAMESPACE,
|
|
962
|
+
schemaLocation: `${require_create.RECEIPT_XSD_BASE_URL}nyugtasend/xmlnyugtasend.xsd`,
|
|
963
|
+
children: [
|
|
964
|
+
require_serialize.el("beallitasok", credentials),
|
|
965
|
+
require_serialize.el("fejlec", [require_serialize.el("nyugtaszam", receiptNumber)]),
|
|
966
|
+
require_serialize.el("emailKuldes", [
|
|
967
|
+
require_serialize.el("email", emails.join(",")),
|
|
968
|
+
require_serialize.optionalEl("emailReplyto", replyTo),
|
|
969
|
+
require_serialize.el("emailTargy", require_create.optionalText(input.subject) ?? `Nyugta ${receiptNumber}`),
|
|
970
|
+
require_serialize.optionalEl("emailSzoveg", input.text?.trim() ? input.text : void 0)
|
|
971
|
+
])
|
|
972
|
+
]
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
function parseSendReceiptResponse(response) {
|
|
976
|
+
require_parse.throwIfHeaderError(response);
|
|
977
|
+
require_parse.throwIfTextError(response);
|
|
978
|
+
if (!require_parse.looksLikeXml(response)) {
|
|
979
|
+
require_parse.throwIfHttpError(response);
|
|
980
|
+
if (require_parse.parseDoneText(response.text())) return;
|
|
981
|
+
throw require_parse.unexpectedResponse(response, "XML választ vártunk a nyugta kiküldésére.");
|
|
982
|
+
}
|
|
983
|
+
const root = require_parse.parseResponseXml(response);
|
|
984
|
+
require_parse.throwIfXmlFailure(root, response);
|
|
985
|
+
if (require_serialize.childBoolean(root, "sikeres") !== true) {
|
|
986
|
+
require_parse.throwIfHttpError(response);
|
|
987
|
+
throw require_parse.unexpectedResponse(response, "A válasz nem jelez sikeres kiküldést.");
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
function sendReceipt(ctx, input, options = {}) {
|
|
991
|
+
const xml = buildSendReceiptXml(ctx.credentials, input);
|
|
992
|
+
return ctx.execute({
|
|
993
|
+
action: "sendReceipt",
|
|
994
|
+
xml,
|
|
995
|
+
signal: options.signal
|
|
996
|
+
}, parseSendReceiptResponse);
|
|
997
|
+
}
|
|
998
|
+
//#endregion
|
|
999
|
+
//#region src/taxpayer/address.ts
|
|
1000
|
+
const ROMAN_NUMERAL = /^[IVX]{1,5}\.?$/;
|
|
1001
|
+
function isShouting(value) {
|
|
1002
|
+
return value === value.toUpperCase() && value !== value.toLowerCase();
|
|
1003
|
+
}
|
|
1004
|
+
function capitalizeWord(word) {
|
|
1005
|
+
if (ROMAN_NUMERAL.test(word)) return word;
|
|
1006
|
+
return word.split("-").map((part) => part.toLowerCase().replace(/\p{L}/u, (letter) => letter.toUpperCase())).join("-");
|
|
1007
|
+
}
|
|
1008
|
+
function toReadableName(value) {
|
|
1009
|
+
if (value === void 0 || !isShouting(value)) return value;
|
|
1010
|
+
return value.split(" ").map(capitalizeWord).join(" ");
|
|
1011
|
+
}
|
|
1012
|
+
function toLowerIfShouting(value) {
|
|
1013
|
+
return value !== void 0 && isShouting(value) ? value.toLowerCase() : value;
|
|
1014
|
+
}
|
|
1015
|
+
function withOrdinalDot(value) {
|
|
1016
|
+
if (value === void 0) return void 0;
|
|
1017
|
+
return /^\d+$/.test(value) ? `${value}.` : value;
|
|
1018
|
+
}
|
|
1019
|
+
function joinParts(parts) {
|
|
1020
|
+
return parts.filter((part) => part !== void 0 && part !== "").join(" ");
|
|
1021
|
+
}
|
|
1022
|
+
function formatAddress(address) {
|
|
1023
|
+
return [
|
|
1024
|
+
joinParts([address.postalCode, address.city]),
|
|
1025
|
+
joinParts([
|
|
1026
|
+
address.street,
|
|
1027
|
+
address.publicPlaceCategory,
|
|
1028
|
+
withOrdinalDot(address.number),
|
|
1029
|
+
address.building === void 0 ? void 0 : `${address.building} ép.`,
|
|
1030
|
+
address.staircase === void 0 ? void 0 : `${withOrdinalDot(address.staircase)} lh.`,
|
|
1031
|
+
address.floor === void 0 ? void 0 : `${withOrdinalDot(address.floor)} em.`,
|
|
1032
|
+
address.door === void 0 ? void 0 : `${withOrdinalDot(address.door)} ajtó`
|
|
1033
|
+
]),
|
|
1034
|
+
address.lotNumber === void 0 ? void 0 : `hrsz. ${address.lotNumber}`,
|
|
1035
|
+
address.countryCode === "" || address.countryCode === "HU" ? void 0 : address.countryCode
|
|
1036
|
+
].filter((part) => part !== void 0 && part !== "").join(", ");
|
|
1037
|
+
}
|
|
1038
|
+
function readDetailedAddress(element) {
|
|
1039
|
+
return {
|
|
1040
|
+
countryCode: require_serialize.childText(element, "countryCode"),
|
|
1041
|
+
region: require_serialize.childText(element, "region"),
|
|
1042
|
+
postalCode: require_serialize.childText(element, "postalCode"),
|
|
1043
|
+
city: require_serialize.childText(element, "city"),
|
|
1044
|
+
streetName: require_serialize.childText(element, "streetName"),
|
|
1045
|
+
publicPlaceCategory: require_serialize.childText(element, "publicPlaceCategory"),
|
|
1046
|
+
number: require_serialize.childText(element, "number"),
|
|
1047
|
+
building: require_serialize.childText(element, "building"),
|
|
1048
|
+
staircase: require_serialize.childText(element, "staircase"),
|
|
1049
|
+
floor: require_serialize.childText(element, "floor"),
|
|
1050
|
+
door: require_serialize.childText(element, "door"),
|
|
1051
|
+
lotNumber: require_serialize.childText(element, "lotNumber")
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
function parseTaxpayerAddress(item) {
|
|
1055
|
+
const raw = readDetailedAddress(require_serialize.findChild(item, "taxpayerAddress"));
|
|
1056
|
+
const address = {
|
|
1057
|
+
type: require_serialize.childText(item, "taxpayerAddressType")?.toUpperCase() ?? "",
|
|
1058
|
+
countryCode: raw.countryCode?.toUpperCase() ?? "",
|
|
1059
|
+
region: toReadableName(raw.region),
|
|
1060
|
+
postalCode: raw.postalCode ?? "",
|
|
1061
|
+
city: toReadableName(raw.city) ?? "",
|
|
1062
|
+
street: toReadableName(raw.streetName),
|
|
1063
|
+
publicPlaceCategory: toLowerIfShouting(raw.publicPlaceCategory),
|
|
1064
|
+
number: raw.number,
|
|
1065
|
+
building: raw.building,
|
|
1066
|
+
staircase: raw.staircase,
|
|
1067
|
+
floor: raw.floor,
|
|
1068
|
+
door: raw.door,
|
|
1069
|
+
lotNumber: raw.lotNumber
|
|
1070
|
+
};
|
|
1071
|
+
return {
|
|
1072
|
+
...address,
|
|
1073
|
+
formatted: formatAddress(address),
|
|
1074
|
+
raw
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1077
|
+
//#endregion
|
|
1078
|
+
//#region src/taxpayer/query-taxpayer.ts
|
|
1079
|
+
const TAXPAYER_NAMESPACE = "http://www.szamlazz.hu/xmltaxpayer";
|
|
1080
|
+
const TAXPAYER_SCHEMA_LOCATION = "http://www.szamlazz.hu/docs/xsds/agent/xmltaxpayer.xsd";
|
|
1081
|
+
function toTaxpayerId(taxNumber) {
|
|
1082
|
+
const digits = typeof taxNumber === "string" ? taxNumber.replace(/[\s-]+/g, "").replace(/^HU/i, "") : "";
|
|
1083
|
+
if (!/^(?:\d{8}|\d{11})$/.test(digits)) throw new require_errors.SzamlazzError(`Érvénytelen adószám: "${String(taxNumber)}". Add meg a 8 jegyű törzsszámot vagy a 11 jegyű adószámot (pl. 12345678-2-42).`, {
|
|
1084
|
+
category: "validation",
|
|
1085
|
+
action: "queryTaxpayer"
|
|
1086
|
+
});
|
|
1087
|
+
return digits.slice(0, 8);
|
|
1088
|
+
}
|
|
1089
|
+
function buildQueryTaxpayerXml(credentials, taxNumber) {
|
|
1090
|
+
return require_serialize.buildXmlDocument({
|
|
1091
|
+
root: "xmltaxpayer",
|
|
1092
|
+
namespace: TAXPAYER_NAMESPACE,
|
|
1093
|
+
schemaLocation: TAXPAYER_SCHEMA_LOCATION,
|
|
1094
|
+
children: [require_serialize.el("beallitasok", credentials), require_serialize.el("torzsszam", toTaxpayerId(taxNumber))]
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
function throwIfNavError(root, response) {
|
|
1098
|
+
const result = require_serialize.findChild(root, "result");
|
|
1099
|
+
if (require_serialize.childText(result, "funcCode")?.toUpperCase() !== "ERROR") return;
|
|
1100
|
+
const errorCode = require_serialize.childText(result, "errorCode");
|
|
1101
|
+
const code = require_errors.parseErrorCode(errorCode);
|
|
1102
|
+
const message = require_serialize.childText(result, "message");
|
|
1103
|
+
const textCode = code === void 0 ? errorCode : void 0;
|
|
1104
|
+
throw require_errors.createAgentError({
|
|
1105
|
+
code,
|
|
1106
|
+
message: textCode === void 0 ? message : [textCode, message].filter(Boolean).join(": "),
|
|
1107
|
+
action: response.action,
|
|
1108
|
+
httpStatus: response.status,
|
|
1109
|
+
rawResponse: response.text().slice(0, 2e3)
|
|
1110
|
+
});
|
|
1111
|
+
}
|
|
1112
|
+
function readTaxNumber(data) {
|
|
1113
|
+
const detail = require_serialize.findChild(data, "taxNumberDetail");
|
|
1114
|
+
const taxpayerId = require_serialize.childText(detail, "taxpayerId");
|
|
1115
|
+
if (taxpayerId === void 0) return void 0;
|
|
1116
|
+
const vatCode = require_serialize.childText(detail, "vatCode");
|
|
1117
|
+
const countyCode = require_serialize.childText(detail, "countyCode");
|
|
1118
|
+
return {
|
|
1119
|
+
taxpayerId,
|
|
1120
|
+
vatCode,
|
|
1121
|
+
countyCode,
|
|
1122
|
+
formatted: vatCode !== void 0 && countyCode !== void 0 ? `${taxpayerId}-${vatCode}-${countyCode}` : void 0
|
|
1123
|
+
};
|
|
1124
|
+
}
|
|
1125
|
+
function readAddresses(data) {
|
|
1126
|
+
return require_serialize.findChildren(require_serialize.findChild(data, "taxpayerAddressList"), "taxpayerAddressItem").map(parseTaxpayerAddress);
|
|
1127
|
+
}
|
|
1128
|
+
function readRequestId(root) {
|
|
1129
|
+
const requestId = require_serialize.childText(require_serialize.findChild(root, "header"), "requestId");
|
|
1130
|
+
return requestId === "-" ? void 0 : requestId;
|
|
1131
|
+
}
|
|
1132
|
+
function parseQueryTaxpayerResponse(response) {
|
|
1133
|
+
require_parse.throwIfAnyError(response);
|
|
1134
|
+
const root = require_parse.parseResponseXml(response);
|
|
1135
|
+
require_parse.throwIfXmlFailure(root, response);
|
|
1136
|
+
if (root.name !== "QueryTaxpayerResponse") throw require_parse.unexpectedResponse(response, "QueryTaxpayerResponse XML választ vártunk.");
|
|
1137
|
+
throwIfNavError(root, response);
|
|
1138
|
+
const requestId = readRequestId(root);
|
|
1139
|
+
const infoDate = require_serialize.childText(root, "infoDate");
|
|
1140
|
+
const data = require_serialize.findChild(root, "taxpayerData");
|
|
1141
|
+
const validity = require_serialize.childBoolean(root, "taxpayerValidity");
|
|
1142
|
+
if (validity === false || data === void 0) return {
|
|
1143
|
+
valid: validity === true,
|
|
1144
|
+
addresses: [],
|
|
1145
|
+
infoDate,
|
|
1146
|
+
requestId
|
|
1147
|
+
};
|
|
1148
|
+
const addresses = readAddresses(data);
|
|
1149
|
+
return {
|
|
1150
|
+
valid: true,
|
|
1151
|
+
name: require_serialize.childText(data, "taxpayerName"),
|
|
1152
|
+
shortName: require_serialize.childText(data, "taxpayerShortName"),
|
|
1153
|
+
taxNumber: readTaxNumber(data),
|
|
1154
|
+
address: addresses.find((address) => address.type === "HQ") ?? addresses[0],
|
|
1155
|
+
addresses,
|
|
1156
|
+
incorporation: require_serialize.childText(data, "incorporation"),
|
|
1157
|
+
vatGroupMembership: require_serialize.childText(data, "vatGroupMembership"),
|
|
1158
|
+
infoDate,
|
|
1159
|
+
requestId
|
|
1160
|
+
};
|
|
1161
|
+
}
|
|
1162
|
+
async function queryTaxpayer(ctx, taxNumber, options = {}) {
|
|
1163
|
+
const xml = buildQueryTaxpayerXml(ctx.credentials, taxNumber);
|
|
1164
|
+
return ctx.execute({
|
|
1165
|
+
action: "queryTaxpayer",
|
|
1166
|
+
xml,
|
|
1167
|
+
signal: options.signal,
|
|
1168
|
+
safeToRetry: true
|
|
1169
|
+
}, parseQueryTaxpayerResponse);
|
|
1170
|
+
}
|
|
1171
|
+
//#endregion
|
|
1172
|
+
//#region src/taxpayer/cache.ts
|
|
1173
|
+
const TAXPAYER_CACHE_KEY_PREFIX = "szamlazz:taxpayer:";
|
|
1174
|
+
const DEFAULT_TAXPAYER_TTL_SECONDS = 86400;
|
|
1175
|
+
const DEFAULT_TAXPAYER_INVALID_TTL_SECONDS = 600;
|
|
1176
|
+
function positiveSeconds(value, fallback, field) {
|
|
1177
|
+
if (value === void 0) return fallback;
|
|
1178
|
+
if (!Number.isFinite(value) || value < 1) throw new require_errors.SzamlazzError(`A(z) ${field} legalább 1 másodperc legyen, kapott: ${String(value)}`, { category: "configuration" });
|
|
1179
|
+
return Math.ceil(value);
|
|
1180
|
+
}
|
|
1181
|
+
function parseCached(value) {
|
|
1182
|
+
if (typeof value !== "string" || value === "") return void 0;
|
|
1183
|
+
try {
|
|
1184
|
+
const parsed = JSON.parse(value);
|
|
1185
|
+
if (typeof parsed !== "object" || parsed === null) return void 0;
|
|
1186
|
+
const info = parsed;
|
|
1187
|
+
return typeof info.valid === "boolean" && Array.isArray(info.addresses) ? info : void 0;
|
|
1188
|
+
} catch {
|
|
1189
|
+
return;
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
function cachedTaxpayerQuery(query, options, warn) {
|
|
1193
|
+
const ttl = positiveSeconds(options.ttlSeconds, DEFAULT_TAXPAYER_TTL_SECONDS, "ttlSeconds");
|
|
1194
|
+
const invalidTtl = positiveSeconds(options.invalidTtlSeconds, 600, "invalidTtlSeconds");
|
|
1195
|
+
const report = (operation, error) => warn?.({
|
|
1196
|
+
kind: "cache",
|
|
1197
|
+
message: `Az adószám-gyorsítótár "${operation}" művelete sikertelen, a kassza a Számlázz.hu-tól kérdez.`,
|
|
1198
|
+
error,
|
|
1199
|
+
action: "queryTaxpayer",
|
|
1200
|
+
operation
|
|
1201
|
+
});
|
|
1202
|
+
return async (taxNumber, requestOptions) => {
|
|
1203
|
+
const key = `${TAXPAYER_CACHE_KEY_PREFIX}${toTaxpayerId(taxNumber)}`;
|
|
1204
|
+
try {
|
|
1205
|
+
const cached = parseCached(await options.store.get(key));
|
|
1206
|
+
if (cached) return cached;
|
|
1207
|
+
} catch (error) {
|
|
1208
|
+
report("get", error);
|
|
1209
|
+
}
|
|
1210
|
+
const info = await query(taxNumber, requestOptions);
|
|
1211
|
+
try {
|
|
1212
|
+
await options.store.set(key, JSON.stringify(info), info.valid ? ttl : invalidTtl);
|
|
1213
|
+
} catch (error) {
|
|
1214
|
+
report("set", error);
|
|
1215
|
+
}
|
|
1216
|
+
return info;
|
|
1217
|
+
};
|
|
1218
|
+
}
|
|
1219
|
+
//#endregion
|
|
1220
|
+
//#region src/client.ts
|
|
1221
|
+
const CREDENTIAL_PROBE_INVOICE_NUMBER = "KASSZA-CREDENTIAL-PROBE-0";
|
|
1222
|
+
async function nullIfNotFound(promise) {
|
|
1223
|
+
try {
|
|
1224
|
+
return await promise;
|
|
1225
|
+
} catch (error) {
|
|
1226
|
+
if (require_errors.isSzamlazzError(error) && (error.isNotFound || error.code === 7)) return null;
|
|
1227
|
+
throw error;
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
function attemptKeyOf(target) {
|
|
1231
|
+
if (typeof target === "string") return target;
|
|
1232
|
+
const key = target.details?.attemptKey;
|
|
1233
|
+
if (key === void 0) throw new TypeError("A resetAttempts egy attempt_limit hibát vagy annak details.attemptKey kulcsát várja.");
|
|
1234
|
+
return key;
|
|
1235
|
+
}
|
|
1236
|
+
function invoiceNumberOf(input) {
|
|
1237
|
+
return typeof input === "string" ? input : input.invoiceNumber;
|
|
1238
|
+
}
|
|
1239
|
+
function receiptNumberOf(input) {
|
|
1240
|
+
return typeof input === "string" ? input : input.receiptNumber;
|
|
1241
|
+
}
|
|
1242
|
+
function createDocumentEmitter(hook, options) {
|
|
1243
|
+
return { emit: (event) => require_create_once.emitDocumentEvent(hook, event, options) };
|
|
1244
|
+
}
|
|
1245
|
+
function createInvoicesApi(ctx, defaults, events, guard) {
|
|
1246
|
+
const api = {
|
|
1247
|
+
async create(input, options) {
|
|
1248
|
+
const document = await createInvoice(ctx, defaults, input, options);
|
|
1249
|
+
await events.emit({
|
|
1250
|
+
kind: "invoice",
|
|
1251
|
+
action: "created",
|
|
1252
|
+
number: document.number,
|
|
1253
|
+
document,
|
|
1254
|
+
input
|
|
1255
|
+
});
|
|
1256
|
+
return document;
|
|
1257
|
+
},
|
|
1258
|
+
createOnce: (input, options) => require_issue.createInvoiceOnce(api, input, options, guard),
|
|
1259
|
+
preview: (input, options) => previewInvoice(ctx, defaults, input, options),
|
|
1260
|
+
async reverse(input, options) {
|
|
1261
|
+
const document = await reverseInvoice(ctx, input, options);
|
|
1262
|
+
await events.emit({
|
|
1263
|
+
kind: "invoice",
|
|
1264
|
+
action: "reversed",
|
|
1265
|
+
number: document.number,
|
|
1266
|
+
reversedNumber: invoiceNumberOf(input),
|
|
1267
|
+
document
|
|
1268
|
+
});
|
|
1269
|
+
return document;
|
|
1270
|
+
},
|
|
1271
|
+
async registerPayment(input, options) {
|
|
1272
|
+
const document = await require_create_once.registerPayment(ctx, input, options);
|
|
1273
|
+
await events.emit({
|
|
1274
|
+
kind: "invoice",
|
|
1275
|
+
action: "payment",
|
|
1276
|
+
number: document.invoiceNumber,
|
|
1277
|
+
document
|
|
1278
|
+
});
|
|
1279
|
+
return document;
|
|
1280
|
+
},
|
|
1281
|
+
registerPaymentOnce: (input, options) => require_create_once.registerPaymentOnce(api, input, options, guard),
|
|
1282
|
+
async clearPayments(input, options) {
|
|
1283
|
+
const document = await require_create_once.clearPayments(ctx, input, options);
|
|
1284
|
+
await events.emit({
|
|
1285
|
+
kind: "invoice",
|
|
1286
|
+
action: "payment",
|
|
1287
|
+
number: document.invoiceNumber,
|
|
1288
|
+
document
|
|
1289
|
+
});
|
|
1290
|
+
return document;
|
|
1291
|
+
},
|
|
1292
|
+
getPdf: (reference, options) => getInvoicePdf(ctx, reference, options),
|
|
1293
|
+
get: (reference, query, options) => require_get.getInvoice(ctx, reference, query, options),
|
|
1294
|
+
find: (reference, query, options) => nullIfNotFound(require_get.getInvoice(ctx, reference, query, options)),
|
|
1295
|
+
deleteProforma: (reference, options) => deleteProforma(ctx, reference, options)
|
|
1296
|
+
};
|
|
1297
|
+
return api;
|
|
1298
|
+
}
|
|
1299
|
+
function convertedJoin(result) {
|
|
1300
|
+
return {
|
|
1301
|
+
receipt: result.receipt,
|
|
1302
|
+
invoice: {
|
|
1303
|
+
...result.invoice,
|
|
1304
|
+
created: false
|
|
1305
|
+
}
|
|
1306
|
+
};
|
|
1307
|
+
}
|
|
1308
|
+
function createReceiptsApi(ctx, defaults, invoices, events, guard) {
|
|
1309
|
+
const api = {
|
|
1310
|
+
async create(input, options) {
|
|
1311
|
+
const document = await require_create.createReceipt(ctx, defaults, input, options);
|
|
1312
|
+
await events.emit({
|
|
1313
|
+
kind: "receipt",
|
|
1314
|
+
action: "created",
|
|
1315
|
+
number: document.number,
|
|
1316
|
+
document
|
|
1317
|
+
});
|
|
1318
|
+
return document;
|
|
1319
|
+
},
|
|
1320
|
+
createOnce: (input, options) => require_create_once.createReceiptOnce(api, input, options, guard),
|
|
1321
|
+
async reverse(input, options) {
|
|
1322
|
+
const document = await reverseReceipt(ctx, input, options);
|
|
1323
|
+
await events.emit({
|
|
1324
|
+
kind: "receipt",
|
|
1325
|
+
action: "reversed",
|
|
1326
|
+
number: document.number,
|
|
1327
|
+
reversedNumber: receiptNumberOf(input),
|
|
1328
|
+
document
|
|
1329
|
+
});
|
|
1330
|
+
return document;
|
|
1331
|
+
},
|
|
1332
|
+
get: (input, options) => getReceipt(ctx, input, options),
|
|
1333
|
+
find: (input, options) => nullIfNotFound(getReceipt(ctx, input, options)),
|
|
1334
|
+
send: (input, options) => sendReceipt(ctx, input, options),
|
|
1335
|
+
convertToInvoice: (input, options = {}) => require_issue.guardOnce(guard, `convert:${input.receiptNumber?.trim() ?? ""}`, {
|
|
1336
|
+
...options,
|
|
1337
|
+
lock: false
|
|
1338
|
+
}, () => require_issue.convertReceiptToInvoice({
|
|
1339
|
+
receipts: api,
|
|
1340
|
+
invoices
|
|
1341
|
+
}, input, options), convertedJoin)
|
|
1342
|
+
};
|
|
1343
|
+
return api;
|
|
1344
|
+
}
|
|
1345
|
+
function onceScopeOf(ctx) {
|
|
1346
|
+
return ctx.credentials.map((node) => `${node.name}=${String(node.content)}`).join("\n");
|
|
1347
|
+
}
|
|
1348
|
+
function createKassza(options = {}) {
|
|
1349
|
+
const ctx = createAgentContext(options);
|
|
1350
|
+
const events = createDocumentEmitter(options.hooks?.onDocument, {
|
|
1351
|
+
mode: options.hooks?.onDocumentError,
|
|
1352
|
+
onWarning: options.hooks?.onWarning
|
|
1353
|
+
});
|
|
1354
|
+
const guard = {
|
|
1355
|
+
scope: onceScopeOf(ctx),
|
|
1356
|
+
lock: options.createOnceLock,
|
|
1357
|
+
warn: ctx.warn
|
|
1358
|
+
};
|
|
1359
|
+
const directQuery = (taxNumber, requestOptions) => queryTaxpayer(ctx, taxNumber, requestOptions);
|
|
1360
|
+
const taxpayerQuery = options.taxpayerCache ? cachedTaxpayerQuery(directQuery, options.taxpayerCache, ctx.warn) : directQuery;
|
|
1361
|
+
const invoices = createInvoicesApi(ctx, options.defaults?.invoice ?? {}, events, guard);
|
|
1362
|
+
const receipts = createReceiptsApi(ctx, options.defaults?.receipt ?? {}, invoices, events, guard);
|
|
1363
|
+
return {
|
|
1364
|
+
invoices,
|
|
1365
|
+
receipts,
|
|
1366
|
+
taxpayer: { query: taxpayerQuery },
|
|
1367
|
+
async verifyCredentials(requestOptions) {
|
|
1368
|
+
try {
|
|
1369
|
+
await getInvoicePdf(ctx, CREDENTIAL_PROBE_INVOICE_NUMBER, requestOptions);
|
|
1370
|
+
return true;
|
|
1371
|
+
} catch (error) {
|
|
1372
|
+
if (!require_errors.isSzamlazzError(error)) throw error;
|
|
1373
|
+
if (error.category === "auth") return false;
|
|
1374
|
+
if (error.isNotFound || error.code === 7) return true;
|
|
1375
|
+
throw error;
|
|
1376
|
+
}
|
|
1377
|
+
},
|
|
1378
|
+
resetSession: () => ctx.resetSession(),
|
|
1379
|
+
resetAttempts: (target) => ctx.resetAttempts(attemptKeyOf(target)),
|
|
1380
|
+
issueForPayment: (payment, issueOptions) => require_issue.issueForPayment({
|
|
1381
|
+
invoices,
|
|
1382
|
+
receipts
|
|
1383
|
+
}, payment, issueOptions)
|
|
1384
|
+
};
|
|
1385
|
+
}
|
|
1386
|
+
//#endregion
|
|
1387
|
+
Object.defineProperty(exports, "ATTEMPT_LEDGER_KEY_PREFIX", {
|
|
1388
|
+
enumerable: true,
|
|
1389
|
+
get: function() {
|
|
1390
|
+
return ATTEMPT_LEDGER_KEY_PREFIX;
|
|
1391
|
+
}
|
|
1392
|
+
});
|
|
1393
|
+
Object.defineProperty(exports, "ATTEMPT_LEDGER_TTL_SECONDS", {
|
|
1394
|
+
enumerable: true,
|
|
1395
|
+
get: function() {
|
|
1396
|
+
return ATTEMPT_LEDGER_TTL_SECONDS;
|
|
1397
|
+
}
|
|
1398
|
+
});
|
|
1399
|
+
Object.defineProperty(exports, "DEFAULT_TAXPAYER_INVALID_TTL_SECONDS", {
|
|
1400
|
+
enumerable: true,
|
|
1401
|
+
get: function() {
|
|
1402
|
+
return DEFAULT_TAXPAYER_INVALID_TTL_SECONDS;
|
|
1403
|
+
}
|
|
1404
|
+
});
|
|
1405
|
+
Object.defineProperty(exports, "DEFAULT_TAXPAYER_TTL_SECONDS", {
|
|
1406
|
+
enumerable: true,
|
|
1407
|
+
get: function() {
|
|
1408
|
+
return DEFAULT_TAXPAYER_TTL_SECONDS;
|
|
1409
|
+
}
|
|
1410
|
+
});
|
|
1411
|
+
Object.defineProperty(exports, "TAXPAYER_CACHE_KEY_PREFIX", {
|
|
1412
|
+
enumerable: true,
|
|
1413
|
+
get: function() {
|
|
1414
|
+
return TAXPAYER_CACHE_KEY_PREFIX;
|
|
1415
|
+
}
|
|
1416
|
+
});
|
|
1417
|
+
Object.defineProperty(exports, "attemptLedgerKey", {
|
|
1418
|
+
enumerable: true,
|
|
1419
|
+
get: function() {
|
|
1420
|
+
return attemptLedgerKey;
|
|
1421
|
+
}
|
|
1422
|
+
});
|
|
1423
|
+
Object.defineProperty(exports, "buildCreateInvoiceXml", {
|
|
1424
|
+
enumerable: true,
|
|
1425
|
+
get: function() {
|
|
1426
|
+
return buildCreateInvoiceXml;
|
|
1427
|
+
}
|
|
1428
|
+
});
|
|
1429
|
+
Object.defineProperty(exports, "createAgentContext", {
|
|
1430
|
+
enumerable: true,
|
|
1431
|
+
get: function() {
|
|
1432
|
+
return createAgentContext;
|
|
1433
|
+
}
|
|
1434
|
+
});
|
|
1435
|
+
Object.defineProperty(exports, "createKassza", {
|
|
1436
|
+
enumerable: true,
|
|
1437
|
+
get: function() {
|
|
1438
|
+
return createKassza;
|
|
1439
|
+
}
|
|
1440
|
+
});
|
|
1441
|
+
Object.defineProperty(exports, "getInvoicePdf", {
|
|
1442
|
+
enumerable: true,
|
|
1443
|
+
get: function() {
|
|
1444
|
+
return getInvoicePdf;
|
|
1445
|
+
}
|
|
1446
|
+
});
|
|
1447
|
+
Object.defineProperty(exports, "queryTaxpayer", {
|
|
1448
|
+
enumerable: true,
|
|
1449
|
+
get: function() {
|
|
1450
|
+
return queryTaxpayer;
|
|
1451
|
+
}
|
|
1452
|
+
});
|