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

FYST-791 ID health insurance premium subtraction #4930

Merged
merged 15 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module StateFile
module Questions
class IdHealthInsurancePremiumController < QuestionsController
include ReturnToReviewConcern
end
end
end
21 changes: 21 additions & 0 deletions app/forms/state_file/id_health_insurance_premium_form.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module StateFile
class IdHealthInsurancePremiumForm < QuestionsForm
set_attributes_for :intake, :has_health_insurance_premium, :health_insurance_paid_amount

validates :has_health_insurance_premium, inclusion: { in: %w[yes no], message: :blank }
validates :health_insurance_paid_amount,
presence: true,
numericality: {
allow_blank: true,
greater_than_or_equal_to: 0,
Copy link
Contributor Author

@arinchoi03 arinchoi03 Oct 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

open question whether we should allow 0 value for this amount, but should be ok to review while I wait on answer from product

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok to allow 0 here!

1- it’s possible that the filer may think that they paid Health Insurance Premiums when they initially respond to the question…..but as they more carefully review all of the supporting text in the reveals describing which Health Insurance payments actually qualify for this subtraction they may realize that the Health Insurance Premium payments that they made don’t actually qualify. So allowing them to enter 0 (and filling the PDF field and updating the state XML field with it) is the behavior that we are looking for here.

https://codeforamerica.atlassian.net/browse/FYST-791?focusedCommentId=12716

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if they answer no for health insurance premium question, should we still be adding 0 for the xml and pdf?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ooh i'll ask this

message: I18n.t("validators.not_a_number")
},
if: -> { has_health_insurance_premium == "yes" }

def save
attributes_to_save = attributes_for(:intake)
attributes_to_save[:health_insurance_paid_amount] = nil if has_health_insurance_premium == "no"
@intake.update!(attributes_to_save)
end
end
end
5 changes: 5 additions & 0 deletions app/lib/efile/id/id39_r_calculator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def initialize(value_access_tracker:, lines:, intake:)

def calculate
set_line(:ID39R_B_LINE_3, :calculate_sec_b_line_3)
set_line(:ID39R_B_LINE_18, :calculate_sec_b_line_18)
@lines.transform_values(&:value)
end

Expand All @@ -25,6 +26,10 @@ def calculate_sec_b_line_3
end
sum.round
end

def calculate_sec_b_line_18
@intake.has_health_insurance_premium_yes? ? @intake.health_insurance_paid_amount&.round : 0
end
end
end
end
2 changes: 2 additions & 0 deletions app/lib/efile/line_data.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ NYC_EIC_RATE_WK_LINE_6:
label: 'Subtract line 4 from line 5 or enter the decimal from the NYC EIC rate table. Also enter on Worksheet C, line 2.'
ID39R_B_LINE_3:
label: 'Interest from U.S. government obligations'
ID39R_B_LINE_18:
label: 'Health insurance premium paid amount for household'
ID40_LINE_6A:
label: '6a Count primary filer as part of household count when primary filer not claimed as dependent'
ID40_LINE_6B:
Expand Down
1 change: 1 addition & 0 deletions app/lib/navigation/state_file_id_question_navigation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class StateFileIdQuestionNavigation < Navigation::StateFileBaseQuestionNavigatio
Navigation::NavigationStep.new(StateFile::Questions::DataTransferOffboardingController, false),
Navigation::NavigationStep.new(StateFile::Questions::IncomeReviewController),
Navigation::NavigationStep.new(StateFile::Questions::UnemploymentController),
Navigation::NavigationStep.new(StateFile::Questions::IdHealthInsurancePremiumController),
Navigation::NavigationStep.new(StateFile::Questions::IdSalesUseTaxController),
Navigation::NavigationStep.new(StateFile::Questions::PrimaryStateIdController),
Navigation::NavigationStep.new(StateFile::Questions::SpouseStateIdController),
Expand Down
3 changes: 2 additions & 1 deletion app/lib/pdf_filler/id39r_pdf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ def initialize(submission)

