From ca9dcbf2d70a0500bae44cccc3ce8cea6d38fb29 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Sat, 4 Jul 2026 18:45:58 +0530 Subject: [PATCH] fix: reuse the existing UTM Campaign mirror when campaign_name is edited --- erpnext/crm/doctype/campaign/campaign.py | 8 +++++--- erpnext/crm/doctype/campaign/test_campaign.py | 8 ++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/erpnext/crm/doctype/campaign/campaign.py b/erpnext/crm/doctype/campaign/campaign.py index d4fd77a70f0..e89b1aa79f6 100644 --- a/erpnext/crm/doctype/campaign/campaign.py +++ b/erpnext/crm/doctype/campaign/campaign.py @@ -32,14 +32,16 @@ class Campaign(Document): self.sync_utm_campaign() def sync_utm_campaign(self): + # look up the existing mirror by the stable Campaign link first, so editing + # campaign_name updates that mirror instead of creating a duplicate + existing = frappe.db.get_value("UTM Campaign", {"crm_campaign": self.name}) or self.campaign_name try: - mc = frappe.get_doc("UTM Campaign", self.campaign_name) + mc = frappe.get_doc("UTM Campaign", existing) except frappe.DoesNotExistError: mc = frappe.new_doc("UTM Campaign") mc.name = self.campaign_name mc.campaign_description = self.description - # link to this Campaign by its document name, which differs from campaign_name - # when a naming series is used + # link by the document name, which differs from campaign_name when a naming series is used mc.crm_campaign = self.name mc.save(ignore_permissions=True) diff --git a/erpnext/crm/doctype/campaign/test_campaign.py b/erpnext/crm/doctype/campaign/test_campaign.py index ed906c04aef..169ecc75765 100644 --- a/erpnext/crm/doctype/campaign/test_campaign.py +++ b/erpnext/crm/doctype/campaign/test_campaign.py @@ -42,3 +42,11 @@ class TestCampaign(ERPNextTestSuite): utm = frappe.get_doc("UTM Campaign", campaign.campaign_name) self.assertEqual(utm.campaign_description, "Spring push") self.assertEqual(utm.crm_campaign, campaign.name) + + def test_editing_campaign_name_reuses_the_same_utm_campaign(self): + campaign = self.make_campaign(campaign_name="_Test Campaign Rename A") + campaign.campaign_name = "_Test Campaign Rename B" + campaign.save() + # the edit updates the existing mirror rather than creating a second one + mirrors = frappe.get_all("UTM Campaign", filters={"crm_campaign": campaign.name}) + self.assertEqual(len(mirrors), 1)