Adding a Bank Parser
A bank's parser lives in backend/src/modules/parsing/parsers, extends GenericPdfParser and keeps only what is that
bank's alone: how to recognise it, payee clean-up, splitting accounts. Anything another bank could print the same way
(a date or amount shape, a header wording, a layout or OCR quirk, a currency hint) goes into the generic helpers under
backend/src/modules/parsing/helpers with a unit test, so every new bank leaves the generic parser better.
For a CSV export, add a column preset to parsers/csv-presets.ts; it needs no parser class.
1. Inspect the input
- Collect multiple statement samples
- Identify stable headers and line item formats
- Note currency, date, and locale differences
- Run the golden suite (
npm --prefix backend run test:golden), so you know it is green before you start
2. Add a parser class
Create backend/src/modules/parsing/parsers/<bank>.parser.ts. absa.parser.ts is a short example:
- Extend
GenericPdfParser - Implement
canParse(bankName, fileType, filePath, cachedText?): claim only this bank's own PDF, whenbankNameis this bank orBankName.OTHER - Override
parse(filePath, cachedText?)only to add what the generic reading cannot know: callsuper.parse, then fill in what the bank's header tells, such as the account number - Log volumes and outcomes only — never transaction contents
3. Register the parser
- Add a value to the
BankNameenum inbackend/src/entities/bank-name.ts - The column is the Postgres enum
bank_name_enum, so add a migration that extends it — seebackend/src/migrations/1787850000000-AddCommBankBankName.ts:ALTER TYPE "bank_name_enum" ADD VALUE IF NOT EXISTS '<bank>' - Add the parser to
createParsers()andFALLBACK_CLAIMSinparsing/services/parser-registry.ts - Add the name the bank prints to
parsing/helpers/pdf-layout-fingerprint.helper.ts - Add the display name to
backend/src/modules/dashboard/bank-display-names.ts,frontend/app/(main)/accounts/account-types.tsandfrontend/app/settings/profile/components/SyncSection.tsx, and a logo tofrontend/app/bank-logos/index.tsif you have one
4. Add tests and fixtures
- The parser's spec goes in
backend/@tests/unit/modules/parsing/parsers/<bank>.parser.spec.ts; also add the parser to the list inbackend/@tests/unit/modules/parsing/services/parser-factory.service.spec.ts - Golden samples live in
backend/golden/<bank>/as an input file next to its.expected.json. They are anonymized copies:backend/scripts/anonymize_statement_pdf.pyrewrites a PDF's text and keeps its layout (its header explains the options), and the real statement stays in the git-ignoredbackend/golden-private/ - Record the expected output:
cd backend
npm run golden:record -- golden/<bank>/sample1.pdf
5. Verify
npm --prefix backend run test:golden # the whole suite: every bank stays green
npm --prefix backend run test:parsing # parsing regression spec
Then import a sample file through the UI.
6. Document the support
Add the bank to Supported Banks and to the table in the README.
Debugging scripts
cd backend
# Print what the parsers read from a file
npm run parse:debug -- /path/to/statement.pdf
# Dump the raw PDF table structure, useful for a new bank format
# (writes <file>.tables.json unless you pass an output path)
npm run parse:tables -- /path/to/statement.pdf
# Compare the parsing output of a file with an expected result
npm run parse:diff -- /path/to/statement.pdf /path/to/expected.json
Next: Deployment