Skip to content

Commit 1234aae

Browse files
check top level military status field in privilege purchase logic
1 parent ce38bf1 commit 1234aae

3 files changed

Lines changed: 44 additions & 16 deletions

File tree

backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/provider/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ def currentHomeJurisdiction(self) -> str | None:
148148
return self._data.get('currentHomeJurisdiction')
149149

150150
@property
151-
def militaryStatus(self) -> str:
151+
def militaryStatus(self) -> str | None:
152152
"""
153153
The military audit status of the provider.
154154
@@ -158,7 +158,7 @@ def militaryStatus(self) -> str:
158158
return self._data.get('militaryStatus')
159159

160160
@property
161-
def militaryStatusNote(self) -> str:
161+
def militaryStatusNote(self) -> str | None:
162162
"""
163163
The note from the most recent military audit decision (if declined).
164164

backend/compact-connect/lambdas/python/purchases/handlers/privileges.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
CompactEligibilityStatus,
1010
HomeJurisdictionChangeStatusEnum,
1111
LicenseDeactivatedStatusEnum,
12-
LicenseEncumberedStatusEnum,
12+
LicenseEncumberedStatusEnum, MilitaryAuditStatus,
1313
)
1414
from cc_common.data_model.schema.compact import Compact
1515
from cc_common.data_model.schema.compact.api import CompactOptionsResponseSchema
@@ -339,16 +339,22 @@ def post_purchase_privileges(event: dict, context: LambdaContext): # noqa: ARG0
339339
)
340340

341341
license_expiration_date: date = matching_license_record.dateOfExpiration
342-
provider_latest_military_status = provider_user_records.get_latest_military_affiliation_status()
343-
if provider_latest_military_status == MilitaryAffiliationStatus.INITIALIZING:
342+
# make sure latest military file upload was successful
343+
provider_latest_military_upload_status = provider_user_records.get_latest_military_affiliation_status()
344+
if provider_latest_military_upload_status == MilitaryAffiliationStatus.INITIALIZING:
344345
# this only occurs if the user's military document was not processed by S3 as expected
345346
raise CCInvalidRequestException(
346347
'Your proof of military affiliation documentation was not successfully processed. '
347348
'Please return to the Military Status page and re-upload your military affiliation '
348349
'documentation or end your military affiliation.'
349350
)
350351

351-
user_active_military = provider_latest_military_status == MilitaryAffiliationStatus.ACTIVE
352+
# Get militaryStatus from the provider record
353+
# militaryStatus defaults to 'notApplicable' if not present (set in generate_api_response_object)
354+
provider_military_status = top_level_provider_record.militaryStatus or MilitaryAuditStatus.NOT_APPLICABLE
355+
356+
# User is considered active military if their militaryStatus is either 'tentative' or 'approved'
357+
user_active_military = provider_military_status in (MilitaryAuditStatus.TENTATIVE, MilitaryAuditStatus.APPROVED)
352358

353359
# Validate attestations are the latest versions before proceeding with the purchase
354360
_validate_attestations(compact_abbr, body.get('attestations', []), user_active_military)

