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.
- package/LICENSE +21 -0
- package/README.md +150 -0
- package/agents/README.md +59 -0
- package/agents/api.md +206 -0
- package/agents/pitfalls.md +52 -0
- package/agents/recipes.md +217 -0
- package/agents/skills/kassza/SKILL.md +29 -0
- package/assets/logo-wordmark.svg +25 -0
- package/assets/logo.svg +19 -0
- package/dist/binary-B89HM03_.cjs +63 -0
- package/dist/binary-D0M9U2MD.js +34 -0
- package/dist/client-B9kbKKBf.d.cts +748 -0
- package/dist/client-zv4enyq7.d.ts +748 -0
- package/dist/cookie-stores/index.cjs +153 -0
- package/dist/cookie-stores/index.d.cts +63 -0
- package/dist/cookie-stores/index.d.ts +63 -0
- package/dist/cookie-stores/index.js +144 -0
- package/dist/create-BZd6CUO7.cjs +1160 -0
- package/dist/create-DDZaNlOz.js +939 -0
- package/dist/dates-D2XebOIg.js +34 -0
- package/dist/dates-DtHzwNU6.d.cts +7 -0
- package/dist/dates-DtHzwNU6.d.ts +7 -0
- package/dist/dates-PPxH0n5H.cjs +57 -0
- package/dist/errors-B0QJhUW1.cjs +302 -0
- package/dist/errors-DapdV5DK.js +273 -0
- package/dist/index-CYAGCdKJ.d.cts +56 -0
- package/dist/index-CYAGCdKJ.d.ts +56 -0
- package/dist/index.cjs +1406 -0
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +1394 -0
- package/dist/ipn/index.cjs +108 -0
- package/dist/ipn/index.d.cts +32 -0
- package/dist/ipn/index.d.ts +32 -0
- package/dist/ipn/index.js +101 -0
- package/dist/money/index.cjs +15 -0
- package/dist/money/index.d.cts +2 -0
- package/dist/money/index.d.ts +2 -0
- package/dist/money/index.js +2 -0
- package/dist/money-C9j7nBNP.js +258 -0
- package/dist/money-DkiGukAw.cjs +335 -0
- package/dist/session-CRGOuz-R.cjs +100 -0
- package/dist/session-Dm_45x8K.d.cts +11 -0
- package/dist/session-Dm_45x8K.d.ts +11 -0
- package/dist/session-OJMLGufT.js +77 -0
- package/dist/shared-CrxlxI8n.cjs +207 -0
- package/dist/shared-D6DLa4b7.js +100 -0
- package/dist/storage/fs.cjs +88 -0
- package/dist/storage/fs.d.cts +13 -0
- package/dist/storage/fs.d.ts +13 -0
- package/dist/storage/fs.js +87 -0
- package/dist/storage/index.cjs +643 -0
- package/dist/storage/index.d.cts +288 -0
- package/dist/storage/index.d.ts +288 -0
- package/dist/storage/index.js +619 -0
- package/dist/testing/index.cjs +409 -0
- package/dist/testing/index.d.cts +35 -0
- package/dist/testing/index.d.ts +35 -0
- package/dist/testing/index.js +407 -0
- package/dist/types-DVRgwcqg.d.cts +26 -0
- package/dist/types-DVRgwcqg.d.ts +26 -0
- package/dist/validators/index.cjs +296 -0
- package/dist/validators/index.d.cts +51 -0
- package/dist/validators/index.d.ts +51 -0
- package/dist/validators/index.js +278 -0
- package/llms.txt +16 -0
- package/package.json +151 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_errors = require("../errors-B0QJhUW1.cjs");
|
|
3
|
+
//#region src/ipn/ip.ts
|
|
4
|
+
const SZAMLAZZ_OUTBOUND_IPS = [
|
|
5
|
+
"3.73.214.98",
|
|
6
|
+
"3.76.149.232",
|
|
7
|
+
"18.153.156.51"
|
|
8
|
+
];
|
|
9
|
+
const OUTBOUND_IP_SET = new Set(SZAMLAZZ_OUTBOUND_IPS);
|
|
10
|
+
function normalizeIp(value) {
|
|
11
|
+
const comma = value.indexOf(",");
|
|
12
|
+
let ip = (comma === -1 ? value : value.slice(0, comma)).trim();
|
|
13
|
+
const bracketed = /^\[([^\]]+)\](?::\d+)?$/.exec(ip);
|
|
14
|
+
if (bracketed?.[1]) ip = bracketed[1];
|
|
15
|
+
const ipv4WithPort = /^(\d{1,3}(?:\.\d{1,3}){3}):\d+$/.exec(ip);
|
|
16
|
+
if (ipv4WithPort?.[1]) ip = ipv4WithPort[1];
|
|
17
|
+
return ip.replace(/^::ffff:/i, "");
|
|
18
|
+
}
|
|
19
|
+
function isSzamlazzIp(ip) {
|
|
20
|
+
if (typeof ip !== "string") return false;
|
|
21
|
+
return OUTBOUND_IP_SET.has(normalizeIp(ip));
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/ipn/notification.ts
|
|
25
|
+
const IPN_FIELDS = {
|
|
26
|
+
invoiceNumber: "szlahu_szamlaszam",
|
|
27
|
+
proformaNumber: "szlahu_dijbekero_szama",
|
|
28
|
+
orderNumber: "szlahu_rendelesszam",
|
|
29
|
+
grossTotal: "szlahu_bruttovegosszeg",
|
|
30
|
+
paidAmount: "szlahu_kifizetettbrutto",
|
|
31
|
+
paymentMethod: "szlahu_fizetesmod",
|
|
32
|
+
paymentDate: "szlahu_kifizdat"
|
|
33
|
+
};
|
|
34
|
+
const AMOUNT_TOLERANCE = .005;
|
|
35
|
+
function ipnError(message) {
|
|
36
|
+
return new require_errors.SzamlazzError(message, { category: "validation" });
|
|
37
|
+
}
|
|
38
|
+
function toRecord(input) {
|
|
39
|
+
if (typeof input === "string") return Object.fromEntries(new URLSearchParams(input.trim().replace(/^\?/, "")));
|
|
40
|
+
if (input instanceof URLSearchParams) return Object.fromEntries(input);
|
|
41
|
+
if (typeof FormData !== "undefined" && input instanceof FormData) return Object.fromEntries([...input.entries()].filter((entry) => typeof entry[1] === "string"));
|
|
42
|
+
if (input !== null && typeof input === "object") return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0 && value !== null).map(([key, value]) => [key, String(value)]));
|
|
43
|
+
throw ipnError("Az IPN értesítés nem értelmezhető: szöveget, URLSearchParams-t, FormData-t vagy objektumot várunk.");
|
|
44
|
+
}
|
|
45
|
+
function optionalField(raw, name) {
|
|
46
|
+
const value = raw[name]?.trim();
|
|
47
|
+
return value === void 0 || value === "" ? void 0 : value;
|
|
48
|
+
}
|
|
49
|
+
function requiredField(raw, name) {
|
|
50
|
+
const value = optionalField(raw, name);
|
|
51
|
+
if (value === void 0) throw ipnError(`Hiányzik a kötelező IPN mező: ${name}`);
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
function parseIpnAmount(value) {
|
|
55
|
+
let text = value.replace(/\s+/g, "");
|
|
56
|
+
const lastComma = text.lastIndexOf(",");
|
|
57
|
+
const lastDot = text.lastIndexOf(".");
|
|
58
|
+
if (lastComma !== -1 && lastDot !== -1) {
|
|
59
|
+
const decimal = lastComma > lastDot ? "," : ".";
|
|
60
|
+
const thousands = decimal === "," ? "." : ",";
|
|
61
|
+
text = text.split(thousands).join("").replace(decimal, ".");
|
|
62
|
+
} else if (lastComma !== -1) text = text.replace(",", ".");
|
|
63
|
+
if (!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$/.test(text)) return void 0;
|
|
64
|
+
return Number(text);
|
|
65
|
+
}
|
|
66
|
+
function requiredAmount(raw, name) {
|
|
67
|
+
const value = requiredField(raw, name);
|
|
68
|
+
const amount = parseIpnAmount(value);
|
|
69
|
+
if (amount === void 0) throw ipnError(`Az IPN mező nem értelmezhető összeg: ${name}="${value}"`);
|
|
70
|
+
return amount;
|
|
71
|
+
}
|
|
72
|
+
function parseIpnNotification(input) {
|
|
73
|
+
const raw = toRecord(input);
|
|
74
|
+
const invoiceNumber = requiredField(raw, IPN_FIELDS.invoiceNumber);
|
|
75
|
+
const grossTotal = requiredAmount(raw, IPN_FIELDS.grossTotal);
|
|
76
|
+
const paidAmount = requiredAmount(raw, IPN_FIELDS.paidAmount);
|
|
77
|
+
return {
|
|
78
|
+
invoiceNumber,
|
|
79
|
+
proformaNumber: optionalField(raw, IPN_FIELDS.proformaNumber),
|
|
80
|
+
orderNumber: optionalField(raw, IPN_FIELDS.orderNumber),
|
|
81
|
+
grossTotal,
|
|
82
|
+
paidAmount,
|
|
83
|
+
paymentMethod: optionalField(raw, IPN_FIELDS.paymentMethod),
|
|
84
|
+
paymentDate: optionalField(raw, IPN_FIELDS.paymentDate),
|
|
85
|
+
isFullyPaid: Math.abs(paidAmount) + AMOUNT_TOLERANCE >= Math.abs(grossTotal),
|
|
86
|
+
raw
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
async function readIpnNotification(request) {
|
|
90
|
+
if ((request.headers.get("content-type")?.toLowerCase() ?? "").includes("multipart/form-data")) return parseIpnNotification(await request.formData());
|
|
91
|
+
const body = await request.text();
|
|
92
|
+
if (body.trim() === "") return parseIpnNotification(new URL(request.url).searchParams);
|
|
93
|
+
return parseIpnNotification(body);
|
|
94
|
+
}
|
|
95
|
+
function ipnOkResponse() {
|
|
96
|
+
return new Response("OK", {
|
|
97
|
+
status: 200,
|
|
98
|
+
headers: { "content-type": "text/plain; charset=utf-8" }
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
//#endregion
|
|
102
|
+
exports.IPN_FIELDS = IPN_FIELDS;
|
|
103
|
+
exports.SZAMLAZZ_OUTBOUND_IPS = SZAMLAZZ_OUTBOUND_IPS;
|
|
104
|
+
exports.ipnOkResponse = ipnOkResponse;
|
|
105
|
+
exports.isSzamlazzIp = isSzamlazzIp;
|
|
106
|
+
exports.parseIpnAmount = parseIpnAmount;
|
|
107
|
+
exports.parseIpnNotification = parseIpnNotification;
|
|
108
|
+
exports.readIpnNotification = readIpnNotification;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/ipn/ip.d.ts
|
|
2
|
+
export declare const SZAMLAZZ_OUTBOUND_IPS: readonly string[];
|
|
3
|
+
export declare function isSzamlazzIp(ip: string): boolean;
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region src/ipn/notification.d.ts
|
|
6
|
+
type IpnInput = string | URLSearchParams | FormData | Readonly<Record<string, string>>;
|
|
7
|
+
interface IpnNotification {
|
|
8
|
+
readonly invoiceNumber: string;
|
|
9
|
+
readonly proformaNumber?: string | undefined;
|
|
10
|
+
readonly orderNumber?: string | undefined;
|
|
11
|
+
readonly grossTotal: number;
|
|
12
|
+
readonly paidAmount: number;
|
|
13
|
+
readonly paymentMethod?: string | undefined;
|
|
14
|
+
readonly paymentDate?: string | undefined;
|
|
15
|
+
readonly isFullyPaid: boolean;
|
|
16
|
+
readonly raw: Readonly<Record<string, string>>;
|
|
17
|
+
}
|
|
18
|
+
export declare const IPN_FIELDS: {
|
|
19
|
+
readonly invoiceNumber: "szlahu_szamlaszam";
|
|
20
|
+
readonly proformaNumber: "szlahu_dijbekero_szama";
|
|
21
|
+
readonly orderNumber: "szlahu_rendelesszam";
|
|
22
|
+
readonly grossTotal: "szlahu_bruttovegosszeg";
|
|
23
|
+
readonly paidAmount: "szlahu_kifizetettbrutto";
|
|
24
|
+
readonly paymentMethod: "szlahu_fizetesmod";
|
|
25
|
+
readonly paymentDate: "szlahu_kifizdat";
|
|
26
|
+
};
|
|
27
|
+
export declare function parseIpnAmount(value: string): number | undefined;
|
|
28
|
+
export declare function parseIpnNotification(input: IpnInput): IpnNotification;
|
|
29
|
+
export declare function readIpnNotification(request: Request): Promise<IpnNotification>;
|
|
30
|
+
export declare function ipnOkResponse(): Response;
|
|
31
|
+
//#endregion
|
|
32
|
+
export type { IpnInput, IpnNotification };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/ipn/ip.d.ts
|
|
2
|
+
export declare const SZAMLAZZ_OUTBOUND_IPS: readonly string[];
|
|
3
|
+
export declare function isSzamlazzIp(ip: string): boolean;
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region src/ipn/notification.d.ts
|
|
6
|
+
type IpnInput = string | URLSearchParams | FormData | Readonly<Record<string, string>>;
|
|
7
|
+
interface IpnNotification {
|
|
8
|
+
readonly invoiceNumber: string;
|
|
9
|
+
readonly proformaNumber?: string | undefined;
|
|
10
|
+
readonly orderNumber?: string | undefined;
|
|
11
|
+
readonly grossTotal: number;
|
|
12
|
+
readonly paidAmount: number;
|
|
13
|
+
readonly paymentMethod?: string | undefined;
|
|
14
|
+
readonly paymentDate?: string | undefined;
|
|
15
|
+
readonly isFullyPaid: boolean;
|
|
16
|
+
readonly raw: Readonly<Record<string, string>>;
|
|
17
|
+
}
|
|
18
|
+
export declare const IPN_FIELDS: {
|
|
19
|
+
readonly invoiceNumber: "szlahu_szamlaszam";
|
|
20
|
+
readonly proformaNumber: "szlahu_dijbekero_szama";
|
|
21
|
+
readonly orderNumber: "szlahu_rendelesszam";
|
|
22
|
+
readonly grossTotal: "szlahu_bruttovegosszeg";
|
|
23
|
+
readonly paidAmount: "szlahu_kifizetettbrutto";
|
|
24
|
+
readonly paymentMethod: "szlahu_fizetesmod";
|
|
25
|
+
readonly paymentDate: "szlahu_kifizdat";
|
|
26
|
+
};
|
|
27
|
+
export declare function parseIpnAmount(value: string): number | undefined;
|
|
28
|
+
export declare function parseIpnNotification(input: IpnInput): IpnNotification;
|
|
29
|
+
export declare function readIpnNotification(request: Request): Promise<IpnNotification>;
|
|
30
|
+
export declare function ipnOkResponse(): Response;
|
|
31
|
+
//#endregion
|
|
32
|
+
export type { IpnInput, IpnNotification };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { n as SzamlazzError } from "../errors-DapdV5DK.js";
|
|
2
|
+
//#region src/ipn/ip.ts
|
|
3
|
+
const SZAMLAZZ_OUTBOUND_IPS = [
|
|
4
|
+
"3.73.214.98",
|
|
5
|
+
"3.76.149.232",
|
|
6
|
+
"18.153.156.51"
|
|
7
|
+
];
|
|
8
|
+
const OUTBOUND_IP_SET = new Set(SZAMLAZZ_OUTBOUND_IPS);
|
|
9
|
+
function normalizeIp(value) {
|
|
10
|
+
const comma = value.indexOf(",");
|
|
11
|
+
let ip = (comma === -1 ? value : value.slice(0, comma)).trim();
|
|
12
|
+
const bracketed = /^\[([^\]]+)\](?::\d+)?$/.exec(ip);
|
|
13
|
+
if (bracketed?.[1]) ip = bracketed[1];
|
|
14
|
+
const ipv4WithPort = /^(\d{1,3}(?:\.\d{1,3}){3}):\d+$/.exec(ip);
|
|
15
|
+
if (ipv4WithPort?.[1]) ip = ipv4WithPort[1];
|
|
16
|
+
return ip.replace(/^::ffff:/i, "");
|
|
17
|
+
}
|
|
18
|
+
function isSzamlazzIp(ip) {
|
|
19
|
+
if (typeof ip !== "string") return false;
|
|
20
|
+
return OUTBOUND_IP_SET.has(normalizeIp(ip));
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/ipn/notification.ts
|
|
24
|
+
const IPN_FIELDS = {
|
|
25
|
+
invoiceNumber: "szlahu_szamlaszam",
|
|
26
|
+
proformaNumber: "szlahu_dijbekero_szama",
|
|
27
|
+
orderNumber: "szlahu_rendelesszam",
|
|
28
|
+
grossTotal: "szlahu_bruttovegosszeg",
|
|
29
|
+
paidAmount: "szlahu_kifizetettbrutto",
|
|
30
|
+
paymentMethod: "szlahu_fizetesmod",
|
|
31
|
+
paymentDate: "szlahu_kifizdat"
|
|
32
|
+
};
|
|
33
|
+
const AMOUNT_TOLERANCE = .005;
|
|
34
|
+
function ipnError(message) {
|
|
35
|
+
return new SzamlazzError(message, { category: "validation" });
|
|
36
|
+
}
|
|
37
|
+
function toRecord(input) {
|
|
38
|
+
if (typeof input === "string") return Object.fromEntries(new URLSearchParams(input.trim().replace(/^\?/, "")));
|
|
39
|
+
if (input instanceof URLSearchParams) return Object.fromEntries(input);
|
|
40
|
+
if (typeof FormData !== "undefined" && input instanceof FormData) return Object.fromEntries([...input.entries()].filter((entry) => typeof entry[1] === "string"));
|
|
41
|
+
if (input !== null && typeof input === "object") return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0 && value !== null).map(([key, value]) => [key, String(value)]));
|
|
42
|
+
throw ipnError("Az IPN értesítés nem értelmezhető: szöveget, URLSearchParams-t, FormData-t vagy objektumot várunk.");
|
|
43
|
+
}
|
|
44
|
+
function optionalField(raw, name) {
|
|
45
|
+
const value = raw[name]?.trim();
|
|
46
|
+
return value === void 0 || value === "" ? void 0 : value;
|
|
47
|
+
}
|
|
48
|
+
function requiredField(raw, name) {
|
|
49
|
+
const value = optionalField(raw, name);
|
|
50
|
+
if (value === void 0) throw ipnError(`Hiányzik a kötelező IPN mező: ${name}`);
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
function parseIpnAmount(value) {
|
|
54
|
+
let text = value.replace(/\s+/g, "");
|
|
55
|
+
const lastComma = text.lastIndexOf(",");
|
|
56
|
+
const lastDot = text.lastIndexOf(".");
|
|
57
|
+
if (lastComma !== -1 && lastDot !== -1) {
|
|
58
|
+
const decimal = lastComma > lastDot ? "," : ".";
|
|
59
|
+
const thousands = decimal === "," ? "." : ",";
|
|
60
|
+
text = text.split(thousands).join("").replace(decimal, ".");
|
|
61
|
+
} else if (lastComma !== -1) text = text.replace(",", ".");
|
|
62
|
+
if (!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$/.test(text)) return void 0;
|
|
63
|
+
return Number(text);
|
|
64
|
+
}
|
|
65
|
+
function requiredAmount(raw, name) {
|
|
66
|
+
const value = requiredField(raw, name);
|
|
67
|
+
const amount = parseIpnAmount(value);
|
|
68
|
+
if (amount === void 0) throw ipnError(`Az IPN mező nem értelmezhető összeg: ${name}="${value}"`);
|
|
69
|
+
return amount;
|
|
70
|
+
}
|
|
71
|
+
function parseIpnNotification(input) {
|
|
72
|
+
const raw = toRecord(input);
|
|
73
|
+
const invoiceNumber = requiredField(raw, IPN_FIELDS.invoiceNumber);
|
|
74
|
+
const grossTotal = requiredAmount(raw, IPN_FIELDS.grossTotal);
|
|
75
|
+
const paidAmount = requiredAmount(raw, IPN_FIELDS.paidAmount);
|
|
76
|
+
return {
|
|
77
|
+
invoiceNumber,
|
|
78
|
+
proformaNumber: optionalField(raw, IPN_FIELDS.proformaNumber),
|
|
79
|
+
orderNumber: optionalField(raw, IPN_FIELDS.orderNumber),
|
|
80
|
+
grossTotal,
|
|
81
|
+
paidAmount,
|
|
82
|
+
paymentMethod: optionalField(raw, IPN_FIELDS.paymentMethod),
|
|
83
|
+
paymentDate: optionalField(raw, IPN_FIELDS.paymentDate),
|
|
84
|
+
isFullyPaid: Math.abs(paidAmount) + AMOUNT_TOLERANCE >= Math.abs(grossTotal),
|
|
85
|
+
raw
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
async function readIpnNotification(request) {
|
|
89
|
+
if ((request.headers.get("content-type")?.toLowerCase() ?? "").includes("multipart/form-data")) return parseIpnNotification(await request.formData());
|
|
90
|
+
const body = await request.text();
|
|
91
|
+
if (body.trim() === "") return parseIpnNotification(new URL(request.url).searchParams);
|
|
92
|
+
return parseIpnNotification(body);
|
|
93
|
+
}
|
|
94
|
+
function ipnOkResponse() {
|
|
95
|
+
return new Response("OK", {
|
|
96
|
+
status: 200,
|
|
97
|
+
headers: { "content-type": "text/plain; charset=utf-8" }
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
101
|
+
export { IPN_FIELDS, SZAMLAZZ_OUTBOUND_IPS, ipnOkResponse, isSzamlazzIp, parseIpnAmount, parseIpnNotification, readIpnNotification };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_money = require("../money-DkiGukAw.cjs");
|
|
3
|
+
exports.NUMERIC_VAT_RATES = require_money.NUMERIC_VAT_RATES;
|
|
4
|
+
exports.SPECIAL_VAT_CODES = require_money.SPECIAL_VAT_CODES;
|
|
5
|
+
exports.addMoney = require_money.addMoney;
|
|
6
|
+
exports.calculateInvoiceItem = require_money.calculateInvoiceItem;
|
|
7
|
+
exports.calculateItemAmounts = require_money.calculateItemAmounts;
|
|
8
|
+
exports.calculateReceiptItem = require_money.calculateReceiptItem;
|
|
9
|
+
exports.decimalPlaces = require_money.decimalPlaces;
|
|
10
|
+
exports.formatVatRate = require_money.formatVatRate;
|
|
11
|
+
exports.isHuf = require_money.isHuf;
|
|
12
|
+
exports.isVatRate = require_money.isVatRate;
|
|
13
|
+
exports.roundMoney = require_money.roundMoney;
|
|
14
|
+
exports.summarizeItems = require_money.summarizeItems;
|
|
15
|
+
exports.vatPercentage = require_money.vatPercentage;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { _ as VatRate, a as DocumentTotals, b as isVatRate, c as VatBreakdown, d as calculateReceiptItem, f as summarizeItems, g as SpecialVatCode, h as SPECIAL_VAT_CODES, i as DocumentKind, l as calculateInvoiceItem, m as NumericVatRate, n as decimalPlaces, o as ItemAmounts, p as NUMERIC_VAT_RATES, r as roundMoney, s as ItemPriceInput, t as addMoney, u as calculateItemAmounts, v as formatVatRate, x as vatPercentage, y as isHuf } from "../index-CYAGCdKJ.cjs";
|
|
2
|
+
export { type DocumentKind, type DocumentTotals, type ItemAmounts, type ItemPriceInput, NUMERIC_VAT_RATES, type NumericVatRate, SPECIAL_VAT_CODES, type SpecialVatCode, type VatBreakdown, type VatRate, addMoney, calculateInvoiceItem, calculateItemAmounts, calculateReceiptItem, decimalPlaces, formatVatRate, isHuf, isVatRate, roundMoney, summarizeItems, vatPercentage };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { _ as VatRate, a as DocumentTotals, b as isVatRate, c as VatBreakdown, d as calculateReceiptItem, f as summarizeItems, g as SpecialVatCode, h as SPECIAL_VAT_CODES, i as DocumentKind, l as calculateInvoiceItem, m as NumericVatRate, n as decimalPlaces, o as ItemAmounts, p as NUMERIC_VAT_RATES, r as roundMoney, s as ItemPriceInput, t as addMoney, u as calculateItemAmounts, v as formatVatRate, x as vatPercentage, y as isHuf } from "../index-CYAGCdKJ.js";
|
|
2
|
+
export { type DocumentKind, type DocumentTotals, type ItemAmounts, type ItemPriceInput, NUMERIC_VAT_RATES, type NumericVatRate, SPECIAL_VAT_CODES, type SpecialVatCode, type VatBreakdown, type VatRate, addMoney, calculateInvoiceItem, calculateItemAmounts, calculateReceiptItem, decimalPlaces, formatVatRate, isHuf, isVatRate, roundMoney, summarizeItems, vatPercentage };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as NUMERIC_VAT_RATES, c as isHuf, d as addMoney, f as decimalPlaces, i as summarizeItems, l as isVatRate, n as calculateItemAmounts, o as SPECIAL_VAT_CODES, p as roundMoney, r as calculateReceiptItem, s as formatVatRate, t as calculateInvoiceItem, u as vatPercentage } from "../money-C9j7nBNP.js";
|
|
2
|
+
export { NUMERIC_VAT_RATES, SPECIAL_VAT_CODES, addMoney, calculateInvoiceItem, calculateItemAmounts, calculateReceiptItem, decimalPlaces, formatVatRate, isHuf, isVatRate, roundMoney, summarizeItems, vatPercentage };
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { n as SzamlazzError } from "./errors-DapdV5DK.js";
|
|
2
|
+
//#region src/money/rounding.ts
|
|
3
|
+
function roundMoney(value, decimals = 0) {
|
|
4
|
+
if (!Number.isFinite(value)) throw new RangeError(`Nem véges összeg: ${value}`);
|
|
5
|
+
const factor = 10 ** decimals;
|
|
6
|
+
const scaled = Number((Math.abs(value) * factor).toPrecision(15));
|
|
7
|
+
const rounded = Math.sign(value) * Math.round(scaled) / factor;
|
|
8
|
+
return rounded === 0 ? 0 : rounded;
|
|
9
|
+
}
|
|
10
|
+
function decimalPlaces(value) {
|
|
11
|
+
if (!Number.isFinite(value) || Number.isInteger(value)) return 0;
|
|
12
|
+
const normalized = Number(value.toPrecision(15)).toString();
|
|
13
|
+
const exponentMatch = /e-(\d+)$/.exec(normalized);
|
|
14
|
+
if (exponentMatch?.[1]) return Number(exponentMatch[1]);
|
|
15
|
+
return normalized.split(".")[1]?.length ?? 0;
|
|
16
|
+
}
|
|
17
|
+
function addMoney(...values) {
|
|
18
|
+
return roundMoney(values.reduce((sum, value) => sum + value, 0), Math.max(0, ...values.map(decimalPlaces)));
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/money/vat.ts
|
|
22
|
+
const NUMERIC_VAT_RATES = [
|
|
23
|
+
0,
|
|
24
|
+
1,
|
|
25
|
+
2,
|
|
26
|
+
2.1,
|
|
27
|
+
3,
|
|
28
|
+
4,
|
|
29
|
+
4.8,
|
|
30
|
+
5,
|
|
31
|
+
5.5,
|
|
32
|
+
6,
|
|
33
|
+
7,
|
|
34
|
+
7.7,
|
|
35
|
+
8,
|
|
36
|
+
8.1,
|
|
37
|
+
9,
|
|
38
|
+
9.5,
|
|
39
|
+
10,
|
|
40
|
+
11,
|
|
41
|
+
12,
|
|
42
|
+
13,
|
|
43
|
+
13.5,
|
|
44
|
+
14,
|
|
45
|
+
15,
|
|
46
|
+
16,
|
|
47
|
+
17,
|
|
48
|
+
18,
|
|
49
|
+
19,
|
|
50
|
+
20,
|
|
51
|
+
21,
|
|
52
|
+
22,
|
|
53
|
+
23,
|
|
54
|
+
24,
|
|
55
|
+
25,
|
|
56
|
+
25.5,
|
|
57
|
+
26,
|
|
58
|
+
27
|
|
59
|
+
];
|
|
60
|
+
const SPECIAL_VAT_CODES = [
|
|
61
|
+
"TAHK",
|
|
62
|
+
"TAM",
|
|
63
|
+
"AAM",
|
|
64
|
+
"EUT",
|
|
65
|
+
"EUKT",
|
|
66
|
+
"F.AFA",
|
|
67
|
+
"K.AFA",
|
|
68
|
+
"HO",
|
|
69
|
+
"EUE",
|
|
70
|
+
"EUFADE",
|
|
71
|
+
"EUFAD37",
|
|
72
|
+
"ATK",
|
|
73
|
+
"NAM",
|
|
74
|
+
"EAM",
|
|
75
|
+
"KBAUK",
|
|
76
|
+
"KBAET"
|
|
77
|
+
];
|
|
78
|
+
const numericRates = new Set(NUMERIC_VAT_RATES);
|
|
79
|
+
const specialCodes = new Set(SPECIAL_VAT_CODES);
|
|
80
|
+
function isVatRate(value) {
|
|
81
|
+
if (typeof value === "number") return numericRates.has(value);
|
|
82
|
+
return typeof value === "string" && specialCodes.has(value);
|
|
83
|
+
}
|
|
84
|
+
function vatPercentage(rate) {
|
|
85
|
+
return typeof rate === "number" ? rate : 0;
|
|
86
|
+
}
|
|
87
|
+
function formatVatRate(rate) {
|
|
88
|
+
return String(rate);
|
|
89
|
+
}
|
|
90
|
+
const HUF_CURRENCIES = /* @__PURE__ */ new Set([
|
|
91
|
+
"HUF",
|
|
92
|
+
"Ft",
|
|
93
|
+
"FT",
|
|
94
|
+
"huf",
|
|
95
|
+
"ft"
|
|
96
|
+
]);
|
|
97
|
+
function isHuf(currency) {
|
|
98
|
+
return currency === void 0 || HUF_CURRENCIES.has(currency.trim());
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region src/money/items.ts
|
|
102
|
+
const FOREIGN_CURRENCY_DECIMALS = 2;
|
|
103
|
+
const RECEIPT_HUF_DECIMALS = 2;
|
|
104
|
+
const MAX_UNIT_PRICE_DECIMALS = 6;
|
|
105
|
+
function validationError(message) {
|
|
106
|
+
return new SzamlazzError(message, { category: "validation" });
|
|
107
|
+
}
|
|
108
|
+
function assertFiniteNumber(value, field) {
|
|
109
|
+
if (value !== void 0 && !Number.isFinite(value)) throw validationError(`A(z) ${field} mező értéke nem érvényes szám: ${value}`);
|
|
110
|
+
}
|
|
111
|
+
function unitPriceFor(amount, quantity, decimals) {
|
|
112
|
+
const exact = amount / quantity;
|
|
113
|
+
for (let precision = 2; precision <= MAX_UNIT_PRICE_DECIMALS; precision++) {
|
|
114
|
+
const candidate = roundMoney(exact, precision);
|
|
115
|
+
if (roundMoney(candidate * quantity, decimals) === amount) return candidate;
|
|
116
|
+
}
|
|
117
|
+
return roundMoney(exact, MAX_UNIT_PRICE_DECIMALS);
|
|
118
|
+
}
|
|
119
|
+
function roundingRuleFor(kind, currency) {
|
|
120
|
+
if (!isHuf(currency)) return {
|
|
121
|
+
netDecimals: FOREIGN_CURRENCY_DECIMALS,
|
|
122
|
+
vatDecimals: FOREIGN_CURRENCY_DECIMALS,
|
|
123
|
+
grossDecimals: FOREIGN_CURRENCY_DECIMALS
|
|
124
|
+
};
|
|
125
|
+
if (kind === "receipt") return {
|
|
126
|
+
netDecimals: RECEIPT_HUF_DECIMALS,
|
|
127
|
+
vatDecimals: RECEIPT_HUF_DECIMALS,
|
|
128
|
+
grossDecimals: 0
|
|
129
|
+
};
|
|
130
|
+
return {
|
|
131
|
+
netDecimals: 0,
|
|
132
|
+
vatDecimals: 0,
|
|
133
|
+
grossDecimals: 0
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function fromNet(input, quantity, rule) {
|
|
137
|
+
const percentage = vatPercentage(input.vat);
|
|
138
|
+
const netAmount = roundMoney(input.netUnitPrice * quantity, rule.netDecimals);
|
|
139
|
+
if (rule.grossDecimals < rule.netDecimals) {
|
|
140
|
+
const grossAmount = roundMoney(netAmount * (1 + percentage / 100), rule.grossDecimals);
|
|
141
|
+
const vatAmount = roundMoney(grossAmount - netAmount, rule.vatDecimals);
|
|
142
|
+
return {
|
|
143
|
+
quantity,
|
|
144
|
+
vat: input.vat,
|
|
145
|
+
netUnitPrice: input.netUnitPrice,
|
|
146
|
+
netAmount,
|
|
147
|
+
vatAmount,
|
|
148
|
+
grossAmount
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
const vatAmount = roundMoney(netAmount * percentage / 100, rule.vatDecimals);
|
|
152
|
+
const grossAmount = roundMoney(netAmount + vatAmount, rule.grossDecimals);
|
|
153
|
+
return {
|
|
154
|
+
quantity,
|
|
155
|
+
vat: input.vat,
|
|
156
|
+
netUnitPrice: input.netUnitPrice,
|
|
157
|
+
netAmount,
|
|
158
|
+
vatAmount,
|
|
159
|
+
grossAmount
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function fromGross(input, quantity, rule) {
|
|
163
|
+
const percentage = vatPercentage(input.vat);
|
|
164
|
+
const grossAmount = roundMoney(input.grossUnitPrice * quantity, rule.grossDecimals);
|
|
165
|
+
const vatAmount = roundMoney(grossAmount * percentage / (100 + percentage), rule.vatDecimals);
|
|
166
|
+
const netAmount = roundMoney(grossAmount - vatAmount, rule.netDecimals);
|
|
167
|
+
return {
|
|
168
|
+
quantity,
|
|
169
|
+
vat: input.vat,
|
|
170
|
+
netUnitPrice: unitPriceFor(netAmount, quantity, rule.netDecimals),
|
|
171
|
+
netAmount,
|
|
172
|
+
vatAmount,
|
|
173
|
+
grossAmount
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function fromExplicit(input, quantity) {
|
|
177
|
+
const { netAmount, vatAmount, grossAmount } = input;
|
|
178
|
+
if (netAmount === void 0 || vatAmount === void 0 || grossAmount === void 0) throw validationError("Explicit összegeknél a netAmount, vatAmount és grossAmount mezőt is meg kell adni.");
|
|
179
|
+
return {
|
|
180
|
+
quantity,
|
|
181
|
+
vat: input.vat,
|
|
182
|
+
netUnitPrice: input.netUnitPrice ?? unitPriceFor(netAmount, quantity, FOREIGN_CURRENCY_DECIMALS),
|
|
183
|
+
netAmount,
|
|
184
|
+
vatAmount,
|
|
185
|
+
grossAmount
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function calculateItemAmounts(input, options) {
|
|
189
|
+
const quantity = input.quantity ?? 1;
|
|
190
|
+
assertFiniteNumber(quantity, "quantity");
|
|
191
|
+
assertFiniteNumber(input.netUnitPrice, "netUnitPrice");
|
|
192
|
+
assertFiniteNumber(input.grossUnitPrice, "grossUnitPrice");
|
|
193
|
+
assertFiniteNumber(input.netAmount, "netAmount");
|
|
194
|
+
assertFiniteNumber(input.vatAmount, "vatAmount");
|
|
195
|
+
assertFiniteNumber(input.grossAmount, "grossAmount");
|
|
196
|
+
if (quantity === 0) throw validationError("A tétel mennyisége nem lehet 0.");
|
|
197
|
+
if (!isVatRate(input.vat)) throw validationError(`Ismeretlen áfakulcs: ${String(input.vat)}`);
|
|
198
|
+
if (input.netAmount !== void 0 || input.vatAmount !== void 0 || input.grossAmount !== void 0) return fromExplicit(input, quantity);
|
|
199
|
+
if (input.netUnitPrice !== void 0 && input.grossUnitPrice !== void 0) throw validationError("A netUnitPrice és a grossUnitPrice közül csak az egyiket add meg.");
|
|
200
|
+
const rule = roundingRuleFor(options.kind, options.currency);
|
|
201
|
+
if (input.netUnitPrice !== void 0) return fromNet({
|
|
202
|
+
...input,
|
|
203
|
+
netUnitPrice: input.netUnitPrice
|
|
204
|
+
}, quantity, rule);
|
|
205
|
+
if (input.grossUnitPrice !== void 0) return fromGross({
|
|
206
|
+
...input,
|
|
207
|
+
grossUnitPrice: input.grossUnitPrice
|
|
208
|
+
}, quantity, rule);
|
|
209
|
+
throw validationError("A tételnél add meg a netUnitPrice vagy a grossUnitPrice mezőt.");
|
|
210
|
+
}
|
|
211
|
+
function calculateInvoiceItem(input, currency) {
|
|
212
|
+
return calculateItemAmounts(input, {
|
|
213
|
+
kind: "invoice",
|
|
214
|
+
currency
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
function calculateReceiptItem(input, currency) {
|
|
218
|
+
return calculateItemAmounts(input, {
|
|
219
|
+
kind: "receipt",
|
|
220
|
+
currency
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
function summarizeItems(items) {
|
|
224
|
+
const byVat = /* @__PURE__ */ new Map();
|
|
225
|
+
let netAmount = 0;
|
|
226
|
+
let vatAmount = 0;
|
|
227
|
+
let grossAmount = 0;
|
|
228
|
+
for (const item of items) {
|
|
229
|
+
netAmount += item.netAmount;
|
|
230
|
+
vatAmount += item.vatAmount;
|
|
231
|
+
grossAmount += item.grossAmount;
|
|
232
|
+
const key = String(item.vat);
|
|
233
|
+
const bucket = byVat.get(key) ?? {
|
|
234
|
+
vat: item.vat,
|
|
235
|
+
netAmount: 0,
|
|
236
|
+
vatAmount: 0,
|
|
237
|
+
grossAmount: 0
|
|
238
|
+
};
|
|
239
|
+
bucket.netAmount += item.netAmount;
|
|
240
|
+
bucket.vatAmount += item.vatAmount;
|
|
241
|
+
bucket.grossAmount += item.grossAmount;
|
|
242
|
+
byVat.set(key, bucket);
|
|
243
|
+
}
|
|
244
|
+
const round = (value) => roundMoney(value, 6);
|
|
245
|
+
return {
|
|
246
|
+
netAmount: round(netAmount),
|
|
247
|
+
vatAmount: round(vatAmount),
|
|
248
|
+
grossAmount: round(grossAmount),
|
|
249
|
+
byVat: [...byVat.values()].map((bucket) => ({
|
|
250
|
+
vat: bucket.vat,
|
|
251
|
+
netAmount: round(bucket.netAmount),
|
|
252
|
+
vatAmount: round(bucket.vatAmount),
|
|
253
|
+
grossAmount: round(bucket.grossAmount)
|
|
254
|
+
}))
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
//#endregion
|
|
258
|
+
export { NUMERIC_VAT_RATES as a, isHuf as c, addMoney as d, decimalPlaces as f, summarizeItems as i, isVatRate as l, calculateItemAmounts as n, SPECIAL_VAT_CODES as o, roundMoney as p, calculateReceiptItem as r, formatVatRate as s, calculateInvoiceItem as t, vatPercentage as u };
|