#!/usr/local/bin/perl # # -------------------------------------------------------------------------------------- # This program reads an EOBS/T data file and transforms the data into multiple # output files ready for the DB2 LOAD utility. Each output file corresponds to # a DB2 table in the EOB database. # # Modification Log # # 02/03/2008 - Add a timestamp value to be used for a common creation # timestamp on all records # 03/03/2012 Create a Massachusetts specific copy to process thier # file because it has a slightly different format. # # --------------------------------------------------------------------------------------- use strict; sub trim($); sub trimToUndef($); sub toYMD($); sub launderMoney($); sub trimFinalSep($); sub pre_process_main($$); # ~ Variables ---------------------------------------------------- my $input_file_name = ""; my $record; my $input_record_count=0; my $eob_count=0; my $claim_count=0; my $message_count=0; my $provider_count=0; my $detail_count=0; my $MESSAGE_SEPARATOR = "!=!"; my $sep_length = length($MESSAGE_SEPARATOR); my $MESSAGE_SEPARATOR2 = "=&="; my $start_time; # Record layout for the EOB_MESSAGE table my $eob_message_template = "A3 A8 A9 A4 A1 A4 A1 A50 A3 A1 A14 A26 A1 A*"; # FINANCIAL_LEG # STATEMENT_DATE # FDSN # MESSAGE_GROUP # MESSAGE_TYPE # MESSAGE_NUMBER # PATIENT_NAME NULL INDICATOR # PATIENT_NAME # PATIENT_SEQUENCE # ICN NULL INDICTOR # ICN # MESSAGE NULL INDICATOR # MESSAGE # global holding variables for the EOB being processed $_=`date +%Y-%m-%d-%H.%M.%S`; #2008-02-03-13.17.04 chomp; my $db2_insert_timestamp="$_" . ".000000"; # DB2 format to be used for creation_timestamp #DRM my $db2_insert_timestamp="2008-06-04-01.01.01.000000"; # DB2 format to be used for creation_timestamp my $statement_date = ""; my $fdsn = ""; my $financial_leg = ""; # The financial leg this EOB is within #my %message_patient = (); # hash of the patient messages on an EOB #my %message_claim = (); # hash of the claim-level messages on an EOB my @messages = (); # ordered array of the claim and patient-level # message-lines on an EOB (ordered on message sequence) #my $message_document = ''; # concatenated document-level messages my %provider_hash; my @claim_recs; # --------------------------------------------------------------------- # ~ Main Procedure ---------------------------------------------------- # --------------------------------------------------------------------- # use as a library or directly from the command line if (@ARGV) { my ($input_file, $output_dir) = @ARGV; &pre_process_main($input_file, $output_dir); } 1; # ---------------------------------------------------------------------# # ~ Subroutines # # ---------------------------------------------------------------------# # ------------------------------------------- # Main - run the primary logic of this script # ------------------------------------------- sub pre_process_main($$) { # start the stopwatch $start_time = time; print "DB2 Insert Date db2_insert_timestamp=$db2_insert_timestamp \n\n"; # Initialize counters in case we are being called as a library $input_record_count=0; $eob_count=0; $claim_count=0; $message_count=0; $provider_count=0; $detail_count=0; # retrieve command line arguments my ($input_file, $output_dir) = @_; if (!$input_file || !$output_dir ) { print "Usage: \n\n"; exit(1); } print "Input Parms are <$input_file> <$output_dir>\n\n"; # extract the file name without the path if ($input_file=~m#([^/]+)$#) { $input_file_name =$1; } # Open Files open (INPUT_FILE, "<$input_file" ) || die "couldn't open input file ($input_file)"; open (EOB_FILE, ">${output_dir}/$input_file_name.eob.asc") || die "Couldn't open EOB_File"; open (EOB_MESSAGE_FILE, ">${output_dir}/$input_file_name.eob-message.asc") || die "Couldn't open EOB_Message_File"; open (EOB_CLAIM_FILE, ">${output_dir}/$input_file_name.eob-claim.asc") || die "Couldn't open EOB_Claim_File"; open (EOB_DETAIL_SERVICE_FILE, ">${output_dir}/$input_file_name.eob-detail-service.asc") || die "Couldn't open EOB_Detail_Service_File"; print "--------------------------\n"; print "Processing starting for input file ($input_file)\n"; # loop over all the records in the input file while ( $record = ) { chomp($record); $input_record_count++; for (substr($record, 0, 1) ) { if (/H/) { &H_header($record); } elsif (/C/) { &C_claim($record); } elsif (/P/) { &P_provider($record); } elsif (/D/) { &D_detail($record); } elsif (/M/) { &M_message($record); } } }# end-while # flush out the last records flush_eob(); # close all open files close(INPUT_FILE); close(EOB_FILE); close(EOB_MESSAGE_FILE); close(EOB_CLAIM_FILE); close(EOB_DETAIL_SERVICE_FILE); # print audit trail information print "Total input record count: $input_record_count\n"; print "Total EOB count: $eob_count\n"; print "Total claim count: $claim_count\n"; print "Total detail count: $detail_count\n"; print "Total message count: $message_count\n"; print "Total provider count: $provider_count\n"; print "Processing complete for input file ($input_file)\n"; print "Elapsed time " . (int(time - $start_time)) . " seconds\n"; print "--------------------------\n"; } # --------------------------- # Header record # --------------------------- sub H_header { $eob_count++; # if we aren't on the first record, write out the remaining stuff # for the last EOB we were on if ($input_record_count != 1) { flush_eob(); } # unpack the record into local fields my( $record_type, $fdsn_local, $statement_date_local, $contract_number, $group_number, $plan_inquiry_name, $inquiry_address_line_1, $inquiry_address_line_2, $inquiry_address_line_3, $inquiry_address_line_4, $antifraud_address_line_1, $antifraud_address_line_2, $antifraud_address_line_3, $antifraud_address_line_4, $antifraud_address_line_5, $subscriber_name, $subscriber_address_line_1, $subscriber_address_line_2, $subscriber_address_line_3, $plan_return_address, $plan_return_address_line_1, $plan_return_address_line_2, $plan_return_address_line_3, $plan_return_address_line_4, $your_responsibility, $tag_line_1_name, $tag_line_1_horizonal_coordinates, $tag_line_1_vertical_coordinates, $tag_line_2_name, $tag_line_2_horizonal_coordinates, $tag_line_2_vertical_coordinates, $tag_line_3_name, $tag_line_3_horizonal_coordinates, $tag_line_3_vertical_coordinates, $tag_line_4_name, $tag_line_4_horizonal_coordinates, $tag_line_4_vertical_coordinates, $tag_line_5_name, $tag_line_5_horizonal_coordinates, $tag_line_5_vertical_coordinates, $demand_feed_insert_1, $demand_feed_insert_2, $demand_feed_insert_3, $plan_code, $servicing_code, $total_amount_charged, $total_allowed_amount, $total_other_insurance, $total_deductible, $total_copay, $total_coinsurance, $total_other_amounts_not_covered, $total_amount_paid, $divert_code, $type_of_eob_record, $check_number, $zip_code, $postnet_code, $printable_subscriber_number, $nps_subscriber_number, $financial_leg_local, @rest) = unpack ("a1 a9 a8 a16 a14 a40 a40 a40 a40 a40 a40 a40 a40 a40 a40 a40 a40 a40 a40 a40 a40 a40 a40 a40 a30 a8 a5 a5 a8 a5 a5 a8 a5 a5 a8 a5 a5 a8 a5 a5 a2 a2 a2 a3 a3 a12 a12 a12 a12 a12 a12 a12 a12 a1 a1 a9 a10 a14 a16 a13 a3 a*", "@_"); # debug stuff # print "record_type(" . $record_type . ")\n"; # print "fdsn_local(" . $fdsn_local . ")\n"; # print "statement_date_local(" . $statement_date_local . ")\n"; # print "contract_number(" . $contract_number . ")\n"; # print "group_number(" . $group_number . ")\n"; # print "plan_inquiry_name(" . $plan_inquiry_name . ")\n"; # print "inquiry_address_line_1(" . $inquiry_address_line_1 . ")\n"; # print "inquiry_address_line_2(" . $inquiry_address_line_2 . ")\n"; # print "inquiry_address_line_3(" . $inquiry_address_line_3 . ")\n"; # print "inquiry_address_line_4(" . $inquiry_address_line_4 . ")\n"; # print "antifraud_address_line_1(" . $antifraud_address_line_1 . ")\n"; # print "antifraud_address_line_2(" . $antifraud_address_line_2 . ")\n"; # print "antifraud_address_line_3(" . $antifraud_address_line_3 . ")\n"; # print "antifraud_address_line_4(" . $antifraud_address_line_4 . ")\n"; # print "antifraud_address_line_5(" . $antifraud_address_line_5 . ")\n"; # print "subscriber_name(" . $subscriber_name . ")\n"; # print "subscriber_address_line_1(" . $subscriber_address_line_1 . ")\n"; # print "subscriber_address_line_2(" . $subscriber_address_line_2 . ")\n"; # print "subscriber_address_line_3(" . $subscriber_address_line_3 . ")\n"; # print "plan_return_address(" . $plan_return_address . ")\n"; # print "plan_return_address_line_1(" . $plan_return_address_line_1 . ")\n"; # print "plan_return_address_line_2(" . $plan_return_address_line_2 . ")\n"; # print "plan_return_address_line_3(" . $plan_return_address_line_3 . ")\n"; # print "plan_return_address_line_4(" . $plan_return_address_line_4 . ")\n"; # print "your_responsibility(" . $your_responsibility . ")\n"; # print "tag_line_1_name(" . $tag_line_1_name . ")\n"; # print "tag_line_1_horizonal_coordinates(" . $tag_line_1_horizonal_coordinates . ")\n"; # print "tag_line_1_vertical_coordinates(" . $tag_line_1_vertical_coordinates . ")\n"; # print "tag_line_2_name(" . $tag_line_2_name . ")\n"; # print "tag_line_2_horizonal_coordinates(" . $tag_line_2_horizonal_coordinates . ")\n"; # print "tag_line_2_vertical_coordinates(" . $tag_line_2_vertical_coordinates . ")\n"; # print "tag_line_3_name(" . $tag_line_3_name . ")\n"; # print "tag_line_3_horizonal_coordinates(" . $tag_line_3_horizonal_coordinates . ")\n"; # print "tag_line_3_vertical_coordinates(" . $tag_line_3_vertical_coordinates . ")\n"; # print "tag_line_4_name(" . $tag_line_4_name . ")\n"; # print "tag_line_4_horizonal_coordinates(" . $tag_line_4_horizonal_coordinates . ")\n"; # print "tag_line_4_vertical_coordinates(" . $tag_line_4_vertical_coordinates . ")\n"; # print "tag_line_5_name(" . $tag_line_5_name . ")\n"; # print "tag_line_5_horizonal_coordinates(" . $tag_line_5_horizonal_coordinates . ")\n"; # print "tag_line_5_vertical_coordinates(" . $tag_line_5_vertical_coordinates . ")\n"; # print "demand_feed_insert_1(" . $demand_feed_insert_1 . ")\n"; # print "demand_feed_insert_2(" . $demand_feed_insert_2 . ")\n"; # print "demand_feed_insert_3(" . $demand_feed_insert_3 . ")\n"; # print "plan_code(" . $plan_code . ")\n"; # print "servicing_code(" . $servicing_code . ")\n"; # print "total_amount_charged(" . $total_amount_charged . ")\n"; # print "total_allowed_amount(" . $total_allowed_amount . ")\n"; # print "total_other_insurance(" . $total_other_insurance . ")\n"; # print "total_deductible(" . $total_deductible . ")\n"; # print "total_copay(" . $total_copay . ")\n"; # print "total_coinsurance(" . $total_coinsurance . ")\n"; # print "total_other_amounts_not_covered(" . $total_other_amounts_not_covered . ")\n"; # print "total_amount_paid(" . $total_amount_paid . ")\n"; # print "divert_code(" . $divert_code . ")\n"; # print "type_of_eob_record(" . $type_of_eob_record . ")\n"; # print "check_number(" . $check_number . ")\n"; # print "zip_code(" . $zip_code . ")\n"; # print "postnet_code(" . $postnet_code . ")\n"; # print "printable_subscriber_number(" . $printable_subscriber_number . ")\n"; # print "nps_subscriber_number(" . $nps_subscriber_number . ")\n"; # print "financial_leg_local(" . $financial_leg_local . ")\n"; # print "rest(" . @rest . ")\n"; # print "--------------------\n"; # Fix for pre financial_leg file versions, force to Central Financial (004) if ($financial_leg_local eq " ") { $financial_leg_local = "004"; } # load up the global variables for this EOB $financial_leg=$financial_leg_local; $fdsn=$fdsn_local; $statement_date=$statement_date_local; # Write the EOB record print EOB_FILE pack("A3 A8 A9 A16 A14 A1 A8 A5 A5 A1 A8 A5 A5 A1 A8 A5 A5 A1 A8 A5 A5 A1 A8 A5 A5 A2 A2 A2 A3 A3 A12 A12 A12 A12 A12 A12 A12 A12 A1 A1 A9 A1 A10 A1 A14 A16 A13 A26 A1 A40 A1 A40 A1 A40 A1 A40 A1 A40 A1 A40 A1 A40 A1 A40 A1 A40 A1 A40 A1 A40 A1 A40 A1 A40 A1 A40 A1 A40 A1 A40 A1 A40 A1 A40 A1 A40 A1 A30 A1 A1 A1", $financial_leg_local, toYMD($statement_date_local), $fdsn_local, $contract_number, $group_number, defined(trimToUndef($tag_line_1_name)) ? "N" : "Y", $tag_line_1_name, $tag_line_1_horizonal_coordinates, $tag_line_1_vertical_coordinates, defined(trimToUndef($tag_line_2_name)) ? "N" : "Y", $tag_line_2_name, $tag_line_2_horizonal_coordinates, $tag_line_2_vertical_coordinates, defined(trimToUndef($tag_line_3_name)) ? "N" : "Y", $tag_line_3_name, $tag_line_3_horizonal_coordinates, $tag_line_3_vertical_coordinates, defined(trimToUndef($tag_line_4_name)) ? "N" : "Y", $tag_line_4_name, $tag_line_4_horizonal_coordinates, $tag_line_4_vertical_coordinates, defined(trimToUndef($tag_line_5_name)) ? "N" : "Y", $tag_line_5_name, $tag_line_5_horizonal_coordinates, $tag_line_5_vertical_coordinates, $demand_feed_insert_1, $demand_feed_insert_2, $demand_feed_insert_3, $plan_code, $servicing_code, ## WTC - Mass file doesnt contain formatting, so removing the call to eat the dollar sign and comma. # launderMoney($total_amount_charged), # launderMoney($total_allowed_amount), # launderMoney($total_other_insurance), # launderMoney($total_deductible), # launderMoney($total_copay), # launderMoney($total_coinsurance), # launderMoney($total_other_amounts_not_covered), # launderMoney($total_amount_paid), $total_amount_charged, $total_allowed_amount, $total_other_insurance, $total_deductible, $total_copay, $total_coinsurance, $total_other_amounts_not_covered, $total_amount_paid, ## $divert_code, $type_of_eob_record, $check_number, defined(trimToUndef($zip_code)) ? "N" : "Y", $zip_code, defined(trimToUndef($postnet_code)) ? "N" : "Y", $postnet_code, $printable_subscriber_number, $nps_subscriber_number, $db2_insert_timestamp, defined(trimToUndef($plan_inquiry_name)) ? "N" : "Y", $plan_inquiry_name, defined(trimToUndef($inquiry_address_line_1)) ? "N" : "Y", $inquiry_address_line_1, defined(trimToUndef($inquiry_address_line_2)) ? "N" : "Y", $inquiry_address_line_2, defined(trimToUndef($inquiry_address_line_3)) ? "N" : "Y", $inquiry_address_line_3, defined(trimToUndef($inquiry_address_line_4)) ? "N" : "Y", $inquiry_address_line_4, defined(trimToUndef($antifraud_address_line_1)) ? "N" : "Y", $antifraud_address_line_1, defined(trimToUndef($antifraud_address_line_2)) ? "N" : "Y", $antifraud_address_line_2, defined(trimToUndef($antifraud_address_line_3)) ? "N" : "Y", $antifraud_address_line_3, defined(trimToUndef($antifraud_address_line_4)) ? "N" : "Y", $antifraud_address_line_4, defined(trimToUndef($antifraud_address_line_5)) ? "N" : "Y", $antifraud_address_line_5, defined(trimToUndef($subscriber_name)) ? "N" : "Y", $subscriber_name, defined(trimToUndef($subscriber_address_line_1)) ? "N" : "Y", $subscriber_address_line_1, defined(trimToUndef($subscriber_address_line_2)) ? "N" : "Y", $subscriber_address_line_2, defined(trimToUndef($subscriber_address_line_3)) ? "N" : "Y", $subscriber_address_line_3, defined(trimToUndef($plan_return_address)) ? "N" : "Y", $plan_return_address, defined(trimToUndef($plan_return_address_line_1)) ? "N" : "Y", $plan_return_address_line_1, defined(trimToUndef($plan_return_address_line_2)) ? "N" : "Y", $plan_return_address_line_2, defined(trimToUndef($plan_return_address_line_3)) ? "N" : "Y", $plan_return_address_line_3, defined(trimToUndef($plan_return_address_line_4)) ? "N" : "Y", $plan_return_address_line_4, defined(trimToUndef($your_responsibility)) ? "N" : "Y", $your_responsibility, "Y", "Y", "Y"); print EOB_FILE "\n"; } # -------------------------------------------- # Provider record # -------------------------------------------- sub P_provider { $provider_count++; # parse the input record into different fields my ( $record_type, $fdsn, $statement_date, $contract_number, $patient_name, $icn, $provider_number, $servicing_provider_number, $provider_name, $servicing_provider_name, $sequence_number, $activation_plan) = unpack("a1 a9 a8 a16 a50 a14 a14 a14 a50 a50 a3 a3", "@_"); # debug stuff #print "record_type(" . $record_type . ")\n"; #print "fdsn(" . $fdsn . ")\n"; #print "statement_date(" . $statement_date . ")\n"; #print "contract_number(" . $contract_number . ")\n"; #print "patient_name(" . $patient_name . ")\n"; #print "icn(" . $icn . ")\n"; #print "provider_number($provider_number)\n"; #print "servicing_provider_number($servicing_provider_number)\n"; #print "provider_name($provider_name)\n"; #print "servicing_provider_name($servicing_provider_name)\n"; #print "sequence_number(" . $sequence_number . ")\n"; #print "activation_plan(" . $activation_plan . ")\n"; #print "----------------------------\n"; # store the provider details in an array # (in a hash) for # later insertion into the claim record $provider_hash{"$icn"} = [ $provider_number, $servicing_provider_number, $provider_name, $servicing_provider_name ]; # alternate method of storing array reference in the hash # my(@provider_rec) = ( # $provider_number, # $servicing_provider_number, # $provider_name, # $servicing_provider_name ); # $provider_hash{"$icn"} = \@provider_rec; } # ----------------------------------------------- # Claim record # ----------------------------------------------- sub C_claim { $claim_count++; # store the claim record into an array for later use push(@claim_recs, "@_"); } # ----------------------------------------------- # Process Claim record # ----------------------------------------------- sub C_write_claims { # loop through all claim records in the array and write # each one to the output file foreach (@claim_recs) { # parse the input record into different fields my ( $record_type, $fdsn, $statement_date, $contract_number, $patient_name, $icn, $total_amount_charged, $total_allowed_amount, $total_other_insurance, $total_deductible, $total_copay, $total_coinsurance, $total_other_amounts_not_covered, $total_amount_paid, $notice_line, ## WTC - Relocated reason_code field to end of record, this displacement is now filler ## $reason_code, $filler, $sequence_number, $pat_sequence_number, $activation_plan, $total_discount, $total_your_responsibility, $reason_code) = unpack("a1 a9 a8 a16 a50 a14 a12 a12 a12 a12 a12 a12 a12 a12 a50 a4 a3 a3 a3 a12 a12 a12", "$_"); # = unpack("a1 a9 a8 a16 a50 a14 a12 a12 a12 a12 a12 a12 a12 a12 a50 a4 a3 a3 a3", "$_"); # debug stuff ## WTC - Added new fields to the debug section. #print "record_type(" . $record_type . ")\n"; #print "fdsn(" . $fdsn . ")\n"; #print "statement_date(" . $statement_date . ")\n"; #print "contract_number(" . $contract_number . ")\n"; #print "patient_name(" . $patient_name . ")\n"; #print "icn(" . $icn . ")\n"; #print "total_amount_charged(" . $total_amount_charged . ")\n"; #print "total_allowed_amount(" . $total_allowed_amount . ")\n"; #print "total_other_insurance(" . $total_other_insurance . ")\n"; #print "total_deductible(" . $total_deductible . ")\n"; #print "total_copay(" . $total_copay . ")\n"; #print "total_coinsurance(" . $total_coinsurance . ")\n"; #print "total_other_amounts_not_covered(" . $total_other_amounts_not_covered . ")\n"; #print "total_amount_paid(" . $total_amount_paid . ")\n"; #print "notice_line(" . $notice_line . ")\n"; #print "filler(" . $filler . ")\n"; #print "sequence_number(" . $sequence_number . ")\n"; #print "pat_sequence_number(" . $pat_sequence_number . ")\n"; #print "activation_plan(" . $activation_plan . ")\n"; #print "total_discount(" . $total_discount . ")\n"; #print "total_your_responsibility(" . $total_your_responsibility . ")\n"; #print "reason_code(" . $reason_code . ")\n"; #print "----------------------------\n"; # retrieve the provider values from the hash # hint. it's a reference to an array my($provider_rec) = $provider_hash{"$icn"}; # debug stuff # print "($provider_rec->[0])\n"; # print "($provider_rec->[1])\n"; # print "($provider_rec->[2])\n"; # print "($provider_rec->[3])\n"; # write the claim record print EOB_CLAIM_FILE pack("A3 A8 A9 A14 A3 A3 A12 A12 A12 A12 A12 A12 A12 A12 A4 A14 A1 A14 A1 A50 A1 A50 A1 A50 A3 A1 A50 A26 A16", $financial_leg, toYMD($statement_date), $fdsn, $icn, $sequence_number, $activation_plan, ## WTC - Mass file doesnt contain formatting, so removing the call to eat the dollar sign and comma. # launderMoney($total_amount_charged), # launderMoney($total_allowed_amount), # launderMoney($total_other_insurance), # launderMoney($total_deductible), # launderMoney($total_copay), # launderMoney($total_coinsurance), # launderMoney($total_other_amounts_not_covered), # launderMoney($total_amount_paid), $total_amount_charged, $total_allowed_amount, $total_other_insurance, $total_deductible, $total_copay, $total_coinsurance, $total_other_amounts_not_covered, $total_amount_paid, ## $reason_code, $provider_rec->[0], # provider number defined(trimToUndef($provider_rec->[1])) ? "N" : "Y", $provider_rec->[1], # servicing provider number defined(trimToUndef($provider_rec->[2])) ? "N" : "Y", $provider_rec->[2], # provider name defined(trimToUndef($provider_rec->[3])) ? "N" : "Y", $provider_rec->[3], # servicing provider name defined(trimToUndef($patient_name)) ? "N" : "Y", $patient_name, $pat_sequence_number, defined(trimToUndef($notice_line)) ? "N" : "Y", $notice_line, $db2_insert_timestamp, $contract_number); print EOB_CLAIM_FILE "\n"; }# end-foreach } # ------------------------------------------- # Detail Service record # ------------------------------------------- sub D_detail { $detail_count++; # parse the input record into different individual fields my ($record_type, $fdsn, $statement_date, $contract_number, $icn, $provider_number, $servicing_provider_number, $dates_of_service_from, $dates_of_service_to, ## WTC - Relocated description_of_services field to end of record, this displacement is now filler ## $description_of_services, $filler1, $amount_charged, $allowed_amount, $other_insurance, $deductible, $copay, $coinsurance, $other_amounts_not_covered, $amount_paid, ## WTC - Relocated rsn_code field to end of record, this displacement is now filler ## $rsn_code, $filler2, $exclude_from_totals, $provider_name, $sequence_number, $activation_plan, $discount, $your_responsibility, $description_of_services, $rsn_code) = unpack("a1 a9 a8 a16 a14 a14 a14 a8 a8 a21 a12 a12 a12 a12 a12 a12 a12 a12 a4 a1 a32 a4 a3 a12 a12 a60 a12", "@_"); # = unpack("a1 a9 a8 a16 a14 a14 a14 a8 a8 a21 a12 a12 a12 a12 a12 a12 a12 a12 a4 a1 a32 a4 a3", "@_"); # debug stuff ## WTC - Added new fields to the debug section. # print "record_type(" . $record_type . ")\n"; # print "fdsn(" . $fdsn . ")\n"; # print "statement_date(" . $statement_date . ")\n"; # print "contract_number(" . $contract_number . ")\n"; # print "icn(" . $icn . ")\n"; # print "provider_number(" . $provider_number . ")\n"; # print "servicing_provider_number(" . $servicing_provider_number . ")\n"; # print "dates_of_service_from(" . $dates_of_service_from . ")\n"; # print "dates_of_service_to(" . $dates_of_service_to . ")\n"; # print "filler1(" . $filler1 . ")\n"; # print "amount_charged(" . $amount_charged . ")\n"; # print "allowed_amount(" . $allowed_amount . ")\n"; # print "other_insurance(" . $other_insurance . ")\n"; # print "deductible(" . $deductible . ")\n"; # print "copay(" . $copay . ")\n"; # print "coinsurance(" . $coinsurance . ")\n"; # print "other_amounts_not_covered(" . $other_amounts_not_covered . ")\n"; # print "amount_paid(" . $amount_paid . ")\n"; # print "filler2(" . $filler2 . ")\n"; # print "exclude_from_totals(" . $exclude_from_totals . ")\n"; # print "provider_name(" . $provider_name . ")\n"; # print "sequence_number(" . $sequence_number . ")\n"; # print "activation_plan(" . $activation_plan . ")\n"; # print "discount(" . $discount . ")\n"; # print "your_responsibility(" . $your_responsibility . ")\n"; # print "description_of_services(" . $description_of_services . ")\n"; # print "rsn_code(" . $rsn_code . ")\n"; # print "--------------------------\n"; # write the detail service record print EOB_DETAIL_SERVICE_FILE pack("A3 A8 A9 A14 A4 A8 A8 A12 A12 A12 A12 A12 A12 A12 A12 A4 A1 A21 A26", $financial_leg, toYMD($statement_date), $fdsn, $icn, $sequence_number, toYMD($dates_of_service_from), toYMD($dates_of_service_to), ## WTC - Mass file doesnt contain formatting, so removing the call to eat the dollar sign and comma. # launderMoney($amount_charged), # launderMoney($allowed_amount), # launderMoney($other_insurance), # launderMoney($deductible), # launderMoney($copay), # launderMoney($coinsurance), # launderMoney($other_amounts_not_covered), # launderMoney($amount_paid), $amount_charged, $allowed_amount, $other_insurance, $deductible, $copay, $coinsurance, $other_amounts_not_covered, $amount_paid, ## $rsn_code, $exclude_from_totals, $description_of_services, $db2_insert_timestamp); print EOB_DETAIL_SERVICE_FILE "\n"; } # ----------------------------------------------- # Write the Message record(s) # One for each message_group # ----------------------------------------------- sub M_write_messages { if (@messages) { foreach my $message_rec (@messages) { print EOB_MESSAGE_FILE pack("$eob_message_template", $financial_leg, toYMD($statement_date), $fdsn, $message_rec->[0], # message_group $message_rec->[1], # message_type $message_rec->[2], # message_number defined(trimToUndef($message_rec->[3])) ? "N" : "Y", $message_rec->[3], # patient_name $message_rec->[4], # patient sequence number defined(trimToUndef($message_rec->[5])) ? "N" : "Y", $message_rec->[5], # icn $db2_insert_timestamp, defined(trimToUndef(trimFinalSep($message_rec->[6]))) ? "N" : "Y", trimFinalSep($message_rec->[6]) #message ); print EOB_MESSAGE_FILE "\n"; } # end-foreach } # end-if } # ----------------------------------------------- # Message record # Here we combine all individual message records for # the same message group. # ----------------------------------------------- sub M_message { $message_count++; # parse the input record into the individual message record fields my( $record_type, $fdsn, $statement_date, $contract_number, $patient_name, $icn, $message_sequence, $message, $patient_sequence_number, $activation_plan, $message_type, $message_number, $message_group) = unpack ("A1 A9 A8 A16 A50 A14 A4 A113 A3 A3 A1 A4 A4", "@_"); # ensure the message data doesn't contain the logical record separator if ($message =~s/$MESSAGE_SEPARATOR/$MESSAGE_SEPARATOR2/g){ print "Separator ($MESSAGE_SEPARATOR) found in message record (@_), replacing with ($MESSAGE_SEPARATOR2)\n"; } # concat the individual records together and save # for the final flush. if (!(@messages) || ($messages[-1]->[0] ne "$message_group")) { push(@messages,[$message_group, $message_type, $message_number, $patient_name, $patient_sequence_number, $icn, trim($message) . $MESSAGE_SEPARATOR]); } else { $messages[-1]->[6] .= (trim($message). $MESSAGE_SEPARATOR); } } # ------------------------------------------------ # Perform final processing for the logical EOB # ------------------------------------------------ sub flush_eob { # write the claim records C_write_claims(); # write the message records M_write_messages(); # Reinitialize the global variables @claim_recs = (); %provider_hash = (); @messages = (); } # -------------------------------------------------------- # Remove whitespace from the end of the string only # -------------------------------------------------------- sub trim($) { my $string = shift; ## $string =~ s/^\s+//; $string =~ s/\s+$//; return $string; } # -------------------------------------------------------- # Remove whitespace from the end of the string only # return undef if blank string # -------------------------------------------------------- sub trimToUndef($) { my $string = shift; $string =~ s/\s+$//; return ($string eq '') ? undef : $string; } # -------------------------------------------------------- # Transform a MMDDYYYY date string into a YYYYMMDD date string # -------------------------------------------------------- sub toYMD($) { my $mdy = shift; return substr($mdy, 4, 4) . substr($mdy, 0, 4); } # -------------------------------------------------------- # Remove unwanted characters from monetary amount fields # ensure length is always 12 # -------------------------------------------------------- sub launderMoney($) { my $amt = shift; $amt=~s/,|\$//g; return sprintf "%12s", $amt; } # -------------------------------------------------------- # Trim the final trailing separator from the message # -------------------------------------------------------- sub trimFinalSep($) { my $msg = shift; return substr($msg, 0, length($msg) - $sep_length); }