Skip to content

Commit a490aa2

Browse files
Update Determinations reason to plural (#3)
* Change determinations reason to array
1 parent 631280e commit a490aa2

9 files changed

Lines changed: 107 additions & 28 deletions

File tree

reporting-app/app/models/certification_case.rb

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,17 @@ def determine_ex_parte_exemption(eligibility_fact)
7373
self.exemption_request_approval_status_updated_at = Time.current
7474
self.close!
7575

76-
# TODO: Extract to Fact class that inherits from Strata::RulesEngine::Fact
77-
true_reasons = eligibility_fact.reasons.select { |reason| reason.value }.map(&:name)
78-
7976
reasons = {
80-
age_under_19_exempt: true_reasons.include?(:age_under_19),
81-
age_over_65_exempt: true_reasons.include?(:age_over_65)
77+
age_under_19: :age_under_19_exempt,
78+
age_over_65: :age_over_65_exempt
8279
}
8380

81+
# TODO: Extract to Fact class that inherits from Strata::RulesEngine::Fact
82+
true_reasons = eligibility_fact.reasons.select { |reason| reason.value }.map(&:name).map { |name| reasons[name] }
8483
certification = Certification.find(self.certification_id)
8584
certification.record_determination!(
8685
decision_method: :automated,
87-
reason: reasons.key(true),
86+
reasons: true_reasons,
8887
outcome: :exempt,
8988
determination_data: eligibility_fact.reasons.to_json,
9089
determined_at: certification.certification_requirements.certification_date

reporting-app/app/models/concerns/determinable.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
# @example Record an automated determination
1818
# record.record_determination!(
1919
# decision_method: :automated,
20-
# reason: "pregnant_member",
20+
# reasons: ["pregnant_member"],
2121
# outcome: :automated_exemption,
2222
# determination_data: rules_engine.evaluate(:pregnant_member).reasons,
2323
# determined_at: Time.current
@@ -26,7 +26,7 @@
2626
# @example Record a staff-reviewed determination
2727
# record.record_determination!(
2828
# decision_method: :staff_review,
29-
# reason: "requirements_verification",
29+
# reasons: ["requirements_verification"],
3030
# outcome: :requirements_met,
3131
# determination_data: {verified_fields: [:income, :address]},
3232
# determined_at: Time.current,

reporting-app/app/models/determination.rb

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
#
55
# By default, Strata::Determination provides:
66
# - A polymorphic +subject+ association to any aggregate root
7-
# - Validations for all required fields (+decision_method+, +reason+, +outcome+, +determination_data+, +determined_at+)
8-
# - Query scopes for filtering by subject, decision method, reason, outcome, user, and time windows
7+
# - Validations for all required fields (+decision_method+, +reasons+, +outcome+, +determination_data+, +determined_at+)
8+
# - Query scopes for filtering by subject, decision method, reasons, outcome, user, and time windows
99
# - Support for automated, staff-reviewed, and attested determinations
1010
#
1111
# Extend this class to add:
@@ -19,7 +19,7 @@
1919
# enum decision_method: { automated: "automated", staff_review: "staff_review", attestation: "attestation" }
2020
# enum outcome: { approved: "approved", denied: "denied", pending: "pending" }
2121
#
22-
# validates :reason, inclusion: { in: %w(pregnant_member incarcerated other) }
22+
# validates :reasons, presence: true, inclusion: { in: %w(pregnant_member incarcerated other) }
2323
# end
2424
#
2525
# @example Query determinations for a specific subject
@@ -31,12 +31,15 @@
3131
# @see Strata::Determinable for the +record_determination!+ method to use in models
3232
#
3333
class Determination < Strata::Determination
34+
VALID_REASONS = %w[
35+
age_under_19_exempt
36+
age_over_65_exempt
37+
pregnancy_exempt
38+
american_indian_alaska_native_exempt
39+
].freeze
40+
3441
enum :decision_method, { automated: "automated", manual: "manual" }
35-
enum :reason, {
36-
age_under_19_exempt: "age_under_19_exempt",
37-
age_over_65_exempt: "age_over_65_exempt",
38-
pregnancy_exempt: "pregnancy_exempt",
39-
american_indian_alaska_native_exempt: "american_indian_alaska_native_exempt"
40-
}
4142
enum :outcome, { compliant: "compliant", exempt: "exempt" }
43+
44+
validates :reasons, presence: true, inclusion: { in: VALID_REASONS }
4245
end
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
en:
2+
activerecord:
3+
errors:
4+
models:
5+
determination:
6+
attributes:
7+
reasons:
8+
inclusion: "must contain only valid reason values"
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# frozen_string_literal: true
2+
3+
class UpdateDeterminationReasons < ActiveRecord::Migration[7.2]
4+
def up
5+
# Add the new reasons column as an array of strings
6+
add_column :strata_determinations, :reasons, :string, array: true, default: [], null: false
7+
8+
# Copy existing reason values into reasons array
9+
execute <<~SQL
10+
UPDATE strata_determinations
11+
SET reasons = ARRAY[reason]
12+
WHERE reason IS NOT NULL AND reason != ''
13+
SQL
14+
15+
# Remove the old reason column
16+
remove_column :strata_determinations, :reason
17+
end
18+
19+
def down
20+
# Add back the old reason column
21+
add_column :strata_determinations, :reason, :string, null: false, default: ""
22+
23+
# Copy first reason from array back to reason column
24+
execute <<~SQL
25+
UPDATE strata_determinations
26+
SET reason = reasons[1]
27+
WHERE array_length(reasons, 1) >= 1
28+
SQL
29+
30+
# Remove the reasons column
31+
remove_column :strata_determinations, :reasons
32+
end
33+
end

reporting-app/db/schema.rb

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

reporting-app/spec/factories/determination_factory.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
factory :determination do
55
subject { association :certification }
66
decision_method { 'automated' }
7-
reason { 'age_under_19_exempt' }
7+
reasons { [ 'age_under_19_exempt' ] }
88
outcome { 'exempt' }
99
determination_data { { reasons: { rule: 'passed' } } }
1010
determined_at { Time.current }

reporting-app/spec/models/certification_case_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@
204204
determination = Determination.first
205205

206206
expect(determination.decision_method).to eq("automated")
207-
expect(determination.reason).to eq("age_under_19_exempt")
207+
expect(determination.reasons).to include("age_under_19_exempt")
208208
expect(determination.outcome).to eq("exempt")
209209
expect(determination.determined_at).to be_present
210210
expect(determination.determination_data).to eq(eligibility_fact.reasons.to_json)

reporting-app/spec/models/determination_spec.rb

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,57 @@
1010
end
1111
end
1212

13-
describe 'reason' do
14-
it 'defines the reason enum with correct values' do
13+
describe 'outcome' do
14+
it 'defines the outcome enum with correct values' do
15+
expect(described_class.outcomes.keys).to contain_exactly('compliant', 'exempt')
16+
end
17+
end
18+
end
19+
20+
describe 'validations' do
21+
describe 'reasons' do
22+
it 'defines valid reason constants' do
1523
expected_reasons = %w[
1624
age_under_19_exempt
1725
age_over_65_exempt
1826
pregnancy_exempt
1927
american_indian_alaska_native_exempt
2028
]
21-
expect(described_class.reasons.keys).to match_array(expected_reasons)
29+
expect(Determination::VALID_REASONS).to match_array(expected_reasons)
2230
end
23-
end
2431

25-
describe 'outcome' do
26-
it 'defines the outcome enum with correct values' do
27-
expect(described_class.outcomes.keys).to contain_exactly('compliant', 'exempt')
32+
it 'validates presence of reasons' do
33+
determination = build(:determination, reasons: nil)
34+
expect(determination).not_to be_valid
35+
expect(determination.errors[:reasons]).to be_present
36+
end
37+
38+
it 'validates presence of non-empty reasons array' do
39+
determination = build(:determination, reasons: [])
40+
expect(determination).not_to be_valid
41+
expect(determination.errors[:reasons]).to be_present
42+
end
43+
44+
it 'allows valid reasons' do
45+
determination = build(:determination, reasons: [ 'age_under_19_exempt' ])
46+
expect(determination).to be_valid
47+
end
48+
49+
it 'allows multiple valid reasons' do
50+
determination = build(:determination, reasons: [ 'age_under_19_exempt', 'pregnancy_exempt' ])
51+
expect(determination).to be_valid
52+
end
53+
54+
it 'rejects invalid reasons' do
55+
determination = build(:determination, reasons: [ 'invalid_reason' ])
56+
expect(determination).not_to be_valid
57+
expect(determination.errors[:reasons]).to include(match(/must contain only valid reason values/))
58+
end
59+
60+
it 'rejects mixed valid and invalid reasons' do
61+
determination = build(:determination, reasons: [ 'age_under_19_exempt', 'invalid_reason' ])
62+
expect(determination).not_to be_valid
63+
expect(determination.errors[:reasons]).to include(match(/must contain only valid reason values/))
2864
end
2965
end
3066
end

0 commit comments

Comments
 (0)