COPAUA0C
Source: app-authorization-ims-db2-mq/cbl/COPAUA0C.cbl
Type: CICS transaction program
COPAUA0C — Card Authorization Decision Program
Purpose
COPAUA0C is a CICS/IMS/MQ program that processes card authorization requests received via MQ, decides whether to approve or decline each transaction based on available credit, and sends an authorization response back to the requesting queue. It is the core decisioning engine in the CardDemo authorization flow, checking the card cross-reference, account, customer, and pending-authorization data before rendering a decision. It also persists authorization activity (summary balances and detail records) to an IMS database for later reconciliation.
How it works
- MAIN-PARA drives the whole program:
1000-INITIALIZE→2000-MAIN-PROCESS→9000-TERMINATE, then issuesEXEC CICS RETURN. - 1000-INITIALIZE: Retrieves CICS start-up data (
EXEC CICS RETRIEVE INTO MQTM) to get the request queue name and trigger data, sets an MQ wait interval (5000), opens the request queue (1100-OPEN-REQUEST-QUEUE, viaMQOPEN), then does a first read from the queue (3100-READ-REQUEST-MQ). - 2000-MAIN-PROCESS loops (
PERFORM UNTIL NO-MORE-MSG-AVAILABLE OR WS-LOOP-END): 2100-EXTRACT-REQUEST-MSGunstrings the raw MQ message text (comma-delimited) into thePENDING-AUTH-REQUESTfields (date, time, card number, auth type, amount, merchant details, etc.) and converts the amount text to numeric viaFUNCTION NUMVAL.5000-PROCESS-AUTHperforms the actual authorization logic (see below).- The program increments a processed-message counter, issues
EXEC CICS SYNCPOINTto commit the unit of work, resets the IMS PSB-scheduled flag, and either stops the loop (afterWS-REQSTS-PROCESS-LIMIT= 500 messages) or reads the next message. - 5000-PROCESS-AUTH — the core decision path:
- Assumes approval (
APPROVE-AUTH), then schedules the IMS PSB (1200-SCHEDULE-PSB). - Looks up the card in the cross-reference file (
5100-READ-XREF-RECORD). - If found, reads the account master (
5200-READ-ACCT-RECORD), customer master (5300-READ-CUST-RECORD), the IMS pending-authorization summary segment (5500-READ-AUTH-SUMMRY), and a currently empty profile-data hook (5600-READ-PROFILE-DATA, justCONTINUE). 6000-MAKE-DECISIONcomputes available credit (from the IMS summary segment if found, else from the account master) and compares it to the transaction amount to approve or decline, setting response codes and reason codes, then builds the pipe/comma-delimited response string.7100-SEND-RESPONSEsends this response to the reply queue viaMQPUT1.- If the card was found in xref,
8000-WRITE-AUTH-TO-DBupdates the IMS summary segment (8400-UPDATE-SUMMARY) and inserts a new detail segment (8500-INSERT-AUTH). - 9000-TERMINATE closes the request MQ queue (
9100-CLOSE-REQUEST-QUEUEviaMQCLOSE). - 9500-LOG-ERROR is the common error-logging paragraph, invoked from nearly every I/O step; it performs
9990-END-ROUTINE, which itself performs9000-TERMINATE— meaning any logged error triggers program termination, not just a warning message.
Inputs & outputs
| Resource | Type | Purpose |
|---|---|---|
Request MQ queue (name from MQTM-QNAME/trigger data) |
MQ queue | Source of authorization request messages, opened once (MQOPEN), read repeatedly (MQGET) up to 500 times per program invocation |
Reply MQ queue (WS-REPLY-QNAME, from MQMD-REPLYTOQ) |
MQ queue | Destination for the authorization response, written via MQPUT1 |
CCXREF (WS-CCXREF-FILE) |
CICS file (VSAM) | Card cross-reference lookup: card number → customer ID / account ID (CVACT03Y layout) |
ACCTDAT (WS-ACCTFILENAME) |
CICS file (VSAM) | Account master record — credit limit, current balance (CVACT01Y layout) |
CUSTDAT (WS-CUSTFILENAME) |
CICS file (VSAM) | Customer master record (CVCUS01Y layout) |
CARDDAT / CARDAIX (WS-CARDFILENAME, WS-CARDFILENAME-ACCT-PATH) |
CICS file names declared but not referenced in any EXEC CICS READ in this program (dead/unused declarations as far as parsed facts show) |
|
IMS database via PSB PSBPAUTB |
IMS DB (DL/I) | PAUTSUM0 root segment (pending authorization summary — credit limit/balance) read (GU) and updated; child detail segment (PENDING-AUTH-DETAILS/CIPAUDTY) inserted for each processed authorization |
CCPAURQY / CCPAURLY copybooks |
In-memory layouts | Request and response message formats used to parse the MQ message and build the reply string |
CCPAUERY copybook |
In-memory layout | Error log record layout (ERR-LOCATION, ERR-MESSAGE, ERR-CODE-1/2, ERR-EVENT-KEY) used by 9500-LOG-ERROR |
CMQODV, CMQMDV, CMQV, CMQTML, CMQPMOV, CMQGMOV copybooks |
MQ control structures | Object descriptors, message descriptors, constants, trigger data, put/get message options for MQOPEN/MQGET/MQPUT1/MQCLOSE calls |
Things to know
- Errors are fatal by design.
9500-LOG-ERRORalways performs9990-END-ROUTINE, which performs9000-TERMINATE. This means even a single MQ, CICS, or IMS error during processing (e.g., aNOTFNDon account read, classified as a "warning") still routes through logic that closes the queue and ends the program — worth verifying this is the intended behavior versus just logging and continuing, since the code sets warning-severity flags (ERR-WARNING) but the shared clean-up path still runs. - Hard-coded values: PSB name
PSBPAUTB, transaction IDCP00, file names (ACCTDAT,CUSTDAT,CARDDAT,CARDAIX,CCXREF), message batch limit of 500 (WS-REQSTS-PROCESS-LIMIT), MQ wait interval of 5000 (ms, presumably), MQ message expiry of 50, and decline reason codes (3100,4100,4200,4300,5100,5200,9000) are all embedded directly in the code rather than externalized/configurable. - Message parsing is fragile:
2100-EXTRACT-REQUEST-MSGuses a straightUNSTRING ... DELIMITED BY ','against the raw MQ payload with a fixed field order. Any change to the upstream message format (extra/missing commas, reordered fields) will silently misalign data into the wrong fields, with no validation shown. - Fraud/profile-based decline reasons are declared but not populated. The
WS-DECLINE-REASON-FLGhas 88-level conditions forCARD-NOT-ACTIVE,ACCOUNT-CLOSED,CARD-FRAUD,MERCHANT-FRAUD, and6000-MAKE-DECISIONevaluates them, but nothing in the shown code ever sets these conditions (onlyINSUFFICIENT-FUNDis set) —5600-READ-PROFILE-DATAis an empty stub (CONTINUE), suggesting fraud/profile checks are planned but not yet implemented. - PSB scheduling retry logic:
1200-SCHEDULE-PSBretries the DL/ISCHDonce if the PSB is already scheduled (PSB-SCHEDULED-MORE-THAN-ONCE), issuing aTERMfirst. Other IMS failure conditions (RETRY-CONDITION88-level:BA,FH,TE) are defined but do not appear to trigger any retry — only logged as critical errors. - Two files declared but seemingly unused:
CARDDATandCARDAIXfilenames are set up in working storage but noEXEC CICS READagainst them appears in the source shown — potentially vestigial from a related program, or used in a portion of the source not included here. - Decision logic depends on data source precedence: if an IMS pending-auth summary segment exists, its credit limit/balance is used; otherwise the account master's credit limit/balance is used. If the account isn't found at all, the authorization is unconditionally declined. Confirm this fallback hierarchy matches business intent, since IMS summary data and account master data could theoretically disagree.
- Unit-of-work boundary:
EXEC CICS SYNCPOINTis issued after each message is processed (commit per message), and the IMS PSB-scheduled flag is manually reset (IMS-PSB-NOT-SCHD) afterward — implying the PSB must be freshly rescheduled for every message, which happens in5000-PROCESS-AUTHvia1200-SCHEDULE-PSB.
CICS commands
RETURN, RETRIEVE, READ, ASKTIME NOHANDLE, FORMATTIME, WRITEQ
Copybooks
CCPAUERY, CCPAURLY, CCPAURQY, CIPAUDTY, CIPAUSMY, CMQGMOV, CMQMDV, CMQODV, CMQPMOV, CMQTML, CMQV, CVACT01Y, CVACT03Y, CVCUS01Y
Calls
MQCLOSE, MQGET, MQOPEN, MQPUT1
Paragraph flow
flowchart TD
MAIN_PARA["MAIN-PARA"]
1000_INITIALIZE["1000-INITIALIZE"]
1000_EXIT["1000-EXIT"]
1100_OPEN_REQUEST_QUEUE["1100-OPEN-REQUEST-QUEUE"]
1100_EXIT["1100-EXIT"]
1200_SCHEDULE_PSB["1200-SCHEDULE-PSB"]
1200_EXIT["1200-EXIT"]
2000_MAIN_PROCESS["2000-MAIN-PROCESS"]
2000_EXIT["2000-EXIT"]
2100_EXTRACT_REQUEST_MSG["2100-EXTRACT-REQUEST-MSG"]
2100_EXIT["2100-EXIT"]
3100_READ_REQUEST_MQ["3100-READ-REQUEST-MQ"]
3100_EXIT["3100-EXIT"]
5000_PROCESS_AUTH["5000-PROCESS-AUTH"]
5000_EXIT["5000-EXIT"]
5100_READ_XREF_RECORD["5100-READ-XREF-RECORD"]
5100_EXIT["5100-EXIT"]
5200_READ_ACCT_RECORD["5200-READ-ACCT-RECORD"]
5200_EXIT["5200-EXIT"]
5300_READ_CUST_RECORD["5300-READ-CUST-RECORD"]
5300_EXIT["5300-EXIT"]
5500_READ_AUTH_SUMMRY["5500-READ-AUTH-SUMMRY"]
5500_EXIT["5500-EXIT"]
5600_READ_PROFILE_DATA["5600-READ-PROFILE-DATA"]
5600_EXIT["5600-EXIT"]
6000_MAKE_DECISION["6000-MAKE-DECISION"]
6000_EXIT["6000-EXIT"]
7100_SEND_RESPONSE["7100-SEND-RESPONSE"]
7100_EXIT["7100-EXIT"]
8000_WRITE_AUTH_TO_DB["8000-WRITE-AUTH-TO-DB"]
8000_EXIT["8000-EXIT"]
8400_UPDATE_SUMMARY["8400-UPDATE-SUMMARY"]
8400_EXIT["8400-EXIT"]
8500_INSERT_AUTH["8500-INSERT-AUTH"]
8500_EXIT["8500-EXIT"]
9000_TERMINATE["9000-TERMINATE"]
9000_EXIT["9000-EXIT"]
9100_CLOSE_REQUEST_QUEUE["9100-CLOSE-REQUEST-QUEUE"]
9100_EXIT["9100-EXIT"]
9500_LOG_ERROR["9500-LOG-ERROR"]
9500_EXIT["9500-EXIT"]
9990_END_ROUTINE["9990-END-ROUTINE"]
9990_EXIT["9990-EXIT"]
1000_INITIALIZE --> 1100_OPEN_REQUEST_QUEUE
1000_INITIALIZE --> 3100_READ_REQUEST_MQ
1100_OPEN_REQUEST_QUEUE --> 9500_LOG_ERROR
1200_SCHEDULE_PSB --> 9500_LOG_ERROR
2000_MAIN_PROCESS --> 2100_EXTRACT_REQUEST_MSG
2000_MAIN_PROCESS --> 3100_READ_REQUEST_MQ
2000_MAIN_PROCESS --> 5000_PROCESS_AUTH
3100_READ_REQUEST_MQ --> 9500_LOG_ERROR
5000_PROCESS_AUTH --> 1200_SCHEDULE_PSB
5000_PROCESS_AUTH --> 5100_READ_XREF_RECORD
5000_PROCESS_AUTH --> 5200_READ_ACCT_RECORD
5000_PROCESS_AUTH --> 5300_READ_CUST_RECORD
5000_PROCESS_AUTH --> 5500_READ_AUTH_SUMMRY
5000_PROCESS_AUTH --> 5600_READ_PROFILE_DATA
5000_PROCESS_AUTH --> 6000_MAKE_DECISION
5000_PROCESS_AUTH --> 7100_SEND_RESPONSE
5000_PROCESS_AUTH --> 8000_WRITE_AUTH_TO_DB
5100_READ_XREF_RECORD --> 9500_LOG_ERROR
5200_READ_ACCT_RECORD --> 9500_LOG_ERROR
5300_READ_CUST_RECORD --> 9500_LOG_ERROR
5500_READ_AUTH_SUMMRY --> 9500_LOG_ERROR
7100_SEND_RESPONSE --> 9500_LOG_ERROR
8000_WRITE_AUTH_TO_DB --> 8400_UPDATE_SUMMARY
8000_WRITE_AUTH_TO_DB --> 8500_INSERT_AUTH
8400_UPDATE_SUMMARY --> 9500_LOG_ERROR
8500_INSERT_AUTH --> 9500_LOG_ERROR
9000_TERMINATE --> 9100_CLOSE_REQUEST_QUEUE
9100_CLOSE_REQUEST_QUEUE --> 9500_LOG_ERROR
9500_LOG_ERROR --> 9990_END_ROUTINE
9990_END_ROUTINE --> 9000_TERMINATE
MAIN_PARA --> 1000_INITIALIZE
MAIN_PARA --> 2000_MAIN_PROCESS
MAIN_PARA --> 9000_TERMINATE
Paragraphs
| Paragraph | Line | Performs |
|---|---|---|
| MAIN-PARA | 220 | 1000-INITIALIZE, 2000-MAIN-PROCESS, 9000-TERMINATE |
| 1000-INITIALIZE | 230 | 1100-OPEN-REQUEST-QUEUE, 3100-READ-REQUEST-MQ |
| 1000-EXIT | 249 | |
| 1100-OPEN-REQUEST-QUEUE | 255 | 9500-LOG-ERROR |
| 1100-EXIT | 286 | |
| 1200-SCHEDULE-PSB | 292 | 9500-LOG-ERROR |
| 1200-EXIT | 319 | |
| 2000-MAIN-PROCESS | 323 | 2100-EXTRACT-REQUEST-MSG, 5000-PROCESS-AUTH, 3100-READ-REQUEST-MQ |
| 2000-EXIT | 347 | |
| 2100-EXTRACT-REQUEST-MSG | 351 | |
| 2100-EXIT | 382 | |
| 3100-READ-REQUEST-MQ | 386 | 9500-LOG-ERROR |
| 3100-EXIT | 434 | |
| 5000-PROCESS-AUTH | 438 | 1200-SCHEDULE-PSB, 5100-READ-XREF-RECORD, 5200-READ-ACCT-RECORD, 5300-READ-CUST-RECORD, 5500-READ-AUTH-SUMMRY, 5600-READ-PROFILE-DATA |
| 5000-EXIT | 468 | |
| 5100-READ-XREF-RECORD | 472 | 9500-LOG-ERROR, 9500-LOG-ERROR |
| 5100-EXIT | 516 | |
| 5200-READ-ACCT-RECORD | 520 | 9500-LOG-ERROR, 9500-LOG-ERROR |
| 5200-EXIT | 564 | |
| 5300-READ-CUST-RECORD | 568 | 9500-LOG-ERROR, 9500-LOG-ERROR |
| 5300-EXIT | 612 | |
| 5500-READ-AUTH-SUMMRY | 616 | 9500-LOG-ERROR |
| 5500-EXIT | 643 | |
| 5600-READ-PROFILE-DATA | 647 | |
| 5600-EXIT | 653 | |
| 6000-MAKE-DECISION | 657 | |
| 6000-EXIT | 734 | |
| 7100-SEND-RESPONSE | 738 | 9500-LOG-ERROR |
| 7100-EXIT | 782 | |
| 8000-WRITE-AUTH-TO-DB | 786 | 8400-UPDATE-SUMMARY, 8500-INSERT-AUTH |
| 8000-EXIT | 794 | |
| 8400-UPDATE-SUMMARY | 798 | 9500-LOG-ERROR |
| 8400-EXIT | 850 | |
| 8500-INSERT-AUTH | 854 | 9500-LOG-ERROR |
| 8500-EXIT | 935 | |
| 9000-TERMINATE | 940 | 9100-CLOSE-REQUEST-QUEUE |
| 9000-EXIT | 950 | |
| 9100-CLOSE-REQUEST-QUEUE | 953 | 9500-LOG-ERROR |
| 9100-EXIT | 979 | |
| 9500-LOG-ERROR | 983 | 9990-END-ROUTINE |
| 9500-EXIT | 1012 | |
| 9990-END-ROUTINE | 1016 | 9000-TERMINATE |
| 9990-EXIT | 1024 |