Add support for Amex importer
This commit is contained in:
@@ -2,11 +2,13 @@ export { BaseTransactionParser } from "./base";
|
|||||||
import { ProfileConfig, ParserConfig, ServerConfig } from "@/types/config";
|
import { ProfileConfig, ParserConfig, ServerConfig } from "@/types/config";
|
||||||
import { BaseTransactionParser } from "./base";
|
import { BaseTransactionParser } from "./base";
|
||||||
import { default as PlIng } from "./pl/ing";
|
import { default as PlIng } from "./pl/ing";
|
||||||
|
import { default as PlAmex } from "./pl/amex";
|
||||||
|
|
||||||
type Constructor<T extends BaseTransactionParser<ParserConfig>> = new (name: string) => T;
|
type Constructor<T extends BaseTransactionParser<ParserConfig>> = new (name: string) => T;
|
||||||
|
|
||||||
const PARSERS: Record<string, Constructor<BaseTransactionParser<ParserConfig>>> = {
|
const PARSERS: Record<string, Constructor<BaseTransactionParser<ParserConfig>>> = {
|
||||||
"pl.ing": PlIng
|
"pl.ing": PlIng,
|
||||||
|
"pl.amex": PlAmex,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function createParser(config: ProfileConfig, serverConfig: ServerConfig): BaseTransactionParser<ParserConfig> {
|
export function createParser(config: ProfileConfig, serverConfig: ServerConfig): BaseTransactionParser<ParserConfig> {
|
||||||
|
|||||||
94
src/parser/pl/amex/index.ts
Normal file
94
src/parser/pl/amex/index.ts
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
import { BaseTransactionParser } from "@/parser/base";
|
||||||
|
import { ParserConfig } from "@/types/config";
|
||||||
|
import { Transaction } from "@/types/transaction";
|
||||||
|
import { parseAmount } from "@/util/parser";
|
||||||
|
|
||||||
|
type AmexTransaction = {
|
||||||
|
[K in typeof headers[number]]: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ValidatedAmexTransaction = Omit<AmexTransaction, 'originalAmount' | 'billedAmount'> & {
|
||||||
|
originalAmount: number;
|
||||||
|
billedAmount: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const headers = [
|
||||||
|
'posted',
|
||||||
|
'occurred',
|
||||||
|
'merchantName',
|
||||||
|
'merchantCity',
|
||||||
|
'merchantState',
|
||||||
|
'merchantZipCode',
|
||||||
|
'mCC/SICCode',
|
||||||
|
'mCCDescription',
|
||||||
|
'originalAmount',
|
||||||
|
'currencyDesc',
|
||||||
|
'conversionRate',
|
||||||
|
'billedAmount',
|
||||||
|
'accountAppliedTo',
|
||||||
|
'debitCredit',
|
||||||
|
'referenceNumber',
|
||||||
|
'statementCycle',
|
||||||
|
'accountName',
|
||||||
|
'accountNumber'
|
||||||
|
];
|
||||||
|
|
||||||
|
export default class extends BaseTransactionParser<ParserConfig> {
|
||||||
|
protected requiredFields = [];
|
||||||
|
#transactions: ValidatedAmexTransaction[] = [];
|
||||||
|
|
||||||
|
async pushTransaction(data: string[]): Promise<boolean> {
|
||||||
|
if (data.length !== headers.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const transaction: AmexTransaction = {};
|
||||||
|
headers.forEach((key, index) => {
|
||||||
|
transaction[key] = data[index].trim();
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(data[0])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const originalAmount = parseAmount(transaction.originalAmount);
|
||||||
|
const billedAmount = parseAmount(transaction.billedAmount);
|
||||||
|
|
||||||
|
if (originalAmount === undefined && billedAmount === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#transactions.push({
|
||||||
|
...transaction,
|
||||||
|
originalAmount,
|
||||||
|
billedAmount
|
||||||
|
} as ValidatedAmexTransaction);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async reconcile(): Promise<Transaction[]> {
|
||||||
|
return this.#transactions.map(transaction => {
|
||||||
|
const amount = transaction.billedAmount;
|
||||||
|
|
||||||
|
if (!amount) {
|
||||||
|
throw new Error(`Undefined amount for transaction: ${transaction}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const to = [transaction.merchantName, transaction.merchantCity, transaction.merchantState, transaction.merchantZipCode]
|
||||||
|
.filter(x => x !== undefined)
|
||||||
|
.map(x => x.trim())
|
||||||
|
.filter(x => x !== "")
|
||||||
|
.join(" ");
|
||||||
|
|
||||||
|
return {
|
||||||
|
kind: 'regular',
|
||||||
|
from: transaction.accountName,
|
||||||
|
to,
|
||||||
|
date: transaction.posted,
|
||||||
|
title: `${transaction.mCCDescription} (${transaction.originalAmount} ${transaction.currencyDesc}, conv. rate: ${transaction.conversionRate})`,
|
||||||
|
amount: -amount,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user