Skip to content

Bank Ingestion Data Model

1. Executive Summary

Purpose

The bank ingestion domain captures, normalizes, deduplicates, and stores bank statement data flowing into the Client Processing system. Bank files arrive as ISO 20022 CAMT.053 (end-of-day statements) and CAMT.052 (intraday reports) from multiple banking partners. The ingestion pipeline parses these files, applies gatekeeper filtering rules, and persists the results into a set of tables that form a complete audit trail from raw file through individual transactions. The centerpiece is the bank_transaction table — the golden record — where each row represents a single, deduplicated, normalized bank transaction that downstream processes (cash receipt creation, reconciliation) query against.

Scope

Covered:

  • bank_file — Tracks each uploaded bank statement file
  • bank_file_account — Junction table linking files to the bank accounts they contain
  • bank_file_header — Preserves raw ISO 20022 group header and statement header fields for audit
  • bank_file_balance — Captures balance snapshots (opening, closing, interim) from each file
  • bank_file_summary — Aggregated credit/debit entry totals from the file's transaction summary block
  • bank_file_group — Links intraday (CAMT.052) files to end-of-day (CAMT.053) files by account and date
  • bank_transaction — The golden record: deduplicated, normalized individual bank transactions
  • bank_transaction_history — Append-only audit trail of every state change to a transaction
  • bank_code_mapping — Bank-specific proprietary code mappings (e.g., BAI codes) linked to a bank and optionally mapped to ISO 20022 universal codes

Not covered (documented separately):

  • Cash receipts, splits, worksheets, and applications — see Cash Receipts Data Model and Worksheets Data Model
  • bank and bank_account reference tables — documented inline below as FK targets; they are shared reference entities without their own foundation document

2. Data Model

2.1 Entity-Relationship Diagram

