Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -426,19 +426,19 @@ def find_best_license_in_current_known_licenses(

def generate_privileges_for_provider(self, include_inactive_privileges: bool = False) -> list[dict]:
"""
Generate privilege dicts at runtime for all eligible license types this provider holds.
Generate privilege dicts at runtime for each license type this provider holds.

For each license type, the home license is chosen from all licenses of that type: the license renewed
most recently (when dateOfRenewal is present), otherwise the license with the most recent date of issuance.
By default, privileges are generated only when the chosen home license is compact-eligible.
When the chosen home license is compact-eligible, one privilege is generated per active compact jurisdiction
(excluding the home jurisdiction). When the home license is not compact-eligible, a privilege is still
generated for a jurisdiction if there is a matching privilege adverse action or an open privilege
investigation for that jurisdiction and license type, so admins can see and resolve those records.

When include_inactive_privileges is True, privileges are also generated for ineligible home
When include_inactive_privileges is True, privileges in all jurisdictions are generated for ineligible home
licenses and are marked inactive. This is primarily used when indexing to OpenSearch so that adverse
actions and investigations remain searchable even when a license is ineligible.

For each qualifying type, one privilege is generated per active compact jurisdiction
(excluding the home jurisdiction).

:param include_inactive_privileges: When True, generate privileges for ineligible home licenses
and mark them inactive instead of omitting them entirely.
"""
Expand Down Expand Up @@ -466,16 +466,6 @@ def generate_privileges_for_provider(self, include_inactive_privileges: bool = F
reverse=True,
)
most_recent_license = sorted_licenses[0]
if (
not include_inactive_privileges
and most_recent_license.compactEligibility != CompactEligibilityStatus.ELIGIBLE
):
logger.debug(
'skipping inactive license',
license_jurisdiction=most_recent_license.jurisdiction,
license_type=most_recent_license.licenseType,
)
continue
most_recent_licenses_for_each_type.append(most_recent_license)

result: list[dict] = []
Expand All @@ -492,6 +482,20 @@ def generate_privileges_for_provider(self, include_inactive_privileges: bool = F
inv_records = self.get_investigation_records_for_privilege(
jurisdiction, license_type_abbr, include_closed=False
)
if (
not is_eligible
and not include_inactive_privileges
and not privilege_aa
and not inv_records
Comment thread
coderabbitai[bot] marked this conversation as resolved.
):
logger.debug('Not returning a privilege for this jurisdiction because the home '
'license is not compact eligible and there are no matching privilege adverse '
'actions or open investigations.',
jurisdiction=jurisdiction,
home_jurisdiction=home_jurisdiction,
license_type_abbr=license_type_abbr,
)
continue
privilege_dict = {
'type': 'privilege',
'administratorSetStatus': ActiveInactiveStatus.ACTIVE.value,
Expand All @@ -501,8 +505,10 @@ def generate_privileges_for_provider(self, include_inactive_privileges: bool = F
'licenseJurisdiction': home_jurisdiction,
'licenseType': most_recent_license.licenseType,
'dateOfExpiration': most_recent_license.dateOfExpiration,
# A privilege is inactive if the home license is ineligible, or if a state admin
# has set an encumbrance that has not been lifted.
# the only way a privilege under this model shows inactive is if
# there has been an encumbrance set by a state admin that has not been
# lifted. Ineligible home licenses still get privilege rows when there are matching
# privilege adverse actions or open investigations.
'status': ActiveInactiveStatus.ACTIVE.value
if is_eligible and not privilege_unlifted
else ActiveInactiveStatus.INACTIVE.value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ moto[all]>=5.0.12, <6
boto3-stubs[full]
Faker>=37, <38
cryptography>=46, <47
attrs>=25, <26
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,68 @@ def test_open_investigation_included_and_investigation_status_set(self):
# even with the investigation status, it should still be set to active
self.assertEqual('active', privilege_al['status'])

def test_returns_privilege_when_home_ineligible_and_privilege_adverse_action_matches(self):
"""Ineligible home license still yields a privilege row when a privilege AA matches that jurisdiction."""
from cc_common.data_model.provider_record_util import ProviderUserRecords
from cc_common.data_model.schema.common import CompactEligibilityStatus

records = self._make_provider_records(
license_overrides_list=[
{
'jurisdiction': 'oh',
'jurisdictionUploadedCompactEligibility': CompactEligibilityStatus.INELIGIBLE,
'dateOfExpiration': date(2026, 4, 4),
}
]
)
records.append(
self.test_data_generator.generate_default_adverse_action(
value_overrides={'jurisdiction': 'al'}
).serialize_to_database_record()
)
with self._patch_config_for_privilege_generation():
pur = ProviderUserRecords(records)
result = pur.generate_privileges_for_provider()
self.assertEqual(1, len(result))
self.assertEqual('al', result[0]['jurisdiction'])
self.assertGreaterEqual(len(result[0]['adverseActions']), 1)
self.assertEqual({'al'}, {p['jurisdiction'] for p in result})

def test_returns_privilege_when_home_ineligible_and_open_privilege_investigation_matches(self):
"""Ineligible home license still yields a privilege row when an open privilege investigation matches."""
from cc_common.data_model.provider_record_util import ProviderUserRecords
from cc_common.data_model.schema.common import CompactEligibilityStatus, InvestigationStatusEnum

records = self._make_provider_records(
license_overrides_list=[
{
'jurisdiction': 'oh',
'licenseType': 'cosmetologist',
'jurisdictionUploadedCompactEligibility': CompactEligibilityStatus.INELIGIBLE,
'dateOfExpiration': date(2026, 4, 4),
}
]
)
open_investigation = self.test_data_generator.generate_default_investigation(
value_overrides={
'jurisdiction': 'al',
'licenseTypeAbbreviation': 'cos',
'licenseType': 'cosmetologist',
'investigationAgainst': 'privilege',
}
)
records.append(open_investigation.serialize_to_database_record())
with self._patch_config_for_privilege_generation():
pur = ProviderUserRecords(records)
result = pur.generate_privileges_for_provider()
self.assertEqual(1, len(result))
self.assertEqual('al', result[0]['jurisdiction'])
self.assertEqual(1, len(result[0]['investigations']))
self.assertEqual(
InvestigationStatusEnum.UNDER_INVESTIGATION.value,
result[0]['investigationStatus'],
)


class TestProviderRecordUtility(TstLambdas):
def setUp(self):
Expand Down
Loading