From efc1d36ca51fe81f38964517afb805fffacae4b5 Mon Sep 17 00:00:00 2001 From: HAKIZIMANA Franck Date: Mon, 16 Sep 2024 17:34:51 +0200 Subject: [PATCH 1/4] Reorder lines so that summary table has the correct order to match VARs with their PO --- plugins/polio/api/vaccines/supply_chain.py | 44 +++++++++++++++++++--- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/plugins/polio/api/vaccines/supply_chain.py b/plugins/polio/api/vaccines/supply_chain.py index be84a0c6c7..9a0731cbb3 100644 --- a/plugins/polio/api/vaccines/supply_chain.py +++ b/plugins/polio/api/vaccines/supply_chain.py @@ -401,9 +401,21 @@ class Meta: # comma separated list of all def get_po_numbers(self, obj): pre_alerts = obj.vaccineprealert_set.all().order_by("-estimated_arrival_time") + if not pre_alerts: return "" - return ", ".join([pre_alert.po_number for pre_alert in pre_alerts]) + + po_numbers = [] + for pre_alert in pre_alerts: + matching_po_numbers = obj.vaccinearrivalreport_set.filter(po_number=pre_alert.po_number).order_by( + "-arrival_report_date" + ) + if matching_po_numbers: + for match in matching_po_numbers: + po_numbers.append(str(match.po_number)) + else: + po_numbers.append(pre_alert.po_number) + return ",".join(po_numbers) def get_start_date(self, obj): rounds = obj.rounds.all() @@ -423,16 +435,36 @@ def get_doses_shipped(self, obj): # Comma Separated List of all estimated arrival times def get_eta(self, obj): pre_alerts = obj.vaccineprealert_set.all().order_by("-estimated_arrival_time") + if not pre_alerts: return "" - return ", ".join([str(pre_alert.estimated_arrival_time) for pre_alert in pre_alerts]) + + estimated_arrival_dates = [] + for pre_alert in pre_alerts: + matching_dates = obj.vaccinearrivalreport_set.filter(po_number=pre_alert.po_number).order_by( + "-arrival_report_date" + ) + if matching_dates: + for match in matching_dates: + estimated_arrival_dates.append(str(pre_alert.estimated_arrival_time)) + else: + estimated_arrival_dates.append(str(pre_alert.estimated_arrival_time)) + return ",".join(estimated_arrival_dates) # Comma Separated List of all arrival report dates def get_var(self, obj): - arrival_reports = obj.vaccinearrivalreport_set.all().order_by("-arrival_report_date") - if not arrival_reports: - return "" - return ", ".join([str(report.arrival_report_date) for report in arrival_reports]) + pre_alerts = obj.vaccineprealert_set.all().order_by("-estimated_arrival_time") + arrival_report_dates = [] + for pre_alert in pre_alerts: + matching_arrival_report = obj.vaccinearrivalreport_set.filter(po_number=pre_alert.po_number).order_by( + "-arrival_report_date" + ) + if matching_arrival_report: + for match in matching_arrival_report: + arrival_report_dates.append(str(match.arrival_report_date)) + else: + arrival_report_dates.append("") + return ",".join(arrival_report_dates) class VRFCustomOrderingFilter(filters.BaseFilterBackend): From 83ef5ce4743a790685157d487625d3ace4b60723 Mon Sep 17 00:00:00 2001 From: HAKIZIMANA Franck Date: Tue, 17 Sep 2024 09:04:36 +0200 Subject: [PATCH 2/4] fix python tests --- plugins/polio/tests/test_vaccine_supply_chain.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/plugins/polio/tests/test_vaccine_supply_chain.py b/plugins/polio/tests/test_vaccine_supply_chain.py index c479f14848..26d2654fa5 100644 --- a/plugins/polio/tests/test_vaccine_supply_chain.py +++ b/plugins/polio/tests/test_vaccine_supply_chain.py @@ -663,13 +663,23 @@ def test_var_field_ordered_reversely(self): request_form = pm.VaccineRequestForm.objects.first() # Create multiple VaccineArrivalReport instances with different dates + po_numbers = ["777777-1", "777777-2", "777777-3"] + dates = ["2024-04-20", "2024-04-19", "2024-04-18"] - for date in dates: + for i, date in enumerate(dates): pm.VaccineArrivalReport.objects.create( request_form=request_form, + po_number=po_numbers[i], arrival_report_date=datetime.datetime.strptime(date, "%Y-%m-%d").date(), doses_received=1000, ) + pm.VaccinePreAlert.objects.create( + date_pre_alert_reception=datetime.datetime.strptime(date, "%Y-%m-%d").date(), + request_form=request_form, + po_number=po_numbers[i], + estimated_arrival_time=datetime.datetime.strptime(date, "%Y-%m-%d").date(), + doses_shipped=100, + ) # Make a GET request to the list endpoint with ordering by start_date response = self.client.get( @@ -680,5 +690,6 @@ def test_var_field_ordered_reversely(self): self.assertEqual(response.status_code, 200) # Verify that the "var" field is a comma-separated list of dates in reverse order - expected_var = ", ".join(dates) + expected_var = ",".join(dates) + print(response.data["results"]) self.assertEqual(response.data["results"][1]["var"], expected_var) From f281249e5b177bcf4a4b63ad8ce0f703e6271e8a Mon Sep 17 00:00:00 2001 From: HAKIZIMANA Franck Date: Tue, 17 Sep 2024 09:40:13 +0200 Subject: [PATCH 3/4] reduce the number of queries --- plugins/polio/api/vaccines/supply_chain.py | 57 ++++++++++++---------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/plugins/polio/api/vaccines/supply_chain.py b/plugins/polio/api/vaccines/supply_chain.py index 9a0731cbb3..925f158fa0 100644 --- a/plugins/polio/api/vaccines/supply_chain.py +++ b/plugins/polio/api/vaccines/supply_chain.py @@ -398,21 +398,32 @@ class Meta: "updated_at", ] - # comma separated list of all - def get_po_numbers(self, obj): + def get_prefetched_data(self, obj): + # Prefetch vaccineprea_lert and vaccinearrival_report to reduce the number of queries in the DB pre_alerts = obj.vaccineprealert_set.all().order_by("-estimated_arrival_time") + arrival_reports = obj.vaccinearrivalreport_set.filter(po_number__in=[p.po_number for p in pre_alerts]).order_by( + "-arrival_report_date" + ) + + # Get arrival reports matching by po_number + arrival_report_matching = {} + for report in arrival_reports: + if report.po_number not in arrival_report_matching: + arrival_report_matching[report.po_number] = [] + arrival_report_matching[report.po_number].append(report) - if not pre_alerts: - return "" + return pre_alerts, arrival_report_matching + + # Comma separated list of all + def get_po_numbers(self, obj): + pre_alerts, arrival_report_matching = self.get_prefetched_data(obj) po_numbers = [] for pre_alert in pre_alerts: - matching_po_numbers = obj.vaccinearrivalreport_set.filter(po_number=pre_alert.po_number).order_by( - "-arrival_report_date" - ) - if matching_po_numbers: - for match in matching_po_numbers: - po_numbers.append(str(match.po_number)) + matching_reports = arrival_report_matching.get(pre_alert.po_number, []) + if matching_reports: + for report in matching_reports: + po_numbers.append(str(report.po_number)) else: po_numbers.append(pre_alert.po_number) return ",".join(po_numbers) @@ -434,18 +445,13 @@ def get_doses_shipped(self, obj): # Comma Separated List of all estimated arrival times def get_eta(self, obj): - pre_alerts = obj.vaccineprealert_set.all().order_by("-estimated_arrival_time") - - if not pre_alerts: - return "" + pre_alerts, arrival_report_matching = self.get_prefetched_data(obj) estimated_arrival_dates = [] for pre_alert in pre_alerts: - matching_dates = obj.vaccinearrivalreport_set.filter(po_number=pre_alert.po_number).order_by( - "-arrival_report_date" - ) - if matching_dates: - for match in matching_dates: + matching_reports = arrival_report_matching.get(pre_alert.po_number, []) + if matching_reports: + for _ in matching_reports: estimated_arrival_dates.append(str(pre_alert.estimated_arrival_time)) else: estimated_arrival_dates.append(str(pre_alert.estimated_arrival_time)) @@ -453,15 +459,14 @@ def get_eta(self, obj): # Comma Separated List of all arrival report dates def get_var(self, obj): - pre_alerts = obj.vaccineprealert_set.all().order_by("-estimated_arrival_time") + pre_alerts, arrival_report_matching = self.get_prefetched_data(obj) + arrival_report_dates = [] for pre_alert in pre_alerts: - matching_arrival_report = obj.vaccinearrivalreport_set.filter(po_number=pre_alert.po_number).order_by( - "-arrival_report_date" - ) - if matching_arrival_report: - for match in matching_arrival_report: - arrival_report_dates.append(str(match.arrival_report_date)) + matching_reports = arrival_report_matching.get(pre_alert.po_number, []) + if matching_reports: + for report in matching_reports: + arrival_report_dates.append(str(report.arrival_report_date)) else: arrival_report_dates.append("") return ",".join(arrival_report_dates) From 87eadc7dc003a60f627b763f5adfa35e66354549 Mon Sep 17 00:00:00 2001 From: HAKIZIMANA Franck Date: Tue, 17 Sep 2024 16:40:36 +0200 Subject: [PATCH 4/4] remove a print --- plugins/polio/tests/test_vaccine_supply_chain.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/polio/tests/test_vaccine_supply_chain.py b/plugins/polio/tests/test_vaccine_supply_chain.py index 26d2654fa5..54aa2be0b2 100644 --- a/plugins/polio/tests/test_vaccine_supply_chain.py +++ b/plugins/polio/tests/test_vaccine_supply_chain.py @@ -691,5 +691,4 @@ def test_var_field_ordered_reversely(self): # Verify that the "var" field is a comma-separated list of dates in reverse order expected_var = ",".join(dates) - print(response.data["results"]) self.assertEqual(response.data["results"][1]["var"], expected_var)