From 3f54e5662299ffff014bff7f779ed67954bb5a28 Mon Sep 17 00:00:00 2001 From: "mark.j0hnst0n" Date: Tue, 21 May 2024 14:31:52 +0100 Subject: [PATCH 1/9] renamed item_list_codes field to denial_cle in db --- .../0026_rename_item_list_codes_to_denial_cle.py | 15 +++++++++++++++ api/external_data/models.py | 4 ++-- 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 api/external_data/migrations/0026_rename_item_list_codes_to_denial_cle.py diff --git a/api/external_data/migrations/0026_rename_item_list_codes_to_denial_cle.py b/api/external_data/migrations/0026_rename_item_list_codes_to_denial_cle.py new file mode 100644 index 0000000000..863945b344 --- /dev/null +++ b/api/external_data/migrations/0026_rename_item_list_codes_to_denial_cle.py @@ -0,0 +1,15 @@ +# Generated by Django 4.2.13 on 2024-05-21 13:17 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("external_data", "0025_entity_type_empty_strings"), + ] + + operations = [ + migrations.RenameField("Denial", "item_list_codes", "denial_cle"), + migrations.RenameField("DenialEntity", "item_list_codes", "denial_cle"), + ] diff --git a/api/external_data/models.py b/api/external_data/models.py index 4286bdeafd..a86dd19a05 100644 --- a/api/external_data/models.py +++ b/api/external_data/models.py @@ -18,7 +18,7 @@ class Denial(TimestampableModel): notifying_government = models.TextField( help_text="The authority that raised the denial", null=True, blank=True, default="" ) - item_list_codes = models.TextField("The codes of the items being denied", null=True, blank=True, default="") + denial_cle = models.TextField("The codes of the items being denied", null=True, blank=True, default="") item_description = models.TextField("The description of the item being denied", null=True, blank=True, default="") end_use = models.TextField(null=True, blank=True, default="") is_revoked = models.BooleanField(default=False, help_text="If true do not include in search results") @@ -48,7 +48,7 @@ class DenialEntity(TimestampableModel): help_text="The authority that raised the denial", blank=True, default="", null=True ) country = models.TextField(blank=True, default="", null=True) - item_list_codes = models.TextField("The codes of the items being denied", blank=True, default="", null=True) + denial_cle = models.TextField("The codes of the items being denied", blank=True, default="", null=True) item_description = models.TextField("The description of the item being denied", blank=True, default="", null=True) consignee_name = models.TextField(blank=True, default="", null=True) end_use = models.TextField(blank=True, default="", null=True) From 55aaf4eb10b54082450084d4da13ae7d26616674 Mon Sep 17 00:00:00 2001 From: "mark.j0hnst0n" Date: Tue, 21 May 2024 14:33:47 +0100 Subject: [PATCH 2/9] amended serialiser to use new field name --- api/external_data/serializers.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/external_data/serializers.py b/api/external_data/serializers.py index 43ed0c9cd5..d03d0fc84c 100644 --- a/api/external_data/serializers.py +++ b/api/external_data/serializers.py @@ -24,7 +24,7 @@ class Meta: "created_by_user", "regime_reg_ref", "notifying_government", - "item_list_codes", + "denial_cle", "item_description", "end_use", "is_revoked", @@ -42,7 +42,7 @@ class Meta: class DenialEntitySerializer(serializers.ModelSerializer): entity_type = KeyValueChoiceField(choices=models.DenialEntityType.choices, required=False) regime_reg_ref = serializers.CharField(source="denial.regime_reg_ref", required=False) - item_list_codes = serializers.CharField(source="denial.item_list_codes", required=False) + denial_cle = serializers.CharField(source="denial.denial_cle", required=False) notifying_government = serializers.CharField(source="denial.notifying_government", required=False) item_description = serializers.CharField(source="denial.item_description", required=False) end_use = serializers.CharField(source="denial.end_use", required=False) @@ -61,7 +61,7 @@ class Meta: "regime_reg_ref", "notifying_government", "country", - "item_list_codes", + "denial_cle", "item_description", "end_use", "data", @@ -239,7 +239,7 @@ class DenialSearchSerializer(DocumentSerializer): entity_type = KeyValueChoiceField(choices=models.DenialEntityType.choices, required=False) regime_reg_ref = serializers.ReadOnlyField(source="denial.regime_reg_ref") reference = serializers.ReadOnlyField(source="denial.reference") - item_list_codes = serializers.ReadOnlyField(source="denial.item_list_codes") + denial_cle = serializers.ReadOnlyField(source="denial.denial_cle") item_description = serializers.ReadOnlyField(source="denial.item_description") end_use = serializers.ReadOnlyField(source="denial.end_use") name = serializers.SerializerMethodField() From 048fc9b45304e02e78509b3ab345453e3b0da816 Mon Sep 17 00:00:00 2001 From: "mark.j0hnst0n" Date: Tue, 21 May 2024 15:41:51 +0100 Subject: [PATCH 3/9] updated elasticsearch index with new field --- api/external_data/documents.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/external_data/documents.py b/api/external_data/documents.py index 0d542a8e62..3291c8e2b3 100644 --- a/api/external_data/documents.py +++ b/api/external_data/documents.py @@ -104,8 +104,8 @@ class DenialEntityDocument(Document): "raw": fields.KeywordField(), }, ), - "item_list_codes": fields.TextField( - attr="item_list_codes", + "denial_cle": fields.TextField( + attr="denial_cle", fields={ "raw": fields.KeywordField(), }, From 733d90b02f0fac1b6f38c3162a1b60fe8960a73d Mon Sep 17 00:00:00 2001 From: "mark.j0hnst0n" Date: Tue, 21 May 2024 15:42:15 +0100 Subject: [PATCH 4/9] updated test data --- api/applications/tests/factories.py | 2 +- .../tests/test_external_data_views.py | 2 +- api/external_data/serializers.py | 2 +- api/external_data/tests/denial_invalid.csv | 2 +- api/external_data/tests/test_views.py | 28 +++++++++---------- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/api/applications/tests/factories.py b/api/applications/tests/factories.py index 67f2b3b129..089edc4a5c 100644 --- a/api/applications/tests/factories.py +++ b/api/applications/tests/factories.py @@ -123,7 +123,7 @@ class DenialMatchFactory(factory.django.DjangoModelFactory): address = factory.LazyAttribute(lambda n: faker.address()) notifying_government = factory.LazyAttribute(lambda n: faker.country()) country = factory.LazyAttribute(lambda n: faker.country()) - item_list_codes = factory.LazyAttribute(lambda n: faker.word()) + denial_cle = factory.LazyAttribute(lambda n: faker.word()) item_description = factory.LazyAttribute(lambda n: faker.sentence()) consignee_name = factory.LazyAttribute(lambda n: faker.name()) end_use = factory.LazyAttribute(lambda n: faker.sentence()) diff --git a/api/data_workspace/tests/test_external_data_views.py b/api/data_workspace/tests/test_external_data_views.py index 1265b9102b..2720fa387f 100644 --- a/api/data_workspace/tests/test_external_data_views.py +++ b/api/data_workspace/tests/test_external_data_views.py @@ -28,7 +28,7 @@ def test_denial_view(self): "reference", "notifying_government", "country", - "item_list_codes", + "denial_cle", "item_description", "end_use", "data", diff --git a/api/external_data/serializers.py b/api/external_data/serializers.py index d03d0fc84c..c27dd310a5 100644 --- a/api/external_data/serializers.py +++ b/api/external_data/serializers.py @@ -116,7 +116,7 @@ class DenialFromCSVFileSerializer(serializers.Serializer): "reference", "regime_reg_ref", "notifying_government", - "item_list_codes", + "denial_cle", "item_description", "end_use", "reason_for_refusal", diff --git a/api/external_data/tests/denial_invalid.csv b/api/external_data/tests/denial_invalid.csv index 123dc27ebf..ca629eed4b 100644 --- a/api/external_data/tests/denial_invalid.csv +++ b/api/external_data/tests/denial_invalid.csv @@ -1,4 +1,4 @@ -name,address,notifying_government,country,item_list_codes,item_description,consignee_name,end_use,end_user_flag,consignee_flag,other_role +name,address,notifying_government,country,denial_cle,item_description,consignee_name,end_use,end_user_flag,consignee_flag,other_role Jim Example,123 fake street,France,Germany,ABC123,Foo,Fred Food,used in car,true,true,false Jak Example,123 fake street,France,Germany,ABC123,Foo,Fred Food,used in car,false,true,false Bob Example,123 fake street,France,Germany,ABC123,Foo,Fred Food,used in car,false,false,true diff --git a/api/external_data/tests/test_views.py b/api/external_data/tests/test_views.py index b14a1d23e4..bcac026a29 100644 --- a/api/external_data/tests/test_views.py +++ b/api/external_data/tests/test_views.py @@ -15,7 +15,7 @@ "reference", "regime_reg_ref", "notifying_government", - "item_list_codes", + "denial_cle", "item_description", "end_use", "reason_for_refusal", @@ -79,7 +79,7 @@ def test_create_success(self): "reference": "DN2000/0000", "regime_reg_ref": "AB-CD-EF-000", "notifying_government": "Country Name", - "item_list_codes": "0A00100", + "denial_cle": "0A00100", "item_description": "Medium Size Widget", "end_use": "Used in industry", "reason_for_refusal": "Risk of outcome", @@ -88,7 +88,7 @@ def test_create_success(self): "reference": "DN2000/0010", "regime_reg_ref": "AB-CD-EF-300", "notifying_government": "Country Name 3", - "item_list_codes": "0A00201", + "denial_cle": "0A00201", "item_description": "Unspecified Size Widget", "end_use": "Used in other industry", "reason_for_refusal": "Risk of outcome 3", @@ -97,7 +97,7 @@ def test_create_success(self): "reference": "", "regime_reg_ref": "AB-XY-EF-900", "notifying_government": "Example Country", - "item_list_codes": "catch all", + "denial_cle": "catch all", "item_description": "Extra Large Size Widget", "end_use": "Used in unknown industry", "reason_for_refusal": "Risk of outcome 4", @@ -106,7 +106,7 @@ def test_create_success(self): "reference": "DN3000/0000", "regime_reg_ref": "AB-CD-EF-100", "notifying_government": "Country Name 2", - "item_list_codes": "0A00200", + "denial_cle": "0A00200", "item_description": "Large Size Widget", "end_use": "Used in other industry", "reason_for_refusal": "Risk of outcome 2", @@ -115,7 +115,7 @@ def test_create_success(self): "reference": "DN4000/0000", "regime_reg_ref": "AB-CD-EF-200", "notifying_government": "United Kingdom", - "item_list_codes": "0A00300", + "denial_cle": "0A00300", "item_description": "Large Size Widget", "end_use": "Used in other industry", "reason_for_refusal": "Risk of outcome 2", @@ -136,7 +136,7 @@ def test_create_error_missing_required_headers(self): def test_create_and_set_entity_type(self): url = reverse("external_data:denial-list") content = """ - reference,regime_reg_ref,name,address,notifying_government,country,item_list_codes,item_description,end_use,reason_for_refusal,entity_type + reference,regime_reg_ref,name,address,notifying_government,country,denial_cle,item_description,end_use,reason_for_refusal,entity_type DN2000/0000,AB-CD-EF-000,Organisation Name,"1000 Street Name, City Name",Country Name,Country Name,0A00100,Medium Size Widget,Used in industry,Risk of outcome,end_user DN2000/0010,AB-CD-EF-300,Organisation Name 3,"2001 Street Name, City Name 3",Country Name 3,Country Name 3,0A00201,Unspecified Size Widget,Used in other industry,Risk of outcome 3,consignee DN2010/0001,AB-XY-EF-900,The Widget Company,"2 Example Road, Example City",Example Country,Country Name X,"catch all",Extra Large Size Widget,Used in unknown industry,Risk of outcome 4,third_party @@ -183,7 +183,7 @@ def test_create_and_set_entity_type(self): def test_update_success(self): url = reverse("external_data:denial-list") content = """ - reference,regime_reg_ref,name,address,notifying_government,country,item_list_codes,item_description,end_use,reason_for_refusal,entity_type + reference,regime_reg_ref,name,address,notifying_government,country,denial_cle,item_description,end_use,reason_for_refusal,entity_type DN2000/0000,AB-CD-EF-000,Organisation Name,"1000 Street Name, City Name",Country Name,Country Name,0A00100,Medium Size Widget,Used in industry,Risk of outcome,end_user """ @@ -199,7 +199,7 @@ def test_update_success(self): "reference": "DN2000/0000", "regime_reg_ref": "AB-CD-EF-000", "notifying_government": "Country Name", - "item_list_codes": "0A00100", + "denial_cle": "0A00100", "item_description": "Medium Size Widget", "end_use": "Used in industry", "reason_for_refusal": "Risk of outcome", @@ -222,7 +222,7 @@ def test_update_success(self): ], ) updated_content = """ - reference,regime_reg_ref,name,address,notifying_government,country,item_list_codes,item_description,end_use,reason_for_refusal,entity_type + reference,regime_reg_ref,name,address,notifying_government,country,denial_cle,item_description,end_use,reason_for_refusal,entity_type DN2000/0000,AB-CD-EF-000,Organisation Name,"1000 Street Name, City Name",Country Name 2,Country Name 2,0A00200,Medium Size Widget 2, Used in industry 2,Risk of outcome 2,end_user """ response = self.client.post(url, {"csv_file": updated_content}, **self.gov_headers) @@ -236,7 +236,7 @@ def test_update_success(self): "reference": "DN2000/0000", "regime_reg_ref": "AB-CD-EF-000", "notifying_government": "Country Name 2", - "item_list_codes": "0A00200", + "denial_cle": "0A00200", "item_description": "Medium Size Widget 2", "end_use": "Used in industry 2", "reason_for_refusal": "Risk of outcome 2", @@ -261,7 +261,7 @@ def test_update_success(self): def test_create_error_serializer_errors(self): url = reverse("external_data:denial-list") - content = """reference,regime_reg_ref,name,address,notifying_government,country,item_list_codes,item_description,end_use,reason_for_refusal,entity_type + content = """reference,regime_reg_ref,name,address,notifying_government,country,denial_cle,item_description,end_use,reason_for_refusal,entity_type DN2000/0000,,Organisation Name,"1000 Street Name, City Name",Country Name,Country Name,0A00100,Medium Size Widget,Used in industry,Risk of outcome,end_user """ response = self.client.post(url, {"csv_file": content}, **self.gov_headers) @@ -300,7 +300,7 @@ def test_create_validation_error_duplicate(self): def test_create_sanitise_csv(self): url = reverse("external_data:denial-list") content = """ - reference,regime_reg_ref,name,address,notifying_government,country,item_list_codes,item_description,end_use,reason_for_refusal,entity_type + reference,regime_reg_ref,name,address,notifying_government,country,denial_cle,item_description,end_use,reason_for_refusal,entity_type DN2000/0000,AB-CD-EF-000,Organisation Name,"",Country Name,Country Name,0A00100,Medium Size Widget,Used in industry,Risk of outcome,end_user """ response = self.client.post(url, {"csv_file": content}, **self.gov_headers) @@ -347,7 +347,7 @@ def test_populate_denial_entity_objects(self, page_query): "address": "2000 Street Name, City Name 2", "country": "Country Name 2", "item_description": "Large Size Widget", - "item_list_codes": "0A00200", + "denial_cle": "0A00200", "name": "Organisation Name XYZ", "notifying_government": "Country Name 2", "end_use": "Used in other industry", From 93621d9e7becccfcb87f25c7513cccc7ec50ed28 Mon Sep 17 00:00:00 2001 From: "mark.j0hnst0n" Date: Tue, 21 May 2024 15:42:33 +0100 Subject: [PATCH 5/9] updated test data --- api/external_data/tests/denial_valid.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/external_data/tests/denial_valid.csv b/api/external_data/tests/denial_valid.csv index 0065bc95dd..546972d534 100644 --- a/api/external_data/tests/denial_valid.csv +++ b/api/external_data/tests/denial_valid.csv @@ -1,4 +1,4 @@ -reference,regime_reg_ref,name,address,notifying_government,country,item_list_codes,item_description,end_use,reason_for_refusal,entity_type +reference,regime_reg_ref,name,address,notifying_government,country,denial_cle,item_description,end_use,reason_for_refusal,entity_type DN2000/0000,AB-CD-EF-000,Organisation Name,"1000 Street Name, City Name",Country Name,Country Name,0A00100,Medium Size Widget,Used in industry,Risk of outcome,end_user DN2000/0010,AB-CD-EF-300,Organisation Name 3,"2001 Street Name, City Name 3",Country Name 3,Country Name 3,0A00201,Unspecified Size Widget,Used in other industry,Risk of outcome 3,consignee ,AB-XY-EF-900,The Widget Company,"2 Example Road, Example City",Example Country,Country Name X,"catch all",Extra Large Size Widget,Used in unknown industry,Risk of outcome 4,end_user From efcb840246ce047a2b3731fb88c987469111b757 Mon Sep 17 00:00:00 2001 From: "mark.j0hnst0n" Date: Tue, 21 May 2024 15:42:54 +0100 Subject: [PATCH 6/9] changed ingest denials and swagger docs --- api/external_data/management/commands/ingest_denials.py | 2 +- .../management/commands/tests/test_ingest_denials.py | 6 +++--- docs/swagger.yaml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/api/external_data/management/commands/ingest_denials.py b/api/external_data/management/commands/ingest_denials.py index d3a6847a2c..c56bea939d 100644 --- a/api/external_data/management/commands/ingest_denials.py +++ b/api/external_data/management/commands/ingest_denials.py @@ -39,7 +39,7 @@ class Command(BaseCommand): "reference", "regime_reg_ref", "notifying_government", - "item_list_codes", + "denial_cle", "item_description", "end_use", "reason_for_refusal", diff --git a/api/external_data/management/commands/tests/test_ingest_denials.py b/api/external_data/management/commands/tests/test_ingest_denials.py index d9a3fe5d02..de57376b36 100644 --- a/api/external_data/management/commands/tests/test_ingest_denials.py +++ b/api/external_data/management/commands/tests/test_ingest_denials.py @@ -28,7 +28,7 @@ def json_file_data(): "address": "somewhere\nmid\nlatter\nCairo", "notifying_government": "United Kingdom", "country": "United States", - "item_list_codes": "123456", + "denial_cle": "123456", "item_description": "phone", "end_use": "locating phone", "end_user_flag": "true", @@ -43,7 +43,7 @@ def json_file_data(): "address": "no address given", "notifying_government": "Germany", "country": "France", - "item_list_codes": "12345\/2009", + "denial_cle": "12345\/2009", "item_description": "testing machine", "end_use": "For teaching purposes", "end_user_flag": "false", @@ -98,7 +98,7 @@ def test_populate_denials(mock_json_content, mock_delete_file, json_file_data): assert denial_record.address == "somewhere\nmid\nlatter\nCairo" assert denial_record.denial.notifying_government == "United Kingdom" assert denial_record.country == "United States" - assert denial_record.denial.item_list_codes == "123456" + assert denial_record.denial.denial_cle == "123456" assert denial_record.denial.item_description == "phone" assert denial_record.denial.end_use == "locating phone" assert denial_record.denial.regime_reg_ref == "12" diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 878eb53310..08d1cfb74e 100755 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -8900,7 +8900,7 @@ components: description: The authority that raised the denial final_destination: type: string - item_list_codes: + denial_cle: type: string item_description: type: string @@ -8922,7 +8922,7 @@ components: - reference - notifying_government - final_destination - - item_list_codes + - denial_cle - item_description - consignee_name - end_use From 5e1385be4a6b00873a95a08f14818f5e69b7da44 Mon Sep 17 00:00:00 2001 From: "mark.j0hnst0n" Date: Tue, 21 May 2024 16:05:10 +0100 Subject: [PATCH 7/9] update dev merge to use renamed field --- api/external_data/documents.py | 2 +- api/external_data/serializers.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/api/external_data/documents.py b/api/external_data/documents.py index 6523ebb06f..887f4d0ceb 100644 --- a/api/external_data/documents.py +++ b/api/external_data/documents.py @@ -89,7 +89,7 @@ class DenialEntityDocument(Document): is_revoked = fields.BooleanField(attr="denial.is_revoked") notifying_government = fields.KeywordField(attr="denial.notifying_government") - item_list_codes = fields.TextField(attr="denial.item_list_codes") + denial_cle = fields.TextField(attr="denial.denial_cle") denial = fields.ObjectField( attr="denial", properties={ diff --git a/api/external_data/serializers.py b/api/external_data/serializers.py index 57375291c0..6728c9a147 100644 --- a/api/external_data/serializers.py +++ b/api/external_data/serializers.py @@ -243,7 +243,7 @@ class DenialSearchSerializer(DocumentSerializer): end_use = serializers.ReadOnlyField(source="denial.end_use") name = serializers.SerializerMethodField() address = serializers.SerializerMethodField() - item_list_codes = serializers.SerializerMethodField() + denial_cle = serializers.SerializerMethodField() class Meta: document = documents.DenialEntityDocument @@ -253,7 +253,7 @@ class Meta: "country", "name", "notifying_government", - "item_list_codes", + "denial_cle", ) def get_entity_type(self, obj): @@ -265,8 +265,8 @@ def get_name(self, obj): def get_address(self, obj): return self.get_highlighted_field(obj, "address") - def get_item_list_codes(self, obj): - return self.get_highlighted_field(obj, "item_list_codes") + def get_denial_cle(self, obj): + return self.get_highlighted_field(obj, "denial_cle") def get_highlighted_field(self, obj, field_name): if hasattr(obj.meta, "highlight") and obj.meta.highlight.to_dict().get(field_name): From edfb07c70e149f65372bd66ddb261b1c0d5da66d Mon Sep 17 00:00:00 2001 From: "mark.j0hnst0n" Date: Tue, 21 May 2024 16:31:50 +0100 Subject: [PATCH 8/9] amend test data to use new field --- api/external_data/tests/test_views.py | 4 ++-- api/external_data/views.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/external_data/tests/test_views.py b/api/external_data/tests/test_views.py index 83d9bfd5d6..d2a2f24b83 100644 --- a/api/external_data/tests/test_views.py +++ b/api/external_data/tests/test_views.py @@ -364,7 +364,7 @@ def test_populate_denial_entity_objects(self, page_query): @parameterized.expand( [ ("name:Organisation Name XYZ", {"name": "Organisation Name XYZ"}), - ("item_list_codes:0A00200", {"item_list_codes": "0A00200"}), + ("denial_cle:0A00200", {"denial_cle": "0A00200"}), ("address:2000", {"address": "2000 Street Name, City Name 2"}), ] ) @@ -396,7 +396,7 @@ def test_search_highlighting(self, search_query, expected_result): ({"search": "address:Street Name"}, 3), ({"search": "address:Example"}, 1), ({"search": "name:UK Issued"}, 0), - ({"search": "item_list_codes:catch all"}, 1), + ({"search": "denial_cle:catch all"}, 1), ] ) def test_denial_entity_search(self, query, quantity): diff --git a/api/external_data/views.py b/api/external_data/views.py index b7c6fbf99c..c431dad38f 100644 --- a/api/external_data/views.py +++ b/api/external_data/views.py @@ -47,7 +47,7 @@ class DenialSearchView(DocumentViewSet): filter_backends.FilteringFilterBackend, filter_backends.HighlightBackend, ] - search_fields = ["name", "address", "item_list_codes"] + search_fields = ["name", "address", "denial_cle"] filter_fields = { "country": { "enabled": True, @@ -70,7 +70,7 @@ class DenialSearchView(DocumentViewSet): "post_tags": [""], }, }, - "item_list_codes": { + "denial_cle": { "enabled": True, "options": { "pre_tags": [""], From fa3c4ef6cbce29fe0efee356d9a773f507d8ee5a Mon Sep 17 00:00:00 2001 From: Kevin Carrogan Date: Thu, 23 May 2024 15:11:40 +0100 Subject: [PATCH 9/9] Handle shift to BST when running backup document healthcheck --- api/document_data/health_checks.py | 6 +-- api/document_data/tests/test_health_checks.py | 42 +++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/api/document_data/health_checks.py b/api/document_data/health_checks.py index 735bede14a..474fe57500 100644 --- a/api/document_data/health_checks.py +++ b/api/document_data/health_checks.py @@ -63,10 +63,10 @@ def check_status(self): # If the date is in the past then it means the task that should have # run previously hasn't for some reason. backup_schedule = app.conf.beat_schedule[BACKUP_DOCUMENT_DATA_SCHEDULE_NAME]["schedule"] - next_run_delta = backup_schedule.remaining_estimate(latest_backup_log.ended_at) - now = timezone.now() + next_run_delta = backup_schedule.remaining_estimate(timezone.localtime(latest_backup_log.ended_at)) + now = timezone.localtime() next_run = now + next_run_delta - if next_run < timezone.now(): + if next_run < now: raise BackupDocumentDataHealthCheckException("Backup not run today") # If we manage to get here we know that the task was run recently and diff --git a/api/document_data/tests/test_health_checks.py b/api/document_data/tests/test_health_checks.py index ed66605eef..f4edb48291 100644 --- a/api/document_data/tests/test_health_checks.py +++ b/api/document_data/tests/test_health_checks.py @@ -1,4 +1,5 @@ import celery +import datetime import uuid from unittest.mock import patch @@ -262,3 +263,44 @@ def test_backup_document_data_files_created_during_backup_ignored(self, mock_app ].remaining_estimate mock_remaining_estimate.return_value = timezone.timedelta(hours=16) self.assertIsNone(self.backend.check_status()) + + @parameterized.expand( + [ + ("2024-05-22 01:49:00", -1), + ("2024-05-22 02:55:00", -1), + ("2024-05-22 14:35:00", -1), + ] + ) + def test_bst_handled_correctly(self, check_status_time, tz_offset): + task_id = uuid.uuid4() + + # We run the cron task at 2am but celery/django correctly handles our + # timezone changes so that this shifts to 1am in UTC when we are in BST + # We need to make sure that the healthcheck takes this into account + started_at = timezone.datetime( + 2024, + 5, + 22, + 1, + 0, + 0, + tzinfo=timezone.timezone.utc, + ) + ended_at = timezone.datetime( + 2024, + 5, + 22, + 1, + 50, + 52, + tzinfo=timezone.timezone.utc, + ) + backup_log = BackupLog.objects.create( + ended_at=ended_at, + task_id=task_id, + ) + backup_log.started_at = started_at + backup_log.save() + + with freeze_time(check_status_time, tz_offset=tz_offset): + self.assertIsNone(self.backend.check_status())