Case Study 2: MedClaim Provider Payment Summary Report
Background
MedClaim Health Services sends monthly payment summary reports to each region's management team. These reports show all claim payments grouped by region and then by provider, with subtotals at each level. The reports are used for:
- Financial reconciliation: Verifying total payments match accounts payable records
- Provider analysis: Identifying high-volume and high-cost providers
- Fraud detection: Flagging unusual payment patterns
- Regulatory reporting: Supporting state insurance commission inquiries
The Problem
Sarah Kim has been asked to implement a new version of the provider payment summary report. The current version is a Crystal Reports document generated from a DB2 query, but the query has become too slow as the data volume has grown. James Okafor proposes generating the report in the batch COBOL processing pipeline, where the sorted payment data is already available.
"We already have the data sorted by region and provider in the batch flow," James explains. "Instead of querying DB2 again for the same data, let's produce the report as a by-product of the batch processing. A Report Writer program downstream of the sort step can produce this report with almost no additional I/O."
Requirements
- Two-level control break: region (major) and provider (minor)
- Control heading for each region showing the region code and name
- Control heading for each provider showing the provider number and name
- Detail lines showing claim date, claim ID, payment status, and amount
- Provider subtotal: total amount, claim count, with denied claims separately
- Region subtotal: total amount, total claims, total denied
- Grand total: all amounts, all claims, all denied
- Page management: headers on every page, "CONFIDENTIAL" watermark
Multi-Level SUM Design
Sarah designs the SUM hierarchy carefully:
DETAIL LINE:
- RPT-PAY-AMOUNT (individual claim amount)
- RPT-PAY-COUNTER (always 1, for counting)
- RPT-DENIED-FLAG (1 if denied, 0 if not)
CONTROL FOOTING PAY-PROVIDER:
- SUM RPT-PAY-AMOUNT → provider total amount
- SUM RPT-PAY-COUNTER → provider claim count
- SUM RPT-DENIED-FLAG → provider denied count
CONTROL FOOTING PAY-REGION:
- SUM RPT-PAY-AMOUNT → region total (sums provider totals)
- SUM RPT-PAY-COUNTER → region claim count
- SUM RPT-DENIED-FLAG → region denied count
CONTROL FOOTING FINAL:
- SUM RPT-PAY-AMOUNT → grand total
- SUM RPT-PAY-COUNTER → total claims
- SUM RPT-DENIED-FLAG → total denied
"The beauty of this," Sarah notes, "is that I define the SUM at each level and Report Writer handles the cascading automatically. The region total is the sum of provider totals, and the grand total is the sum of region totals. I don't write any accumulation code."
Implementation Challenge: Conditional Counting
Counting denied claims requires a trick. Report Writer's SUM can only add numeric fields. Sarah defines a field in the DETAIL group that is set to 1 for denied claims and 0 otherwise:
01 PAYMENT-DETAIL TYPE IS DETAIL.
05 LINE PLUS 1.
10 RPT-DENIED-FLAG PIC 9 VALUE 0.
10 RPT-PAY-COUNTER PIC 9 VALUE 1.
* ... visible detail fields ...
In the PROCEDURE DIVISION, before each GENERATE:
1000-PROCESS-PAYMENTS.
IF PAY-STATUS = 'DN'
MOVE 1 TO WS-DENIED-FLAG
ELSE
MOVE 0 TO WS-DENIED-FLAG
END-IF
GENERATE PAYMENT-DETAIL
READ PAYMENT-FILE ...
Wait — but the DETAIL group's RPT-DENIED-FLAG has VALUE 0. How does the conditional value get there? Sarah uses USE BEFORE REPORTING:
DECLARATIVES.
DETAIL-SECTION SECTION.
USE BEFORE REPORTING PAYMENT-DETAIL.
SET-DENIED-FLAG.
IF PAY-STATUS = 'DN'
MOVE 1 TO RPT-DENIED-FLAG
ELSE
MOVE 0 TO RPT-DENIED-FLAG
END-IF.
END DECLARATIVES.
This executes just before each detail line is generated, setting the denied flag appropriately. The SUM clause in the control footings then correctly accumulates the denied count.
Results
The batch-generated report replaced the Crystal Reports version with several advantages:
| Metric | Crystal Reports Version | COBOL Report Writer Version |
|---|---|---|
| Generation time | 45 minutes (DB2 query) | 12 seconds (sorted file) |
| Data freshness | Previous day (query lag) | Current run (real-time) |
| Maintenance | Requires Crystal Reports license | Standard COBOL |
| Integration | Separate process | Part of batch pipeline |
Key Insight: Report Writer in the Batch Pipeline
The most significant lesson from this case study is architectural. By placing the Report Writer program in the existing batch processing pipeline — downstream of the sort step that produces the sorted payment file — MedClaim eliminated the redundant DB2 query entirely. The report is now a zero-cost by-product of normal batch processing, not a separate reporting step.
James summarizes: "The best report is the one you generate as a side effect of processing you're already doing. The data was already sorted. The file was already open. We just added a GENERATE statement."
Discussion Questions
- How does the USE BEFORE REPORTING declarative solve the conditional counting problem? Could you achieve the same result without it?
- What would happen if the payment file were not sorted by region then provider? How would you detect this?
- If MedClaim needed to produce separate report files per region (one file for East, one for Central, etc.), how would you modify the approach?
- Compare the maintenance burden of updating this report vs. the original Crystal Reports version when a new payment status code is added.
- James says "the best report is the one you generate as a side effect." What are the risks of this approach?