Skip to content

Commit

Permalink
fix: Rename SanctionsFallback to SDNFallback models and functions
Browse files Browse the repository at this point in the history
  • Loading branch information
julianajlk committed Nov 6, 2023
1 parent b99497f commit 86d50e6
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 64 deletions.
8 changes: 4 additions & 4 deletions .annotation_safe_list.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ sanctions.SanctionsCheckFailure:
".. no_pii:": "This model has no PII"
sanctions.HistoricalSanctionsCheckFailure:
".. no_pii:": "This model has no PII"
sanctions.SanctionsFallbackMetadata:
sanctions.SDNFallbackMetadata:
".. no_pii:": "This model has no PII"
sanctions.HistoricalSanctionsFallbackMetadata:
sanctions.HistoricalSDNFallbackMetadata:
".. no_pii:": "This model has no PII"
sanctions.SanctionsFallbackData:
sanctions.SDNFallbackData:
".. no_pii:": "This model has no PII"
sanctions.HistoricalSanctionsFallbackData:
sanctions.HistoricalSDNFallbackData:
".. no_pii:": "This model has no PII"
sessions.Session:
".. no_pii:": "This model has no PII"
Expand Down
2 changes: 1 addition & 1 deletion sanctions/apps/api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def post(self, request):
except (HTTPError, Timeout) as e:
logger.info(
'SDNCheckView: SDN API call received an error: %s.'
' Calling SanctionsFallback function for user %s.',
' Calling sanctions checkSDNFallback function for user %s.',
str(e),
lms_user_id
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@ def handle(self, *args, **options):
status_code = download.status_code
except Timeout:
logger.warning(
"SanctionsFallback: DOWNLOAD FAILURE: Timeout occurred trying to download SDN csv. "
"Sanctions SDNFallback: DOWNLOAD FAILURE: Timeout occurred trying to download SDN csv. "
"Timeout threshold (in seconds): %s", timeout)
raise
except Exception as e: # pylint: disable=broad-except
logger.warning("SanctionsFallback: DOWNLOAD FAILURE: Exception occurred: [%s]", e)
logger.warning("Sanctions SDNFallback: DOWNLOAD FAILURE: Exception occurred: [%s]", e)
raise

if download.status_code != 200:
logger.warning("SanctionsFallback: DOWNLOAD FAILURE: Status code was: [%s]", status_code)
logger.warning("Sanctions SDNFallback: DOWNLOAD FAILURE: Status code was: [%s]", status_code)
raise Exception("CSV download url got an unsuccessful response code: ", status_code)

with tempfile.TemporaryFile() as temp_csv:
Expand All @@ -62,17 +62,17 @@ def handle(self, *args, **options):
metadata_entry = populate_sdn_fallback_data_and_metadata(sdn_file_string)
if metadata_entry:
logger.info(
'SanctionsFallback: IMPORT SUCCESS: Imported SDN CSV. Metadata id %s',
'Sanctions SDNFallback: IMPORT SUCCESS: Imported SDN CSV. Metadata id %s',
metadata_entry.id)

logger.info('SanctionsFallback: DOWNLOAD SUCCESS: Successfully downloaded the SDN CSV.')
logger.info('Sanctions SDNFallback: DOWNLOAD SUCCESS: Successfully downloaded the SDN CSV.')
self.stdout.write(
self.style.SUCCESS(
'SanctionsFallback: Imported SDN CSV into the SanctionsFallbackMetadata and SanctionsFallbackData models.'
'Sanctions SDNFallback: Imported SDN CSV into the SDNFallbackMetadata and SDNFallbackData models.'
)
)
else:
logger.warning(
"SanctionsFallback: DOWNLOAD FAILURE: file too small! "
"Sanctions SDNFallback: DOWNLOAD FAILURE: file too small! "
"(%f MB vs threshold of %s MB)", file_size_in_MB, threshold)
raise Exception("CSV file download did not meet threshold given")
12 changes: 6 additions & 6 deletions sanctions/apps/sanctions/management/commands/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@
import factory
from faker import Faker

from sanctions.apps.sanctions.models import SanctionsFallbackData, SanctionsFallbackMetadata
from sanctions.apps.sanctions.models import SDNFallbackData, SDNFallbackMetadata

class SanctionsFallbackMetadataFactory(factory.DjangoModelFactory):
class SDNFallbackMetadataFactory(factory.DjangoModelFactory):
class Meta:
model = SanctionsFallbackMetadata
model = SDNFallbackMetadata

file_checksum = factory.Sequence(lambda n: Faker().md5())
import_state = 'New'
download_timestamp = datetime.now() - timedelta(days=10)


class SanctionsFallbackDataFactory(factory.DjangoModelFactory):
class SDNFallbackDataFactory(factory.DjangoModelFactory):
class Meta:
model = SanctionsFallbackData
model = SDNFallbackData

sdn_fallback_metadata = factory.SubFactory(SanctionsFallbackMetadataFactory)
sdn_fallback_metadata = factory.SubFactory(SDNFallbackMetadataFactory)
source = "Specially Designated Nationals (SDN) - Treasury Department"
sdn_type = "Individual"
names = factory.Faker('name')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ def test_handle_pass(self, mock_response):
self.LOGGER_NAME,
'INFO',
StringComparison(
r'(?s)SanctionsFallback: IMPORT SUCCESS: Imported SDN CSV\. Metadata id.*')
r'(?s)Sanctions SDNFallback: IMPORT SUCCESS: Imported SDN CSV\. Metadata id.*')
),
(
self.LOGGER_NAME,
'INFO',
"SanctionsFallback: DOWNLOAD SUCCESS: Successfully downloaded the SDN CSV."
"Sanctions SDNFallback: DOWNLOAD SUCCESS: Successfully downloaded the SDN CSV."
)
)

