Coverage for benefits/core/admin/enrollment.py: 87%
90 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-12 23:32 +0000
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-12 23:32 +0000
1from django import forms
2from django.conf import settings
3from django.core.exceptions import ValidationError
4from django.contrib import admin
5from django.http import HttpRequest
7from adminsortable2.admin import SortableAdminMixin
9from benefits.core import models
10from .users import is_staff_member_or_superuser
13@admin.register(models.EnrollmentEvent)
14class EnrollmentEventAdmin(admin.ModelAdmin):
15 list_display = ("enrollment_datetime", "transit_agency", "enrollment_flow", "enrollment_method", "verified_by")
16 ordering = ("-enrollment_datetime",)
18 def has_add_permission(self, request: HttpRequest, obj=None):
19 if settings.RUNTIME_ENVIRONMENT() == settings.RUNTIME_ENVS.PROD:
20 return False
21 elif request.user and is_staff_member_or_superuser(request.user): 21 ↛ 24line 21 didn't jump to line 24 because the condition on line 21 was always true
22 return True
23 else:
24 return False
26 def has_change_permission(self, request: HttpRequest, obj=None):
27 if settings.RUNTIME_ENVIRONMENT() == settings.RUNTIME_ENVS.PROD:
28 return False
29 elif request.user and request.user.is_superuser:
30 return True
31 else:
32 return False
34 def has_delete_permission(self, request: HttpRequest, obj=None):
35 if settings.RUNTIME_ENVIRONMENT() == settings.RUNTIME_ENVS.PROD: 35 ↛ 36line 35 didn't jump to line 36 because the condition on line 35 was never true
36 return False
37 elif request.user and is_staff_member_or_superuser(request.user): 37 ↛ 40line 37 didn't jump to line 40 because the condition on line 37 was always true
38 return True
39 else:
40 return False
42 def has_view_permission(self, request: HttpRequest, obj=None):
43 if request.user and is_staff_member_or_superuser(request.user): 43 ↛ 46line 43 didn't jump to line 46 because the condition on line 43 was always true
44 return True
45 else:
46 return False
49class EnrollmentFlowForm(forms.ModelForm):
50 def has_field(self, field_name):
51 return self.fields.get(field_name) is not None
53 def get(self, cleaned_data, field_name):
54 """
55 If the field is present on the form, simply get the value from the cleaned_data.
57 If the field is not present on the form, that means the user doesn't have access to the field,
58 so get the value from the form's instance of the object.
59 """
60 return cleaned_data.get(field_name) if self.has_field(field_name) else getattr(self.instance, field_name)
62 def clean(self):
63 cleaned_data = super().clean()
65 field_errors = {}
66 non_field_errors = []
68 supports_expiration = cleaned_data.get("supports_expiration")
70 if supports_expiration:
71 expiration_days = cleaned_data.get("expiration_days")
72 expiration_reenrollment_days = cleaned_data.get("expiration_reenrollment_days")
74 message = "When support_expiration is True, this value must be greater than 0."
75 if expiration_days is None or expiration_days <= 0: 75 ↛ 77line 75 didn't jump to line 77 because the condition on line 75 was always true
76 field_errors.update(expiration_days=ValidationError(message))
77 if expiration_reenrollment_days is None or expiration_reenrollment_days <= 0: 77 ↛ 80line 77 didn't jump to line 80 because the condition on line 77 was always true
78 field_errors.update(expiration_reenrollment_days=ValidationError(message))
80 transit_agency = cleaned_data.get("transit_agency")
82 if transit_agency:
83 # these fields might not be on the form, so use helper method to correctly get the value
84 eligibility_api_url = self.get(cleaned_data, "eligibility_api_url")
86 if eligibility_api_url:
87 message = "Required for Eligibility API verification."
88 needed = dict(
89 eligibility_api_auth_header=self.get(cleaned_data, "eligibility_api_auth_header"),
90 eligibility_api_auth_key_secret_name=self.get(cleaned_data, "eligibility_api_auth_key_secret_name"),
91 eligibility_api_jwe_cek_enc=self.get(cleaned_data, "eligibility_api_jwe_cek_enc"),
92 eligibility_api_jwe_encryption_alg=self.get(cleaned_data, "eligibility_api_jwe_encryption_alg"),
93 eligibility_api_jws_signing_alg=self.get(cleaned_data, "eligibility_api_jws_signing_alg"),
94 eligibility_api_public_key=self.get(cleaned_data, "eligibility_api_public_key"),
95 )
96 for k, v in needed.items():
97 if self.has_field(k) and not v: 97 ↛ 99line 97 didn't jump to line 99 because the condition on line 97 was always true
98 field_errors.update({k: ValidationError(f"{message}.")})
99 elif not v:
100 non_field_errors.append(ValidationError(f"{message}: {k}"))
101 elif not cleaned_data.get("claims_request"):
102 message = (
103 "Must configure either claims verification or Eligibility API verification before"
104 + " adding to a transit agency."
105 )
106 non_field_errors.append(ValidationError(message))
108 for field_name, validation_error in field_errors.items():
109 self.add_error(field_name, validation_error)
110 for validation_error in non_field_errors:
111 self.add_error(None, validation_error)
114@admin.register(models.EnrollmentFlow)
115class SortableEnrollmentFlowAdmin(SortableAdminMixin, admin.ModelAdmin):
116 list_display = ("label", "transit_agency", "supported_enrollment_methods")
117 form = EnrollmentFlowForm
119 def get_exclude(self, request, obj=None):
120 fields = []
122 if not request.user.is_superuser:
123 fields.extend(
124 [
125 "eligibility_api_auth_header",
126 "eligibility_api_auth_key_secret_name",
127 "eligibility_api_public_key",
128 "eligibility_api_jwe_cek_enc",
129 "eligibility_api_jwe_encryption_alg",
130 "eligibility_api_jws_signing_alg",
131 ]
132 )
134 return fields or super().get_exclude(request, obj)
136 def get_readonly_fields(self, request, obj=None):
137 fields = []
139 if not request.user.is_superuser:
140 fields.extend(
141 [
142 "eligibility_api_url",
143 "selection_label_template_override",
144 ]
145 )
147 return fields or super().get_readonly_fields(request, obj)
149 def has_add_permission(self, request: HttpRequest, obj=None):
150 if settings.RUNTIME_ENVIRONMENT() != settings.RUNTIME_ENVS.PROD:
151 return True
152 elif request.user and is_staff_member_or_superuser(request.user): 152 ↛ 155line 152 didn't jump to line 155 because the condition on line 152 was always true
153 return True
154 else:
155 return False