class Era835Parser::Parser
Constants
- ADJUSTMENT_CODES
- ADJUSTMENT_GROUP_CODES
- CLAIM_STATUS_CODES
- PROVIDER_LEVEL_ADJUSTMENTS
- REMARK_CODES
Attributes
file[R]
file_path[R]
Public Class Methods
new(**options)
click to toggle source
# File lib/era_835_parser/parser.rb, line 15 def initialize(**options) @file_path = options[:file_path] @file = options[:file] end
Public Instance Methods
parse()
click to toggle source
# File lib/era_835_parser/parser.rb, line 20 def parse # hash initialization era = Hash.new checks = Hash.new check = Hash.new line_items = Hash.new adjustment_groups = Hash.new adjustments = Hash.new individual_era = Hash.new individual_line_item = Hash.new check_number = '' era_text = "--------------------------------------------------------------------------------------------------------------------------------------------------------\n" # counters adjustment_counter = 0 adjustment_counter_a = -1 svc_counter = 0 # trigger variables adjustments_start = false checks_start = false eras_start = false next_line_check_number = false next_line_address = false next_line_city = false next_line_tax_id = false next_line_payer_claim_control = false next_line_claim_statement_period = false next_line_line_item = false next_line_adjustment_group = false # file type file_type = '' # loops payer_identification_loop = false payee_identification_loop = false header_number_loop = false claim_payment_information_loop = false patient_loop = false rendering_provider_loop = false service_payment_information_loop = false bpr_amount = '' bpr_date = '' receive_date = false claim_date_start = false claim_date_end = false service_date = false floating_adjustment_group_code = nil returned_reference_number = false file_or_file_path = !file.nil? ? file : file_path opened_file = file_or_file_path.respond_to?(:write) ? file_or_file_path : open(file_or_file_path) opened_file.readlines.each do |line| if line.include?("ISA") file_type = "machine_readable" elsif line.include?("Dear:") file_type = "human_readable" end if file_type == "human_readable" era_text += line if eras_start && line !~ /-{10,}/i if line.include?("Dear:") era[:addressed_to] = line.gsub("Dear:", "").strip end if line !~ /={10,}/i && adjustments_start == true adjustment = Hash.new adjustment[:adjustment_date] = /\d+\/\d+\/\d+/.match(line)[0].strip if !/\d+\/\d+\/\d+/.match(line).nil? adjustment[:provider_id] = /\d+\/\d+\/\d+\s+\d+\s+[^\s]+/.match(line)[0].split(" ")[1].strip if !/\d+\/\d+\/\d+\s+\d+\s+[^\s]+/.match(line).nil? adjustment[:reference_id] = /\d+\/\d+\/\d+\s+[^\.]+/.match(line)[0].split(" ").each_with_index.map { |x,i| (/\d+\/\d+\/\d+\s+[^\.]+/.match(line)[0].split(" ").count - 1) > i && i > 1 ? x.strip : '' }.join(" ").strip if !/\d+\/\d+\/\d+\s+[^\.]+/.match(line).nil? adjustment[:adjustment_amount] = (/\d+\/\d+\/\d+\s+[^\.]+\.\d+/.match(line)[0].split(" ")[-1].strip.to_f * 100).round().to_i if !/\d+\/\d+\/\d+\s+[^\.]+\.\d+/.match(line).nil? adjustment[:reason] = line.gsub(/\d+\/\d+\/\d+\s+[^\.]+\.\d+/, "").strip adjustments[adjustment_counter] = adjustment adjustment_counter += 1 end if line !~ /={10,}/i && checks_start == true && line !~ /^\s+$/ && line !~ /-{10,}/i check = Hash.new check[:check_number] = /^[^\s]+(?=\s)/.match(line)[0] if !/^[^\s]+(?=\s)/.match(line).nil? check[:amount] = (/^[^\s]+\s+\d+\.\d+(?=\s)/.match(line)[0].split(" ")[1].strip.to_f * 100).round().to_i if !/^[^\s]+\s+\d+\.\d+(?=\s)/.match(line).nil? check[:number_of_claims] = /^[^\s]+\s+\d+\.\d+\s+\d+(?=\s)/.match(line)[0].split(" ")[2].strip.to_i if !/^[^\s]+\s+\d+\.\d+\s+\d+(?=\s)/.match(line).nil? check[:npi_tax_id] = /^[^\s]+\s+\d+\.\d+\s+\d+\s+[^\s]+/.match(line)[0].split(" ")[3].strip if !/^[^\s]+\s+\d+\.\d+\s+\d+\s+[^\s]+/.match(line).nil? check[:date] = /\d+\/\d+\/\d+/.match(line)[0] if !/\d+\/\d+\/\d+/.match(line).nil? check[:payee] = line.gsub(check[:check_number].to_s, "").gsub(check[:npi_tax_id].to_s, "").gsub(check[:amount].to_s, "").gsub(/\d/, "").gsub(/\./, "").gsub(/\//, "").strip checks[check[:check_number]] = check end if next_line_line_item individual_line_item = Hash.new adjustment_groups = Hash.new end if line.include?("Line Item:") || line =~ /-{10,}/i || line =~ /^\s+$/ next_line_adjustment_group = false end if next_line_adjustment_group && individual_adjustment_group_item = Hash.new individual_adjustment_group_item[:adjustment_group] = /.+\s+\-?\d+\.\d+/.match(line)[0].strip.split(/\s+\-?\d+/)[0].strip if !/.+\s+\-?\d+\.\d+/.match(line).nil? individual_adjustment_group_item[:adjustment_amount] = (/\-?\d+\.\d+/.match(line)[0].strip.to_f * 100).round().to_i if !/\-?\d+\.\d+/.match(line).nil? individual_adjustment_group_item[:translated_reason_code] = /\-?\d+\.\d+\s+.+/.match(line)[0].strip.split(/(?:\d)\s/)[1].strip if !/\-?\d+\.\d+\s+.+/.match(line).nil? if adjustment_groups.nil? adjustment_groups[0] = individual_adjustment_group_item else adjustment_groups[adjustment_groups.count] = individual_adjustment_group_item end individual_line_item[:adjustment_groups] = adjustment_groups end if line.include?("Adjustment Group") next_line_adjustment_group = true end if next_line_line_item individual_line_item[:service_date] = /\d+\/\d+\/\d+/.match(line)[0].strip if !/\d+\/\d+\/\d+/.match(line).nil? individual_line_item[:cpt_code] = /\d+\/\d+\/\d+\s\d+/.match(line)[0].strip.split(" ")[1] if !/\d+\/\d+\/\d+\s\d+/.match(line).nil? individual_line_item[:charge_amount] = (/\d+\/\d+\/\d+\s\d+\s+\-?\d+\.\d+/.match(line)[0].strip.split(" ")[2].to_f * 100).round().to_i if !/\d+\/\d+\/\d+\s\d+\s+\-?\d+\.\d+/.match(line).nil? individual_line_item[:payment_amount] = (/\d+\/\d+\/\d+\s\d+\s+\-?\d+\.\d+\s+\-?\d+\.\d+/.match(line)[0].strip.split(" ")[3].to_f * 100).round().to_i if !/\d+\/\d+\/\d+\s\d+\s+\-?\d+\.\d+\s+\-?\d+\.\d+/.match(line).nil? individual_line_item[:total_adjustment_amount] = (/\d+\/\d+\/\d+\s\d+\s+\-?\d+\.\d+\s+\-?\d+\.\d+\s+\-?\d+\.\d+/.match(line)[0].strip.split(" ")[4].to_f * 100).round().to_i if !/\d+\/\d+\/\d+\s\d+\s+\-?\d+\.\d+\s+\-?\d+\.\d+\s+\-?\d+\.\d+/.match(line).nil? individual_line_item[:remarks] = line.gsub(/\d+\/\d+\/\d+\s\d+\s+\-?\d+\.\d+\s+\-?\d+\.\d+\s+\-?\d+\.\d+/, "").strip if !/\d+\/\d+\/\d+\s\d+\s+\-?\d+\.\d+\s+\-?\d+\.\d+\s+\-?\d+\.\d+/.match(line).nil? if line_items.nil? if individual_line_item[:service_date].nil? individual_line_item[:service_date] = individual_era[:claim_statement_period_start] end line_items[0] = individual_line_item else if individual_line_item[:service_date].nil? individual_line_item[:service_date] = individual_era[:claim_statement_period_start] end line_items[line_items.count] = individual_line_item end next_line_line_item = false end if line.include?("Line Item:") next_line_line_item = true end if next_line_claim_statement_period && line.include?("Claim Statement Period") individual_era[:claim_statement_period_start] = line.gsub("Claim Statement Period:", "").strip.split("-")[0].strip individual_era[:claim_statement_period_end] = line.gsub("Claim Statement Period:", "").strip.split("-")[1].strip next_line_claim_statement_period = false elsif next_line_claim_statement_period next_line_claim_statement_period = false end if next_line_payer_claim_control && line.include?("Payer Claim Control Number") individual_era[:payer_claim_control_number] = line.gsub("Payer Claim Control Number:", "").strip next_line_payer_claim_control = false next_line_claim_statement_period = true elsif next_line_payer_claim_control next_line_payer_claim_control = false next_line_claim_statement_period = true end if next_line_tax_id && line.include?("Tax ID") era[:checks][check_number][:payer_tax_id] = line.gsub("Tax ID:", "").strip next_line_tax_id = false next_line_payer_claim_control = true elsif next_line_tax_id next_line_tax_id = false next_line_payer_claim_control = true end if next_line_city if line.include?(",") era[:checks][check_number][:payer_city] = line.strip.split(",")[0].strip era[:checks][check_number][:payer_state] = line.strip.split(",")[1].split(" ")[0].strip era[:checks][check_number][:payer_zip_code] = line.strip.split(",")[1].split(" ")[1].strip next_line_city = false next_line_tax_id = true else era[:checks][check_number][:payer_address] = era[:checks][check_number][:payer_address] + " " + line.strip end end if next_line_address era[:checks][check_number][:payer_address] = line.strip next_line_address = false next_line_city = true end if next_line_check_number check_number = /^[^\s]+(?=\s)/.match(line)[0].strip if !/^[^\s]+(?=\s)/.match(line).nil? next_line_check_number = false individual_era[:patient_id] = /^[^\s]+(?=\s)\s+[^\s]+/.match(line)[0].strip.split(" ")[1] if !/^[^\s]+(?=\s)\s+[^\s]+/.match(line).nil? individual_era[:patient_name] = /\s\D*,\D*\s/.match(line)[0].strip if !/\s\D*,\D*\s/.match(line).nil? individual_era[:patient_last_name] = individual_era[:patient_name].split(",")[0].downcase.split(" ").map { |word| word.capitalize }.join(" ") if !individual_era[:patient_name].split(",")[0].nil? individual_era[:patient_first_name] = individual_era[:patient_name].split(",")[1].downcase.split(" ").map { |word| word.capitalize }.join(" ") if !individual_era[:patient_name].split(",")[1].nil? individual_era[:charge_amount] = (/,\D+\d+\.\d+\s/.match(line)[0].gsub(/[a-zA-Z,]/, "").strip.to_f * 100).round().to_i if !/,\D+\d+\.\d+\s/.match(line).nil? individual_era[:payment_amount] = (/\.\d+\s+\-?\d+\.\d+\s/.match(line)[0].strip.split(" ")[1].strip.to_f * 100).round().to_i if !/\.\d+\s+\-?\d+\.\d+\s/.match(line).nil? individual_era[:account_number] = /\.\d+\s+\-?\d+\.\d+\s+[A-Z\d]+\s/.match(line)[0].strip.split(" ")[2] if !/\.\d+\s+\-?\d+\.\d+\s+[A-Z\d]+\s/.match(line).nil? if !/PROCESSED AS PRIMARY\s+.+$/.match(line).nil? && !/^[^\s]+(?=\s)/.match(line).nil? individual_era[:status] = "PROCESSED AS PRIMARY" era[:checks][check_number][:payer_name] = /PROCESSED AS PRIMARY\s+.+$/.match(line)[0].gsub("PROCESSED AS PRIMARY", "").strip elsif !/PROCESSED AS SECONDARY\s+.+$/.match(line).nil? && !/^[^\s]+(?=\s)/.match(line).nil? individual_era[:status] = "PROCESSED AS SECONDARY" era[:checks][check_number][:payer_name] = /PROCESSED AS SECONDARY\s+.+$/.match(line)[0].gsub("PROCESSED AS SECONDARY", "").strip elsif !/PROCESSED AS TERTIARY\s+.+$/.match(line).nil? && !/^[^\s]+(?=\s)/.match(line).nil? individual_era[:status] = "PROCESSED AS TERTIARY" era[:checks][check_number][:payer_name] = /PROCESSED AS TERTIARY\s+.+$/.match(line)[0].gsub("PROCESSED AS TERTIARY", "").strip elsif !/PROCESSED AS PRIMARY,\sFWDED\s+.+$/.match(line).nil? && !/^[^\s]+(?=\s)/.match(line).nil? individual_era[:status] = "PROCESSED AS PRIMARY, FWDED" era[:checks][check_number][:payer_name] = /PROCESSED AS PRIMARY,\sFWDED\s+.+$/.match(line)[0].gsub("PROCESSED AS PRIMARY, FWDED", "").strip elsif !/PROCESSED AS SECONDARY,\sFWDED\s+.+$/.match(line).nil? && !/^[^\s]+(?=\s)/.match(line).nil? individual_era[:status] = "PROCESSED AS SECONDARY, FWDED" era[:checks][check_number][:payer_name] = /PROCESSED AS SECONDARY,\sFWDED\s+.+$/.match(line)[0].gsub("PROCESSED AS SECONDARY, FWDED", "").strip elsif !/PROCESSED AS TERTIARY,\sFWDED\s+.+$/.match(line).nil? && !/^[^\s]+(?=\s)/.match(line).nil? individual_era[:status] = "PROCESSED AS TERTIARY, FWDED" era[:checks][check_number][:payer_name] = /PROCESSED AS TERTIARY,\sFWDED\s+.+$/.match(line)[0].gsub("PROCESSED AS TERTIARY, FWDED", "").strip elsif !/DENIED\s+.+$/.match(line).nil? && !/^[^\s]+(?=\s)/.match(line).nil? individual_era[:status] = "DENIED" era[:checks][check_number][:payer_name] = /DENIED\s+.+$/.match(line)[0].gsub("DENIED", "").strip elsif !/OTHER\s+.+$/.match(line).nil? && !/^[^\s]+(?=\s)/.match(line).nil? individual_era[:status] = "OTHER" era[:checks][check_number][:payer_name] = /OTHER\s+.+$/.match(line)[0].gsub("OTHER", "").strip end next_line_address = true end if line.include?("Check#") && line.include?("Patient ID") next_line_check_number = true individual_era = Hash.new line_items = Hash.new end if eras_start == true && !line.include?("Check#") if line =~ /-{10,}/i if era[:checks][check_number][:eras].nil? era_counter = 0 eras = Hash.new individual_era[:line_items] = line_items individual_era[:era_text] = era_text.strip.gsub(/\r/, "") eras[era_counter] = individual_era era[:checks][check_number][:eras] = eras else era_counter = era[:checks][check_number][:eras].count eras = Hash.new individual_era[:line_items] = line_items individual_era[:era_text] = era_text.strip.gsub(/\r/, "") eras[era_counter] = individual_era era[:checks][check_number][:eras] = era[:checks][check_number][:eras].merge(eras) end era_text = "--------------------------------------------------------------------------------------------------------------------------------------------------------\n" end end if line.include?("Adjustment Date") adjustments_start = true end if line.include?("Check#") && line.include?("# Claims") checks_start = true end if line =~ /={10,}/i && adjustments_start == true && adjustments != {} adjustments_start = false end if line =~ /-{10,}/i && checks_start == true && checks != {} checks_start = false era[:adjustments] = adjustments era[:checks] = checks eras_start = true end else element_types = [] line.split("~").each do |subline| next if subline.strip == "" element_type = /[^\*]+/.match(subline)[0] element_types << element_type # puts "-------------" # puts element_type # puts subline # https://www.healthpartnersplans.com/media/100017241/254_Electronic-Remittance-Advice.pdf subline.split("*").each_with_index do |element, index| case element_type when "ST" # Start of new check payer_identification_loop = false payee_identification_loop = false claim_payment_information_loop = false when "ISA" case index when 1 # Authorization Information Qualifier # puts "Authorization Information Qualifier: #{element}" when 2 # Authorization Information # puts "Authorization Information: #{element}" when 3 # Security Information Qualifier # puts "Security Information Qualifier: #{element}" when 4 # Security Information # puts "Security Information: #{element}" when 5 # Interchange Sender ID Qualifier # puts "Interchange Sender ID Qualifier: #{element}" when 6 # Interchange Sender ID # puts "Interchange Sender ID: #{element}" when 7 # Interchange Receiver ID Qualifier # puts "Interchange Receiver ID Qualifier: #{element}" when 8 # Interchange Receiver ID # puts "Interchange Receiver ID: #{element}" era[:addressed_to] = element.strip.downcase when 9 # Interchange Date # puts "Interchange Date: #{element}" when 10 # Interchange Time # puts "Interchange Time: #{element}" when 11 # Interchange Control Standards Identifier # puts "Interchange Control Standards Identifier: #{element}" when 12 # Interchange Control Version Number # puts "Interchange Control Version Number: #{element}" when 13 # Interchange Control Number # puts "Interchange Control Number: #{element}" when 14 # Acknowledgement Requested # puts "Acknowledgement Requested: #{element}" when 15 # Usage Indicator # puts "Usage Indicator: #{element}" when 16 # Component element Separator # puts "Component element Separator: #{element}" end when "BPR" case index when 1 # Transaction Handling Code # puts "Transaction Handling Code: #{element}" when 2 # Monetary Amount # puts "Monetary Amount: #{element}" bpr_amount = element.strip when 3 # Credit/Debit Flag # puts "Credit/Debit Flag: #{element}" when 4 # PAYMENT METHOD CODE # puts "PAYMENT METHOD CODE: #{element}" when 5 # PAYMENT FORMAT CODE # puts "PAYMENT FORMAT CODE: #{element}" when 6 # (DFI) ID NUMBER QUALIFIER # puts "(DFI) ID NUMBER QUALIFIER: #{element}" when 7 # (DFI) IDENTIFICATION NUMBER # puts "(DFI) IDENTIFICATION NUMBER: #{element}" when 8 # Account Number Qualifier # puts "Account Number Qualifier: #{element}" when 9 # Sender Bank Account Number # puts "Sender Bank Account Number: #{element}" when 10 # ORIGINATING COMPANY IDENTIFIER # puts "ORIGINATING COMPANY IDENTIFIER: #{element}" when 11 # Originating Company Supplemental Code # puts "Originating Company Supplemental Code: #{element}" when 12 # DFI Identification Number Qualifier # puts "DFI Identification Number Qualifier: #{element}" when 13 # Receiver or Provider Bank ID Number # puts "Receiver or Provider Bank ID Number: #{element}" when 14 # ACCOUNT NUMBER QUALIFIER # puts "ACCOUNT NUMBER QUALIFIER: #{element}" when 15 # Receiver or Provider ACCOUNT NUMBER # puts "Receiver or Provider ACCOUNT NUMBER: #{element}" when 16 # Check Issue or EFT Effective Date # puts "Check Issue or EFT Effective Date: #{element}" bpr_date = element.strip[4..5] + "/" + element.strip[6..7] + "/" + element.strip[0..3] end when "GS" case index when 1 # Functional Identifier Code # puts "Functional Identifier Code : #{element}" when 2 # Application Sender Code # puts "Application Sender Code: #{element}" when 3 # Application Receiver ID # puts "Application Receiver ID: #{element}" when 4 # Date # puts "Date: #{element}" when 5 # Time # puts "Time: #{element}" when 6 # Group Control Number # puts "Group Control Number: #{element}" when 7 # Responsible Agency Code # puts "Responsible Agency Code: #{element}" when 8 # Version/Release/Industry Identifier # puts "Version/Release/Industry Identifier: #{element}" end when "TRN" case index when 1 # Trace Type Code # puts "Trace Type Code: #{element}" when 2 # REFERENCE IDENTIFICATION # puts "REFERENCE IDENTIFICATION: #{element}" check = Hash.new check[:check_number] = element.strip check[:amount] = (bpr_amount.to_f * 100).round().to_i bpr_amount = '' check[:date] = bpr_date bpr_date = '' checks[check[:check_number]] = check when 3 # ORIGINATING COMPANY IDENTIFIER # puts "ORIGINATING COMPANY IDENTIFIER: #{element}" era[:checks][check[:check_number]][:payer_tax_id] = element.strip[1..2] + "-" + element.strip[3..-1] when 4 # Originating Company Supplemental Code # puts "Originating Company Supplemental Code: #{element}" end when "N1" if !payer_identification_loop && !payee_identification_loop payer_identification_loop = true end case index when 1 # Payer Identifier Code # puts "Payer Identifier Code: #{element}" when 2 # Payer NAME # puts "Payer NAME: #{element}" if payer_identification_loop era[:checks][check[:check_number]][:payer_name] = element.strip elsif payee_identification_loop era[:checks][check[:check_number]][:payee] = element.strip end when 3 # Identification Code Qualifier # puts "Identification Code Qualifier: #{element}" when 4 # Payer Identification Code # puts "Payer Identification Code: #{element}" if payee_identification_loop era[:checks][check[:check_number]][:npi_tax_id] = element.strip payee_identification_loop = false end end when "N3" case index when 1 # Payer Address Line # puts "Payer Address Line: #{element}" if payer_identification_loop era[:checks][check[:check_number]][:payer_address] = element.strip end when 2 # Payer Address Line # puts "Payer Address Line: #{element}" if payer_identification_loop era[:checks][check[:check_number]][:payer_address] = era[:checks][check[:check_number]][:payer_address] + " " + element.strip end end when "DTM" case index when 1 # Date Time Qualifier # puts "Date Time Qualifier: #{element}" if element == "050" receive_date = true elsif element == "150" service_date = true elsif element == "232" claim_date_start = true elsif element == "233" claim_date_end = true elsif element == "472" service_date = true end when 2 # Service Date # puts "Service Date: #{element}" if service_date individual_line_item[:service_date] = element.strip[4..5] + "/" + element.strip[6..7] + "/" + element.strip[0..3] service_date = false elsif claim_date_start individual_era[:claim_statement_period_start] = element.strip[4..5] + "/" + element.strip[6..7] + "/" + element.strip[0..3] claim_date_start = false elsif claim_date_end individual_era[:claim_statement_period_end] = element.strip[4..5] + "/" + element.strip[6..7] + "/" + element.strip[0..3] claim_date_end = false end end when "N4" case index when 1 # Payer City Name # puts "Payer City Name: #{element}" if payer_identification_loop era[:checks][check[:check_number]][:payer_city] = element.strip end when 2 # Payer State Code # puts "Payer State Code: #{element}" if payer_identification_loop era[:checks][check[:check_number]][:payer_state] = element.strip end when 3 # Payer Postal Zone or Zip Code # puts "Payer Postal Zone or Zip Code: #{element}" if payer_identification_loop era[:checks][check[:check_number]][:payer_zip_code] = element.strip payer_identification_loop = false payee_identification_loop = true end end when "PER" case index when 1 # Contact Function Code # puts "Contact Function Code: #{element}" when 2 # Payer Technical Contact Name # puts "Payer Technical Contact Name: #{element}" when 3 # Communication Number Qualifier # puts "Communication Number Qualifier: #{element}" when 4 # Payer Contact Communication Number # puts "Payer Contact Communication Number: #{element}" when 5 # Payer Contact Communication Number # puts "Payer Contact Communication Number: #{element}" when 6 # Payer Technical Contact Communication # puts "Payer Technical Contact Communication: #{element}" end when "LX" case index when 1 # Claim Sequence Number # puts "Claim Sequence Number: #{element}" end when "CLP" svc_counter = 0 claim_payment_information_loop = true service_payment_information_loop = true if individual_line_item[:service_date].nil? case index when 1 if individual_line_item != {} if line_items.nil? if individual_line_item[:service_date].nil? individual_line_item[:service_date] = individual_era[:claim_statement_period_start] end line_items[0] = individual_line_item else if individual_line_item[:service_date].nil? individual_line_item[:service_date] = individual_era[:claim_statement_period_start] end line_items[line_items.count] = individual_line_item end individual_era[:line_items] = line_items individual_line_item = Hash.new end individual_era = Hash.new line_items = Hash.new adjustment_groups = Hash.new # Patient Control Number # puts "Patient Control Number: #{element}" individual_era[:account_number] = element.strip when 2 # Claim Status Code # puts "Claim Status Code: #{element}" individual_era[:claim_status_code] = element.strip individual_era[:status] = CLAIM_STATUS_CODES[element.strip][1] when 3 # Total Claim Charge Amount # puts "Total Claim Charge Amount: #{element}" individual_era[:charge_amount] = (element.to_f * 100).round().to_i when 4 # Total Claim Payment Amount # puts "Total Claim Payment Amount: #{element}" individual_era[:payment_amount] = (element.to_f * 100).round().to_i when 5 # Patient Responsibility Amount # puts "Patient Responsibility Amount: #{element}" when 6 # Claim Filing Indicator Code # puts "Claim Filing Indicator Code: #{element}" when 7 # Payer Claim Control Number # puts "Payer Claim Control Number: #{element}" individual_era[:payer_claim_control_number] = element.strip if era[:checks][check[:check_number]][:eras].nil? individual_eras = Hash.new individual_eras[0] = individual_era era[:checks][check[:check_number]][:eras] = individual_eras else individual_eras = era[:checks][check[:check_number]][:eras] individual_eras[era[:checks][check[:check_number]][:eras].size] = individual_era era[:checks][check[:check_number]][:eras] = individual_eras end when 8 # Facility Type Code # puts "Facility Type Code: #{element}" when 9 # Claim Frequency Code # puts "Claim Frequency Code: #{element}" when 10 # Patient Status Code # puts "Patient Status Code: #{element}" when 11 # Diagnosis Related Group (DRG) Code # puts "Diagnosis Related Group (DRG) Code: #{element}" when 12 # DRG Weight # puts "DRG Weight: #{element}" when 13 # PERCENT - Discharge Fraction # puts "PERCENT - Discharge Fraction: #{element}" end when "PLB" case index when 1 # Provider Identifier adjustment_counter_a += 1 adjustment = Hash.new adjustment[:provider_id] = element.strip when 2 # Fiscal Period Date adjustment[:adjustment_date] = element.strip[4..5] + "/" + element.strip[6..7] + "/" + element.strip[0..3] when 3 element.split(":").each_with_index do |subelement, i| case i when 0 # PROVIDER ADJUSTMENT REASON CODE # puts "PROVIDER ADJUSTMENT REASON CODE: #{subelement}" adjustment[:reason_code] = subelement.strip adjustment[:reason] = PROVIDER_LEVEL_ADJUSTMENTS[subelement.strip] when 1 # Provider Adjustment Identifier # puts "Provider Adjustment Identifier: #{subelement}" adjustment[:reference_id] = subelement.strip end end when 4 # Provider Adjustment Amount adjustment[:adjustment_amount] = (element.to_f * 100).round().to_i when 5 adjustment_counter_a += 1 element.split(":").each_with_index do |subelement, i| case i when 0 # PROVIDER ADJUSTMENT REASON CODE # puts "PROVIDER ADJUSTMENT REASON CODE: #{subelement}" adjustment[:reason_code] = subelement.strip adjustment[:reason] = PROVIDER_LEVEL_ADJUSTMENTS[subelement.strip] when 1 # Provider Adjustment Identifier # puts "Provider Adjustment Identifier: #{subelement}" adjustment[:reference_id] = subelement.strip end end when 6 # Provider Adjustment Amount adjustment[:adjustment_amount] = (element.to_f * 100).round().to_i when 7 adjustment_counter_a += 1 element.split(":").each_with_index do |subelement, i| case i when 0 # PROVIDER ADJUSTMENT REASON CODE # puts "PROVIDER ADJUSTMENT REASON CODE: #{subelement}" adjustment[:reason_code] = subelement.strip adjustment[:reason] = PROVIDER_LEVEL_ADJUSTMENTS[subelement.strip] when 1 # Provider Adjustment Identifier # puts "Provider Adjustment Identifier: #{subelement}" adjustment[:reference_id] = subelement.strip end end when 8 # Provider Adjustment Amount adjustment[:adjustment_amount] = (element.to_f * 100).round().to_i when 9 adjustment_counter_a += 1 element.split(":").each_with_index do |subelement, i| case i when 0 # PROVIDER ADJUSTMENT REASON CODE # puts "PROVIDER ADJUSTMENT REASON CODE: #{subelement}" adjustment[:reason_code] = subelement.strip adjustment[:reason] = PROVIDER_LEVEL_ADJUSTMENTS[subelement.strip] when 1 # Provider Adjustment Identifier # puts "Provider Adjustment Identifier: #{subelement}" adjustment[:reference_id] = subelement.strip end end when 10 # Provider Adjustment Amount adjustment[:adjustment_amount] = (element.to_f * 100).round().to_i when 11 adjustment_counter_a += 1 element.split(":").each_with_index do |subelement, i| case i when 0 # PROVIDER ADJUSTMENT REASON CODE # puts "PROVIDER ADJUSTMENT REASON CODE: #{subelement}" adjustment[:reason_code] = subelement.strip adjustment[:reason] = PROVIDER_LEVEL_ADJUSTMENTS[subelement.strip] when 1 # Provider Adjustment Identifier # puts "Provider Adjustment Identifier: #{subelement}" adjustment[:reference_id] = subelement.strip end end when 12 # Provider Adjustment Amount adjustment[:adjustment_amount] = (element.to_f * 100).round().to_i when 13 adjustment_counter_a += 1 element.split(":").each_with_index do |subelement, i| case i when 0 # PROVIDER ADJUSTMENT REASON CODE # puts "PROVIDER ADJUSTMENT REASON CODE: #{subelement}" adjustment[:reason_code] = subelement.strip adjustment[:reason] = PROVIDER_LEVEL_ADJUSTMENTS[subelement.strip] when 1 # Provider Adjustment Identifier # puts "Provider Adjustment Identifier: #{subelement}" adjustment[:reference_id] = subelement.strip end end when 14 # Provider Adjustment Amount adjustment[:adjustment_amount] = (element.to_f * 100).round().to_i end adjustments[adjustment_counter_a] = adjustment if adjustment_counter_a > -1 && (adjustment != {} && !adjustment.nil?) when "CAS" case index when 1 # Claim Adjustment Group Code # puts "Claim Adjustment Group Code: #{element}" individual_adjustment_group_item = Hash.new individual_adjustment_group_item[:adjustment_group_code] = element.strip individual_adjustment_group_item[:adjustment_group] = ADJUSTMENT_GROUP_CODES[element.strip] floating_adjustment_group_code = element.strip when 2,5,8,11,14,17 # Adjustment Reason Code if index > 2 individual_adjustment_group_item = Hash.new individual_adjustment_group_item[:adjustment_group_code] = floating_adjustment_group_code individual_adjustment_group_item[:adjustment_group] = ADJUSTMENT_GROUP_CODES[floating_adjustment_group_code] end # puts "Adjustment Reason Code: #{element}" individual_adjustment_group_item[:reason_code] = element.strip individual_adjustment_group_item[:translated_reason_code] = ADJUSTMENT_CODES[element.strip] when 3,6,9,12,15,18 # Adjustment Amount # puts "Adjustment Amount: #{element}" # individual_adjustment_group_item[:adjustment_amount] = (element.to_f * 100).round().to_i # puts individual_adjustment_group_item if adjustment_groups.nil? adjustment_groups[0] = individual_adjustment_group_item else adjustment_groups[adjustment_groups.count] = individual_adjustment_group_item end individual_line_item[:adjustment_groups] = adjustment_groups adjustment_amount_tally = 0 individual_line_item[:adjustment_groups].each do |k,v| adjustment_amount_tally += v[:adjustment_amount] end individual_line_item[:total_adjustment_amount] = adjustment_amount_tally when 4,7,10,13,16,19 # QUANTITY # puts "QUANTITY: #{element}" end when "LQ" case index when 1 # Service Line Remittance Remark Code 1 # puts "Service Line Remittance Remark Code 1: #{element}" when 2 # Service Line Remittance Remark Code 2 # puts "Service Line Remittance Remark Code 2: #{element}" individual_line_item[:remark_code] = element.strip individual_line_item[:remarks] = REMARK_CODES[element.strip] end when "AMT" case index when 1 # Amount Qualifier Code # puts "Amount Qualifier Code: #{element}" when 2 # Service Line Allowed Amount # puts "Service Line Allowed Amount: #{element}" end when "NM1" case index when 1 # Patient Identifier Code # puts "Patient Identifier Code: #{element}" if element == "QC" patient_loop = true else patient_loop = false end if element == "82" rendering_provider_loop = true else rendering_provider_loop = false end when 2 # Entity Type Qualifier # puts "Entity Type Qualifier: #{element}" when 3 # Patient Last Name # puts "Patient Last Name: #{element}" if claim_payment_information_loop && patient_loop individual_era[:patient_last_name] = element.strip.downcase.split(" ").map { |word| word.capitalize }.join(" ") end if claim_payment_information_loop && rendering_provider_loop individual_era[:rendering_provider_last_name] = element.strip.downcase.split(" ").map { |word| word.capitalize }.join(" ") end when 4 # Patient First Name # puts "Patient First Name: #{element}" if claim_payment_information_loop && patient_loop individual_era[:patient_first_name] = element.strip.downcase.split(" ").map { |word| word.capitalize }.join(" ") individual_era[:patient_name] = individual_era[:patient_last_name].upcase + "," + individual_era[:patient_first_name].upcase end if claim_payment_information_loop && rendering_provider_loop individual_era[:rendering_provider_first_name] = element.strip.downcase.split(" ").map { |word| word.capitalize }.join(" ") individual_era[:rendering_provider_name] = individual_era[:rendering_provider_last_name].upcase + "," + individual_era[:rendering_provider_first_name].upcase end when 5 # Patient Middle Initial # puts "Patient Middle Initial: #{element}" when 6 # Name Prefix # puts "Name Prefix: #{element}" when 7 # Patient Name Suffix # puts "Patient Name Suffix: #{element}" when 8 # Identification Code Qualifier # puts "Identification Code Qualifier: #{element}" when 9 # Patient Member Number # puts "Patient Member Number: #{element}" if claim_payment_information_loop && patient_loop individual_era[:patient_id] = element.strip end end when "SVC" case index when 1 svc_counter += 1 if individual_line_item != {} && svc_counter > 1 if line_items.nil? if individual_line_item[:service_date].nil? individual_line_item[:service_date] = individual_era[:claim_statement_period_start] end line_items[0] = individual_line_item else if individual_line_item[:service_date].nil? individual_line_item[:service_date] = individual_era[:claim_statement_period_start] end line_items[line_items.count] = individual_line_item end individual_era[:line_items] = line_items individual_line_item = Hash.new end adjustment_groups = Hash.new service_payment_information_loop = true if individual_line_item[:service_date].nil? element.split(":").each_with_index do |subelement, i| case i when 0 # Service Type Code # puts "Service Type Code: #{subelement}" when 1 # Service Code # puts "Service Code: #{subelement}" individual_line_item[:cpt_code] = subelement.strip end end when 2 # Monetary Amount (Charge amount) # puts "Monetary Amount (Charge amount): #{element}" individual_line_item[:charge_amount] = (element.to_f * 100).round().to_i when 3 # Monetary Amount (Payment amount) # puts "Monetary Amount (Payment amount): #{element}" individual_line_item[:payment_amount] = (element.to_f * 100).round().to_i when 4 # NUBC Revenue Code # puts "NUBC Revenue Code: #{element}" when 5 # Units of Service Paid Count # puts "Units of Service Paid Count: #{element}" when 6 element.split(":").each_with_index do |subelement, i| case index when 1 # PRODUCT/SERVICE ID QUALIFIER # puts "PRODUCT/SERVICE ID QUALIFIER: #{element}" when 2 # Procedure Code # puts "Procedure Code: #{element}" end end when 7 # Original Units of Service Count # puts "Original Units of Service Count: #{element}" end when "REF" case index when 1 # Additional Payee Identification Qualifier # puts "Additional Payee Identification Qualifier: #{element}" returned_reference_number = true if element == '6R' when 2 # Reference Identification Code # puts "Reference Identification Code: #{element}" if individual_line_item != {} && svc_counter >= 1 && returned_reference_number && !element.nil? individual_line_item[:reference_number] = element returned_reference_number = false end when 3 # Additional Payee Identification Qualifier # puts "Additional Payee Identification Qualifier: #{element}" when 4 # Reference Identification Code # puts "Reference Identification Code: #{element}" end end era[:checks] = checks end end end end if file_type == "human_readable" if era[:checks][check_number][:eras].nil? era_counter = 0 eras = Hash.new individual_era[:line_items] = line_items individual_era[:era_text] = era_text.strip.gsub(/\r/, "") eras[era_counter] = individual_era era[:checks][check_number][:eras] = eras else era_counter = era[:checks][check_number][:eras].count eras = Hash.new individual_era[:line_items] = line_items individual_era[:era_text] = era_text.strip.gsub(/\r/, "") eras[era_counter] = individual_era era[:checks][check_number][:eras] = era[:checks][check_number][:eras].merge(eras) end return era else if individual_line_item != {} if line_items.nil? if individual_line_item[:service_date].nil? individual_line_item[:service_date] = individual_era[:claim_statement_period_start] end line_items[0] = individual_line_item else if individual_line_item[:service_date].nil? individual_line_item[:service_date] = individual_era[:claim_statement_period_start] end line_items[line_items.count] = individual_line_item end individual_era[:line_items] = line_items end era[:adjustments] = adjustments if adjustments != {} era[:checks].each do |i, check| if check[:eras].nil? era[:checks][check[:check_number]][:number_of_claims] = 0 else era[:checks][check[:check_number]][:number_of_claims] = check[:eras].size end if !check[:eras].nil? check[:eras].each do |era_counter, individual_era| line_items = '' if !individual_era[:line_items].nil? individual_era[:line_items].each do |line_item_counter, line_item| if line_item[:remarks].nil? remark = "NO REMARKS" else remark = truncate(line_item[:remarks], 82) end line_items += "#{" " * (22)}#{line_item[:service_date]} #{line_item[:cpt_code]}#{" " * (7 - get_length(line_item[:cpt_code]))}#{'%.2f' % (line_item[:charge_amount].to_f / 100)}#{" " * (13 - get_length('%.2f' % (line_item[:charge_amount].to_f / 100)))}#{'%.2f' % (line_item[:payment_amount].to_f / 100)}#{" " * (13 - get_length('%.2f' % (line_item[:payment_amount].to_f / 100)))}#{'%.2f' % (line_item[:total_adjustment_amount].to_f / 100)}#{" " * (15 - get_length('%.2f' % (line_item[:total_adjustment_amount].to_f / 100)))}#{remark}\n\n" if !line_item[:adjustment_groups].nil? line_item[:adjustment_groups].each do |adjustment_group_counter, adjustment_group| line_items += " Adjustment Group Adj Amt Translated Reason Code\n" if adjustment_group_counter == 0 reason_code = adjustment_group[:translated_reason_code].nil? ? '' : adjustment_group[:translated_reason_code].upcase line_items += " #{adjustment_group[:adjustment_group].upcase}#{" " * (28 - get_length(adjustment_group[:adjustment_group]))}#{'%.2f' % (adjustment_group[:adjustment_amount].to_f / 100)}#{" " * (8 - get_length('%.2f' % (adjustment_group[:adjustment_amount].to_f / 100)))}#{truncate(reason_code, 84)}\n" line_items += "\n" if line_item[:adjustment_groups].length == (adjustment_group_counter + 1) end end end end era_text = "--------------------------------------------------------------------------------------------------------------------------------------------------------\n" era_text += "Check# Patient ID Last,First Charge Amt Payment Amt Accnt##{" " * [8, get_length(individual_era[:account_number]) - 5].max}Status Payer\n" era_text += "#{check[:check_number]}#{" " * (31 - get_length(check[:check_number]))}#{individual_era[:patient_id]}#{" " * (19 - get_length(individual_era[:patient_id]))}#{truncate(individual_era[:patient_name], 18)}#{" " * (20 - get_length(truncate(individual_era[:patient_name], 18)))}#{'%.2f' % (individual_era[:charge_amount].to_f / 100)}#{" " * (12 - get_length('%.2f' % (individual_era[:charge_amount].to_f / 100)))}#{'%.2f' % (individual_era[:payment_amount].to_f / 100)}#{" " * (13 - get_length('%.2f' % (individual_era[:payment_amount].to_f / 100)))}#{individual_era[:account_number]}#{" " * ([14, get_length(individual_era[:account_number]) + 1].max - get_length(individual_era[:account_number]))}#{individual_era[:status]}#{" " * (31 - get_length(individual_era[:status]))}#{check[:payer_name]}\n" era_text += "#{" " * (126 + [14, get_length(individual_era[:account_number]) + 1].max)}#{check[:payer_address]}\n" era_text += "#{" " * (126 + [14, get_length(individual_era[:account_number]) + 1].max)}#{check[:payer_city]},#{check[:payer_state]} #{check[:payer_zip_code]}\n" era_text += "#{" " * (126 + [14, get_length(individual_era[:account_number]) + 1].max)}Tax ID: #{check[:payer_tax_id]}\n" if !individual_era[:claim_statement_period_end].nil? && !individual_era[:claim_statement_period_start].nil? era_text += "#{" " * (96)}Payer Claim Control Number: #{individual_era[:payer_claim_control_number]}\n" era_text += "#{" " * (96)}Claim Statement Period: #{individual_era[:claim_statement_period_start]} - #{individual_era[:claim_statement_period_end]}\n\n" else era_text += "#{" " * (96)}Payer Claim Control Number: #{individual_era[:payer_claim_control_number]}\n\n" end if line_items.length > 0 era_text += "#{" " * (10)}Line Item: Svc Date CPT Charge Amt Payment Amt Total Adj Amt Remarks\n" era_text += line_items end era[:checks][check[:check_number]][:eras][era_counter][:era_text] = era_text end end end return era end end
Private Instance Methods
get_length(string)
click to toggle source
# File lib/era_835_parser/parser.rb, line 1073 def get_length(string) if string.nil? return 0 else return string.length end end
truncate(string, truncate_at)
click to toggle source
# File lib/era_835_parser/parser.rb, line 1081 def truncate(string, truncate_at) if !string.nil? return string.to_s[0...truncate_at] end end