diff --git a/app/controllers/policies_controller.rb b/app/controllers/policies_controller.rb index 2fc8ea833..2758c7b9a 100644 --- a/app/controllers/policies_controller.rb +++ b/app/controllers/policies_controller.rb @@ -56,6 +56,23 @@ def transmit end + # Handles a PUT request + # @note This method may modify our termination reason on policy + # @param request [Request] the request object + # @return [String] the resulting webpage + def change_npt_indicator + altered_npt_indicator = params[:policy][:npt_indicator] + policy = Policy.find(params[:policy][:id]) + response = policy.change_npt_indicator(policy, altered_npt_indicator, current_user.email) + if response + message = {notice: "The NPT Indicator was successfully updated to '#{altered_npt_indicator.capitalize}'."} + else + message = {error: "An error occurred: The NPT Indicator was unable to be updated with the new value selected."} + end + person = Policy.find(params[:policy][:id]).subscriber.person + redirect_to person_path(person), flash: message + end + def index @q = params[:q] @qf = params[:qf] @@ -68,9 +85,9 @@ def index end respond_to do |format| - format.html # index.html.erb - format.json { render json: @policies } - end + format.html # index.html.erb + format.json { render json: @policies } + end end def generate_tax_document @@ -163,6 +180,12 @@ def delete_local_generated_tax_document end end + def trigger_1095A_H41 + policy = Policy.find(params[:id]) + Observers::PolicyUpdated.notify(policy) + redirect_to generate_tax_document_form_policy_path(Policy.find(params[:id]), {person_id: Person.find(params[:person_id])}), :flash => { :notice=> "Triggered 1095A and H41 for policy_id: #{policy.id}" } + end + private def void_policy_ids(policy_ids_string) diff --git a/app/helpers/policies_helper.rb b/app/helpers/policies_helper.rb index 115fccf76..133893fcc 100644 --- a/app/helpers/policies_helper.rb +++ b/app/helpers/policies_helper.rb @@ -1,11 +1,11 @@ module PoliciesHelper def show_1095A_document_button?(policy) - if policy.subscriber - Time.now.in_time_zone('Eastern Time (US & Canada)').year > policy.subscriber.coverage_start.year - else - false - end + is_policy_not_eligible_to_notify?(policy) ? false : true + end + + def is_policy_not_eligible_to_notify?(policy) + policy.kind == 'coverall' || policy.is_shop? || policy.plan.metal_level == "catastrophic" || policy.coverage_type.to_s.downcase != "health" || policy.coverage_year.first.year >= Time.now.year end def disable_radio_button?(policy) diff --git a/app/models/cancel_terminate.rb b/app/models/cancel_terminate.rb index 413b604fc..321c555eb 100644 --- a/app/models/cancel_terminate.rb +++ b/app/models/cancel_terminate.rb @@ -18,6 +18,10 @@ def persisted? attr_accessor :people attr_accessor :policy + # Controls the npt_indicator value. + # @return [Boolean] + attr_accessor :npt_indicator + validate :term_date_valid?, :unless => :is_cancel? validate :selected_at_least_one? validate :non_aptc_dependents? diff --git a/app/models/parsers/xml/enrollment/change_request.rb b/app/models/parsers/xml/enrollment/change_request.rb index ee3c81274..5dd778009 100644 --- a/app/models/parsers/xml/enrollment/change_request.rb +++ b/app/models/parsers/xml/enrollment/change_request.rb @@ -10,13 +10,30 @@ def initialize(xml) def type @xml.at_xpath('/proc:Operation/proc:operation/proc:type', @namespaces).text end - def cancel? - type == 'cancel' - end - def terminate? - type == 'terminate' - end + def market_type + @payload.first_element_child.name.split('_').first + end + + def individual_market? + market_type == 'individual' + end + + def subscriber_id + @enrollment_group.at_xpath('./ins:subscriber/ins:exchange_member_id', @namespaces).text + end + + def cancel? + type == 'cancel' + end + + def terminate? + type == 'terminate' + end + + def reinstate? + type == 'reinstate' + end def reason @xml.at_xpath('/proc:Operation/proc:operation/proc:reason', @namespaces) @@ -76,7 +93,6 @@ def affected_enrollees end def subscriber_affected? - subscriber_id = @enrollment_group.at_xpath('./ins:subscriber/ins:exchange_member_id', @namespaces).text affected_enrollees.any? { |e| e.hbx_member_id == subscriber_id} end end diff --git a/app/models/parsers/xml/enrollment/individual_change_request.rb b/app/models/parsers/xml/enrollment/individual_change_request.rb index d8e5d4a17..82a315ab6 100644 --- a/app/models/parsers/xml/enrollment/individual_change_request.rb +++ b/app/models/parsers/xml/enrollment/individual_change_request.rb @@ -4,12 +4,25 @@ def initialize(xml) super(xml) @enrollment_group = @payload.at_xpath('./ins:individual_market_enrollment_group', @namespaces) @plan = @enrollment_group.at_xpath('./ins:plan', @namespaces) + @carrier = @enrollment_group.at_xpath('./ins:carrier', @namespaces) + end + + def eg_id + @enrollment_group.at_xpath('./ins:exchange_policy_id', @namespaces).text end def hios_plan_id @plan.at_xpath('./pln:plan/pln:hios_plan_id', @namespaces).text end + def hbx_carrier_id + @carrier.at_xpath('./car:carrier/car:exchange_carrier_id', @namespaces).text + end + + def carrier_id + @carrier.at_xpath('./ins:carrier_id', @namespaces).text + end + def plan_year subscriber = Parsers::Xml::Enrollment::IndividualEnrollee.new(@enrollment_group.xpath('./ins:subscriber', @namespaces)) begin @@ -19,6 +32,15 @@ def plan_year end end + def begin_date + begin_date = @enrollment_group.at_xpath('./ins:subscriber/ins:coverage/ins:benefit_begin_date', @namespaces).text + Date.strptime(begin_date.to_s, '%Y%m%d') + end + + def plan_id + @plan.at_xpath('./ins:plan_id', @namespaces).text + end + def premium_amount_total @plan.at_xpath('./ins:premium_amount_total', @namespaces).text.to_f end diff --git a/app/models/parsers/xml/enrollment/namespaces.rb b/app/models/parsers/xml/enrollment/namespaces.rb index 0a531e2f9..58bcb5a74 100644 --- a/app/models/parsers/xml/enrollment/namespaces.rb +++ b/app/models/parsers/xml/enrollment/namespaces.rb @@ -4,6 +4,7 @@ module Parsers::Xml::Enrollment ins: 'http://dchealthlink.com/vocabularies/1/insured', con: 'http://dchealthlink.com/vocabularies/1/contact', pln: 'http://dchealthlink.com/vocabularies/1/plan', - emp: 'http://dchealthlink.com/vocabularies/1/employer' + emp: 'http://dchealthlink.com/vocabularies/1/employer', + car: 'http://dchealthlink.com/vocabularies/1/carrier' } -end \ No newline at end of file +end diff --git a/app/models/policy.rb b/app/models/policy.rb index 9137d341b..46791b5ce 100644 --- a/app/models/policy.rb +++ b/app/models/policy.rb @@ -966,6 +966,46 @@ def plan_matched?(active_plan, renewal_plan) end end + # Changing the NPT indicator on a Policy with certain rules they are: + # * NPT indicator value can be change to true if and if only the state of a policy is in termination + # * NPT indicator value can be changed to false regardless of policy state + # * NPT indicator value won't be updated if the exisiting value is same + # @return [Boolean] + def change_npt_indicator(policy, altered_npt_indicator, submitted_by) + old_npt = policy.term_for_np + if (altered_npt_indicator == "true") && (policy.term_for_np == false) && ["terminated", "canceled"].include?(policy.aasm_state) + policy.update_attributes!(term_for_np: true) + Observers::PolicyUpdated.notify(policy) + log_npt_altering(policy, old_npt, submitted_by) + true + elsif (altered_npt_indicator == "false") && (policy.term_for_np == true) + policy.update_attributes!(term_for_np: false) + Observers::PolicyUpdated.notify(policy) + log_npt_altering(policy, old_npt, submitted_by) + true + else + false + end + end + + # Logging the transaction when NPT indicator is succesfully updated + def log_npt_altering(policy, old_npt, submitted_by) + broadcast_info = { + :routing_key => "info.events.policy.non_payment_indicator_altered", + :app_id => "gluedb", + :headers => { + "policy_id" => policy.id.to_s, + "eg_id" => policy.eg_id, + "old_npt" => old_npt, + "new_npt" => policy.term_for_np, + "submitted_by" => submitted_by + } + } + Amqp::EventBroadcaster.with_broadcaster do |eb| + eb.broadcast(broadcast_info, policy.id.to_s) + end + end + protected def generate_enrollment_group_id self.eg_id = self.eg_id || self._id.to_s diff --git a/app/models/vocab_upload.rb b/app/models/vocab_upload.rb index 47cfc9858..e7d0515b5 100644 --- a/app/models/vocab_upload.rb +++ b/app/models/vocab_upload.rb @@ -28,12 +28,10 @@ def save(listener) return(false) unless self.valid? file_data = vocab.read file_name = vocab.original_filename - + doc = Nokogiri::XML(file_data) + change_request = Parsers::Xml::Enrollment::ChangeRequestFactory.create_from_xml(doc) + plan = Plan.find_by_hios_id_and_year(change_request.hios_plan_id, change_request.plan_year) unless bypass_validation - doc = Nokogiri::XML(file_data) - - change_request = Parsers::Xml::Enrollment::ChangeRequestFactory.create_from_xml(doc) - plan = Plan.find_by_hios_id_and_year(change_request.hios_plan_id, change_request.plan_year) validations = [ Validators::PremiumTotalValidatorFactory.create_for(change_request, listener), Validators::PremiumResponsibleValidator.new(change_request, listener), @@ -44,12 +42,79 @@ def save(listener) return false end end - + alter_npt_flag(change_request) if change_request.individual_market? log_upload(file_name, file_data) submit_cv(kind, file_name, file_data) true end + # Changing the NPT indicator to false on a Policy with certain rules they are: + # * If uploaded CV is for carefirst, initial transaction and it has existing terminated policy or canceled policy with term_for_np value as True + # * If uploaded CV is for non-carefirst, maintenance(reinstate) and it has existing terminated policy or canceled policy with term_for_np value as True + # @return [Boolean] + def alter_npt_flag(change_request) + begin + policy = Policy.where(hbx_enrollment_ids: change_request.eg_id).first + if change_request.hbx_carrier_id == "116036" #hbx_carrier_id of CareFirst carrier + alter_carefirst_npt_flag(change_request, policy) + else + alter_non_carefirst_npt_flag(change_request, policy) + end + rescue Exception => e + puts e.to_s + end + end + + def alter_carefirst_npt_flag(change_request, policy) + reinstate_policy_m_id = change_request.subscriber_id + pols = Person.where(authority_member_id: reinstate_policy_m_id).first.policies + pols.each do |pol| + if change_request.type == 'add' && change_request.reason.text == 'initial_enrollment' && pol.term_for_np == true && term_or_cancel_carefirst_policy_exists?(pol, change_request) + pol.update_attributes!(term_for_np: false) + Observers::PolicyUpdated.notify(pol) + elsif change_request.cancel? && policy.aasm_state == 'submitted' && pol.versions.last.try(:term_for_np) == true && term_or_cancel_carefirst_policy_exists?(pol, change_request) + pol.update_attributes!(term_for_np: true) + Observers::PolicyUpdated.notify(pol) + elsif change_request.reinstate? && policy.aasm_state == 'canceled' && pol.term_for_np == true && term_or_cancel_carefirst_policy_exists?(pol, change_request) + pol.update_attributes!(term_for_np: false) + Observers::PolicyUpdated.notify(pol) + elsif change_request.terminate? && policy.aasm_state == 'terminated' && policy.term_for_np == true + policy.update_attributes!(term_for_np: false) + Observers::PolicyUpdated.notify(policy) + end + end + end + + def term_or_cancel_carefirst_policy_exists?(pol, change_request) + reinstate_policy_plan_id = change_request.plan_id + reinstate_policy_carrier_id = change_request.carrier_id + term_policy_end_date = change_request.begin_date - 1.day + term_en_ids = pol.enrollees.map(&:m_id).sort + reinstate_en_ids = change_request.affected_member_ids.sort + return false unless pol.employer_id == nil + return false unless (pol.aasm_state == "terminated" && pol.policy_end == term_policy_end_date) + return false unless pol.plan_id.to_s == reinstate_policy_plan_id + return false unless pol.carrier_id.to_s == reinstate_policy_carrier_id + return false unless term_en_ids.count == reinstate_en_ids.count + return false unless term_en_ids == reinstate_en_ids + true + end + + def alter_non_carefirst_npt_flag(change_request, policy) + if change_request.reinstate? && policy.term_for_np == true + policy.update_attributes!(term_for_np: false) + Observers::PolicyUpdated.notify(policy) + elsif change_request.cancel? && policy.aasm_state == 'resubmitted' + unless policy.versions.empty? + last_version_npt = policy.versions.last.term_for_np + policy.update_attributes!(term_for_np: last_version_npt) + end + elsif change_request.terminate? && policy.aasm_state == 'terminated' && policy.term_for_np == true + policy.update_attributes!(term_for_np: false) + Observers::PolicyUpdated.notify(policy) + end + end + def submit_cv(cv_kind, name, data) return if Rails.env.test? tag = (cv_kind.to_s.downcase == "maintenance") diff --git a/app/use_cases/end_coverage.rb b/app/use_cases/end_coverage.rb index 5ca3cdf37..1b92ea6f4 100644 --- a/app/use_cases/end_coverage.rb +++ b/app/use_cases/end_coverage.rb @@ -14,10 +14,9 @@ def execute(request) @policy = @policy_repo.find(request[:policy_id]) enrollees_not_already_canceled = @policy.enrollees.select { |e| !e.canceled? } - update_policy(affected_enrollee_ids) notify_if_qualifies(request, @policy) - + alter_npt_flag(request, @policy) action = @action_factory.create_for(request) action_request = { policy_id: @policy.id, @@ -199,6 +198,54 @@ def parse_coverage_end(requested_coverage_end) end end + def alter_npt_flag(request, policy) + begin + if policy.carrier.hbx_carrier_id == "116036" #hbx_carrier_id of CareFirst carrier + alter_carefirst_npt_flag(request, policy) + else + alter_non_carefirst_npt_flag(request, policy) + end + rescue Exception => e + puts e.to_s + puts "policy_id: #{policy.id}" + end + end + + def alter_carefirst_npt_flag(request, policy) + reinstate_policy_m_id = policy.subscriber.m_id + pols = Person.where(authority_member_id: reinstate_policy_m_id).first.policies + pols.each do |pol| + if request[:operation] == 'cancel' && policy.aasm_state == 'submitted' && pol.versions.last.try(:term_for_np) == true && term_or_cancel_carefirst_policy_exists?(pol, policy) + pol.update_attributes!(term_for_np: true) + Observers::PolicyUpdated.notify(pol) + end + end + end + + def term_or_cancel_carefirst_policy_exists?(pol, policy) + reinstate_policy_plan_id = policy.plan_id + reinstate_policy_carrier_id = policy.carrier_id + term_policy_end_date = policy.policy_start - 1.day + term_en_ids = pol.enrollees.map(&:m_id).sort + reinstate_en_ids = policy.enrollees.map(&:m_id).sort + return false unless pol.employer_id == nil + return false unless (pol.aasm_state == "terminated" && pol.policy_end == term_policy_end_date) + return false unless pol.plan_id.to_s == reinstate_policy_plan_id + return false unless pol.carrier_id.to_s == reinstate_policy_carrier_id + return false unless term_en_ids.count == reinstate_en_ids.count + return false unless term_en_ids == reinstate_en_ids + true + end + + def alter_non_carefirst_npt_flag(request, policy) + if request[:operation] == 'cancel' && policy.aasm_state == 'resubmitted' + unless policy.versions.empty? + last_version_npt = policy.versions.last.term_for_np + policy.update_attributes!(term_for_np: last_version_npt) + end + end + end + class PremiumCalcError < StandardError end diff --git a/app/views/people/_policy_detail.html.erb b/app/views/people/_policy_detail.html.erb index 17059cf48..bb583d094 100644 --- a/app/views/people/_policy_detail.html.erb +++ b/app/views/people/_policy_detail.html.erb @@ -74,7 +74,7 @@ <%= link_to "Cancel / Term", cancelterminate_policy_path(p), :class => "btn btn-inverse" %>