def hash_for_pdf
answers = {
"BL3" => @xml_document.at('IncomeUSObligations')&.text
"BL3" => @xml_document.at('IncomeUSObligations')&.text,
"BL18" => @xml_document.at('HealthInsurancePaid')&.text,
}
@submission.data_source.dependents.drop(4).first(3).each_with_index do |dependent, index|
answers.merge!(
Expand Down
Binary file modified app/lib/pdfs/idform39r-TY2023.pdf
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class Id39R < SubmissionBuilder::Document
def document
build_xml_doc("Form39R") do |xml|
xml.IncomeUSObligations calculated_fields.fetch(:ID39R_B_LINE_3)
xml.HealthInsurancePaid calculated_fields.fetch(:ID39R_B_LINE_18)
end
end

Expand Down
4 changes: 4 additions & 0 deletions app/models/state_file_base_intake.rb
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,10 @@ def filer_count
filing_status_mfj? ? 2 : 1
end

def household_count
filer_count + dependents.size
end
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mike is implementing this on another PR but don't know who will get to merge it first


def primary
Person.new(self, :primary)
end
Expand Down
3 changes: 3 additions & 0 deletions app/models/state_file_id_intake.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
# email_address_verified_at :datetime
# failed_attempts :integer default(0), not null
# federal_return_status :string
# has_health_insurance_premium :integer default("unfilled"), not null
# has_unpaid_sales_use_tax :integer default("unfilled"), not null
# hashed_ssn :string
# health_insurance_paid_amount :decimal(12, 2)
# last_sign_in_at :datetime
# last_sign_in_ip :inet
# locale :string default("en")
Expand Down Expand Up @@ -77,6 +79,7 @@ class StateFileIdIntake < StateFileBaseIntake
enum eligibility_withdrew_msa_fthb: { unfilled: 0, yes: 1, no: 2 }, _prefix: :eligibility_withdrew_msa_fthb
enum eligibility_emergency_rental_assistance: { unfilled: 0, yes: 1, no: 2 }, _prefix: :eligibility_emergency_rental_assistance
enum has_unpaid_sales_use_tax: { unfilled: 0, yes: 1, no: 2 }, _prefix: :has_unpaid_sales_use_tax
enum has_health_insurance_premium: { unfilled: 0, yes: 1, no: 2 }, _prefix: :has_health_insurance_premium

def disqualifying_df_data_reason; end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<% title = t('.title', year: MultiTenantService.statefile.current_tax_year) %>
<% content_for :page_title, title %>

<% content_for :card do %>
<h1 class="h2"><%= title %></h1>
<p><%= t(".subtitle", count: current_intake.household_count) %></p>
<%= form_with model: @form, url: { action: :update }, local: true, method: "put", builder: VitaMinFormBuilder do |f| %>
<div class="reveal">
<p><a href="#" class="reveal__link"><%= t('.what_is_title') %></a></p>
<div class="reveal__content"><%= t('.what_is_content_html') %></div>
</div>

<div class="reveal">
<p><a href="#" class="reveal__link"><%= t('.qualifications_title') %></a></p>
<div class="reveal__content"><%= t('.qualifications_content') %></div>
</div>

<div class="reveal">
<p><a href="#" class="reveal__link"><%= t('.medicaid_title') %></a></p>
<div class="reveal__content"><%= t('.medicaid_content') %></div>
</div>

<div class="question-with-follow-up spacing-below-25">
<div class="question-with-follow-up__question">
<div class="white-group">
<%=
f.cfa_radio_set(
:has_health_insurance_premium,
label_text: t('.health_insurance_premium_question', count: current_intake.household_count, year: MultiTenantService.statefile.current_tax_year),
collection: [
{ value: :yes, label: t("general.affirmative"), input_html: { "data-follow-up": "#sut-field" } },
{ value: :no, label: t("general.negative") },
]
)
%>
</div>
</div>
<div class="question-with-follow-up__follow-up" id="sut-field">
<div class="notice--warning">
<p><%= t('.do_not_include_notice_html') %></p>
</div>

<div class="white-group">
<div class="spacing-below-15"><%= t(".qualifying_amount_help_text", year: MultiTenantService.statefile.current_tax_year) %></div>
<p class="text--help text--small spacing-below-0"><b><%= t(".amount_paid_helper_text", year: MultiTenantService.statefile.current_tax_year) %></b></p>
<%= f.vita_min_money_field(:health_insurance_paid_amount, "", classes: ["form-width--long"]) %>
</div>
</div>

</div>

<% if params[:return_to_review].present? %>
<%= hidden_field_tag "return_to_review", params[:return_to_review] %>
<% end %>
<%= f.continue %>
<% end %>
<% end %>
8 changes: 8 additions & 0 deletions app/views/state_file/questions/id_review/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,13 @@
<% content_for :card do %>
<%= render "state_file/questions/shared/review_header" %>

<div id="health-insurance-premium" class="white-group">
<div class="spacing-below-5">
<p class="text--bold spacing-below-5"><%=t(".health_insurance_premium_title") %></p>
<p><%=number_to_currency(current_intake.health_insurance_paid_amount || 0, precision: 2)%></p>
<%= link_to t("general.edit"), StateFile::Questions::IdHealthInsurancePremiumController.to_path_helper(return_to_review: "y"), class: "button--small" %>
</div>
</div>

<%= render "state_file/questions/shared/review_footer" %>
<% end %>
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
<%=
f.cfa_radio_set(
:has_unpaid_sales_use_tax,
label_text: t('.unpaid_sales_use_tax_label_html'),
collection: [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this taken out?

Copy link
Contributor Author

@arinchoi03 arinchoi03 Oct 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is not supposed to be a copy above this Yes/No question -- according to figma. I had included the same text twice (text about sales/use amount) & noticed it was different from the figma, so I removed it

{ value: :yes, label: t("general.affirmative"), input_html: { "data-follow-up": "#sut-field" } },
{ value: :no, label: t("general.negative") },
Expand Down
36 changes: 36 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2523,13 +2523,49 @@ en:
withdrew_msa_fthb_list:
bullet_1_html: "<strong>Medical Savings Account</strong> and use it for non-qualifying expenses"
bullet_2_html: "<strong>First-Time Homebuyer Account</strong> and didn’t use it for eligible home costs"
id_health_insurance_premium:
edit:
amount_paid_helper_text: Total amount paid in %{year}
do_not_include_notice_html: |
Some health insurance premiums do not qualify for this subtraction. <b>Do not include</b> any premiums paid using the following:

<ul class="list--bulleted">
<li><b>Idaho medical savings account:</b> Funds used from this account cannot be deducted again.</li>
<li><b>Salary reduction plans:</b> Premiums deducted from your paycheck before taxes do not qualify.</li>
<li><b>Social Security Medicare A and B:</b> No deduction for employer-required Medicare A payments.</li>
</ul>
health_insurance_premium_question:
one: Did you pay health insurance premiums for yourself in %{year}?
other: Did you pay health insurance premiums for yourself and your household in %{year}?
medicaid_content: Yes, if you are on Medicaid, your health insurance premium counts.  Check your monthly letter from the Idaho Department of Health and Welfare for your premium amount. It could be as low as $0, depending on your income and other factors.
medicaid_title: Do Medicaid payments count?
qualifications_content: You can deduct health insurance premiums paid for yourself, your spouse, and your dependents, including Medicaid, dental, and vision, as long as they haven’t been deducted from your income pre-tax.
qualifications_title: Which health coverage premiums qualify?
qualifying_amount_help_text: Enter the total amount of qualifying health insurance premiums your household paid in %{year}.
subtitle:
one: To see if you qualify, we need more information about you.
other: To see if you qualify, we need more information about you and your household.
title: You might be eligible for the Idaho Health Insurance Premium Deduction!
what_is_content_html: |
A health insurance premium is the monthly fee you pay for your health coverage.

You can find your premium amounts on your:
<ul>
<li>Monthly pay stub</li>
<li>Form 1095-C</li>
<li>Form 1095-A, by subtracting the total of column C from the total of column A.</li>
</ul>
what_is_title: What is a health insurance premium?
id_primary_state_id:
id_primary:
encourage_sharing_html: If you and your spouse have a driver’s license or state issued identification card please provide the requested information from it. The return will not be rejected if you do not provide a driver’s license or state-issued identification. <br><br> If you provide this information, it may help to identify you as the taxpayer.
protect_identity: Many state revenue agencies, including Idaho, are requesting additional information in an effort to combat stolen-identity tax fraud and to protect you and your tax refund.
subtitle: Provide your driver’s license or identity card number when you e-File to help your refund process faster.
title: We need some details from your state-issued ID, if you have one
why_ask_this: Why are you asking for this information?
id_review:
edit:
health_insurance_premium_title: Idaho Health Insurance Premium Subtraction
id_sales_use_tax:
edit:
sales_tax_content: This is a tax collected at the point of sale when you buy goods within your state.
Expand Down
35 changes: 35 additions & 0 deletions config/locales/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2496,13 +2496,48 @@ es:
withdrew_msa_fthb_list:
bullet_1_html: "<strong>Cuenta de Ahorros Médicos</strong> y lo utilizó para gastos no calificados"
bullet_2_html: "<strong>Cuenta para Compradores de Vivienda por Primera Vez</strong> y no lo usó para costos elegibles de vivienda"
id_health_insurance_premium:
edit:
amount_paid_helper_text: Importe total pagado en %{year}
do_not_include_notice_html: |
Algunas primas de seguros médicos no califican para esta resta. <b>No incluya</b> ninguna prima pagada utilizando lo siguiente:
<ul class="list--bulleted">
<li><b>Cuenta de ahorros médicos de Idaho:</b> Los fondos utilizados de esta cuenta no se pueden deducir nuevamente.</li>
<li><b>Planes de reducción salarial:</b> Las primas deducidas de su cheque de pago antes de impuestos no califican.</li>
<li><b>Seguro Social Medicare A y B:</b> Sin deducción por pagos de Medicare A requeridos por el empleador.</li>
</ul>
health_insurance_premium_question:
one: "¿Pagó usted primas de seguro médico en %{year}?"
other: "¿Pagó primas de seguro médico para usted y su hogar en %{year}?"
medicaid_content: Sí, si tiene Medicaid, la prima de su seguro médico cuenta. Consulte su carta mensual del Departamento de Salud y Bienestar de Idaho para conocer el monto de su prima. Podría ser tan bajo como $0, dependiendo de sus ingresos y otros factores.
medicaid_title: "¿Cuentan los pagos de Medicaid?"
qualifications_content: Puede deducir las primas de seguro médico pagadas para usted, su cónyuge y sus dependientes, incluidos Medicaid, dental y de la vista, siempre que no se hayan deducido de sus ingresos antes de impuestos.
qualifications_title: "¿Qué primas de cobertura médica califican?"
qualifying_amount_help_text: Ingrese el monto total de las primas de seguro médico calificadas que su hogar pagó en %{year}.
subtitle:
one: Para ver si califica, necesitamos más información sobre usted.
other: Para ver si califica, necesitamos más información sobre usted y su hogar.
title: "¡Es posible que sea elegible para la deducción de la prima del seguro médico de Idaho!"
what_is_content_html: |
Una prima de seguro médico es la tarifa mensual que paga por su cobertura médica.

Puede encontrar los montos de sus primas en su:
<ul>
<li>Talón de pago mensual</li>
<li>Formulario 1095-C</li>
<li>Formulario 1095-A, restando el total de la columna C del total de la columna A.</li>
</ul>
what_is_title: "¿Qué es una prima de seguro médico?"
id_primary_state_id:
id_primary:
encourage_sharing_html: Si usted y su cónyuge tienen una licencia de conducir o una tarjeta de identificación emitida por el estado, proporcione la información solicitada. La devolución no será rechazada si no proporciona una licencia de conducir o una identificación emitida por el estado. <br><br>Si proporciona esta información, puede ayudar a identificarlo como contribuyente.
protect_identity: Muchas agencias de ingresos estatales, incluida Idaho, están solicitando información adicional en un esfuerzo por combatir el fraude fiscal por identidad robada y protegerlo a usted y a su reembolso de impuestos.
subtitle: Proporcione su número de licencia de conducir o tarjeta de identidad cuando presente su declaración electrónica para ayudar a procesar su reembolso más rápido.
title: Necesitamos algunos detalles de su documento de identidad oficial, si tiene uno
why_ask_this: "¿Por qué pides esta información?"
id_review:
edit:
health_insurance_premium_title: Resta de primas de seguro médico de Idaho
id_sales_use_tax:
edit:
sales_tax_content: Este es un impuesto que se recauda en el punto de venta cuando se compran productos dentro de su estado.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class AddHealthInsurancePremiumColumnsToIdStateFileIntake < ActiveRecord::Migration[7.1]
def change
add_column :state_file_id_intakes, :has_health_insurance_premium, :integer, default: 0, null: false
add_column :state_file_id_intakes, :health_insurance_paid_amount, :decimal, precision: 12, scale: 2
end
end
2 changes: 2 additions & 0 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1827,8 +1827,10 @@
t.integer "failed_attempts", default: 0, null: false
t.string "federal_return_status"
t.string "federal_submission_id"
t.integer "has_health_insurance_premium", default: 0, null: false
t.integer "has_unpaid_sales_use_tax", default: 0, null: false
t.string "hashed_ssn"
t.decimal "health_insurance_paid_amount", precision: 12, scale: 2
t.datetime "last_sign_in_at"
t.inet "last_sign_in_ip"
t.string "locale", default: "en"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require "rails_helper"

RSpec.describe StateFile::Questions::IdHealthInsurancePremiumController do
let(:intake) { create :state_file_id_intake }
before do
sign_in intake
end

describe "#edit" do
render_views
it 'succeeds' do
get :edit
expect(response).to be_successful
end
end

describe "#update" do
# use the return_to_review_concern shared example if the page
# should skip to the review page when the return_to_review param is present
# requires form_params to be set with any other required params
it_behaves_like :return_to_review_concern do
let(:form_params) do
{
state_file_id_health_insurance_premium_form: {
has_health_insurance_premium: "yes",
health_insurance_paid_amount: "123"
}
}
end
end
end
end
2 changes: 2 additions & 0 deletions spec/factories/state_file_id_intakes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
# email_address_verified_at :datetime
# failed_attempts :integer default(0), not null
# federal_return_status :string
# has_health_insurance_premium :integer default("unfilled"), not null
# has_unpaid_sales_use_tax :integer default("unfilled"), not null
# hashed_ssn :string
# health_insurance_paid_amount :decimal(12, 2)
# last_sign_in_at :datetime
# last_sign_in_ip :inet
# locale :string default("en")
Expand Down
10 changes: 9 additions & 1 deletion spec/features/state_file/complete_intake_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -492,10 +492,16 @@
# 1099G Review
click_on I18n.t("general.continue")

# Health Insurance Premium
expect(page).to have_text I18n.t('state_file.questions.id_health_insurance_premium.edit.title')
choose I18n.t("general.affirmative")
fill_in 'state_file_id_health_insurance_premium_form_health_insurance_paid_amount', with: "1234.60"
click_on I18n.t("general.continue")

# Sales/Use Tax
expect(page).to have_text I18n.t('state_file.questions.id_sales_use_tax.edit.title', year: MultiTenantService.statefile.current_tax_year)
choose I18n.t("general.affirmative")
fill_in 'state_file_id_sales_use_tax_form_total_purchase_amount', with: "290"

click_on I18n.t("general.continue")

expect(page).to have_text I18n.t('state_file.questions.id_primary_state_id.id_primary.title')
Expand All @@ -510,6 +516,8 @@
click_on I18n.t("general.continue")

# ID Review page
expect(page).to have_text "Idaho Health Insurance Premium Subtraction"
expect(page).to have_text "$1,234.60"
click_on I18n.t("general.continue")

expect(page).to have_text I18n.t("state_file.questions.esign_declaration.edit.title", state_name: "Idaho")
Expand Down
Loading
Loading