Coverage for benefits/in_person/forms.py: 74%
44 statements
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-07 00:01 +0000
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-07 00:01 +0000
1"""
2The in-person eligibility application: Form definition for the
3in-person eligibility verification flow, in which a
4transit agency employee manually verifies a rider's eligibility.
5"""
7from dataclasses import dataclass
9from django import forms
11from benefits.core import models
12from benefits.enrollment.forms import CardTokenizeFailForm, CardTokenizeSuccessForm # noqa
13from benefits.routes import routes
16@dataclass
17class EligibilityPolicy:
18 details: str
21class InPersonEligibilityForm(forms.Form):
22 """Form to capture eligibility for in-person verification flow selection."""
24 action_url = routes.IN_PERSON_ELIGIBILITY
25 id = "form-flow-selection"
26 method = "POST"
28 flow = forms.ChoiceField(label="Choose an eligibility type to qualify this rider.", widget=forms.widgets.RadioSelect)
30 cancel_url = routes.ADMIN_INDEX
32 flow_field_error_message = "Choose an eligibility type"
33 verified_field_error_message = "Check the box to verify you have confirmed eligibility"
35 eligibility_policies = {
36 models.SystemName.COURTESY_CARD.value: EligibilityPolicy(
37 details="I confirmed this rider’s identity using a government-issued ID and verified they possess an MST "
38 "Courtesy Card."
39 ),
40 models.SystemName.MEDICARE.value: EligibilityPolicy(
41 details="I confirmed this rider’s identity using a government-issued ID and verified they possess a valid "
42 "Medicare card."
43 ),
44 models.SystemName.OLDER_ADULT.value: EligibilityPolicy(
45 details="I confirmed this rider’s identity using a government-issued ID and verified they are age 65 or older."
46 ),
47 models.SystemName.REDUCED_FARE_MOBILITY_ID.value: EligibilityPolicy(
48 details="I confirmed this rider’s identity using a government-issued ID and verified they possess an SBMTD "
49 "Reduced Fare Mobility ID."
50 ),
51 models.SystemName.GCTD_CARD.value: EligibilityPolicy(
52 details="I confirmed this rider’s identity using a government-issued ID and verified they possess a GCTD Reduced "
53 " Fare ID."
54 ),
55 }
57 def __init__(self, agency: models.TransitAgency, *args, **kwargs):
58 super().__init__(*args, **kwargs)
59 flows = agency.enrollment_flows.filter(supported_enrollment_methods__contains=models.EnrollmentMethods.IN_PERSON)
61 self.classes = "in-person-eligibility-form"
62 flow_field = self.fields["flow"]
63 flow_field.choices = [(f.id, f.label) for f in flows]
64 flow_field.widget.attrs.update({"data-custom-validity": self.flow_field_error_message})
66 # dynamically add a BooleanField for each flow
67 for flow in flows:
68 field_id = f"verified_{flow.id}"
69 self.fields[field_id] = forms.BooleanField(
70 required=False, # `clean()` will handle requiring the specific field
71 label=self.get_policy_details(flow),
72 widget=forms.widgets.CheckboxInput(attrs={"class": "d-none"}), # start out hidden
73 )
74 field = self.fields[field_id]
75 field.hide = True
76 field.widget.attrs.update({"data-custom-validity": self.verified_field_error_message})
78 self.use_custom_validity = True
80 def get_policy_details(self, flow: models.EnrollmentFlow):
81 policy = self.eligibility_policies.get(flow.system_name, None)
82 return policy.details if policy else None
84 def clean(self):
85 cleaned_data = super().clean()
87 flow_field_name = "flow"
88 selected_flow = cleaned_data.get(flow_field_name)
90 if not selected_flow:
91 self.add_error(flow_field_name, self.flow_field_error_message)
92 else:
93 verified_field_name = f"verified_{selected_flow}"
94 verified = cleaned_data.get(verified_field_name)
95 if not verified:
96 self.add_error(verified_field_name, self.verified_field_error_message)