From 19ec6ca1aec178eeeb5a23c147a2defc740396af Mon Sep 17 00:00:00 2001 From: Tahiru Abdullai Date: Tue, 28 May 2024 15:44:27 +0000 Subject: [PATCH 1/6] Refactor querying logic in campaign.py This commit simplifies and optimizes the querying logic in campaign.py. The main changes involve minimizing the number of separate queries within loops and instead using single queries with the "__in" lookup. This is more performant and reduces database load. The code is also slightly more readable with this structure. --- src/api/store/campaign.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/api/store/campaign.py b/src/api/store/campaign.py index e6ebaadbb..464cbd056 100644 --- a/src/api/store/campaign.py +++ b/src/api/store/campaign.py @@ -814,7 +814,9 @@ def add_campaign_technology_event(self, context: Context, args): if not campaign_technology_id: return None, CustomMassenergizeError("campaign_technology_id is required!") + campaign_tech = CampaignTechnology.objects.filter(id=campaign_technology_id).first() + if not campaign_tech: return None, CustomMassenergizeError("campaignTechnology with id not found!") @@ -826,12 +828,12 @@ def add_campaign_technology_event(self, context: Context, args): campaign_manager = CampaignManager.objects.filter(user__id=context.user_id,campaign__id=campaign_tech.campaign.id, is_deleted=False) if not campaign_manager: return None, CustomMassenergizeError("Not authorized to add event") - - for event_id in event_ids: - event = Event.objects.filter(id=event_id).first() - if event: - campaign_event, _ = CampaignTechnologyEvent.objects.get_or_create(campaign_technology=campaign_tech, event=event, is_deleted=False) - created_list.append(campaign_event.simple_json()) + + all_events = Event.objects.filter(id__in=event_ids) + + for event in all_events: + campaign_event, _ = CampaignTechnologyEvent.objects.get_or_create(campaign_technology=campaign_tech, event=event, is_deleted=False) + created_list.append(campaign_event.simple_json()) return created_list, None except Exception as e: @@ -1385,17 +1387,20 @@ def list_campaign_communities_events(self, context: Context, args): return None, CustomMassenergizeError("campaign_id is required!") communities = CampaignCommunity.objects.filter(campaign__id=campaign_id, is_deleted=False) events = [] - for community in communities: - events.extend(Event.objects.filter(community__id=community.community.id, is_deleted=False, is_published=True)) + community_ids = communities.values_list('community__id', flat=True) + + events.extend(Event.objects.filter(community__id__in=community_ids, is_deleted=False, is_published=True, end_date_and_time__gte=datetime.now())) + to_return = [] for event in events: + community = communities.filter(community__id=event.community.id).first() obj = { "id": event.id, "name": event.name, "community":{ "id": event.community.id, "name": event.community.name, - "alias": communities.filter(campaign__id=campaign_id, community__id=event.community.id).first().alias + "alias": community.alias if community else None } } to_return.append(obj) From 6080153d7dd921df99038003d2c837235b74772f Mon Sep 17 00:00:00 2001 From: Tahiru Abdullai Date: Thu, 30 May 2024 10:00:55 +0000 Subject: [PATCH 2/6] Update .gitignore and refactor campaign technology event logic Updated the .gitignore file to ignore JetBrains IDE files .idea/. In the store/campaign.py, refactored add_campaign_technology_event method to handle multiple campaign technologies instead of a single one. Modified error messages and variable names to reflect changes. --- .gitignore | 1 + src/api/store/campaign.py | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 1d74e2196..1c0b8d4de 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .vscode/ +.idea/ \ No newline at end of file diff --git a/src/api/store/campaign.py b/src/api/store/campaign.py index 32a932d59..0e5e759c1 100644 --- a/src/api/store/campaign.py +++ b/src/api/store/campaign.py @@ -808,16 +808,17 @@ def list_campaign_partners(self, context: Context, args): def add_campaign_technology_event(self, context: Context, args): try: campaign_technology_id = args.pop("campaign_technology_id", None) + campaign_technology_ids = args.pop("campaign_technology_ids", None) event_ids = args.pop("event_ids", None) created_list = [] - if not campaign_technology_id: - return None, CustomMassenergizeError("campaign_technology_id is required!") + if not campaign_technology_ids: + return None, CustomMassenergizeError("campaign_technology_ids is required!") - campaign_tech = CampaignTechnology.objects.filter(id=campaign_technology_id).first() + campaign_techs = CampaignTechnology.objects.filter(id__in=campaign_technology_ids) - if not campaign_tech: + if not campaign_techs: return None, CustomMassenergizeError("campaignTechnology with id not found!") if not event_ids: From 9603c16f119d9edd7c9e9ec5b01cbd3d1649121f Mon Sep 17 00:00:00 2001 From: Tahiru Abdullai Date: Thu, 30 May 2024 14:07:05 +0000 Subject: [PATCH 3/6] Refactor campaign technology event handling This commit involves refactoring of the implementation of add_campaign_technology_event method in the campaign.py file. The multiple campaign ids handling has been removed and replaced with handling for a single campaign id. This promises for a more direct, and less error-prone system. --- src/api/store/campaign.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/api/store/campaign.py b/src/api/store/campaign.py index 0e5e759c1..32a932d59 100644 --- a/src/api/store/campaign.py +++ b/src/api/store/campaign.py @@ -808,17 +808,16 @@ def list_campaign_partners(self, context: Context, args): def add_campaign_technology_event(self, context: Context, args): try: campaign_technology_id = args.pop("campaign_technology_id", None) - campaign_technology_ids = args.pop("campaign_technology_ids", None) event_ids = args.pop("event_ids", None) created_list = [] - if not campaign_technology_ids: - return None, CustomMassenergizeError("campaign_technology_ids is required!") + if not campaign_technology_id: + return None, CustomMassenergizeError("campaign_technology_id is required!") - campaign_techs = CampaignTechnology.objects.filter(id__in=campaign_technology_ids) + campaign_tech = CampaignTechnology.objects.filter(id=campaign_technology_id).first() - if not campaign_techs: + if not campaign_tech: return None, CustomMassenergizeError("campaignTechnology with id not found!") if not event_ids: From a3bc4b1d30ed2335424c2d8587ebc6f27a9ba6b7 Mon Sep 17 00:00:00 2001 From: Tahiru Abdullai Date: Mon, 3 Jun 2024 08:06:58 +0000 Subject: [PATCH 4/6] Update campaign technology event creation logic The commit introduces iterative processing for assigning multiple technologies to a campaign. Instead of dealing with a single technology at a time, the updated method accepts and processes a list of technologies, allowing numerous assignments in one operation, and subsequently returns a list of successful assignments. This offers a more efficient way to handle campaign technologies. --- src/api/store/campaign.py | 45 ++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/api/store/campaign.py b/src/api/store/campaign.py index 32a932d59..91f681110 100644 --- a/src/api/store/campaign.py +++ b/src/api/store/campaign.py @@ -804,42 +804,47 @@ def list_campaign_partners(self, context: Context, args): except Exception as e: capture_message(str(e), level="error") return None, CustomMassenergizeError(e) - + def add_campaign_technology_event(self, context: Context, args): try: - campaign_technology_id = args.pop("campaign_technology_id", None) + campaign_technology_ids = args.pop("campaign_technology_ids", None) event_ids = args.pop("event_ids", None) - - created_list = [] - - if not campaign_technology_id: - return None, CustomMassenergizeError("campaign_technology_id is required!") - campaign_tech = CampaignTechnology.objects.filter(id=campaign_technology_id).first() + data_to_return = [] + + if not campaign_technology_ids: + return None, CustomMassenergizeError("campaign_technology_ids is required!") - if not campaign_tech: - return None, CustomMassenergizeError("campaignTechnology with id not found!") - if not event_ids: return None, CustomMassenergizeError("event_ids is required!") + campaign_techs = CampaignTechnology.objects.filter(id__in=campaign_technology_ids) + + if not campaign_techs: + return None, CustomMassenergizeError("No campaignTechnology found!") + if not context.user_is_super_admin: - if context.user_email != campaign_tech.campaign.owner.email: - campaign_manager = CampaignManager.objects.filter(user__id=context.user_id,campaign__id=campaign_tech.campaign.id, is_deleted=False) + campaign = campaign_techs.first().campaign + if context.user_email != campaign.owner.email: + campaign_manager = CampaignManager.objects.filter(user__id=context.user_id,campaign__id=campaign.id, is_deleted=False) if not campaign_manager: - return None, CustomMassenergizeError("Not authorized to add event") - + return None, CustomMassenergizeError("Unauthorized to add event") + all_events = Event.objects.filter(id__in=event_ids) - for event in all_events: + # Create a list of tuples for each combination of campaign_tech and event + combinations = [(campaign_tech, event) for campaign_tech in campaign_techs for event in all_events] + + for campaign_tech, event in combinations: campaign_event, _ = CampaignTechnologyEvent.objects.get_or_create(campaign_technology=campaign_tech, event=event, is_deleted=False) - created_list.append(campaign_event.simple_json()) - - return created_list, None + data_to_return.append(campaign_event.simple_json()) + + return data_to_return, None + except Exception as e: capture_message(str(e), level="error") return None, CustomMassenergizeError(e) - + def generate_campaign_link(self, context: Context, args): try: campaign_id = args.pop("campaign_id", None) From c3c14e13937ac00ee105bd5a80f71298c5bb1258 Mon Sep 17 00:00:00 2001 From: Tahiru Abdullai Date: Mon, 3 Jun 2024 09:43:39 +0000 Subject: [PATCH 5/6] refactor: Update campaign API and data store Updated the validation rules in the "campaign" API handler to require "campaign_technology_ids" and "event_ids". Removed a redundant comment in the "campaign" data store file. The changes aim to improve data integrity and code readability. --- src/api/handlers/campaign.py | 4 ++-- src/api/store/campaign.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/api/handlers/campaign.py b/src/api/handlers/campaign.py index fb5ea35b3..a1f15a85d 100644 --- a/src/api/handlers/campaign.py +++ b/src/api/handlers/campaign.py @@ -651,8 +651,8 @@ def add_campaign_technology_event(self, request): context: Context = request.context args: dict = context.args - self.validator.expect("campaign_technology_id", str, is_required=False) - self.validator.expect("event_ids", list, is_required=False) + self.validator.expect("campaign_technology_ids", "str_list", is_required=True) + self.validator.expect("event_ids", list, is_required=True) args, err = self.validator.verify(args) if err: return err diff --git a/src/api/store/campaign.py b/src/api/store/campaign.py index 91f681110..e4d16d72b 100644 --- a/src/api/store/campaign.py +++ b/src/api/store/campaign.py @@ -832,7 +832,6 @@ def add_campaign_technology_event(self, context: Context, args): all_events = Event.objects.filter(id__in=event_ids) - # Create a list of tuples for each combination of campaign_tech and event combinations = [(campaign_tech, event) for campaign_tech in campaign_techs for event in all_events] for campaign_tech, event in combinations: From 979e3de73050b26869555537e4415789b48c15a1 Mon Sep 17 00:00:00 2001 From: Tahiru Abdullai Date: Mon, 3 Jun 2024 10:34:00 +0000 Subject: [PATCH 6/6] chore: Update test payload in add campaign technology event test The payload in the test "test_add_campaign_technology_event" in "test_campaigns.py" has been updated. The "campaign_technology_id" attribute has been renamed to "campaign_technology_ids" and now accepts a list of ids instead of a single id. --- src/api/tests/test_campaigns.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/tests/test_campaigns.py b/src/api/tests/test_campaigns.py index 9ca362f91..a93497a9d 100644 --- a/src/api/tests/test_campaigns.py +++ b/src/api/tests/test_campaigns.py @@ -618,7 +618,7 @@ def test_delete_campaign_technology_comment(self): self.assertEqual(response['success'], True) def test_add_campaign_technology_event(self): - payload = {"campaign_technology_id": self.CAMPAIGN_TECHNOLOGY.id, "event_ids": [self.event_1.id],} + payload = {"campaign_technology_ids": [self.CAMPAIGN_TECHNOLOGY.id], "event_ids": [self.event_1.id],} Console.header("Testing the campaigns.technology.events.add endpoint") signinAs(self.client, self.SADMIN) response = self.make_request("campaigns.technology.events.add", payload)