@rvboris/sberparse 1.0.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 (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +42 -0
  3. package/dist/balance-checker.d.ts +17 -0
  4. package/dist/balance-checker.d.ts.map +1 -0
  5. package/dist/balance-checker.js +34 -0
  6. package/dist/balance-checker.js.map +1 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +31 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/commands/index.d.ts +17 -0
  12. package/dist/commands/index.d.ts.map +1 -0
  13. package/dist/commands/index.js +70 -0
  14. package/dist/commands/index.js.map +1 -0
  15. package/dist/converter.d.ts +9 -0
  16. package/dist/converter.d.ts.map +1 -0
  17. package/dist/converter.js +101 -0
  18. package/dist/converter.js.map +1 -0
  19. package/dist/csv-writer.d.ts +10 -0
  20. package/dist/csv-writer.d.ts.map +1 -0
  21. package/dist/csv-writer.js +71 -0
  22. package/dist/csv-writer.js.map +1 -0
  23. package/dist/exceptions.d.ts +31 -0
  24. package/dist/exceptions.d.ts.map +1 -0
  25. package/dist/exceptions.js +46 -0
  26. package/dist/exceptions.js.map +1 -0
  27. package/dist/extractor-selector.d.ts +16 -0
  28. package/dist/extractor-selector.d.ts.map +1 -0
  29. package/dist/extractor-selector.js +48 -0
  30. package/dist/extractor-selector.js.map +1 -0
  31. package/dist/extractor.d.ts +58 -0
  32. package/dist/extractor.d.ts.map +1 -0
  33. package/dist/extractor.js +65 -0
  34. package/dist/extractor.js.map +1 -0
  35. package/dist/extractors/index.d.ts +10 -0
  36. package/dist/extractors/index.d.ts.map +1 -0
  37. package/dist/extractors/index.js +14 -0
  38. package/dist/extractors/index.js.map +1 -0
  39. package/dist/extractors/sber-debit-2510.d.ts +15 -0
  40. package/dist/extractors/sber-debit-2510.d.ts.map +1 -0
  41. package/dist/extractors/sber-debit-2510.js +157 -0
  42. package/dist/extractors/sber-debit-2510.js.map +1 -0
  43. package/dist/extractors/sber-debit-2603.d.ts +16 -0
  44. package/dist/extractors/sber-debit-2603.d.ts.map +1 -0
  45. package/dist/extractors/sber-debit-2603.js +161 -0
  46. package/dist/extractors/sber-debit-2603.js.map +1 -0
  47. package/dist/index.d.ts +5 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +4 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/json-writer.d.ts +11 -0
  52. package/dist/json-writer.d.ts.map +1 -0
  53. package/dist/json-writer.js +38 -0
  54. package/dist/json-writer.js.map +1 -0
  55. package/dist/logger.d.ts +2 -0
  56. package/dist/logger.d.ts.map +1 -0
  57. package/dist/logger.js +21 -0
  58. package/dist/logger.js.map +1 -0
  59. package/dist/pdf-parser.d.ts +14 -0
  60. package/dist/pdf-parser.d.ts.map +1 -0
  61. package/dist/pdf-parser.js +31 -0
  62. package/dist/pdf-parser.js.map +1 -0
  63. package/dist/types.d.ts +58 -0
  64. package/dist/types.d.ts.map +1 -0
  65. package/dist/types.js +2 -0
  66. package/dist/types.js.map +1 -0
  67. package/dist/unidecode.d.ts +6 -0
  68. package/dist/unidecode.d.ts.map +1 -0
  69. package/dist/unidecode.js +92 -0
  70. package/dist/unidecode.js.map +1 -0
  71. package/dist/utils.d.ts +27 -0
  72. package/dist/utils.d.ts.map +1 -0
  73. package/dist/utils.js +65 -0
  74. package/dist/utils.js.map +1 -0
  75. package/package.json +72 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor-selector.js","sourceRoot":"","sources":["../src/extractor-selector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE1E,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAAgB;IACrD,MAAM,mBAAmB,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,cAAc,EAAE,EAAE;QACnE,IAAI,CAAC;YACH,MAAM,UAAU,GACd,cAGD,CAAC,UAAU,CAAC;YAEb,IAAI,UAAU,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACxC,OAAO,KAAK,CAAC;YACf,CAAC;YAED,MAAM,SAAS,GAAG,IAAI,cAAc,CAAC,QAAQ,CAAC,CAAC;YAC/C,OAAO,SAAS,CAAC,YAAY,EAAE,CAAC;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,uBAAuB,CAC/B,iEAAiE,CAClE,CAAC;IACJ,CAAC;IAED,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,uBAAuB,CAC/B,oFAAoF,mBAAmB;aACpG,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;aAClB,IAAI,CAAC,IAAI,CAAC,EAAE,CAChB,CAAC;IACJ,CAAC;IAED,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CACtC,aAAqB;IAIrB,KAAK,MAAM,cAAc,IAAI,cAAc,EAAE,CAAC;QAC5C,IAAI,cAAc,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAC1C,OAAO,cAAc,CAAC;QACxB,CAAC;IACH,CAAC;IAED,MAAM,cAAc,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpE,MAAM,IAAI,cAAc,CACtB,2BAA2B,aAAa,oCAAoC,cAAc,EAAE,CAC7F,CAAC;AACJ,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { Decimal } from "decimal.js";
2
+ import type { Transaction } from "./types.js";
3
+ /**
4
+ * Абстрактный базовый класс для всех экстракторов
5
+ * Все конкретные экстракторы должны наследоваться от этого класса
6
+ * и переопределять все абстрактные методы
7
+ */
8
+ export declare abstract class Extractor {
9
+ /** Текст выписки */
10
+ protected bank_text: string;
11
+ constructor(bank_text: string);
12
+ /**
13
+ * Проверяет специфичные сигнатуры формата выписки
14
+ * @throws {InputFileStructureError} если текст не соответствует формату
15
+ */
16
+ abstract checkSpecificSignatures(): void;
17
+ /**
18
+ * Получает баланс периода из шапки выписки
19
+ * @returns Баланс периода
20
+ * @throws {InputFileStructureError} если не удалось найти баланс
21
+ */
22
+ abstract getPeriodBalance(): Decimal;
23
+ /**
24
+ * Разделяет текст на отдельные записи (транзакции)
25
+ * @returns Массив текстовых записей
26
+ * @throws {InputFileStructureError} если не найдено транзакций
27
+ */
28
+ abstract splitTextOnEntries(): string[];
29
+ /**
30
+ * Разбирает одну запись в объект транзакции
31
+ * @param entry Текст записи
32
+ * @returns Объект транзакции или массив объектов
33
+ * @throws {InputFileStructureError} если не удалось разобрать запись
34
+ */
35
+ abstract decomposeEntryToDict(entry: string): Transaction | Transaction[];
36
+ /**
37
+ * Возвращает название колонки для расчёта баланса
38
+ * @returns Название колонки
39
+ */
40
+ abstract getColumnNameForBalanceCalculation(): string;
41
+ /**
42
+ * Возвращает информацию о колонках
43
+ * @returns Словарь: ключ поля → название колонки
44
+ */
45
+ abstract getColumnsInfo(): Record<string, string>;
46
+ /**
47
+ * Проверяет, поддерживается ли данный текст экстрактором
48
+ * @returns true если поддерживается
49
+ */
50
+ checkSupport(): boolean;
51
+ /**
52
+ * Получает список всех транзакций из выписки
53
+ * @returns Массив объектов транзакций
54
+ * @throws {SberParseError} если произошла ошибка при обработке
55
+ */
56
+ getEntries(): Transaction[];
57
+ }
58
+ //# sourceMappingURL=extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../src/extractor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;GAIG;AACH,8BAAsB,SAAS;IAC7B,oBAAoB;IACpB,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEhB,SAAS,EAAE,MAAM;IAI7B;;;OAGG;IACH,QAAQ,CAAC,uBAAuB,IAAI,IAAI;IAExC;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,IAAI,OAAO;IAEpC;;;;OAIG;IACH,QAAQ,CAAC,kBAAkB,IAAI,MAAM,EAAE;IAEvC;;;;;OAKG;IACH,QAAQ,CAAC,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,WAAW,EAAE;IAEzE;;;OAGG;IACH,QAAQ,CAAC,kCAAkC,IAAI,MAAM;IAErD;;;OAGG;IACH,QAAQ,CAAC,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAEjD;;;OAGG;IACH,YAAY,IAAI,OAAO;IA0BvB;;;;OAIG;IACH,UAAU,IAAI,WAAW,EAAE;CAoB5B"}
@@ -0,0 +1,65 @@
1
+ import { Decimal } from "decimal.js";
2
+ import { InputFileStructureError, SberParseError } from "./exceptions.js";
3
+ /**
4
+ * Абстрактный базовый класс для всех экстракторов
5
+ * Все конкретные экстракторы должны наследоваться от этого класса
6
+ * и переопределять все абстрактные методы
7
+ */
8
+ export class Extractor {
9
+ /** Текст выписки */
10
+ bank_text;
11
+ constructor(bank_text) {
12
+ this.bank_text = bank_text;
13
+ }
14
+ /**
15
+ * Проверяет, поддерживается ли данный текст экстрактором
16
+ * @returns true если поддерживается
17
+ */
18
+ checkSupport() {
19
+ try {
20
+ // Проверка сигнатур
21
+ this.checkSpecificSignatures();
22
+ // Проверка что баланс получен
23
+ const balance = this.getPeriodBalance();
24
+ if (!(balance instanceof Decimal)) {
25
+ return false;
26
+ }
27
+ // Проверка что есть транзакции
28
+ const entries = this.splitTextOnEntries();
29
+ if (entries.length === 0) {
30
+ return false;
31
+ }
32
+ return true;
33
+ }
34
+ catch (error) {
35
+ if (error instanceof InputFileStructureError) {
36
+ return false;
37
+ }
38
+ throw error;
39
+ }
40
+ }
41
+ /**
42
+ * Получает список всех транзакций из выписки
43
+ * @returns Массив объектов транзакций
44
+ * @throws {SberParseError} если произошла ошибка при обработке
45
+ */
46
+ getEntries() {
47
+ const entries_list = [];
48
+ for (const entry of this.splitTextOnEntries()) {
49
+ try {
50
+ const result = this.decomposeEntryToDict(entry);
51
+ if (Array.isArray(result)) {
52
+ entries_list.push(...result);
53
+ }
54
+ else {
55
+ entries_list.push(result);
56
+ }
57
+ }
58
+ catch (_error) {
59
+ throw new SberParseError(`Ошибка при обработке транзакции\n${"-".repeat(20)}\n${entry}\n${"-".repeat(20)}`);
60
+ }
61
+ }
62
+ return entries_list;
63
+ }
64
+ }
65
+ //# sourceMappingURL=extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.js","sourceRoot":"","sources":["../src/extractor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAG1E;;;;GAIG;AACH,MAAM,OAAgB,SAAS;IAC7B,oBAAoB;IACV,SAAS,CAAS;IAE5B,YAAY,SAAiB;QAC3B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IA0CD;;;OAGG;IACH,YAAY;QACV,IAAI,CAAC;YACH,oBAAoB;YACpB,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAE/B,8BAA8B;YAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxC,IAAI,CAAC,CAAC,OAAO,YAAY,OAAO,CAAC,EAAE,CAAC;gBAClC,OAAO,KAAK,CAAC;YACf,CAAC;YAED,+BAA+B;YAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,KAAK,CAAC;YACf,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,uBAAuB,EAAE,CAAC;gBAC7C,OAAO,KAAK,CAAC;YACf,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,UAAU;QACR,MAAM,YAAY,GAAkB,EAAE,CAAC;QAEvC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,kBAAkB,EAAE,EAAE,CAAC;YAC9C,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;gBAChD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC1B,YAAY,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;gBAC/B,CAAC;qBAAM,CAAC;oBACN,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC5B,CAAC;YACH,CAAC;YAAC,OAAO,MAAM,EAAE,CAAC;gBAChB,MAAM,IAAI,cAAc,CACtB,oCAAoC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,KAAK,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAClF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,YAAY,CAAC;IACtB,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ import type { Extractor } from "../extractor.js";
2
+ /**
3
+ * Список всех доступных экстракторов
4
+ */
5
+ export declare const extractorsList: Array<new (bank_text: string) => Extractor>;
6
+ /**
7
+ * Возвращает список имён экстракторов
8
+ */
9
+ export declare function getListExtractorsInText(): string[];
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/extractors/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,KAAK,SAAS,EAAE,MAAM,KAAK,SAAS,CAEtE,CAAC;AAEF;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,EAAE,CAElD"}
@@ -0,0 +1,14 @@
1
+ import { SBER_DEBIT_2603 } from "./sber-debit-2603.js";
2
+ /**
3
+ * Список всех доступных экстракторов
4
+ */
5
+ export const extractorsList = [
6
+ SBER_DEBIT_2603,
7
+ ];
8
+ /**
9
+ * Возвращает список имён экстракторов
10
+ */
11
+ export function getListExtractorsInText() {
12
+ return extractorsList.map((extractor) => extractor.name);
13
+ }
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/extractors/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAgD;IACzE,eAAe;CAChB,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO,cAAc,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { Decimal } from "decimal.js";
2
+ import { Extractor } from "../extractor.js";
3
+ import { Transaction } from "../types.js";
4
+ /**
5
+ * Экстрактор для дебетовой карты Сбербанка образца октября 2025 (SBER_DEBIT_2510)
6
+ */
7
+ export declare class SBER_DEBIT_2510 extends Extractor {
8
+ checkSpecificSignatures(): void;
9
+ getPeriodBalance(): Decimal;
10
+ splitTextOnEntries(): string[];
11
+ decomposeEntryToDict(entry: string): Transaction;
12
+ getColumnNameForBalanceCalculation(): string;
13
+ getColumnsInfo(): Record<string, string>;
14
+ }
15
+ //# sourceMappingURL=sber-debit-2510.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sber-debit-2510.d.ts","sourceRoot":"","sources":["../../src/extractors/sber-debit-2510.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI1C;;GAEG;AACH,qBAAa,eAAgB,SAAQ,SAAS;IAC5C,uBAAuB,IAAI,IAAI;IAsB/B,gBAAgB,IAAI,OAAO;IAgB3B,kBAAkB,IAAI,MAAM,EAAE;IA+B9B,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW;IAuFhD,kCAAkC,IAAI,MAAM;IAI5C,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAazC"}
@@ -0,0 +1,157 @@
1
+ import { InputFileStructureError, SberParseError } from "../exceptions.js";
2
+ import { Extractor } from "../extractor.js";
3
+ import { getDecimalFromMoney, splitSberbankLine } from "../utils.js";
4
+ /**
5
+ * Экстрактор для дебетовой карты Сбербанка образца октября 2025 (SBER_DEBIT_2510)
6
+ */
7
+ export class SBER_DEBIT_2510 extends Extractor {
8
+ checkSpecificSignatures() {
9
+ const testSberbank = /сбербанк/i.test(this.bank_text);
10
+ const testVipiska = /Выписка по счёту дебетовой карты/i.test(this.bank_text);
11
+ const testDataForm = /Дата формирования/i.test(this.bank_text);
12
+ const testDergunova = /Дергунова К\. А\./i.test(this.bank_text);
13
+ const testPodlinnost = /Для проверки подлинности документа/i.test(this.bank_text);
14
+ const testOstatok = /ОСТАТОК ПО СЧЁТУ/i.test(this.bank_text);
15
+ if (
16
+ !(testSberbank && testVipiska && testPodlinnost && testDataForm) ||
17
+ testOstatok ||
18
+ testDergunova
19
+ ) {
20
+ throw new InputFileStructureError("Не найдены паттерны, соответствующие выписке");
21
+ }
22
+ }
23
+ getPeriodBalance() {
24
+ const pattern = /ОСТАТОК НА.*?ВСЕГО ПОПОЛНЕНИЙ.*?ВСЕГО СПИСАНИЙ.*?ОСТАТОК НА.*?\n(.*?)\n/;
25
+ const match = this.bank_text.match(pattern);
26
+ if (!match) {
27
+ throw new InputFileStructureError("Не найдена структура с остатками и пополнениями");
28
+ }
29
+ const lineParts = match[1].split("\t");
30
+ const summaPopolneniy = getDecimalFromMoney(lineParts[1]);
31
+ const summaSpisaniy = getDecimalFromMoney(lineParts[2]);
32
+ return summaPopolneniy.minus(summaSpisaniy);
33
+ }
34
+ splitTextOnEntries() {
35
+ // Удаляем разделы между страницами
36
+ const cleanedText = this.bank_text.replace(
37
+ /Продолжение на следующей странице[\s\S]*?операции²\n/g,
38
+ "",
39
+ );
40
+ // Ищем записи транзакций
41
+ const pattern = new RegExp(
42
+ String.raw`\d{2}\.\d{2}\.\d{4}\s\d{2}:\d{2}\s` + // Дата и время
43
+ String.raw`(?=\d{3,8}|-|0)` + // Код авторизации
44
+ String.raw`.*?\n` + // Всё до конца строки
45
+ String.raw`\d{2}\.\d{2}\.\d{4}\s` + // Дата обработки
46
+ String.raw`[\s\S]*?` + // Всё включая новые строки (non-greedy)
47
+ String.raw`(?=\d{2}\.\d{2}\.\d{4}\s\d{2}:\d{2}|Дата\sформирования)`, // До следующей транзакции или конца
48
+ "g",
49
+ );
50
+ const entries = [];
51
+ let match;
52
+ while ((match = pattern.exec(cleanedText)) !== null) {
53
+ entries.push(match[0]);
54
+ }
55
+ if (entries.length === 0) {
56
+ throw new InputFileStructureError(
57
+ "Не обнаружена ожидаемая структура данных: не найдено ни одной транзакции",
58
+ );
59
+ }
60
+ return entries;
61
+ }
62
+ decomposeEntryToDict(entry) {
63
+ const lines = entry.split("\n").filter((line) => line.trim().length > 0);
64
+ if (lines.length < 2 || lines.length > 4) {
65
+ throw new InputFileStructureError(`entry is expected to have from 2 to 4 lines\n${entry}`);
66
+ }
67
+ // Первая строка
68
+ const firstLineParts = splitSberbankLine(lines[0]);
69
+ const operationDate = new Date(
70
+ parseInt(firstLineParts[0].split(".")[2], 10),
71
+ parseInt(firstLineParts[0].split(".")[1], 10) - 1,
72
+ parseInt(firstLineParts[0].split(".")[0], 10),
73
+ parseInt(firstLineParts[1].split(":")[0], 10),
74
+ parseInt(firstLineParts[1].split(":")[1], 10),
75
+ );
76
+ const valueAccountCurrency = getDecimalFromMoney(firstLineParts[4], true);
77
+ const result = {
78
+ operation_date: operationDate,
79
+ processing_date: new Date(), // Временное значение
80
+ authorisation_code: firstLineParts[2],
81
+ description: "",
82
+ category: firstLineParts[3],
83
+ value_account_currency: valueAccountCurrency.toNumber(),
84
+ remainder_account_currency: 0,
85
+ };
86
+ // Остаток, если есть
87
+ if (firstLineParts.length > 5) {
88
+ result.remainder_account_currency = getDecimalFromMoney(firstLineParts[5], false).toNumber();
89
+ }
90
+ // Вторая строка
91
+ const secondLineParts = splitSberbankLine(lines[1]);
92
+ if (secondLineParts.length < 2 || secondLineParts.length > 4) {
93
+ throw new SberParseError(`Line is expected to have 2 or 4 parts: ${lines[1]}`);
94
+ }
95
+ result.processing_date = new Date(
96
+ parseInt(secondLineParts[0].split(".")[2], 10),
97
+ parseInt(secondLineParts[0].split(".")[1], 10) - 1,
98
+ parseInt(secondLineParts[0].split(".")[0], 10),
99
+ );
100
+ // Проверяем последнюю часть на деньги или валюту
101
+ const lastPartAsMoney = secondLineParts[secondLineParts.length - 1].match(
102
+ /(\d[\d\s]*?,\d{2})\s(\S*)$/,
103
+ );
104
+ const lastPartAsCurrency = secondLineParts[secondLineParts.length - 1].match(/(\S)$/);
105
+ if (secondLineParts.length === 2) {
106
+ if (lastPartAsMoney) {
107
+ result.value_operational_currency = getDecimalFromMoney(
108
+ lastPartAsMoney[1],
109
+ true,
110
+ ).toNumber();
111
+ result.operational_currency = lastPartAsMoney[2];
112
+ } else {
113
+ result.description = secondLineParts[1];
114
+ }
115
+ } else if (secondLineParts.length === 3) {
116
+ result.description = secondLineParts[1];
117
+ if (lastPartAsMoney) {
118
+ result.value_operational_currency = getDecimalFromMoney(
119
+ lastPartAsMoney[1],
120
+ true,
121
+ ).toNumber();
122
+ result.operational_currency = lastPartAsMoney[2];
123
+ } else if (lastPartAsCurrency) {
124
+ result.operational_currency = lastPartAsCurrency[1];
125
+ }
126
+ }
127
+ // Третья строка, если есть
128
+ if (lines.length >= 3) {
129
+ const thirdLineParts = splitSberbankLine(lines[2]);
130
+ result.description = `${result.description || ""} ${thirdLineParts[0]}`;
131
+ }
132
+ // Четвёртая строка, если есть
133
+ if (lines.length >= 4) {
134
+ const fourthLineParts = splitSberbankLine(lines[3]);
135
+ result.description = `${result.description || ""} ${fourthLineParts[0]}`;
136
+ }
137
+ result.description = result.description.trim();
138
+ return result;
139
+ }
140
+ getColumnNameForBalanceCalculation() {
141
+ return "value_account_currency";
142
+ }
143
+ getColumnsInfo() {
144
+ return {
145
+ operation_date: "Дата операции",
146
+ processing_date: "Дата обработки",
147
+ authorisation_code: "Код авторизации",
148
+ description: "Описание операции",
149
+ category: "Категория",
150
+ value_account_currency: "Сумма в валюте счёта",
151
+ value_operational_currency: "Сумма в валюте операции",
152
+ operational_currency: "Валюта операции",
153
+ remainder_account_currency: "Остаток средств в валюте счёта",
154
+ };
155
+ }
156
+ }
157
+ //# sourceMappingURL=sber-debit-2510.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sber-debit-2510.js","sourceRoot":"","sources":["../../src/extractors/sber-debit-2510.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { Decimal } from "decimal.js";
2
+ import { Extractor } from "../extractor.js";
3
+ import type { Transaction } from "../types.js";
4
+ /**
5
+ * Экстрактор для дебетовой карты Сбербанка образца марта 2026 (SBER_DEBIT_2603)
6
+ */
7
+ export declare class SBER_DEBIT_2603 extends Extractor {
8
+ static quickCheck(text: string): boolean;
9
+ checkSpecificSignatures(): void;
10
+ getPeriodBalance(): Decimal;
11
+ splitTextOnEntries(): string[];
12
+ decomposeEntryToDict(entry: string): Transaction;
13
+ getColumnNameForBalanceCalculation(): string;
14
+ getColumnsInfo(): Record<string, string>;
15
+ }
16
+ //# sourceMappingURL=sber-debit-2603.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sber-debit-2603.d.ts","sourceRoot":"","sources":["../../src/extractors/sber-debit-2603.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C;;GAEG;AACH,qBAAa,eAAgB,SAAQ,SAAS;IAC5C,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAQxC,uBAAuB,IAAI,IAAI;IAY/B,gBAAgB,IAAI,OAAO;IAc3B,kBAAkB,IAAI,MAAM,EAAE;IAoE9B,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW;IAuFhD,kCAAkC,IAAI,MAAM;IAI5C,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAazC"}
@@ -0,0 +1,161 @@
1
+ import { InputFileStructureError } from "../exceptions.js";
2
+ import { Extractor } from "../extractor.js";
3
+ import { getDecimalFromMoney } from "../utils.js";
4
+ /**
5
+ * Экстрактор для дебетовой карты Сбербанка образца марта 2026 (SBER_DEBIT_2603)
6
+ */
7
+ export class SBER_DEBIT_2603 extends Extractor {
8
+ static quickCheck(text) {
9
+ return (/сбербанк/i.test(text) &&
10
+ /Выписка по плат[её]жному сч[её]ту/i.test(text) &&
11
+ (/Расшифровка операций/i.test(text) || /ИТОГО ПО ОПЕРАЦИЯМ/i.test(text)));
12
+ }
13
+ checkSpecificSignatures() {
14
+ const testSberbank = /сбербанк/i.test(this.bank_text) || /sberbank/i.test(this.bank_text);
15
+ const testVipiska = /Выписка по плат[её]жному сч[её]ту/i.test(this.bank_text);
16
+ const testPodlinnost = /Для проверки подлинности документа/i.test(this.bank_text);
17
+ const testOstatokPoSchetu = /ОСТАТОК ПО СЧ[ЕЁ]ТУ/i.test(this.bank_text);
18
+ const testDergunova = /Дергунова К\. А\./i.test(this.bank_text);
19
+ if (!(testSberbank && testVipiska && testPodlinnost) || testOstatokPoSchetu || testDergunova) {
20
+ throw new InputFileStructureError("Не найдены паттерны, соответствующие выписке");
21
+ }
22
+ }
23
+ getPeriodBalance() {
24
+ const topUpMatch = this.bank_text.match(/Пополнение\s*([\d\s\u00a0]+,\d{2})/);
25
+ const debitMatch = this.bank_text.match(/Списание\s*([\d\s\u00a0]+,\d{2})/);
26
+ if (!topUpMatch || !debitMatch) {
27
+ throw new InputFileStructureError("Не найдена структура с остатками и пополнениями");
28
+ }
29
+ const summaPopolneniy = getDecimalFromMoney(topUpMatch[1]);
30
+ const summaSpisaniy = getDecimalFromMoney(debitMatch[1]);
31
+ return summaPopolneniy.minus(summaSpisaniy);
32
+ }
33
+ splitTextOnEntries() {
34
+ const headerIndex = this.bank_text.search(/Расшифровка операций/i);
35
+ if (headerIndex === -1) {
36
+ throw new InputFileStructureError("Не обнаружена ожидаемая структура данных: не найден блок операций");
37
+ }
38
+ const tailSlice = this.bank_text.slice(headerIndex);
39
+ const tailIndex = tailSlice.search(/\nДата формирования/i);
40
+ const relevantText = tailIndex === -1 ? tailSlice : tailSlice.slice(0, tailIndex);
41
+ const opLineRegex = /^\d{2}\.\d{2}\.\d{4}\s*\d{2}:\d{2}\s*\d{3,8}/;
42
+ const skipLineRegex = /^(Продолжение на следующей странице|Выписка по плат[её]жному сч[её]туСтраница|ДАТА ОПЕРАЦИИ|Дата обработки|КАТЕГОРИЯ$|Описание операции$|СУММА В ВАЛЮТЕ СЧЁТА|Сумма в валюте|ОСТАТОК СРЕДСТВ|В ВАЛЮТЕ СЧЁТА)/i;
43
+ const stopLineRegex = /^(Дата формирования|ПАО Сбербанк|Проверить подпись|Скачать электронный формат подписи|Согласно статье|Денежные средства списываются|\*)$/i;
44
+ const entries = [];
45
+ let current = [];
46
+ let started = false;
47
+ let startIndex = 0;
48
+ while (startIndex <= relevantText.length) {
49
+ const endIndex = relevantText.indexOf("\n", startIndex);
50
+ const rawLine = endIndex === -1
51
+ ? relevantText.slice(startIndex)
52
+ : relevantText.slice(startIndex, endIndex);
53
+ startIndex = endIndex === -1 ? relevantText.length + 1 : endIndex + 1;
54
+ const line = rawLine.trim();
55
+ if (!line || skipLineRegex.test(line)) {
56
+ continue;
57
+ }
58
+ if (opLineRegex.test(line)) {
59
+ started = true;
60
+ if (current.length > 0) {
61
+ entries.push(current.join("\n"));
62
+ }
63
+ current = [line];
64
+ continue;
65
+ }
66
+ if (started && stopLineRegex.test(line)) {
67
+ if (current.length > 0) {
68
+ entries.push(current.join("\n"));
69
+ current = [];
70
+ }
71
+ break;
72
+ }
73
+ if (current.length > 0) {
74
+ current.push(line);
75
+ }
76
+ }
77
+ if (current.length > 0) {
78
+ entries.push(current.join("\n"));
79
+ }
80
+ if (entries.length === 0) {
81
+ throw new InputFileStructureError("Не обнаружена ожидаемая структура данных: не найдено ни одной транзакции");
82
+ }
83
+ return entries;
84
+ }
85
+ decomposeEntryToDict(entry) {
86
+ const lines = entry
87
+ .split("\n")
88
+ .map((line) => line.trim())
89
+ .filter((line) => line.length > 0);
90
+ if (lines.length < 2) {
91
+ throw new InputFileStructureError(`entry is expected to have at least 2 lines\n${entry}`);
92
+ }
93
+ const firstLine = lines[0];
94
+ const moneyRegex = /[+-]?\d[\d\s\u00a0]*,\d{2}/g;
95
+ let match;
96
+ let lastMatch = null;
97
+ let prevMatch = null;
98
+ while ((match = moneyRegex.exec(firstLine)) !== null) {
99
+ prevMatch = lastMatch;
100
+ lastMatch = match;
101
+ }
102
+ if (!prevMatch || !lastMatch || prevMatch.index === undefined || lastMatch.index === undefined) {
103
+ throw new InputFileStructureError(`Не удалось найти суммы в строке операции\n${firstLine}`);
104
+ }
105
+ const amountStr = prevMatch[0];
106
+ const remainderStr = lastMatch[0];
107
+ const opHeader = (firstLine.slice(0, prevMatch.index) +
108
+ firstLine.slice(prevMatch.index + amountStr.length, lastMatch.index) +
109
+ firstLine.slice(lastMatch.index + remainderStr.length)).trim();
110
+ const opHeaderMatch = opHeader.match(/^(\d{2}\.\d{2}\.\d{4})\s*(\d{2}:\d{2})\s*(\d{3,8})(.*)$/);
111
+ if (!opHeaderMatch) {
112
+ throw new InputFileStructureError(`Не удалось разобрать строку операции\n${firstLine}`);
113
+ }
114
+ const operationDate = new Date(parseInt(opHeaderMatch[1].split(".")[2], 10), parseInt(opHeaderMatch[1].split(".")[1], 10) - 1, parseInt(opHeaderMatch[1].split(".")[0], 10), parseInt(opHeaderMatch[2].split(":")[0], 10), parseInt(opHeaderMatch[2].split(":")[1], 10));
115
+ const result = {
116
+ operation_date: operationDate,
117
+ processing_date: operationDate,
118
+ authorisation_code: opHeaderMatch[3],
119
+ description: "",
120
+ category: opHeaderMatch[4].trim(),
121
+ value_account_currency: getDecimalFromMoney(amountStr, true).toNumber(),
122
+ remainder_account_currency: getDecimalFromMoney(remainderStr, false).toNumber(),
123
+ };
124
+ const processingLine = lines[1];
125
+ const processingMatch = processingLine.match(/^(\d{2}\.\d{2}\.\d{4})(.*)$/);
126
+ const descriptionParts = [];
127
+ if (processingMatch) {
128
+ result.processing_date = new Date(parseInt(processingMatch[1].split(".")[2], 10), parseInt(processingMatch[1].split(".")[1], 10) - 1, parseInt(processingMatch[1].split(".")[0], 10));
129
+ if (processingMatch[2].trim()) {
130
+ descriptionParts.push(processingMatch[2].trim());
131
+ }
132
+ }
133
+ else {
134
+ descriptionParts.push(processingLine);
135
+ }
136
+ for (const line of lines.slice(2)) {
137
+ if (line.trim()) {
138
+ descriptionParts.push(line.trim());
139
+ }
140
+ }
141
+ result.description = descriptionParts.join(" ").trim();
142
+ return result;
143
+ }
144
+ getColumnNameForBalanceCalculation() {
145
+ return "value_account_currency";
146
+ }
147
+ getColumnsInfo() {
148
+ return {
149
+ operation_date: "Дата операции",
150
+ processing_date: "Дата обработки",
151
+ authorisation_code: "Код авторизации",
152
+ description: "Описание операции",
153
+ category: "Категория",
154
+ value_account_currency: "Сумма в валюте счёта",
155
+ value_operational_currency: "Сумма в валюте операции",
156
+ operational_currency: "Валюта операции",
157
+ remainder_account_currency: "Остаток средств в валюте счёта",
158
+ };
159
+ }
160
+ }
161
+ //# sourceMappingURL=sber-debit-2603.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sber-debit-2603.js","sourceRoot":"","sources":["../../src/extractors/sber-debit-2603.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,SAAS;IAC5C,MAAM,CAAC,UAAU,CAAC,IAAY;QAC5B,OAAO,CACL,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;YACtB,oCAAoC,CAAC,IAAI,CAAC,IAAI,CAAC;YAC/C,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CACzE,CAAC;IACJ,CAAC;IAED,uBAAuB;QACrB,MAAM,YAAY,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC1F,MAAM,WAAW,GAAG,oCAAoC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC9E,MAAM,cAAc,GAAG,qCAAqC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAClF,MAAM,mBAAmB,GAAG,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxE,MAAM,aAAa,GAAG,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAEhE,IAAI,CAAC,CAAC,YAAY,IAAI,WAAW,IAAI,cAAc,CAAC,IAAI,mBAAmB,IAAI,aAAa,EAAE,CAAC;YAC7F,MAAM,IAAI,uBAAuB,CAAC,8CAA8C,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;IAED,gBAAgB;QACd,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAC9E,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;QAE5E,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,EAAE,CAAC;YAC/B,MAAM,IAAI,uBAAuB,CAAC,iDAAiD,CAAC,CAAC;QACvF,CAAC;QAED,MAAM,eAAe,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3D,MAAM,aAAa,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QAEzD,OAAO,eAAe,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAC9C,CAAC;IAED,kBAAkB;QAChB,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC;QACnE,IAAI,WAAW,KAAK,CAAC,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,uBAAuB,CAC/B,mEAAmE,CACpE,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACpD,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAC3D,MAAM,YAAY,GAAG,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QAElF,MAAM,WAAW,GAAG,8CAA8C,CAAC;QACnE,MAAM,aAAa,GAAG,+MAA+M,CAAC;QACtO,MAAM,aAAa,GAAG,2IAA2I,CAAC;QAElK,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,OAAO,GAAa,EAAE,CAAC;QAC3B,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,OAAO,UAAU,IAAI,YAAY,CAAC,MAAM,EAAE,CAAC;YACzC,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YACxD,MAAM,OAAO,GAAG,QAAQ,KAAK,CAAC,CAAC;gBAC7B,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC;gBAChC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YAC7C,UAAU,GAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC;YAEtE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,IAAI,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtC,SAAS;YACX,CAAC;YAED,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC3B,OAAO,GAAG,IAAI,CAAC;gBACf,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACvB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;gBACnC,CAAC;gBACD,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC;gBACjB,SAAS;YACX,CAAC;YAED,IAAI,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACvB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;oBACjC,OAAO,GAAG,EAAE,CAAC;gBACf,CAAC;gBACD,MAAM;YACR,CAAC;YAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACnC,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,uBAAuB,CAC/B,0EAA0E,CAC3E,CAAC;QACJ,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,oBAAoB,CAAC,KAAa;QAChC,MAAM,KAAK,GAAG,KAAK;aAChB,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;aAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAErC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,uBAAuB,CAAC,+CAA+C,KAAK,EAAE,CAAC,CAAC;QAC5F,CAAC;QAED,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM,UAAU,GAAG,6BAA6B,CAAC;QACjD,IAAI,KAA6B,CAAC;QAClC,IAAI,SAAS,GAA2B,IAAI,CAAC;QAC7C,IAAI,SAAS,GAA2B,IAAI,CAAC;QAE7C,OAAO,CAAC,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACrD,SAAS,GAAG,SAAS,CAAC;YACtB,SAAS,GAAG,KAAK,CAAC;QACpB,CAAC;QAED,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,KAAK,KAAK,SAAS,IAAI,SAAS,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC/F,MAAM,IAAI,uBAAuB,CAAC,6CAA6C,SAAS,EAAE,CAAC,CAAC;QAC9F,CAAC;QAED,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,YAAY,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAElC,MAAM,QAAQ,GAAG,CACf,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC;YACnC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC;YACpE,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,CACvD,CAAC,IAAI,EAAE,CAAC;QACT,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,CAClC,yDAAyD,CAC1D,CAAC;QAEF,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,uBAAuB,CAAC,yCAAyC,SAAS,EAAE,CAAC,CAAC;QAC1F,CAAC;QAED,MAAM,aAAa,GAAG,IAAI,IAAI,CAC5B,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAC5C,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,EAChD,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAC5C,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAC5C,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAC7C,CAAC;QAEF,MAAM,MAAM,GAAgB;YAC1B,cAAc,EAAE,aAAa;YAC7B,eAAe,EAAE,aAAa;YAC9B,kBAAkB,EAAE,aAAa,CAAC,CAAC,CAAC;YACpC,WAAW,EAAE,EAAE;YACf,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;YACjC,sBAAsB,EAAE,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,QAAQ,EAAE;YACvE,0BAA0B,EAAE,mBAAmB,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,QAAQ,EAAE;SAChF,CAAC;QAEF,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,eAAe,GAAG,cAAc,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAC5E,MAAM,gBAAgB,GAAa,EAAE,CAAC;QAEtC,IAAI,eAAe,EAAE,CAAC;YACpB,MAAM,CAAC,eAAe,GAAG,IAAI,IAAI,CAC/B,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAC9C,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,EAClD,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAC/C,CAAC;YACF,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;gBAC9B,gBAAgB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,gBAAgB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACxC,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YAClC,IAAI,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;gBAChB,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;QAED,MAAM,CAAC,WAAW,GAAG,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAEvD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,kCAAkC;QAChC,OAAO,wBAAwB,CAAC;IAClC,CAAC;IAED,cAAc;QACZ,OAAO;YACL,cAAc,EAAE,eAAe;YAC/B,eAAe,EAAE,gBAAgB;YACjC,kBAAkB,EAAE,iBAAiB;YACrC,WAAW,EAAE,mBAAmB;YAChC,QAAQ,EAAE,WAAW;YACrB,sBAAsB,EAAE,sBAAsB;YAC9C,0BAA0B,EAAE,yBAAyB;YACrD,oBAAoB,EAAE,iBAAiB;YACvC,0BAA0B,EAAE,gCAAgC;SAC7D,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,5 @@
1
+ export { convertPdf } from "./converter.js";
2
+ export { BalanceVerificationError, InputFileStructureError, SberParseError, UserInputError, } from "./exceptions.js";
3
+ export { Extractor } from "./extractor.js";
4
+ export type { CLIOptions, ExtractorResult, Transaction } from "./types.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,cAAc,EACd,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { convertPdf } from "./converter.js";
2
+ export { BalanceVerificationError, InputFileStructureError, SberParseError, UserInputError, } from "./exceptions.js";
3
+ export { Extractor } from "./extractor.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,cAAc,EACd,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { Transaction } from "./types.js";
2
+ /**
3
+ * Записывает транзакции в JSON файл
4
+ * @param transactions Список транзакций
5
+ * @param filename Имя файла (без расширения)
6
+ * @param extractorName Имя экстрактора
7
+ * @param errors Ошибки при конвертации
8
+ * @returns Имя созданного файла
9
+ */
10
+ export declare function writeTransactionsToJson(transactions: Transaction[], filename: string, extractorName: string, errors: string): Promise<string>;
11
+ //# sourceMappingURL=json-writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-writer.d.ts","sourceRoot":"","sources":["../src/json-writer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAe9C;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,YAAY,EAAE,WAAW,EAAE,EAC3B,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CA8BjB"}
@@ -0,0 +1,38 @@
1
+ import fs from "node:fs/promises";
2
+ /**
3
+ * Записывает транзакции в JSON файл
4
+ * @param transactions Список транзакций
5
+ * @param filename Имя файла (без расширения)
6
+ * @param extractorName Имя экстрактора
7
+ * @param errors Ошибки при конвертации
8
+ * @returns Имя созданного файла
9
+ */
10
+ export async function writeTransactionsToJson(transactions, filename, extractorName, errors) {
11
+ const outputFilename = filename.endsWith(".json") ? filename : `${filename}.json`;
12
+ // Конвертируем транзакции в сериализуемый формат
13
+ const serializableTransactions = transactions.map((transaction) => {
14
+ const result = {};
15
+ for (const [key, value] of Object.entries(transaction)) {
16
+ if (value instanceof Date) {
17
+ // Преобразуем дату в ISO строку
18
+ result[key] = value.toISOString();
19
+ }
20
+ else {
21
+ result[key] = value;
22
+ }
23
+ }
24
+ return result;
25
+ });
26
+ const output = {
27
+ metadata: {
28
+ version: "1.0.0",
29
+ extractor: extractorName,
30
+ generated_at: new Date().toISOString(),
31
+ errors: errors,
32
+ },
33
+ transactions: serializableTransactions,
34
+ };
35
+ await fs.writeFile(outputFilename, JSON.stringify(output, null, 2), "utf-8");
36
+ return outputFilename;
37
+ }
38
+ //# sourceMappingURL=json-writer.js.map