Add simple support for SGB Oława
This commit is contained in:
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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> {
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
103
src/parser/pl/sgbolawa/index.ts
Normal file
103
src/parser/pl/sgbolawa/index.ts
Normal 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: ";"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ export type ProfileConfig = {
|
||||
parser: string;
|
||||
encoding?: string;
|
||||
config?: ParserConfig;
|
||||
csv?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type ParserConfig = {
|
||||
|
||||
Reference in New Issue
Block a user