Coverage for benefits/in_person/views.py: 98%
107 statements
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-19 00:56 +0000
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-19 00:56 +0000
1import logging
3from django.contrib.admin import site as admin_site
4from django.http import JsonResponse
5from django.template.response import TemplateResponse
6from django.shortcuts import redirect
7from django.urls import reverse
8import sentry_sdk
11from benefits.routes import routes
12from benefits.core import models, session
13from benefits.eligibility import analytics as eligibility_analytics
14from benefits.enrollment import analytics as enrollment_analytics
15from benefits.enrollment.enrollment import Status, request_card_tokenization_access, enroll
17from benefits.in_person import forms
19logger = logging.getLogger(__name__)
22def eligibility(request):
23 """View handler for the in-person eligibility flow selection form."""
25 agency = session.agency(request)
26 context = {
27 **admin_site.each_context(request),
28 "form": forms.InPersonEligibilityForm(agency=agency),
29 "title": f"{agency.long_name} | In-person enrollment | {admin_site.site_title}",
30 }
32 if request.method == "POST":
33 form = forms.InPersonEligibilityForm(data=request.POST, agency=agency)
35 if form.is_valid():
36 flow_id = form.cleaned_data.get("flow")
37 flow = models.EnrollmentFlow.objects.get(id=flow_id)
38 session.update(request, flow=flow)
39 eligibility_analytics.selected_flow(request, flow, enrollment_method=models.EnrollmentMethods.IN_PERSON)
40 eligibility_analytics.started_eligibility(request, flow, enrollment_method=models.EnrollmentMethods.IN_PERSON)
42 in_person_enrollment = reverse(routes.IN_PERSON_ENROLLMENT)
43 response = redirect(in_person_enrollment)
44 else:
45 context["form"] = form
46 response = TemplateResponse(request, "in_person/eligibility.html", context)
47 else:
48 response = TemplateResponse(request, "in_person/eligibility.html", context)
50 return response
53def token(request):
54 """View handler for the enrollment auth token."""
55 if not session.enrollment_token_valid(request):
56 response = request_card_tokenization_access(request)
58 if response.status is Status.SUCCESS:
59 session.update(request, enrollment_token=response.access_token, enrollment_token_exp=response.expires_at)
60 elif response.status is Status.SYSTEM_ERROR or response.status is Status.EXCEPTION: 60 ↛ 75line 60 didn't jump to line 75 because the condition on line 60 was always true
61 logger.debug("Error occurred while requesting access token", exc_info=response.exception)
62 sentry_sdk.capture_exception(response.exception)
63 enrollment_analytics.failed_access_token_request(
64 request, response.status_code, enrollment_method=models.EnrollmentMethods.IN_PERSON
65 )
67 if response.status is Status.SYSTEM_ERROR:
68 redirect = reverse(routes.IN_PERSON_ENROLLMENT_SYSTEM_ERROR)
69 else:
70 redirect = reverse(routes.IN_PERSON_SERVER_ERROR)
72 data = {"redirect": redirect}
73 return JsonResponse(data)
75 data = {"token": session.enrollment_token(request)}
77 return JsonResponse(data)
80def enrollment(request):
81 """View handler for the in-person enrollment page."""
82 # POST back after transit processor form, process card token
83 if request.method == "POST":
84 form = forms.CardTokenizeSuccessForm(request.POST)
85 if not form.is_valid():
86 raise Exception("Invalid card token form")
88 flow = session.flow(request)
89 eligibility_analytics.returned_success(request, flow, enrollment_method=models.EnrollmentMethods.IN_PERSON)
90 card_token = form.cleaned_data.get("card_token")
91 status, exception = enroll(request, card_token)
93 match (status):
94 case Status.SUCCESS:
95 agency = session.agency(request)
96 expiry = session.enrollment_expiry(request)
97 verified_by = f"{request.user.first_name} {request.user.last_name}"
98 event = models.EnrollmentEvent.objects.create(
99 transit_agency=agency,
100 enrollment_flow=flow,
101 enrollment_method=models.EnrollmentMethods.IN_PERSON,
102 verified_by=verified_by,
103 expiration_datetime=expiry,
104 )
105 event.save()
106 enrollment_analytics.returned_success(
107 request, flow.group_id, enrollment_method=models.EnrollmentMethods.IN_PERSON
108 )
109 return redirect(routes.IN_PERSON_ENROLLMENT_SUCCESS)
111 case Status.SYSTEM_ERROR:
112 enrollment_analytics.returned_error(
113 request, str(exception), enrollment_method=models.EnrollmentMethods.IN_PERSON
114 )
115 sentry_sdk.capture_exception(exception)
116 return redirect(routes.IN_PERSON_ENROLLMENT_SYSTEM_ERROR)
118 case Status.EXCEPTION:
119 enrollment_analytics.returned_error(
120 request, str(exception), enrollment_method=models.EnrollmentMethods.IN_PERSON
121 )
122 sentry_sdk.capture_exception(exception)
123 return redirect(routes.IN_PERSON_SERVER_ERROR)
125 case Status.REENROLLMENT_ERROR: 125 ↛ exitline 125 didn't return from function 'enrollment' because the pattern on line 125 always matched
126 enrollment_analytics.returned_error(
127 request, "Re-enrollment error.", enrollment_method=models.EnrollmentMethods.IN_PERSON
128 )
129 return redirect(routes.IN_PERSON_ENROLLMENT_REENROLLMENT_ERROR)
130 # GET enrollment index
131 else:
132 agency = session.agency(request)
134 tokenize_retry_form = forms.CardTokenizeFailForm(routes.IN_PERSON_ENROLLMENT_RETRY, "form-card-tokenize-fail-retry")
135 tokenize_server_error_form = forms.CardTokenizeFailForm(
136 routes.IN_PERSON_SERVER_ERROR, "form-card-tokenize-fail-server-error"
137 )
138 tokenize_system_error_form = forms.CardTokenizeFailForm(
139 routes.IN_PERSON_ENROLLMENT_SYSTEM_ERROR, "form-card-tokenize-fail-system-error"
140 )
141 tokenize_success_form = forms.CardTokenizeSuccessForm(
142 action_url=routes.IN_PERSON_ENROLLMENT, auto_id=True, label_suffix=""
143 )
145 context = {
146 **admin_site.each_context(request),
147 "forms": [tokenize_retry_form, tokenize_server_error_form, tokenize_system_error_form, tokenize_success_form],
148 "cta_button": "tokenize_card",
149 "card_tokenize_env": agency.transit_processor.card_tokenize_env,
150 "card_tokenize_func": agency.transit_processor.card_tokenize_func,
151 "card_tokenize_url": agency.transit_processor.card_tokenize_url,
152 "enrollment_method": models.EnrollmentMethods.IN_PERSON,
153 "token_field": "card_token",
154 "form_retry": tokenize_retry_form.id,
155 "form_server_error": tokenize_server_error_form.id,
156 "form_success": tokenize_success_form.id,
157 "form_system_error": tokenize_system_error_form.id,
158 "title": f"{agency.long_name} | In-person enrollment | {admin_site.site_title}",
159 }
161 return TemplateResponse(request, "in_person/enrollment/index.html", context)
164def reenrollment_error(request):
165 """View handler for a re-enrollment attempt that is not yet within the re-enrollment window."""
167 agency = session.agency(request)
168 context = {
169 **admin_site.each_context(request),
170 "title": f"{agency.long_name} | In-person enrollment | {admin_site.site_title}",
171 }
173 flow = session.flow(request)
174 context["flow_label"] = flow.label
176 return TemplateResponse(request, "in_person/enrollment/reenrollment_error.html", context)
179def retry(request):
180 """View handler for card verification failure."""
181 # enforce POST-only route for sending analytics
182 if request.method == "POST":
183 enrollment_analytics.returned_retry(request, enrollment_method=models.EnrollmentMethods.IN_PERSON)
185 agency = session.agency(request)
186 context = {
187 **admin_site.each_context(request),
188 "title": f"{agency.long_name} | In-person enrollment | {admin_site.site_title}",
189 }
191 return TemplateResponse(request, "in_person/enrollment/retry.html", context)
194def system_error(request):
195 """View handler for an enrollment system error."""
196 agency = session.agency(request)
197 context = {
198 **admin_site.each_context(request),
199 "title": f"{agency.long_name} | In-person enrollment | {admin_site.site_title}",
200 }
202 return TemplateResponse(request, "in_person/enrollment/system_error.html", context)
205def server_error(request):
206 """View handler for errors caused by a misconfiguration or bad request."""
207 agency = session.agency(request)
208 context = {
209 **admin_site.each_context(request),
210 "title": f"{agency.long_name} | In-person enrollment | {admin_site.site_title}",
211 }
213 return TemplateResponse(request, "in_person/enrollment/server_error.html", context)
216def success(request):
217 """View handler for the final success page."""
218 agency = session.agency(request)
219 context = {
220 **admin_site.each_context(request),
221 "title": f"{agency.long_name} | In-person enrollment | {admin_site.site_title}",
222 }
224 return TemplateResponse(request, "in_person/enrollment/success.html", context)