@ksefnik/core 0.0.1
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/dist/bank/auto-detect.d.ts +3 -0
- package/dist/bank/auto-detect.d.ts.map +1 -0
- package/dist/bank/auto-detect.js +29 -0
- package/dist/bank/auto-detect.js.map +1 -0
- package/dist/bank/index.d.ts +10 -0
- package/dist/bank/index.d.ts.map +1 -0
- package/dist/bank/index.js +20 -0
- package/dist/bank/index.js.map +1 -0
- package/dist/bank/nip-extractor.d.ts +3 -0
- package/dist/bank/nip-extractor.d.ts.map +1 -0
- package/dist/bank/nip-extractor.js +36 -0
- package/dist/bank/nip-extractor.js.map +1 -0
- package/dist/bank/parsers/csv-base.d.ts +4 -0
- package/dist/bank/parsers/csv-base.d.ts.map +1 -0
- package/dist/bank/parsers/csv-base.js +48 -0
- package/dist/bank/parsers/csv-base.js.map +1 -0
- package/dist/bank/parsers/index.d.ts +8 -0
- package/dist/bank/parsers/index.d.ts.map +1 -0
- package/dist/bank/parsers/index.js +21 -0
- package/dist/bank/parsers/index.js.map +1 -0
- package/dist/bank/parsers/ing.parser.d.ts +7 -0
- package/dist/bank/parsers/ing.parser.d.ts.map +1 -0
- package/dist/bank/parsers/ing.parser.js +43 -0
- package/dist/bank/parsers/ing.parser.js.map +1 -0
- package/dist/bank/parsers/mbank.parser.d.ts +7 -0
- package/dist/bank/parsers/mbank.parser.d.ts.map +1 -0
- package/dist/bank/parsers/mbank.parser.js +39 -0
- package/dist/bank/parsers/mbank.parser.js.map +1 -0
- package/dist/bank/parsers/mt940.parser.d.ts +7 -0
- package/dist/bank/parsers/mt940.parser.d.ts.map +1 -0
- package/dist/bank/parsers/mt940.parser.js +57 -0
- package/dist/bank/parsers/mt940.parser.js.map +1 -0
- package/dist/bank/parsers/pko.parser.d.ts +7 -0
- package/dist/bank/parsers/pko.parser.d.ts.map +1 -0
- package/dist/bank/parsers/pko.parser.js +38 -0
- package/dist/bank/parsers/pko.parser.js.map +1 -0
- package/dist/bank/parsers/santander.parser.d.ts +7 -0
- package/dist/bank/parsers/santander.parser.d.ts.map +1 -0
- package/dist/bank/parsers/santander.parser.js +46 -0
- package/dist/bank/parsers/santander.parser.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/ksef/cache.d.ts +12 -0
- package/dist/ksef/cache.d.ts.map +1 -0
- package/dist/ksef/cache.js +36 -0
- package/dist/ksef/cache.js.map +1 -0
- package/dist/ksef/index.d.ts +6 -0
- package/dist/ksef/index.d.ts.map +1 -0
- package/dist/ksef/index.js +5 -0
- package/dist/ksef/index.js.map +1 -0
- package/dist/ksef/ksef.adapter.d.ts +16 -0
- package/dist/ksef/ksef.adapter.d.ts.map +1 -0
- package/dist/ksef/ksef.adapter.js +81 -0
- package/dist/ksef/ksef.adapter.js.map +1 -0
- package/dist/ksef/retry.d.ts +7 -0
- package/dist/ksef/retry.d.ts.map +1 -0
- package/dist/ksef/retry.js +41 -0
- package/dist/ksef/retry.js.map +1 -0
- package/dist/ksef/session.d.ts +16 -0
- package/dist/ksef/session.d.ts.map +1 -0
- package/dist/ksef/session.js +39 -0
- package/dist/ksef/session.js.map +1 -0
- package/dist/ksef/types.d.ts +56 -0
- package/dist/ksef/types.d.ts.map +1 -0
- package/dist/ksef/types.js +2 -0
- package/dist/ksef/types.js.map +1 -0
- package/dist/ksefnik.d.ts +51 -0
- package/dist/ksefnik.d.ts.map +1 -0
- package/dist/ksefnik.js +104 -0
- package/dist/ksefnik.js.map +1 -0
- package/dist/matching/context.d.ts +5 -0
- package/dist/matching/context.d.ts.map +1 -0
- package/dist/matching/context.js +19 -0
- package/dist/matching/context.js.map +1 -0
- package/dist/matching/index.d.ts +6 -0
- package/dist/matching/index.d.ts.map +1 -0
- package/dist/matching/index.js +6 -0
- package/dist/matching/index.js.map +1 -0
- package/dist/matching/passes/exact.pass.d.ts +3 -0
- package/dist/matching/passes/exact.pass.d.ts.map +1 -0
- package/dist/matching/passes/exact.pass.js +34 -0
- package/dist/matching/passes/exact.pass.js.map +1 -0
- package/dist/matching/passes/fuzzy.pass.d.ts +3 -0
- package/dist/matching/passes/fuzzy.pass.d.ts.map +1 -0
- package/dist/matching/passes/fuzzy.pass.js +40 -0
- package/dist/matching/passes/fuzzy.pass.js.map +1 -0
- package/dist/matching/passes/index.d.ts +9 -0
- package/dist/matching/passes/index.d.ts.map +1 -0
- package/dist/matching/passes/index.js +21 -0
- package/dist/matching/passes/index.js.map +1 -0
- package/dist/matching/passes/invoice-ref.pass.d.ts +3 -0
- package/dist/matching/passes/invoice-ref.pass.d.ts.map +1 -0
- package/dist/matching/passes/invoice-ref.pass.js +32 -0
- package/dist/matching/passes/invoice-ref.pass.js.map +1 -0
- package/dist/matching/passes/ksef-ref.pass.d.ts +3 -0
- package/dist/matching/passes/ksef-ref.pass.d.ts.map +1 -0
- package/dist/matching/passes/ksef-ref.pass.js +25 -0
- package/dist/matching/passes/ksef-ref.pass.js.map +1 -0
- package/dist/matching/passes/partial.pass.d.ts +3 -0
- package/dist/matching/passes/partial.pass.d.ts.map +1 -0
- package/dist/matching/passes/partial.pass.js +55 -0
- package/dist/matching/passes/partial.pass.js.map +1 -0
- package/dist/matching/passes/proximity.pass.d.ts +3 -0
- package/dist/matching/passes/proximity.pass.d.ts.map +1 -0
- package/dist/matching/passes/proximity.pass.js +49 -0
- package/dist/matching/passes/proximity.pass.js.map +1 -0
- package/dist/matching/pipeline.d.ts +3 -0
- package/dist/matching/pipeline.d.ts.map +1 -0
- package/dist/matching/pipeline.js +76 -0
- package/dist/matching/pipeline.js.map +1 -0
- package/dist/matching/scoring.d.ts +5 -0
- package/dist/matching/scoring.d.ts.map +1 -0
- package/dist/matching/scoring.js +28 -0
- package/dist/matching/scoring.js.map +1 -0
- package/dist/plugins/index.d.ts +3 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +3 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/loader.d.ts +3 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js +13 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/registry.d.ts +8 -0
- package/dist/plugins/registry.d.ts.map +1 -0
- package/dist/plugins/registry.js +15 -0
- package/dist/plugins/registry.js.map +1 -0
- package/dist/storage/in-memory.storage.d.ts +13 -0
- package/dist/storage/in-memory.storage.d.ts.map +1 -0
- package/dist/storage/in-memory.storage.js +57 -0
- package/dist/storage/in-memory.storage.js.map +1 -0
- package/dist/storage/index.d.ts +3 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +3 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/sqlite.storage.d.ts +13 -0
- package/dist/storage/sqlite.storage.d.ts.map +1 -0
- package/dist/storage/sqlite.storage.js +225 -0
- package/dist/storage/sqlite.storage.js.map +1 -0
- package/dist/validation/engine.d.ts +10 -0
- package/dist/validation/engine.d.ts.map +1 -0
- package/dist/validation/engine.js +19 -0
- package/dist/validation/engine.js.map +1 -0
- package/dist/validation/index.d.ts +6 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +4 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/rule.d.ts +17 -0
- package/dist/validation/rule.d.ts.map +1 -0
- package/dist/validation/rule.js +2 -0
- package/dist/validation/rule.js.map +1 -0
- package/dist/validation/rules/amount-max.d.ts +3 -0
- package/dist/validation/rules/amount-max.d.ts.map +1 -0
- package/dist/validation/rules/amount-max.js +14 -0
- package/dist/validation/rules/amount-max.js.map +1 -0
- package/dist/validation/rules/amount-positive.d.ts +3 -0
- package/dist/validation/rules/amount-positive.d.ts.map +1 -0
- package/dist/validation/rules/amount-positive.js +13 -0
- package/dist/validation/rules/amount-positive.js.map +1 -0
- package/dist/validation/rules/buyer-nip-format.d.ts +3 -0
- package/dist/validation/rules/buyer-nip-format.d.ts.map +1 -0
- package/dist/validation/rules/buyer-nip-format.js +16 -0
- package/dist/validation/rules/buyer-nip-format.js.map +1 -0
- package/dist/validation/rules/currency-valid.d.ts +3 -0
- package/dist/validation/rules/currency-valid.d.ts.map +1 -0
- package/dist/validation/rules/currency-valid.js +13 -0
- package/dist/validation/rules/currency-valid.js.map +1 -0
- package/dist/validation/rules/date-not-future.d.ts +3 -0
- package/dist/validation/rules/date-not-future.d.ts.map +1 -0
- package/dist/validation/rules/date-not-future.js +18 -0
- package/dist/validation/rules/date-not-future.js.map +1 -0
- package/dist/validation/rules/date-order.d.ts +3 -0
- package/dist/validation/rules/date-order.d.ts.map +1 -0
- package/dist/validation/rules/date-order.js +15 -0
- package/dist/validation/rules/date-order.js.map +1 -0
- package/dist/validation/rules/date-range.d.ts +3 -0
- package/dist/validation/rules/date-range.d.ts.map +1 -0
- package/dist/validation/rules/date-range.js +18 -0
- package/dist/validation/rules/date-range.js.map +1 -0
- package/dist/validation/rules/date-valid.d.ts +3 -0
- package/dist/validation/rules/date-valid.d.ts.map +1 -0
- package/dist/validation/rules/date-valid.js +15 -0
- package/dist/validation/rules/date-valid.js.map +1 -0
- package/dist/validation/rules/description-length.d.ts +3 -0
- package/dist/validation/rules/description-length.d.ts.map +1 -0
- package/dist/validation/rules/description-length.js +19 -0
- package/dist/validation/rules/description-length.js.map +1 -0
- package/dist/validation/rules/duplicate-check.d.ts +3 -0
- package/dist/validation/rules/duplicate-check.d.ts.map +1 -0
- package/dist/validation/rules/duplicate-check.js +17 -0
- package/dist/validation/rules/duplicate-check.js.map +1 -0
- package/dist/validation/rules/index.d.ts +24 -0
- package/dist/validation/rules/index.d.ts.map +1 -0
- package/dist/validation/rules/index.js +44 -0
- package/dist/validation/rules/index.js.map +1 -0
- package/dist/validation/rules/invoice-number-format.d.ts +3 -0
- package/dist/validation/rules/invoice-number-format.d.ts.map +1 -0
- package/dist/validation/rules/invoice-number-format.js +14 -0
- package/dist/validation/rules/invoice-number-format.js.map +1 -0
- package/dist/validation/rules/ksef-reference-format.d.ts +3 -0
- package/dist/validation/rules/ksef-reference-format.d.ts.map +1 -0
- package/dist/validation/rules/ksef-reference-format.js +18 -0
- package/dist/validation/rules/ksef-reference-format.js.map +1 -0
- package/dist/validation/rules/line-items-sum.d.ts +3 -0
- package/dist/validation/rules/line-items-sum.d.ts.map +1 -0
- package/dist/validation/rules/line-items-sum.js +17 -0
- package/dist/validation/rules/line-items-sum.js.map +1 -0
- package/dist/validation/rules/nip-format.d.ts +3 -0
- package/dist/validation/rules/nip-format.d.ts.map +1 -0
- package/dist/validation/rules/nip-format.js +14 -0
- package/dist/validation/rules/nip-format.js.map +1 -0
- package/dist/validation/rules/nip-not-zeros.d.ts +3 -0
- package/dist/validation/rules/nip-not-zeros.d.ts.map +1 -0
- package/dist/validation/rules/nip-not-zeros.js +12 -0
- package/dist/validation/rules/nip-not-zeros.js.map +1 -0
- package/dist/validation/rules/quantity-positive.d.ts +3 -0
- package/dist/validation/rules/quantity-positive.d.ts.map +1 -0
- package/dist/validation/rules/quantity-positive.js +21 -0
- package/dist/validation/rules/quantity-positive.js.map +1 -0
- package/dist/validation/rules/required-fields.d.ts +3 -0
- package/dist/validation/rules/required-fields.d.ts.map +1 -0
- package/dist/validation/rules/required-fields.js +18 -0
- package/dist/validation/rules/required-fields.js.map +1 -0
- package/dist/validation/rules/seller-buyer-different.d.ts +3 -0
- package/dist/validation/rules/seller-buyer-different.d.ts.map +1 -0
- package/dist/validation/rules/seller-buyer-different.js +15 -0
- package/dist/validation/rules/seller-buyer-different.js.map +1 -0
- package/dist/validation/rules/vat-calculation.d.ts +3 -0
- package/dist/validation/rules/vat-calculation.d.ts.map +1 -0
- package/dist/validation/rules/vat-calculation.js +19 -0
- package/dist/validation/rules/vat-calculation.js.map +1 -0
- package/dist/validation/rules/vat-rate-valid.d.ts +3 -0
- package/dist/validation/rules/vat-rate-valid.d.ts.map +1 -0
- package/dist/validation/rules/vat-rate-valid.js +22 -0
- package/dist/validation/rules/vat-rate-valid.js.map +1 -0
- package/package.json +44 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 CodeFormers-it
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-detect.d.ts","sourceRoot":"","sources":["../../src/bank/auto-detect.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,WAAW,CAAA;AAExE,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAiCnE"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export function detectBankFormat(content) {
|
|
2
|
+
// MT940: starts with SWIFT message tags or contains MT940 fields
|
|
3
|
+
if (content.includes(':20:') && (content.includes(':60F:') || content.includes(':61:'))) {
|
|
4
|
+
return 'mt940';
|
|
5
|
+
}
|
|
6
|
+
if (content.startsWith('{1:')) {
|
|
7
|
+
return 'mt940';
|
|
8
|
+
}
|
|
9
|
+
// CSV detection: check first few lines for header patterns
|
|
10
|
+
const firstLines = content.slice(0, 2000);
|
|
11
|
+
// mBank: headers start with #
|
|
12
|
+
if (firstLines.includes('#Data operacji') && firstLines.includes('#Opis operacji')) {
|
|
13
|
+
return 'mbank';
|
|
14
|
+
}
|
|
15
|
+
// ING: quoted headers with specific columns
|
|
16
|
+
if (firstLines.includes('"Data transakcji"') && firstLines.includes('"Dane kontrahenta"')) {
|
|
17
|
+
return 'ing';
|
|
18
|
+
}
|
|
19
|
+
// PKO BP: comma-separated with specific headers
|
|
20
|
+
if (firstLines.includes('"Data operacji"') && firstLines.includes('"Typ transakcji"')) {
|
|
21
|
+
return 'pko';
|
|
22
|
+
}
|
|
23
|
+
// Santander: unquoted headers with specific pattern
|
|
24
|
+
if (firstLines.includes('Data operacji;Data waluty;Tytu') && firstLines.includes('Nadawca/Odbiorca')) {
|
|
25
|
+
return 'santander';
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=auto-detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-detect.js","sourceRoot":"","sources":["../../src/bank/auto-detect.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,iEAAiE;IACjE,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QACxF,OAAO,OAAO,CAAA;IAChB,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,2DAA2D;IAC3D,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;IAEzC,8BAA8B;IAC9B,IAAI,UAAU,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACnF,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,4CAA4C;IAC5C,IAAI,UAAU,CAAC,QAAQ,CAAC,mBAAmB,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC;QAC1F,OAAO,KAAK,CAAA;IACd,CAAC;IAED,gDAAgD;IAChD,IAAI,UAAU,CAAC,QAAQ,CAAC,iBAAiB,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACtF,OAAO,KAAK,CAAA;IACd,CAAC;IAED,oDAAoD;IACpD,IAAI,UAAU,CAAC,QAAQ,CAAC,gCAAgC,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACrG,OAAO,WAAW,CAAA;IACpB,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BankTransaction, BankStatementParser } from '@ksefnik/shared';
|
|
2
|
+
export { extractNIPs, extractFirstNIP } from './nip-extractor.js';
|
|
3
|
+
export { detectBankFormat } from './auto-detect.js';
|
|
4
|
+
export * from './parsers/index.js';
|
|
5
|
+
export interface ImportBankStatementOpts {
|
|
6
|
+
parsers?: BankStatementParser[];
|
|
7
|
+
}
|
|
8
|
+
export declare function importBankStatement(filePath: string, opts?: ImportBankStatementOpts): Promise<BankTransaction[]>;
|
|
9
|
+
export declare function importBankStatementFromString(content: string, opts?: ImportBankStatementOpts): Promise<BankTransaction[]>;
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bank/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAI3E,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnD,cAAc,oBAAoB,CAAA;AAElC,MAAM,WAAW,uBAAuB;IACtC,OAAO,CAAC,EAAE,mBAAmB,EAAE,CAAA;CAChC;AAED,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,uBAAuB,GAC7B,OAAO,CAAC,eAAe,EAAE,CAAC,CAG5B;AAED,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,uBAAuB,GAC7B,OAAO,CAAC,eAAe,EAAE,CAAC,CAU5B"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { UnsupportedBankFormatError } from '@ksefnik/shared';
|
|
3
|
+
import { getDefaultParsers } from './parsers/index.js';
|
|
4
|
+
export { extractNIPs, extractFirstNIP } from './nip-extractor.js';
|
|
5
|
+
export { detectBankFormat } from './auto-detect.js';
|
|
6
|
+
export * from './parsers/index.js';
|
|
7
|
+
export async function importBankStatement(filePath, opts) {
|
|
8
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
9
|
+
return importBankStatementFromString(content, opts);
|
|
10
|
+
}
|
|
11
|
+
export async function importBankStatementFromString(content, opts) {
|
|
12
|
+
const parsers = opts?.parsers ?? getDefaultParsers();
|
|
13
|
+
for (const parser of parsers) {
|
|
14
|
+
if (await parser.canParse(content)) {
|
|
15
|
+
return parser.parse(content);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
throw new UnsupportedBankFormatError('unknown');
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bank/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAEtC,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAA;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAEtD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnD,cAAc,oBAAoB,CAAA;AAMlC,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB,EAChB,IAA8B;IAE9B,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAC/C,OAAO,6BAA6B,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;AACrD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,OAAe,EACf,IAA8B;IAE9B,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,IAAI,iBAAiB,EAAE,CAAA;IAEpD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACnC,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAC9B,CAAC;IACH,CAAC;IAED,MAAM,IAAI,0BAA0B,CAAC,SAAS,CAAC,CAAA;AACjD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nip-extractor.d.ts","sourceRoot":"","sources":["../../src/bank/nip-extractor.ts"],"names":[],"mappings":"AAOA,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CA8BlD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEhE"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { isValidNIP } from '@ksefnik/shared';
|
|
2
|
+
const MPP_PATTERN = /\/NIP\/(\d{10})\//;
|
|
3
|
+
const IDC_PATTERN = /\/IDC\/(\d{10})\//;
|
|
4
|
+
const PREFIXED_PATTERN = /NIP[:\s]*(\d{10})/gi;
|
|
5
|
+
const RAW_10_DIGIT = /\b(\d{10})\b/g;
|
|
6
|
+
export function extractNIPs(text) {
|
|
7
|
+
const found = new Set();
|
|
8
|
+
// Strategy 1: MPP structured
|
|
9
|
+
const mppMatch = text.match(MPP_PATTERN);
|
|
10
|
+
if (mppMatch?.[1]) {
|
|
11
|
+
found.add(mppMatch[1]);
|
|
12
|
+
}
|
|
13
|
+
const idcMatch = text.match(IDC_PATTERN);
|
|
14
|
+
if (idcMatch?.[1]) {
|
|
15
|
+
found.add(idcMatch[1]);
|
|
16
|
+
}
|
|
17
|
+
// Strategy 2: Prefixed (NIP: or NIP followed by digits)
|
|
18
|
+
let prefixMatch;
|
|
19
|
+
while ((prefixMatch = PREFIXED_PATTERN.exec(text)) !== null) {
|
|
20
|
+
if (prefixMatch[1]) {
|
|
21
|
+
found.add(prefixMatch[1]);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// Strategy 3: Raw 10-digit with valid checksum
|
|
25
|
+
let rawMatch;
|
|
26
|
+
while ((rawMatch = RAW_10_DIGIT.exec(text)) !== null) {
|
|
27
|
+
if (rawMatch[1] && isValidNIP(rawMatch[1])) {
|
|
28
|
+
found.add(rawMatch[1]);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return [...found];
|
|
32
|
+
}
|
|
33
|
+
export function extractFirstNIP(text) {
|
|
34
|
+
return extractNIPs(text)[0];
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=nip-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nip-extractor.js","sourceRoot":"","sources":["../../src/bank/nip-extractor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C,MAAM,WAAW,GAAG,mBAAmB,CAAA;AACvC,MAAM,WAAW,GAAG,mBAAmB,CAAA;AACvC,MAAM,gBAAgB,GAAG,qBAAqB,CAAA;AAC9C,MAAM,YAAY,GAAG,eAAe,CAAA;AAEpC,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAA;IAE/B,6BAA6B;IAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;IACxC,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClB,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IACxB,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;IACxC,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClB,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IACxB,CAAC;IAED,wDAAwD;IACxD,IAAI,WAAmC,CAAA;IACvC,OAAO,CAAC,WAAW,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC5D,IAAI,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;YACnB,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;QAC3B,CAAC;IACH,CAAC;IAED,+CAA+C;IAC/C,IAAI,QAAgC,CAAA;IACpC,OAAO,CAAC,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACrD,IAAI,QAAQ,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3C,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;QACxB,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,KAAK,CAAC,CAAA;AACnB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;AAC7B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csv-base.d.ts","sourceRoot":"","sources":["../../../src/bank/parsers/csv-base.ts"],"names":[],"mappings":"AAAA,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,GAAE,MAAY,GAAG,MAAM,EAAE,EAAE,CAG7E;AAkCD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKhD"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export function parseCSV(content, delimiter = ';') {
|
|
2
|
+
const lines = content.split(/\r?\n/).filter((l) => l.trim().length > 0);
|
|
3
|
+
return lines.map((line) => parseCsvLine(line, delimiter));
|
|
4
|
+
}
|
|
5
|
+
function parseCsvLine(line, delimiter) {
|
|
6
|
+
const fields = [];
|
|
7
|
+
let current = '';
|
|
8
|
+
let inQuotes = false;
|
|
9
|
+
for (let i = 0; i < line.length; i++) {
|
|
10
|
+
const char = line[i];
|
|
11
|
+
if (inQuotes) {
|
|
12
|
+
if (char === '"' && line[i + 1] === '"') {
|
|
13
|
+
current += '"';
|
|
14
|
+
i++;
|
|
15
|
+
}
|
|
16
|
+
else if (char === '"') {
|
|
17
|
+
inQuotes = false;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
current += char;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
if (char === '"') {
|
|
25
|
+
inQuotes = true;
|
|
26
|
+
}
|
|
27
|
+
else if (char === delimiter) {
|
|
28
|
+
fields.push(current.trim());
|
|
29
|
+
current = '';
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
current += char;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
fields.push(current.trim());
|
|
37
|
+
return fields;
|
|
38
|
+
}
|
|
39
|
+
export function stripBOM(content) {
|
|
40
|
+
return content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;
|
|
41
|
+
}
|
|
42
|
+
export function parseAmount(text) {
|
|
43
|
+
// Handle both "1230,00" and "1230.00" and "+1230,00" / "-1230,00"
|
|
44
|
+
const cleaned = text.replace(/\s/g, '').replace(',', '.');
|
|
45
|
+
const num = parseFloat(cleaned);
|
|
46
|
+
return Math.round(num * 100);
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=csv-base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csv-base.js","sourceRoot":"","sources":["../../../src/bank/parsers/csv-base.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,QAAQ,CAAC,OAAe,EAAE,YAAoB,GAAG;IAC/D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACvE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAA;AAC3D,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,SAAiB;IACnD,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,IAAI,OAAO,GAAG,EAAE,CAAA;IAChB,IAAI,QAAQ,GAAG,KAAK,CAAA;IAEpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAE,CAAA;QACrB,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBACxC,OAAO,IAAI,GAAG,CAAA;gBACd,CAAC,EAAE,CAAA;YACL,CAAC;iBAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBACxB,QAAQ,GAAG,KAAK,CAAA;YAClB,CAAC;iBAAM,CAAC;gBACN,OAAO,IAAI,IAAI,CAAA;YACjB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBACjB,QAAQ,GAAG,IAAI,CAAA;YACjB,CAAC;iBAAM,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC9B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;gBAC3B,OAAO,GAAG,EAAE,CAAA;YACd,CAAC;iBAAM,CAAC;gBACN,OAAO,IAAI,IAAI,CAAA;YACjB,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;IAE3B,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,OAAe;IACtC,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;AACtE,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,kEAAkE;IAClE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IACzD,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,CAAA;IAC/B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAA;AAC9B,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { BankStatementParser } from '@ksefnik/shared';
|
|
2
|
+
export { Mt940Parser } from './mt940.parser.js';
|
|
3
|
+
export { MbankParser } from './mbank.parser.js';
|
|
4
|
+
export { IngParser } from './ing.parser.js';
|
|
5
|
+
export { PkoParser } from './pko.parser.js';
|
|
6
|
+
export { SantanderParser } from './santander.parser.js';
|
|
7
|
+
export declare function getDefaultParsers(): BankStatementParser[];
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/bank/parsers/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAO1D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAUvD,wBAAgB,iBAAiB,IAAI,mBAAmB,EAAE,CAEzD"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Mt940Parser } from './mt940.parser.js';
|
|
2
|
+
import { MbankParser } from './mbank.parser.js';
|
|
3
|
+
import { IngParser } from './ing.parser.js';
|
|
4
|
+
import { PkoParser } from './pko.parser.js';
|
|
5
|
+
import { SantanderParser } from './santander.parser.js';
|
|
6
|
+
export { Mt940Parser } from './mt940.parser.js';
|
|
7
|
+
export { MbankParser } from './mbank.parser.js';
|
|
8
|
+
export { IngParser } from './ing.parser.js';
|
|
9
|
+
export { PkoParser } from './pko.parser.js';
|
|
10
|
+
export { SantanderParser } from './santander.parser.js';
|
|
11
|
+
const defaultParsers = [
|
|
12
|
+
new Mt940Parser(),
|
|
13
|
+
new MbankParser(),
|
|
14
|
+
new IngParser(),
|
|
15
|
+
new PkoParser(),
|
|
16
|
+
new SantanderParser(),
|
|
17
|
+
];
|
|
18
|
+
export function getDefaultParsers() {
|
|
19
|
+
return defaultParsers;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/bank/parsers/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAEvD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAEvD,MAAM,cAAc,GAA0B;IAC5C,IAAI,WAAW,EAAE;IACjB,IAAI,WAAW,EAAE;IACjB,IAAI,SAAS,EAAE;IACf,IAAI,SAAS,EAAE;IACf,IAAI,eAAe,EAAE;CACtB,CAAA;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,cAAc,CAAA;AACvB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BankStatementParser, BankTransaction } from '@ksefnik/shared';
|
|
2
|
+
export declare class IngParser implements BankStatementParser {
|
|
3
|
+
bank: string;
|
|
4
|
+
canParse(content: string | Buffer): Promise<boolean>;
|
|
5
|
+
parse(content: string | Buffer): Promise<BankTransaction[]>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=ing.parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ing.parser.d.ts","sourceRoot":"","sources":["../../../src/bank/parsers/ing.parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAS3E,qBAAa,SAAU,YAAW,mBAAmB;IACnD,IAAI,SAAQ;IAEN,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKpD,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;CAiClE"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { parseCSV, stripBOM, parseAmount } from './csv-base.js';
|
|
2
|
+
import { extractFirstNIP } from '../nip-extractor.js';
|
|
3
|
+
function formatIngDate(yyyymmdd) {
|
|
4
|
+
// ING format: 20260301 -> 2026-03-01
|
|
5
|
+
return `${yyyymmdd.slice(0, 4)}-${yyyymmdd.slice(4, 6)}-${yyyymmdd.slice(6, 8)}`;
|
|
6
|
+
}
|
|
7
|
+
export class IngParser {
|
|
8
|
+
bank = 'ing';
|
|
9
|
+
async canParse(content) {
|
|
10
|
+
const text = typeof content === 'string' ? content : content.toString('utf-8');
|
|
11
|
+
return text.includes('"Data transakcji"') && text.includes('"Dane kontrahenta"');
|
|
12
|
+
}
|
|
13
|
+
async parse(content) {
|
|
14
|
+
const text = stripBOM(typeof content === 'string' ? content : content.toString('utf-8'));
|
|
15
|
+
const rows = parseCSV(text, ';');
|
|
16
|
+
const dataRows = rows.slice(1);
|
|
17
|
+
const transactions = [];
|
|
18
|
+
for (const row of dataRows) {
|
|
19
|
+
const [dateRaw, , counterparty, title, , , details, , amountStr] = row;
|
|
20
|
+
if (!dateRaw || !amountStr)
|
|
21
|
+
continue;
|
|
22
|
+
const date = formatIngDate(dateRaw);
|
|
23
|
+
const amount = parseAmount(amountStr);
|
|
24
|
+
const isOutgoing = amount < 0;
|
|
25
|
+
const description = title ?? '';
|
|
26
|
+
const nip = extractFirstNIP(`${counterparty ?? ''} ${details ?? ''} ${description}`);
|
|
27
|
+
transactions.push({
|
|
28
|
+
id: crypto.randomUUID(),
|
|
29
|
+
date,
|
|
30
|
+
amount,
|
|
31
|
+
description,
|
|
32
|
+
...(isOutgoing
|
|
33
|
+
? { recipientName: counterparty?.split(' UL ')[0]?.split(' ul ')[0], recipientNIP: nip }
|
|
34
|
+
: { senderName: counterparty?.split(' UL ')[0]?.split(' ul ')[0], senderNIP: nip }),
|
|
35
|
+
bank: 'ing',
|
|
36
|
+
raw: row.join(';'),
|
|
37
|
+
createdAt: new Date().toISOString(),
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return transactions;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=ing.parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ing.parser.js","sourceRoot":"","sources":["../../../src/bank/parsers/ing.parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAErD,SAAS,aAAa,CAAC,QAAgB;IACrC,qCAAqC;IACrC,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAA;AAClF,CAAC;AAED,MAAM,OAAO,SAAS;IACpB,IAAI,GAAG,KAAK,CAAA;IAEZ,KAAK,CAAC,QAAQ,CAAC,OAAwB;QACrC,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAC9E,OAAO,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAA;IAClF,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,OAAwB;QAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAA;QACxF,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAEhC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAC9B,MAAM,YAAY,GAAsB,EAAE,CAAA;QAE1C,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,MAAM,CAAC,OAAO,EAAE,AAAD,EAAG,YAAY,EAAE,KAAK,EAAE,AAAD,EAAG,AAAD,EAAG,OAAO,EAAE,AAAD,EAAG,SAAS,CAAC,GAAG,GAAG,CAAA;YACtE,IAAI,CAAC,OAAO,IAAI,CAAC,SAAS;gBAAE,SAAQ;YAEpC,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;YACnC,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,CAAA;YACrC,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,CAAA;YAC7B,MAAM,WAAW,GAAG,KAAK,IAAI,EAAE,CAAA;YAC/B,MAAM,GAAG,GAAG,eAAe,CAAC,GAAG,YAAY,IAAI,EAAE,IAAI,OAAO,IAAI,EAAE,IAAI,WAAW,EAAE,CAAC,CAAA;YAEpF,YAAY,CAAC,IAAI,CAAC;gBAChB,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;gBACvB,IAAI;gBACJ,MAAM;gBACN,WAAW;gBACX,GAAG,CAAC,UAAU;oBACZ,CAAC,CAAC,EAAE,aAAa,EAAE,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,GAAG,EAAE;oBACxF,CAAC,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;gBACrF,IAAI,EAAE,KAAK;gBACX,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;gBAClB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,YAAY,CAAA;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BankStatementParser, BankTransaction } from '@ksefnik/shared';
|
|
2
|
+
export declare class MbankParser implements BankStatementParser {
|
|
3
|
+
bank: string;
|
|
4
|
+
canParse(content: string | Buffer): Promise<boolean>;
|
|
5
|
+
parse(content: string | Buffer): Promise<BankTransaction[]>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=mbank.parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mbank.parser.d.ts","sourceRoot":"","sources":["../../../src/bank/parsers/mbank.parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAI3E,qBAAa,WAAY,YAAW,mBAAmB;IACrD,IAAI,SAAU;IAER,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKpD,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;CAiClE"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { parseCSV, stripBOM, parseAmount } from './csv-base.js';
|
|
2
|
+
import { extractFirstNIP } from '../nip-extractor.js';
|
|
3
|
+
export class MbankParser {
|
|
4
|
+
bank = 'mbank';
|
|
5
|
+
async canParse(content) {
|
|
6
|
+
const text = typeof content === 'string' ? content : content.toString('utf-8');
|
|
7
|
+
return text.includes('#Data operacji') && text.includes('#Opis operacji');
|
|
8
|
+
}
|
|
9
|
+
async parse(content) {
|
|
10
|
+
const text = stripBOM(typeof content === 'string' ? content : content.toString('utf-8'));
|
|
11
|
+
const rows = parseCSV(text, ';');
|
|
12
|
+
// Skip header row
|
|
13
|
+
const dataRows = rows.slice(1);
|
|
14
|
+
const transactions = [];
|
|
15
|
+
for (const row of dataRows) {
|
|
16
|
+
const [date, , operationType, title, counterparty, accountNumber, amountStr] = row;
|
|
17
|
+
if (!date || !amountStr)
|
|
18
|
+
continue;
|
|
19
|
+
const amount = parseAmount(amountStr);
|
|
20
|
+
const isOutgoing = amount < 0;
|
|
21
|
+
const description = title ?? '';
|
|
22
|
+
const nip = extractFirstNIP(`${counterparty ?? ''} ${description}`);
|
|
23
|
+
transactions.push({
|
|
24
|
+
id: crypto.randomUUID(),
|
|
25
|
+
date,
|
|
26
|
+
amount,
|
|
27
|
+
description,
|
|
28
|
+
...(isOutgoing
|
|
29
|
+
? { recipientName: counterparty, recipientNIP: nip }
|
|
30
|
+
: { senderName: counterparty, senderNIP: nip }),
|
|
31
|
+
bank: 'mbank',
|
|
32
|
+
raw: row.join(';'),
|
|
33
|
+
createdAt: new Date().toISOString(),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return transactions;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=mbank.parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mbank.parser.js","sourceRoot":"","sources":["../../../src/bank/parsers/mbank.parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAErD,MAAM,OAAO,WAAW;IACtB,IAAI,GAAG,OAAO,CAAA;IAEd,KAAK,CAAC,QAAQ,CAAC,OAAwB;QACrC,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAC9E,OAAO,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAA;IAC3E,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,OAAwB;QAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAA;QACxF,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAEhC,kBAAkB;QAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAC9B,MAAM,YAAY,GAAsB,EAAE,CAAA;QAE1C,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,MAAM,CAAC,IAAI,EAAE,AAAD,EAAG,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,CAAC,GAAG,GAAG,CAAA;YAClF,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS;gBAAE,SAAQ;YAEjC,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,CAAA;YACrC,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,CAAA;YAC7B,MAAM,WAAW,GAAG,KAAK,IAAI,EAAE,CAAA;YAC/B,MAAM,GAAG,GAAG,eAAe,CAAC,GAAG,YAAY,IAAI,EAAE,IAAI,WAAW,EAAE,CAAC,CAAA;YAEnE,YAAY,CAAC,IAAI,CAAC;gBAChB,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;gBACvB,IAAI;gBACJ,MAAM;gBACN,WAAW;gBACX,GAAG,CAAC,UAAU;oBACZ,CAAC,CAAC,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,EAAE;oBACpD,CAAC,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;gBACjD,IAAI,EAAE,OAAO;gBACb,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;gBAClB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,YAAY,CAAA;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BankStatementParser, BankTransaction } from '@ksefnik/shared';
|
|
2
|
+
export declare class Mt940Parser implements BankStatementParser {
|
|
3
|
+
bank: string;
|
|
4
|
+
canParse(content: string | Buffer): Promise<boolean>;
|
|
5
|
+
parse(content: string | Buffer): Promise<BankTransaction[]>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=mt940.parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mt940.parser.d.ts","sourceRoot":"","sources":["../../../src/bank/parsers/mt940.parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAgB3E,qBAAa,WAAY,YAAW,mBAAmB;IACrD,IAAI,SAAU;IAER,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMpD,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;CA+BlE"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Parser as Mt940JsParser } from 'mt940js';
|
|
2
|
+
import { extractFirstNIP } from '../nip-extractor.js';
|
|
3
|
+
function createMt940JsParser() {
|
|
4
|
+
return new Mt940JsParser();
|
|
5
|
+
}
|
|
6
|
+
function formatDate(d) {
|
|
7
|
+
return d.toISOString().slice(0, 10);
|
|
8
|
+
}
|
|
9
|
+
function amountToGrosze(amount) {
|
|
10
|
+
return Math.round(amount * 100);
|
|
11
|
+
}
|
|
12
|
+
export class Mt940Parser {
|
|
13
|
+
bank = 'mt940';
|
|
14
|
+
async canParse(content) {
|
|
15
|
+
const text = typeof content === 'string' ? content : content.toString('utf-8');
|
|
16
|
+
return (text.includes(':20:') && (text.includes(':60F:') || text.includes(':61:'))) ||
|
|
17
|
+
text.startsWith('{1:');
|
|
18
|
+
}
|
|
19
|
+
async parse(content) {
|
|
20
|
+
const text = typeof content === 'string' ? content : content.toString('utf-8');
|
|
21
|
+
const parser = createMt940JsParser();
|
|
22
|
+
const statements = parser.parse(text);
|
|
23
|
+
const transactions = [];
|
|
24
|
+
for (const statement of statements) {
|
|
25
|
+
for (const tx of statement.transactions) {
|
|
26
|
+
const details = tx.details ?? '';
|
|
27
|
+
const nip = extractFirstNIP(details);
|
|
28
|
+
const isOutgoing = tx.amount < 0;
|
|
29
|
+
transactions.push({
|
|
30
|
+
id: crypto.randomUUID(),
|
|
31
|
+
date: formatDate(tx.date),
|
|
32
|
+
amount: amountToGrosze(tx.amount),
|
|
33
|
+
description: details,
|
|
34
|
+
...(isOutgoing
|
|
35
|
+
? { recipientNIP: nip, recipientName: extractName(details) }
|
|
36
|
+
: { senderNIP: nip, senderName: extractName(details) }),
|
|
37
|
+
bank: 'mt940',
|
|
38
|
+
raw: details,
|
|
39
|
+
createdAt: new Date().toISOString(),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return transactions;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function extractName(details) {
|
|
47
|
+
// MT940 field 86 subfield ~27 contains beneficiary name
|
|
48
|
+
const match = details.match(/~27([^~]+)/);
|
|
49
|
+
if (match?.[1])
|
|
50
|
+
return match[1].trim();
|
|
51
|
+
// fallback: try to find name after ~32
|
|
52
|
+
const match32 = details.match(/~32([^~]+)/);
|
|
53
|
+
if (match32?.[1])
|
|
54
|
+
return match32[1].trim();
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=mt940.parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mt940.parser.js","sourceRoot":"","sources":["../../../src/bank/parsers/mt940.parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,SAAS,CAAA;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAErD,SAAS,mBAAmB;IAC1B,OAAO,IAAI,aAAa,EAAE,CAAA;AAC5B,CAAC;AAED,SAAS,UAAU,CAAC,CAAO;IACzB,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;AACrC,CAAC;AAED,SAAS,cAAc,CAAC,MAAc;IACpC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAA;AACjC,CAAC;AAED,MAAM,OAAO,WAAW;IACtB,IAAI,GAAG,OAAO,CAAA;IAEd,KAAK,CAAC,QAAQ,CAAC,OAAwB;QACrC,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAC9E,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;YACjF,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;IAC1B,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,OAAwB;QAClC,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAC9E,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAA;QACpC,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAErC,MAAM,YAAY,GAAsB,EAAE,CAAA;QAE1C,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,KAAK,MAAM,EAAE,IAAI,SAAS,CAAC,YAAY,EAAE,CAAC;gBACxC,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,IAAI,EAAE,CAAA;gBAChC,MAAM,GAAG,GAAG,eAAe,CAAC,OAAO,CAAC,CAAA;gBAEpC,MAAM,UAAU,GAAG,EAAE,CAAC,MAAM,GAAG,CAAC,CAAA;gBAEhC,YAAY,CAAC,IAAI,CAAC;oBAChB,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;oBACvB,IAAI,EAAE,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC;oBACzB,MAAM,EAAE,cAAc,CAAC,EAAE,CAAC,MAAM,CAAC;oBACjC,WAAW,EAAE,OAAO;oBACpB,GAAG,CAAC,UAAU;wBACZ,CAAC,CAAC,EAAE,YAAY,EAAE,GAAG,EAAE,aAAa,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE;wBAC5D,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;oBACzD,IAAI,EAAE,OAAO;oBACb,GAAG,EAAE,OAAO;oBACZ,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACpC,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;QAED,OAAO,YAAY,CAAA;IACrB,CAAC;CACF;AAED,SAAS,WAAW,CAAC,OAAe;IAClC,wDAAwD;IACxD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;IACzC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAEtC,uCAAuC;IACvC,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;IAC3C,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAE1C,OAAO,SAAS,CAAA;AAClB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BankStatementParser, BankTransaction } from '@ksefnik/shared';
|
|
2
|
+
export declare class PkoParser implements BankStatementParser {
|
|
3
|
+
bank: string;
|
|
4
|
+
canParse(content: string | Buffer): Promise<boolean>;
|
|
5
|
+
parse(content: string | Buffer): Promise<BankTransaction[]>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=pko.parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pko.parser.d.ts","sourceRoot":"","sources":["../../../src/bank/parsers/pko.parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAI3E,qBAAa,SAAU,YAAW,mBAAmB;IACnD,IAAI,SAAQ;IAEN,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKpD,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;CAgClE"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { parseCSV, stripBOM, parseAmount } from './csv-base.js';
|
|
2
|
+
import { extractFirstNIP } from '../nip-extractor.js';
|
|
3
|
+
export class PkoParser {
|
|
4
|
+
bank = 'pko';
|
|
5
|
+
async canParse(content) {
|
|
6
|
+
const text = typeof content === 'string' ? content : content.toString('utf-8');
|
|
7
|
+
return text.includes('"Data operacji"') && text.includes('"Typ transakcji"');
|
|
8
|
+
}
|
|
9
|
+
async parse(content) {
|
|
10
|
+
const text = stripBOM(typeof content === 'string' ? content : content.toString('utf-8'));
|
|
11
|
+
const rows = parseCSV(text, ',');
|
|
12
|
+
const dataRows = rows.slice(1);
|
|
13
|
+
const transactions = [];
|
|
14
|
+
for (const row of dataRows) {
|
|
15
|
+
const [date, , , amountStr, , , counterparty, title, nipRaw] = row;
|
|
16
|
+
if (!date || !amountStr)
|
|
17
|
+
continue;
|
|
18
|
+
const amount = parseAmount(amountStr);
|
|
19
|
+
const isOutgoing = amount < 0;
|
|
20
|
+
const description = title ?? '';
|
|
21
|
+
const nip = nipRaw?.match(/^\d{10}$/)?.[0] ?? extractFirstNIP(`${counterparty ?? ''} ${description}`);
|
|
22
|
+
transactions.push({
|
|
23
|
+
id: crypto.randomUUID(),
|
|
24
|
+
date,
|
|
25
|
+
amount,
|
|
26
|
+
description,
|
|
27
|
+
...(isOutgoing
|
|
28
|
+
? { recipientName: counterparty, recipientNIP: nip }
|
|
29
|
+
: { senderName: counterparty, senderNIP: nip }),
|
|
30
|
+
bank: 'pko',
|
|
31
|
+
raw: row.join(','),
|
|
32
|
+
createdAt: new Date().toISOString(),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return transactions;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=pko.parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pko.parser.js","sourceRoot":"","sources":["../../../src/bank/parsers/pko.parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAErD,MAAM,OAAO,SAAS;IACpB,IAAI,GAAG,KAAK,CAAA;IAEZ,KAAK,CAAC,QAAQ,CAAC,OAAwB;QACrC,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAC9E,OAAO,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAA;IAC9E,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,OAAwB;QAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAA;QACxF,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAEhC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAC9B,MAAM,YAAY,GAAsB,EAAE,CAAA;QAE1C,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,MAAM,CAAC,IAAI,EAAE,AAAD,EAAG,AAAD,EAAG,SAAS,EAAE,AAAD,EAAG,AAAD,EAAG,YAAY,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,GAAG,CAAA;YAClE,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS;gBAAE,SAAQ;YAEjC,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,CAAA;YACrC,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,CAAA;YAC7B,MAAM,WAAW,GAAG,KAAK,IAAI,EAAE,CAAA;YAC/B,MAAM,GAAG,GAAG,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC,GAAG,YAAY,IAAI,EAAE,IAAI,WAAW,EAAE,CAAC,CAAA;YAErG,YAAY,CAAC,IAAI,CAAC;gBAChB,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;gBACvB,IAAI;gBACJ,MAAM;gBACN,WAAW;gBACX,GAAG,CAAC,UAAU;oBACZ,CAAC,CAAC,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,EAAE;oBACpD,CAAC,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;gBACjD,IAAI,EAAE,KAAK;gBACX,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;gBAClB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,YAAY,CAAA;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BankStatementParser, BankTransaction } from '@ksefnik/shared';
|
|
2
|
+
export declare class SantanderParser implements BankStatementParser {
|
|
3
|
+
bank: string;
|
|
4
|
+
canParse(content: string | Buffer): Promise<boolean>;
|
|
5
|
+
parse(content: string | Buffer): Promise<BankTransaction[]>;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=santander.parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"santander.parser.d.ts","sourceRoot":"","sources":["../../../src/bank/parsers/santander.parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAU3E,qBAAa,eAAgB,YAAW,mBAAmB;IACzD,IAAI,SAAc;IAEZ,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKpD,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;CAoClE"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { parseCSV, stripBOM, parseAmount } from './csv-base.js';
|
|
2
|
+
import { extractFirstNIP } from '../nip-extractor.js';
|
|
3
|
+
function formatSantanderDate(ddmmyyyy) {
|
|
4
|
+
// Santander format: 01-03-2026 -> 2026-03-01
|
|
5
|
+
const [dd, mm, yyyy] = ddmmyyyy.split('-');
|
|
6
|
+
return `${yyyy}-${mm}-${dd}`;
|
|
7
|
+
}
|
|
8
|
+
export class SantanderParser {
|
|
9
|
+
bank = 'santander';
|
|
10
|
+
async canParse(content) {
|
|
11
|
+
const text = typeof content === 'string' ? content : content.toString('utf-8');
|
|
12
|
+
return text.includes('Data operacji;Data waluty;Tytu') && text.includes('Nadawca/Odbiorca');
|
|
13
|
+
}
|
|
14
|
+
async parse(content) {
|
|
15
|
+
const text = stripBOM(typeof content === 'string' ? content : content.toString('utf-8'));
|
|
16
|
+
const rows = parseCSV(text, ';');
|
|
17
|
+
const dataRows = rows.slice(1);
|
|
18
|
+
const transactions = [];
|
|
19
|
+
for (const row of dataRows) {
|
|
20
|
+
const [dateRaw, , title, counterparty, , amountStr] = row;
|
|
21
|
+
if (!dateRaw || !amountStr)
|
|
22
|
+
continue;
|
|
23
|
+
const date = formatSantanderDate(dateRaw);
|
|
24
|
+
const amount = parseAmount(amountStr);
|
|
25
|
+
const isOutgoing = amount < 0;
|
|
26
|
+
const description = title ?? '';
|
|
27
|
+
const nip = extractFirstNIP(`${counterparty ?? ''} ${description}`);
|
|
28
|
+
// Santander puts "FIRMA NIP: 1234567890" in counterparty field
|
|
29
|
+
const cleanName = counterparty?.replace(/\s*NIP:\s*\d{10}/, '').trim();
|
|
30
|
+
transactions.push({
|
|
31
|
+
id: crypto.randomUUID(),
|
|
32
|
+
date,
|
|
33
|
+
amount,
|
|
34
|
+
description,
|
|
35
|
+
...(isOutgoing
|
|
36
|
+
? { recipientName: cleanName, recipientNIP: nip }
|
|
37
|
+
: { senderName: cleanName, senderNIP: nip }),
|
|
38
|
+
bank: 'santander',
|
|
39
|
+
raw: row.join(';'),
|
|
40
|
+
createdAt: new Date().toISOString(),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return transactions;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=santander.parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"santander.parser.js","sourceRoot":"","sources":["../../../src/bank/parsers/santander.parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAErD,SAAS,mBAAmB,CAAC,QAAgB;IAC3C,6CAA6C;IAC7C,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC1C,OAAO,GAAG,IAAI,IAAI,EAAE,IAAI,EAAE,EAAE,CAAA;AAC9B,CAAC;AAED,MAAM,OAAO,eAAe;IAC1B,IAAI,GAAG,WAAW,CAAA;IAElB,KAAK,CAAC,QAAQ,CAAC,OAAwB;QACrC,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAC9E,OAAO,IAAI,CAAC,QAAQ,CAAC,gCAAgC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAA;IAC7F,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,OAAwB;QAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAA;QACxF,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAEhC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAC9B,MAAM,YAAY,GAAsB,EAAE,CAAA;QAE1C,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,MAAM,CAAC,OAAO,EAAE,AAAD,EAAG,KAAK,EAAE,YAAY,EAAE,AAAD,EAAG,SAAS,CAAC,GAAG,GAAG,CAAA;YACzD,IAAI,CAAC,OAAO,IAAI,CAAC,SAAS;gBAAE,SAAQ;YAEpC,MAAM,IAAI,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAA;YACzC,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,CAAA;YACrC,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,CAAA;YAC7B,MAAM,WAAW,GAAG,KAAK,IAAI,EAAE,CAAA;YAC/B,MAAM,GAAG,GAAG,eAAe,CAAC,GAAG,YAAY,IAAI,EAAE,IAAI,WAAW,EAAE,CAAC,CAAA;YAEnE,+DAA+D;YAC/D,MAAM,SAAS,GAAG,YAAY,EAAE,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;YAEtE,YAAY,CAAC,IAAI,CAAC;gBAChB,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;gBACvB,IAAI;gBACJ,MAAM;gBACN,WAAW;gBACX,GAAG,CAAC,UAAU;oBACZ,CAAC,CAAC,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,EAAE;oBACjD,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;gBAC9C,IAAI,EAAE,WAAW;gBACjB,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;gBAClB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,YAAY,CAAA;IACrB,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { Ksefnik, createKsefnik } from './ksefnik.js';
|
|
2
|
+
export type { CreateKsefnikOpts } from './ksefnik.js';
|
|
3
|
+
export { InMemoryStorage, SqliteStorage } from './storage/index.js';
|
|
4
|
+
export { KsefAdapterImpl } from './ksef/index.js';
|
|
5
|
+
export { withRetry } from './ksef/index.js';
|
|
6
|
+
export { TtlCache, cacheKey } from './ksef/index.js';
|
|
7
|
+
export { SessionManager } from './ksef/index.js';
|
|
8
|
+
export type { KsefClient, KsefClientConfig, KsefSessionState, KsefRawInvoice } from './ksef/index.js';
|
|
9
|
+
export type { RetryOptions } from './ksef/index.js';
|
|
10
|
+
export type { SessionManagerOptions } from './ksef/index.js';
|
|
11
|
+
export { importBankStatement, importBankStatementFromString, extractNIPs, extractFirstNIP, detectBankFormat, Mt940Parser, MbankParser, IngParser, PkoParser, SantanderParser, getDefaultParsers, } from './bank/index.js';
|
|
12
|
+
export { validateInvoice, validateInvoices, allRules } from './validation/index.js';
|
|
13
|
+
export type { ValidationRule, ValidationResult, ValidationContext, ValidationReport } from './validation/index.js';
|
|
14
|
+
export { runPipeline, defaultPasses } from './matching/index.js';
|
|
15
|
+
export { PluginRegistry, loadPlugin } from './plugins/index.js';
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACrD,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAGrD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAGnE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAChD,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACrG,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,YAAY,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAG5D,OAAO,EACL,mBAAmB,EACnB,6BAA6B,EAC7B,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,SAAS,EACT,SAAS,EACT,eAAe,EACf,iBAAiB,GAClB,MAAM,iBAAiB,CAAA;AAGxB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AACnF,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAGlH,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAGhE,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA"}
|