UNPKG

statement-parser-fab

Version:

Parse bank and credit card statements. Updated fork with FAB (First Abu Dhabi Bank) support and maintained dependencies.

105 lines (104 loc) 4.45 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.chasePrimeVisaCreditCardParser = exports.defaultChaseCreditCardParserOptions = void 0; const augment_vir_1 = require("augment-vir"); const date_1 = require("../../augments/date"); const statement_parser_1 = require("../statement-parser"); var State; (function (State) { State["Header"] = "header"; State["Payment"] = "payment"; State["Purchase"] = "purchase"; State["End"] = "end"; })(State || (State = {})); const ChaseParsingTriggers = { Payments: 'payments and other credits', Purchase: /^\s*purchase\s*$/i, Purchases: /^\s*purchases\s*$/i, Totals: 'totals year-to-date', AccountNumber: 'account number:', OpeningClosingDate: 'opening/closing date', }; const accountNumberRegExp = new RegExp(`${ChaseParsingTriggers.AccountNumber} .+(\\d{1,4})$`, 'i'); const closingDateRegExp = new RegExp(`${ChaseParsingTriggers.OpeningClosingDate}\\s+(\\d{1,2}/\\d{1,2}/\\d{1,2})\\s+-\\s+(\\d{1,2}/\\d{1,2}/\\d{1,2})`, 'i'); exports.defaultChaseCreditCardParserOptions = { includeMultiLineDescriptions: true, }; exports.chasePrimeVisaCreditCardParser = (0, statement_parser_1.createStatementParser)({ action: performStateAction, next: nextState, initialState: State.Header, endState: State.End, defaultParserOptions: exports.defaultChaseCreditCardParserOptions, parserKeywords: Object.values(ChaseParsingTriggers), }); function processTransactionLine(line, startDate, endDate) { const [, date, description, amount,] = (0, augment_vir_1.safeMatch)(line, /^(\d{1,2}\/\d{1,2})\s+(\S.+?)\s+([\.\d,\-]+)$/); if (date && description && amount) { const [month, day,] = date.split('/'); return { amount: Number((0, augment_vir_1.removeCommasFromNumberString)(amount)), description, date: (0, date_1.dateWithinRange)(startDate, endDate, Number(month), Number(day)), originalText: [line], }; } else { return line; } } function performStateAction(currentState, line, output, parserOptions) { if (currentState === State.Header) { const [, startDateString, endDateString,] = (0, augment_vir_1.safeMatch)(line, closingDateRegExp); const [, accountNumber,] = (0, augment_vir_1.safeMatch)(line, accountNumberRegExp); if (startDateString && endDateString) { const startDate = (0, augment_vir_1.createDateFromSlashFormat)(startDateString, parserOptions.yearPrefix); const endDate = (0, augment_vir_1.createDateFromSlashFormat)(endDateString, parserOptions.yearPrefix); // Chase statements sometimes include transactions a few days outside of the statement range. startDate.setDate(startDate.getDate() - 3); endDate.setDate(endDate.getDate() + 3); output.startDate = startDate; output.endDate = endDate; } else if (accountNumber && !output.accountSuffix) { output.accountSuffix = accountNumber; } } else if (currentState === State.Payment || currentState === State.Purchase) { if (!output.endDate || !output.startDate) { throw new Error('Started reading transactions but got no start or end dates.'); } const array = currentState === State.Payment ? output.incomes : output.expenses; const result = processTransactionLine(line, output.startDate, output.endDate); if (typeof result !== 'string') { array.push(result); } } return output; } function nextState(currentState, line) { line = line.toLowerCase(); switch (currentState) { case State.Header: if (line === ChaseParsingTriggers.Payments) { return State.Payment; } else if (line.match(ChaseParsingTriggers.Purchase) || line.match(ChaseParsingTriggers.Purchases)) { return State.Purchase; } break; case State.Payment: if (line.match(ChaseParsingTriggers.Purchase) || line.match(ChaseParsingTriggers.Purchases)) { return State.Purchase; } break; case State.Purchase: if (line.includes(ChaseParsingTriggers.Totals)) { return State.End; } break; } return currentState; }