Loading...
This document describes how data moves through the AWS CardDemo application from a technical perspective, including transaction flows, batch processing flows, and data transformations across system components.
The CardDemo application has four primary data flow categories:
Data Elements:
Technical Details:
Data Transformation:
Input: ACCT-ID (11 digits)
↓
Query: ACCTDAT → Account Record (300 bytes)
CUSTDAT → Customer Record (500 bytes)
CCXREF (AIX) → Card Numbers (multiple)
CARDDAT → Card Details (150 bytes each)
↓
Output: Formatted BMS map with:
- Account balances
- Customer name/address
- List of cards with status
Performance Characteristics:
Data Transformations:
Input Data (Terminal):
├── Card-Num: X(16)
├── Amount: S9(09)V99
├── Type: X(02)
├── Category: 9(04)
└── Description: X(100)
Processing:
├── Lookup: Card → Account (CCXREF)
├── Generate: TRAN-ID (timestamp + sequence)
├── Calculate: New Balance = Old Balance + Amount
├── Calculate: Cycle Debit/Credit += Amount
└── Calculate: Category Balance += Amount
Output Data:
├── TRANSACT Record (350 bytes)
├── ACCTDAT Record (updated)
├── TCATBALF Record (updated/created)
└── Screen: Confirmation message
ACID Properties:
Validation Rules:
Valid Status Values: 'A' (Active), 'C' (Closed), 'S' (Suspended)
Expiry Date: Must be future date (YYYY-MM-DD)
Card Number: No changes allowed (primary key)
Account ID: No changes allowed (referential integrity)
Processing Logic:
FOR EACH record in DALYTRAN:
1. Read transaction record
2. Parse and validate fields
3. Lookup card in CCXREF (KEY = CARD-NUM)
→ Get ACCT-ID, CUST-ID
4. Read account in ACCTDAT (KEY = ACCT-ID)
→ Get current balances, limits
5. Validate transaction:
- Account status = 'A' (active)
- Amount ≠ 0
- Type code valid
6. Generate unique TRAN-ID:
TRAN-ID = YYYY-MM-DD + HH-MM-SS + NNNN (sequence)
7. Build transaction record:
- Copy input fields
- Add TRAN-ID
- Set TRAN-PROC-TS = current timestamp
8. Write to TRANSACT file
9. Update ACCTDAT:
IF TRAN-AMT > 0 (Debit):
ACCT-CURR-BAL += TRAN-AMT
ACCT-CURR-CYC-DEBIT += TRAN-AMT
ELSE (Credit):
ACCT-CURR-BAL += TRAN-AMT (negative)
ACCT-CURR-CYC-CREDIT += ABS(TRAN-AMT)
10. Update TCATBALF:
KEY = ACCT-ID + TRAN-TYPE + TRAN-CAT
IF exists:
TRAN-CAT-BAL += TRAN-AMT
ELSE:
Create new record with TRAN-AMT
11. Commit (checkpoint every 100 records)
12. Write statistics to report
Data Volume:
Error Handling:
Error Types:
├── Invalid Card Number → Write to error file with code E001
├── Inactive Account → Write to error file with code E002
├── Invalid Amount → Write to error file with code E003
├── Invalid Type Code → Write to error file with code E004
└── File I/O Error → Abend with U0100
Error File Format:
Original Record (350 bytes) + Error Code (4 bytes) + Error Message (100 bytes)
Processing Algorithm:
1. Read TCATBALF sequentially (by account)
2. For each account:
a. Group categories by account
b. Read ACCTDAT for account details
c. Get discount group from ACCT-GROUP-ID
d. For each category balance:
i. Read DISCGRP (KEY = GROUP-ID + TYPE + CAT)
ii. Calculate interest:
Interest = Balance * (Rate / 100) / 12
iii. Apply business rules:
- Minimum interest: $1.00
- Round to nearest cent
- Cap at maximum (if defined)
iv. Create transaction record:
TRAN-TYPE = '05' (Interest)
TRAN-AMT = Calculated Interest
TRAN-DESC = "Interest Charge - " + Category
v. Create fee record (if applicable):
TRAN-TYPE = '04' (Fee)
TRAN-AMT = Fee Amount
TRAN-DESC = "Account Fee - " + Category
vi. Write to SYSTRAN(+1)
e. Update account totals (in memory)
3. Write summary report
4. Close files
Calculation Example:
Account: 12345678901
Category Balance: $1,000.00
Transaction Type: 01 (Purchase)
Discount Group: STANDARD
Interest Rate: 18.00% APR
Calculation:
Monthly Rate = 18.00% / 12 = 1.5%
Interest = $1,000.00 * 0.015 = $15.00
Output Transaction:
TRAN-ID: 2023-12-01-00-00-01-0001
TRAN-TYPE: 05
TRAN-CAT: 0001
TRAN-AMT: +15.00
TRAN-DESC: Interest Charge - Purchases
Performance:
Data Collection:
-- Pseudo-code (COBOL batch logic)
FOR EACH account IN ACCTDAT WHERE statement-due:
1. Account Information:
READ ACCTDAT (KEY = ACCT-ID)
Extract:
├── Account Number
├── Previous Balance
├── Current Balance
├── Credit Limit
├── Available Credit
├── Payment Due Date
└── Minimum Payment Due
2. Customer Information:
READ CUSTDAT (KEY = CUST-ID from account)
Extract:
├── Customer Name (First, Middle, Last)
├── Billing Address
├── City, State, ZIP
└── Phone Numbers
3. Transaction Details:
BROWSE TRANSACT (AIX = TRAN-PROC-TS)
WHERE:
CARD-NUM in account's cards AND
TRAN-PROC-TS between cycle start and end
For each transaction:
├── Date
├── Description
├── Merchant
├── Amount
└── Type (Purchase, Payment, Fee, Interest)
4. Card Information:
BROWSE CCXREF (AIX = ACCT-ID)
WHERE XREF-ACCT-ID = ACCT-ID
For each card:
├── Card Number (masked)
├── Card Holder Name
├── Expiration Date
└── Status
5. Calculate Summary:
Previous Balance: From ACCTDAT
+ Purchases: Sum of type '01' transactions
+ Cash Advances: Sum of type '02' transactions
+ Fees: Sum of type '04' transactions
+ Interest: Sum of type '05' transactions
- Payments: Sum of type '03' transactions (negative)
= New Balance: Current balance from ACCTDAT
Minimum Payment: MAX(25.00, Balance * 0.02)
Payment Due Date: Cycle date + 25 days
6. Format Statement:
├── Header (Account, Customer, Date)
├── Account Summary
├── Payment Information
├── Transaction Detail (sorted by date)
├── Year-to-Date Summary
└── Footer (Disclosure, Contact Info)
7. Write Statement:
WRITE to SYSOUT (print file)
Format: 132-byte records (line printer)
Statement Layout:
┌────────────────────────────────────────────────────────┐
│ CREDIT CARD STATEMENT │
│ │
│ Account: XXXX-XXXX-XXXX-1234 Statement Date: 12/01 │
│ John Q. Customer Payment Due: 12/26 │
│ 123 Main Street Minimum Due: $25.00 │
│ Anytown, CA 94101 │
├────────────────────────────────────────────────────────┤
│ ACCOUNT SUMMARY │
│ Previous Balance: $1,234.56 │
│ Purchases: +567.89 │
│ Cash Advances: +100.00 │
│ Fees: +35.00 │
│ Interest Charges: +18.50 │
│ Payments: -500.00 │
│ ──────────────────────────────────────── │
│ New Balance: $1,455.95 │
│ │
│ Credit Limit: $5,000.00 │
│ Available Credit: $3,544.05 │
├────────────────────────────────────────────────────────┤
│ TRANSACTION DETAILS │
│ Date Description Amount │
│ 11/05 ACME GROCERY $67.89 │
│ 11/08 PAYMENT - THANK YOU -$500.00 │
│ 11/12 GAS STATION $45.00 │
│ ... │
└────────────────────────────────────────────────────────┘
Processing Steps Detail:
1. Message Receipt:
- MQ Trigger fires on message arrival
- CICS starts transaction CP00
- Program COPAUA0C begins execution
2. Message Parsing:
Input CSV: 18 fields
Parse into working storage:
├── AUTH-DATE (8 bytes)
├── AUTH-TIME (6 bytes)
├── CARD-NUM (16 bytes)
├── AUTH-TYPE (4 bytes)
├── CARD-EXPIRY-DATE (4 bytes)
├── MESSAGE-TYPE (6 bytes)
├── MESSAGE-SOURCE (6 bytes)
├── PROCESSING-CODE (6 bytes)
├── TRANSACTION-AMT (12 bytes)
├── MERCHANT-CATAGORY-CODE (4 bytes)
├── ACQR-COUNTRY-CODE (3 bytes)
├── POS-ENTRY-MODE (3 bytes)
├── MERCHANT-ID (15 bytes)
├── MERCHANT-NAME (22 bytes)
├── MERCHANT-CITY (13 bytes)
├── MERCHANT-STATE (2 bytes)
├── MERCHANT-ZIP (9 bytes)
└── TRANSACTION-ID (15 bytes)
3. Card Validation:
READ CCXREF (KEY = CARD-NUM)
IF not found:
Response = '05' (Do Not Honor)
GOTO 8. Build Response
ELSE:
Save ACCT-ID, CUST-ID
4. Card Status Check:
READ CARDDAT (KEY = CARD-NUM)
IF CARD-ACTIVE-STATUS ≠ 'A':
Response = '05' (Do Not Honor)
GOTO 8. Build Response
IF CARD-EXPIRATION-DATE < Current Date:
Response = '54' (Expired Card)
GOTO 8. Build Response
5. Account Validation:
READ ACCTDAT (KEY = ACCT-ID)
IF ACCT-ACTIVE-STATUS ≠ 'A':
Response = '05' (Do Not Honor)
GOTO 8. Build Response
6. Limit Check:
Available Credit = ACCT-CREDIT-LIMIT - ACCT-CURR-BAL
IF TRANSACTION-AMT > Available Credit:
Response = '51' (Insufficient Funds)
GOTO 8. Build Response
7. Fraud Detection:
Apply business rules:
├── Large transaction (> $5,000)?
├── Foreign country code?
├── Unusual merchant category?
├── Multiple transactions in short time?
└── Velocity check (transactions per day)
IF suspected fraud:
Set FRAUD-FLAG = 'Y'
INSERT into DB2 AUTHFRDS table
8. Store Authorization (IMS):
Generate AUTH-ID = 'AUTH' + timestamp
IMS DL/I Calls:
a. GU PAUTSUM0 (Account Summary)
IF not found (GE):
ISRT PAUTSUM0 (Create Summary)
b. ISRT PAUTDTL1 (Authorization Detail)
Parent: PAUTSUM0
Data:
├── AUTH-DATE-9C (compressed)
├── AUTH-TIME-9C (compressed)
├── CARD-NUM
├── AUTH-TYPE
├── TRANSACTION-AMT
├── APPROVED-AMT
├── MERCHANT info
└── TRANSACTION-ID
9. Build Response:
Response CSV: 6 fields
├── CARD-NUM (from request)
├── TRANSACTION-ID (from request)
├── AUTH-ID-CODE (generated)
├── AUTH-RESP-CODE (00, 05, 51, 54, 61)
├── AUTH-RESP-REASON (APPR, DECL, NSUF, EXPR)
└── APPROVED-AMT (transaction amount or 0)
10. Send Response:
PUT message to MQ Reply Queue
Set correlation ID = request message ID
11. Clean Up:
Commit CICS unit of work
Return to CICS
Response Codes:
Code | Reason | Triggered By
-----|------------------|------------------------------------------
00 | Approved | All validations pass
05 | Do Not Honor | Card not found, inactive, account closed
51 | Insufficient | Transaction exceeds available credit
54 | Expired Card | Card past expiration date
61 | Exceeds Limit | Over transaction limit
91 | System Error | Technical failure (file I/O, IMS, etc.)
Performance Targets:
Purge Logic:
Program: CBPAUP0C (IMS Batch Message Processing)
PSB: PSBPAUTB
PCB: DBPAUTP0 (Update mode)
Process:
1. Open IMS databases
2. Set checkpoint frequency = 100 accounts
3. Initialize counters
LOOP through all accounts:
4. Get account summary:
EXEC DLI GU
SEGMENT('PAUTSUM0')
END-EXEC
5. IF not found (GB):
EXIT LOOP
6. Initialize account counters:
├── Auth-Deleted = 0
├── Auth-Remaining = 0
└── Amount-Purged = 0
7. LOOP through authorization details:
EXEC DLI GN
SEGMENT('PAUTDTL1')
END-EXEC
IF not found (GB):
EXIT LOOP
8. Calculate auth age:
Age = Current-Date - PA-AUTH-DATE-9C
9. IF Age > 30 days:
a. Get for update:
EXEC DLI GHU
SEGMENT('PAUTDTL1')
END-EXEC
b. Delete:
EXEC DLI DLET
SEGMENT('PAUTDTL1')
END-EXEC
c. Update counters:
Auth-Deleted += 1
Amount-Purged += PA-APPROVED-AMT
ELSE:
Auth-Remaining += 1
END LOOP (details)
10. Update or delete summary:
IF Auth-Remaining = 0:
a. Get summary for update:
EXEC DLI GHU
SEGMENT('PAUTSUM0')
END-EXEC
b. Delete summary:
EXEC DLI DLET
SEGMENT('PAUTSUM0')
END-EXEC
ELSE:
a. Get summary for update:
EXEC DLI GHU
SEGMENT('PAUTSUM0')
END-EXEC
b. Update summary fields:
PA-APPROVED-AUTH-CNT -= Auth-Deleted
PA-APPROVED-AUTH-AMT -= Amount-Purged
(or DECLINED if declined auths)
c. Replace summary:
EXEC DLI REPL
SEGMENT('PAUTSUM0')
FROM(:PAUTSUM0-SEGMENT)
END-EXEC
11. Increment processed count
12. IF processed count MOD 100 = 0:
EXEC DLI CHKP
END-EXEC
Write checkpoint record
END LOOP (accounts)
13. Write final statistics:
├── Accounts processed
├── Authorizations deleted
├── Summaries deleted
└── Total amount purged
14. Close databases
15. End program
Sync Process:
Job: TRANEXTR (Weekly, Sunday 2:00 AM)
Step 1: DB2 Unload
EXEC PGM=DSNTIAUL
SQL:
SELECT TR_TYPE, TR_DESCRIPTION
FROM CARDDEMO.TRANSACTION_TYPE
ORDER BY TR_TYPE
Output: Sequential file (FB, LRECL=60)
Step 2: Sort
EXEC PGM=SORT
SORT FIELDS=(1,2,CH,A)
Output: Sorted file
Step 3: Transform and Load
EXEC PGM=TRANTRAN (custom COBOL)
FOR EACH record in input:
1. Read DB2 unload record:
├── Type (2 bytes)
└── Description (50 bytes)
2. Transform to VSAM format:
VSAM-TRAN-TYPE = DB2-TR-TYPE
VSAM-TRAN-DESC = DB2-TR-DESCRIPTION
VSAM-TRAN-ACTIVE = 'Y'
VSAM-TRAN-UPDATE-DATE = Current Date
3. READ VSAM TRANTYPE (KEY = Type)
IF found:
REWRITE with new description
Increment UPDATE-COUNT
ELSE:
WRITE new record
Increment INSERT-COUNT
END FOR
Write statistics:
├── Records processed
├── Records updated
├── Records inserted
└── Processing time
Step 4: Backup
IDCAMS REPRO
Copy TRANTYPE to backup dataset
Data Integrity:
| Flow Type | Frequency | Volume | Latency | Complexity |
|---|---|---|---|---|
| User Login | Per session | Low (100s/day) | < 1s | Low |
| Account Inquiry | On demand | Medium (1000s/day) | < 1s | Medium |
| Transaction Add | On demand | Medium (100s/day) | < 2s | High |
| Card Update | On demand | Low (10s/day) | < 1s | Medium |
| Daily Posting | Daily | High (10K/day) | 2-5 min | Medium |
| Interest Calc | Monthly | Very High (500K) | 5-15 min | High |
| Statement Gen | Monthly | High (50K) | 15-30 min | High |
| Authorization | Real-time | High (1000s/hour) | < 2s | High |
| Auth Purge | Daily | High (100K) | 10-20 min | Medium |
| DB2 Sync | Weekly | Low (100s) | 1-2 min | Low |