Skip to content

Commit 4de91de

Browse files
committed
feat: outline new business logic for enrollment that includes expiry
stub out a module for handling the calculations related to expiration / re-enrollment
1 parent 31b486c commit 4de91de

File tree

3 files changed

+63
-14
lines changed

3 files changed

+63
-14
lines changed

benefits/enrollment/expiration.py

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""
2+
The enrollment application: helper functions for calculations related to expiration / re-enrollment.
3+
"""
4+
5+
6+
def is_expired(group_funding_source):
7+
"""Returns whether the funding source has expired or not."""
8+
pass
9+
10+
11+
def calculate_reenrollment_date(group_funding_source, expiration_reenrollment_days):
12+
"""Returns the date on which the funding source can be re-enrolled."""
13+
pass
14+
15+
16+
def calculate_expiry_date(group_funding_source, expiration_days):
17+
"""Returns the date on which the funding source expires."""
18+
pass

benefits/enrollment/views.py

+44-13
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
pageview_decorator,
1919
)
2020
from benefits.core.views import ROUTE_LOGGED_OUT
21-
from . import analytics, forms
21+
from . import analytics, expiration, forms
2222

2323

2424
ROUTE_INDEX = "enrollment:index"
@@ -84,25 +84,56 @@ def index(request):
8484
client.oauth.ensure_active_token(client.token)
8585

8686
funding_source = client.get_funding_source_by_token(card_token)
87+
group_id = eligibility.group_id
8788

8889
try:
89-
client.link_concession_group_funding_source(funding_source_id=funding_source.id, group_id=eligibility.group_id)
90-
except HTTPError as e:
91-
# 409 means that customer already belongs to a concession group.
92-
# the response JSON will look like:
93-
# {"errors":[{"detail":"Conflict (409) - Customer already belongs to a concession group."}]}
94-
if e.response.status_code == 409:
90+
group_funding_sources = client.get_concession_group_linked_funding_sources(group_id)
91+
matching_group_funding_source = None
92+
for group_funding_source in group_funding_sources:
93+
if group_funding_source.id == funding_source.id:
94+
matching_group_funding_source = group_funding_source
95+
break
96+
97+
# funding source is already linked to the group
98+
if matching_group_funding_source:
99+
# if no expiration date, return success
100+
if matching_group_funding_source.concession_expiry is None:
101+
analytics.returned_success(request, group_id)
102+
return success(request)
103+
# else if expiration date has passed, then re-enroll
104+
elif expiration.is_expired(matching_group_funding_source):
105+
client.link_concession_group_funding_source(funding_source_id=funding_source.id, group_id=group_id)
106+
analytics.returned_success(request, group_id)
107+
return success(request)
108+
# else expiration date hasn't passed, so calculate re-enrollment date and show user
109+
else:
110+
reenrollment_date = expiration.calculate_reenrollment_date( # noqa
111+
matching_group_funding_source, eligibility.expiration_reenrollment_days
112+
)
113+
114+
analytics.returned_error(request, "Funding source already enrolled and has not expired")
115+
# todo for #1921: show reenrollment_date to user
116+
# funding source has not been linked to the group yet
117+
else:
118+
# if eligibility_type does not supports_expiration, then just link it
119+
if not eligibility.supports_expiration:
120+
client.link_concession_group_funding_source(funding_source_id=funding_source.id, group_id=group_id)
121+
# else eligibility_type supports_expiration, so calculate expiration date from today and include in request
122+
else:
123+
expiry_date = expiration.calculate_expiry_date(matching_group_funding_source, eligibility.expiration_days)
124+
client.link_concession_group_funding_source(
125+
funding_source_id=funding_source.id, group_id=group_id, expiry_date=expiry_date
126+
)
127+
95128
analytics.returned_success(request, eligibility.group_id)
96129
return success(request)
97-
else:
98-
analytics.returned_error(request, str(e))
99-
raise Exception(f"{e}: {e.response.json()}")
130+
131+
except HTTPError as e:
132+
analytics.returned_error(request, str(e))
133+
raise Exception(f"{e}: {e.response.json()}")
100134
except Exception as e:
101135
analytics.returned_error(request, str(e))
102136
raise e
103-
else:
104-
analytics.returned_success(request, eligibility.group_id)
105-
return success(request)
106137

107138
# GET enrollment index
108139
else:

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ dependencies = [
1515
"django-admin-sortable2==2.1.5",
1616
"django-google-sso==6.0.2",
1717
"eligibility-api==2023.9.1",
18-
"calitp-littlepay==2024.3.1",
18+
"calitp-littlepay@git+https://github.com/cal-itp/littlepay",
1919
"requests==2.31.0",
2020
"sentry-sdk==1.41.0",
2121
"six==1.16.0",

0 commit comments

Comments
 (0)