kassza 0.1.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.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -0
  3. package/agents/README.md +59 -0
  4. package/agents/api.md +206 -0
  5. package/agents/pitfalls.md +52 -0
  6. package/agents/recipes.md +217 -0
  7. package/agents/skills/kassza/SKILL.md +29 -0
  8. package/assets/logo-wordmark.svg +25 -0
  9. package/assets/logo.svg +19 -0
  10. package/dist/binary-B89HM03_.cjs +63 -0
  11. package/dist/binary-D0M9U2MD.js +34 -0
  12. package/dist/client-B9kbKKBf.d.cts +748 -0
  13. package/dist/client-zv4enyq7.d.ts +748 -0
  14. package/dist/cookie-stores/index.cjs +153 -0
  15. package/dist/cookie-stores/index.d.cts +63 -0
  16. package/dist/cookie-stores/index.d.ts +63 -0
  17. package/dist/cookie-stores/index.js +144 -0
  18. package/dist/create-BZd6CUO7.cjs +1160 -0
  19. package/dist/create-DDZaNlOz.js +939 -0
  20. package/dist/dates-D2XebOIg.js +34 -0
  21. package/dist/dates-DtHzwNU6.d.cts +7 -0
  22. package/dist/dates-DtHzwNU6.d.ts +7 -0
  23. package/dist/dates-PPxH0n5H.cjs +57 -0
  24. package/dist/errors-B0QJhUW1.cjs +302 -0
  25. package/dist/errors-DapdV5DK.js +273 -0
  26. package/dist/index-CYAGCdKJ.d.cts +56 -0
  27. package/dist/index-CYAGCdKJ.d.ts +56 -0
  28. package/dist/index.cjs +1406 -0
  29. package/dist/index.d.cts +8 -0
  30. package/dist/index.d.ts +8 -0
  31. package/dist/index.js +1394 -0
  32. package/dist/ipn/index.cjs +108 -0
  33. package/dist/ipn/index.d.cts +32 -0
  34. package/dist/ipn/index.d.ts +32 -0
  35. package/dist/ipn/index.js +101 -0
  36. package/dist/money/index.cjs +15 -0
  37. package/dist/money/index.d.cts +2 -0
  38. package/dist/money/index.d.ts +2 -0
  39. package/dist/money/index.js +2 -0
  40. package/dist/money-C9j7nBNP.js +258 -0
  41. package/dist/money-DkiGukAw.cjs +335 -0
  42. package/dist/session-CRGOuz-R.cjs +100 -0
  43. package/dist/session-Dm_45x8K.d.cts +11 -0
  44. package/dist/session-Dm_45x8K.d.ts +11 -0
  45. package/dist/session-OJMLGufT.js +77 -0
  46. package/dist/shared-CrxlxI8n.cjs +207 -0
  47. package/dist/shared-D6DLa4b7.js +100 -0
  48. package/dist/storage/fs.cjs +88 -0
  49. package/dist/storage/fs.d.cts +13 -0
  50. package/dist/storage/fs.d.ts +13 -0
  51. package/dist/storage/fs.js +87 -0
  52. package/dist/storage/index.cjs +643 -0
  53. package/dist/storage/index.d.cts +288 -0
  54. package/dist/storage/index.d.ts +288 -0
  55. package/dist/storage/index.js +619 -0
  56. package/dist/testing/index.cjs +409 -0
  57. package/dist/testing/index.d.cts +35 -0
  58. package/dist/testing/index.d.ts +35 -0
  59. package/dist/testing/index.js +407 -0
  60. package/dist/types-DVRgwcqg.d.cts +26 -0
  61. package/dist/types-DVRgwcqg.d.ts +26 -0
  62. package/dist/validators/index.cjs +296 -0
  63. package/dist/validators/index.d.cts +51 -0
  64. package/dist/validators/index.d.ts +51 -0
  65. package/dist/validators/index.js +278 -0
  66. package/llms.txt +16 -0
  67. package/package.json +151 -0
