mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-01 19:29:10 +00:00
fix(pos): preserve contacts and enforce permissions in set_customer_info (#55463)
This commit is contained in:
@@ -427,42 +427,80 @@ def get_past_order_list(search_term: str, status: str, limit: int = 20):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def set_customer_info(fieldname: str, customer: str, value: str = ""):
|
def set_customer_info(fieldname: str, customer: str, value: str = ""):
|
||||||
|
customer_doc = frappe.get_doc("Customer", customer)
|
||||||
|
customer_doc.check_permission("write")
|
||||||
|
|
||||||
if fieldname == "loyalty_program":
|
if fieldname == "loyalty_program":
|
||||||
frappe.db.set_value("Customer", customer, "loyalty_program", value)
|
customer_doc.loyalty_program = value
|
||||||
|
else:
|
||||||
|
contact = customer_doc.get("customer_primary_contact")
|
||||||
|
if not contact:
|
||||||
|
Contact = DocType("Contact")
|
||||||
|
DynamicLink = DocType("Dynamic Link")
|
||||||
|
|
||||||
contact = frappe.get_cached_value("Customer", customer, "customer_primary_contact")
|
# Inner join with Contact DocType, to priorities records that have is_primary_contact set.
|
||||||
if not contact:
|
query = (
|
||||||
contact = frappe.db.sql(
|
frappe.qb.from_(DynamicLink)
|
||||||
"""
|
.join(Contact)
|
||||||
SELECT parent FROM `tabDynamic Link`
|
.on(DynamicLink.parent == Contact.name)
|
||||||
WHERE
|
.select(DynamicLink.parent)
|
||||||
parenttype = 'Contact' AND
|
.where(
|
||||||
parentfield = 'links' AND
|
(DynamicLink.link_name == customer)
|
||||||
link_doctype = 'Customer' AND
|
& (DynamicLink.parentfield == "links")
|
||||||
link_name = %s
|
& (DynamicLink.parenttype == "Contact")
|
||||||
""",
|
& (DynamicLink.link_doctype == "Customer")
|
||||||
(customer),
|
)
|
||||||
as_dict=1,
|
.orderby(Contact.is_primary_contact, order=Order.desc)
|
||||||
)
|
)
|
||||||
contact = contact[0].get("parent") if contact else None
|
|
||||||
|
|
||||||
if not contact:
|
contacts = query.run(pluck=DynamicLink.parent)
|
||||||
new_contact = frappe.new_doc("Contact")
|
|
||||||
new_contact.is_primary_contact = 1
|
|
||||||
new_contact.first_name = customer
|
|
||||||
new_contact.set("links", [{"link_doctype": "Customer", "link_name": customer}])
|
|
||||||
new_contact.save()
|
|
||||||
contact = new_contact.name
|
|
||||||
frappe.db.set_value("Customer", customer, "customer_primary_contact", contact)
|
|
||||||
|
|
||||||
contact_doc = frappe.get_doc("Contact", contact)
|
contact = contacts[0] if contacts else None
|
||||||
if fieldname == "email_id":
|
|
||||||
contact_doc.set("email_ids", [{"email_id": value, "is_primary": 1}])
|
if not contact:
|
||||||
frappe.db.set_value("Customer", customer, "email_id", value)
|
new_contact = frappe.new_doc("Contact")
|
||||||
elif fieldname == "mobile_no":
|
new_contact.is_primary_contact = 1
|
||||||
contact_doc.set("phone_nos", [{"phone": value, "is_primary_mobile_no": 1}])
|
new_contact.first_name = customer
|
||||||
frappe.db.set_value("Customer", customer, "mobile_no", value)
|
new_contact.set("links", [{"link_doctype": "Customer", "link_name": customer}])
|
||||||
contact_doc.save()
|
new_contact.save()
|
||||||
|
contact = new_contact.name
|
||||||
|
|
||||||
|
def set_primary_phone_no_email(field, value):
|
||||||
|
# Create new record instead deleting existing email or phone_no and setting the new row as primary.
|
||||||
|
field_mapper = {
|
||||||
|
"email_ids": {"field": "email_id", "primary": "is_primary"},
|
||||||
|
"phone_nos": {"field": "phone", "primary": "is_primary_mobile_no"},
|
||||||
|
}
|
||||||
|
|
||||||
|
value_already_exists = False
|
||||||
|
for d in contact_doc.get(field):
|
||||||
|
if d.get(field_mapper[field].get("field")) == value and not value_already_exists:
|
||||||
|
d.set(field_mapper[field]["primary"], 1)
|
||||||
|
value_already_exists = True
|
||||||
|
continue
|
||||||
|
d.set(field_mapper[field]["primary"], 0)
|
||||||
|
|
||||||
|
if not value_already_exists:
|
||||||
|
contact_doc.append(
|
||||||
|
field, {field_mapper[field]["field"]: value, field_mapper[field]["primary"]: 1}
|
||||||
|
)
|
||||||
|
|
||||||
|
contact_doc = frappe.get_doc("Contact", contact)
|
||||||
|
# setting is_primary_contact = 1 on Contact to refetch the same contact incase it's removed from Customer records.
|
||||||
|
contact_doc.set("is_primary_contact", 1)
|
||||||
|
if fieldname == "email_id":
|
||||||
|
set_primary_phone_no_email("email_ids", value)
|
||||||
|
elif fieldname == "mobile_no":
|
||||||
|
set_primary_phone_no_email("phone_nos", value)
|
||||||
|
# Saving contact_doc to set mobile_no and email.
|
||||||
|
contact_doc.save()
|
||||||
|
|
||||||
|
# Auto-fetches from Contact DocType, no need to set values separately.
|
||||||
|
customer_doc.customer_primary_contact = contact
|
||||||
|
|
||||||
|
# using save method instead db.set_value which bypasses the validation for loyalty program
|
||||||
|
# and auto sets the mobile_no and email field on customer records.
|
||||||
|
customer_doc.save()
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
|||||||
@@ -987,6 +987,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
customer: current_customer,
|
customer: current_customer,
|
||||||
value: this.value,
|
value: this.value,
|
||||||
},
|
},
|
||||||
|
freeze: true,
|
||||||
callback: (r) => {
|
callback: (r) => {
|
||||||
if (!r.exc) {
|
if (!r.exc) {
|
||||||
me.customer_info[this.df.fieldname] = this.value;
|
me.customer_info[this.df.fieldname] = this.value;
|
||||||
|
|||||||
Reference in New Issue
Block a user