mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-13 22:51:49 +00:00
fix: don't hijack another Campaign's UTM mirror when display names collide
This commit is contained in:
@@ -32,19 +32,29 @@ 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", existing)
|
||||
except frappe.DoesNotExistError:
|
||||
mc = frappe.new_doc("UTM Campaign")
|
||||
mc.name = self.campaign_name
|
||||
mc = self.get_utm_campaign_mirror()
|
||||
mc.campaign_description = self.description
|
||||
# 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)
|
||||
|
||||
def get_utm_campaign_mirror(self):
|
||||
# the mirror already linked to this Campaign, if any (survives campaign_name edits)
|
||||
if owned := frappe.db.get_value("UTM Campaign", {"crm_campaign": self.name}):
|
||||
return frappe.get_doc("UTM Campaign", owned)
|
||||
|
||||
# reuse a same-named mirror only when it isn't already owned by another Campaign,
|
||||
# otherwise two Campaigns sharing a display name would hijack each other's mirror
|
||||
if frappe.db.exists("UTM Campaign", self.campaign_name):
|
||||
same_name = frappe.get_doc("UTM Campaign", self.campaign_name)
|
||||
if not same_name.crm_campaign or same_name.crm_campaign == self.name:
|
||||
return same_name
|
||||
|
||||
# create a fresh mirror, keeping its name unique when the display name is taken
|
||||
mc = frappe.new_doc("UTM Campaign")
|
||||
mc.name = self.name if frappe.db.exists("UTM Campaign", self.campaign_name) else self.campaign_name
|
||||
return mc
|
||||
|
||||
def autoname(self):
|
||||
if frappe.defaults.get_global_default("campaign_naming_by") != "Naming Series":
|
||||
self.name = self.campaign_name
|
||||
|
||||
@@ -50,3 +50,21 @@ class TestCampaign(ERPNextTestSuite):
|
||||
# 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)
|
||||
|
||||
def test_two_campaigns_sharing_a_name_do_not_hijack_each_others_mirror(self):
|
||||
# a naming series lets two Campaigns share a display name; each must keep its own mirror
|
||||
original = frappe.defaults.get_global_default("campaign_naming_by")
|
||||
frappe.defaults.set_global_default("campaign_naming_by", "Naming Series")
|
||||
try:
|
||||
first = self.make_campaign(campaign_name="_Test Shared Mirror", naming_series="SAL-CAM-.YYYY.-")
|
||||
second = self.make_campaign(campaign_name="_Test Shared Mirror", naming_series="SAL-CAM-.YYYY.-")
|
||||
finally:
|
||||
frappe.defaults.set_global_default("campaign_naming_by", original or "")
|
||||
|
||||
# the first Campaign's mirror is untouched; the second gets a distinct one
|
||||
self.assertEqual(
|
||||
frappe.db.get_value("UTM Campaign", "_Test Shared Mirror", "crm_campaign"), first.name
|
||||
)
|
||||
second_mirror = frappe.db.get_value("UTM Campaign", {"crm_campaign": second.name})
|
||||
self.assertTrue(second_mirror)
|
||||
self.assertNotEqual(second_mirror, "_Test Shared Mirror")
|
||||
|
||||
Reference in New Issue
Block a user