🔗 Module: Card Cross-Reference

ID: card-crossref  |  Legacy Source: CBACT03C.cbl + bridge.py:get_all_crossref() + Flask GET /crossref

This guide covers the Card Cross-Reference module — a read-only view that maps credit card numbers to customer IDs and account IDs. It replaces the COBOL batch program CBACT03C which read cardxref.txt (50-byte fixed-width records) and emitted pipe-delimited XREF03| lines. The new system stores this data in the card_customer_xref relational table.

🏗️ Technical Foundation

LayerTarget ComponentLegacy Equivalent
API ControllerCardsController.csFlask GET /crossref
Application QueryListCardCrossRefQuery.cs + ListCardCrossRefQueryHandler.csbridge.py:get_all_crossref()
Response DTOCardCrossRefDto.csXREF03|card-num|cust-id|acct-id stream lines from CBACT03C
Data AccessEF Core: CardCustomerXref table (PostgreSQL)Sequential read of cardxref.txt (50-byte records, CVACT03Y layout)
React PageCrossRefPage.tsxtemplates/crossref.html (Jinja2)
React ComponentCrossRefTable.tsxHTML table in crossref.html
React HookuseCardCrossRef.ts (TanStack Query)Server-side render

🌐 Public APIs

GET /api/cards/crossref

Returns a paginated list of all card-to-customer-to-account cross-reference entries. Replaces CBACT03C full sequential scan.

Query Parameters

ParameterTypeDefaultDescription
pageint1Page number
pageSizeint50Results per page
accountIdlongFilter by account ID
customerIdintFilter by customer ID

Response Shape

{
  "data": [
    {
      "cardNumber": "4111111111111111",
      "customerId": 111111111,
      "accountId": 4000000111
    }
  ],
  "page": 1,
  "pageSize": 50,
  "totalCount": 1200,
  "totalPages": 24
}
GET /api/cards/{cardNumber}/crossref

Returns the single cross-reference entry for a specific card number. Returns 404 if not found.

// Response
{
  "cardNumber": "4111111111111111",
  "customerId": 111111111,
  "accountId": 4000000111
}

📐 Data Model Involved

// CVACT03Y layout → CardCustomerXref table
// Legacy: 50-byte fixed record: XREF-CARD-NUM(16) + XREF-CUST-ID(9) + XREF-ACCT-ID(11) + FILLER(14)

public class CardCustomerXref
{
    public string CardNumber { get; set; }    // PK, FK → cards.card_number
    public int CustomerId { get; set; }       // FK → customers.id
    public long AccountId { get; set; }       // FK → accounts.id
}

public record CardCrossRefDto(
    string CardNumber,
    int CustomerId,
    long AccountId
);

🎯 User Story Development Patterns

US-CR-01 · View Full Card Cross-Reference Table (3 pts)
As a bank clerk, I want to view a paginated list of all card-to-account cross-reference entries so that I can trace which card belongs to which account and customer.
US-CR-02 · Filter Cross-Reference by Account (2 pts)
As a bank clerk, I want to filter the cross-reference table by account ID so that I can see all cards linked to a specific account.
US-CR-03 · Lookup Cross-Reference for a Single Card (2 pts)
As a bank clerk, I want to look up the account and customer linked to a specific card number so that I can quickly resolve customer inquiries about a particular card.
US-CR-04 · Card Number Masking in UI (1 pt)
As a compliance officer, I want card numbers displayed in the cross-reference table to be masked (showing only first 4 and last 4 digits) so that full PAN data is not exposed on-screen unnecessarily.

📊 Story Complexity Guidelines

PointsExample
1–2Change column order. Add card number masking. Add "Copy Account ID" button.
3–5Add multi-column filtering (account + customer). Add CSV export of cross-reference data.
8+Full card lifecycle management (activate, deactivate cards) requiring write endpoints and domain logic.

⚡ Performance Requirements