mermaid
erDiagram
    bank ||--o{ bank_file : "source_bank_id"
    bank ||--o{ bank_account : "bank_id"
    bank_file ||--o{ bank_file_account : "bank_file_id"
    bank_file ||--o{ bank_file_header : "bank_file_id"
    bank_file ||--o{ bank_file_balance : "bank_file_id"
    bank_file ||--o{ bank_file_summary : "bank_file_id"
    bank_file ||--o{ bank_transaction : "bank_file_id (latest source)"
    bank_file ||--o{ bank_transaction_history : "bank_file_id"
    bank_file ||--o{ bank_file_group : "parent_file_id (CAMT.053)"
    bank_file ||--o{ bank_file_group : "child_file_id (CAMT.052)"
    bank_account ||--o{ bank_file_account : "bank_account_id"
    bank_account ||--o{ bank_file_balance : "bank_account_id"
    bank_account ||--o{ bank_file_group : "bank_account_id"
    bank_account ||--o{ bank_transaction : "bank_account_id"
    bank_transaction ||--o{ bank_transaction_history : "bank_transaction_id"
    bank_transaction ||--o| bank_transaction : "reversal_of_transaction_id"
    bank_file ||--o| bank_file : "duplicate_of_file_id"
    bank_code_mapping }o--|| bank : "bank_id"

2.2 bank_file

Tracks each uploaded bank statement file; one row per file upload regardless of how many accounts or transactions the file contains.

FieldTypeRequiredDefaultDescription
bank_file_idserialYesAutoPrimary key. Referenced by all child file tables and bank_transaction.
source_bank_idvarchar(20)NoFK to bank.bank_id. Identifies which bank produced the file (e.g., BOFA, JPM, CNB).
file_nametextYesOriginal file name as uploaded.
file_typevarchar(20)YesCAMT053 (end-of-day) or CAMT052 (intraday). See Section 5.
xsd_namevarchar(50)NoISO 20022 schema version identifier (e.g., camt.052.001.02).
message_idvarchar(100)NoExtracted from <MsgId> in the XML group header. Used in file-level deduplication.
content_hashvarchar(64)NoSHA-256 hash of raw file content. Secondary deduplication mechanism.
electronic_seq_nbintegerNoExtracted from <ElctrncSeqNb>. Sequential file number assigned by the bank.
is_duplicatebooleanYesfalseSet to true when the file is detected as a duplicate of a previously uploaded file.
duplicate_of_file_idintegerNoSelf-referencing FK to bank_file.bank_file_id. Points to the original file when is_duplicate = true.
statement_currencyvarchar(10)NoCurrency code extracted from the statement-level <Ccy> attribute.
upload_datetimestampYesnow()When the file was uploaded to the system.
statusvarchar(50)YesProcessing status. See Section 3: Status Lifecycle.
raw_contenttextNoOriginal XML content preserved for debugging and reprocessing. All entries including filtered ones are stored here.
transaction_countintegerNoNumber of transactions parsed from the file after gatekeeper filtering.

IMPORTANT

A single bank file can contain data for multiple bank accounts. The bank_file_account junction table captures this many-to-many relationship. The source_bank_id on bank_file identifies the issuing bank, not any specific account.

FK reference — bank: The bank table is a first-class reference entity with fields bank_id (PK, e.g., BOFA), bank_name, bank_full_name, file_format (ISO20022_XML or CNB_JSON), adapter_class, bic, country_code, and active_ind.


2.3 bank_file_account

Junction table linking a bank file to the bank accounts it contains. A single CAMT file can include multiple <Rpt> or <Stmt> blocks for different accounts.

FieldTypeRequiredDefaultDescription
bank_file_account_idserialYesAutoPrimary key.
bank_file_idintegerYesFK to bank_file.bank_file_id.
bank_account_idintegerYesFK to bank_account.bank_account_id.
statement_idvarchar(100)NoStatement identifier extracted from <StmtId>.
statement_from_datetimestampNoStart of the statement period for this account within the file.
statement_to_datetimestampNoEnd of the statement period for this account within the file.
account_currencyvarchar(10)NoCurrency of this specific account within the file.
transaction_countintegerNoNumber of transactions for this account within the file.

FK reference — bank_account: The bank_account table stores account details including bank_account_name, bank_account_no, bank_account_routing_no, currency_cd, country_cd, is_uta_account, uta_account_id, and a FK to bank.bank_id.

NOTE

Pure audit columns (created_by, created_dt, updated_by, updated_dt) and auto-generated primary keys are omitted unless they carry business meaning.


2.4 bank_file_header

Preserves all group header (<GrpHdr>) and statement/report header fields from the ISO 20022 XML. One row per file, capturing raw metadata for audit and traceability.

FieldTypeRequiredDefaultDescription
bank_file_header_idserialYesAutoPrimary key.
bank_file_idintegerYesFK to bank_file.bank_file_id.
message_idvarchar(100)NoFrom <GrpHdr><MsgId>. Same value as bank_file.message_id.
creation_date_timetimestampNoFrom <GrpHdr><CreDtTm>. When the bank generated the file. Used as fallback booking date for transactions.
statement_idvarchar(100)NoFrom <Stmt><StmtId> or <Rpt><RptId>.
electronic_sequence_numberintegerNoFrom <ElctrncSeqNb>.
legal_sequence_numberintegerNoFrom <LglSeqNb>.
statement_from_datetimestampNoStart of the statement/report period.
statement_to_datetimestampNoEnd of the statement/report period.
account_ibanvarchar(34)NoFrom <Acct><Id><IBAN>.
account_other_idvarchar(100)NoFrom <Acct><Id><Othr><Id>. Used when IBAN is not present.
account_currencyvarchar(10)NoFrom <Acct><Ccy>.
account_owner_namevarchar(255)NoFrom <Acct><Ownr><Nm>.
servicer_bicvarchar(11)NoFrom <Svr><FinInstnId><BIC>. The bank's SWIFT/BIC code.
servicer_namevarchar(255)NoFrom <Svr><FinInstnId><Nm>. The bank's name as stated in the file.
additional_infotextNoFrom <AddtlInf>. Freeform text from the bank.

2.5 bank_file_balance

Captures all <Bal> elements from the file. A single file typically contains multiple balance types (opening booked, closing booked, interim, etc.), and multi-account files produce balances per account.

FieldTypeRequiredDefaultDescription
bank_file_balance_idserialYesAutoPrimary key.
bank_file_idintegerYesFK to bank_file.bank_file_id.
bank_account_idintegerNoFK to bank_account.bank_account_id. Identifies which account this balance belongs to in multi-account files.
balance_typevarchar(10)YesISO 20022 balance type code (OPBD, CLBD, ITBD, etc.). See Section 5.
amountdecimal(15,2)YesBalance amount.
currencyvarchar(10)YesCurrency code of the balance.
credit_debit_indicatorvarchar(10)NoCRDT or DBIT. Indicates whether the balance represents a credit or debit position.
balance_datetimestampNoDate of the balance (date only).
balance_date_timevarchar(50)NoFull ISO datetime string when finer granularity is available.
account_ibanvarchar(34)NoIBAN from the file, used for account matching during parsing.
account_other_idvarchar(100)NoNon-IBAN account identifier from the file.
availability_daysintegerNoFrom <Avlbty><Dt><NbOfDays>. Number of days until funds become available.

NOTE

Balance records serve two purposes: daily cash position reporting for treasury, and reconciliation anchoring. The closing booked balance (CLBD) of one statement should match the opening booked balance (OPBD) of the next.


2.6 bank_file_summary

Captures the <TxsSummry> element from the file, providing aggregated credit and debit totals without requiring summation over individual transactions.

FieldTypeRequiredDefaultDescription
bank_file_summary_idserialYesAutoPrimary key.
bank_file_idintegerYesFK to bank_file.bank_file_id.
total_credit_entriesintegerNoCount of credit entries reported in the file summary block.
total_credit_amountdecimal(15,2)NoSum of all credit entry amounts as reported by the bank.
total_debit_entriesintegerNoCount of debit entries reported in the file summary block.
total_debit_amountdecimal(15,2)NoSum of all debit entry amounts as reported by the bank.
net_entry_amountdecimal(15,2)NoNet of credits minus debits as reported in the file.

2.7 bank_file_group

Links CAMT.052 (intraday) files to CAMT.053 (end-of-day) files at the account level. Grouping may be performed automatically by the system or manually by a user.

FieldTypeRequiredDefaultDescription
bank_file_group_idserialYesAutoPrimary key.
parent_file_idintegerYesFK to bank_file.bank_file_id. The CAMT.053 end-of-day file (parent).
child_file_idintegerYesFK to bank_file.bank_file_id. The CAMT.052 intraday file (child).
bank_account_idintegerNoFK to bank_account.bank_account_id. Scopes the grouping to a specific account.
statement_datetimestampNoThe statement date used for matching, derived from file content.
matching_criteriavarchar(50)NoHow the group was formed: AUTO or MANUAL. See Section 5.

NOTE

Auto-grouping is triggered when a CAMT.053 file is uploaded. The system searches for existing CAMT.052 files with the same source_bank_id, bank_account_id, and statement_date, then creates group records automatically. Manual grouping allows users to associate files that auto-grouping could not match.


2.8 bank_transaction

The golden record — the deduplicated, normalized representation of individual bank transactions. This is the primary table that downstream processes (cash receipt creation, reconciliation) query against.

IMPORTANT

The golden record uses (bank_account_id, bank_reference_id) as a composite unique key. When an intraday file creates a PDNG record and the end-of-day file arrives with the same transaction, the existing record is updated in place: status is promoted to BOOK and bank_file_id is updated to point to the latest source file. This upsert pattern is fundamental to preventing duplicate transactions.

Core Fields

FieldTypeRequiredDefaultDescription
bank_transaction_idserialYesAutoPrimary key.
bank_file_idintegerYesFK to bank_file.bank_file_id. Points to the latest source file that created or last updated this record. Updated on upsert.
bank_account_idintegerNoFK to bank_account.bank_account_id. The UTA bank account this transaction belongs to. Part of the golden-record unique key.
bank_reference_idvarchar(100)YesFrom <AcctSvcrRef>. The bank's unique reference for this transaction. Part of the golden-record unique key.
booking_datetimestampNoFrom <Ntry><BookgDt><Dt>, with fallback to <GrpHdr><CreDtTm>. The date the bank booked the transaction.
value_datetimestampNoSettlement/value date if different from booking date.
amountdecimal(15,2)YesTransaction amount from the parent <Ntry><Amt>. Always taken from the entry level, not from individual <TxDtls>.
currencyvarchar(10)YesCurrency code of the transaction amount.
statusvarchar(20)YesISO 20022 entry status. See Section 3: Status Lifecycle.
cash_receipt_statusvarchar(20)Yes'UNMATCHED'Reconciliation status tracking whether a cash receipt has been created from this transaction. See Section 3.
directionvarchar(10)NoCREDIT or DEBIT. Derived from <CdtDbtInd>.

Reversal Fields

FieldTypeRequiredDefaultDescription
is_reversalintegerYes01 if this transaction is a reversal of a prior transaction; 0 otherwise.
reversal_of_transaction_idintegerNoSelf-referencing FK to bank_transaction.bank_transaction_id. Links to the original transaction being reversed.
reversal_statusvarchar(20)NoPENDING, ACCEPTED, or REJECTED. null for non-reversal transactions. See Section 3.
reversal_accepted_attimestampNoWhen the reversal was manually accepted by a user.
reversal_accepted_byvarchar(100)NoIdentifier of the user who accepted the reversal.

WARNING

Reversal transactions (is_reversal = 1) always start with reversal_status = 'PENDING' and require manual human review before acceptance. Accepting a reversal triggers downstream effects including unapplication from receivables. This is not automated because reversals represent real financial risk (ACH bounces, payment clawbacks).

Classification Fields

FieldTypeRequiredDefaultDescription
transaction_typevarchar(50)NoHuman-readable classification: ACH, WIRE, FX, etc.
bank_transaction_codevarchar(50)NoFrom <BkTxCd><Prtry><Cd>. Bank-specific proprietary code (e.g., BAI codes 165, 195, 208).
source_bankvarchar(20)NoDetected bank identifier: BOFA, JPM, CNB.
domain_codevarchar(10)NoFrom <BkTxCd><Domn><Cd>. ISO 20022 domain (e.g., PMNT for Payments).
family_codevarchar(10)NoFrom <BkTxCd><Domn><Fmly><Cd>. Transaction family (e.g., RCDT for Received Credit Transfer).
sub_family_codevarchar(10)NoFrom <BkTxCd><Domn><Fmly><SubFmlyCd>. Sub-family detail (e.g., ACDT for ACH Credit).
transaction_code_issuervarchar(20)NoFrom <BkTxCd><Prtry><Issr>. Code system issuer (e.g., BAI).

Remittance and Counterparty Fields

FieldTypeRequiredDefaultDescription
payer_namevarchar(255)NoExtracted from <Ustrd> remittance text. The name of the entity that sent the payment.
payer_idvarchar(100)NoExtracted vendor/payer ID (e.g., from ID:00046064 patterns in remittance text).
invoice_numbervarchar(100)NoExtracted invoice reference (e.g., INV 2024-001 patterns in remittance text).
end_to_end_idvarchar(100)NoFrom <EndToEndId>. Only stored if non-placeholder; values like 0000000000 are ignored.
remittance_infotextNoRaw <Ustrd> text preserved as fallback when structured extraction does not yield results.
debtor_namevarchar(255)NoFrom <RltdPties><Dbtr><Nm>. The payer's formal name from structured party data.
debtor_accountvarchar(100)NoFrom <RltdPties><Dbtr><Acct>. The payer's account number.
debtor_org_idvarchar(100)NoFrom <Dbtr><Id><OrgId><Othr><Id>. Organization identifier for the payer.
creditor_namevarchar(255)NoFrom <RltdPties><Cdtr><Nm>. The payee's name (typically UTA).
creditor_accountvarchar(100)NoFrom <RltdPties><Cdtr><Acct>. The payee's account number.
debtor_agent_namevarchar(255)NoFrom <RltdAgts><DbtrAgt><FinInstnId><Nm>. The payer's bank name.
creditor_agent_namevarchar(255)NoFrom <RltdAgts><CdtrAgt><FinInstnId><Nm>. UTA's bank name.

Entry Reference and FX Fields

FieldTypeRequiredDefaultDescription
tx_idvarchar(100)NoFrom <TxId>. The bank's internal transaction identifier.
entry_class_typevarchar(100)NoFrom <Prtry><Tp> (e.g., ENTRY CLASS).
entry_class_refvarchar(50)NoFrom <Prtry><Ref> (e.g., CCD, CTX). Indicates ACH format type.
purposevarchar(100)NoFrom <Purp><Prtry> (e.g., PAYMENTS).
original_amountdecimal(15,2)NoFor FX transactions: amount in the original currency before conversion.
original_currencyvarchar(10)NoOriginal currency code (e.g., GBP) before conversion to account currency.
exchange_ratedecimal(15,6)NoFX rate applied by the bank. Precision of 6 decimal places for rate accuracy.
availability_daysintegerNoFrom <Avlbty><Dt><NbOfDays>. 0 = same-day availability.
booking_date_timevarchar(50)NoFull ISO datetime with time component (e.g., 2026-01-23T19:00:24.0Z).
raw_entry_refvarchar(100)NoFrom <NtryRef>. Less reliable than <AcctSvcrRef> but preserved for reference.

2.9 bank_transaction_history

Append-only audit trail that records every state change to a bank_transaction record. Every file upload that creates or updates a transaction produces one history record.

FieldTypeRequiredDefaultDescription
bank_transaction_history_idserialYesAutoPrimary key.
bank_transaction_idintegerYesFK to bank_transaction.bank_transaction_id.
bank_file_idintegerYesFK to bank_file.bank_file_id. The source file that caused this state change.
from_statusvarchar(20)NoPrevious status. null for CREATE actions (new transaction).
to_statusvarchar(20)YesNew status after the change.
booking_datetimestampNoBooking date as recorded at the time of this state change.
action_typevarchar(20)YesCREATE (new record) or UPDATE (existing record modified).

NOTE

Records in this table are never updated or deleted. Combined with the bank_file_id FK, it provides a complete provenance chain: for any transaction, you can trace every file that touched it and exactly how its status changed over time.


2.10 bank_code_mapping

Stores bank-specific proprietary codes that appear in <Prtry> elements of ISO 20022 XML, such as BAI codes. Each record links a bank-specific code to an optional universal ISO 20022 code and carries extended attributes for treasury and cash application guidance.

FieldTypeRequiredDefaultDescription
bank_code_mapping_idserialYesAutoPrimary key.
bank_idvarchar(20)YesFK to bank.bank_id. The bank that issues this proprietary code.
bank_code_typevarchar(50)YesCategory of the code, e.g., BAI_CODE or PROPRIETARY_STATUS.
bank_codevarchar(50)YesThe bank's proprietary code value (e.g., 165, ZBAL).
bank_code_issuervarchar(50)NoThe code system issuer (e.g., BAI, BOFA, JPM).
bank_code_namevarchar(255)NoShort name for this code (e.g., Preauthorized ACH Credit).
bank_code_descriptiontextNoFull description of the code's meaning and usage.
universal_code_typevarchar(50)NoISO 20022 code type this maps to (e.g., ISO20022_SUBFAMILY).
universal_codevarchar(50)NoThe corresponding universal ISO 20022 code (e.g., APAC, DMCT).
treasury_impacttextNoFree-text guidance on cash position and treasury implications.
cash_application_impacttextNoFree-text guidance on how this code affects cash application decisions.
cash_application_notestextNoAdditional notes for cash processors reviewing transactions with this code.
direction_indicatorvarchar(10)NoCREDIT, DEBIT, or BOTH. Indicates the typical cash flow direction for this code.
active_indbooleanYestrueWhether this mapping is active. Inactive mappings are retained for historical reference.

NOTE

Pure audit columns (created_by, created_dt, updated_by, updated_dt) and auto-generated primary keys are omitted unless they carry business meaning.


3. Status Lifecycle

3.1 Bank File Processing Status (bank_file.status)

The bank_file.status field tracks the processing state of each uploaded file.

StatusCodeDescriptionAllowed Transitions
PendingPENDINGFile has been received but parsing has not yet started.PROCESSED, ERROR, DUPLICATE
ProcessedPROCESSEDFile parsed successfully. Transactions extracted and upserted.
ErrorERRORParsing failed. Raw content preserved for debugging.
DuplicateDUPLICATEFile detected as a duplicate of a previously uploaded file. is_duplicate set to true.
mermaid
stateDiagram-v2
    [*] --> PENDING : File uploaded
    PENDING --> PROCESSED : Parse succeeds
    PENDING --> ERROR : Parse fails
    PENDING --> DUPLICATE : Duplicate detected

Transition: PENDING → PROCESSED

  • Trigger: Parser successfully extracts and upserts all transactions from the file.
  • Preconditions: File content is valid ISO 20022 XML (CAMT.052 or CAMT.053) or CNB JSON. Gatekeeper filter runs during parse.
  • Side-effects: bank_transaction records created or updated; bank_transaction_history records created; bank_file.transaction_count set to the count of accepted transactions.

Transition: PENDING → ERROR

  • Trigger: Parser encounters an unrecoverable error (malformed XML, schema violation, unexpected format).
  • Preconditions: None.
  • Side-effects: No transactions are upserted. bank_file.raw_content preserved for debugging and reprocessing.

Transition: PENDING → DUPLICATE

  • Trigger: Incoming file's (source_bank_id, message_id) matches an existing processed file, or content_hash matches.
  • Preconditions: An existing bank_file record with the same source_bank_id and message_id already exists.
  • Side-effects: bank_file.is_duplicate set to true; bank_file.duplicate_of_file_id set to the bank_file_id of the original. No transactions are parsed or upserted.

IMPORTANT

Duplicate detection happens during processing. A file with status = 'DUPLICATE' is preserved in the database with its raw_content intact but contributes no transactions to the golden record.


3.2 Bank Transaction Entry Status (bank_transaction.status)

The bank_transaction.status field uses ISO 20022 entry status codes. These determine whether a transaction is safe for downstream processing.

StatusCodeDescriptionAllowed Transitions
BookedBOOKFunds are settled. Safe to apply to receivables.
PendingPDNGTransaction may still reverse. Apply with caution.BOOK
InformationINFONo cash movement. Informational entry only.
FutureFUTRFuture-dated transaction. Queue for future application.BOOK
mermaid
stateDiagram-v2
    [*] --> PDNG : CAMT.052 intraday file creates transaction
    [*] --> BOOK : CAMT.053 end-of-day file creates transaction (no prior intraday)
    PDNG --> BOOK : CAMT.053 end-of-day file upserts same bank_reference_id
    FUTR --> BOOK : End-of-day file confirms settlement

Transition: (new) → PDNG

  • Trigger: A CAMT.052 intraday file is processed and contains a transaction with a bank_reference_id not yet present in bank_transaction.
  • Preconditions: No existing bank_transaction record for (bank_account_id, bank_reference_id).
  • Side-effects: New bank_transaction row inserted; bank_transaction_history record created with action_type = 'CREATE', from_status = null, to_status = 'PDNG'.

Transition: (new) → BOOK

  • Trigger: A CAMT.053 end-of-day file is processed and contains a transaction with no prior intraday record.
  • Preconditions: No existing bank_transaction record for (bank_account_id, bank_reference_id).
  • Side-effects: New bank_transaction row inserted with status = 'BOOK'; bank_transaction_history record created with action_type = 'CREATE'.

Transition: PDNG → BOOK

  • Trigger: A CAMT.053 end-of-day file is processed and contains the same bank_reference_id as an existing PDNG transaction.
  • Preconditions: Existing bank_transaction row with matching (bank_account_id, bank_reference_id) and status = 'PDNG'.
  • Side-effects: Existing row updated in place: status set to BOOK, bank_file_id updated to the latest source file, booking_date refreshed. bank_transaction_history record created with action_type = 'UPDATE', from_status = 'PDNG', to_status = 'BOOK'.

3.3 Cash Receipt Reconciliation Status (bank_transaction.cash_receipt_status)

The bank_transaction.cash_receipt_status field tracks whether a cash receipt has been created from this transaction.

StatusCodeDescriptionAllowed Transitions
UnmatchedUNMATCHEDNo cash receipt has been created from this transaction. Default state.MATCHED, PARTIAL
MatchedMATCHEDA cash receipt has been created and fully linked to this transaction.
PartialPARTIALA cash receipt exists but only partially covers this transaction amount.MATCHED

Default on creation: UNMATCHED

Transition: UNMATCHED → MATCHED

  • Trigger: User creates a cash receipt from this bank transaction and the receipt amount equals the transaction amount.
  • Preconditions: bank_transaction.status = 'BOOK'; no existing linked cash receipt.
  • Side-effects: cash_receipt row created; cash_receipt.bank_transaction_id set to this transaction's bank_transaction_id.

Transition: UNMATCHED → PARTIAL

  • Trigger: User creates a cash receipt from this bank transaction with an amount less than the transaction amount.
  • Preconditions: bank_transaction.status = 'BOOK'.
  • Side-effects: cash_receipt row created with partial amount.

Transition: PARTIAL → MATCHED

  • Trigger: Additional cash receipt(s) created to cover the remaining balance on the transaction.
  • Preconditions: Sum of linked cash receipts now equals the transaction amount.
  • Side-effects: Status promoted to MATCHED.

3.4 Reversal Status (bank_transaction.reversal_status)

The bank_transaction.reversal_status field applies only to reversal transactions (is_reversal = 1). Non-reversal transactions have reversal_status = null.

StatusCodeDescriptionAllowed Transitions
PendingPENDINGReversal detected but not yet reviewed by a user. Initial state for all reversals.ACCEPTED, REJECTED
AcceptedACCEPTEDUser has reviewed and accepted the reversal. Downstream reversal actions proceed.
RejectedREJECTEDUser has reviewed and rejected the reversal (e.g., false positive, disputed).
mermaid
stateDiagram-v2
    [*] --> PENDING : Reversal transaction detected during parse
    PENDING --> ACCEPTED : User accepts reversal
    PENDING --> REJECTED : User rejects reversal

Transition: (new) → PENDING

  • Trigger: Parser detects a reversal entry (<RvslInd> = true or RVSL/ARET sub-family code) during file processing.
  • Preconditions: None.
  • Side-effects: bank_transaction inserted with is_reversal = 1, reversal_status = 'PENDING', reversal_of_transaction_id set to the original transaction if matched.

Transition: PENDING → ACCEPTED

  • Trigger: User reviews the reversal and accepts it.
  • Preconditions: reversal_status = 'PENDING'.
  • Side-effects: reversal_accepted_at and reversal_accepted_by set. Downstream: any cash receipt created from the original transaction must be reviewed and potentially unapplied.

Transition: PENDING → REJECTED

  • Trigger: User reviews the reversal and rejects it (e.g., determines it is a false positive or disputes the reversal).
  • Preconditions: reversal_status = 'PENDING'.
  • Side-effects: reversal_status set to REJECTED. No downstream action taken on linked cash receipts.

4. Validation & Database Constraints

Unique Constraints

TableConstraintColumnsBusiness Rule
bank_fileuq_bank_file_dedup(source_bank_id, message_id)Prevents duplicate file uploads from the same bank. A given <MsgId> is unique per bank.
bank_file_accountuq_bank_file_account(bank_file_id, bank_account_id)A file can reference a given account at most once.
bank_file_groupuq_bank_file_group(parent_file_id, child_file_id, bank_account_id)Prevents duplicate grouping of the same intraday file under the same end-of-day file for the same account.
bank_transactionuq_bank_transaction_golden_record(bank_account_id, bank_reference_id)Enforces the golden-record pattern. A bank's transaction reference is unique within an account. Enables safe upserts.
bank_code_mappinguq_bank_code_mapping_code(bank_id, bank_code_type, bank_code)Prevents duplicate code definitions for the same bank and code type.

Business Validation

File-level deduplication:

  • When a file's (source_bank_id, message_id) matches an existing file, the incoming file is stored with status = 'DUPLICATE', is_duplicate = true, and duplicate_of_file_id pointing to the original. No transactions are parsed or upserted.
  • The content_hash (SHA-256) provides a secondary safety net. Even if the message_id differs (e.g., bank reissues a corrected file with a new message ID but identical content), the content hash can flag the overlap for manual review.

Gatekeeper filtering rules:

Before transactions are persisted, a gatekeeper filter is applied during parsing. The filter determines which entries from the raw bank file are accepted for processing.

RuleConditionResult
Direction filter<CdtDbtInd> = DBITRejected. Only credits (incoming payments) are processed.
Reversal filter<RvslInd> = trueRejected at parse time; handled separately as reversal transactions.
Code whitelist<BkTxCd><Prtry><Cd> not in accepted BAI codes (165, 195, 208)Rejected. Only whitelisted BAI codes are accepted.

Transactions that pass all rules are accepted for upsert into bank_transaction. Filtered entries are not stored in bank_transaction; the raw file in bank_file.raw_content preserves all entries for audit purposes.

Transaction-level upsert behavior (golden record):

ScenarioAction
No existing record for (bank_account_id, bank_reference_id)INSERT new row. History record created with action_type = 'CREATE', from_status = null.
Existing record foundUPDATE in place: promote status, update bank_file_id to latest source, refresh booking_date. History record created with action_type = 'UPDATE'.

IMPORTANT

The bank_file_id on bank_transaction always points to the latest file that touched the record. To see the full file history for a transaction, query bank_transaction_history, which preserves every bank_file_id that created or updated the transaction.

Precision rules:

Field CategoryPrecisionScale
Monetary amounts152
Exchange rates156

5. Code Master Values

5.1 FILE_TYPE (bank_file.file_type)

CodeDescriptionBehavior / When Used
CAMT052Intraday bank statement (ISO 20022 BkToCstmrAcctRpt)Transactions arrive with PDNG status. Created when intraday data is available before end-of-day settlement.
CAMT053End-of-day bank statement (ISO 20022 BkToCstmrStmt)Transactions arrive with BOOK status. The authoritative statement for the day.

Default on creation: Derived from file content. Not defaulted.


5.2 ISO20022_ENTRY_STATUS (bank_transaction.status)

CodeDescriptionBehavior / When Used
BOOKBookedFunds are settled and cleared. Safe to apply to receivables. Downstream cash receipt creation is permitted.
PDNGPendingTransaction is pending settlement. Apply with caution — may reverse. Cash receipts can be created but should be flagged as tentative.
INFOInformationNo cash movement. Informational entry only. Do not create cash receipts.
FUTRFutureFuture-dated transaction. Queue for application when the settlement date arrives.

Default on creation: Set by the parser from the <Sts> element of the bank file entry. PDNG for CAMT.052 files; BOOK for CAMT.053 files.


5.3 CASH_RECEIPT_STATUS (bank_transaction.cash_receipt_status)

CodeDescriptionBehavior / When Used
UNMATCHEDNo cash receipt created from this transactionDefault state on transaction creation. Transaction is available for cash receipt creation.
MATCHEDCash receipt created and fully linkedReceipt amount equals transaction amount. Transaction is fully reconciled.
PARTIALCash receipt created but partially covers transactionReceipt amount is less than transaction amount. Additional receipts may be created to cover the remainder.

Default on creation: UNMATCHED


5.4 REVERSAL_STATUS (bank_transaction.reversal_status)

CodeDescriptionBehavior / When Used
PENDINGReversal detected, awaiting reviewSet on all reversal transactions at parse time. Requires human review before downstream effects are applied.
ACCEPTEDReversal accepted by a userDownstream cash application review proceeds. reversal_accepted_at and reversal_accepted_by are set.
REJECTEDReversal rejected by a userNo downstream action. Transaction treated as non-actionable.

Default on creation: PENDING (applies only to transactions where is_reversal = 1).


5.5 ISO20022_BALANCE_TYPE (bank_file_balance.balance_type)

CodeDescriptionBehavior / When Used
OPBDOpening Booked BalanceReconciliation anchor — must match the prior statement's CLBD. Found as the first balance in CAMT.053 files.
CLBDClosing Booked BalanceEnd-of-day settled cash position for reporting. Found as the final balance in CAMT.053 files.
OPAVOpening Available BalanceLiquidity available at day start.
CLAVClosing Available BalanceEnd-of-day available liquidity.
ITBDInterim Booked BalanceReal-time settled position during the day. Found in CAMT.052 intraday files.
ITAVInterim Available BalanceReal-time spendable cash during the day. Found in CAMT.052 intraday files.
FWAVForward Available BalanceFuture projected availability for forecasting.
PRCDPreviously Closed BalancePrior period closing balance for audit reference.

Default on creation: Not defaulted; derived from <Bal><Tp><CdOrPrtry><Cd> in file content.


5.6 ISO20022_FAMILY (bank_transaction.family_code)

CodeDescriptionBehavior / When Used
RCDTReceived Credit TransferCREDIT direction. Primary family for incoming deposits — match to open invoices.
ICDTIssued Credit TransferDEBIT direction. Outgoing payments — not used for receivables matching.
RDDTReceived Direct DebitDEBIT direction. Someone pulled from UTA's account.
IDDTIssued Direct DebitCREDIT direction. UTA pulled from a customer's account as a collection method.

Default on creation: Not defaulted; derived from <BkTxCd><Domn><Fmly><Cd> in file content.


5.7 ISO20022_SUBFAMILY (bank_transaction.sub_family_code)

CodeDescriptionBehavior / When Used
DMCTDomestic Credit TransferHigh-value, same-day funds. Match by reference.
XBCTCross-Border Credit TransferInternational wire. Watch for FX conversion.
APACACH Pre-Authorized CreditPredictable timing. Good candidate for auto-matching.
ACDTACH Credit1–2 day settlement. Match by ACH trace number.
ATXNACH TransactionCheck direction indicator to determine nature.
BOOKBook TransferMay be an internal transfer rather than a customer payment.
STDOStanding OrderScheduled disbursement.
RVSLReversalCritical — represents a reversal of a prior payment. Requires unapplication from receivables.
ARETACH ReturnCritical — ACH payment bounced. Requires reversal of cash application and reopening of the invoice.
NTAVNot AvailableManual review required.
CCHQCertified ChequeMay have a hold period before funds are available.
PRCTPriority Credit TransferSame-day wire. High value.
SALASalary PaymentUsually not a customer payment.
ESCTExpress Credit TransferExpedited transfer with fast settlement.

Default on creation: Not defaulted; derived from <BkTxCd><Domn><Fmly><SubFmlyCd> in file content.

WARNING

RVSL (Reversal) and ARET (ACH Return) sub-family codes represent critical financial events. Both require immediate investigation: any cash receipt created from the original transaction must be reviewed, and any cash application must be considered for reversal.


5.8 BAI Codes (bank_code_mapping where bank_code_type = 'BAI_CODE')

BAI codes are bank-specific transaction type codes stored in <BkTxCd><Prtry><Cd> with issuer BAI. They are stored in bank_code_mapping with a bank_id and optionally mapped to a universal ISO20022_SUBFAMILY code. The gatekeeper filter accepts only BAI codes 165, 195, and 208.

Bank of America (BOFA):

CodeNameDirectionUniversal Code
165Preauthorized ACH CreditCREDITAPAC
169Miscellaneous ACH CreditCREDITACDT
195Incoming Wire TransferCREDITDMCT
208Incoming International WireCREDITXBCT
255Check DepositCREDITCCHQ
399Miscellaneous CreditCREDIT
451ACH Debit ReceivedDEBITATXN
469Miscellaneous ACH DebitDEBITATXN
495Outgoing Wire TransferDEBITDMCT
508Outgoing International WireDEBITXBCT
527Standing Order DebitDEBITSTDO
699Miscellaneous DebitDEBIT

JPMorgan Chase (JPM):

CodeNameDirectionUniversal Code
165Preauthorized ACH CreditCREDITAPAC
169Miscellaneous ACH CreditCREDITACDT
195Incoming Wire TransferCREDITDMCT
208Incoming International WireCREDITXBCT
255Check DepositCREDITCCHQ
475ACH DebitDEBITATXN
495Outgoing Wire TransferDEBITDMCT
508Outgoing International WireDEBITXBCT

Default on creation: Not applicable. BAI codes are seeded reference data managed in bank_code_mapping, not set at transaction parse time.


5.9 File Grouping Matching Criteria (bank_file_group.matching_criteria)

CodeDescriptionBehavior / When Used
AUTOAutomatic matchSystem matched CAMT.052 to CAMT.053 using source_bank_id + bank_account_id + statement_date. Applied during CAMT.053 upload.
MANUALManual associationUser explicitly associated a CAMT.052 file with a CAMT.053 file. Used when auto-grouping fails to find a match.

Default on creation: AUTO when created by the system during file processing; MANUAL when created by a user action.


6. Cross-References

DocumentRelationship
Cash Receipts Data Modelbank_transaction.bank_transaction_id is optionally stored on cash_receipt.bank_transaction_id as an audit trail back to the originating bank data. bank_transaction.cash_receipt_status tracks whether a receipt has been created.
Worksheets Data ModelWorksheets are created downstream of cash receipts, which originate from bank transactions. No direct FK from worksheets to bank ingestion tables.
Accounting Data ModelBank balance records in bank_file_balance are used for daily cash position reporting and GL reconciliation anchoring.
Parties Data Modelbank_account (FK target throughout this domain) is a shared reference table; party_bank_account links parties to their bank accounts for outbound payments.

Confidential. For internal use only.