Expand All @@ -65,7 +65,7 @@ def test_handle_fail_size(self, mock_response):
(
self.LOGGER_NAME,
'WARNING',
"SanctionsFallback: DOWNLOAD FAILURE: file too small! (0.000642 MB vs threshold of 1.0 MB)"
"Sanctions SDNFallback: DOWNLOAD FAILURE: file too small! (0.000642 MB vs threshold of 1.0 MB)"
)
)
self.assertEqual('CSV file download did not meet threshold given', str(e.exception))
Expand All @@ -82,7 +82,7 @@ def test_handle_500_response(self, mock_response):
(
self.LOGGER_NAME,
'WARNING',
"SanctionsFallback: DOWNLOAD FAILURE: Status code was: [500]"
"Sanctions SDNFallback: DOWNLOAD FAILURE: Status code was: [500]"
)
)
self.assertEqual("('CSV download url got an unsuccessful response code: ', 500)", str(e.exception))
Expand All @@ -105,7 +105,7 @@ def test_general_exception(self):
(
self.LOGGER_NAME,
'WARNING',
"SanctionsFallback: DOWNLOAD FAILURE: Exception occurred: [%s]" % self.ERROR_MESSAGE
"Sanctions SDNFallback: DOWNLOAD FAILURE: Exception occurred: [%s]" % self.ERROR_MESSAGE
)
)

Expand All @@ -123,7 +123,7 @@ def test_timeout_exception(self):
(
self.LOGGER_NAME,
'WARNING',
"SanctionsFallback: DOWNLOAD FAILURE: Timeout occurred trying to download SDN csv. Timeout threshold (in seconds): 5" # pylint: disable=line-too-long
"Sanctions SDNFallback: DOWNLOAD FAILURE: Timeout occurred trying to download SDN csv. Timeout threshold (in seconds): 5" # pylint: disable=line-too-long
)
)

Expand Down
54 changes: 27 additions & 27 deletions sanctions/apps/sanctions/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def __str__(self):
)


class SanctionsFallbackMetadata(TimeStampedModel):
class SDNFallbackMetadata(TimeStampedModel):
"""
Record metadata about the SDN fallback CSV file download.
This table is used to track the state of the SDN CSV file data that are currently
Expand Down Expand Up @@ -91,29 +91,29 @@ class SanctionsFallbackMetadata(TimeStampedModel):
@classmethod
def insert_new_sdn_fallback_metadata_entry(cls, file_checksum):
"""
Insert a new SanctionsFallbackMetadata entry if the new CSV differs from the current one.
Insert a new SDNFallbackMetadata entry if the new CSV differs from the current one.
If there is no current metadata entry, create a new one and log a warning.
Args:
file_checksum (str): Hash of the CSV content
Returns:
sanctions_fallback_metadata_entry (SanctionsFallbackMetadata): Instance of the current SanctionsFallbackMetadata class
sdn_fallback_metadata_entry (SDNFallbackMetadata): Instance of the current SDNFallbackMetadata class
or None if none exists
"""
now = datetime.utcnow()
try:
if file_checksum == SanctionsFallbackMetadata.objects.get(import_state='Current').file_checksum:
if file_checksum == SDNFallbackMetadata.objects.get(import_state='Current').file_checksum:
logger.info(
"SanctionsFallback: The CSV file has not changed, so skipping import. The file_checksum was %s",
"Sanctions SDNFallback: The CSV file has not changed, so skipping import. The file_checksum was %s",
file_checksum)
# Update download timestamp even though we're not importing this list
SanctionsFallbackMetadata.objects.filter(import_state="New").update(download_timestamp=now)
SDNFallbackMetadata.objects.filter(import_state="New").update(download_timestamp=now)
return None
except SanctionsFallbackMetadata.DoesNotExist:
logger.warning("SanctionsFallback: SanctionsFallbackMetadata has no record with import_state Current")
except SDNFallbackMetadata.DoesNotExist:
logger.warning("Sanctions SDNFallback: SDNFallbackMetadata has no record with import_state Current")

sanctions_fallback_metadata_entry = SanctionsFallbackMetadata.objects.create(
sanctions_fallback_metadata_entry = SDNFallbackMetadata.objects.create(
file_checksum=file_checksum,
download_timestamp=now,
)
Expand All @@ -133,22 +133,22 @@ def swap_all_states(cls):
2) There are any issues with the existing rows + updating them (e.g. a row with a
duplicate import_state is manually inserted into the table during the transaction)
"""
SanctionsFallbackMetadata._swap_state('Discard')
SanctionsFallbackMetadata._swap_state('Current')
SanctionsFallbackMetadata._swap_state('New')
SDNFallbackMetadata._swap_state('Discard')
SDNFallbackMetadata._swap_state('Current')
SDNFallbackMetadata._swap_state('New')

# After the above swaps happen:
# If there are 0 rows in the table, there cannot be a row in the 'Current' status.
# If there is 1 row in the table, it is expected to be in the 'Current' status
# (e.g. when the first file is added + just swapped).
# If there are 2 rows in the table, after the swaps, we expect to have one row in
# the 'Current' status and one row in the 'Discard' status.
if len(SanctionsFallbackMetadata.objects.all()) >= 1:
if len(SDNFallbackMetadata.objects.all()) >= 1:
try:
SanctionsFallbackMetadata.objects.get(import_state='Current')
except SanctionsFallbackMetadata.DoesNotExist:
SDNFallbackMetadata.objects.get(import_state='Current')
except SDNFallbackMetadata.DoesNotExist:
logger.warning(
"SanctionsFallback: Expected a row in the 'Current' import_state after swapping, but there are none.",
"Sanctions SDNFallback: Expected a row in the 'Current' import_state after swapping, but there are none.",
)
raise

Expand All @@ -160,7 +160,7 @@ def _swap_state(cls, import_state):
There can be at most one row in each import_state at a given time.
"""
try:
existing_metadata = SanctionsFallbackMetadata.objects.get(import_state=import_state)
existing_metadata = SDNFallbackMetadata.objects.get(import_state=import_state)
if import_state == 'Discard':
existing_metadata.delete()
else:
Expand All @@ -170,20 +170,20 @@ def _swap_state(cls, import_state):
existing_metadata.import_state = 'Discard'
existing_metadata.full_clean()
existing_metadata.save()
except SanctionsFallbackMetadata.DoesNotExist:
except SDNFallbackMetadata.DoesNotExist:
logger.info(
"SanctionsFallback: Cannot update import_state of %s row if there is no row in this state.",
"Sanctions SDNFallback: Cannot update import_state of %s row if there is no row in this state.",
import_state
)


class SanctionsFallbackData(models.Model):
class SDNFallbackData(models.Model):
"""
Model used to record and process one row received from SanctionsFallbackMetadata.
Model used to record and process one row received from SDNFallbackMetadata.
Fields:
sanctions_fallback_metadata (ForeignKey): Foreign Key field with the CSV import Primary Key
referenced in SanctionsFallbackMetadata.
sdn_fallback_metadata (ForeignKey): Foreign Key field with the CSV import Primary Key
referenced in SDNFallbackMetadata.
source (CharField): Origin of where the data comes from, since the CSV consolidates
export screening lists of the Departments of Commerce, State and the Treasury.
Expand All @@ -205,7 +205,7 @@ class SanctionsFallbackData(models.Model):
required field in billing information form, those records would not be matched in the API/fallback.
"""
history = HistoricalRecords()
sanctions_fallback_metadata = models.ForeignKey(SanctionsFallbackMetadata, on_delete=models.CASCADE)
sanctions_fallback_metadata = models.ForeignKey(SDNFallbackMetadata, on_delete=models.CASCADE)
source = models.CharField(default='', max_length=255, db_index=True)
sdn_type = models.CharField(default='', max_length=255, db_index=True)
names = models.TextField(default='')
Expand All @@ -218,10 +218,10 @@ def get_current_records_and_filter_by_source_and_type(cls, source, sdn_type):
Query the records that have 'Current' import state, and filter by source and sdn_type.
"""
try:
current_metadata = SanctionsFallbackMetadata.objects.get(import_state='Current')
current_metadata = SDNFallbackMetadata.objects.get(import_state='Current')

# The 'get' relies on the manage command having been run. If it fails, tell engineer what's needed
except SanctionsFallbackMetadata.DoesNotExist as fallback_metadata_no_exist:
except SDNFallbackMetadata.DoesNotExist as fallback_metadata_no_exist:
logger.warning(
"Sanctions SDNFallback: SDNFallbackMetadata is empty! Run this: "
"./manage.py populate_sdn_fallback_data_and_metadata"
Expand All @@ -230,4 +230,4 @@ def get_current_records_and_filter_by_source_and_type(cls, source, sdn_type):
'Sanctions SDNFallback empty error when calling checkSDNFallback, data is not yet populated.'
) from fallback_metadata_no_exist
query_params = {'source': source, 'sdn_fallback_metadata': current_metadata, 'sdn_type': sdn_type}
return SanctionsFallbackData.objects.filter(**query_params)
return SDNFallbackData.objects.filter(**query_params)
26 changes: 13 additions & 13 deletions sanctions/apps/sanctions/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@

import pycountry

from sanctions.apps.sanctions.models import SanctionsFallbackData, SanctionsFallbackMetadata
from sanctions.apps.sanctions.models import SDNFallbackData, SDNFallbackMetadata

logger = logging.getLogger(__name__)
COUNTRY_CODES = {country.alpha_2 for country in pycountry.countries}


def checkSDNFallback(name, city, country):
"""
Performs an SDN check against the SanctionsFallbackData.
Performs an SDN check against the SDNFallbackData.
First, filter the SanctionsFallbackData records by source, type and country.
First, filter the SDNFallbackData records by source, type and country.
Then, compare the provided name/city against each record and return whether we find a match.
The check uses the following properties:
1. Order of words doesn’t matter
Expand All @@ -32,7 +32,7 @@ def checkSDNFallback(name, city, country):
5. Capitalization doesn’t matter
"""
hit_count = 0
records = SanctionsFallbackData.get_current_records_and_filter_by_source_and_type(
records = SDNFallbackData.get_current_records_and_filter_by_source_and_type(
'Specially Designated Nationals (SDN) - Treasury Department', 'Individual'
)
records = records.filter(countries__contains=country)
Expand Down Expand Up @@ -125,27 +125,27 @@ def extract_country_information(addresses, ids):

def populate_sdn_fallback_metadata(sdn_csv_string):
"""
Insert a new SanctionsFallbackMetadata entry if the new csv differs from the current one
Insert a new SDNFallbackMetadata entry if the new csv differs from the current one
Args:
sdn_csv_string (bytes): Bytes of the sdn csv
Returns:
sdn_fallback_metadata_entry (SanctionsFallbackMetadata): Instance of the current SanctionsFallbackMetadata class
sdn_fallback_metadata_entry (SDNFallbackMetadata): Instance of the current SDNFallbackMetadata class
or None if none exists
"""
file_checksum = hashlib.sha256(sdn_csv_string.encode('utf-8')).hexdigest()
metadata_entry = SanctionsFallbackMetadata.insert_new_sdn_fallback_metadata_entry(file_checksum)
metadata_entry = SDNFallbackMetadata.insert_new_sdn_fallback_metadata_entry(file_checksum)
return metadata_entry


def populate_sdn_fallback_data(sdn_csv_string, metadata_entry):
"""
Process CSV data and create SanctionsFallbackData records
Process CSV data and create SDNFallbackData records
Args:
sdn_csv_string (str): String of the sdn csv
metadata_entry (SanctionsFallbackMetadata): Instance of the current SanctionsFallbackMetadata class
metadata_entry (SDNFallbackMetadata): Instance of the current SDNFallbackMetadata class
"""
sdn_csv_reader = csv.DictReader(io.StringIO(sdn_csv_string))
processed_records = []
Expand All @@ -157,7 +157,7 @@ def populate_sdn_fallback_data(sdn_csv_string, metadata_entry):
processed_names = ' '.join(process_text(' '.join(filter(None, [names, alt_names]))))
processed_addresses = ' '.join(process_text(addresses))
countries = extract_country_information(addresses, ids)
processed_records.append(SanctionsFallbackData(
processed_records.append(SDNFallbackData(
sanctions_fallback_metadata=metadata_entry,
source=sdn_source,
sdn_type=sdn_type,
Expand All @@ -166,13 +166,13 @@ def populate_sdn_fallback_data(sdn_csv_string, metadata_entry):
countries=countries
))
# Bulk create should be more efficient for a few thousand records without needing to use SQL directly.
SanctionsFallbackData.objects.bulk_create(processed_records)
SDNFallbackData.objects.bulk_create(processed_records)


def populate_sdn_fallback_data_and_metadata(sdn_csv_string):
"""
1. Create the SanctionsFallbackMetadata entry
2. Populate the SanctionsFallbackData from the csv
1. Create the SDNFallbackMetadata entry
2. Populate the SDNFallbackData from the csv
Args:
sdn_csv_string (str): String of the sdn csv
Expand Down

0 comments on commit 86d50e6

Please sign in to comment.