COPAUA0C
Source: app-authorization-ims-db2-mq/cbl/COPAUA0C.cbl
Type: CICS transaction 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 issues EXEC 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, via MQOPEN), 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-MSG unstrings the raw MQ message text (comma-delimited) into the PENDING-AUTH-REQUEST fields (date, time, card number, auth type, amount, merchant details, etc.) and converts the amount text to numeric via FUNCTION NUMVAL.
-
5000-PROCESS-AUTH performs the actual authorization logic (see below).
-
The program increments a processed-message counter, issues EXEC CICS SYNCPOINT to commit the unit of work, resets the IMS PSB-scheduled flag, and either stops the loop (after WS-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, just CONTINUE).
-
6000-MAKE-DECISION computes 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-RESPONSE sends this response to the reply queue via MQPUT1.
-
If the card was found in xref, 8000-WRITE-AUTH-TO-DB updates 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-QUEUE via MQCLOSE).
-
9500-LOG-ERROR is the common error-logging paragraph, invoked from nearly every I/O step; it performs 9990-END-ROUTINE, which itself performs 9000-TERMINATE — meaning any logged error triggers program termination, not just a warning message.
Inputs & outputs
Things to know
-
Errors are fatal by design. 9500-LOG-ERROR always performs 9990-END-ROUTINE, which performs 9000-TERMINATE. This means even a single MQ, CICS, or IMS error during processing (e.g., a NOTFND on 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 ID CP00, 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-MSG uses a straight UNSTRING ... 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-FLG has 88-level conditions for CARD-NOT-ACTIVE, ACCOUNT-CLOSED, CARD-FRAUD, MERCHANT-FRAUD, and 6000-MAKE-DECISION evaluates them, but nothing in the shown code ever sets these conditions (only INSUFFICIENT-FUND is set) — 5600-READ-PROFILE-DATA is an empty stub (CONTINUE), suggesting fraud/profile checks are planned but not yet implemented.
-
PSB scheduling retry logic: 1200-SCHEDULE-PSB retries the DL/I SCHD once if the PSB is already scheduled (PSB-SCHEDULED-MORE-THAN-ONCE), issuing a TERM first. Other IMS failure conditions (RETRY-CONDITION 88-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: CARDDAT and CARDAIX filenames are set up in working storage but no EXEC CICS READ against 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 SYNCPOINT is 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 in 5000-PROCESS-AUTH via 1200-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
Unresolved conditions
Numeric comparisons with no matching 88-level condition-name anywhere in this program or the copybooks it COPYs — no meaning found in the source export, not guessed.
| Field | Value | Line |
|---|---|---|
PA-AUTH-DATE-9C |
99999 |
874 |
PA-AUTH-TIME-9C |
999999999 |
875 |
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 |