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) }