@@ -0,0 +1,1160 @@
1
+ const require_errors = require("./errors-B0QJhUW1.cjs");
2
+ const require_binary = require("./binary-B89HM03_.cjs");
3
+ const require_dates = require("./dates-PPxH0n5H.cjs");
4
+ const require_money = require("./money-DkiGukAw.cjs");
5
+ //#region src/core/actions.ts
6
+ const SZAMLAZZ_AGENT_URL = "https://www.szamlazz.hu/szamla/";
7
+ const AGENT_ACTIONS = {
8
+ createInvoice: "action-xmlagentxmlfile",
9
+ reverseInvoice: "action-szamla_agent_st",
10
+ registerPayment: "action-szamla_agent_kifiz",
11
+ getInvoicePdf: "action-szamla_agent_pdf",
12
+ getInvoiceXml: "action-szamla_agent_xml",
13
+ deleteProforma: "action-szamla_agent_dijbekero_torlese",
14
+ createReceipt: "action-szamla_agent_nyugta_create",
15
+ reverseReceipt: "action-szamla_agent_nyugta_storno",
16
+ getReceipt: "action-szamla_agent_nyugta_get",
17
+ sendReceipt: "action-szamla_agent_nyugta_send",
18
+ queryTaxpayer: "action-szamla_agent_taxpayer"
19
+ };
20
+ const MAX_INVOICE_ATTACHMENTS = 5;
21
+ //#endregion
22
+ //#region src/core/xml/parse.ts
23
+ var XmlParseError = class extends Error {
24
+ name = "XmlParseError";
25
+ };
26
+ const NAMED_ENTITIES = {
27
+ amp: "&",
28
+ lt: "<",
29
+ gt: ">",
30
+ quot: "\"",
31
+ apos: "'"
32
+ };
33
+ function decodeEntities(value) {
34
+ return value.replace(/&(#x[0-9a-fA-F]+|#\d+|[a-zA-Z]+);/g, (match, entity) => {
35
+ if (entity.startsWith("#x")) return String.fromCodePoint(Number.parseInt(entity.slice(2), 16));
36
+ if (entity.startsWith("#")) return String.fromCodePoint(Number.parseInt(entity.slice(1), 10));
37
+ return NAMED_ENTITIES[entity] ?? match;
38
+ });
39
+ }
40
+ function localName(qualifiedName) {
41
+ const colon = qualifiedName.indexOf(":");
42
+ return colon === -1 ? qualifiedName : qualifiedName.slice(colon + 1);
43
+ }
44
+ const ATTRIBUTE_PATTERN = /([^\s=/>]+)\s*=\s*("([^"]*)"|'([^']*)')/g;
45
+ function parseAttributes(source) {
46
+ const attributes = {};
47
+ for (const match of source.matchAll(ATTRIBUTE_PATTERN)) {
48
+ const [, name, , doubleQuoted, singleQuoted] = match;
49
+ if (name === void 0) continue;
50
+ attributes[name] = decodeEntities(doubleQuoted ?? singleQuoted ?? "");
51
+ }
52
+ return attributes;
53
+ }
54
+ function skipUntil(xml, from, terminator) {
55
+ const end = xml.indexOf(terminator, from);
56
+ if (end === -1) throw new XmlParseError(`Lezáratlan szerkezet, hiányzik: ${terminator}`);
57
+ return end + terminator.length;
58
+ }
59
+ function parseXml(xml) {
60
+ const stack = [];
61
+ let root;
62
+ let position = xml.charCodeAt(0) === 65279 ? 1 : 0;
63
+ const appendText = (value) => {
64
+ const current = stack.at(-1);
65
+ if (current) current.text += value;
66
+ };
67
+ while (position < xml.length) {
68
+ const tagStart = xml.indexOf("<", position);
69
+ if (tagStart === -1) {
70
+ appendText(decodeEntities(xml.slice(position)));
71
+ break;
72
+ }
73
+ if (tagStart > position) appendText(decodeEntities(xml.slice(position, tagStart)));
74
+ if (xml.startsWith("<!--", tagStart)) {
75
+ position = skipUntil(xml, tagStart + 4, "-->");
76
+ continue;
77
+ }
78
+ if (xml.startsWith("<![CDATA[", tagStart)) {
79
+ const end = xml.indexOf("]]>", tagStart + 9);
80
+ if (end === -1) throw new XmlParseError("Lezáratlan CDATA szakasz");
81
+ appendText(xml.slice(tagStart + 9, end));
82
+ position = end + 3;
83
+ continue;
84
+ }
85
+ if (xml.startsWith("<?", tagStart)) {
86
+ position = skipUntil(xml, tagStart + 2, "?>");
87
+ continue;
88
+ }
89
+ if (xml.startsWith("<!", tagStart)) {
90
+ position = skipUntil(xml, tagStart + 2, ">");
91
+ continue;
92
+ }
93
+ const tagEnd = xml.indexOf(">", tagStart);
94
+ if (tagEnd === -1) throw new XmlParseError("Lezáratlan XML tag");
95
+ const rawTag = xml.slice(tagStart + 1, tagEnd);
96
+ position = tagEnd + 1;
97
+ if (rawTag.startsWith("/")) {
98
+ const closingName = localName(rawTag.slice(1).trim());
99
+ const current = stack.pop();
100
+ if (!current || current.name !== closingName) throw new XmlParseError(`Váratlan záró tag: ${closingName}`);
101
+ continue;
102
+ }
103
+ const selfClosing = rawTag.endsWith("/");
104
+ const tagBody = selfClosing ? rawTag.slice(0, -1) : rawTag;
105
+ const nameMatch = /^\s*([^\s/>]+)/.exec(tagBody);
106
+ if (!nameMatch?.[1]) throw new XmlParseError("Érvénytelen XML tag");
107
+ const element = {
108
+ name: localName(nameMatch[1]),
109
+ attributes: parseAttributes(tagBody.slice(nameMatch[0].length)),
110
+ children: [],
111
+ text: ""
112
+ };
113
+ const parent = stack.at(-1);
114
+ if (parent) parent.children.push(element);
115
+ else if (root) throw new XmlParseError("Az XML-nek csak egy gyökéreleme lehet");
116
+ else root = element;
117
+ if (!selfClosing) stack.push(element);
118
+ }
119
+ if (stack.length > 0) throw new XmlParseError(`Lezáratlan elem: ${stack.at(-1)?.name}`);
120
+ if (!root) throw new XmlParseError("Üres XML dokumentum");
121
+ return root;
122
+ }
123
+ function findChild(element, name) {
124
+ return element?.children.find((child) => child.name === name);
125
+ }
126
+ function findChildren(element, name) {
127
+ return element?.children.filter((child) => child.name === name) ?? [];
128
+ }
129
+ function childText(element, name) {
130
+ const child = findChild(element, name);
131
+ if (!child) return void 0;
132
+ const value = child.text.trim();
133
+ return value === "" ? void 0 : value;
134
+ }
135
+ function childNumber(element, name) {
136
+ const value = childText(element, name);
137
+ if (value === void 0) return void 0;
138
+ const parsed = Number(value.replace(",", "."));
139
+ return Number.isFinite(parsed) ? parsed : void 0;
140
+ }
141
+ function childBoolean(element, name) {
142
+ const value = childText(element, name)?.toLowerCase();
143
+ if (value === "true" || value === "1") return true;
144
+ if (value === "false" || value === "0") return false;
145
+ }
146
+ //#endregion
147
+ //#region src/core/response.ts
148
+ function createAgentResponse(action, status, headers, body) {
149
+ let cachedText;
150
+ return {
151
+ action,
152
+ status,
153
+ headers,
154
+ body,
155
+ isPdf: require_binary.isPdf(body),
156
+ text() {
157
+ cachedText ??= require_binary.decodeUtf8(body);
158
+ return cachedText;
159
+ }
160
+ };
161
+ }
162
+ function decodeHeaderValue(value) {
163
+ try {
164
+ return decodeURIComponent(value.replace(/\+/g, " "));
165
+ } catch {
166
+ return value;
167
+ }
168
+ }
169
+ function readHeader(headers, name, encoded = false) {
170
+ const raw = headers.get(name);
171
+ if (raw === null) return void 0;
172
+ const value = (encoded ? decodeHeaderValue(raw) : raw).trim();
173
+ return value === "" ? void 0 : value;
174
+ }
175
+ function readNumberHeader(headers, name) {
176
+ const value = readHeader(headers, name);
177
+ if (value === void 0) return void 0;
178
+ const parsed = Number(value.replace(",", "."));
179
+ return Number.isFinite(parsed) ? parsed : void 0;
180
+ }
181
+ function readDocumentHeaders(headers) {
182
+ return {
183
+ number: readHeader(headers, "szlahu_szamlaszam", true),
184
+ netTotal: readNumberHeader(headers, "szlahu_nettovegosszeg"),
185
+ grossTotal: readNumberHeader(headers, "szlahu_bruttovegosszeg"),
186
+ paymentMethod: readHeader(headers, "szlahu_fizetesmod", true),
187
+ buyerAccountUrl: readHeader(headers, "szlahu_vevoifiokurl", true)
188
+ };
189
+ }
190
+ const RAW_RESPONSE_PREVIEW_LENGTH = 2e3;
191
+ function rawPreview(response) {
192
+ if (response.isPdf) return void 0;
193
+ return response.text().slice(0, RAW_RESPONSE_PREVIEW_LENGTH);
194
+ }
195
+ function throwIfHeaderError(response) {
196
+ const message = readHeader(response.headers, "szlahu_error", true);
197
+ const code = require_errors.parseErrorCode(response.headers.get("szlahu_error_code"));
198
+ if (message === void 0 && code === void 0) return;
199
+ throw require_errors.createAgentError({
200
+ code,
201
+ message,
202
+ action: response.action,
203
+ httpStatus: response.status,
204
+ rawResponse: rawPreview(response)
205
+ });
206
+ }
207
+ function extractTextError(text) {
208
+ const start = text.indexOf("[ERR]");
209
+ if (start === -1) return void 0;
210
+ const afterMarker = text.slice(start + 5);
211
+ const separator = afterMarker.search(/-{5,}/);
212
+ const message = (separator === -1 ? afterMarker.split("\n")[0] ?? "" : afterMarker.slice(0, separator)).replace(/\s+/g, " ").trim();
213
+ const codeMatch = /^\[?(\d{1,4})\]?\s+/.exec(message);
214
+ if (codeMatch?.[1]) return {
215
+ code: Number(codeMatch[1]),
216
+ message: message.slice(codeMatch[0].length)
217
+ };
218
+ return {
219
+ code: void 0,
220
+ message
221
+ };
222
+ }
223
+ function throwIfTextError(response) {
224
+ if (response.isPdf) return;
225
+ const text = response.text().trimStart();
226
+ if (!text.startsWith("[ERR]")) return;
227
+ const error = extractTextError(text);
228
+ if (!error) return;
229
+ throw require_errors.createAgentError({
230
+ code: error.code,
231
+ message: error.message,
232
+ action: response.action,
233
+ httpStatus: response.status,
234
+ rawResponse: rawPreview(response)
235
+ });
236
+ }
237
+ function parseDoneText(text) {
238
+ const match = /xmlagentresponse\s*=\s*DONE(?:;([^\r\n]*))?/i.exec(text);
239
+ if (!match) return void 0;
240
+ const number = match[1]?.trim();
241
+ return { number: number ? decodeHeaderValue(number) : void 0 };
242
+ }
243
+ function unexpectedResponse(response, detail) {
244
+ const suffix = detail ? ` ${detail}` : "";
245
+ return new require_errors.SzamlazzError(`Váratlan válasz a Számlázz.hu-tól (HTTP ${response.status}).${suffix}`, {
246
+ category: "unexpected_response",
247
+ action: response.action,
248
+ httpStatus: response.status,
249
+ rawResponse: rawPreview(response)
250
+ });
251
+ }
252
+ function looksLikeXml(response) {
253
+ if (response.isPdf) return false;
254
+ const text = response.text();
255
+ return /^\s*</.test(text.charCodeAt(0) === 65279 ? text.slice(1) : text);
256
+ }
257
+ function parseResponseXml(response) {
258
+ if (!looksLikeXml(response)) throw unexpectedResponse(response, "XML választ vártunk.");
259
+ try {
260
+ return parseXml(response.text());
261
+ } catch (error) {
262
+ throw new require_errors.SzamlazzError(`A Számlázz.hu XML válasza nem értelmezhető (HTTP ${response.status}).`, {
263
+ category: "unexpected_response",
264
+ action: response.action,
265
+ httpStatus: response.status,
266
+ rawResponse: rawPreview(response),
267
+ cause: error
268
+ });
269
+ }
270
+ }
271
+ function throwIfXmlFailure(root, response) {
272
+ const success = childText(root, "sikeres")?.toLowerCase();
273
+ const code = childNumber(root, "hibakod");
274
+ const message = childText(root, "hibauzenet");
275
+ if (success === "true" && code === void 0) return;
276
+ if (success === void 0 && code === void 0 && message === void 0) return;
277
+ throw require_errors.createAgentError({
278
+ code,
279
+ message,
280
+ action: response.action,
281
+ httpStatus: response.status,
282
+ rawResponse: rawPreview(response)
283
+ });
284
+ }
285
+ function throwIfHttpError(response) {
286
+ if (response.status >= 200 && response.status < 400) return;
287
+ const error = unexpectedResponse(response);
288
+ if (response.status >= 500) throw new require_errors.SzamlazzError(error.message, {
289
+ category: "network",
290
+ action: response.action,
291
+ httpStatus: response.status,
292
+ rawResponse: error.rawResponse
293
+ });
294
+ throw error;
295
+ }
296
+ function throwIfAnyError(response) {
297
+ throwIfHeaderError(response);
298
+ throwIfTextError(response);
299
+ throwIfHttpError(response);
300
+ }
301
+ //#endregion
302
+ //#region src/core/xml/serialize.ts
303
+ function el(name, content) {
304
+ return {
305
+ name,
306
+ content
307
+ };
308
+ }
309
+ function optionalEl(name, content) {
310
+ if (content === void 0 || content === null) return void 0;
311
+ if (Array.isArray(content) && !content.some(Boolean)) return void 0;
312
+ return {
313
+ name,
314
+ content
315
+ };
316
+ }
317
+ function isAllowedXmlChar(codePoint) {
318
+ if (codePoint === 9 || codePoint === 10 || codePoint === 13) return true;
319
+ if (codePoint < 32) return false;
320
+ return codePoint !== 65534 && codePoint !== 65535;
321
+ }
322
+ function stripInvalidXmlChars(value) {
323
+ let result = "";
324
+ for (const char of value) if (isAllowedXmlChar(char.codePointAt(0) ?? 0)) result += char;
325
+ return result;
326
+ }
327
+ function escapeXml(value) {
328
+ return stripInvalidXmlChars(value).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
329
+ }
330
+ function formatXmlNumber(value) {
331
+ if (!Number.isFinite(value)) throw new RangeError(`Az XML-be csak véges szám írható, kapott: ${value}`);
332
+ if (Number.isInteger(value)) return value.toString();
333
+ const fixed = value.toFixed(10).replace(/0+$/, "").replace(/\.$/, "");
334
+ return fixed === "-0" ? "0" : fixed;
335
+ }
336
+ function formatScalar(value) {
337
+ if (typeof value === "boolean") return value ? "true" : "false";
338
+ if (typeof value === "number") return formatXmlNumber(value);
339
+ return escapeXml(value);
340
+ }
341
+ function isPresent(child) {
342
+ return Boolean(child);
343
+ }
344
+ function renderNode(node, depth) {
345
+ const indent = " ".repeat(depth);
346
+ const { name, content } = node;
347
+ if (content === void 0 || content === null) return `${indent}<${name}></${name}>`;
348
+ if (!Array.isArray(content)) return `${indent}<${name}>${formatScalar(content)}</${name}>`;
349
+ const children = content.filter(isPresent);
350
+ if (children.length === 0) return `${indent}<${name}></${name}>`;
351
+ return `${indent}<${name}>\n${children.map((child) => renderNode(child, depth + 1)).join("\n")}\n${indent}</${name}>`;
352
+ }
353
+ function buildXmlDocument(options) {
354
+ const attributes = [`xmlns="${options.namespace}"`];
355
+ if (options.schemaLocation !== void 0) attributes.push("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"", `xsi:schemaLocation="${options.namespace} ${options.schemaLocation}"`);
356
+ const body = options.children.filter(isPresent).map((child) => renderNode(child, 1)).join("\n");
357
+ return `<?xml version="1.0" encoding="UTF-8"?>\n<${options.root} ${attributes.join(" ")}>\n${body}\n</${options.root}>\n`;
358
+ }
359
+ //#endregion
360
+ //#region src/invoices/create-types.ts
361
+ const INVOICE_TYPES = [
362
+ "invoice",
363
+ "proforma",
364
+ "advance",
365
+ "final",
366
+ "corrective",
367
+ "deliveryNote"
368
+ ];
369
+ const INVOICE_LANGUAGES = [
370
+ "hu",
371
+ "en",
372
+ "de",
373
+ "it",
374
+ "ro",
375
+ "sk",
376
+ "hr",
377
+ "fr",
378
+ "es",
379
+ "cz",
380
+ "pl",
381
+ "bg",
382
+ "nl",
383
+ "ru",
384
+ "si"
385
+ ];
386
+ const INVOICE_TEMPLATES = [
387
+ "SzlaMost",
388
+ "SzlaAlap",
389
+ "SzlaNoEnv",
390
+ "Szla8cm",
391
+ "SzlaTomb",
392
+ "SzlaFuvarlevelesAlap"
393
+ ];
394
+ const TAXPAYER_TYPE_CODES = {
395
+ nonEuBusiness: 7,
396
+ euBusiness: 6,
397
+ hungarianTaxNumber: 1,
398
+ unknown: 0,
399
+ noTaxNumber: -1
400
+ };
401
+ const SIMPLE_ITEMS_MAX = 2;
402
+ const SIMPLE_ITEMS_FINAL_MAX = 4;
403
+ const SIMPLE_ITEMS_VAT_RATES = /* @__PURE__ */ new Set([
404
+ 0,
405
+ 5,
406
+ 18,
407
+ 27,
408
+ "TAM",
409
+ "AAM",
410
+ "K.AFA",
411
+ "F.AFA"
412
+ ]);
413
+ const LANGUAGES = new Set(INVOICE_LANGUAGES);
414
+ const TEMPLATES = new Set(INVOICE_TEMPLATES);
415
+ const TYPES = new Set(INVOICE_TYPES);
416
+ function invalid(message, cause) {
417
+ return new require_errors.SzamlazzError(message, {
418
+ category: "validation",
419
+ cause
420
+ });
421
+ }
422
+ function presentText(value) {
423
+ return value === void 0 || value.trim() === "" ? void 0 : value;
424
+ }
425
+ function agentDate(value, field) {
426
+ try {
427
+ return require_dates.toAgentDate(value);
428
+ } catch (error) {
429
+ throw invalid(`A(z) ${field} mező nem érvényes dátum: ${String(value)}`, error);
430
+ }
431
+ }
432
+ function optionalAgentDate(value, field) {
433
+ return value === void 0 ? void 0 : agentDate(value, field);
434
+ }
435
+ function requireText$1(value, message) {
436
+ if (typeof value !== "string" || value.trim() === "") throw invalid(message);
437
+ }
438
+ function assertNonNegativeInteger(value, field) {
439
+ if (value === void 0) return;
440
+ if (!Number.isInteger(value) || value < 0) throw invalid(`A(z) ${field} mező nemnegatív egész szám legyen, kapott: ${value}`);
441
+ }
442
+ function assertFinite(value, field) {
443
+ if (value !== void 0 && !Number.isFinite(value)) throw invalid(`A(z) ${field} mező nem érvényes szám: ${value}`);
444
+ }
445
+ function mergeSeller(defaults = {}, input = {}) {
446
+ return {
447
+ bank: input.bank ?? defaults.bank,
448
+ bankAccount: input.bankAccount ?? defaults.bankAccount,
449
+ emailReplyTo: input.emailReplyTo ?? defaults.emailReplyTo,
450
+ emailSubject: input.emailSubject ?? defaults.emailSubject,
451
+ emailText: input.emailText ?? defaults.emailText,
452
+ signatoryName: input.signatoryName ?? defaults.signatoryName
453
+ };
454
+ }
455
+ function resolveType(input) {
456
+ const type = input.type ?? "invoice";
457
+ if (!TYPES.has(type)) throw invalid(`Ismeretlen bizonylattípus: ${String(type)}`);
458
+ if (input.type === "corrective") requireText$1(input.correctedInvoiceNumber, "Helyesbítő számlához add meg a helyesbített számla számát (correctedInvoiceNumber).");
459
+ if (input.type === "final" && !presentText(input.advanceInvoiceNumber)) requireText$1(input.orderNumber, "Végszámlához add meg az előlegszámla számát (advanceInvoiceNumber) vagy az előlegszámla rendelésszámát (orderNumber).");
460
+ return type;
461
+ }
462
+ function resolveDates(defaults, input, now) {
463
+ if (input.dueDate !== void 0 && input.paymentDueInDays !== void 0) throw invalid("A dueDate és a paymentDueInDays közül csak az egyiket add meg.");
464
+ const issueDate = optionalAgentDate(input.issueDate, "issueDate") ?? agentDate(now, "now");
465
+ const fulfillmentDate = optionalAgentDate(input.fulfillmentDate, "fulfillmentDate") ?? issueDate;
466
+ const explicitDue = optionalAgentDate(input.dueDate, "dueDate");
467
+ if (explicitDue !== void 0) return {
468
+ issueDate,
469
+ fulfillmentDate,
470
+ dueDate: explicitDue
471
+ };
472
+ const days = input.paymentDueInDays ?? defaults.paymentDueInDays ?? 0;
473
+ assertNonNegativeInteger(days, "paymentDueInDays");
474
+ return {
475
+ issueDate,
476
+ fulfillmentDate,
477
+ dueDate: require_dates.addBudapestDays(/* @__PURE__ */ new Date(`${issueDate}T12:00:00Z`), days)
478
+ };
479
+ }
480
+ function resolveCurrency(defaults, input) {
481
+ const currency = presentText(input.currency) ?? presentText(defaults.currency) ?? "HUF";
482
+ const exchangeRate = input.exchangeRate;
483
+ if (require_money.isHuf(currency)) {
484
+ if (exchangeRate !== void 0 || presentText(input.exchangeBank) !== void 0) throw invalid("Forintos számlán nem adható meg árfolyam (exchangeRate, exchangeBank).");
485
+ return {
486
+ currency,
487
+ exchangeBank: void 0,
488
+ exchangeRate: void 0
489
+ };
490
+ }
491
+ if (exchangeRate !== void 0 && !(Number.isFinite(exchangeRate) && exchangeRate > 0)) throw invalid(`Az árfolyam (exchangeRate) pozitív szám legyen, kapott: ${exchangeRate}`);
492
+ const exchangeBank = presentText(input.exchangeBank) ?? presentText(defaults.exchangeBank) ?? "MNB";
493
+ if (exchangeRate === void 0 && exchangeBank.trim().toUpperCase() !== "MNB") throw invalid(`Devizás számlához (${currency}) add meg az árfolyamot (exchangeRate). Árfolyam nélkül csak az MNB automatikus árfolyama használható.`);
494
+ return {
495
+ currency,
496
+ exchangeBank,
497
+ exchangeRate
498
+ };
499
+ }
500
+ function resolveItems(items, currency) {
501
+ if (!Array.isArray(items) || items.length === 0) throw invalid("A számlán legalább egy tételnek szerepelnie kell.");
502
+ return items.map((item, index) => {
503
+ const label = `${index + 1}. tétel`;
504
+ requireText$1(item.name, `A(z) ${label} megnevezése (name) nem lehet üres.`);
505
+ const unit = item.unit ?? "db";
506
+ requireText$1(unit, `A(z) ${label} mennyiségi egysége (unit) nem lehet üres.`);
507
+ assertNonNegativeInteger(item.dataDeletionCode, `${label} dataDeletionCode`);
508
+ assertFinite(item.marginVatBase, `${label} marginVatBase`);
509
+ let amounts;
510
+ try {
511
+ amounts = require_money.calculateInvoiceItem(item, currency);
512
+ } catch (error) {
513
+ const message = error instanceof Error ? error.message : String(error);
514
+ throw invalid(`${label} (${item.name}): ${message}`, error);
515
+ }
516
+ return {
517
+ input: item,
518
+ unit,
519
+ amounts: {
520
+ name: item.name,
521
+ ...amounts
522
+ }
523
+ };
524
+ });
525
+ }
526
+ function validateSimpleItems(type, items) {
527
+ if (type === "corrective" || type === "deliveryNote") throw invalid("Egyszerűsített számlakép (simpleItems) helyesbítő számlán és szállítólevélen nem használható.");
528
+ const max = type === "final" ? SIMPLE_ITEMS_FINAL_MAX : SIMPLE_ITEMS_MAX;
529
+ if (items.length > max) throw invalid(`Egyszerűsített számlaképen (simpleItems) legfeljebb ${max} tétel adható meg.`);
530
+ const invalidItem = items.find((item) => !SIMPLE_ITEMS_VAT_RATES.has(item.amounts.vat));
531
+ if (invalidItem) throw invalid(`Egyszerűsített számlaképen (simpleItems) csak 0, 5, 18, 27, TAM, AAM, K.AFA vagy F.AFA áfakulcs használható, kapott: ${String(invalidItem.amounts.vat)}`);
532
+ }
533
+ function attachmentSize(content) {
534
+ if (typeof content === "string") return require_binary.encodeUtf8(content).byteLength;
535
+ if (content instanceof Blob) return content.size;
536
+ return content.byteLength;
537
+ }
538
+ function validateAttachments(attachments, sendEmail) {
539
+ if (attachments.length === 0) return attachments;
540
+ if (attachments.length > 5) throw invalid(`Legfeljebb 5 melléklet csatolható, kapott: ${attachments.length}`);
541
+ if (!sendEmail) throw invalid("Mellékletet csak e-mail értesítővel lehet küldeni: add meg a vevő e-mail címét, és ne kapcsold ki a sendEmail beállítást.");
542
+ for (const attachment of attachments) {
543
+ requireText$1(attachment.filename, "A melléklet fájlneve (filename) nem lehet üres.");
544
+ if (attachmentSize(attachment.content) > 2097152) throw invalid(`A(z) ${attachment.filename} melléklet nagyobb 2 MB-nál.`);
545
+ }
546
+ return attachments;
547
+ }
548
+ function validateWaybill(waybill) {
549
+ if (!waybill) return;
550
+ assertNonNegativeInteger(waybill.transOFlex?.packageCount, "waybill.transOFlex.packageCount");
551
+ assertNonNegativeInteger(waybill.sprinter?.packageCount, "waybill.sprinter.packageCount");
552
+ const mpl = waybill.mpl;
553
+ if (!mpl) return;
554
+ requireText$1(mpl.customerCode, "Az MPL fuvarlevélhez add meg a vevőkódot (customerCode).");
555
+ requireText$1(mpl.barcode, "Az MPL fuvarlevélhez add meg a vonalkódot (barcode).");
556
+ requireText$1(String(mpl.weight ?? ""), "Az MPL fuvarlevélhez add meg a tömeget (weight).");
557
+ assertFinite(mpl.declaredValue, "waybill.mpl.declaredValue");
558
+ }
559
+ function resolveSendEmail(defaults, input) {
560
+ const hasEmail = presentText(input.buyer.email) !== void 0;
561
+ if (input.buyer.sendEmail === true && !hasEmail) throw invalid("A sendEmail be van kapcsolva, de a vevőnek nincs e-mail címe (buyer.email).");
562
+ if (!hasEmail) return false;
563
+ return input.buyer.sendEmail ?? defaults.sendEmail ?? true;
564
+ }
565
+ function validateBuyer(input) {
566
+ const buyer = input.buyer;
567
+ if (!buyer || typeof buyer !== "object") throw invalid("A vevő adatai (buyer) kötelezők.");
568
+ requireText$1(buyer.name, "A vevő neve (buyer.name) nem lehet üres.");
569
+ requireText$1(buyer.zip, "A vevő irányítószáma (buyer.zip) nem lehet üres.");
570
+ requireText$1(buyer.city, "A vevő települése (buyer.city) nem lehet üres.");
571
+ requireText$1(buyer.address, "A vevő címe (buyer.address) nem lehet üres.");
572
+ }
573
+ function resolveInvoice(defaults, input, now) {
574
+ validateBuyer(input);
575
+ const type = resolveType(input);
576
+ const language = input.language ?? defaults.language ?? "hu";
577
+ if (!LANGUAGES.has(language)) throw invalid(`Ismeretlen számlanyelv: ${String(language)}`);
578
+ const template = input.template ?? defaults.template;
579
+ if (template !== void 0 && !TEMPLATES.has(template)) throw invalid(`Ismeretlen számlasablon: ${String(template)}`);
580
+ assertFinite(input.paymentCorrection, "paymentCorrection");
581
+ const currency = resolveCurrency(defaults, input);
582
+ const dates = resolveDates(defaults, input, now);
583
+ const items = resolveItems(input.items, currency.currency);
584
+ const simpleItems = input.simpleItems ?? defaults.simpleItems;
585
+ if (simpleItems) validateSimpleItems(type, items);
586
+ validateWaybill(input.waybill);
587
+ const sendEmail = resolveSendEmail(defaults, input);
588
+ const attachments = validateAttachments(input.attachments ?? [], sendEmail);
589
+ return {
590
+ input,
591
+ type,
592
+ ...dates,
593
+ ...currency,
594
+ paymentMethod: presentText(input.paymentMethod) ?? presentText(defaults.paymentMethod) ?? "Átutalás",
595
+ language,
596
+ prefix: presentText(input.prefix) ?? presentText(defaults.prefix),
597
+ eInvoice: input.eInvoice ?? defaults.eInvoice ?? false,
598
+ downloadPdf: input.downloadPdf ?? defaults.downloadPdf ?? true,
599
+ template,
600
+ simpleItems,
601
+ euVat: input.euVat ?? defaults.euVat,
602
+ logoExtra: presentText(input.logoExtra) ?? presentText(defaults.logoExtra),
603
+ aggregator: presentText(input.aggregator) ?? presentText(defaults.aggregator),
604
+ guardian: input.guardian ?? defaults.guardian,
605
+ articleIdentifierInvoice: input.articleIdentifierInvoice ?? defaults.articleIdentifierInvoice,
606
+ seller: mergeSeller(defaults.seller, input.seller),
607
+ sendEmail,
608
+ items,
609
+ attachments
610
+ };
611
+ }
612
+ //#endregion
613
+ //#region src/receipts/types.ts
614
+ const RECEIPT_ONLY_VAT_CODES = [
615
+ "ÁKK",
616
+ "MAA",
617
+ "EU",
618
+ "EUK"
619
+ ];
620
+ const RECEIPT_PDF_TEMPLATES = [
621
+ "A",
622
+ "N",
623
+ "J",
624
+ "L"
625
+ ];
626
+ //#endregion
627
+ //#region src/receipts/common.ts
628
+ const RECEIPT_XSD_BASE_URL = "https://www.szamlazz.hu/szamla/docs/xsds/";
629
+ function receiptValidationError(message) {
630
+ return new require_errors.SzamlazzError(message, { category: "validation" });
631
+ }
632
+ function requireText(value, message) {
633
+ const trimmed = value?.trim();
634
+ if (!trimmed) throw receiptValidationError(message);
635
+ return trimmed;
636
+ }
637
+ function optionalText(value) {
638
+ const trimmed = value?.trim();
639
+ return trimmed ? trimmed : void 0;
640
+ }
641
+ const templates = new Set(RECEIPT_PDF_TEMPLATES);
642
+ function validateTemplate(template) {
643
+ if (template === void 0) return void 0;
644
+ if (!templates.has(template)) throw receiptValidationError(`Ismeretlen nyugta PDF sablon: ${String(template)}. Lehetséges értékek: A (normál A4), N (80 mm), J (jegy), L (jegy logóval).`);
645
+ return template;
646
+ }
647
+ function requireReceiptNumber(value) {
648
+ return requireText(value, "Add meg a nyugtaszámot (receiptNumber).");
649
+ }
650
+ //#endregion
651
+ //#region src/receipts/parse.ts
652
+ function requiredText(element, name, response) {
653
+ const value = childText(element, name);
654
+ if (value === void 0) throw unexpectedResponse(response, `Hiányzik a(z) <${name}> elem a nyugta válaszból.`);
655
+ return value;
656
+ }
657
+ function amount(element, names) {
658
+ for (const name of names) {
659
+ const value = childNumber(element, name);
660
+ if (value !== void 0) return value;
661
+ }
662
+ return 0;
663
+ }
664
+ function vatOf(element) {
665
+ const vatPercentage = childNumber(element, "afakulcs") ?? 0;
666
+ return {
667
+ vat: childText(element, "afatipus") ?? vatPercentage,
668
+ vatPercentage
669
+ };
670
+ }
671
+ function parseLedger(element) {
672
+ const ledger = findChild(element, "fokonyv");
673
+ const revenue = childText(ledger, "arbevetel");
674
+ const vat = childText(ledger, "afa");
675
+ if (revenue === void 0 && vat === void 0) return void 0;
676
+ return {
677
+ revenue,
678
+ vat
679
+ };
680
+ }
681
+ function parseItem(element) {
682
+ return {
683
+ name: childText(element, "megnevezes") ?? "",
684
+ identifier: childText(element, "azonosito"),
685
+ quantity: childNumber(element, "mennyiseg") ?? 0,
686
+ unit: childText(element, "mennyisegiEgyseg") ?? "",
687
+ netUnitPrice: childNumber(element, "nettoEgysegar") ?? 0,
688
+ ...vatOf(element),
689
+ netAmount: amount(element, ["netto", "nettoErtek"]),
690
+ vatAmount: amount(element, ["afa", "afaErtek"]),
691
+ grossAmount: amount(element, ["brutto", "bruttoErtek"]),
692
+ ledger: parseLedger(element)
693
+ };
694
+ }
695
+ function parsePayment(element) {
696
+ return {
697
+ method: childText(element, "fizetoeszkoz") ?? "",
698
+ amount: childNumber(element, "osszeg") ?? 0,
699
+ description: childText(element, "leiras")
700
+ };
701
+ }
702
+ function parseVatTotal(element) {
703
+ return {
704
+ ...vatOf(element),
705
+ netAmount: amount(element, ["netto"]),
706
+ vatAmount: amount(element, ["afa"]),
707
+ grossAmount: amount(element, ["brutto"])
708
+ };
709
+ }
710
+ function parseTotals(receipt, items) {
711
+ const totals = findChild(receipt, "osszegek");
712
+ const byVat = findChildren(totals, "afakulcsossz").map(parseVatTotal);
713
+ const total = findChild(totals, "totalossz");
714
+ if (total) return {
715
+ netAmount: amount(total, ["netto"]),
716
+ vatAmount: amount(total, ["afa"]),
717
+ grossAmount: amount(total, ["brutto"]),
718
+ byVat
719
+ };
720
+ const sum = (pick) => Number(items.reduce((acc, item) => acc + pick(item), 0).toFixed(2));
721
+ return {
722
+ netAmount: sum((item) => item.netAmount),
723
+ vatAmount: sum((item) => item.vatAmount),
724
+ grossAmount: sum((item) => item.grossAmount),
725
+ byVat
726
+ };
727
+ }
728
+ function parsePdf(root) {
729
+ const encoded = childText(root, "nyugtaPdf");
730
+ if (encoded === void 0) return void 0;
731
+ const bytes = require_binary.base64ToBytes(encoded);
732
+ return bytes.length > 0 ? bytes : void 0;
733
+ }
734
+ function parseReceiptXml(root, response) {
735
+ const receipt = findChild(root, "nyugta");
736
+ const base = findChild(receipt, "alap");
737
+ if (!receipt || !base) throw unexpectedResponse(response, "A nyugta válaszból hiányzik a <nyugta> blokk.");
738
+ const items = findChildren(findChild(receipt, "tetelek"), "tetel").map(parseItem);
739
+ const pdf = parsePdf(root);
740
+ return {
741
+ id: childNumber(base, "id") ?? 0,
742
+ number: requiredText(base, "nyugtaszam", response),
743
+ callId: childText(base, "hivasAzonosito"),
744
+ type: childText(base, "tipus")?.toUpperCase() === "SN" ? "reversal" : "receipt",
745
+ isReversed: childBoolean(base, "stornozott") ?? false,
746
+ reversedReceiptNumber: childText(base, "stornozottNyugtaszam"),
747
+ issueDate: childText(base, "kelt") ?? "",
748
+ paymentMethod: childText(base, "fizmod") ?? "",
749
+ currency: childText(base, "penznem") ?? "HUF",
750
+ exchangeBank: childText(base, "devizabank"),
751
+ exchangeRate: childNumber(base, "devizaarf"),
752
+ comment: childText(base, "megjegyzes"),
753
+ customerLedgerId: childText(base, "fokonyvVevo"),
754
+ isTest: childBoolean(base, "teszt") ?? false,
755
+ orderNumber: childText(base, "rendelesSzam"),
756
+ items,
757
+ payments: findChildren(findChild(receipt, "kifizetesek"), "kifizetes").map(parsePayment),
758
+ totals: parseTotals(receipt, items),
759
+ ...pdf ? { pdf } : {}
760
+ };
761
+ }
762
+ function throwIfNotXml(response) {
763
+ throwIfHeaderError(response);
764
+ throwIfTextError(response);
765
+ if (looksLikeXml(response)) return;
766
+ throwIfHttpError(response);
767
+ throw unexpectedResponse(response, "XML választ vártunk.");
768
+ }
769
+ function parseReceiptResponse(response) {
770
+ throwIfNotXml(response);
771
+ const root = parseResponseXml(response);
772
+ throwIfXmlFailure(root, response);
773
+ if (childBoolean(root, "sikeres") !== true) {
774
+ throwIfHttpError(response);
775
+ throw unexpectedResponse(response, "A válasz nem jelez sikeres műveletet.");
776
+ }
777
+ return parseReceiptXml(root, response);
778
+ }
779
+ //#endregion
780
+ //#region src/receipts/create.ts
781
+ const CREATE_RECEIPT_NAMESPACE = "http://www.szamlazz.hu/xmlnyugtacreate";
782
+ const DEFAULT_CURRENCY = "HUF";
783
+ const DEFAULT_UNIT = "db";
784
+ const PREFIX_PATTERN = /^[A-Z0-9]+$/;
785
+ const AMOUNT_TOLERANCE = 2;
786
+ const MONEY_DECIMALS = 2;
787
+ const receiptOnlyVatCodes = new Set(RECEIPT_ONLY_VAT_CODES);
788
+ function calculateItem(item, currency, index) {
789
+ const vat = typeof item.vat === "string" && receiptOnlyVatCodes.has(item.vat) ? 0 : item.vat;
790
+ try {
791
+ return require_money.calculateReceiptItem({
792
+ ...item,
793
+ vat
794
+ }, currency);
795
+ } catch (error) {
796
+ if (!(error instanceof require_errors.SzamlazzError)) throw error;
797
+ throw receiptValidationError(`${index + 1}. tétel (${item.name}): ${error.message}`);
798
+ }
799
+ }
800
+ function assertHufAmounts(amounts, label, vat) {
801
+ if (!Number.isInteger(amounts.grossAmount)) throw receiptValidationError(`${label}: forintos nyugtán a bruttó összegnek egész számnak kell lennie (363).`);
802
+ if (require_money.decimalPlaces(amounts.netAmount) > MONEY_DECIMALS) throw receiptValidationError(`${label}: forintos nyugtán a nettó összeg legfeljebb 2 tizedesjegyet tartalmazhat (364).`);
803
+ if (require_money.decimalPlaces(amounts.vatAmount) > MONEY_DECIMALS) throw receiptValidationError(`${label}: forintos nyugtán az áfa összeg legfeljebb 2 tizedesjegyet tartalmazhat (365).`);
804
+ if (require_money.roundMoney(amounts.netAmount + amounts.vatAmount, MONEY_DECIMALS) !== amounts.grossAmount) throw receiptValidationError(`${label}: a nettó és az áfa összegének pontosan ki kell adnia a bruttót (261).`);
805
+ if (Math.abs(amounts.netUnitPrice * amounts.quantity - amounts.netAmount) > AMOUNT_TOLERANCE) throw receiptValidationError(`${label}: a nettó egységár és a mennyiség szorzata nem egyezik a nettó összeggel (259).`);
806
+ const expectedVat = amounts.netAmount * require_money.vatPercentage(vat) / 100;
807
+ if (Math.abs(expectedVat - amounts.vatAmount) > AMOUNT_TOLERANCE) throw receiptValidationError(`${label}: az áfa összeg nem egyezik a nettó összeg és az áfakulcs szorzatával (260).`);
808
+ }
809
+ function calculateReceiptItems(items, currency) {
810
+ if (items.length === 0) throw receiptValidationError("A nyugtán legalább egy tételnek szerepelnie kell.");
811
+ return items.map((input, index) => {
812
+ requireText(input.name, `A(z) ${index + 1}. tétel megnevezése (name) kötelező.`);
813
+ const amounts = calculateItem(input, currency, index);
814
+ if (require_money.isHuf(currency)) assertHufAmounts(amounts, `${index + 1}. tétel (${input.name})`, input.vat);
815
+ if (input.dataDeletionCode !== void 0) {
816
+ if (!Number.isInteger(input.dataDeletionCode) || input.dataDeletionCode < 0) throw receiptValidationError(`A(z) ${index + 1}. tétel adattörlő kódja (dataDeletionCode) nemnegatív egész szám legyen.`);
817
+ }
818
+ return {
819
+ input,
820
+ amounts,
821
+ vat: input.vat
822
+ };
823
+ });
824
+ }
825
+ function formatAmount(value, currency, decimals) {
826
+ return require_money.isHuf(currency) ? value.toFixed(decimals) : value;
827
+ }
828
+ function itemNode(item, currency, unit) {
829
+ const { input, amounts } = item;
830
+ const ledger = input.ledger;
831
+ return el("tetel", [
832
+ el("megnevezes", input.name.trim()),
833
+ optionalEl("azonosito", optionalText(input.identifier)),
834
+ el("mennyiseg", amounts.quantity),
835
+ el("mennyisegiEgyseg", optionalText(input.unit) ?? unit),
836
+ el("nettoEgysegar", amounts.netUnitPrice),
837
+ el("afakulcs", String(item.vat)),
838
+ el("netto", formatAmount(amounts.netAmount, currency, MONEY_DECIMALS)),
839
+ el("afa", formatAmount(amounts.vatAmount, currency, MONEY_DECIMALS)),
840
+ el("brutto", formatAmount(amounts.grossAmount, currency, 0)),
841
+ ledger && optionalEl("fokonyv", [optionalEl("arbevetel", optionalText(ledger.revenue)), optionalEl("afa", optionalText(ledger.vat))]),
842
+ optionalEl("megjegyzes", optionalText(input.comment)),
843
+ optionalEl("torloKod", input.dataDeletionCode)
844
+ ]);
845
+ }
846
+ function paymentNodes(payments, items) {
847
+ if (payments === void 0 || payments.length === 0) return void 0;
848
+ const nodes = payments.map((payment, index) => {
849
+ const method = requireText(payment.method, `A(z) ${index + 1}. kifizetés fizetési eszköze (method) kötelező.`);
850
+ if (!Number.isFinite(payment.amount)) throw receiptValidationError(`A(z) ${index + 1}. kifizetés összege nem érvényes szám.`);
851
+ return el("kifizetes", [
852
+ el("fizetoeszkoz", method),
853
+ el("osszeg", payment.amount),
854
+ optionalEl("leiras", optionalText(payment.description))
855
+ ]);
856
+ });
857
+ const paid = require_money.roundMoney(payments.reduce((sum, payment) => sum + payment.amount, 0), MONEY_DECIMALS);
858
+ const gross = require_money.roundMoney(items.reduce((sum, item) => sum + item.amounts.grossAmount, 0), MONEY_DECIMALS);
859
+ if (paid !== gross) throw receiptValidationError(`A kifizetések összege (${paid}) eltér a nyugta bruttó végösszegétől (${gross}) (340).`);
860
+ return el("kifizetesek", nodes);
861
+ }
862
+ function resolvePrefix(value) {
863
+ const prefix = requireText(value, "Add meg a nyugta előtagját (prefix) a hívásban vagy a receipts alapbeállításaiban.");
864
+ if (!PREFIX_PATTERN.test(prefix)) throw receiptValidationError(`A nyugta előtag csak nagybetűt és számot tartalmazhat, kapott: ${prefix} (337).`);
865
+ return prefix;
866
+ }
867
+ function resolveExchange(currency, rate, bank) {
868
+ if (require_money.isHuf(currency)) return {
869
+ rate: void 0,
870
+ bank: void 0
871
+ };
872
+ if (rate === void 0 || !Number.isFinite(rate) || rate <= 0) throw receiptValidationError(`Devizás nyugtánál (${currency}) add meg az árfolyamot (exchangeRate) pozitív számként.`);
873
+ return {
874
+ rate,
875
+ bank: requireText(bank, `Devizás nyugtánál (${currency}) add meg az árfolyamot jegyző bankot (exchangeBank).`)
876
+ };
877
+ }
878
+ function buildCreateReceiptXml(credentials, defaults, input) {
879
+ const prefix = resolvePrefix(input.prefix ?? defaults.prefix);
880
+ const paymentMethod = requireText(input.paymentMethod ?? defaults.paymentMethod, "Add meg a fizetési módot (paymentMethod) a hívásban vagy a receipts alapbeállításaiban.");
881
+ const currency = optionalText(input.currency ?? defaults.currency) ?? DEFAULT_CURRENCY;
882
+ const exchange = resolveExchange(currency, input.exchangeRate ?? defaults.exchangeRate, input.exchangeBank ?? defaults.exchangeBank);
883
+ const template = validateTemplate(input.template ?? defaults.template);
884
+ const items = calculateReceiptItems(input.items ?? [], currency);
885
+ const unit = optionalText(defaults.unit) ?? DEFAULT_UNIT;
886
+ const payments = paymentNodes(input.payments, items);
887
+ const downloadPdf = input.downloadPdf ?? defaults.downloadPdf ?? true;
888
+ return buildXmlDocument({
889
+ root: "xmlnyugtacreate",
890
+ namespace: CREATE_RECEIPT_NAMESPACE,
891
+ schemaLocation: `${RECEIPT_XSD_BASE_URL}nyugtacreate/xmlnyugtacreate.xsd`,
892
+ children: [
893
+ el("beallitasok", [...credentials, el("pdfLetoltes", downloadPdf)]),
894
+ el("fejlec", [
895
+ optionalEl("hivasAzonosito", optionalText(input.callId)),
896
+ el("elotag", prefix),
897
+ el("fizmod", paymentMethod),
898
+ el("penznem", currency),
899
+ optionalEl("devizaarf", exchange.rate),
900
+ optionalEl("devizabank", exchange.bank),
901
+ optionalEl("megjegyzes", optionalText(input.comment)),
902
+ optionalEl("pdfSablon", template),
903
+ optionalEl("fokonyvVevo", optionalText(input.customerLedgerId ?? defaults.customerLedgerId)),
904
+ optionalEl("rendelesSzam", optionalText(input.orderNumber))
905
+ ]),
906
+ el("tetelek", items.map((item) => itemNode(item, currency, unit))),
907
+ payments
908
+ ]
909
+ });
910
+ }
911
+ const DUPLICATE_CALL_ID_CODE = 338;
912
+ function enrichDuplicateError(error, input) {
913
+ if (!(error instanceof require_errors.SzamlazzError) || error.code !== DUPLICATE_CALL_ID_CODE) return error;
914
+ const lookup = input.orderNumber ? ` A meglévő nyugtát a getReceipt({ orderNumber: '${input.orderNumber}' }) hívással kérdezheted le, ha a fiókban tiltva van a rendelésszám ismétlődése.` : " A Számla Agent hívásazonosító alapján nem ad lekérdezési lehetőséget, ezért a meglévő nyugtát a Számlázz.hu felületén keresd meg, vagy adj meg rendelésszámot (orderNumber) is.";
915
+ return new require_errors.SzamlazzError(error.message, {
916
+ category: "duplicate",
917
+ code: error.code,
918
+ hint: `Ezzel a hívásazonosítóval (callId: ${input.callId ?? ""}) már készült nyugta, a nyugta nem jött létre újra.${lookup}`,
919
+ action: error.action,
920
+ httpStatus: error.httpStatus,
921
+ rawResponse: error.rawResponse,
922
+ cause: error
923
+ });
924
+ }
925
+ async function createReceipt(ctx, defaults, input, options = {}) {
926
+ const xml = buildCreateReceiptXml(ctx.credentials, defaults, input);
927
+ try {
928
+ return await ctx.execute({
929
+ action: "createReceipt",
930
+ xml,
931
+ signal: options.signal,
932
+ safeToRetry: optionalText(input.callId) !== void 0
933
+ }, parseReceiptResponse);
934
+ } catch (error) {
935
+ throw enrichDuplicateError(error, input);
936
+ }
937
+ }
938
+ //#endregion
939
+ Object.defineProperty(exports, "AGENT_ACTIONS", {
940
+ enumerable: true,
941
+ get: function() {
942
+ return AGENT_ACTIONS;
943
+ }
944
+ });
945
+ Object.defineProperty(exports, "INVOICE_TEMPLATES", {
946
+ enumerable: true,
947
+ get: function() {
948
+ return INVOICE_TEMPLATES;
949
+ }
950
+ });
951
+ Object.defineProperty(exports, "MAX_INVOICE_ATTACHMENTS", {
952
+ enumerable: true,
953
+ get: function() {
954
+ return MAX_INVOICE_ATTACHMENTS;
955
+ }
956
+ });
957
+ Object.defineProperty(exports, "RECEIPT_XSD_BASE_URL", {
958
+ enumerable: true,
959
+ get: function() {
960
+ return RECEIPT_XSD_BASE_URL;
961
+ }
962
+ });
963
+ Object.defineProperty(exports, "SZAMLAZZ_AGENT_URL", {
964
+ enumerable: true,
965
+ get: function() {
966
+ return SZAMLAZZ_AGENT_URL;
967
+ }
968
+ });
969
+ Object.defineProperty(exports, "TAXPAYER_TYPE_CODES", {
970
+ enumerable: true,
971
+ get: function() {
972
+ return TAXPAYER_TYPE_CODES;
973
+ }
974
+ });
975
+ Object.defineProperty(exports, "buildCreateReceiptXml", {
976
+ enumerable: true,
977
+ get: function() {
978
+ return buildCreateReceiptXml;
979
+ }
980
+ });
981
+ Object.defineProperty(exports, "buildXmlDocument", {
982
+ enumerable: true,
983
+ get: function() {
984
+ return buildXmlDocument;
985
+ }
986
+ });
987
+ Object.defineProperty(exports, "calculateReceiptItems", {
988
+ enumerable: true,
989
+ get: function() {
990
+ return calculateReceiptItems;
991
+ }
992
+ });
993
+ Object.defineProperty(exports, "childBoolean", {
994
+ enumerable: true,
995
+ get: function() {
996
+ return childBoolean;
997
+ }
998
+ });
999
+ Object.defineProperty(exports, "childNumber", {
1000
+ enumerable: true,
1001
+ get: function() {
1002
+ return childNumber;
1003
+ }
1004
+ });
1005
+ Object.defineProperty(exports, "childText", {
1006
+ enumerable: true,
1007
+ get: function() {
1008
+ return childText;
1009
+ }
1010
+ });
1011
+ Object.defineProperty(exports, "createAgentResponse", {
1012
+ enumerable: true,
1013
+ get: function() {
1014
+ return createAgentResponse;
1015
+ }
1016
+ });
1017
+ Object.defineProperty(exports, "createReceipt", {
1018
+ enumerable: true,
1019
+ get: function() {
1020
+ return createReceipt;
1021
+ }
1022
+ });
1023
+ Object.defineProperty(exports, "el", {
1024
+ enumerable: true,
1025
+ get: function() {
1026
+ return el;
1027
+ }
1028
+ });
1029
+ Object.defineProperty(exports, "findChild", {
1030
+ enumerable: true,
1031
+ get: function() {
1032
+ return findChild;
1033
+ }
1034
+ });
1035
+ Object.defineProperty(exports, "findChildren", {
1036
+ enumerable: true,
1037
+ get: function() {
1038
+ return findChildren;
1039
+ }
1040
+ });
1041
+ Object.defineProperty(exports, "looksLikeXml", {
1042
+ enumerable: true,
1043
+ get: function() {
1044
+ return looksLikeXml;
1045
+ }
1046
+ });
1047
+ Object.defineProperty(exports, "optionalAgentDate", {
1048
+ enumerable: true,
1049
+ get: function() {
1050
+ return optionalAgentDate;
1051
+ }
1052
+ });
1053
+ Object.defineProperty(exports, "optionalEl", {
1054
+ enumerable: true,
1055
+ get: function() {
1056
+ return optionalEl;
1057
+ }
1058
+ });
1059
+ Object.defineProperty(exports, "optionalText", {
1060
+ enumerable: true,
1061
+ get: function() {
1062
+ return optionalText;
1063
+ }
1064
+ });
1065
+ Object.defineProperty(exports, "parseDoneText", {
1066
+ enumerable: true,
1067
+ get: function() {
1068
+ return parseDoneText;
1069
+ }
1070
+ });
1071
+ Object.defineProperty(exports, "parseReceiptResponse", {
1072
+ enumerable: true,
1073
+ get: function() {
1074
+ return parseReceiptResponse;
1075
+ }
1076
+ });
1077
+ Object.defineProperty(exports, "parseResponseXml", {
1078
+ enumerable: true,
1079
+ get: function() {
1080
+ return parseResponseXml;
1081
+ }
1082
+ });
1083
+ Object.defineProperty(exports, "presentText", {
1084
+ enumerable: true,
1085
+ get: function() {
1086
+ return presentText;
1087
+ }
1088
+ });
1089
+ Object.defineProperty(exports, "readDocumentHeaders", {
1090
+ enumerable: true,
1091
+ get: function() {
1092
+ return readDocumentHeaders;
1093
+ }
1094
+ });
1095
+ Object.defineProperty(exports, "readHeader", {
1096
+ enumerable: true,
1097
+ get: function() {
1098
+ return readHeader;
1099
+ }
1100
+ });
1101
+ Object.defineProperty(exports, "receiptValidationError", {
1102
+ enumerable: true,
1103
+ get: function() {
1104
+ return receiptValidationError;
1105
+ }
1106
+ });
1107
+ Object.defineProperty(exports, "requireReceiptNumber", {
1108
+ enumerable: true,
1109
+ get: function() {
1110
+ return requireReceiptNumber;
1111
+ }
1112
+ });
1113
+ Object.defineProperty(exports, "resolveInvoice", {
1114
+ enumerable: true,
1115
+ get: function() {
1116
+ return resolveInvoice;
1117
+ }
1118
+ });
1119
+ Object.defineProperty(exports, "throwIfAnyError", {
1120
+ enumerable: true,
1121
+ get: function() {
1122
+ return throwIfAnyError;
1123
+ }
1124
+ });
1125
+ Object.defineProperty(exports, "throwIfHeaderError", {
1126
+ enumerable: true,
1127
+ get: function() {
1128
+ return throwIfHeaderError;
1129
+ }
1130
+ });
1131
+ Object.defineProperty(exports, "throwIfHttpError", {
1132
+ enumerable: true,
1133
+ get: function() {
1134
+ return throwIfHttpError;
1135
+ }
1136
+ });
1137
+ Object.defineProperty(exports, "throwIfTextError", {
1138
+ enumerable: true,
1139
+ get: function() {
1140
+ return throwIfTextError;
1141
+ }
1142
+ });
1143
+ Object.defineProperty(exports, "throwIfXmlFailure", {
1144
+ enumerable: true,
1145
+ get: function() {
1146
+ return throwIfXmlFailure;
1147
+ }
1148
+ });
1149
+ Object.defineProperty(exports, "unexpectedResponse", {
1150
+ enumerable: true,
1151
+ get: function() {
1152
+ return unexpectedResponse;
1153
+ }
1154
+ });
1155
+ Object.defineProperty(exports, "validateTemplate", {
1156
+ enumerable: true,
1157
+ get: function() {
1158
+ return validateTemplate;
1159
+ }
1160
+ });