The INSMASTR program implements sophisticated data flow patterns for insurance operations, processing three distinct transaction types through a unified batch processing framework. Each data flow follows a consistent pattern of input validation, business logic execution, database operations, and output generation, while maintaining strict transaction boundaries and error handling protocols.
The system operates in a batch mode, reading sequential input files and processing records through validation, calculation, and persistence layers. All database operations occur within controlled transaction boundaries with periodic commits to balance performance and recovery requirements.
Policy creation represents the entry point for new customer applications. This flow transforms raw application data into validated, risk-assessed, and priced insurance policies stored in the database.
Primary Input: POLFILE (Policy Input File)
Input Data Elements (Lines 313-383):
JCL Parameters:
The program reads records sequentially from POLFILE. Each record contains a 2-byte record type indicator:
Only detail records proceed to validation.
Validation Rules:
Database Interactions: None at this stage
Output: Sets validation flag; on failure, populates error message and invokes error handler
Algorithm:
Customer Age = Current Year - Birth Year
IF Current Month < Birth Month THEN
Customer Age = Customer Age - 1
ELSE IF Current Month = Birth Month THEN
IF Current Day < Birth Day THEN
Customer Age = Customer Age - 1
Uses: COBOL intrinsic function CURRENT-DATE for system date
Result: Stored in WS-CUSTOMER-AGE for subsequent risk and premium calculations
Database Query (Lines 1358-1365):
SELECT COUNT(*)
INTO :WS-DUPLICATE-COUNT
FROM POLICY_TABLE
WHERE CUSTOMER_NUMBER = :POL-CUSTOMER-NUMBER
AND INSURANCE_TYPE = :POL-INSURANCE-TYPE
AND POLICY_STATUS = 'ACTIVE'
Business Rule: One customer cannot have multiple active policies of the same insurance type
Outcome:
Commit Point: None (read-only query)
Risk Components (additive scoring, 0-100 scale):
Age Factor (Lines 1394-1401):
Gender Factor (Lines 1406-1408):
Smoker Factor (Lines 1413-1415):
Health Factor (Lines 1420-1422):
Occupation Factor (Lines 1427-1433):
Final Adjustment (Lines 1438-1444):
Database Interactions: None (pure calculation)
Output: WS-RISK-SCORE stored for premium calculation and database insert
Multi-Stage Calculation:
Stage 1: Base Premium (Lines 1454-1473)
Base Premium = Coverage Amount × Insurance Type Rate
Insurance Type Rates:
- HEALTH: 0.0040 (0.4%)
- LIFE: 0.0020 (0.2%)
- AUTO: 0.0080 (0.8%)
- PROPERTY: 0.0030 (0.3%)
- DENTAL: 0.0015 (0.15%)
- VISION: 0.0010 (0.1%)
Stage 2: Deductible Adjustment (Lines 1478-1481)
IF Deductible > 0 THEN
Deductible Ratio = Deductible / Coverage Amount
Base Premium = Base Premium × (1 - (Deductible Ratio × 0.30))
Higher deductibles reduce premium by up to 30% of the ratio.
Stage 3: Age Factor Application (Lines 1486-1495)
Uses indexed table search (WS-AGE-RATE-TABLE) with 7 age brackets:
Stage 4: Risk Adjustment (Lines 1500-1501)
Risk Adjustment = Base Premium × (Risk Score / 100)
Adds proportional premium based on risk (0% to 100% of base).
Stage 5: Discounts (Lines 1506-1518)
IF Payment Frequency = 'A' (Annual) THEN
Annual Discount = Premium × 0.05 (5%)
IF Coverage Amount > $500,000 THEN
Large Coverage Discount = Premium × 0.10 (10%)
Total Discount = Sum of applicable discounts
Stage 6: State Tax (Lines 1523-1534)
Uses indexed table search (WS-STATE-RATE-TABLE) with state-specific rates:
Tax Amount = (Base Premium + Risk Adjustment - Discounts) × State Tax Rate
Stage 7: Final Premium (Lines 1539-1551)
Final Premium = Base Premium + Risk Adjustment - Total Discount + Tax Amount + $25.00
Processing Fee: $25.00 (fixed)
IF Payment Frequency = 'M' (Monthly) THEN
Monthly Premium = Final Premium / 12
Database Interactions: None (pure calculation)
Output: WS-FINAL-PREMIUM stored in HV-PREMIUM-AMOUNT for database insert
Database Operation: MERGE (upsert pattern)
SQL Statement (Lines 1597-1629):
MERGE INTO CUSTOMER_TABLE AS C
USING (VALUES(
:HV-CUST-NUMBER,
:HV-CUST-NAME,
:HV-CUST-DOB,
:HV-CUST-SSN,
:HV-CUST-GENDER,
:HV-CUST-MARITAL-STATUS,
:HV-CUST-ADDRESS,
:HV-CUST-PHONE,
:HV-CUST-EMAIL,
:HV-CUST-STATUS,
:HV-CUST-RISK-PROFILE,
:HV-CUST-CREDIT-SCORE
)) AS S(CUSTOMER_NUMBER, CUSTOMER_NAME, DATE_OF_BIRTH, SSN,
GENDER, MARITAL_STATUS, ADDRESS, PHONE, EMAIL, STATUS,
RISK_PROFILE, CREDIT_SCORE)
ON C.CUSTOMER_NUMBER = S.CUSTOMER_NUMBER
WHEN MATCHED THEN
UPDATE SET
CUSTOMER_NAME = S.CUSTOMER_NAME,
ADDRESS = S.ADDRESS,
PHONE = S.PHONE,
EMAIL = S.EMAIL,
LAST_UPDATE_DATE = CURRENT_TIMESTAMP,
UPDATED_BY = :WS-PROGRAM-NAME
WHEN NOT MATCHED THEN
INSERT (CUSTOMER_NUMBER, CUSTOMER_NAME, DATE_OF_BIRTH, SSN,
GENDER, MARITAL_STATUS, ADDRESS, PHONE, EMAIL, STATUS,
RISK_PROFILE, CREDIT_SCORE, CREATED_DATE, CREATED_BY)
VALUES (S.CUSTOMER_NUMBER, S.CUSTOMER_NAME, S.DATE_OF_BIRTH, S.SSN,
S.GENDER, S.MARITAL_STATUS, S.ADDRESS, S.PHONE, S.EMAIL,
'ACTIVE', S.RISK_PROFILE, S.CREDIT_SCORE,
CURRENT_TIMESTAMP, :WS-PROGRAM-NAME)
Risk Profile Assignment (Lines 1582-1589):
IF Risk Score < 30 THEN
Risk Profile = 'LOW'
ELSE IF Risk Score >= 30 AND Risk Score < 70 THEN
Risk Profile = 'MEDIUM'
ELSE
Risk Profile = 'HIGH'
Commit Point: No immediate commit; marked for batch commit
Error Handling: SQLCODE checked; non-zero triggers rollback and error logging
Sequence Generation (Lines 1645-1649):
SELECT NEXT VALUE FOR POLICY_SEQ
INTO :HV-POLICY-NUMBER
FROM SYSIBM.SYSDUMMY1
Generates unique 15-digit policy number.
Date Calculations (Lines 1657-1668):
Policy Start Date = Current Date
Policy Term Months = 12 (standard one-year policy)
Policy End Date = Add 12 months to Start Date
Initialization (Lines 1673-1678):
Policy Status = 'ACTIVE'
Deductible Met = $0.00
Out of Pocket Met = $0.00
Claims Count = 0
Renewal Count = 0
Database Insert (Lines 1697-1719):
INSERT INTO POLICY_TABLE
(POLICY_NUMBER, CUSTOMER_NUMBER, CUSTOMER_NAME,
INSURANCE_TYPE, POLICY_START_DATE, POLICY_END_DATE,
POLICY_TERM_MONTHS, POLICY_STATUS,
COVERAGE_AMOUNT, DEDUCTIBLE_AMOUNT, DEDUCTIBLE_MET,
OUT_OF_POCKET_MAX, OUT_OF_POCKET_MET,
PREMIUM_AMOUNT, PAYMENT_FREQUENCY, PAYMENT_METHOD,
RISK_SCORE, FRAUD_SCORE, CLAIMS_COUNT, RENEWAL_COUNT,
CREATED_DATE, CREATED_BY)
VALUES
(:HV-POLICY-NUMBER, :HV-CUSTOMER-NUMBER, :HV-CUSTOMER-NAME,
:HV-INSURANCE-TYPE, :HV-POLICY-START-DATE, :HV-POLICY-END-DATE,
:HV-POLICY-TERM-MONTHS, :HV-POLICY-STATUS,
:HV-COVERAGE-AMOUNT, :HV-DEDUCTIBLE-AMOUNT, :HV-DEDUCTIBLE-MET,
:HV-OUT-OF-POCKET-MAX, :HV-OUT-OF-POCKET-MET,
:HV-PREMIUM-AMOUNT, :HV-PAYMENT-FREQUENCY, :HV-PAYMENT-METHOD,
:HV-RISK-SCORE, :HV-FRAUD-SCORE, :HV-CLAIMS-COUNT, :HV-RENEWAL-COUNT,
:HV-CREATED-DATE, :HV-CREATED-BY)
Commit Point: Increments WS-COMMIT-COUNT; actual commit when counter reaches 500
Error Handling: SQLCODE checked; duplicate key or constraint violations trigger rollback
POLOUT File Record (Lines 1737-1747):
Transaction Type: 'POLICY'
Policy Number: Generated 15-digit number
Customer Number: 10-digit customer ID
Customer Name: 50 characters
Insurance Type: 10 characters
Premium Amount: Calculated premium (9,999,999.99)
Status: 'CREATED'
Processing Timestamp: Current date/time
RPTFILE Report Line (Lines 797-804):
Report Detail Format:
Policy Number | Customer Name | Insurance Type | Premium | Status
Counters Updated:
Commit Point: Checked after output; commit if threshold reached
Begin Transaction: Implicit at program start or after previous commit Commit Points:
Rollback Points:
Policy renewal creates a new policy record with updated terms while maintaining linkage to the original policy, enabling complete policy history tracking.
Primary Input: RENFILE (Renewal Input File)
Input Data Elements (Lines 389-438):
Validation Rules:
Database Interactions: None
Output: Validation flag set; errors logged to ERRFILE
Database Query (Lines 1906-1920):
SELECT CUSTOMER_NUMBER, CUSTOMER_NAME,
INSURANCE_TYPE, COVERAGE_AMOUNT,
PREMIUM_AMOUNT, DEDUCTIBLE_AMOUNT,
POLICY_STATUS, POLICY_END_DATE,
RISK_SCORE, CLAIMS_COUNT, RENEWAL_COUNT
INTO :HV-CUSTOMER-NUMBER, :HV-CUSTOMER-NAME,
:HV-INSURANCE-TYPE, :HV-COVERAGE-AMOUNT,
:HV-PREMIUM-AMOUNT, :HV-DEDUCTIBLE-AMOUNT,
:HV-POLICY-STATUS, :HV-POLICY-END-DATE,
:HV-RISK-SCORE, :HV-CLAIMS-COUNT,
:HV-RENEWAL-COUNT
FROM POLICY_TABLE
WHERE POLICY_NUMBER = :REN-POLICY-NUMBER
Business Rules (Lines 1925-1942):
Commit Point: None (read-only)
Base Calculation by Renewal Type (Lines 1952-1986):
STANDARD RENEWAL:
New Base Premium = Current Premium × 1.03 (+3% annual increase)
UPGRADE:
IF Requested Coverage > Current Coverage THEN
New Base Premium = Current Premium × 1.25 (+25% adjustment)
IF Requested Coverage specified THEN
Recalculate: New Coverage × Original Rate × 1.25
END IF
END IF
DOWNGRADE:
IF Requested Coverage < Current Coverage THEN
New Base Premium = Current Premium × 0.75 (-25% adjustment)
IF Requested Coverage specified THEN
Recalculate: New Coverage × Original Rate × 0.75
END IF
END IF
MULTI-YEAR:
Annual Premium = Current Premium × 1.03
New Base Premium = Annual Premium × (Term Months / 12) × 0.95
(5% discount for multi-year commitment)
Loyalty Discount (Lines 1991-1998):
IF REN-LOYALTY-YEARS > 0 THEN
Loyalty Discount % = REN-LOYALTY-YEARS × 1%
IF Loyalty Discount % > 15% THEN
Loyalty Discount % = 15% (cap)
END IF
Loyalty Discount Amount = New Base Premium × Loyalty Discount %
END IF
No-Claims Discount (Lines 2003-2011):
Database Check:
SELECT CLAIMS_COUNT
INTO :HV-CLAIMS-COUNT
FROM POLICY_TABLE
WHERE POLICY_NUMBER = :REN-POLICY-NUMBER
IF CLAIMS_COUNT = 0 AND REN-NO-CLAIMS-YEARS > 0 THEN
No-Claims Discount % = REN-NO-CLAIMS-YEARS × 2%
IF No-Claims Discount % > 20% THEN
No-Claims Discount % = 20% (cap)
END IF
No-Claims Discount Amount = New Base Premium × No-Claims Discount %
END IF
Multi-Policy Discount (Lines 2016-2030):
Database Query:
SELECT COUNT(*)
INTO :WS-POLICY-COUNT
FROM POLICY_TABLE
WHERE CUSTOMER_NUMBER = :HV-CUSTOMER-NUMBER
AND POLICY_STATUS = 'ACTIVE'
IF Policy Count >= 2 THEN
Multi-Policy Discount = New Base Premium × 10%
END IF
Deductible Change Adjustment (Lines 2035-2045):
IF Requested Deductible > Current Deductible THEN
Premium Adjustment = -5% (higher deductible reduces premium)
ELSE IF Requested Deductible < Current Deductible THEN
Premium Adjustment = +5% (lower deductible increases premium)
END IF
Final Renewal Premium = New Base Premium - All Discounts + Adjustment
Database Interactions:
Commit Point: None (calculations only)
Sequence Generation (Lines 2055-2059):
SELECT NEXT VALUE FOR POLICY_SEQ
INTO :HV-POLICY-NUMBER
FROM SYSIBM.SYSDUMMY1
Date Calculations (Lines 2065-2079):
New Policy Start Date = Old Policy End Date (seamless transition)
New Policy Term = Renewal Term Months (12, 24, or 36)
New Policy End Date = Start Date + Term Months
Field Population (Lines 2084-2101):
Copy from old policy:
- Customer Number
- Customer Name
- Insurance Type
- Risk Score (unless upgrade/downgrade)
Update values:
- Coverage Amount (if changed)
- Deductible Amount (if changed)
- Premium Amount (newly calculated)
- Payment Method (if changed)
Reset usage counters:
- Deductible Met = $0.00
- Out of Pocket Met = $0.00
- Claims Count = 0
Increment:
- Renewal Count = Old Renewal Count + 1
Link policies:
- Renewal From Policy = Old Policy Number
Database Insert (Lines 2107-2139):
INSERT INTO POLICY_TABLE
(POLICY_NUMBER, CUSTOMER_NUMBER, CUSTOMER_NAME,
INSURANCE_TYPE, POLICY_START_DATE, POLICY_END_DATE,
POLICY_TERM_MONTHS, POLICY_STATUS,
COVERAGE_AMOUNT, DEDUCTIBLE_AMOUNT, DEDUCTIBLE_MET,
OUT_OF_POCKET_MAX, OUT_OF_POCKET_MET,
PREMIUM_AMOUNT, PAYMENT_FREQUENCY, PAYMENT_METHOD,
RISK_SCORE, FRAUD_SCORE, CLAIMS_COUNT, RENEWAL_COUNT,
RENEWAL_FROM_POLICY,
CREATED_DATE, CREATED_BY)
VALUES
(...new policy values including RENEWAL_FROM_POLICY link...)
Commit Point: Marked for batch commit; actual commit at 500-record threshold
Database Update (Lines 2146-2153):
UPDATE POLICY_TABLE
SET POLICY_STATUS = 'RENEWED',
RENEWAL_TO_POLICY = :HV-POLICY-NUMBER,
LAST_UPDATE_DATE = CURRENT_TIMESTAMP,
UPDATED_BY = :WS-PROGRAM-NAME
WHERE POLICY_NUMBER = :REN-POLICY-NUMBER
Purpose:
Commit Point: Same transaction as new policy insert; both commit together
RENOUT File Record (Lines 2169-2178):
Transaction Type: 'RENEWAL'
Old Policy Number: Original 15-digit number
New Policy Number: Generated 15-digit number
Customer Number: 10-digit customer ID
New Premium Amount: Calculated renewal premium
Status: 'RENEWED'
Processing Timestamp: Current date/time
Report Line: Detail line written to RPTFILE showing renewal success
Counters Updated:
Single Transaction Scope:
Both operations commit together, ensuring atomic renewal. If either fails, both rollback.
Commit Frequency: Every 500 successful renewal operations
Claims processing implements sophisticated fraud detection and payment calculation logic, updating policy usage tracking while generating payment instructions.
Primary Input: CLMFILE (Claims Input File)
Input Data Elements (Lines 444-523):
Validation Rules:
Database Interactions: None
Database Query (Lines 2384-2398):
SELECT POLICY_STATUS, POLICY_START_DATE, POLICY_END_DATE,
COVERAGE_AMOUNT, DEDUCTIBLE_AMOUNT, DEDUCTIBLE_MET,
OUT_OF_POCKET_MAX, OUT_OF_POCKET_MET,
COPAY_PCT, CLAIMS_COUNT
INTO :HV-POLICY-STATUS, :HV-POLICY-START-DATE, :HV-POLICY-END-DATE,
:HV-COVERAGE-AMOUNT, :HV-DEDUCTIBLE-AMOUNT, :HV-DEDUCTIBLE-MET,
:HV-OUT-OF-POCKET-MAX, :HV-OUT-OF-POCKET-MET,
:WS-COPAY-PERCENTAGE, :HV-CLAIMS-COUNT
FROM POLICY_TABLE
WHERE POLICY_NUMBER = :CLM-POLICY-NUMBER
Business Rules:
Commit Point: None (read-only)
Database Query (Lines 2437-2442):
SELECT COUNT(*)
INTO :WS-DUPLICATE-COUNT
FROM CLAIM_TABLE
WHERE CLAIM_NUMBER = :CLM-CLAIM-NUMBER
Business Rule: Same claim number cannot be submitted twice
Commit Point: None (read-only)
Component 1: Frequency Analysis (Lines 2460-2474):
SELECT COUNT(*)
INTO :WS-ROW-COUNT
FROM CLAIM_TABLE
WHERE CUSTOMER_NUMBER = :CLM-CUSTOMER-NUMBER
AND CLAIM_DATE >= CURRENT_DATE - 30 DAYS
Scoring:
- Count > 3: +25 fraud points (very high frequency)
- Count > 1: +10 fraud points (high frequency)
- Count <= 1: +0 points (normal)
Component 2: Amount Analysis (Lines 2479-2485):
Scoring:
- Claim Amount > $50,000: +15 fraud points (very large claim)
- Claim Amount > $25,000: +10 fraud points (large claim)
- Claim Amount <= $25,000: +0 points (normal)
Component 3: Provider History (Lines 2490-2508):
SELECT FRAUD_SCORE, ACTIVE_FLAG
INTO :HV-PROV-FRAUD-SCORE, :HV-PROV-ACTIVE-FLAG
FROM PROVIDER_TABLE
WHERE PROVIDER_CODE = :CLM-PROVIDER-CODE
Scoring:
- Provider Fraud Score > 50: +20 fraud points (high-risk provider)
- Provider Active Flag = 'N': +30 fraud points (inactive provider)
- Otherwise: +0 points
Component 4: Pattern Detection (Lines 2513-2526):
SELECT COUNT(*)
INTO :WS-ROW-COUNT
FROM CLAIM_TABLE
WHERE CUSTOMER_NUMBER = :CLM-CUSTOMER-NUMBER
AND CLAIM_TYPE = :CLM-CLAIM-TYPE
AND CLAIM_AMOUNT = :CLM-CLAIM-AMOUNT
AND CLAIM_DATE >= CURRENT_DATE - 90 DAYS
Scoring:
- Identical claims found: +20 fraud points (suspicious pattern)
- No matches: +0 points
Component 5: Timing Analysis (Lines 2531-2535):
Day of Week Check (using FUNCTION DAY-OF-WEEK):
- Weekend incident (Saturday/Sunday): +5 fraud points
- Weekday: +0 points
Fraud Score Decision Logic (Lines 2542-2561):
Total Fraud Score = Sum of all components (0-100+)
IF Fraud Score >= 70 THEN
Claim Status = 'UNDER REVIEW'
Approval Status = 'FRAUD INVESTIGATION'
Fraud Flag = 'Y'
Investigation Flag = 'Y'
Insurance Payment = $0.00
Patient Responsibility = $0.00
Skip payment calculation
ELSE IF Fraud Score >= 50 AND Fraud Score < 70 THEN
Claim Status = 'PROCESSING'
Approval Status = 'MANUAL REVIEW REQUIRED'
Fraud Flag = 'N'
Investigation Flag = 'N'
Insurance Payment = $0.00
Patient Responsibility = $0.00
Skip payment calculation
ELSE IF Fraud Score < 50 THEN
Proceed to payment calculation
IF Claim Amount <= $5,000 THEN
Approval Status = 'AUTO-APPROVED'
ELSE
Approval Status = 'PENDING APPROVAL'
END IF
END IF
Database Interactions:
Commit Point: None (read-only fraud analysis)
Only executes if fraud score < 50
Stage 1: Approved Amount (Lines 2577-2585):
Approved Amount = Claim Amount (initial assignment)
Insurance Pays = $0.00 (initialize)
Patient Pays = $0.00 (initialize)
Stage 2: Deductible Application (Lines 2591-2603):
Calculate Remaining Deductible:
Remaining Deductible = Policy Deductible Amount - Deductible Met
IF Remaining Deductible > 0 THEN
IF Approved Amount >= Remaining Deductible THEN
Deductible Applied = Remaining Deductible
ELSE
Deductible Applied = Approved Amount (claim doesn't cover full deductible)
END IF
Patient Pays = Patient Pays + Deductible Applied
Approved Amount = Approved Amount - Deductible Applied
END IF
Example:
Claim: $10,000
Policy Deductible: $2,000
Already Met: $500
Remaining Deductible = $2,000 - $500 = $1,500
Deductible Applied = $1,500
Patient Pays = $0 + $1,500 = $1,500
Approved Amount = $10,000 - $1,500 = $8,500
Stage 3: Copay/Coinsurance (Lines 2608-2620):
Default Copay Percentage = 20% (if not specified in policy)
Copay Amount = Approved Amount × Copay Percentage
Patient Pays = Patient Pays + Copay Amount
Coinsurance Applied = Copay Amount (for reporting)
Insurance Pays = Approved Amount - Copay Amount
Continuing example:
Approved Amount (after deductible) = $8,500
Copay Percentage = 20%
Copay Amount = $8,500 × 0.20 = $1,700
Patient Pays = $1,500 + $1,700 = $3,200
Insurance Pays = $8,500 - $1,700 = $6,800
Stage 4: Out-of-Pocket Maximum (Lines 2625-2633):
Calculate Remaining Out-of-Pocket:
Remaining OOP = Policy OOP Maximum - OOP Already Met
IF Patient Pays > Remaining OOP THEN
Excess Amount = Patient Pays - Remaining OOP
Patient Pays = Remaining OOP (capped at limit)
Insurance Pays = Insurance Pays + Excess Amount (insurance covers excess)
END IF
Continuing example:
Policy OOP Maximum = $5,000
Already Met = $3,000
Remaining OOP = $5,000 - $3,000 = $2,000
Patient Pays = $3,200
Excess = $3,200 - $2,000 = $1,200
Patient Pays = $2,000 (capped)
Insurance Pays = $6,800 + $1,200 = $8,000
Stage 5: Coverage Limit Check (Lines 2641-2645):
IF Insurance Pays > Policy Coverage Amount THEN
Insurance Pays = Policy Coverage Amount (cap at policy limit)
Recalculate Patient Pays = Claim Amount - Insurance Pays
END IF
Final calculation result:
Original Claim Amount: $10,000
Insurance Pays: $8,000
Patient Responsibility: $2,000
Deductible Applied: $1,500
Copay Applied: $1,700
Coinsurance Applied: $1,700
Database Interactions: None (pure calculation)
Sequence Generation (Lines 2675-2679):
SELECT NEXT VALUE FOR CLAIM_SEQ
INTO :HV-CLAIM-ID
FROM SYSIBM.SYSDUMMY1
Generates unique 10-digit claim ID.
Database Insert (Lines 2718-2747):
INSERT INTO CLAIM_TABLE
(CLAIM_ID, CLAIM_NUMBER, POLICY_NUMBER, CUSTOMER_NUMBER,
CLAIM_TYPE, INCIDENT_DATE, CLAIM_DATE,
CLAIM_AMOUNT, APPROVED_AMOUNT,
DEDUCTIBLE_APPLIED, COPAY_APPLIED, COINSURANCE_APPLIED,
INSURANCE_PAID, PATIENT_RESPONSIBILITY,
CLAIM_STATUS, APPROVAL_STATUS, PAYMENT_STATUS,
DENIAL_REASON, PROVIDER_CODE, PROVIDER_NAME,
DIAGNOSIS_CODE, PROCEDURE_CODE,
FRAUD_FLAG, FRAUD_SCORE, INVESTIGATION_FLAG,
CREATED_DATE, CREATED_BY)
VALUES
(:HV-CLAIM-ID, :HV-CLAIM-NUMBER, :HV-CLM-POLICY-NUMBER,
:HV-CLM-CUSTOMER-NUMBER, :HV-CLAIM-TYPE,
:HV-INCIDENT-DATE, :HV-CLAIM-DATE,
:HV-CLAIM-AMOUNT, :HV-APPROVED-AMOUNT,
:HV-DEDUCTIBLE-APPLIED, :HV-COPAY-APPLIED,
:HV-COINSURANCE-APPLIED, :HV-INSURANCE-PAID,
:HV-PATIENT-RESPONSIBILITY, :HV-CLAIM-STATUS,
:HV-APPROVAL-STATUS, 'PENDING', :WS-DENIAL-REASON,
:HV-PROVIDER-CODE, :HV-PROVIDER-NAME,
:HV-DIAGNOSIS-CODE, :HV-PROCEDURE-CODE,
:HV-FRAUD-FLAG, :HV-CLM-FRAUD-SCORE,
:HV-INVESTIGATION-FLAG,
:HV-CREATED-DATE, :HV-CREATED-BY)
Commit Point: Marked for batch commit
Database Update (Lines 2774-2785):
UPDATE POLICY_TABLE
SET DEDUCTIBLE_MET = DEDUCTIBLE_MET + :WS-DEDUCTIBLE-APPLIED,
OUT_OF_POCKET_MET = OUT_OF_POCKET_MET + :WS-PATIENT-PAYS,
CLAIMS_COUNT = CLAIMS_COUNT + 1,
LAST_CLAIM_DATE = CURRENT_DATE,
LAST_UPDATE_DATE = CURRENT_TIMESTAMP,
UPDATED_BY = :WS-PROGRAM-NAME
WHERE POLICY_NUMBER = :CLM-POLICY-NUMBER
High Fraud Customer Update (Lines 2790-2805):
IF Fraud Score >= 70 THEN
UPDATE CUSTOMER_TABLE
SET RISK_PROFILE = 'HIGH',
FRAUD_ALERT_FLAG = 'Y',
LAST_UPDATE_DATE = CURRENT_TIMESTAMP,
UPDATED_BY = :WS-PROGRAM-NAME
WHERE CUSTOMER_NUMBER = :CLM-CUSTOMER-NUMBER
END IF
Purpose:
Commit Point: Same transaction as claim insert; both commit together
CLMOUT File Record (Lines 2815-2825):
Transaction Type: 'CLAIM'
Claim ID: Generated 10-digit number
Claim Number: Business claim reference (15 characters)
Policy Number: 15-digit policy ID
Insurance Payment Amount: Calculated amount
Patient Responsibility: Calculated amount
Claim Status: PROCESSING, UNDER REVIEW, AUTO-APPROVED, etc.
Processing Timestamp: Current date/time
Special Outputs:
Counters Updated:
Single Transaction Scope:
All operations commit together. If any fails, all rollback.
Commit Frequency: Every 500 successful claim operations
The INSMASTR program implements a sophisticated batch processing architecture that handles multiple input file types, manages transaction commits, and generates comprehensive processing reports.
Mode Determination (Lines 847-879):
The program accepts a processing mode parameter via SYSIN:
ACCEPT WS-PROCESSING-MODE FROM SYSIN
EVALUATE TRUE
WHEN PROCESS-POLICIES-ONLY (Mode = 'POLICY')
PERFORM 2000-PROCESS-POLICIES
WHEN PROCESS-RENEWALS-ONLY (Mode = 'RENEWAL')
PERFORM 3000-PROCESS-RENEWALS
WHEN PROCESS-CLAIMS-ONLY (Mode = 'CLAIM')
PERFORM 4000-PROCESS-CLAIMS
WHEN PROCESS-ALL-FILES (Mode = 'ALL')
PERFORM 2000-PROCESS-POLICIES
PERFORM 3000-PROCESS-RENEWALS
PERFORM 4000-PROCESS-CLAIMS
WHEN OTHER
Display 'INVALID PROCESSING MODE'
Return Code = 8
END-EVALUATE
Use Cases:
Each file type follows the same processing pattern:
Generic Loop Structure (applies to all three file types):
SET EOF-FLAG TO FALSE
PERFORM UNTIL EOF-FLAG = 'Y'
READ INPUT-FILE INTO WORK-AREA
EVALUATE FILE-STATUS
WHEN '00'
ADD 1 TO READ-COUNT
IF DETAIL-RECORD
PERFORM PROCESS-RECORD-SECTION
END-IF
WHEN '10'
SET EOF-FLAG TO TRUE
WHEN OTHER
PERFORM 8000-ERROR-HANDLER
END-EVALUATE
IF COMMIT-COUNT >= COMMIT-FREQUENCY
PERFORM 7000-COMMIT-WORK
END-IF
END-PERFORM
Key Characteristics:
Threshold-Based Commits (Lines 2852-2867):
7000-COMMIT-WORK SECTION.
IF WS-COMMIT-COUNT > 0 THEN
EXEC SQL
COMMIT WORK
END-EXEC
IF SQLCODE = 0 THEN
MOVE ZERO TO WS-COMMIT-COUNT
DISPLAY 'COMMIT PERFORMED - RECORDS COMMITTED: '
WS-COMMIT-COUNT
ELSE
PERFORM 8000-ERROR-HANDLER
END-IF
END-IF.
Commit Counter Management:
After each successful database INSERT/UPDATE/MERGE:
WS-COMMIT-COUNT = WS-COMMIT-COUNT + 1
After COMMIT:
WS-COMMIT-COUNT = 0 (reset)
After ROLLBACK (error condition):
WS-COMMIT-COUNT = 0 (reset)
Commit Frequency Configuration:
Error Handling Philosophy:
Error Flow:
Record Processing Error
↓
Set ERROR-OCCURRED Flag
↓
Determine Severity (CRITICAL/SEVERE/WARNING)
↓
Format Error Record
↓
Write to ERRFILE
↓
Display on Console
↓
If SQL Error: ROLLBACK uncommitted work
↓
If CRITICAL: Abort program (9999-ABORT-PROGRAM)
↓
Otherwise: Continue to next record
Error handling in INSMASTR follows a centralized pattern with severity-based routing and comprehensive error capture.
Critical Errors (1101-1999) - Program Termination:
Severe Errors (2001-4999) - Record Rejection, Continue Processing:
Policy Processing (2001-2999):
Renewal Processing (3001-3999):
Claims Processing (4001-4999):
Warning Errors (Other Codes) - Logged for Review:
ERRFILE Record Layout (250 bytes):
ERROR | [Code] | [Severity] | [Message] | SQLCODE=[code] | [Timestamp]
Example Error Records:
ERROR|2004|SEVERE|CUSTOMER AGE OUT OF RANGE: 17|SQLCODE=0|2024-01-15-14.30.25.123456
ERROR|2010|SEVERE|POLICY INSERT FAILED|SQLCODE=-803|2024-01-15-14.30.26.456789
ERROR|3002|SEVERE|POLICY NOT FOUND FOR RENEWAL|SQLCODE=+100|2024-01-15-14.30.27.789012
ERROR|4006|SEVERE|FRAUD DETECTION QUERY FAILED|SQLCODE=-911|2024-01-15-14.30.28.012345
SQLCODE Interpretation:
Common SQL Errors:
Rollback Trigger (Lines 2928-2933):
IF SQLCODE NOT = 0 AND SQLCODE NOT = 100 THEN
EXEC SQL
ROLLBACK WORK
END-EXEC
MOVE ZERO TO WS-COMMIT-COUNT
END-IF
Impact of Rollback:
Error Console Output (Lines 2917-2923):
DISPLAY '***ERROR*** CODE: ' WS-ERROR-CODE
DISPLAY ' SEVERITY: ' WS-ERROR-SEVERITY
DISPLAY ' MESSAGE: ' WS-ERROR-MESSAGE
DISPLAY ' SQLCODE: ' SQLCODE
DISPLAY ' SQLERRMC: ' SQLERRMC
Purpose:
Normal Termination (Return Code 0 or 4):
Abnormal Termination (Return Code 16):
Transaction boundaries define the scope of atomic database operations, ensuring data consistency and enabling recovery from failures.
Transaction 1: Policy Creation
BEGIN (implicit after last commit or program start)
↓
MERGE INTO CUSTOMER_TABLE (customer record)
↓
INSERT INTO POLICY_TABLE (policy record)
↓
COMMIT (explicit at 500-record threshold or program end)
Atomicity: Customer and policy inserted together or not at all.
Transaction 2: Policy Renewal
BEGIN (implicit)
↓
INSERT INTO POLICY_TABLE (new policy record)
↓
UPDATE POLICY_TABLE (old policy status = RENEWED)
↓
COMMIT (explicit at threshold or program end)
Atomicity: New policy and old policy update occur together.
Transaction 3: Claim Processing
BEGIN (implicit)
↓
INSERT INTO CLAIM_TABLE (claim record)
↓
UPDATE POLICY_TABLE (deductible met, OOP met, claims count)
↓
[Optional] UPDATE CUSTOMER_TABLE (risk profile if fraud detected)
↓
COMMIT (explicit at threshold or program end)
Atomicity: Claim and policy usage update occur together.
Explicit Commit Locations:
7000-COMMIT-WORK Section (Lines 2852-2867)
9000-FINALIZE-PROGRAM Section (Lines 2947-3228)
Implicit Transaction Boundaries:
Automatic Rollback Triggers:
IF SQLCODE NOT = 0 AND SQLCODE NOT = 100
EXEC SQL ROLLBACK WORK END-EXEC
MOVE ZERO TO WS-COMMIT-COUNT
EXEC SQL ROLLBACK WORK END-EXEC
DISPLAY 'TRANSACTION ROLLED BACK DUE TO ABEND'
Rollback Impact:
Recovery Strategy:
Cursor Stability (CS) Configuration (Lines 1043-1049):
EXEC SQL
CONNECT TO INSPROD USER :WS-PROGRAM-NAME
USING 'INSPROD'
END-EXEC
Isolation Level: CS (Cursor Stability)
Lock Timeout: 30 seconds
CS Isolation Characteristics:
Implications for INSMASTR:
Concurrency Considerations:
The commit strategy balances three competing objectives: performance, data integrity, and recovery capability.
500-Record Threshold (WS-COMMIT-FREQUENCY = 500):
Advantages:
Disadvantages:
Alternative Configurations:
Small Batch (100 records):
+ Faster recovery
+ Lower memory
- More commit overhead
- Reduced throughput
Large Batch (1000 records):
+ Higher throughput
+ Less commit overhead
- Longer recovery time
- Higher lock contention
DB2 Transaction Log Considerations:
Before Image (UNDO) Logging:
After Image (REDO) Logging:
Log Space Calculation (approximate):
Single Policy Insert: ~500 bytes
Single Claim Insert: ~600 bytes
Single Update: ~200 bytes
500-Record Policy Batch:
500 × (CUSTOMER_MERGE + POLICY_INSERT)
≈ 500 × (500 + 500) = 500 KB per commit
500-Record Claim Batch:
500 × (CLAIM_INSERT + POLICY_UPDATE)
≈ 500 × (600 + 200) = 400 KB per commit
Log Space Monitoring:
Sequential File Processing (Mode = 'ALL'):
Process Policy File:
Read all policy records
Commit every 500 records
Final commit at end of file
Process Renewal File:
Read all renewal records
Commit every 500 records (separate counter continues)
Final commit at end of file
Process Claims File:
Read all claims records
Commit every 500 records
Final commit at end of file
Key Point: Commit counter is CONTINUOUS across file types, not reset between files.
Example Scenario:
Policy File: 400 records processed
- No commit yet (counter = 400)
Renewal File: 150 records processed
- Commit triggered at record 100 (counter = 500)
- Counter reset to 0
- Counter now = 50 after 150 renewals processed
Claims File: 500 records processed
- Commit triggered at record 450 (counter = 500)
- Counter reset to 0
- Commit triggered at record 500 (counter = 500)
- Counter reset to 0
Recovery Point Objective (RPO): Maximum acceptable data loss
Current Configuration:
Recovery Procedure:
Audit Trail Support:
Example Recovery:
Job Log Shows:
- Policies Processed: 1500
- Policies Committed: 1500 (3 commits of 500 each)
- Renewals Processed: 750
- Renewals Committed: 500 (1 commit)
- Claims Processed: 200
- Database Error at Claim #200
- Rollback Executed
Recovery Action:
- Policies: Fully committed (no action)
- Renewals: 500 committed, 250 pending (resubmit last 250)
- Claims: None committed (resubmit all 200 after error correction)
Post-Commit Verification (Lines 2856-2864):
EXEC SQL
COMMIT WORK
END-EXEC
IF SQLCODE = 0 THEN
MOVE ZERO TO WS-COMMIT-COUNT
DISPLAY 'COMMIT PERFORMED - RECORDS COMMITTED: '
WS-COMMIT-COUNT
ELSE
PERFORM 8000-ERROR-HANDLER
(Error handler will execute ROLLBACK)
END-IF
Commit Failure Handling:
Monitoring Points: