Add simple support for SGB Oława

This commit is contained in:
2025-05-05 13:41:39 +02:00
parent ea58180e69
commit 1a9a3f7f53
6 changed files with 120 additions and 8 deletions

View File

@@ -33,4 +33,12 @@ export abstract class BaseTransactionParser<C extends ParserConfig> {
abstract pushTransaction(data: string[]): Promise<boolean>;
abstract reconcile(): Promise<Transaction[]>;
get csvConfig(): Record<string, unknown>|undefined {
return undefined;
}
get csvEncoding(): string {
return "utf8";
}
}

View File

@@ -3,12 +3,14 @@ import { ProfileConfig, ParserConfig, ServerConfig } from "@/types/config";
import { BaseTransactionParser } from "./base";
import { default as PlIng } from "./pl/ing";
import { default as PlAmex } from "./pl/amex";
import { default as PlSgbOlawa } from "./pl/sgbolawa";
type Constructor<T extends BaseTransactionParser<ParserConfig>> = new (name: string) => T;
const PARSERS: Record<string, Constructor<BaseTransactionParser<ParserConfig>>> = {
"pl.ing": PlIng,
"pl.amex": PlAmex,
"pl.sgbolawa": PlSgbOlawa,
};
export function createParser(config: ProfileConfig, serverConfig: ServerConfig): BaseTransactionParser<ParserConfig> {

View File

@@ -152,20 +152,14 @@ export default class extends BaseTransactionParser<IngParserConfig> {
const bAmount = b.transactionAmount ?? b.lockAmount;
if (a.date !== b.date) {
console.log(a);
console.log(b);
throw new Error(`Transfer transaction dates mismatch`);
}
if (a.title !== b.title) {
console.log(a);
console.log(b);
throw new Error(`Transfer transaction titles mismatch`);
}
if (aAmount === undefined || bAmount === undefined) {
console.log(a);
console.log(b);
throw new Error(`Undefined amounts for transactions`);
}
@@ -196,4 +190,8 @@ export default class extends BaseTransactionParser<IngParserConfig> {
return transaction as Transaction;
}
get csvEncoding(): string {
return "win1250";
}
}

View File

@@ -0,0 +1,103 @@
import { BaseTransactionParser } from "@/parser/base";
import { ParserConfig } from "@/types/config";
import { Transaction } from "@/types/transaction";
import { parseAmount } from "@/util/parser";
const headers = [
'Lp',
'Tytuł_1',
'Tytuł_2',
'Tytuł_3',
'Tytuł_4',
'Rachunek Nadawcy',
'Odbiorca_1',
'Odbiorca_2',
'Odbiorca_3',
'Odbiorca_4',
'Rachunek Odbiorcy',
'Nadawca_1',
'Nadawca_2',
'Nadawca_3',
'Nadawca_4',
'Data_operacji',
'Kwota',
'Saldo',
'Nr_dokumentu',
'Data_waluty',
'Data_nadania',
];
type SgbTransaction = {
[K in typeof headers[number]]: string;
};
type ValidatedSgbTransaction = Omit<SgbTransaction, 'Kwota'> & {
Kwota: number;
};
export default class extends BaseTransactionParser<ParserConfig> {
protected requiredFields = [];
#header = true;
#transactions: ValidatedSgbTransaction[] = [];
async pushTransaction(data: string[]): Promise<boolean> {
if (data.length !== headers.length) {
return false;
}
if (this.#header) {
this.#header = false;
return false;
}
const transaction: SgbTransaction = {};
headers.forEach((key, index) => {
transaction[key] = data[index].trim();
});
const Kwota = parseAmount(transaction.Kwota);
if (Kwota === undefined) {
return false;
}
this.#transactions.push({
...transaction,
Kwota
} as ValidatedSgbTransaction);
return true;
}
async reconcile(): Promise<Transaction[]> {
return this.#transactions.map(this.#mapTransaction.bind(this));
}
#mapTransaction(transaction: ValidatedSgbTransaction): Transaction {
const from = `${transaction.Nadawca_1} ${transaction.Nadawca_2} ${transaction.Nadawca_3}`.trim();
const to = `${transaction.Odbiorca_1} ${transaction.Odbiorca_2} ${transaction.Odbiorca_3}`.trim();
const title = `${transaction['Tytuł_1']} ${transaction['Tytuł_2']} ${transaction['Tytuł_3']}`.trim();
return {
kind: 'regular',
date: transaction.Data_nadania,
amount: transaction.Kwota,
from,
fromDetails: from,
to,
toDetails: to,
title
}
}
get csvEncoding(): string {
return "win1250";
}
get csvConfig(): Record<string, unknown> {
return {
delimiter: ";"
}
}
}

View File

@@ -55,8 +55,8 @@ const submitTransactions = (load: (server: Actual, t: Transaction[]) => Promise<
};
stream
.pipe(iconv.decodeStream(profileConfig.encoding ?? "utf8"))
.pipe(Papa.parse(Papa.NODE_STREAM_INPUT))
.pipe(iconv.decodeStream(profileConfig.encoding ?? parser.csvEncoding ?? "utf8"))
.pipe(Papa.parse(Papa.NODE_STREAM_INPUT, profileConfig.csv ?? parser.csvConfig))
.on('data', handleRow)
.on('close', handleClose);
});

View File

@@ -10,6 +10,7 @@ export type ProfileConfig = {
parser: string;
encoding?: string;
config?: ParserConfig;
csv?: Record<string, unknown>;
};
export type ParserConfig = {