Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dc 201 shr #119

Open
wants to merge 21 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
eed014b
92522: added NPT Term Maintenance Reason Control UI and logging the t…
nks2109 Feb 24, 2021
9725bce
92522: addressed all review comments
nks2109 Mar 8, 2021
2fe2ae0
92660: success and failure message information has been changed
nks2109 Mar 19, 2021
023fda8
93400: added a warning message on clicking approval and upload button
nks2109 Mar 26, 2021
5ed7e8a
93401# Added 1095A/H41 Trigger function section to the existing 1095A…
nks2109 Mar 29, 2021
b3c9951
93402: Corrected the display of the 1095A Document button on policies
nks2109 Mar 31, 2021
06e646b
93402: '1095A Document' button will be available on all prior plan year
nks2109 Apr 2, 2021
a4c6d7f
92527: Reinstating a policy via CV upload and changing the NPT indica…
nks2109 Apr 12, 2021
ccd974a
93396: Canceling a reinstate policy via cv upload and restoring npt flag
nks2109 Apr 14, 2021
964c9dd
93397: Termination via CV to change npt indicator
nks2109 Apr 14, 2021
a236f21
93397: removed unused local variable
nks2109 May 26, 2021
0b845cc
92520: verified enrollees count for reinstate transaction
nks2109 May 27, 2021
14f1a50
92661: modification on NPT indicator control
nks2109 Jun 18, 2021
3a86c7e
93401: updated the language of the 1095 page document headings
nks2109 Jun 21, 2021
0138900
93401: updated the language of the 1095 page document headings
nks2109 Jun 21, 2021
84f386b
92520: cancelling a reinstated CF carrier need to check the NPT indic…
nks2109 Jun 29, 2021
425e7d6
95624: CF Reinstate Cancelled
nks2109 Jun 29, 2021
f904556
92661: modification on NPT indicator control
nks2109 Jun 30, 2021
3cbcd3a
93401: updated the language of the 1095 page document headings
nks2109 Jul 12, 2021
5f7ecc4
96089: NPT indicator not reset when reinstated policy cancelled via b…
nks2109 Aug 24, 2021
575b605
remove conflicts
saipraveen18 Aug 22, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions app/controllers/policies_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down
10 changes: 5 additions & 5 deletions app/helpers/policies_helper.rb
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
4 changes: 4 additions & 0 deletions app/models/cancel_terminate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down
30 changes: 23 additions & 7 deletions app/models/parsers/xml/enrollment/change_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
22 changes: 22 additions & 0 deletions app/models/parsers/xml/enrollment/individual_change_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
5 changes: 3 additions & 2 deletions app/models/parsers/xml/enrollment/namespaces.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
end
40 changes: 40 additions & 0 deletions app/models/policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
77 changes: 71 additions & 6 deletions app/models/vocab_upload.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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")
Expand Down
51 changes: 49 additions & 2 deletions app/use_cases/end_coverage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion app/views/people/_policy_detail.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
<%= link_to "Cancel / Term", cancelterminate_policy_path(p), :class => "btn btn-inverse" %>
<p></p>
<% 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 %>
</div>
<% end %>
Expand Down
Loading