<% if show_1095A_document_button?(p) %> - <%= link_to "1095A Document", generate_tax_document_form_policy_path(p, {person_id: @person.id}), :class => "btn btn-primary" %> + <%= link_to "1095A Document ", generate_tax_document_form_policy_path(p, {person_id: @person.id}), :class => "btn btn-primary" %> <% end %> <% end %> diff --git a/app/views/policies/_change_npt_indicator.html.haml b/app/views/policies/_change_npt_indicator.html.haml new file mode 100644 index 000000000..e651357cc --- /dev/null +++ b/app/views/policies/_change_npt_indicator.html.haml @@ -0,0 +1,31 @@ +%ul.breadcrumb + NPT Indicator += form_for policy, url: change_npt_indicator_policy_path(policy.id) do |f| + .panel.panel-default + .panel-body + = f.hidden_field :id, value: policy.id + .row + .col-md-12 + .control-group.npt_indicator_radio + = f.radio_button :npt_indicator, true, onclick: "handleClick(this, #{policy.term_for_np});", checked: policy.term_for_np + = f.label true + = f.radio_button :npt_indicator, false, onclick: "handleClick(this, #{policy.term_for_np});", checked: (policy.term_for_np == false) + = f.label false + .row + .col-md-2 + .form_actions + = f.submit 'Submit', id: "npt_submit_button", class: 'btn btn-inverse', confirm: 'WARNING: This action will change the policy NPT Indicator value. Are you sure you want to continue?' + +:javascript + $(document).ready(function() { + $('#npt_submit_button').attr('disabled', true); + }); + var currentValue = 0; + function handleClick(myRadio, npt_value) { + if (npt_value.toString() == myRadio.value) { + $('#npt_submit_button').attr('disabled', true); + } + else{ + $('#npt_submit_button').attr('disabled', false); + } + } diff --git a/app/views/policies/cancelterminate.html.haml b/app/views/policies/cancelterminate.html.haml index 142038af8..4fcab2652 100644 --- a/app/views/policies/cancelterminate.html.haml +++ b/app/views/policies/cancelterminate.html.haml @@ -50,3 +50,6 @@ .col-md-2 = f.label "Transmit?" = f.check_box :transmit, checked: true + +- unless @policy.employer_id.present? || ["submitted", "resubmitted", "effectuated", "canceled"].include?(@policy.aasm_state) + = render 'policies/change_npt_indicator', policy: @policy diff --git a/app/views/policies/generate_tax_document.html.haml b/app/views/policies/generate_tax_document.html.haml index 7245baab7..42e4a4257 100644 --- a/app/views/policies/generate_tax_document.html.haml +++ b/app/views/policies/generate_tax_document.html.haml @@ -8,5 +8,6 @@ .control-group = link_to "Download PDF for review", download_tax_document_policy_path(@policy, {file_name: @file_name, person_id: @person.id}), target: "_blank"