backend/compact-connect/lambdas/python/purchases/tests/function/test_handlers/test_purchase_privileges.py

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,10 @@ def test_post_purchase_privileges_forbidden_with_recent_encumbrance(self, mock_p
300300
resp = post_purchase_privileges(event, self.mock_context)
301301
self.assertEqual(400, resp['statusCode'])
302302

303-
def _when_testing_military_affiliation_status(
303+
def _when_testing_military_status(
304304
self,
305305
mock_purchase_client_constructor: MagicMock,
306-
military_affiliation_status: str,
306+
military_status: str,
307307
expected_military_parameter: bool,
308308
):
309309
from handlers.privileges import post_purchase_privileges
@@ -312,8 +312,11 @@ def _when_testing_military_affiliation_status(
312312
mock_purchase_client_constructor
313313
)
314314
event = self._when_testing_provider_user_event_with_custom_claims()
315-
self._load_military_affiliation_record_data(status=military_affiliation_status)
316-
attestations = generate_default_attestation_list(active_military=military_affiliation_status == 'active')
315+
# Set militaryStatus on the provider record
316+
self.test_data_generator.put_default_provider_record_in_provider_table(
317+
value_overrides={'militaryStatus': military_status, 'providerId': TEST_PROVIDER_ID}
318+
)
319+
attestations = generate_default_attestation_list(active_military=expected_military_parameter)
317320

318321
event['body'] = _generate_test_request_body(attestations=attestations)
319322

@@ -324,16 +327,32 @@ def _when_testing_military_affiliation_status(
324327
self.assertEqual(expected_military_parameter, purchase_client_call_kwargs['user_active_military'])
325328

326329
@patch('handlers.privileges.PurchaseClient')
327-
def test_post_purchase_privileges_calls_purchase_client_with_active_military_status(
330+
def test_post_purchase_privileges_calls_purchase_client_with_tentative_military_status(
331+
self, mock_purchase_client_constructor
332+
):
333+
"""Test that tentative military status is considered active military."""
334+
self._when_testing_military_status(mock_purchase_client_constructor, 'tentative', True)
335+
336+
@patch('handlers.privileges.PurchaseClient')
337+
def test_post_purchase_privileges_calls_purchase_client_with_approved_military_status(
328338
self, mock_purchase_client_constructor
329339
):
330-
self._when_testing_military_affiliation_status(mock_purchase_client_constructor, 'active', True)
340+
"""Test that approved military status is considered active military."""
341+
self._when_testing_military_status(mock_purchase_client_constructor, 'approved', True)
331342

332343
@patch('handlers.privileges.PurchaseClient')
333-
def test_post_purchase_privileges_calls_purchase_client_with_inactive_military_status(
344+
def test_post_purchase_privileges_calls_purchase_client_with_declined_military_status(
334345
self, mock_purchase_client_constructor
335346
):
336-
self._when_testing_military_affiliation_status(mock_purchase_client_constructor, 'inactive', False)
347+
"""Test that declined military status is not considered active military."""
348+
self._when_testing_military_status(mock_purchase_client_constructor, 'declined', False)
349+
350+
@patch('handlers.privileges.PurchaseClient')
351+
def test_post_purchase_privileges_calls_purchase_client_with_not_applicable_military_status(
352+
self, mock_purchase_client_constructor
353+
):
354+
"""Test that notApplicable military status is not considered active military."""
355+
self._when_testing_military_status(mock_purchase_client_constructor, 'notApplicable', False)
337356

338357
@patch('handlers.privileges.PurchaseClient')
339358
def test_post_purchase_privileges_raises_exception_when_military_affiliation_in_initializing_status(
@@ -948,14 +967,17 @@ def test_post_purchase_privileges_validates_investigation_attestations(self, moc
948967

949968
@patch('handlers.privileges.PurchaseClient')
950969
def test_post_purchase_privileges_validates_military_attestation(self, mock_purchase_client_constructor):
951-
"""Test that military attestation is required when user has active military affiliation."""
970+
"""Test that military attestation is required when user has active military status (tentative or approved)."""
952971
from handlers.privileges import post_purchase_privileges
953972

954973
self._when_purchase_client_successfully_processes_request(mock_purchase_client_constructor)
955-
self._load_military_affiliation_record_data(status='active')
956974

957975
event = self._when_testing_provider_user_event_with_custom_claims()
958976
event['body'] = _generate_test_request_body()
977+
# Set militaryStatus to 'approved' on the provider record
978+
self.test_data_generator.put_default_provider_record_in_provider_table(
979+
value_overrides={'militaryStatus': 'approved', 'providerId': TEST_PROVIDER_ID}
980+
)
959981

960982
resp = post_purchase_privileges(event, self.mock_context)
961983
self.assertEqual(400, resp['statusCode'], resp['body'])

0 commit comments

Comments
 (0)