diff --git a/Gemfile b/Gemfile index 253f562..c74854c 100644 --- a/Gemfile +++ b/Gemfile @@ -85,7 +85,11 @@ gem "tailwindcss-rails" gem 'docx' gem 'httparty' gem 'combine_pdf' +gem 'pdf-reader' gem 'rails_icons' gem 'fastimage' gem 'rubyzip', require: 'zip' -gem "solid_queue" \ No newline at end of file +gem "solid_queue" +gem 'image_processing' +gem 'whenever', require: false +gem 'amatch' \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index 8f53c16..2bd7965 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,7 @@ GEM remote: https://rubygems.org/ specs: + Ascii85 (2.0.1) actioncable (7.2.3) actionpack (= 7.2.3) activesupport (= 7.2.3) @@ -79,6 +80,10 @@ GEM tzinfo (~> 2.0, >= 2.0.5) addressable (2.8.9) public_suffix (>= 2.0.2, < 8.0) + afm (1.0.0) + amatch (0.6.0) + mize + tins (~> 1) ast (2.4.3) base64 (0.3.0) bcrypt (3.1.22) @@ -103,6 +108,7 @@ GEM regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) cgi (0.5.1) + chronic (0.10.2) coderay (1.1.3) combine_pdf (1.0.31) matrix @@ -128,11 +134,13 @@ GEM et-orbi (1.4.0) tzinfo fastimage (2.4.1) + ffi (1.17.4-x86_64-linux-gnu) fugit (1.12.1) et-orbi (~> 1.4) raabro (~> 1.4) globalid (1.3.0) activesupport (>= 6.1) + hashery (2.1.2) httparty (0.24.2) csv mini_mime (>= 1.0.0) @@ -141,6 +149,9 @@ GEM concurrent-ruby (~> 1.0) icons (0.8.1) nokogiri (~> 1.16, >= 1.16.4) + image_processing (1.14.0) + mini_magick (>= 4.9.5, < 6) + ruby-vips (>= 2.0.17, < 3) importmap-rails (2.2.3) actionpack (>= 6.0.0) activesupport (>= 6.0.0) @@ -170,10 +181,13 @@ GEM marcel (1.1.0) matrix (0.4.3) method_source (1.1.0) + mini_magick (5.3.1) + logger mini_mime (1.1.5) minitest (6.0.2) drb (~> 2.0) prism (~> 1.5) + mize (0.6.1) msgpack (1.8.0) multi_xml (0.8.1) bigdecimal (>= 3.1, < 5) @@ -194,6 +208,12 @@ GEM parser (3.3.10.2) ast (~> 2.4.1) racc + pdf-reader (2.15.1) + Ascii85 (>= 1.0, < 3.0, != 2.0.0) + afm (>= 0.2.1, < 2) + hashery (~> 2.0) + ruby-rc4 + ttfunk pp (0.6.3) prettyprint prettyprint (0.2.0) @@ -264,6 +284,8 @@ GEM erb psych (>= 4.0.0) tsort + readline (0.0.4) + reline regexp_parser (2.11.3) reline (0.6.3) io-console (~> 0.5) @@ -321,6 +343,9 @@ GEM rubocop (~> 1.81) ruby-progressbar (1.13.0) ruby-rc4 (0.1.5) + ruby-vips (2.3.0) + ffi (~> 1.12) + logger rubyzip (3.2.2) securerandom (0.4.1) selenium-webdriver (4.41.0) @@ -347,15 +372,22 @@ GEM stimulus-rails (1.3.4) railties (>= 6.0.0) stringio (3.2.0) + sync (0.5.0) tailwindcss-rails (4.4.0) railties (>= 7.0.0) tailwindcss-ruby (~> 4.0) tailwindcss-ruby (4.2.1-x86_64-linux-gnu) thor (1.5.0) timeout (0.6.1) + tins (1.52.0) + bigdecimal + mize (~> 0.6) + readline + sync tiny_tds (3.4.0-x86_64-linux-gnu) bigdecimal (>= 2.0.0) tsort (0.2.0) + ttfunk (1.7.0) turbo-rails (2.0.23) actionpack (>= 7.1.0) railties (>= 7.1.0) @@ -377,6 +409,8 @@ GEM base64 websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) + whenever (1.1.2) + chronic (>= 0.6.3) xpath (3.2.0) nokogiri (~> 1.8) zeitwerk (2.7.5) @@ -386,6 +420,7 @@ PLATFORMS DEPENDENCIES activerecord-sqlserver-adapter + amatch bootsnap brakeman bundler-audit @@ -395,8 +430,10 @@ DEPENDENCIES docx fastimage httparty + image_processing importmap-rails jbuilder + pdf-reader pry-rails puma (~> 6.5) pundit @@ -417,6 +454,7 @@ DEPENDENCIES turbo-rails tzinfo-data web-console + whenever RUBY VERSION ruby 3.4.8p72 diff --git a/app/controllers/employers_controller.rb b/app/controllers/employers_controller.rb index eb60505..4e6c8c0 100644 --- a/app/controllers/employers_controller.rb +++ b/app/controllers/employers_controller.rb @@ -69,6 +69,18 @@ class EmployersController < ApplicationController # API Methods + def refresh_employer_information + @employer = Employer.find(params[:id]) + @employer.sync_with_vhcs + redirect_to employer_path(@employer.slug) + end + + def refresh_employer_members_information + @employer = Employer.find(params[:id]) + @employer.sync_members_with_vhcs + redirect_to employer_path(@employer.slug) + end + def import word_doc = params[:employer][:import_from_word] if word_doc.present? && word_doc.is_a?(ActionDispatch::Http::UploadedFile) diff --git a/app/controllers/id_card/print_controller.rb b/app/controllers/id_card/print_controller.rb index da1007c..f00a766 100644 --- a/app/controllers/id_card/print_controller.rb +++ b/app/controllers/id_card/print_controller.rb @@ -4,39 +4,31 @@ module IdCard # View Methods def index @employer_setups = IdCard::Setup.active.to_a - @queue_counts = IdCardQueueService::GetQueuedCounts.new().call - add_queued_count_to_card_setup - @queued = @employer_setups.select { |setup| setup.queued_card_count > 0 }.sort_by { |setup| setup.pl_plan_key.to_i } - @not_queued = @employer_setups.select { |setup| setup.queued_card_count == 0 }.sort_by { |setup| setup.pl_plan_key.to_i } + @queue_members = IdCardQueueService::GetQueuedMembers.new().call + add_queued_count_to_employer_setup(@queue_members) + @queued = @employer_setups.select { |setup| setup.queued_card_count > 0 }.sort_by { |setup| setup.print_name } + @not_queued = @employer_setups.select { |setup| setup.queued_card_count == 0 }.sort_by { |setup| setup.print_name } render :index end # API Methods def print_all_queued - @queue_members = IdCardQueueService::GetQueuedCards.new().call - cards_pdf = IdCardPrinterService::QueuedCardsGenerator.new(@queue_members).call + @queue_members = IdCardQueueService::GetQueuedMembers.new().call + cards_pdf = IdCardPrinterService::CardsGenerator.new(@queue_members, "PrintCard").call - if cards_pdf.is_a?(CombinePDF::PDF) - send_data cards_pdf.to_pdf, - filename: "queued_cards_#{Date.today}.pdf", - type: "application/pdf", - disposition: 'attachment' - else - cards_pdf.rewind - send_data cards_pdf.read, - filename: "queued_cards_#{Date.today}.zip", - type: 'application/zip', - disposition: 'attachment' - end + send_data cards_pdf.to_pdf, + filename: "all_queued_cards_#{Date.today}.pdf", + type: "application/pdf", + disposition: 'attachment' end def print_queued_by_employer pl_plan_key = params[:id].to_s @employer = Employer.find_by(pl_plan_key: pl_plan_key) - @queue_members = IdCardQueueService::GetQueuedCards.new(pl_plan_key).call - cards_pdf = IdCardPrinterService::QueuedCardsGenerator.new(@queue_members).call + @queue_members = IdCardQueueService::GetQueuedMembers.new(pl_plan_key).call + cards_pdf = IdCardPrinterService::CardsGenerator.new(@queue_members, "PrintCard").call send_data cards_pdf.to_pdf, filename: "#{@employer.name.parameterize(separator: "_")}_queued_cards_#{Date.today}.pdf", @@ -104,7 +96,8 @@ module IdCard slug = params[:id] @employer = Employer.find_by(slug: slug) end - cards_pdf = IdCardPrinterService::EmployerCardsGenerator.new(@employer, "FullPageCard", true).call + cards_pdf = IdCardPrinterService::CardsGenerator.new(@employer.employer_member_keys, "FullPageCard", true).call + # cards_pdf = IdCardPrinterService::EmployerCardsGenerator.new(@employer, "FullPageCard", true).call cards_pdf.rewind send_data cards_pdf.sysread, @@ -117,11 +110,11 @@ module IdCard private - def add_queued_count_to_card_setup - @queue_counts.each do |qc| - match = @employer_setups.find { |setup| setup.pl_plan_key == qc["PLPlanKey"] } + def add_queued_count_to_employer_setup(queued_employer_members) + queued_employer_members.each do |queued_employer| + match = @employer_setups.find { |setup| setup.pl_plan_key == queued_employer[:pl_plan_key] } if match.present? - match.queued_card_count = qc["QueuedCardsCount"] + match.queued_card_count = queued_employer[:member_keys].length end end end diff --git a/app/javascript/controllers/add_exception_item_controller.js b/app/javascript/controllers/add_exception_item_controller.js index 06e71e2..141065f 100644 --- a/app/javascript/controllers/add_exception_item_controller.js +++ b/app/javascript/controllers/add_exception_item_controller.js @@ -4,10 +4,10 @@ export default class extends Controller { static targets = ["exceptionItemTemplate", "exceptionItemContainer", "exceptionItem", "exceptionItemButton"] connect() { - if (this.exceptionItemTargets.length > 0) { - const content = this.#newExemptionItem() - this.exceptionItemButtonTarget.insertAdjacentHTML('beforebegin', content); - } + // if (this.exceptionItemTargets.length > 0) { + // const content = this.#newExemptionItem() + // this.exceptionItemButtonTarget.insertAdjacentHTML('beforebegin', content); + // } } addExemptionItem(event) { diff --git a/app/jobs/process_id_card_data_job.rb b/app/jobs/process_id_card_data_job.rb deleted file mode 100644 index 7b0cf00..0000000 --- a/app/jobs/process_id_card_data_job.rb +++ /dev/null @@ -1,90 +0,0 @@ -class ProcessIdCardDataJob < ApplicationJob - queue_as :default - - def perform(member_key, field_exception_ids, has_divisions = false) - member = Member.find_by(pb_entity_key: member_key) - - effect_date = determine_eff_date(member) - if effect_date - member_card = @base_card.dup - member_attributes = { - full_name: member.id_card_display_name, - full_name_last_name_first: member.name, - primary_mb_member_key: member.pb_entity_key, - family_id: member.family_id, - plan_id: member.id_card_plan_id, - medical_eff_date: effect_date.strftime("%m/%d/%Y") - } - - dependent_attributes = get_dependent_fields(member) - if dependent_attributes.present? - member_attributes.merge!(dependent_attributes) - end - - if has_divisions - member_attributes.merge!({employer_name: member.division}) - end - - if field_exception_ids.present? - exceptions_attributes = {} - field_exceptions = IdCard::FieldException.where(id: field_exception_ids) - member_exception_values = member.id_card_field_exception_values - field_exceptions.each do |fe| - if member_exception_values[fe.field_type] == fe.field_value - fe.field_exception_items.each do |fei| - if fei.field_value.present? - exceptions_attributes[fei.field_name] = fei.field_value - elsif fei.provider_section_id.present? - provider_attributes = IdCard::ProviderSection.find(fei.provider_section_id).attributes.with_indifferent_access.slice( - :provider_line_1, :provider_line_2, :provider_line_3, :provider_line_4, :provider_line_5, :provider_line_6, - :provider_line_7, :provider_line_8, :provider_line_9, :provider_line_10, :provider_line_11, :provider_line_12, - :claim_to_1, :claim_to_2, :claim_to_3, :claim_to_4, :claim_to_5, :claim_to_6, - :claim_to_7, :claim_to_8, :claim_to_9, :claim_to_10, :claim_to_11, :claim_to_12 - ) - exceptions_attributes.merge!(provider_attributes) - elsif fei.network_logo_id.present? - exceptions_attributes.merge!(network_logo_id: fei.network_logo_id) - exceptions_attributes.merge!(network_logo_filename: fei.network_logo.filename) - end - end - end - end - member_attributes.merge!(exceptions_attributes) - end - - member_card = IdCard::PrintData.find_by(pl_plan_key: member.pl_plan_key, plan_id: member.id_card_plan_id, primary_mb_member_key: nil).dup - member_card.assign_attributes(member_attributes) - member_card.save - end - - true - - # BatchProcess.increment_counter(:completed_jobs, batch_process_id) - - end - - private - - def determine_eff_date(member) - participation = Vhcs::PbProductParticipation.joins('INNER JOIN "PBCoveredEntities" ON "PBProductParticipation"."PBProductParticipationKey" = "PBCoveredEntities"."PBProductParticipationKey"').where('"PBCoveredEntities"."PBEntityKey" = ?', member.pb_entity_key).last - in_effect = participation.in_effect - out_of_effect = participation.out_of_effect - - if in_effect <= (Date.today + 90.days) && (out_of_effect - 1.day) > Date.today && out_of_effect > in_effect - in_effect - else - false - end - end - - def get_dependent_fields(member) - dependent_attributes = {} - dependents = Vhcs::VwmbMember.where(pl_plan_key: member.pl_plan_key, family_id: member.family_id).where.not(pb_entity_key: member.pb_entity_key) - dependents.each do |dep| - dependent_name = dep.first_name + ' ' + dep.last_name - dependent_attributes["dependent_#{dep.sequence_number - 1}".to_sym] = dependent_name - end - dependent_attributes - end - -end \ No newline at end of file diff --git a/app/jobs/process_member_card_data_job.rb b/app/jobs/process_member_card_data_job.rb new file mode 100644 index 0000000..7786a6d --- /dev/null +++ b/app/jobs/process_member_card_data_job.rb @@ -0,0 +1,118 @@ +class ProcessMemberCardDataJob < ApplicationJob + queue_as :default + + def perform(member_key, member_card_exceptions_attrs, has_divisions = false, has_dental = false) + member = Member.find_by(pb_entity_key: member_key) + + effect_date = determine_eff_date(member) + if effect_date + member_card = @base_card.dup + member_attributes = { + full_name: member.id_card_display_name, + full_name_last_name_first: member.name, + primary_mb_member_key: member.pb_entity_key, + family_id: member.family_id, + plan_id: member.id_card_plan_id, + medical_eff_date: effect_date.strftime("%m/%d/%Y") + } + + if member.dependents.present? + dependent_attributes = format_dependent_attributes(member) + member_attributes.merge!(dependent_attributes) + end + + if has_divisions + member_attributes.merge!({employer_name: member.division}) + end + + if member_card_exceptions_attrs.present? + # exceptions_attributes = {} + # field_exceptions = IdCard::FieldException.where(id: field_exception_ids) + # member_exception_values = member.id_card_field_exception_values + # field_exceptions.each do |fe| + # if fe.exception_values.include?(member_exception_values[fe.exception_type.to_sym]) + # fe.field_exception_items.each do |fei| + # if fei.field_value.present? + # exception_eff_date = Date.strptime(fei.field_value, "%m/%d/%Y") + # member_eff_date = Date.strptime(member_attributes[:medical_eff_date], "%m/%d/%Y") + # if exception_eff_date > member_eff_date + # exceptions_attributes[fei.field_name.to_sym] = fei.field_value + # end + # elsif fei.provider_section_id.present? + # provider_attributes = IdCard::ProviderSection.find(fei.provider_section_id).attributes.with_indifferent_access.slice( + # :provider_line_1, :provider_line_2, :provider_line_3, :provider_line_4, :provider_line_5, :provider_line_6, + # :provider_line_7, :provider_line_8, :provider_line_9, :provider_line_10, :provider_line_11, :provider_line_12, + # :claim_to_1, :claim_to_2, :claim_to_3, :claim_to_4, :claim_to_5, :claim_to_6, + # :claim_to_7, :claim_to_8, :claim_to_9, :claim_to_10, :claim_to_11, :claim_to_12 + # ) + # exceptions_attributes.merge!(provider_attributes) + # elsif fei.network_logo_id.present? + # exceptions_attributes.merge!(network_logo_filename: fei.network_logo.filename) + # end + # end + # end + # end + member_attributes.merge!(member_card_exceptions_attrs) + end + + if has_dental + if member.dental_plan_key + member_attributes.merge!({dental_coverage: member.coverage_class.upcase}) + unless member.id_card_plan_id + member_attributes.merge!({group_number: "", medical_eff_date: ""}) + # dental_plan = IdCard::Plan.find_by(pb_product_key: 1025) + if IdCard::Plan.find_by(pb_product_key: member.dental_plan_key).blank? + member_attributes.merge!({employer_name: 'COBRA'}) + end + end + end + end + + if member.id_card_plan.present? && member.id_card_plan.title.upcase.include?('COBRA') + member_attributes.merge!({employer_name: 'COBRA'}) + end + + if member.id_card_plan_id.present? + member_card = IdCard::PrintData.find_by(pl_plan_key: member.pl_plan_key, plan_id: member.id_card_plan_id, primary_mb_member_key: nil).dup + else + member_card = IdCard::PrintData.where(pl_plan_key: member.pl_plan_key, primary_mb_member_key: nil).first.dup + end + + member_card.assign_attributes(member_attributes) + member_card.save + # if dependent_attributes.present? + # dependent_card = member_card.dup + # dependent_card.full_name_last_name_first = dependent_card.full_name_last_name_first.concat(" dependent") + # dependent_card.save + # end + end + + true + + # BatchProcess.increment_counter(:completed_jobs, batch_process_id) + + end + + private + + def determine_eff_date(member) + participation = Vhcs::PbProductParticipation.joins('INNER JOIN "PBCoveredEntities" ON "PBProductParticipation"."PBProductParticipationKey" = "PBCoveredEntities"."PBProductParticipationKey"').where('"PBCoveredEntities"."PBEntityKey" = ?', member.pb_entity_key).order(out_of_effect: :desc).first + in_effect = participation.in_effect + out_of_effect = participation.out_of_effect + + if in_effect <= (Date.today + 90.days) && (out_of_effect - 1.day) > Date.today && out_of_effect > in_effect + in_effect + else + false + end + end + + def format_dependent_attributes(member) + dependent_attributes = {} + member.dependents.each_with_index do |dep, index| + dependent_attributes["dependent_#{index + 1}".to_sym] = dep + end + dependent_attributes + end + +end \ No newline at end of file diff --git a/app/jobs/update_employer_job.rb b/app/jobs/update_employer_job.rb new file mode 100644 index 0000000..f56bddd --- /dev/null +++ b/app/jobs/update_employer_job.rb @@ -0,0 +1,126 @@ +class UpdateEmployerJob < ApplicationJob + queue_as :default + + def perform(pl_plan_key, plan_header = {}, full_sync = false) + + unless plan_header.present? + sql_query = "SELECT PLPlanKey, PlanId, ShortDesc FROM PLPlanHeader WHERE PLPlanKey = #{pl_plan_key}" + plan_header = VhcsRecord.connection.select_all(sql_query).first + end + + puts "== Updating #{plan_header['ShortDesc'].strip.titleize} ==" + + plan_code = Vhcs::HlPlanCode.find_by(plan_key: plan_header['PLPlanKey']) + pb_company_plan = Vhcs::PbCompanyPlans.find_by(pl_plan_key: plan_header['PLPlanKey']) + employer = Employer.find_or_create_by!(pl_plan_key: plan_header['PLPlanKey']) + full_sync = employer.previously_new_record? || full_sync + # id_card_setup = employer.id_card_setup || employer.create_id_card_setup(pl_plan_key: employer.pl_plan_key) + # id_card_setup = employer.id_card_setup.find_or_create_by(pl_plan_key: employer.pl_plan_key) + + employer_update_attrs = {} + setup_update_attrs = {} + + employer_update_attrs.merge!({ + plan_id: plan_header['PlanId'].strip.to_i, + company_pb_entity_key: pb_company_plan.company_pb_entity_key + }) + + if plan_code.present? + employer_update_attrs.merge!({ + group_number: plan_code.group_number, + effective_date: plan_code.effect_date.strftime("%m/%d/%Y") + }) + setup_update_attrs.merge!({ + rx_group_number: plan_code.medical_number + }) + end + + # id_card_setup = employer.id_card_setup.find_or_create_by(pl_plan_key: employer.pl_plan_key) + # employer.name = plan_header['ShortDesc'].strip.titleize + # employer.plan_id = plan_header['PlanId'].strip.to_i + + + # id_card_templates = determine_id_card_templates(employer.pl_plan_key) + # employer.single_card_template = id_card_templates[:single_card_template] + # employer.multiple_card_template = id_card_templates[:multiple_card_template] + + if full_sync + employer_update_attrs.merge!({ + name: plan_header['ShortDesc'].strip.titleize + }) + setup_update_attrs.merge!({ + print_name: determine_card_print_name(pb_company_plan.company_pb_entity_key, @pl_plan_key) + }) + end + employer.update(employer_update_attrs) + # if full_sync + # setup_update_attrs.merge!{ + # print_name: card_print_name + # } + # end + id_card_setup = employer.id_card_setup || employer.create_id_card_setup!(pl_plan_key: employer.pl_plan_key) + id_card_setup.update(setup_update_attrs) + + # plan_code = Vhcs::HlPlanCode.find_by(plan_key: employer.pl_plan_key) + # employer.group_number = plan_code.group_number + # id_card_setup.rx_group_number = plan_code.medical_number + # employer.effective_date = plan_code.effect_date.strftime("%m/%d/%Y") + + # pb_company_plan = Vhcs::PbCompanyPlans.find_by(pl_plan_key: employer.pl_plan_key) + # employer.company_pb_entity_key = pb_company_plan.company_pb_entity_key + + # card_print_name = Vhcs::PbEntity.where(company_pb_entity_key: employer.company_pb_entity_key, entity_type_id: 1007).last.last_name + # id_card_setup.print_name = card_print_name + + # if employer.up_to_date? + # employer.active = true + # end + + # employer.default_network_logo = determine_network_logos(employer.pl_plan_key) + + # plan_codes = Vhcs::HlEgglestonCardBenefit.where(plan_key: employer.pl_plan_key).pluck(:plan_id).uniq + employer_plans = employer.id_card_setup.plans + plan_titles = employer_plans.pluck(:title) + vhcs_plans = Vhcs::PbProduct.where(company_pb_entity_key: pb_company_plan.company_pb_entity_key, is_active: 255) + vhcs_plans.each do |vp| + if employer_plans.present? && plan_titles.all?(&:present?) && employer_plans.find_by(pb_product_key: vp.pb_product_key).nil? + plan_title_matcher = Amatch::JaroWinkler.new(vp.short_description) + closest_title = plan_titles.max_by { |title| plan_title_matcher.match(title) } + plan = employer_plans.find_or_create_by(title: closest_title) + plan.update( + title: vp.short_description, + pb_product_key: vp.pb_product_key, + pl_plan_key: employer.pl_plan_key + ) + plan_titles.delete(closest_title) + elsif employer_plans.blank? + employer_plans.create!( + pb_product_key: vp.pb_product_key, + title: vp.short_description, + pl_plan_key: employer.pl_plan_key + ) + # plan.update( + # title: vp.short_description, + # pl_plan_key: employer.pl_plan_key + # ) + end + end + + employer + end + + private + + def determine_card_print_name(company_pb_entity_key, pl_plan_key) + card_print_names = Vhcs::PbEntity.where(company_pb_entity_key: company_pb_entity_key, entity_type_id: 1007) + .where.not("LastName LIKE ? OR LastName LIKE ? OR LastName LIKE ?", "%COBRA%", "Active", ".%").pluck(:last_name) + if pl_plan_key == "2" + "sm ART" + elsif card_print_names.count > 2 + Employer.employer_trim_name(card_print_names.first) + else + card_print_names.last + end + end + +end \ No newline at end of file diff --git a/app/jobs/update_member_job.rb b/app/jobs/update_member_job.rb new file mode 100644 index 0000000..944c6ca --- /dev/null +++ b/app/jobs/update_member_job.rb @@ -0,0 +1,104 @@ +class UpdateMemberJob < ApplicationJob + queue_as :default + + def perform(pb_entity_key, employer_id, has_divisions = false, has_dental = false, vw_mb_member = {}) + + unless vw_mb_member.present? + vw_mb_member = Vhcs::VwmbMember.find_by(enrollee_type_value_id: 1, pb_entity_key: pb_entity_key).attributes.with_indifferent_access.slice(:mb_member_key, :pb_entity_key, :pl_plan_key, :family_id, :full_name_last_name_first, :social_security_number) + end + + pb_products = Vhcs::PbProduct.joins(' + INNER JOIN "PBProductAvailability" ON "PBProductAvailability"."PBProductKey" = "PBProduct"."PBProductKey" + INNER JOIN "PBProductParticipation" ON "PBProductParticipation"."PBProductAvailabilityKey" = "PBProductAvailability"."PBProductAvailabilityKey" + INNER JOIN "PBCoveredEntities" ON "PBProductParticipation"."PBProductParticipationKey" = "PBCoveredEntities"."PBProductParticipationKey" + ').where(' + "PBCoveredEntities"."PBEntityKey" = ? + AND "PBProductParticipation"."InEffect" <= ? + AND "PBProductParticipation"."OutOfEffect" > ?', + vw_mb_member[:pb_entity_key], 2.month.from_now , 1.day.ago + ) + + if pb_products.present? && vw_mb_member[:social_security_number].present? + member = Member.find_or_create_by!(pb_entity_key: vw_mb_member[:pb_entity_key], employer_id: employer_id) + member.name = vw_mb_member[:full_name_last_name_first].titleize + member.mb_member_key = vw_mb_member[:mb_member_key] + member.family_id = vw_mb_member[:family_id] + member.pl_plan_key = vw_mb_member[:pl_plan_key] + + card_display_name = Vhcs::PbEntity.find_by(pb_entity_key: member.pb_entity_key).full_name + member.id_card_display_name = card_display_name + + if has_divisions + division = Vhcs::PbEntity.joins(' + INNER JOIN "PBAffiliation" ON "PBAffiliation"."ParentPBEntityKey" = "PBEntity"."PBEntityKey" + INNER JOIN "PBProductParticipation" ON "PBProductParticipation"."PBAffiliationKey" = "PBAffiliation"."PBAffiliationKey" + INNER JOIN "PBCoveredEntities" ON "PBProductParticipation"."PBProductParticipationKey" = "PBCoveredEntities"."PBProductParticipationKey" + ').find_by(' + "PBCoveredEntities"."PBEntityKey" = ? + AND "PBProductParticipation"."OutOfEffect" > ?', + member.pb_entity_key, 1.day.ago + ).last_name + member.division = division + end + + if has_dental + medical_pb_product_key = pb_products.where(short_description: "Medical")&.first&.pb_product_key + dental_pb_product_key = pb_products.where("ShortDescription LIKE ?", "%Dental%")&.first&.pb_product_key + # dental_pb_product_key = pb_products.where(short_description: "Dental")&.first&.pb_product_key + if dental_pb_product_key + member.dental_plan_key = dental_pb_product_key + + coverage_class = Vhcs::GenLookupTables.joins(' + INNER JOIN "PBProductParticipation" ON "PBProductParticipation"."CoverageTypeCode" = "GEN_LookupTables"."RecordID" + INNER JOIN "PBCoveredEntities" ON "PBProductParticipation"."PBProductParticipationKey" = "PBCoveredEntities"."PBProductParticipationKey" + INNER JOIN "PBProductAvailability" ON "PBProductAvailability"."PBProductAvailabilityKey" = "PBProductParticipation"."PBProductAvailabilityKey" + INNER JOIN "PBProduct" ON "PBProduct"."PBProductKey" = "PBProductAvailability"."PBProductKey" + ').find_by(' + "PBCoveredEntities"."PBEntityKey" = ? + AND "PBProductParticipation"."InEffect" <= ? + AND "PBProductParticipation"."OutOfEffect" > ? + AND "PBProduct"."PBProductKey" = ?', + member.pb_entity_key, 1.month.from_now, 1.day.ago, dental_pb_product_key + ).short_desc + member.coverage_class = coverage_class + end + else + medical_pb_product_key = pb_products.first.pb_product_key + end + if medical_pb_product_key && plan = IdCard::Plan.find_by(pb_product_key: medical_pb_product_key) + member.id_card_plan = plan + end + member.dependents = get_dependent_names_by_sequence(member) + # if employer_members_update + # member + # else + + # end + end + puts "---- #{member.name}" + member.presence + + end + + private + + def get_dependent_names_by_sequence(member) + dependents = Vhcs::VwmbMember.joins(' + INNER JOIN "PBCoveredEntities" ON "PBCoveredEntities"."PBEntityKey" = "vwMBMember"."PBEntityKey" + INNER JOIN "PBProductParticipation" ON "PBProductParticipation"."PBProductParticipationKey" = "PBCoveredEntities"."PBProductParticipationKey" + INNER JOIN "PBProductAvailability" ON "PBProductAvailability"."PBProductAvailabilityKey" = "PBProductParticipation"."PBProductAvailabilityKey" + INNER JOIN "PBProduct" ON "PBProduct"."PBProductKey" = "PBProductAvailability"."PBProductKey" + ').where(' + "EnrolleeTypeKey" != 1044 AND "PLPlanKey" = ? AND "PBProductParticipation"."OutOfEffect" >= ? AND "FamilyID" = ?', member.pl_plan_key, Date.today.strftime("%m/%d/%Y"), member.family_id + ) + if member.pl_plan_key == 3 + dependents = dependents.where('"PBProduct"."PBProductKey" != 1024') + elsif member.pl_plan_key == 2 + dependents = dependents.where('"PBProduct"."PBProductKey" != 1019') + end + dependent_names = dependents.order(:sequence_number).map { |dep| dep.first_name + ' ' + dep.last_name}.uniq + dependent_names +end + + +end \ No newline at end of file diff --git a/app/models/batch_process.rb b/app/models/batch_process.rb new file mode 100644 index 0000000..5214540 --- /dev/null +++ b/app/models/batch_process.rb @@ -0,0 +1,5 @@ +class BatchProcess < ApplicationRecord + + + +end diff --git a/app/models/concerns/employer_automation.rb b/app/models/concerns/employer_automation.rb index d113441..fcc4dbd 100644 --- a/app/models/concerns/employer_automation.rb +++ b/app/models/concerns/employer_automation.rb @@ -1,12 +1,36 @@ module EmployerAutomation extend ActiveSupport::Concern -# included do -# # Code in this block becomes instance methods or class macros (like scopes, validations, associations) in the including class. -# scope :visible, -> { where(visible: true) } -# scope :invisible, -> { where(visible: false) } -# validates :status, inclusion: { in: %w(visible invisible), message: "%{value} is not a valid status" } -# end + included do + scope :new_groups, -> { + where(active: false) + .where.not(pl_plan_key: [nil, '']) + } + + scope :with_plans, -> { + joins(id_card_setup: :plans).distinct + } + + # scope :with_survey_and_no_questions, -> { + # joins(:survey) # join has_one + # .left_joins(survey: :questions) # join has_many through has_one + # .where(questions: { id: nil }) # filter where has_many is empty + # } + + scope :missing_keychain_values, -> { + new_groups + .where( + arel_table[:company_pb_entity_key].in([nil, '']) + .or(arel_table[:plan_id].in([nil, ''])) + .or(arel_table[:group_number].in([nil, ''])) + .or(arel_table[:effective_date].in([nil, ''])) + ) + } + + scope :missing_initial_members, -> { + new_groups.with_plans + } + end # class_methods do # # Methods in this block become class methods of the including class. @@ -16,16 +40,20 @@ module EmployerAutomation # end # Any other methods defined here become instance methods automatically. - def up_to_date? - self.pl_plan_key.present? && - self.company_pb_entity_key.present? && - self.plan_id.present? && - self.group_number.present? && - self.effect_date.present? + # def up_to_date? + # self.pl_plan_key.present? && + # self.company_pb_entity_key.present? && + # self.plan_id.present? && + # self.group_number.present? && + # self.effective_date.present? + # end + + def sync_members_with_vhcs + AutomationService::EmployerMembersUpdate.new(self.pl_plan_key).call end + def sync_with_vhcs - sql_query = "SELECT PLPlanKey, PlanId, ShortDesc FROM PLPlanHeader WHERE ActiveInactive = 'Active' And PLPlanKey = 57" - plan_header = VhcsRecord.connection.select_all(sql_query).first + AutomationService::EmployerUpdate.new(self.pl_plan_key).call end end \ No newline at end of file diff --git a/app/models/concerns/member_automation.rb b/app/models/concerns/member_automation.rb new file mode 100644 index 0000000..509f9e6 --- /dev/null +++ b/app/models/concerns/member_automation.rb @@ -0,0 +1,30 @@ +module MemberAutomation + extend ActiveSupport::Concern + +# included do +# # Code in this block becomes instance methods or class macros (like scopes, validations, associations) in the including class. +# scope :visible, -> { where(visible: true) } +# scope :invisible, -> { where(visible: false) } +# validates :status, inclusion: { in: %w(visible invisible), message: "%{value} is not a valid status" } +# end + +# class_methods do +# # Methods in this block become class methods of the including class. +# def count_all_visible +# visible.count +# end +# end + + # Any other methods defined here become instance methods automatically. + # def up_to_date? + # self.pl_plan_key.present? && + # self.company_pb_entity_key.present? && + # self.plan_id.present? && + # self.group_number.present? && + # self.effective_date.present? + # end + + def sync_with_vhcs + AutomationService::MemberUpdate.new(self.employer.pl_plan_key, self.pb_entity_key).call + end +end \ No newline at end of file diff --git a/app/models/employer.rb b/app/models/employer.rb index 177dc62..959708a 100644 --- a/app/models/employer.rb +++ b/app/models/employer.rb @@ -1,7 +1,10 @@ class Employer < ApplicationRecord - has_many :members + include EmployerAutomation + has_many :members, dependent: :destroy + accepts_nested_attributes_for :members, allow_destroy: true, reject_if: :all_blank has_one :id_card_setup, class_name: 'IdCard::Setup', dependent: :destroy + scope :active, -> { where(active: true) } scope :inactive, -> { where(active: false) } @@ -9,7 +12,9 @@ class Employer < ApplicationRecord # before_save :process_employer_logo # before_save :process_employer_logo, if: :employer_logo_filename_changed? - before_save :create_slug, if: :new_record? + # before_save :create_slug, if: :new_record? + before_save :create_slug, if: :will_save_change_to_name? + # before_save :set_active_status, unless: :will_save_change_to_active? # after_save :process_employer_logo, if: :saved_change_to_employer_logo_filename? # def process_employer_logo @@ -35,7 +40,17 @@ class Employer < ApplicationRecord # end def create_slug - self.slug = employer_trim_name(self.name).parameterize + self.slug = Employer.employer_trim_name(self.name).parameterize + end + + def set_active_status + self.active = ( + self.pl_plan_key.present? && + self.company_pb_entity_key.present? && + self.plan_id.present? && + self.group_number.present? && + self.effective_date.present? + ) end def id_card_enabled? @@ -54,12 +69,12 @@ class Employer < ApplicationRecord end def name_to_logo_filename(extension) - self.employer_trim_name(self.name).titleize.gsub(/[^a-zA-Z]/, '').concat('Logo').concat(extension.downcase) + Employer.employer_trim_name(self.name).titleize.gsub(/[^a-zA-Z]/, '').concat('Logo').concat(extension.downcase) end - def employer_trim_name(name = nil) - employer_name = name.present? ? name : self.name - regex_source = Regexp.union(["health ", "plan", "the", "inc", "llc"]).source + def self.employer_trim_name(employer_name) + # employer_name = name.present? ? name : self.name + regex_source = Regexp.union(["health ", "plan", "the", "inc", "llc", "group"]).source case_insensitive_regex = Regexp.new(regex_source, "i") employer_name.gsub(case_insensitive_regex, "").gsub(/[^[:alpha:][:space:]]/, "").squish end @@ -82,21 +97,20 @@ class Employer < ApplicationRecord medical_number: self.group_number, dental_number: '', plan_key: self.pl_plan_key, - effect_date: self.effective_date + effect_date: DateTime.strptime(self.effective_date, "%m/%d/%y") ) - # Replace fairos_info with template like for benefits - fairos_info = Vhcs::HlrxCrosRef.where(pl_plan_key: 52).first + rx_info = self.id_card_setup.rx_section Vhcs::HlrxCrosRef.create!( group_no: self.group_number, rx_group_id: self.group_number, - help_desk: fairos_info.help_desk, - customer_service: fairos_info.customer_service, - web_url: fairos_info.web_url, + help_desk: rx_info.help_desk, + customer_service: rx_info.customer_service, + web_url: rx_info.web_url, pl_plan_key: self.pl_plan_key ) - self.plans.each_with_index do |plan, i| + self.id_card_setup.plans.each_with_index do |plan, i| plan.plan_benefits.each do |bene| Vhcs::HlEgglestonCardBenefit.create!( plan_id: plan.pb_product_key, diff --git a/app/models/id_card/employer_logo.rb b/app/models/id_card/employer_logo.rb index a60ee1b..e62ccc6 100644 --- a/app/models/id_card/employer_logo.rb +++ b/app/models/id_card/employer_logo.rb @@ -1,16 +1,50 @@ module IdCard class EmployerLogo < ApplicationRecord - before_validation :calculate_aspect_ratio, if: :image_data_changed? + # before_validation :resize_logo, if: :image_data_changed? + # before_validation :calculate_aspect_ratio, if: :image_data_changed? + before_validation :process_image, if: :image_data_changed? private - def calculate_aspect_ratio - image_io = StringIO.new(self.image_data) - width, height = FastImage.size(image_io) - image_ratio = width.to_f / height + def process_image + image = Vips::Image.new_from_buffer(self.image_data, "") + + resized_image = ImageProcessing::Vips + .source(image) + .resize_to_limit(nil, 400) + + processed_image = resized_image.convert("png").call + new_image_data = processed_image.read + if new_image_data + self.image_data = new_image_data + self.filename = File.basename(self.filename, File.extname(self.filename)) + ".png" + self.content_type = "image/png" + end + + image_ratio = image.width.to_f / image.height if image_ratio self.aspect_ratio = image_ratio.round(2) end end + + # def resize_logo + # image = Vips::Image.new_from_buffer(self.image_data, "") + + # processed_image = ImageProcessing::Vips + # .source(image) + # .resize_to_limit(nil, 200) + # .call + + # self.image_data = processed_image.read + # end + + # def calculate_aspect_ratio + # image_io = StringIO.new(self.image_data) + # width, height = FastImage.size(image_io) + # image_ratio = width.to_f / height + # if image_ratio + # self.aspect_ratio = image_ratio.round(2) + # end + # end end end diff --git a/app/models/id_card/field_exception.rb b/app/models/id_card/field_exception.rb index 2ae01e8..b5cf0b7 100644 --- a/app/models/id_card/field_exception.rb +++ b/app/models/id_card/field_exception.rb @@ -4,19 +4,27 @@ module IdCard has_many :field_exception_items, dependent: :destroy accepts_nested_attributes_for :field_exception_items, allow_destroy: true, reject_if: :all_blank - VALID_TYPES = ['zipcode', 'state', 'family_id'] + serialize :exception_values, coder: JSON + + VALID_TYPES = ['family_id', 'zipcode', 'state'].freeze + + before_validation :format_exception_values, if: :exception_values_changed? validates :exception_type, inclusion: { in: VALID_TYPES, message: "%{value} is not a valid exception type" } + def to_card_attrs + self.field_exception_items.map(&:card_attrs).reduce({}, :merge) + end + class << self def permitted_params(params) params.require(:id_card_setup).permit( field_exceptions_attributes: [ :exception_type, - :exception_value, + :exception_values, :_destroy, field_exception_items_attributes: [ :field_name, @@ -31,5 +39,13 @@ module IdCard end + private + + def format_exception_values + if self.exception_values.is_a?(String) + self.exception_values = self.exception_values.split(",").map(&:strip) + end + end + end end diff --git a/app/models/id_card/field_exception_item.rb b/app/models/id_card/field_exception_item.rb index 30a7513..49fcdc4 100644 --- a/app/models/id_card/field_exception_item.rb +++ b/app/models/id_card/field_exception_item.rb @@ -6,14 +6,30 @@ module IdCard validate :only_one_exception_field_present - FIELDS_TO_VALIDATE = [:field_value, :card_logo_file_id, :card_provider_id].freeze + FIELDS_TO_VALIDATE = [:field_value, :network_logo_id, :provider_section_id].freeze - VALID_FIELD_NAMES = ['network_logo', 'provider_section', 'effective_date'] + VALID_FIELD_NAMES = ['network_logo', 'provider_section', 'medical_eff_date'] validates :field_name, inclusion: { in: VALID_FIELD_NAMES, message: "%{value} is not a valid Id Card Field Name" } + def card_attrs + case self.field_name + when "network_logo" + {"network_logo_filename" => IdCard::NetworkLogo.find(self.network_logo_id).filename} + when "provider_section" + IdCard::ProviderSection.find(self.provider_section_id).attributes.with_indifferent_access.slice( + :provider_line_1, :provider_line_2, :provider_line_3, :provider_line_4, :provider_line_5, :provider_line_6, + :provider_line_7, :provider_line_8, :provider_line_9, :provider_line_10, :provider_line_11, :provider_line_12, + :claim_to_1, :claim_to_2, :claim_to_3, :claim_to_4, :claim_to_5, :claim_to_6, + :claim_to_7, :claim_to_8, :claim_to_9, :claim_to_10, :claim_to_11, :claim_to_12 + ) + when "medical_eff_date" + {"medical_eff_date" => self.field_value} + end + end + private def only_one_exception_field_present diff --git a/app/models/id_card/network_logo.rb b/app/models/id_card/network_logo.rb index 61ae8a7..2231aab 100644 --- a/app/models/id_card/network_logo.rb +++ b/app/models/id_card/network_logo.rb @@ -1,6 +1,8 @@ module IdCard class NetworkLogo < ApplicationRecord - before_validation :calculate_aspect_ratio, if: :image_data_changed? + # before_validation :resize_logo, if: :image_data_changed? + # before_validation :calculate_aspect_ratio, if: :image_data_changed? + before_validation :process_image, if: :image_data_changed? scope :defaults, -> { where(default: true) } @@ -18,14 +20,46 @@ module IdCard private - def calculate_aspect_ratio - image_io = StringIO.new(image_data) - width, height = FastImage.size(image_io) - image_ratio = width.to_f / height + def process_image + image = Vips::Image.new_from_buffer(self.image_data, "") + + resized_image = ImageProcessing::Vips + .source(image) + .resize_to_limit(nil, 400) + + processed_image = resized_image.convert("png").call + new_image_data = processed_image.read + if new_image_data + self.image_data = new_image_data + self.filename = File.basename(self.filename, File.extname(self.filename)) + ".png" + self.content_type = "image/png" + end + + image_ratio = image.width.to_f / image.height if image_ratio self.aspect_ratio = image_ratio.round(2) end end + # def resize_logo + # image = Vips::Image.new_from_buffer(self.image_data, "") + + # processed_image = ImageProcessing::Vips + # .source(image) + # .resize_to_limit(nil, 400) + # .call + + # self.image_data = processed_image.read + # end + + # def calculate_aspect_ratio + # image_io = StringIO.new(image_data) + # width, height = FastImage.size(image_io) + # image_ratio = width.to_f / height + # if image_ratio + # self.aspect_ratio = image_ratio.round(2) + # end + # end + end end diff --git a/app/models/id_card/print_data.rb b/app/models/id_card/print_data.rb index c9c509c..5823234 100644 --- a/app/models/id_card/print_data.rb +++ b/app/models/id_card/print_data.rb @@ -1,7 +1,7 @@ module IdCard class PrintData < ApplicationRecord - STRING_ATTRIBUTES = %w[provider_line_1 provider_line_2 provider_line_3 provider_line_4 provider_line_5 provider_line_6 provider_line_7 provider_line_8 provider_line_9 provider_line_10 provider_line_11 claim_to_1 claim_to_2 claim_to_3 claim_to_4 claim_to_5 claim_to_6 claim_to_7 claim_to_8 claim_to_9 claim_to_10 claim_to_11 dependent_1 dependent_2 dependent_3 dependent_4 dependent_5 dependent_6 dependent_7 dependent_8] + STRING_ATTRIBUTES = %w[provider_line_1 provider_line_2 provider_line_3 provider_line_4 provider_line_5 provider_line_6 provider_line_7 provider_line_8 provider_line_9 provider_line_10 provider_line_11 provider_line_12 claim_to_1 claim_to_2 claim_to_3 claim_to_4 claim_to_5 claim_to_6 claim_to_7 claim_to_8 claim_to_9 claim_to_10 claim_to_11 claim_to_12 dependent_1 dependent_2 dependent_3 dependent_4 dependent_5 dependent_6 dependent_7 dependent_8 dental_coverage] before_validation :assign_blank_strings_to_unassigned_params diff --git a/app/models/id_card/setup.rb b/app/models/id_card/setup.rb index 01ef045..ebd27b3 100644 --- a/app/models/id_card/setup.rb +++ b/app/models/id_card/setup.rb @@ -40,6 +40,45 @@ module IdCard self.field_exceptions.present? end + def field_exceptions_card_attributes_by_member_id(member_array = nil) + unless member_array.present? + member_array = self.employer.members.pluck(:pb_entity_key) + end + + card_fes = self.field_exceptions.includes(:field_exception_items).in_order_of(:exception_type, IdCard::FieldException::VALID_TYPES) + # fe_by_value = card_fes.in_order_of(:exception_type, IdCard::FieldException::VALID_TYPES).group_by(&:exception_type) + # .transform_values { |fes| fes.map { |fe| [fe.id, fe.exception_values] }.to_h } + # .compact_blank + + # field_exception_types = card_fes.pluck(:exception_type).uniq + # if field_exception_types.include?("family_id") + # members = Member.where(pb_entity_key: member_array) + # end + # if field_exception_types.intersect?(["state", "zipcode"]) + # member_addresses = Vhcs::PbEntityAddress.where(pb_entity_key: member_array) + # end + card_exceptions_map = {} + card_fes.each do |fe| + if fe.exception_type == "family_id" + matches = Member.where(pb_entity_key: member_array, family_id: fe.exception_values).pluck(:pb_entity_key) + elsif fe.exception_type == "zipcode" + matches = Vhcs::PbEntityAddress.where(pb_entity_key: member_array, zip: fe.exception_values).pluck(:pb_entity_key) + elsif fe.exception_type == "state" + matches = Vhcs::PbEntityAddress.where(pb_entity_key: member_array, state: fe.exception_values).pluck(:pb_entity_key) + end + if matches.present? + card_exceptions_map[fe.id] = fe.to_card_attrs + matches.each do |match| + unless card_exceptions_map[match].present? + card_exceptions_map[match] = fe.id + end + end + end + end + + card_exceptions_map + end + def self.permitted_params(params) params.require(:id_card_setup).permit( :print_name, diff --git a/app/models/member.rb b/app/models/member.rb index aa81b8f..6d0f6f0 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -1,7 +1,11 @@ class Member < ApplicationRecord + include MemberAutomation belongs_to :id_card_plan, class_name: 'IdCard::Plan', optional: true belongs_to :employer + serialize :dependents, coder: JSON + before_validation :format_dependents, if: :dependents_changed? + def id_card_field_exception_values address = Vhcs::PbEntityAddress.find_by(pb_entity_key: self.pb_entity_key) { @@ -11,6 +15,14 @@ class Member < ApplicationRecord } end + private + + def format_dependents + if self.dependents.is_a?(String) + self.dependents = self.dependents.split(",").map(&:strip) + end + end + diff --git a/app/models/report.rb b/app/models/report.rb new file mode 100644 index 0000000..2ac1031 --- /dev/null +++ b/app/models/report.rb @@ -0,0 +1,5 @@ +module Report + def self.table_name_prefix + "report_" + end +end diff --git a/app/models/report/comparison_error.rb b/app/models/report/comparison_error.rb new file mode 100644 index 0000000..eefb1ed --- /dev/null +++ b/app/models/report/comparison_error.rb @@ -0,0 +1,4 @@ +class Report::ComparisonError < ApplicationRecord + belongs_to :employer_card_comparison, optional: true + belongs_to :member_card_comparison, optional: true +end diff --git a/app/models/report/employer_card_comparison.rb b/app/models/report/employer_card_comparison.rb new file mode 100644 index 0000000..92c90ac --- /dev/null +++ b/app/models/report/employer_card_comparison.rb @@ -0,0 +1,15 @@ +module Report + class EmployerCardComparison < ApplicationRecord + has_many :comparison_errors, dependent: :destroy + accepts_nested_attributes_for :comparison_errors, allow_destroy: true, reject_if: :all_blank + + has_many :member_card_comparisons + has_many :member_comparison_errors, through: :member_card_comparisons, source: :comparison_errors + + + def employer_total_errors + self.comparison_errors.count + self.member_comparison_errors.count + end + + end +end diff --git a/app/models/report/member_card_comparison.rb b/app/models/report/member_card_comparison.rb new file mode 100644 index 0000000..4b8ac82 --- /dev/null +++ b/app/models/report/member_card_comparison.rb @@ -0,0 +1,9 @@ +module Report + class MemberCardComparison < ApplicationRecord + has_many :comparison_errors, dependent: :destroy + accepts_nested_attributes_for :comparison_errors, allow_destroy: true, reject_if: :all_blank + + belongs_to :employer_card_comparison, optional: true + + end +end diff --git a/app/models/report/old_card_duplicate.rb b/app/models/report/old_card_duplicate.rb new file mode 100644 index 0000000..7979974 --- /dev/null +++ b/app/models/report/old_card_duplicate.rb @@ -0,0 +1,2 @@ +class Report::OldCardDuplicate < ApplicationRecord +end diff --git a/app/models/vhcs/gen_lookup_tables.rb b/app/models/vhcs/gen_lookup_tables.rb new file mode 100644 index 0000000..c9588ec --- /dev/null +++ b/app/models/vhcs/gen_lookup_tables.rb @@ -0,0 +1,43 @@ +module Vhcs + class GenLookupTables < VhcsRecord + + self.table_name = 'GEN_LookupTables' + + alias_attribute :record_id, :RecordID + alias_attribute :table_id, :TableID + alias_attribute :value_id, :ValueID + alias_attribute :company_pb_entity_key, :CompanyPBEntityKey + alias_attribute :short_desc, :ShortDesc + alias_attribute :long_desc, :LongDesc + alias_attribute :is_active, :IsActive + alias_attribute :is_default, :IsDefault + alias_attribute :is_bit_flag, :IsBitFlag + alias_attribute :is_company_specific, :IsCompanySpecific + alias_attribute :is_editable, :IsEditable + alias_attribute :long_description, :LongDescription + alias_attribute :sort_value, :SortValue + alias_attribute :system_id_bit_mask, :SystemIDBitMask + + def attributes + rails_like = { + record_id: self.record_id, + table_id: self.table_id, + value_id: self.value_id, + company_pb_entity_key: self.company_pb_entity_key, + short_desc: self.short_desc, + long_desc: self.long_desc, + is_active: self.is_active, + is_default: self.is_default, + is_bit_flag: self.is_bit_flag, + is_company_specific: self.is_company_specific, + is_editable: self.is_editable, + long_description: self.long_description, + sort_value: self.sort_value, + system_id_bit_mask: self.system_id_bit_mask, + } + super.merge(rails_like) + end + + + end +end \ No newline at end of file diff --git a/app/models/vhcs/hlid_card_egg_data.rb b/app/models/vhcs/hlid_card_egg_data.rb index b9a2cff..4a6bad4 100644 --- a/app/models/vhcs/hlid_card_egg_data.rb +++ b/app/models/vhcs/hlid_card_egg_data.rb @@ -5,12 +5,12 @@ module Vhcs alias_attribute :id, :ID alias_attribute :facility, :Facility - alias_attribute :division, :Division + alias_attribute :employer_name, :Division alias_attribute :full_name, :FullName alias_attribute :ssn, :SSN alias_attribute :medical_coverage, :MedicalCoverage alias_attribute :medical_eff_date, :MedicalEffDate - alias_attribute :medical_group_num, :MedicalGroupNum + alias_attribute :group_number, :MedicalGroupNum alias_attribute :dental_coverage, :DentalCoverage alias_attribute :dental_eff_date, :DentalEffDate alias_attribute :dental_group_num, :DentalGroupNum @@ -25,8 +25,8 @@ module Vhcs alias_attribute :provider_line_7, :ProviderLine7 alias_attribute :provider_line_8, :ProviderLine8 alias_attribute :provider_line_9, :ProviderLine9 - alias_attribute :provider_line_1_0, :ProviderLine10 - alias_attribute :provider_line_1_1, :ProviderLine11 + alias_attribute :provider_line_10, :ProviderLine10 + alias_attribute :provider_line_11, :ProviderLine11 alias_attribute :mail_to, :MailTo alias_attribute :mail_to_2, :MailTo2 alias_attribute :claim_to_1, :ClaimTo1 @@ -38,15 +38,15 @@ module Vhcs alias_attribute :claim_to_7, :ClaimTo7 alias_attribute :claim_to_8, :ClaimTo8 alias_attribute :claim_to_9, :ClaimTo9 - alias_attribute :claim_to_1_0, :ClaimTo10 - alias_attribute :claim_to_1_1, :ClaimTo11 + alias_attribute :claim_to_10, :ClaimTo10 + alias_attribute :claim_to_11, :ClaimTo11 alias_attribute :contact_line_1, :ContactLine1 alias_attribute :contact_line_2, :ContactLine2 alias_attribute :contact_line_3, :ContactLine3 alias_attribute :group_number, :GroupNumber alias_attribute :family_id, :FamilyId alias_attribute :group_no, :GroupNo - alias_attribute :rx_group_id, :RXGroupID + alias_attribute :rx_group, :RXGroupID alias_attribute :help_desk, :HelpDesk alias_attribute :customer_service, :CustomerService alias_attribute :web_url, :WebUrl @@ -60,34 +60,34 @@ module Vhcs alias_attribute :dependent_6, :Dependent6 alias_attribute :dependent_7, :Dependent7 alias_attribute :dependent_8, :Dependent8 - alias_attribute :ben_desc_1, :BenDesc1 - alias_attribute :ben_1, :Ben1 - alias_attribute :ben_desc_2, :BenDesc2 - alias_attribute :ben_2, :Ben2 - alias_attribute :ben_desc_3, :BenDesc3 - alias_attribute :ben_3, :Ben3 - alias_attribute :ben_desc_4, :BenDesc4 - alias_attribute :ben_4, :Ben4 - alias_attribute :ben_desc_5, :BenDesc5 - alias_attribute :ben_5, :Ben5 - alias_attribute :ben_desc_6, :BenDesc6 - alias_attribute :ben_6, :Ben6 - alias_attribute :ben_desc_7, :BenDesc7 - alias_attribute :ben_7, :Ben7 - alias_attribute :ben_desc_8, :BenDesc8 - alias_attribute :ben_8, :Ben8 - alias_attribute :ben_desc_9, :BenDesc9 - alias_attribute :ben_9, :Ben9 - alias_attribute :ben_desc_1_0, :BenDesc10 - alias_attribute :ben_1_0, :Ben10 - alias_attribute :ben_desc_1_1, :BenDesc11 - alias_attribute :ben_1_1, :Ben11 - alias_attribute :ben_desc_1_2, :BenDesc12 - alias_attribute :ben_1_2, :Ben12 - alias_attribute :ben_desc_1_3, :BenDesc13 - alias_attribute :ben_1_3, :Ben13 - alias_attribute :ben_desc_1_4, :BenDesc14 - alias_attribute :ben_1_4, :Ben14 + alias_attribute :benefit_desc_1, :BenDesc1 + alias_attribute :benefit_1, :Ben1 + alias_attribute :benefit_desc_2, :BenDesc2 + alias_attribute :benefit_2, :Ben2 + alias_attribute :benefit_desc_3, :BenDesc3 + alias_attribute :benefit_3, :Ben3 + alias_attribute :benefit_desc_4, :BenDesc4 + alias_attribute :benefit_4, :Ben4 + alias_attribute :benefit_desc_5, :BenDesc5 + alias_attribute :benefit_5, :Ben5 + alias_attribute :benefit_desc_6, :BenDesc6 + alias_attribute :benefit_6, :Ben6 + alias_attribute :benefit_desc_7, :BenDesc7 + alias_attribute :benefit_7, :Ben7 + alias_attribute :benefit_desc_8, :BenDesc8 + alias_attribute :benefit_8, :Ben8 + alias_attribute :benefit_desc_9, :BenDesc9 + alias_attribute :benefit_9, :Ben9 + alias_attribute :benefit_desc_10, :BenDesc10 + alias_attribute :benefit_10, :Ben10 + alias_attribute :benefit_desc_11, :BenDesc11 + alias_attribute :benefit_11, :Ben11 + alias_attribute :benefit_desc_12, :BenDesc12 + alias_attribute :benefit_12, :Ben12 + alias_attribute :benefit_desc_13, :BenDesc13 + alias_attribute :benefit_13, :Ben13 + alias_attribute :benefit_desc_14, :BenDesc14 + alias_attribute :benefit_14, :Ben14 alias_attribute :pl_plan_key, :PLPlanKey alias_attribute :primary_mb_member_key, :PrimaryMBMemberKey alias_attribute :ppo_lookup_1, :PPOLookup1 @@ -103,19 +103,19 @@ module Vhcs alias_attribute :ppo_data_2, :PPOData2 alias_attribute :ppo_data_3, :PPOData3 alias_attribute :last_name, :LastName - alias_attribute :provider_line_1_2, :ProviderLine12 - alias_attribute :claim_to_1_2, :ClaimTo12 + alias_attribute :provider_line_12, :ProviderLine12 + alias_attribute :claim_to_12, :ClaimTo12 def attributes rails_like = { id: self.id, facility: self.facility, - division: self.division, + employer_name: self.employer_name, full_name: self.full_name, ssn: self.ssn, medical_coverage: self.medical_coverage, medical_eff_date: self.medical_eff_date, - medical_group_num: self.medical_group_num, + group_number: self.group_number, dental_coverage: self.dental_coverage, dental_eff_date: self.dental_eff_date, dental_group_num: self.dental_group_num, @@ -130,8 +130,8 @@ module Vhcs provider_line_7: self.provider_line_7, provider_line_8: self.provider_line_8, provider_line_9: self.provider_line_9, - provider_line_1_0: self.provider_line_1_0, - provider_line_1_1: self.provider_line_1_1, + provider_line_10: self.provider_line_10, + provider_line_11: self.provider_line_11, mail_to: self.mail_to, mail_to_2: self.mail_to_2, claim_to_1: self.claim_to_1, @@ -143,15 +143,15 @@ module Vhcs claim_to_7: self.claim_to_7, claim_to_8: self.claim_to_8, claim_to_9: self.claim_to_9, - claim_to_1_0: self.claim_to_1_0, - claim_to_1_1: self.claim_to_1_1, + claim_to_10: self.claim_to_10, + claim_to_11: self.claim_to_11, contact_line_1: self.contact_line_1, contact_line_2: self.contact_line_2, contact_line_3: self.contact_line_3, group_number: self.group_number, family_id: self.family_id, group_no: self.group_no, - rx_group_id: self.rx_group_id, + rx_group: self.rx_group, help_desk: self.help_desk, customer_service: self.customer_service, web_url: self.web_url, @@ -165,34 +165,34 @@ module Vhcs dependent_6: self.dependent_6, dependent_7: self.dependent_7, dependent_8: self.dependent_8, - ben_desc_1: self.ben_desc_1, - ben_1: self.ben_1, - ben_desc_2: self.ben_desc_2, - ben_2: self.ben_2, - ben_desc_3: self.ben_desc_3, - ben_3: self.ben_3, - ben_desc_4: self.ben_desc_4, - ben_4: self.ben_4, - ben_desc_5: self.ben_desc_5, - ben_5: self.ben_5, - ben_desc_6: self.ben_desc_6, - ben_6: self.ben_6, - ben_desc_7: self.ben_desc_7, - ben_7: self.ben_7, - ben_desc_8: self.ben_desc_8, - ben_8: self.ben_8, - ben_desc_9: self.ben_desc_9, - ben_9: self.ben_9, - ben_desc_1_0: self.ben_desc_1_0, - ben_1_0: self.ben_1_0, - ben_desc_1_1: self.ben_desc_1_1, - ben_1_1: self.ben_1_1, - ben_desc_1_2: self.ben_desc_1_2, - ben_1_2: self.ben_1_2, - ben_desc_1_3: self.ben_desc_1_3, - ben_1_3: self.ben_1_3, - ben_desc_1_4: self.ben_desc_1_4, - ben_1_4: self.ben_1_4, + benefit_desc_1: self.benefit_desc_1, + benefit_1: self.benefit_1, + benefit_desc_2: self.benefit_desc_2, + benefit_2: self.benefit_2, + benefit_desc_3: self.benefit_desc_3, + benefit_3: self.benefit_3, + benefit_desc_4: self.benefit_desc_4, + benefit_4: self.benefit_4, + benefit_desc_5: self.benefit_desc_5, + benefit_5: self.benefit_5, + benefit_desc_6: self.benefit_desc_6, + benefit_6: self.benefit_6, + benefit_desc_7: self.benefit_desc_7, + benefit_7: self.benefit_7, + benefit_desc_8: self.benefit_desc_8, + benefit_8: self.benefit_8, + benefit_desc_9: self.benefit_desc_9, + benefit_9: self.benefit_9, + benefit_desc_10: self.benefit_desc_10, + benefit_10: self.benefit_10, + benefit_desc_11: self.benefit_desc_11, + benefit_11: self.benefit_11, + benefit_desc_12: self.benefit_desc_12, + benefit_12: self.benefit_12, + benefit_desc_13: self.benefit_desc_13, + benefit_13: self.benefit_13, + benefit_desc_14: self.benefit_desc_14, + benefit_14: self.benefit_14, pl_plan_key: self.pl_plan_key, primary_mb_member_key: self.primary_mb_member_key, ppo_lookup_1: self.ppo_lookup_1, @@ -208,8 +208,8 @@ module Vhcs ppo_data_2: self.ppo_data_2, ppo_data_3: self.ppo_data_3, last_name: self.last_name, - provider_line_1_2: self.provider_line_1_2, - claim_to_1_2: self.claim_to_1_2, + provider_line_12: self.provider_line_12, + claim_to_12: self.claim_to_12, } super.merge(rails_like) end diff --git a/app/models/vhcs/hlid_cards_view_egg.rb b/app/models/vhcs/hlid_cards_view_egg.rb new file mode 100644 index 0000000..46ff85e --- /dev/null +++ b/app/models/vhcs/hlid_cards_view_egg.rb @@ -0,0 +1,217 @@ +module Vhcs + class HlidCardsViewEgg < VhcsRecord + + self.table_name = 'HLIDCardsViewEgg' + + alias_attribute :facility, :Facility + alias_attribute :division, :Division + alias_attribute :full_name, :FullName + alias_attribute :ssn, :SSN + alias_attribute :medical_coverage, :MedicalCoverage + alias_attribute :medical_eff_date, :MedicalEffDate + alias_attribute :medical_group_num, :MedicalGroupNum + alias_attribute :dental_coverage, :DentalCoverage + alias_attribute :dental_eff_date, :DentalEffDate + alias_attribute :dental_group_num, :DentalGroupNum + alias_attribute :card_type, :CardType + alias_attribute :provider_code, :ProviderCode + alias_attribute :provider_line_1, :ProviderLine1 + alias_attribute :provider_line_2, :ProviderLine2 + alias_attribute :provider_line_3, :ProviderLine3 + alias_attribute :provider_line_4, :ProviderLine4 + alias_attribute :provider_line_5, :ProviderLine5 + alias_attribute :provider_line_6, :ProviderLine6 + alias_attribute :provider_line_7, :ProviderLine7 + alias_attribute :provider_line_8, :ProviderLine8 + alias_attribute :provider_line_9, :ProviderLine9 + alias_attribute :provider_line_1_0, :ProviderLine10 + alias_attribute :provider_line_1_1, :ProviderLine11 + alias_attribute :mail_to, :MailTo + alias_attribute :mail_to_2, :MailTo2 + alias_attribute :claim_to_1, :ClaimTo1 + alias_attribute :claim_to_2, :ClaimTo2 + alias_attribute :claim_to_3, :ClaimTo3 + alias_attribute :claim_to_4, :ClaimTo4 + alias_attribute :claim_to_5, :ClaimTo5 + alias_attribute :claim_to_6, :ClaimTo6 + alias_attribute :claim_to_7, :ClaimTo7 + alias_attribute :claim_to_8, :ClaimTo8 + alias_attribute :claim_to_9, :ClaimTo9 + alias_attribute :claim_to_1_0, :ClaimTo10 + alias_attribute :claim_to_1_1, :ClaimTo11 + alias_attribute :contact_line_1, :ContactLine1 + alias_attribute :contact_line_2, :ContactLine2 + alias_attribute :contact_line_3, :ContactLine3 + alias_attribute :group_number, :GroupNumber + alias_attribute :family_id, :FamilyId + alias_attribute :group_no, :GroupNo + alias_attribute :rx_group_id, :RXGroupID + alias_attribute :help_desk, :HelpDesk + alias_attribute :customer_service, :CustomerService + alias_attribute :web_url, :WebUrl + alias_attribute :expr_1, :Expr1 + alias_attribute :line_3, :Line3 + alias_attribute :dependent_1, :Dependent1 + alias_attribute :dependent_2, :Dependent2 + alias_attribute :dependent_3, :Dependent3 + alias_attribute :dependent_4, :Dependent4 + alias_attribute :dependent_5, :Dependent5 + alias_attribute :dependent_6, :Dependent6 + alias_attribute :dependent_7, :Dependent7 + alias_attribute :dependent_8, :Dependent8 + alias_attribute :ben_desc_1, :BenDesc1 + alias_attribute :ben_1, :Ben1 + alias_attribute :ben_desc_2, :BenDesc2 + alias_attribute :ben_2, :Ben2 + alias_attribute :ben_desc_3, :BenDesc3 + alias_attribute :ben_3, :Ben3 + alias_attribute :ben_desc_4, :BenDesc4 + alias_attribute :ben_4, :Ben4 + alias_attribute :ben_desc_5, :BenDesc5 + alias_attribute :ben_5, :Ben5 + alias_attribute :ben_desc_6, :BenDesc6 + alias_attribute :ben_6, :Ben6 + alias_attribute :ben_desc_7, :BenDesc7 + alias_attribute :ben_7, :Ben7 + alias_attribute :ben_desc_8, :BenDesc8 + alias_attribute :ben_8, :Ben8 + alias_attribute :ben_desc_9, :BenDesc9 + alias_attribute :ben_9, :Ben9 + alias_attribute :ben_desc_1_0, :BenDesc10 + alias_attribute :ben_1_0, :Ben10 + alias_attribute :ben_desc_1_1, :BenDesc11 + alias_attribute :ben_1_1, :Ben11 + alias_attribute :ben_desc_1_2, :BenDesc12 + alias_attribute :ben_1_2, :Ben12 + alias_attribute :ben_desc_1_3, :BenDesc13 + alias_attribute :ben_1_3, :Ben13 + alias_attribute :ben_desc_1_4, :BenDesc14 + alias_attribute :ben_1_4, :Ben14 + alias_attribute :pl_plan_key, :PLPlanKey + alias_attribute :mb_member_key, :MBMemberKey + alias_attribute :provider_lookup_1, :ProviderLookup1 + alias_attribute :provider_lookup_2, :ProviderLookup2 + alias_attribute :precert_1, :Precert1 + alias_attribute :precert_2, :Precert2 + alias_attribute :precert_3, :Precert3 + alias_attribute :precert_4, :Precert4 + alias_attribute :precert_5, :Precert5 + alias_attribute :precert_6, :Precert6 + alias_attribute :miscdata, :MISCDATA + alias_attribute :ppodata, :PPODATA + alias_attribute :ppodata_2, :PPODATA2 + alias_attribute :ppodata_3, :PPODATA3 + alias_attribute :last_name, :LastName + alias_attribute :provider_line_1_2, :ProviderLine12 + alias_attribute :claim_to_1_2, :ClaimTo12 + + def attributes + rails_like = { + facility: self.facility, + division: self.division, + full_name: self.full_name, + ssn: self.ssn, + medical_coverage: self.medical_coverage, + medical_eff_date: self.medical_eff_date, + medical_group_num: self.medical_group_num, + dental_coverage: self.dental_coverage, + dental_eff_date: self.dental_eff_date, + dental_group_num: self.dental_group_num, + card_type: self.card_type, + provider_code: self.provider_code, + provider_line_1: self.provider_line_1, + provider_line_2: self.provider_line_2, + provider_line_3: self.provider_line_3, + provider_line_4: self.provider_line_4, + provider_line_5: self.provider_line_5, + provider_line_6: self.provider_line_6, + provider_line_7: self.provider_line_7, + provider_line_8: self.provider_line_8, + provider_line_9: self.provider_line_9, + provider_line_1_0: self.provider_line_1_0, + provider_line_1_1: self.provider_line_1_1, + mail_to: self.mail_to, + mail_to_2: self.mail_to_2, + claim_to_1: self.claim_to_1, + claim_to_2: self.claim_to_2, + claim_to_3: self.claim_to_3, + claim_to_4: self.claim_to_4, + claim_to_5: self.claim_to_5, + claim_to_6: self.claim_to_6, + claim_to_7: self.claim_to_7, + claim_to_8: self.claim_to_8, + claim_to_9: self.claim_to_9, + claim_to_1_0: self.claim_to_1_0, + claim_to_1_1: self.claim_to_1_1, + contact_line_1: self.contact_line_1, + contact_line_2: self.contact_line_2, + contact_line_3: self.contact_line_3, + group_number: self.group_number, + family_id: self.family_id, + group_no: self.group_no, + rx_group_id: self.rx_group_id, + help_desk: self.help_desk, + customer_service: self.customer_service, + web_url: self.web_url, + expr_1: self.expr_1, + line_3: self.line_3, + dependent_1: self.dependent_1, + dependent_2: self.dependent_2, + dependent_3: self.dependent_3, + dependent_4: self.dependent_4, + dependent_5: self.dependent_5, + dependent_6: self.dependent_6, + dependent_7: self.dependent_7, + dependent_8: self.dependent_8, + ben_desc_1: self.ben_desc_1, + ben_1: self.ben_1, + ben_desc_2: self.ben_desc_2, + ben_2: self.ben_2, + ben_desc_3: self.ben_desc_3, + ben_3: self.ben_3, + ben_desc_4: self.ben_desc_4, + ben_4: self.ben_4, + ben_desc_5: self.ben_desc_5, + ben_5: self.ben_5, + ben_desc_6: self.ben_desc_6, + ben_6: self.ben_6, + ben_desc_7: self.ben_desc_7, + ben_7: self.ben_7, + ben_desc_8: self.ben_desc_8, + ben_8: self.ben_8, + ben_desc_9: self.ben_desc_9, + ben_9: self.ben_9, + ben_desc_1_0: self.ben_desc_1_0, + ben_1_0: self.ben_1_0, + ben_desc_1_1: self.ben_desc_1_1, + ben_1_1: self.ben_1_1, + ben_desc_1_2: self.ben_desc_1_2, + ben_1_2: self.ben_1_2, + ben_desc_1_3: self.ben_desc_1_3, + ben_1_3: self.ben_1_3, + ben_desc_1_4: self.ben_desc_1_4, + ben_1_4: self.ben_1_4, + pl_plan_key: self.pl_plan_key, + mb_member_key: self.mb_member_key, + provider_lookup_1: self.provider_lookup_1, + provider_lookup_2: self.provider_lookup_2, + precert_1: self.precert_1, + precert_2: self.precert_2, + precert_3: self.precert_3, + precert_4: self.precert_4, + precert_5: self.precert_5, + precert_6: self.precert_6, + miscdata: self.miscdata, + ppodata: self.ppodata, + ppodata_2: self.ppodata_2, + ppodata_3: self.ppodata_3, + last_name: self.last_name, + provider_line_1_2: self.provider_line_1_2, + claim_to_1_2: self.claim_to_1_2, + } + super.merge(rails_like) + end + + + end +end \ No newline at end of file diff --git a/app/services/automation_service/employer_members_update.rb b/app/services/automation_service/employer_members_update.rb new file mode 100644 index 0000000..e6aa8f7 --- /dev/null +++ b/app/services/automation_service/employer_members_update.rb @@ -0,0 +1,35 @@ +module AutomationService + class EmployerMembersUpdate + + def initialize(pl_plan_key) + @pl_plan_key = pl_plan_key + end + + def call + employer = Employer.includes(:id_card_setup).find_by(pl_plan_key: @pl_plan_key) + card_setup = employer.id_card_setup + puts "-- #{employer.name}" + + # employer_members =[] + vw_mb_members = Vhcs::VwmbMember.where(enrollee_type_value_id: 1, pl_plan_key: @pl_plan_key).select(:mb_member_key, :pb_entity_key, :pl_plan_key, :family_id, :full_name_last_name_first, :social_security_number) + # vw_mb_members.each do |vw_mb_member| + # member = UpdateMemberJob.perform_now(@pb_entity_key, employer.id, card_setup.has_divisions, card_setup.has_dental, true, vw_mb_member) + # end + # employer.members = employer_members + # employer.save + + member_update_futures = vw_mb_members.map do |vw_mb_member| + Concurrent::Future.execute do + ActiveRecord::Base.connection_pool.with_connection do + UpdateMemberJob.perform_now(@pb_entity_key, employer.id, card_setup.has_divisions, card_setup.has_dental, vw_mb_member) + end + end + end + + member_updates = member_update_futures.map(&:value).compact + employer.members = member_updates + employer.save + + end + end +end \ No newline at end of file diff --git a/app/services/automation_service/employer_update.rb b/app/services/automation_service/employer_update.rb new file mode 100644 index 0000000..cffb0ad --- /dev/null +++ b/app/services/automation_service/employer_update.rb @@ -0,0 +1,23 @@ +module AutomationService + class EmployerUpdate + + def initialize(pl_plan_key, full_sync = false) + @pl_plan_key = pl_plan_key + @full_sync = full_sync + end + + def call + # employer = Employer.includes(:id_card_setup).find_by(pl_plan_key: @pl_plan_key) + # card_setup = employer.id_card_setup + UpdateEmployerJob.new.perform(@pl_plan_key, {}, @full_sync) + # if employer.present? + # employer.save + # else + # Member.find_by(pb_entity_key: vw_mb_member[:pb_entity_key]).destroy + # end + end + + end +end + +# AutomationService::MemberUpdate('13', 337710) \ No newline at end of file diff --git a/app/services/automation_service/member_update.rb b/app/services/automation_service/member_update.rb new file mode 100644 index 0000000..215c6ce --- /dev/null +++ b/app/services/automation_service/member_update.rb @@ -0,0 +1,23 @@ +module AutomationService + class MemberUpdate + + def initialize(pl_plan_key, pb_entity_key) + @pl_plan_key = pl_plan_key + @pb_entity_key = pb_entity_key + end + + def call + employer = Employer.includes(:id_card_setup).find_by(pl_plan_key: @pl_plan_key) + card_setup = employer.id_card_setup + member = UpdateMemberJob.perform_now(@pb_entity_key, employer.id, card_setup.has_divisions, card_setup.has_dental) + if member.present? + member.save + else + Member.find_by(pb_entity_key: vw_mb_member[:pb_entity_key]).destroy + end + end + + end +end + +# AutomationService::MemberUpdate('13', 337710) \ No newline at end of file diff --git a/app/services/id_card_printer_service/card_data_formatter.rb b/app/services/id_card_printer_service/card_data_formatter.rb index 5ab5f63..ce48803 100644 --- a/app/services/id_card_printer_service/card_data_formatter.rb +++ b/app/services/id_card_printer_service/card_data_formatter.rb @@ -3,7 +3,7 @@ module IdCardPrinterService def initialize(employers_member_keys) # @employer = employer - @employers_member_keys = employers_member_keys + @employers_member_keys = Array.wrap(employers_member_keys) # @employer = Employer.includes(id_card_setup: [:provider_section, :rx_section]).find_by(pl_plan_key: pl_plan_key) # @card_setup = @employer.id_card_setup @@ -41,7 +41,6 @@ module IdCardPrinterService group_number: @employer.group_number, rx_group: @card_setup.rx_group_number, network_provider: @card_setup.network_provider, - network_logo_id: @card_setup.network_logo_id, network_logo_filename: @card_setup.network_logo.filename, employer_logo_filename: @card_setup.employer_logo.filename } @@ -58,7 +57,8 @@ module IdCardPrinterService :provider_line_1, :provider_line_2, :provider_line_3, :provider_line_4, :provider_line_5, :provider_line_6, :provider_line_7, :provider_line_8, :provider_line_9, :provider_line_10, :provider_line_11, :provider_line_12, :claim_to_1, :claim_to_2, :claim_to_3, :claim_to_4, :claim_to_5, :claim_to_6, - :claim_to_7, :claim_to_8, :claim_to_9, :claim_to_10, :claim_to_11, :claim_to_12 + :claim_to_7, :claim_to_8, :claim_to_9, :claim_to_10, :claim_to_11, :claim_to_12, + :precert_1, :precert_2, :precert_3, :precert_4 ) selected_attributes = employer_attributes.merge(rx_attributes).merge(provider_attributes) @@ -83,11 +83,16 @@ module IdCardPrinterService end def create_member_cards_async - field_exceptions = @card_setup.field_exceptions.pluck(:id) + field_exceptions_map = @card_setup.field_exceptions_card_attributes_by_member_id(@member_keys) mmember_card_futures = @member_keys.map do |member_key| + member_card_exceptions_attrs = {} + member_card_exception_id = field_exceptions_map[member_key] + if member_card_exception_id + member_card_exceptions_attrs = field_exceptions_map[member_card_exception_id] + end Concurrent::Future.execute do ActiveRecord::Base.connection_pool.with_connection do - ProcessIdCardDataJob.perform_now(member_key, field_exceptions, @card_setup.has_divisions) + ProcessMemberCardDataJob.perform_now(member_key, member_card_exceptions_attrs, @card_setup.has_divisions, @card_setup.has_dental) end end end diff --git a/app/services/id_card_printer_service/cards_generator.rb b/app/services/id_card_printer_service/cards_generator.rb index a68ce0f..34bca88 100644 --- a/app/services/id_card_printer_service/cards_generator.rb +++ b/app/services/id_card_printer_service/cards_generator.rb @@ -15,13 +15,30 @@ module IdCardPrinterService IdCard::PrintData.where(pl_plan_key: pl_plan_keys, primary_mb_member_key: nil).destroy_all pdf_array = [] - batches = break_into_batches(pl_plan_keys) - batches.each do |card_template, batch_pl_plan_keys| - jasper_batch_id = "#{batch_pl_plan_keys.join('_')}-#{Time.current.utc.to_i}" - batch = IdCard::PrintData.where(pl_plan_key: batch_pl_plan_keys) - batch.update!(jasper_batch_id: jasper_batch_id) - batch_pdf = IdCardPrinterService::PdfBatchProcessor.new(card_template, jasper_batch_id, @layout).call - pdf_array << batch_pdf + template_groups = break_up_by_template(pl_plan_keys) + template_groups.each do |card_template, template_pl_plan_keys| + batch = IdCard::PrintData.where(pl_plan_key: template_pl_plan_keys) + # all_template_cards.in_batches(of: 75).each_with_index do |batch, index| + jasper_batch_id = "#{template_pl_plan_keys.join('_')}-#{Time.current.utc.to_i}" + # binding.pry + batch.update!(jasper_batch_id: jasper_batch_id) + if @layout == "PrintCard" + add_dependent_cards(batch) + end + batch_pdf = IdCardPrinterService::PdfBatchProcessor.new(card_template, jasper_batch_id, @layout).call + pdf_array << batch_pdf + # end + # jasper_batches = break_into_jasper_batches(group_pl_plan_keys) + # jasper_batches.each_with_index do |batch, index| + # jasper_batch_id = "#{group_pl_plan_keys.join('_')}-#{index + 1}-#{Time.current.utc.to_i}" + # binding.pry + # batch.update!(jasper_batch_id: jasper_batch_id) + # if @layout == "PrintCard" + # add_dependent_cards(batch) + # end + # batch_pdf = IdCardPrinterService::PdfBatchProcessor.new(card_template, jasper_batch_id, @layout).call + # pdf_array << batch_pdf + # end end # @employers_member_keys.each do |emk| # employer_jasper_batches = IdCard::PrintData.where(pl_plan_key: emk[:pl_plan_key]).pluck(:network_logo_id).uniq @@ -44,18 +61,47 @@ module IdCardPrinterService private - def break_into_batches(pl_plan_keys) + def break_up_by_template(pl_plan_keys) batches_by_card_template = IdCard::Setup.where(pl_plan_key: pl_plan_keys).group_by(&:card_template) .transform_values { |setups| setups.map(&:pl_plan_key) } .compact_blank end + def break_into_jasper_batches(pl_plan_keys) + all_cards = IdCard::PrintData.where(pl_plan_key: pl_plan_keys) + binding.pry + jasper_batches = all_cards.each_slice(75).to_a + jasper_batches + end + + def add_dependent_cards(batch) + batch.where.not(dependent_1: [nil, ""]).find_each do |member_card| + dependent_card = member_card.dup + dependent_card.update( + full_name_last_name_first: member_card.full_name_last_name_first.concat(" dependent") + ) + dependent_card.save + end + end + def combine_pdfs(pdf_array) if @zip group_cards_pdf = Zip::OutputStream.write_buffer do |zio| - pdf_array.each do |file| - zio.put_next_entry(file[:name]) - zio.write(file[:data]) + pdf_file = pdf_array.first + puts "-- CombinePdfPages --" + puts pdf_file.pages.count + pdf_file.pages.reverse.each do |page| + page_pdf = CombinePDF.new + page_pdf << page + page_data = page_pdf.to_pdf + full_name_last_name_first = get_watermark_field(page_data) + if full_name_last_name_first.present? + page_filename = "#{full_name_last_name_first.gsub(", ", "_")}_digital_card_#{Date.today}.pdf" + puts "-- Filename --" + puts page_filename + zio.put_next_entry(page_filename) + zio.write(page_data) + end end end else @@ -64,5 +110,19 @@ module IdCardPrinterService end group_cards_pdf end + + def get_watermark_field(page_data) + watermark_field = "" + reader = PDF::Reader.new(StringIO.new(page_data)) + puts "-- ReaderPages --" + puts reader.pages.count + page = reader.pages.first + if watermark_match = page.text.match(/:WATERMARK:([^:]*):/) + watermark_field = page.text.match(/:WATERMARK:([^:]*):/)[1].strip + else + puts "blank page" + end + watermark_field + end end end diff --git a/app/services/id_card_printer_service/jasper_batch_url_generator.rb b/app/services/id_card_printer_service/jasper_batch_url_generator.rb index 7876167..4c0f3d4 100644 --- a/app/services/id_card_printer_service/jasper_batch_url_generator.rb +++ b/app/services/id_card_printer_service/jasper_batch_url_generator.rb @@ -32,7 +32,7 @@ module IdCardPrinterService host: '10.41.1.115', port: 8080, path: '/trunk/IdCardsServlet', - query: "reportConn=BrittonConnect&cardTemplate=#{@card_template}Batch&printType=Batch#{@layout}&jasper_batch_id=#{@jasper_batch_id}&FileType=PDF" + query: "reportConn=BrittonConnect&cardTemplate=#{@card_template}&printType=#{@layout}&jasper_batch_id=#{@jasper_batch_id}&FileType=PDF" } end diff --git a/app/services/id_card_printer_service/jasper_pdf_generator.rb b/app/services/id_card_printer_service/jasper_pdf_generator.rb index 206bcde..5160a3e 100644 --- a/app/services/id_card_printer_service/jasper_pdf_generator.rb +++ b/app/services/id_card_printer_service/jasper_pdf_generator.rb @@ -9,6 +9,7 @@ module IdCardPrinterService def call response = HTTParty.get(@jasper_url) + # response.body CombinePDF.parse(response.body) end diff --git a/app/services/id_card_printer_service/pdf_formatter.rb b/app/services/id_card_printer_service/pdf_formatter.rb new file mode 100644 index 0000000..1077440 --- /dev/null +++ b/app/services/id_card_printer_service/pdf_formatter.rb @@ -0,0 +1,118 @@ +module IdCardPrinterService + class PdfFormatter + + def initialize(pdf_array ,layout, zip=false) + @pdf_array = pdf_array + @layout = layout + @zip = zip + end + + def call + + if @layout == "FullPageCard" + pdf_file = @pdf_array.first + puts "-- CombinePdfPages --" + puts pdf_file.pages.count + pdf_file.pages.reverse.each do |page| + page_pdf = CombinePDF.new + page_pdf << page + page_data = page_pdf.to_pdf + full_name_last_name_first = get_watermark_field(page_data) + if full_name_last_name_first.present? + page_filename = "#{full_name_last_name_first.gsub(", ", "_")}_digital_card_#{Date.today}.pdf" + group_cards_pdf_array << { name: page_filename, data: page_data } + end + end + + group_cards_pdf = Zip::OutputStream.write_buffer do |zio| + pdf_file = pdf_array.first + puts "-- CombinePdfPages --" + puts pdf_file.pages.count + pdf_file.pages.reverse.each do |page| + page_pdf = CombinePDF.new + page_pdf << page + page_data = page_pdf.to_pdf + full_name_last_name_first = get_watermark_field(page_data) + if full_name_last_name_first.present? + page_filename = "#{full_name_last_name_first.gsub(", ", "_")}_digital_card_#{Date.today}.pdf" + puts "-- Filename --" + puts page_filename + zio.put_next_entry(page_filename) + zio.write(page_data) + end + end + end + else + group_cards_pdf = CombinePDF.new + pdf_array.each { |pdf| group_cards_pdf << pdf } + end + group_cards_pdf + + + + end + + private + + def get_watermark_field(page_data) + watermark_field = "" + reader = PDF::Reader.new(StringIO.new(page_data)) + puts "-- ReaderPages --" + puts reader.pages.count + page = reader.pages.first + if watermark_match = page.text.match(/:WATERMARK:([^:]*):/) + watermark_field = page.text.match(/:WATERMARK:([^:]*):/)[1].strip + else + puts "blank page" + end + watermark_field + end + + def break_into_batches(pl_plan_keys) + batches_by_card_template = IdCard::Setup.where(pl_plan_key: pl_plan_keys).group_by(&:card_template) + .transform_values { |setups| setups.map(&:pl_plan_key) } + .compact_blank + end + + def combine_pdfs(pdf_array) + if @zip + group_cards_pdf = Zip::OutputStream.write_buffer do |zio| + pdf_file = pdf_array.first + puts "-- CombinePdfPages --" + puts pdf_file.pages.count + pdf_file.pages.reverse.each do |page| + page_pdf = CombinePDF.new + page_pdf << page + page_data = page_pdf.to_pdf + full_name_last_name_first = get_watermark_field(page_data) + if full_name_last_name_first.present? + page_filename = "#{full_name_last_name_first.gsub(", ", "_")}_digital_card_#{Date.today}.pdf" + puts "-- Filename --" + puts page_filename + zio.put_next_entry(page_filename) + zio.write(page_data) + end + end + end + else + group_cards_pdf = CombinePDF.new + pdf_array.each { |pdf| group_cards_pdf << pdf } + end + group_cards_pdf + end + + def get_watermark_field(page_data) + watermark_field = "" + reader = PDF::Reader.new(StringIO.new(page_data)) + puts "-- ReaderPages --" + puts reader.pages.count + page = reader.pages.first + if watermark_match = page.text.match(/:WATERMARK:([^:]*):/) + watermark_field = page.text.match(/:WATERMARK:([^:]*):/)[1].strip + else + puts "blank page" + end + watermark_field + end + end +end diff --git a/app/services/id_card_queue_service/get_queued_cards.rb b/app/services/id_card_queue_service/get_queued_members.rb similarity index 82% rename from app/services/id_card_queue_service/get_queued_cards.rb rename to app/services/id_card_queue_service/get_queued_members.rb index bf3cc4e..e5e11d3 100644 --- a/app/services/id_card_queue_service/get_queued_cards.rb +++ b/app/services/id_card_queue_service/get_queued_members.rb @@ -1,5 +1,5 @@ module IdCardQueueService - class GetQueuedCards + class GetQueuedMembers def initialize(pl_plan_keys = nil) if pl_plan_keys @@ -10,7 +10,7 @@ module IdCardQueueService end def call - raw_employers_member_keys = CallStoredProc.new('BrittonGetQueuedIdCardMemberKeysTPA', { PLPlanKeys: @employer_pl_plan_keys }).call.to_ary + raw_employers_member_keys = CallStoredProc.new('HLGetQueuedIdCardMemberKeysTPA', { PLPlanKeys: @employer_pl_plan_keys }).call.to_ary format_employers_member_keys(raw_employers_member_keys) end diff --git a/app/services/reports_service/card_comparisons.rb b/app/services/reports_service/card_comparisons.rb new file mode 100644 index 0000000..c7d04ec --- /dev/null +++ b/app/services/reports_service/card_comparisons.rb @@ -0,0 +1,237 @@ +module ReportsService + class CardComparisons + + def initialize(pl_plan_key, member_pb_entity_key = nil) + @pl_plan_key = pl_plan_key + @member_pb_entity_key = member_pb_entity_key + @hlid_ids_compared = [] + end + + def call + if @member_pb_entity_key + IdCard::PrintData.where(primary_mb_member_key: @member_pb_entity_key).destroy_all + CallStoredProc.new('HLQueueIDCardByKey', { PBEntityKey: @member_pb_entity_key }).call + IdCardPrinterService::CardDataFormatter.new([{pl_plan_key: @pl_plan_key, member_keys: [@member_pb_entity_key]}]).call + puts "use ID Cards app for group #{@pl_plan_key}, then press enter." + continue = gets + + compare_member_cards(@member_pb_entity_key) + else + employer_card_comparison = Report::CardComparison.find_or_create_by(member_number: "#{@pl_plan_key}-Group", pl_plan_key: @pl_plan_key) + + AutomationService::EmployerMembersUpdate.new(@pl_plan_key).call + employer_member_keys = Employer.find_by(pl_plan_key: @pl_plan_key).employer_member_keys + IdCard::PrintData.where(pl_plan_key: @pl_plan_key).destroy_all + CallStoredProc.new('HLQueueAllIDCardsByPlan', { PLPlanKey: @pl_plan_key }).call + IdCardPrinterService::CardDataFormatter.new(employer_member_keys).call + + puts "use ID Cards app for group #{@pl_plan_key}, then press enter." + continue = gets + + IdCard::PrintData.where(pl_plan_key: @pl_plan_key, primary_mb_member_key: nil).destroy_all + + + # new_cards = IdCard::PrintData.where(pl_plan_key: @pl_plan_key) + # add_dependent_cards(new_cards) + new_card_member_keys = IdCard::PrintData.where(pl_plan_key: @pl_plan_key).pluck(:primary_mb_member_key).uniq + old_card_member_keys = Vhcs::HlidCardEggData.where(pl_plan_key: @pl_plan_key).pluck(:primary_mb_member_key).uniq.map(&:to_s) + + missing_from_new = old_card_member_keys - new_card_member_keys + missing_from_old = new_card_member_keys - old_card_member_keys + + if missing_from_new.present? || missing_from_old.present? + employer_card_comparison.comparison_errors.new( + card_field: "Missing Cards", + new_value: missing_from_old.join(', '), + old_value: missing_from_new.join(', ') + ) + end + + # group_errors = [] + # unless new_card_count == old_card_count + # group_errors.push({ + # employer: @pl_plan_key, + # field: 'Card Count Mismatch', + # new_value: new_card_count, + # old_value: old_card_count + # }) + # end + member_keys_array = new_card_member_keys | old_card_member_keys + member_keys_array.each do |member_key| + compare_member_cards(member_key) + end + + failed_cards = Report::CardComparison.where(pl_plan_key: @pl_plan_key, passed: false).where.not(member_number: @pl_plan_key) + if failed_cards.empty? + employer_card_comparison.passed = true + end + + employer_card_comparison.save + @hlid_ids_compared + end + + end + + private + + def compare_member_cards(member_pb_entity_key) + member_card_comparison = Report::CardComparison.find_or_create_by(member_number: member_pb_entity_key, pl_plan_key: @pl_plan_key) + new_card = IdCard::PrintData.find_by(primary_mb_member_key: member_pb_entity_key) + old_card = Vhcs::HlidCardEggData.where(primary_mb_member_key: member_pb_entity_key).first + @hlid_ids_compared << old_card.id + + errors = [] + if new_card.present? && old_card.present? + + # :pl_plan_key, :primary_mb_member_key, :family_id, :full_name, :medical_eff_date, :dental_coverage, + # :provider_line_1, :provider_line_2, :provider_line_3, :provider_line_4, :provider_line_5, :provider_line_6, + # :provider_line_7, :provider_line_8, :provider_line_9, :provider_line_10, :provider_line_11, :provider_line_12, + # :claim_to_1, :claim_to_2, :claim_to_3, :claim_to_4, :claim_to_5, :claim_to_6, + # :claim_to_7, :claim_to_8, :claim_to_9, :claim_to_10, :claim_to_11, :claim_to_12, + # :precert_1, :precert_2, :precert_3, :precert_4, :customer_service, :web_url, :dependent_1, :dependent_2, :dependent_3, + # :dependent_4, :dependent_5, :dependent_6, :dependent_7, :dependent_8, :benefit_desc_1, + + new_card_common = new_card.attributes.with_indifferent_access.except( + :id, :created_at, :full_name_last_name_first, :network_provider, :plan_id, + :network_logo_filename, :employer_logo_filename, :sample_plan_title, :jasper_batch_id, :updated_at + ) + new_card_common.delete_if { |key, value| key.match?(/[[:upper:]]/) } + + new_card_dependents = new_card.attributes.with_indifferent_access.slice( + :dependent_1, :dependent_2, :dependent_3, :dependent_4, :dependent_5, :dependent_6, :dependent_7, :dependent_8 + ) + new_card_dependents.delete_if { |key, value| key.match?(/[[:upper:]]/) } + + new_card_dental = new_card[:dental_coverage] + new_card_eff_date = new_card[:medical_eff_date] + + # old_card_common = old_card.attributes.except( + # :id, :facility, :ssn, :medical_coverage, :dental_eff_date, :dental_group_num, :mail_to, :mail_to_2, :contact_line_1, + # :contact_line_2, :contact_line_3, :group_number, :group_no, :help_desk, :expr_1, :line_3, :ppo_lookup_1, :ppo_lookup_2, + # :precert_5, :precert_6, :misc_data, :ppo_data, :ppo_data_2, :ppo_data_3, :last_name, :card_type, :provider_code + # ) + old_card_common = old_card.attributes.with_indifferent_access.slice( + :employer_name, :full_name, :group_number, :provider_line_1, :provider_line_2, :provider_line_3, + :provider_line_4, :provider_line_5, :provider_line_6, :provider_line_7, :provider_line_8, :provider_line_9, :provider_line_10, + :provider_line_11, :claim_to_1, :claim_to_2, :claim_to_3, :claim_to_4, :claim_to_5, :claim_to_6, :claim_to_7, :claim_to_8, :claim_to_9, + :claim_to_10, :claim_to_11, :family_id, :rx_group, :customer_service, :web_url, :benefit_desc_1, :benefit_1, :benefit_desc_2, :benefit_2, :benefit_desc_3, :benefit_3, + :benefit_desc_4, :benefit_4, :benefit_desc_5, :benefit_5, :benefit_desc_6, :benefit_6, :benefit_desc_7, :benefit_7, :benefit_desc_8, :benefit_8, + :benefit_desc_9, :benefit_9, :benefit_desc_10, :benefit_10, :benefit_desc_11, :benefit_11, :benefit_desc_12, :benefit_12, :benefit_desc_13, :benefit_13, + :benefit_desc_14, :benefit_14, :pl_plan_key, :primary_mb_member_key, :provider_line_12, :claim_to_12 + ) # :precert_1, :precert_2, :precert_3, :precert_4 + old_card_common.transform_keys!(division: :employer_name, medical_group_num: :group_number, rx_group_id: :rx_group) + + old_card_dependents = old_card.attributes.with_indifferent_access.slice( + :dependent_1, :dependent_2, :dependent_3, :dependent_4, :dependent_5, :dependent_6, :dependent_7, :dependent_8 + ) + old_card_dependents.delete_if { |key, value| key.match?(/[[:upper:]]/) } + + old_card_dental = old_card[:dental_coverage] + old_card_eff_date = old_card[:medical_eff_date] + + old_card_common.each do |key, value| + # if key == :benefit_desc_4 + # binding.pry + # end + unless new_card_common[key].to_s.downcase.strip.gsub(/\W/, ' ') == value.to_s.downcase.strip.gsub(/\W/, ' ') + comp_error = member_card_comparison.comparison_errors.find_or_create_by(card_field: key.to_s) + comp_error.update!(new_value: new_card_common[key], old_value: value) + # errors.push({ + # member: old_card_common[:primary_mb_member_key], + # field: key, + # new_value: value, + # old_value: new_card_common[key] + # }) + end + end + + unless old_card_dependents.values.sort == new_card_dependents.values.sort + + missing_from_new = (old_card_dependents.values - new_card_dependents.values).compact_blank + missing_from_old = (new_card_dependents.values - old_card_dependents.values).compact_blank + + # member_card_comparison.comparison_errors.new( + # card_field: "Missing Dependent(s)", + # new_value: missing_from_old.join(', '), + # old_value: missing_from_new.join(', ') + # ) + + comp_error = member_card_comparison.comparison_errors.find_or_create_by(card_field: "Missing Dependent(s)") + comp_error.update!(new_value: missing_from_old.join(', '), old_value: missing_from_new.join(', ')) + + # errors.push({ + # member: old_card_common[:primary_mb_member_key], + # field: 'Missing Dependent(s)', + # new_value: new_card_dependents.values, + # old_value: old_card_dependents.values + # }) + end + + unless new_card_dental == old_card_dental || (old_card_dental == "NONE" && new_card_dental.empty?) + member_card_comparison.comparison_errors.new( + card_field: "dental_coverage", + new_value: new_card_dental, + old_value: old_card_dental + ) + + comp_error = member_card_comparison.comparison_errors.find_or_create_by(card_field: "dental_coverage") + comp_error.update!(new_value: new_card_dental, old_value: old_card_dental) + + # errors.push({ + # member: old_card_common[:primary_mb_member_key], + # field: :dental_coverage, + # new_value: new_card_dental, + # old_value: old_card_dental + # }) + end + + unless new_card_eff_date.to_date == old_card_eff_date.to_date + # member_card_comparison.comparison_errors.new( + # card_field: "medical_eff_date", + # new_value: new_card_eff_date, + # old_value: old_card_eff_date + # ) + + comp_error = member_card_comparison.comparison_errors.find_or_create_by(card_field: "medical_eff_date") + comp_error.update!(new_value: new_card_eff_date, old_value: old_card_eff_date) + + # errors.push({ + # member: old_card_common[:primary_mb_member_key], + # field: :medical_eff_date, + # new_value: new_card_eff_date, + # old_value: old_card_eff_date + # }) + end + else + comp_error = member_card_comparison.comparison_errors.find_or_create_by(card_field: "Missing Member") + comp_error.update!(new_value: new_card.present?, old_value: old_card.present?) + # member_card_comparison.comparison_errors.new( + # card_field: "Missing Member", + # new_value: new_card.present?, + # old_value: old_card.present? + # ) + # errors.push({ + # member: old_card[:primary_mb_member_key], + # field: "Missing Member", + # new_value: new_card.present?, + # old_value: old_card.present? + # }) + end + if member_card_comparison.comparison_errors.empty? + member_card_comparison.passed = true + end + member_card_comparison.save + end + + # def add_dependent_cards(batch) + # batch.where.not(dependent_1: [nil, ""]).find_each do |member_card| + # dependent_card = member_card.dup + # dependent_card.update( + # full_name_last_name_first: member_card.full_name_last_name_first.concat(" dependent") + # ) + # dependent_card.save + # end + # end + + end +end \ No newline at end of file diff --git a/app/services/reports_service/duplicate_old_cards.rb b/app/services/reports_service/duplicate_old_cards.rb new file mode 100644 index 0000000..9732d41 --- /dev/null +++ b/app/services/reports_service/duplicate_old_cards.rb @@ -0,0 +1,56 @@ +module ReportsService + class DuplicateOldCards + + def initialize(pl_plan_keys) + @pl_plan_keys = Array.wrap(pl_plan_keys) + end + + def call + @pl_plan_keys.each do |pl_plan_key| + Vhcs::HlidCardEggData.destroy_all + clear_out_queue() + CallStoredProc.new('HLQueueAllIDCardsByPlan', { PLPlanKey: pl_plan_key }).call + puts "---------------------------------------------------------------------------------" + puts "---------------------------------------------------------------------------------" + puts "use ID Cards app to pull queued for group #{pl_plan_key}, then press enter." + puts "---------------------------------------------------------------------------------" + puts "---------------------------------------------------------------------------------" + continue = gets + + old_cards = Vhcs::HlidCardEggData.where(pl_plan_key: pl_plan_key) + old_cards.each do |card| + duplicate_card(card) + end + + end + + end + + private + + def duplicate_card(card) + unless Report::OldCardDuplicate.exists?(primary_mb_member_key: card.primary_mb_member_key) + dup_attrs = card.attributes.with_indifferent_access.slice( + :employer_name, :full_name, :group_number, :medical_eff_date, :dental_coverage, :provider_line_1, :provider_line_2, :provider_line_3, + :provider_line_4, :provider_line_5, :provider_line_6, :provider_line_7, :provider_line_8, :provider_line_9, :provider_line_10, + :provider_line_11, :provider_line_12, :claim_to_1, :claim_to_2, :claim_to_3, :claim_to_4, :claim_to_5, :claim_to_6, :claim_to_7, + :claim_to_8, :claim_to_9, :claim_to_10, :claim_to_11, :claim_to_12,:family_id, :rx_group, :customer_service, :web_url, :benefit_desc_1, + :benefit_1, :benefit_desc_2, :benefit_2, :benefit_desc_3, :benefit_3, :benefit_desc_4, :benefit_4, :benefit_desc_5, :benefit_5, + :benefit_desc_6, :benefit_6, :benefit_desc_7, :benefit_7, :benefit_desc_8, :benefit_8, :benefit_desc_9, :benefit_9, :benefit_desc_10, + :benefit_10, :benefit_desc_11, :benefit_11, :benefit_desc_12, :benefit_12, :benefit_desc_13, :benefit_13, :benefit_desc_14, :benefit_14, + :dependent_1, :dependent_2, :dependent_3, :dependent_4, :dependent_5, :dependent_6, :dependent_7, :dependent_8, :pl_plan_key, :primary_mb_member_key + ) + Report::OldCardDuplicate.create(dup_attrs) + end + end + + def clear_out_queue + VhcsRecord.connection.execute(" + UPDATE CLDocument + SET DocStatus = 'Printed', PrintDate = GetDate() + where DocStatus <> 'Printed' + ") + end + + end +end diff --git a/app/services/reports_service/employer_card_comparisons.rb b/app/services/reports_service/employer_card_comparisons.rb new file mode 100644 index 0000000..bb1da3d --- /dev/null +++ b/app/services/reports_service/employer_card_comparisons.rb @@ -0,0 +1,147 @@ +module ReportsService + class EmployerCardComparisons + + def initialize(pl_plan_keys) + @pl_plan_keys = Array.wrap(pl_plan_keys) + @hlid_ids_compared = [] + end + + def call + @pl_plan_keys.each do |pl_plan_key| + employer = Employer.find_by(pl_plan_key: pl_plan_key) + employer_card_comparison = Report::EmployerCardComparison.find_or_create_by(pl_plan_key: pl_plan_key) + employer_card_comparison.employer_name = employer.name + + AutomationService::EmployerMembersUpdate.new(pl_plan_key).call + employer_member_keys = employer.employer_member_keys + IdCard::PrintData.where(pl_plan_key: pl_plan_key).destroy_all + IdCardPrinterService::CardDataFormatter.new(employer_member_keys).call + IdCard::PrintData.where(pl_plan_key: pl_plan_key, primary_mb_member_key: nil).destroy_all + + new_card_member_keys = IdCard::PrintData.where(pl_plan_key: pl_plan_key).pluck(:primary_mb_member_key).uniq + old_card_member_keys = Report::OldCardDuplicate.where(pl_plan_key: pl_plan_key).pluck(:primary_mb_member_key).uniq.map(&:to_s) + + missing_from_new = old_card_member_keys - new_card_member_keys + missing_from_old = new_card_member_keys - old_card_member_keys + + if missing_from_new.present? || missing_from_old.present? + comp_error = employer_card_comparison.comparison_errors.find_or_create_by(card_field: "Missing Cards") + comp_error.update(new_value: missing_from_old.join(', '), old_value: missing_from_new.join(', ')) + end + + employer_card_comparison.new_cards_count = new_card_member_keys.count + employer_card_comparison.old_cards_count = old_card_member_keys.count + + member_keys_array = new_card_member_keys | old_card_member_keys + member_keys_array.each do |member_key| + compare_member_cards(member_key, pl_plan_key, employer_card_comparison.id) + end + + employer_card_comparison.total_errors_count = employer_card_comparison.employer_total_errors + if employer_card_comparison.total_errors_count == 0 + employer_card_comparison.passed = true + end + + employer_card_comparison.save + + end + end + + private + + def compare_member_cards(member_pb_entity_key, pl_plan_key, employer_card_comparison_id) + member_card_comparison = Report::MemberCardComparison.find_or_create_by(member_number: member_pb_entity_key, pl_plan_key: pl_plan_key, employer_card_comparison_id: employer_card_comparison_id) + new_card = IdCard::PrintData.find_by(primary_mb_member_key: member_pb_entity_key) + old_card = Report::OldCardDuplicate.find_by(primary_mb_member_key: member_pb_entity_key) + + current_errors = [] + if new_card.present? && old_card.present? + new_card_common = new_card.attributes.with_indifferent_access.except( + :id, :created_at, :full_name_last_name_first, :network_provider, :plan_id, + :network_logo_filename, :employer_logo_filename, :sample_plan_title, :jasper_batch_id, :updated_at, + :dependent_1, :dependent_2, :dependent_3, :dependent_4, :dependent_5, :dependent_6, :dependent_7, :dependent_8, + :precert_1, :precert_2, :precert_3, :precert_4 + ) + new_card_common.delete_if { |key, value| key.match?(/[[:upper:]]/) } + + new_card_dependents = new_card.attributes.with_indifferent_access.slice( + :dependent_1, :dependent_2, :dependent_3, :dependent_4, :dependent_5, :dependent_6, :dependent_7, :dependent_8 + ) + new_card_dependents.delete_if { |key, value| key.match?(/[[:upper:]]/) } + + new_card_dental = new_card[:dental_coverage] + new_card_eff_date = new_card[:medical_eff_date] + + old_card_common = old_card.attributes.with_indifferent_access.except( + :id, :created_at, :updated_at, :dental_coverage, :medical_eff_date, + :dependent_1, :dependent_2, :dependent_3, :dependent_4, :dependent_5, :dependent_6, :dependent_7, :dependent_8, + :precert_1, :precert_2, :precert_3, :precert_4 + ) + if pl_plan_key = '2' + old_card_common.except!( + :benefit_desc_1, :benefit_1, :benefit_desc_2, :benefit_2, :benefit_desc_3, :benefit_3, + :benefit_desc_4, :benefit_4, :benefit_desc_5, :benefit_5, :benefit_desc_6, :benefit_6, :benefit_desc_7, :benefit_7, :benefit_desc_8, :benefit_8, + :benefit_desc_9, :benefit_9, :benefit_desc_10, :benefit_10, :benefit_desc_11, :benefit_11, :benefit_desc_12, :benefit_12, :benefit_desc_13, :benefit_13, + :benefit_desc_14, :benefit_14 + ) + end + old_card_common.delete_if { |key, value| key.match?(/[[:upper:]]/) } + + old_card_dependents = old_card.attributes.with_indifferent_access.slice( + :dependent_1, :dependent_2, :dependent_3, :dependent_4, :dependent_5, :dependent_6, :dependent_7, :dependent_8 + ) + old_card_dependents.delete_if { |key, value| key.match?(/[[:upper:]]/) } + + old_card_dental = old_card[:dental_coverage] + old_card_eff_date = old_card[:medical_eff_date] + + old_card_common.each do |key, value| + unless new_card_common[key].to_s.downcase.squish.gsub(/\W/, ' ') == value.to_s.downcase.squish.gsub(/\W/, ' ') + comp_error = member_card_comparison.comparison_errors.find_or_create_by(card_field: key.to_s) + comp_error.assign_attributes(new_value: new_card_common[key], old_value: value) + current_errors << comp_error + end + end + + unless old_card_dependents.values.map(&:squish).sort == new_card_dependents.values.map(&:squish).sort + missing_from_new = (old_card_dependents.values - new_card_dependents.values).compact_blank + missing_from_old = (new_card_dependents.values - old_card_dependents.values).compact_blank + + comp_error = member_card_comparison.comparison_errors.find_or_create_by(card_field: "Missing Dependent(s)") + comp_error.assign_attributes(new_value: missing_from_old.join(', '), old_value: missing_from_new.join(', ')) + current_errors << comp_error + end + + unless (new_card_dental == old_card_dental) || (old_card_dental == "NONE" && new_card_dental.empty?) + comp_error = member_card_comparison.comparison_errors.find_or_create_by(card_field: "dental_coverage") + comp_error.assign_attributes(new_value: new_card_dental, old_value: old_card_dental) + current_errors << comp_error + end + + unless (old_card_eff_date.present?) || (convert_to_date(new_card_eff_date) == convert_to_date(old_card_eff_date)) + comp_error = member_card_comparison.comparison_errors.find_or_create_by(card_field: "medical_eff_date") + comp_error.assign_attributes(new_value: new_card_eff_date, old_value: old_card_eff_date) + current_errors << comp_error + end + else + comp_error = member_card_comparison.comparison_errors.find_or_create_by(card_field: "Missing Member") + + comp_error.assign_attributes( + new_value: new_card.presence&.primary_mb_member_key || "Missing", + old_value: old_card.presence&.primary_mb_member_key || "Missing" + ) + current_errors << comp_error + end + member_card_comparison.comparison_errors = current_errors + if current_errors.empty? + member_card_comparison.passed = true + end + member_card_comparison.save + end + + def convert_to_date(string_date) + string_date.presence&.then { |s| Date.strptime(s, '%m/%d/%Y') } + end + + end +end \ No newline at end of file diff --git a/app/views/employer_setup/_alt_network_logo_fields.html.erb b/app/views/employer_setup/_alt_network_logo_fields.html.erb index 3246b9c..4a1acbf 100644 --- a/app/views/employer_setup/_alt_network_logo_fields.html.erb +++ b/app/views/employer_setup/_alt_network_logo_fields.html.erb @@ -21,7 +21,7 @@ <%= network_fields.select :exception_type, options_for_select(["Zip","State"]), label: { text: "Exception Type" }, prompt: "Select Type", class: "w-full" %>
- <%= network_fields.text_field :exception_value, label: { text: "Exception Value" }, class: "w-full" %> + <%= network_fields.text_field :exception_values, label: { text: "Exception Values" }, class: "w-full" %>
diff --git a/app/views/employers/show.html.erb b/app/views/employers/show.html.erb index 97bff89..f597b86 100644 --- a/app/views/employers/show.html.erb +++ b/app/views/employers/show.html.erb @@ -60,8 +60,8 @@
- <%= link_to 'Sync Employer with VHCS', generate_sample_id_card_print_path(id: @employer.slug), data: { turbo: false }, class: "flex justify-center items-center w-full cursor-pointer bg-brightlava hover:bg-deepcove border-2 border-brightlava text-platinum text-lg font-bold px-3 rounded-lg h-10 transition duration-100" %> - <%= link_to 'Sync Members with VHCS', generate_print_id_card_print_path(id: @employer.slug),data: { turbo: false }, class: "flex justify-center items-center w-full bg-brightlava hover:bg-deepcove border-2 border-brightlava text-platinum text-lg font-bold px-3 rounded-lg h-10 transition duration-100" %> + <%= link_to 'Sync Employer with VHCS', refresh_employer_information_employers_path(id: @employer.id), data: { turbo: false }, class: "flex justify-center items-center w-full cursor-pointer bg-brightlava hover:bg-deepcove border-2 border-brightlava text-platinum text-lg font-bold px-3 rounded-lg h-10 transition duration-100" %> + <%= link_to 'Sync Members with VHCS', refresh_employer_members_information_employers_path(id: @employer.id),data: { turbo: false }, class: "flex justify-center items-center w-full bg-brightlava hover:bg-deepcove border-2 border-brightlava text-platinum text-lg font-bold px-3 rounded-lg h-10 transition duration-100" %>
diff --git a/app/views/id_card/print/index.html.erb b/app/views/id_card/print/index.html.erb index 60823d9..13d7695 100644 --- a/app/views/id_card/print/index.html.erb +++ b/app/views/id_card/print/index.html.erb @@ -10,7 +10,6 @@ <% @queued.each do |qu| %>
- <%= qu.pl_plan_key %> - <%= qu.employer.name %> (
@@ -32,7 +31,6 @@ <% end %>
- <%= nq.pl_plan_key %> - <%= nq.employer.name %> (
diff --git a/app/views/id_card/setup/_alt_network_logo_fields.html.erb b/app/views/id_card/setup/_alt_network_logo_fields.html.erb index e42bda9..3fd1b69 100644 --- a/app/views/id_card/setup/_alt_network_logo_fields.html.erb +++ b/app/views/id_card/setup/_alt_network_logo_fields.html.erb @@ -1,7 +1,7 @@