- = link_to "Approve and Upload", upload_tax_document_to_S3_policy_path(@policy, {file_name: @file_name, person_id: @person.id}), :class => "btn btn-primary", :method=> :post - = link_to "Cancel", delete_local_generated_tax_document_policy_path(@policy, {file_name: @file_name, person_id: @person.id}), :class => "btn btn-inverse", :method=> :delete \ No newline at end of file + = link_to "Approve and Upload", upload_tax_document_to_S3_policy_path(@policy, {file_name: @file_name, person_id: @person.id}), :class => "btn btn-primary", :confirm => 'WARNING: This will create and mail the 1095A PDF Form to the Consumer (no IRS data sent). Do you wish to continue?', :method=> :post + = link_to "Cancel", delete_local_generated_tax_document_policy_path(@policy, {file_name: @file_name, person_id: @person.id}), :class => "btn btn-inverse", :method=> :delete + diff --git a/app/views/policies/generate_tax_document_form.html.haml b/app/views/policies/generate_tax_document_form.html.haml index bcdb6534e..15131d92f 100644 --- a/app/views/policies/generate_tax_document_form.html.haml +++ b/app/views/policies/generate_tax_document_form.html.haml @@ -1,5 +1,5 @@ %ul.breadcrumb - Generate 1095A Document for Policy: + Re-print and Mail ONLY of 1095A Document: Policy ID = @policy.id = form_tag generate_tax_document_policy_path(@policy, {person_id:@person.id}), :method => "post", :id => '1095A_generation_form', :onsubmit => "return validate_1095A_form()" do .panel.panel-default @@ -67,6 +67,16 @@ .form_actions = submit_tag 'Submit', class: 'btn btn-inverse' +- if show_1095A_document_button?(@policy) && @policy.coverage_year.first.year > 2017 + %ul.breadcrumb + Automated 1095A/H41 Trigger (to Consumer and IRS): + = @policy.id + .panel.panel-default + .panel-body + .row + .col-md-2 + = link_to "1095A/H41 Trigger", trigger_1095A_H41_policy_path(@policy, {person_id:@person.id}), :class => "btn btn-primary", confirm: 'WARNING: Submission will trigger generation of 1095A PDF Form to Consumer and H41 XML Report to IRS. Do you wish to continue?', :method=> :post + :javascript function validate_1095A_form() { var return_value = false; diff --git a/config/routes.rb b/config/routes.rb index d3f9030e0..cae7d2a4a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -103,8 +103,10 @@ member do get :cancelterminate post :transmit + put :change_npt_indicator get :generate_tax_document_form post :generate_tax_document + post :trigger_1095A_H41 get :download_tax_document post :upload_tax_document_to_S3 delete :delete_local_generated_tax_document diff --git a/spec/controllers/policies_controller_spec.rb b/spec/controllers/policies_controller_spec.rb index 93ceac181..20526c899 100644 --- a/spec/controllers/policies_controller_spec.rb +++ b/spec/controllers/policies_controller_spec.rb @@ -125,4 +125,121 @@ end end + describe "POST trigger_1095A_H41" do + context "success" do + before do + allow(Observers::PolicyUpdated).to receive(:notify).with(policy) + post :trigger_1095A_H41, {id: policy.id, person_id: person.id} + end + + it 'redirects to `person_path`' do + expect(response).to redirect_to(generate_tax_document_form_policy_path(policy.id, {person_id: person.id})) + expect(flash[:notice]).to match(/Triggered 1095A and H41 for policy_id/) + end + end + end + + describe "Change NPT indicator" do + + let(:mock_event_broadcaster) do + instance_double(Amqp::EventBroadcaster) + end + let(:submitted_by) {"example@example.com"} + + let(:plan) { FactoryGirl.create(:plan) } + let(:calender_year) { 2018 } + let(:coverage_start) { Date.new(calender_year, 1, 1) } + let(:coverage_end) { Date.new(calender_year, 6, 30) } + + let!(:primary) { + person = FactoryGirl.create :person, dob: Date.new(1970, 5, 1), name_first: "John", name_last: "Roberts" + person.update(authority_member_id: person.members.first.hbx_member_id) + person + } + + let!(:child) { + person = FactoryGirl.create :person, dob: Date.new(1998, 9, 6), name_first: "Adam", name_last: "Roberts" + person.update(authority_member_id: person.members.first.hbx_member_id) + person + } + + let!(:policy) { + policy = FactoryGirl.create :policy, plan_id: plan.id, coverage_start: coverage_start, coverage_end: coverage_end + policy.enrollees[0].m_id = primary.authority_member.hbx_member_id + policy.enrollees[1].m_id = child.authority_member.hbx_member_id + policy.enrollees[1].rel_code ='child'; policy.save + policy + } + + before do + allow(Observers::PolicyUpdated).to receive(:notify).with(policy) + allow(Amqp::EventBroadcaster).to receive(:with_broadcaster).and_yield(mock_event_broadcaster) + end + + context "Sending True NPT Indicator" do + + context "when aasm_state of a policy is in termination state" do + it "displays success message" do + policy.update_attributes!(aasm_state: "terminated") + allow(mock_event_broadcaster).to receive(:broadcast).with( + { + :routing_key => "info.events.policy.non_payment_indicator_altered", + :app_id => "gluedb", + :headers => { + "policy_id" => policy.id.to_s, + "eg_id" => policy.eg_id, + "old_npt" => false, + "new_npt" => true, + "submitted_by" => submitted_by + } + }, + policy.id.to_s + ) + + put :change_npt_indicator, {id: policy.id, person_id: primary.id, policy: {id: policy.id, npt_indicator: "true"}} + expect(response).to redirect_to(person_path(primary)) + expect(flash[:notice]).to match(/The NPT Indicator was successfully updated/) + end + + it "displays failure message when policy NPT indicator is already true" do + policy.update_attributes!(aasm_state: "terminated", term_for_np: true) + put :change_npt_indicator, {id: policy.id, person_id: primary.id, policy: {id: policy.id, npt_indicator: "true"}} + expect(flash[:error]).to match(/The NPT Indicator was unable to be updated with the new value selected./) + end + end + end + + context "Sending False NPT Indicator" do + + context "when aasm_state of a policy is in termination state" do + it "displays success message" do + policy.update_attributes!(aasm_state: "terminated", term_for_np: true) + allow(mock_event_broadcaster).to receive(:broadcast).with( + { + :routing_key => "info.events.policy.non_payment_indicator_altered", + :app_id => "gluedb", + :headers => { + "policy_id" => policy.id.to_s, + "eg_id" => policy.eg_id, + "old_npt" => true, + "new_npt" => false, + "submitted_by" => submitted_by + } + }, + policy.id.to_s + ) + put :change_npt_indicator, {id: policy.id, person_id: primary.id, policy: {id: policy.id, npt_indicator: "false"}} + expect(response).to redirect_to(person_path(primary)) + expect(flash[:notice]).to match(/The NPT Indicator was successfully updated/) + end + end + + context "when aasm_state of a policy is not in termination state" do + it "displays failure message" do + put :change_npt_indicator, {id: policy.id, person_id: primary.id, policy: {id: policy.id, npt_indicator: "false"}} + expect(flash[:error]).to match(/The NPT Indicator was unable to be updated with the new value selected./) + end + end + end + end end diff --git a/spec/features/payment_processor_upload/uploading_cancel_spec.rb b/spec/features/payment_processor_upload/uploading_cancel_spec.rb index 644cd8e05..fbb7d978a 100644 --- a/spec/features/payment_processor_upload/uploading_cancel_spec.rb +++ b/spec/features/payment_processor_upload/uploading_cancel_spec.rb @@ -58,7 +58,7 @@ end scenario 'subscriber member canceled' do - file_path = Rails.root + "spec/support/fixtures/cancel/subscriber_cancel.xml" + file_path = Rails.root + "spec/support/fixtures/cancel/carefirst_subscriber_cancel.xml" allow(Amqp::EventBroadcaster).to receive(:with_broadcaster).and_yield(mock_event_broadcaster) allow(mock_event_broadcaster).to receive(:broadcast).with( { diff --git a/spec/features/payment_processor_upload/uploading_individual_cv_spec.rb b/spec/features/payment_processor_upload/uploading_individual_cv_spec.rb index 55aa3b39b..5c6536f7e 100644 --- a/spec/features/payment_processor_upload/uploading_individual_cv_spec.rb +++ b/spec/features/payment_processor_upload/uploading_individual_cv_spec.rb @@ -27,7 +27,7 @@ end scenario 'IVL CV fails to upload successful' do - file_path = Rails.root + "spec/support/fixtures/individual_enrollment/correct.xml" + file_path = Rails.root + "spec/support/fixtures/individual_enrollment/carefirst_correct.xml" allow(Amqp::EventBroadcaster).to receive(:with_broadcaster).and_yield(mock_event_broadcaster) allow(mock_event_broadcaster).to receive(:broadcast).with( { diff --git a/spec/features/vocab_upload/uploading_cancel_spec.rb b/spec/features/vocab_upload/uploading_cancel_spec.rb index 8380b4c2f..225be27f0 100644 --- a/spec/features/vocab_upload/uploading_cancel_spec.rb +++ b/spec/features/vocab_upload/uploading_cancel_spec.rb @@ -5,10 +5,34 @@ instance_double(Amqp::EventBroadcaster) end + let!(:member) { FactoryGirl.build :member, hbx_member_id: '123456' } + let!(:person) { FactoryGirl.create :person, name_first: 'Example', name_last: 'Person', members: [ member ] } + let!(:policy1) { Policy.new(eg_id: '1', enrollees: [enrollee1], plan: plan, carrier: carrier, aasm_state: 'submitted' ) } + let!(:plan) { build(:plan, id: '5f77432ac09d079fd44c1ae9') } + let!(:carrier) {create(:carrier, id: '53e67210eb899a4603000004', hbx_carrier_id: '116036')} + let!(:enrollee1) do + Enrollee.new( + m_id: member.hbx_member_id, + benefit_status_code: 'active', + employment_status_code: 'active', + relationship_status_code: 'self', + coverage_start: Date.new(2020,4,1)) + end + let!(:enrollee2) do + Enrollee.new( + m_id: member.hbx_member_id, + benefit_status_code: 'active', + employment_status_code: 'terminated', + relationship_status_code: 'self', + coverage_start: Date.new(2020,1,1), + coverage_end: Date.new(2020,3,31)) + end + + let!(:policy) { Policy.new(eg_id: '7654321', enrollees: [enrollee2], plan: plan, carrier: carrier, employer_id: nil, aasm_state: "terminated", term_for_np: true ) } given(:premium) do PremiumTable.new( - rate_start_date: Date.new(2014, 1, 1), - rate_end_date: Date.new(2014, 12, 31), + rate_start_date: Date.new(2020, 1, 1), + rate_end_date: Date.new(2020, 12, 31), age: 53, amount: 398.24 ) @@ -21,9 +45,14 @@ sign_in_with(user.email, user.password) # Note: The file fixture is dependent on this record. - plan = Plan.new(coverage_type: 'health', hios_plan_id: '11111111111111-11', year: 2014, ehb: 0.5) + plan = Plan.new(coverage_type: 'health', hios_plan_id: '11111111111111-11', year: 2020, ehb: 0.5) plan.premium_tables << premium plan.save! + + person.update_attributes!(:authority_member_id => person.members.first.hbx_member_id) + policy.save! + policy1.save! + allow(Observers::PolicyUpdated).to receive(:notify).with(policy) end scenario 'nonsubscriber member canceled' do @@ -56,8 +85,39 @@ expect(page).to have_content 'Uploaded successfully.' end - scenario 'subscriber member canceled' do - file_path = Rails.root + "spec/support/fixtures/cancel/subscriber_cancel.xml" + scenario 'carefirst subscriber member canceled' do + file_path = Rails.root + "spec/support/fixtures/cancel/carefirst_subscriber_cancel.xml" + allow(Amqp::EventBroadcaster).to receive(:with_broadcaster).and_yield(mock_event_broadcaster) + allow(mock_event_broadcaster).to receive(:broadcast).with( + { + :routing_key => "info.events.legacy_enrollment_vocabulary.uploaded", + :app_id => "gluedb", + :headers => { + "file_name" => File.basename(file_path), + "kind" => 'initial_enrollment', + "submitted_by" => user.email, + "bypass_validation" => "false", + "redmine_ticket" => "1234" + } + }, + File.read(file_path) + ) + visit new_vocab_upload_path + + choose 'Initial Enrollment' + fill_in "vocab_upload[redmine_ticket]", with: "1234" + + attach_file('vocab_upload_vocab', file_path) + expect(policy1.term_for_np).to eq false + policy.update_attributes!(term_for_np: false) + click_button "Upload" + expect(policy.term_for_np).to eq false + expect(policy.versions.last.term_for_np).to eq true + expect(page).to have_content 'Uploaded successfully.' + end + + scenario 'non carefirst subscriber member canceled' do + file_path = Rails.root + "spec/support/fixtures/cancel/non_carefirst_subscriber_cancel.xml" allow(Amqp::EventBroadcaster).to receive(:with_broadcaster).and_yield(mock_event_broadcaster) allow(mock_event_broadcaster).to receive(:broadcast).with( { @@ -79,9 +139,12 @@ fill_in "vocab_upload[redmine_ticket]", with: "1234" attach_file('vocab_upload_vocab', file_path) - + policy.enrollees.first.update_attributes!(emp_stat: 'active', coverage_end: nil) + policy.update_attributes!(aasm_state: 'resubmitted', term_for_np: false) + expect(policy.term_for_np).to eq false click_button "Upload" - + policy.reload + expect(policy.term_for_np).to eq true expect(page).to have_content 'Uploaded successfully.' end diff --git a/spec/features/vocab_upload/uploading_individual_cv_spec.rb b/spec/features/vocab_upload/uploading_individual_cv_spec.rb index 126af052f..40bb5508b 100644 --- a/spec/features/vocab_upload/uploading_individual_cv_spec.rb +++ b/spec/features/vocab_upload/uploading_individual_cv_spec.rb @@ -5,10 +5,72 @@ instance_double(Amqp::EventBroadcaster) end + let!(:member) { FactoryGirl.build :member, hbx_member_id: '123456' } + let!(:child_member) { FactoryGirl.build :member, hbx_member_id: '789012' } + let!(:person) { FactoryGirl.create :person, name_first: 'Example', name_last: 'Person', members: [ member ] } + let!(:policy1) { Policy.new(eg_id: '1', enrollees: [enrollee1, child_enrollee1], plan: plan, carrier: carrier ) } + let!(:policy2) { Policy.new(eg_id: '2', enrollees: [enrollee2, child_enrollee2], plan: plan, carrier: carrier, employer_id: nil, aasm_state: "terminated", term_for_np: true ) } + let!(:plan) { build(:plan, id: '5f77432ac09d079fd44c1ae9') } + let!(:carrier) {create(:carrier, id: '53e67210eb899a4603000004', hbx_carrier_id: '116036')} + let!(:enrollee1) do + Enrollee.new( + m_id: member.hbx_member_id, + benefit_status_code: 'active', + employment_status_code: 'active', + relationship_status_code: 'self', + coverage_start: Date.new(2020,4,1)) + end + let!(:child_enrollee1) do + Enrollee.new( + m_id: child_member.hbx_member_id, + benefit_status_code: 'active', + employment_status_code: 'active', + relationship_status_code: 'child', + coverage_start: Date.new(2020,4,1)) + end + let!(:enrollee2) do + Enrollee.new( + m_id: member.hbx_member_id, + benefit_status_code: 'active', + employment_status_code: 'terminated', + relationship_status_code: 'self', + coverage_start: Date.new(2020,1,1), + coverage_end: Date.new(2020,3,31)) + end + let!(:child_enrollee2) do + Enrollee.new( + m_id: child_member.hbx_member_id, + benefit_status_code: 'active', + employment_status_code: 'terminated', + relationship_status_code: 'child', + coverage_start: Date.new(2020,1,1), + coverage_end: Date.new(2020,3,31)) + end + let!(:enrollee3) do + Enrollee.new( + m_id: member.hbx_member_id, + benefit_status_code: 'active', + employment_status_code: 'terminated', + relationship_status_code: 'self', + coverage_start: Date.new(2020,4,1), + coverage_end: Date.new(2020,4,1)) + end + + let!(:child_enrollee3) do + Enrollee.new( + m_id: child_member.hbx_member_id, + benefit_status_code: 'active', + employment_status_code: 'terminated', + relationship_status_code: 'child', + coverage_start: Date.new(2020,4,1), + coverage_end: Date.new(2020,4,1)) + end + let!(:policy3) { Policy.new(eg_id: '740893', enrollees: [enrollee3, child_enrollee3], plan: plan, carrier: carrier, employer_id: nil, aasm_state: "canceled") } + let!(:policy) { FactoryGirl.create(:policy, eg_id: '7654321', employer_id: nil, aasm_state: "terminated", term_for_np: true ) } given(:premium) do PremiumTable.new( - rate_start_date: Date.new(2014, 1, 1), - rate_end_date: Date.new(2014, 12, 31), + rate_start_date: Date.new(2020, 1, 1), + rate_end_date: Date.new(2020, 12, 31), age: 53, amount: 398.24 ) @@ -21,13 +83,20 @@ sign_in_with(user.email, user.password) # Note: The file fixture is dependent on this record. - plan = Plan.new(coverage_type: 'health', hios_plan_id: '11111111111111-11', year: 2014, ehb: 0.5) + plan = Plan.new(coverage_type: 'health', hios_plan_id: '11111111111111-11', year: 2020, ehb: 0.5) plan.premium_tables << premium plan.save! + + person.update_attributes!(:authority_member_id => person.members.first.hbx_member_id) + policy1.save! + policy2.save! + policy3.save! + allow(Observers::PolicyUpdated).to receive(:notify).with(policy2) + allow(Observers::PolicyUpdated).to receive(:notify).with(policy) end - scenario 'a successful upload' do - file_path = Rails.root + "spec/support/fixtures/individual_enrollment/correct.xml" + scenario 'A carefirst reinstate CV successful upload' do + file_path = Rails.root + "spec/support/fixtures/individual_enrollment/carefirst_correct.xml" allow(Amqp::EventBroadcaster).to receive(:with_broadcaster).and_yield(mock_event_broadcaster) allow(mock_event_broadcaster).to receive(:broadcast).with( { @@ -49,9 +118,138 @@ fill_in "vocab_upload[redmine_ticket]", with: "1234" attach_file('vocab_upload_vocab', file_path) + terminated_policy = Policy.where(eg_id: '2').first + expect(terminated_policy.term_for_np).to eq true + click_button "Upload" + terminated_policy.reload + expect(terminated_policy.term_for_np).to eq false + expect(page).to have_content 'Uploaded successfully.' + end + scenario 'A non carefirst reinstate CV successful upload' do + file_path = Rails.root + "spec/support/fixtures/individual_enrollment/non_carefirst_correct.xml" + allow(Amqp::EventBroadcaster).to receive(:with_broadcaster).and_yield(mock_event_broadcaster) + allow(mock_event_broadcaster).to receive(:broadcast).with( + { + :routing_key => "info.events.legacy_enrollment_vocabulary.uploaded", + :app_id => "gluedb", + :headers => { + "file_name" => File.basename(file_path), + "kind" => 'maintenance', + "submitted_by" => user.email, + "bypass_validation" => "false", + "redmine_ticket" => "1234" + } + }, + File.read(file_path) + ) + visit new_vocab_upload_path + + choose 'Maintenance' + fill_in "vocab_upload[redmine_ticket]", with: "1234" + + attach_file('vocab_upload_vocab', file_path) + + expect(policy.term_for_np).to eq true click_button "Upload" + policy.reload + expect(policy.term_for_np).to eq false + expect(page).to have_content 'Uploaded successfully.' + end + scenario 'A carefirst reinstated canceled CV successful upload' do + file_path = Rails.root + "spec/support/fixtures/individual_enrollment/carefirst_reinstate.xml" + allow(Amqp::EventBroadcaster).to receive(:with_broadcaster).and_yield(mock_event_broadcaster) + allow(mock_event_broadcaster).to receive(:broadcast).with( + { + :routing_key => "info.events.legacy_enrollment_vocabulary.uploaded", + :app_id => "gluedb", + :headers => { + "file_name" => File.basename(file_path), + "kind" => 'initial_enrollment', + "submitted_by" => user.email, + "bypass_validation" => "false", + "redmine_ticket" => "1234" + } + }, + File.read(file_path) + ) + visit new_vocab_upload_path + + choose 'Initial Enrollment' + fill_in "vocab_upload[redmine_ticket]", with: "1234" + + attach_file('vocab_upload_vocab', file_path) + canceled_policy = Policy.where(eg_id: '740893').first + terminated_policy = Policy.where(eg_id: '2').first + expect(terminated_policy.term_for_np).to eq true + expect(terminated_policy.aasm_state).to eq "terminated" + expect(canceled_policy.term_for_np).to eq false + expect(canceled_policy.aasm_state).to eq "canceled" + click_button "Upload" + terminated_policy.reload + expect(terminated_policy.term_for_np).to eq false + expect(page).to have_content 'Uploaded successfully.' + end + + scenario 'A carefirst termination CV successful upload' do + file_path = Rails.root + "spec/support/fixtures/individual_enrollment/term_carefirst_correct.xml" + allow(Amqp::EventBroadcaster).to receive(:with_broadcaster).and_yield(mock_event_broadcaster) + allow(mock_event_broadcaster).to receive(:broadcast).with( + { + :routing_key => "info.events.legacy_enrollment_vocabulary.uploaded", + :app_id => "gluedb", + :headers => { + "file_name" => File.basename(file_path), + "kind" => 'maintenance', + "submitted_by" => user.email, + "bypass_validation" => "false", + "redmine_ticket" => "1234" + } + }, + File.read(file_path) + ) + visit new_vocab_upload_path + + choose 'Maintenance' + fill_in "vocab_upload[redmine_ticket]", with: "1234" + attach_file('vocab_upload_vocab', file_path) + terminated_policy = Policy.where(eg_id: '2').first + expect(terminated_policy.term_for_np).to eq true + click_button "Upload" + terminated_policy.reload + expect(terminated_policy.term_for_np).to eq false + expect(page).to have_content 'Uploaded successfully.' + end + + scenario 'A non carefirst termination CV successful upload' do + file_path = Rails.root + "spec/support/fixtures/individual_enrollment/term_non_carefirst_correct.xml" + allow(Amqp::EventBroadcaster).to receive(:with_broadcaster).and_yield(mock_event_broadcaster) + allow(mock_event_broadcaster).to receive(:broadcast).with( + { + :routing_key => "info.events.legacy_enrollment_vocabulary.uploaded", + :app_id => "gluedb", + :headers => { + "file_name" => File.basename(file_path), + "kind" => 'maintenance', + "submitted_by" => user.email, + "bypass_validation" => "false", + "redmine_ticket" => "1234" + } + }, + File.read(file_path) + ) + visit new_vocab_upload_path + + choose 'Maintenance' + fill_in "vocab_upload[redmine_ticket]", with: "1234" + + attach_file('vocab_upload_vocab', file_path) + + expect(policy.term_for_np).to eq true + click_button "Upload" + policy.reload + expect(policy.term_for_np).to eq false expect(page).to have_content 'Uploaded successfully.' end diff --git a/spec/helpers/policies_helper_spec.rb b/spec/helpers/policies_helper_spec.rb index cc9cb9df9..497331c4b 100644 --- a/spec/helpers/policies_helper_spec.rb +++ b/spec/helpers/policies_helper_spec.rb @@ -2,28 +2,148 @@ RSpec.describe PoliciesHelper, :type => :helper do - describe "show_1095A_document_button?" do - let(:policy) { FactoryGirl.create(:policy) } + describe "is_is_policy_not_eligible_to_notify?" do - context "current year policy" do - let(:subscriber) { FactoryGirl.build(:enrollee, :coverage_start => Date.new(Date.today.year,01,01)) } - before do - allow(policy).to receive(:subscriber).and_return(subscriber) + let(:today) { Time.now } + let(:current_year) { ((today.beginning_of_year)..today.end_of_year) } + let(:future_year) { ((today.beginning_of_year + 1.year)..(today.end_of_year + 1.year)) } + let(:coverage_year_first) { (Time.mktime(2018, 1, 1)..Time.mktime(2018, 12, 31) )} + let(:coverage_year_too_old) { (Time.mktime(2017, 1, 1)..Time.mktime(2017, 12, 31) )} + let(:plan) { build(:plan, metal_level: "platinum")} + + context "given a shop policy" do + let(:policy) do + instance_double( + Policy, + is_shop?: true, + kind: 'employer_sponsored' + ) end - it "returns false" do - expect(helper.show_1095A_document_button?(policy)).to be_falsey + it "returns true" do + expect(helper.is_policy_not_eligible_to_notify?(policy)).to be_truthy + end + end + + context 'given a coverall kind policy' do + let(:policy) do + instance_double( + Policy, + is_shop?: false, + kind: 'coverall' + ) + end + + it "returns true" do + expect(helper.is_policy_not_eligible_to_notify?(policy)).to be_truthy + end + end + + context 'given a health policy with catastrophic plan' do + let(:policy_id) { "A POLICY ID" } + let(:eg_id) { "A POLICY ID" } + let(:policy) do + instance_double( + Policy, + :id => policy_id, + :eg_id => eg_id, + is_shop?: false, + kind: 'individual', + plan: plan + ) + end + let(:plan) { build(:plan, metal_level: "catastrophic")} + + it "returns true" do + expect(helper.is_policy_not_eligible_to_notify?(policy)).to be_truthy + end + end + + context "given a dental policy" do + let(:policy) do + instance_double( + Policy, + is_shop?: true, + coverage_type: "dental", + kind: 'employer_sponsored' + ) + end + + it "returns true" do + expect(helper.is_policy_not_eligible_to_notify?(policy)).to be_truthy end end - context "previous year policy" do - let(:subscriber) { FactoryGirl.build(:enrollee, :coverage_start => Date.new(Date.today.year - 1 ,01,01)) } - before do - allow(policy).to receive(:subscriber).and_return(subscriber) + context "given an ivl policy from the current year" do + let(:policy) do + instance_double( + Policy, + is_shop?: false, + kind: 'individual', + coverage_year: current_year, + coverage_type: "health", + plan: plan + ) + end + + it "returns true" do + expect(helper.is_policy_not_eligible_to_notify?(policy)).to be_truthy + end + end + + context "given an ivl policy from the future year" do + let(:policy) do + instance_double( + Policy, + is_shop?: false, + kind: 'individual', + coverage_year: future_year, + coverage_type: "health", + plan: plan + ) + end + + it "returns true" do + expect(helper.is_policy_not_eligible_to_notify?(policy)).to be_truthy + end + end + + context "given an ivl policy from before 2018" do + let(:policy) do + instance_double( + Policy, + is_shop?: false, + kind: 'individual', + coverage_year: coverage_year_too_old, + coverage_type: "health", + plan: plan + ) end it "returns false" do - expect(helper.show_1095A_document_button?(policy)).to be_truthy + expect(helper.is_policy_not_eligible_to_notify?(policy)).to be_falsey + end + end + + context "given an ivl policy from a previous policy year, after 1/1/2018" do + let(:policy_id) { "A POLICY ID" } + let(:eg_id) { "A POLICY ID" } + + let(:policy) do + instance_double( + Policy, + :id => policy_id, + :eg_id => eg_id, + is_shop?: false, + kind: 'individual', + coverage_year: coverage_year_first, + coverage_type: "health", + plan: plan + ) + end + + it "return false" do + expect(helper.is_policy_not_eligible_to_notify?(policy)).to be_falsey end end end diff --git a/spec/models/policy_spec.rb b/spec/models/policy_spec.rb index c2874a0af..849f81be8 100644 --- a/spec/models/policy_spec.rb +++ b/spec/models/policy_spec.rb @@ -908,3 +908,101 @@ end end end + +describe ".change_npt_indicator", :dbclean => :after_each do + let(:submitted_by) {"admin@dc.gov"} + let(:coverage_start) { Date.new(2014, 1, 1) } + let(:enrollee) { build(:subscriber_enrollee, coverage_start: coverage_start) } + let(:policy1) { build(:policy, enrollees: [ enrollee ], term_for_np: true) } + let(:policy2) { build(:policy, enrollees: [ enrollee ], term_for_np: false) } + let(:policy3) { FactoryGirl.create(:policy, term_for_np: false, aasm_state: 'submitted') } + let(:true_npt) {"true"} + let(:false_npt) {"false"} + let(:mock_event_broadcaster) do + instance_double(Amqp::EventBroadcaster) + end + before { policy1.save! } + before {policy2.save!} + + before :each do + allow(Observers::PolicyUpdated).to receive(:notify).with(policy1) + allow(Amqp::EventBroadcaster).to receive(:with_broadcaster).and_yield(mock_event_broadcaster) + end + + context 'when policy term_for_np value is changing to true' do + context 'when policy is in terminated state' do + it 'return false when policy term_for_np is already true' do + allow(Observers::PolicyUpdated).to receive(:notify).with(policy1) + npt_value = policy1.change_npt_indicator(policy1, true_npt, submitted_by) + expect(policy1.aasm_state).to eq "terminated" + expect(npt_value).to eq false + end + + it 'return true' do + old_npt = policy2.term_for_np + allow(Observers::PolicyUpdated).to receive(:notify).with(policy2) + allow(mock_event_broadcaster).to receive(:broadcast).with( + { + :routing_key => "info.events.policy.non_payment_indicator_altered", + :app_id => "gluedb", + :headers => { + "policy_id" => policy2.id.to_s, + "eg_id" => policy2.eg_id, + "old_npt" => old_npt, + "new_npt" => true, + "submitted_by" => submitted_by + } + }, + policy2.id.to_s + ) + npt_value = policy2.change_npt_indicator(policy2, true_npt, submitted_by) + expect(policy2.aasm_state).to eq "terminated" + expect(npt_value).to eq true + end + end + + context 'when policy is in submitted state' do + it 'return false' do + allow(Observers::PolicyUpdated).to receive(:notify).with(policy3) + npt_value = policy3.change_npt_indicator(policy3, true_npt, submitted_by) + expect(policy3.aasm_state).to eq "submitted" + expect(npt_value).to eq false + end + end + end + + context 'when policy term_for_np value is changing to false' do + context 'when policy is in terminated state' do + it 'return true' do + old_npt = policy1.term_for_np + allow(Observers::PolicyUpdated).to receive(:notify).with(policy1) + allow(mock_event_broadcaster).to receive(:broadcast).with( + { + :routing_key => "info.events.policy.non_payment_indicator_altered", + :app_id => "gluedb", + :headers => { + "policy_id" => policy1.id.to_s, + "eg_id" => policy1.eg_id, + "old_npt" => old_npt, + "new_npt" => false, + "submitted_by" => submitted_by + } + }, + policy1.id.to_s + ) + npt_value = policy1.change_npt_indicator(policy1, false_npt, submitted_by) + expect(policy1.aasm_state).to eq "terminated" + expect(npt_value).to eq true + end + end + + context 'when policy is in submitted state' do + it 'return false when policy term_for_np is already false' do + allow(Observers::PolicyUpdated).to receive(:notify).with(policy3) + npt_value = policy3.change_npt_indicator(policy3, false_npt, submitted_by) + expect(policy3.aasm_state).to eq "submitted" + expect(npt_value).to eq false + end + end + end +end diff --git a/spec/support/fixtures/cancel/subscriber_cancel.xml b/spec/support/fixtures/cancel/carefirst_subscriber_cancel.xml similarity index 79% rename from spec/support/fixtures/cancel/subscriber_cancel.xml rename to spec/support/fixtures/cancel/carefirst_subscriber_cancel.xml index 52889bf0d..96152bd65 100644 --- a/spec/support/fixtures/cancel/subscriber_cancel.xml +++ b/spec/support/fixtures/cancel/carefirst_subscriber_cancel.xml @@ -4,23 +4,24 @@ cancel termination_of_benefits - 1111111 + 123456 + 1 Example Person - 1111111 + 123456 Self 19610101 398.24 - 20140701 + 20200401 @@ -36,10 +37,20 @@ 20140701 + + + GHMSI_IND + CareFirst + 116036 + + 53e67210eb899a4603000004 + + 53e67210eb899a4603000004 11111111111111-11 + 5f77432ac09d079fd44c1ae9 796.48 62.0 734.48 diff --git a/spec/support/fixtures/cancel/incorrect_premium_total.xml b/spec/support/fixtures/cancel/incorrect_premium_total.xml index be1953a4a..45b3bd039 100644 --- a/spec/support/fixtures/cancel/incorrect_premium_total.xml +++ b/spec/support/fixtures/cancel/incorrect_premium_total.xml @@ -20,7 +20,7 @@ 19610101 398.24 - 20140701 + 20200701 diff --git a/spec/support/fixtures/cancel/non_carefirst_subscriber_cancel.xml b/spec/support/fixtures/cancel/non_carefirst_subscriber_cancel.xml new file mode 100644 index 000000000..cef7c010d --- /dev/null +++ b/spec/support/fixtures/cancel/non_carefirst_subscriber_cancel.xml @@ -0,0 +1,60 @@ + + + + cancel + termination_of_benefits + + 123456 + + + + + + 7654321 + + + Example + Person + + 123456 + Self + 19610101 + + 398.24 + 20200701 + + + + + Example + Person + + 2222222 + Child + 19610101 + + 398.24 + 20140701 + + + + + KFMASI_IND + Kaiser + 116028 + + 53e67210eb899a460300000d + + + + 53e67210eb899a460300000d + 11111111111111-11 + + 5da63bd3c09d07292270fb10 + 796.48 + 62.0 + 734.48 + + + + diff --git a/spec/support/fixtures/cancel/nonsubscriber_cancel.xml b/spec/support/fixtures/cancel/nonsubscriber_cancel.xml index 552234902..689f587ac 100644 --- a/spec/support/fixtures/cancel/nonsubscriber_cancel.xml +++ b/spec/support/fixtures/cancel/nonsubscriber_cancel.xml @@ -10,6 +10,7 @@ + 7654321 Example @@ -20,7 +21,7 @@ 19610101 398.24 - 20140701 + 20200701 @@ -33,13 +34,23 @@ 19610101 398.24 - 20140701 + 20200701 + + + KFMASI_IND + Kaiser + 116028 + + 53e67210eb899a460300000d + + 53e67210eb899a460300000d 11111111111111-11 + 5da63bd3c09d07292270fb10 398.24 62.0 336.24 diff --git a/spec/support/fixtures/individual_enrollment/correct.xml b/spec/support/fixtures/individual_enrollment/carefirst_correct.xml similarity index 70% rename from spec/support/fixtures/individual_enrollment/correct.xml rename to spec/support/fixtures/individual_enrollment/carefirst_correct.xml index b37d03cea..b439da0bb 100755 --- a/spec/support/fixtures/individual_enrollment/correct.xml +++ b/spec/support/fixtures/individual_enrollment/carefirst_correct.xml @@ -2,25 +2,42 @@ add + initial_enrollment + + 123456 + 789012 + + 1 Example Person + 123456 Self 19610101 398.24 - 20140701 + 20200401 + + + GHMSI_IND + CareFirst + 116036 + + 53e67210eb899a4603000004 + + 53e67210eb899a4603000004 11111111111111-11 + 5f77432ac09d079fd44c1ae9 398.24 62.0 336.24 diff --git a/spec/support/fixtures/individual_enrollment/carefirst_reinstate.xml b/spec/support/fixtures/individual_enrollment/carefirst_reinstate.xml new file mode 100644 index 000000000..03aeb0df7 --- /dev/null +++ b/spec/support/fixtures/individual_enrollment/carefirst_reinstate.xml @@ -0,0 +1,47 @@ + + + + reinstate + reenrollment + + 123456 + 789012 + + + + + 740893 + + + Example + Person + + 123456 + Self + 19610101 + + 398.24 + 20200401 + + + + + GHMSI_IND + CareFirst + 116036 + + 53e67210eb899a4603000004 + + + + 53e67210eb899a4603000004 + 11111111111111-11 + + 5f77432ac09d079fd44c1ae9 + 398.24 + 62.0 + 336.24 + + + + diff --git a/spec/support/fixtures/individual_enrollment/non_carefirst_correct.xml b/spec/support/fixtures/individual_enrollment/non_carefirst_correct.xml new file mode 100644 index 000000000..33bd5b824 --- /dev/null +++ b/spec/support/fixtures/individual_enrollment/non_carefirst_correct.xml @@ -0,0 +1,46 @@ + + + + reinstate + reenrollment + + 123456 + + + + + 7654321 + + + Example + Person + + 5 + Self + 19610101 + + 398.24 + 20200701 + + + + + KFMASI_IND + Kaiser + 116028 + + 53e67210eb899a460300000d + + + + 53e67210eb899a460300000d + 11111111111111-11 + + 5da63bd3c09d07292270fb10 + 398.24 + 62.0 + 336.24 + + + + diff --git a/spec/support/fixtures/individual_enrollment/term_carefirst_correct.xml b/spec/support/fixtures/individual_enrollment/term_carefirst_correct.xml new file mode 100644 index 000000000..b4232a9b8 --- /dev/null +++ b/spec/support/fixtures/individual_enrollment/term_carefirst_correct.xml @@ -0,0 +1,46 @@ + + + + terminate + termination_of_benefits + + 123456 + + + + + 2 + + + Example + Person + + 123456 + Self + 19610101 + + 398.24 + 20200401 + + + + + GHMSI_IND + CareFirst + 116036 + + 53e67210eb899a4603000004 + + + + 53e67210eb899a4603000004 + 11111111111111-11 + + 5f77432ac09d079fd44c1ae9 + 398.24 + 62.0 + 336.24 + + + + diff --git a/spec/support/fixtures/individual_enrollment/term_non_carefirst_correct.xml b/spec/support/fixtures/individual_enrollment/term_non_carefirst_correct.xml new file mode 100644 index 000000000..7b3af140b --- /dev/null +++ b/spec/support/fixtures/individual_enrollment/term_non_carefirst_correct.xml @@ -0,0 +1,46 @@ + + + + terminate + termination_of_benefits + + 123456 + + + + + 7654321 + + + Example + Person + + 5 + Self + 19610101 + + 398.24 + 20200701 + + + + + KFMASI_IND + Kaiser + 116028 + + 53e67210eb899a460300000d + + + + 53e67210eb899a460300000d + 11111111111111-11 + + 5da63bd3c09d07292270fb10 + 398.24 + 62.0 + 336.24 + + + + diff --git a/spec/use_cases/end_coverage_spec.rb b/spec/use_cases/end_coverage_spec.rb index 644eb23ba..56de8a11c 100644 --- a/spec/use_cases/end_coverage_spec.rb +++ b/spec/use_cases/end_coverage_spec.rb @@ -31,7 +31,8 @@ let(:operation) { 'terminate' } let(:current_user) { 'joe.kramer@dc.gov' } let(:policy_repo) { double(find: policy) } - let(:policy) { Policy.create!(eg_id: '1', enrollees: enrollees, pre_amt_tot: premium_total, plan_id: "1", plan: plan) } + let(:policy) { Policy.create!(eg_id: '1', enrollees: enrollees, pre_amt_tot: premium_total, plan_id: "1", plan: plan, carrier: carrier) } + let!(:carrier) {create(:carrier, hbx_carrier_id: '116000')} let(:plan) { Plan.create!(coverage_type: 'health', year: 2015, premium_tables: premium_tables) } let(:premium_tables) { [premium_table_for_subscriber, premium_table_for_member, premium_table_for_inactive_member]} let(:premium_total) { 300.00 } @@ -62,7 +63,6 @@ allow(Observers::PolicyUpdated).to receive(:notify).with(policy) end - shared_examples_for "coverage ended with correct responsible amount" do describe "when a shop enrollment" do let(:employer) { double(name: "Fakery", fein: 000000000, plan_years: [plan_year], __bson_dump__: nil) }