You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

224 line
6.0 KiB

  1. import frappe
  2. from frappe.desk.notifications import notify_mentions
  3. from frappe.model.document import Document
  4. from frappe.utils import cstr, now, today
  5. from pypika import functions
  6. def update_lead_phone_numbers(contact, method):
  7. if contact.phone_nos:
  8. contact_lead = contact.get_link_for("Lead")
  9. if contact_lead:
  10. phone = mobile_no = contact.phone_nos[0].phone
  11. if len(contact.phone_nos) > 1:
  12. # get the default phone number
  13. primary_phones = [
  14. phone_doc.phone for phone_doc in contact.phone_nos if phone_doc.is_primary_phone
  15. ]
  16. if primary_phones:
  17. phone = primary_phones[0]
  18. # get the default mobile number
  19. primary_mobile_nos = [
  20. phone_doc.phone for phone_doc in contact.phone_nos if phone_doc.is_primary_mobile_no
  21. ]
  22. if primary_mobile_nos:
  23. mobile_no = primary_mobile_nos[0]
  24. lead = frappe.get_doc("Lead", contact_lead)
  25. lead.db_set("phone", phone)
  26. lead.db_set("mobile_no", mobile_no)
  27. def copy_comments(doctype, docname, doc):
  28. comments = frappe.db.get_values(
  29. "Comment",
  30. filters={"reference_doctype": doctype, "reference_name": docname, "comment_type": "Comment"},
  31. fieldname="*",
  32. )
  33. for comment in comments:
  34. comment = frappe.get_doc(comment.update({"doctype": "Comment"}))
  35. comment.name = None
  36. comment.reference_doctype = doc.doctype
  37. comment.reference_name = doc.name
  38. comment.insert()
  39. def link_communications(doctype, docname, doc):
  40. communication_list = get_linked_communication_list(doctype, docname)
  41. for communication in communication_list:
  42. communication_doc = frappe.get_doc("Communication", communication)
  43. communication_doc.add_link(doc.doctype, doc.name, autosave=True)
  44. def get_linked_communication_list(doctype, docname):
  45. communications = frappe.get_all(
  46. "Communication", filters={"reference_doctype": doctype, "reference_name": docname}, pluck="name"
  47. )
  48. communication_links = frappe.get_all(
  49. "Communication Link",
  50. {"link_doctype": doctype, "link_name": docname, "parent": ("not in", communications)},
  51. pluck="parent",
  52. )
  53. return communications + communication_links
  54. def link_communications_with_prospect(communication, method):
  55. prospect = get_linked_prospect(communication.reference_doctype, communication.reference_name)
  56. if prospect:
  57. already_linked = any(
  58. [
  59. d.name
  60. for d in communication.get("timeline_links")
  61. if d.link_doctype == "Prospect" and d.link_name == prospect
  62. ]
  63. )
  64. if not already_linked:
  65. row = communication.append("timeline_links")
  66. row.link_doctype = "Prospect"
  67. row.link_name = prospect
  68. row.db_update()
  69. def get_linked_prospect(reference_doctype, reference_name):
  70. prospect = None
  71. if reference_doctype == "Lead":
  72. prospect = frappe.db.get_value("Prospect Lead", {"lead": reference_name}, "parent")
  73. elif reference_doctype == "Opportunity":
  74. opportunity_from, party_name = frappe.db.get_value(
  75. "Opportunity", reference_name, ["opportunity_from", "party_name"]
  76. )
  77. if opportunity_from == "Lead":
  78. prospect = frappe.db.get_value(
  79. "Prospect Opportunity", {"opportunity": reference_name}, "parent"
  80. )
  81. if opportunity_from == "Prospect":
  82. prospect = party_name
  83. return prospect
  84. def link_events_with_prospect(event, method):
  85. if event.event_participants:
  86. ref_doctype = event.event_participants[0].reference_doctype
  87. ref_docname = event.event_participants[0].reference_docname
  88. prospect = get_linked_prospect(ref_doctype, ref_docname)
  89. if prospect:
  90. event.add_participant("Prospect", prospect)
  91. event.save()
  92. def link_open_tasks(ref_doctype, ref_docname, doc):
  93. todos = get_open_todos(ref_doctype, ref_docname)
  94. for todo in todos:
  95. todo_doc = frappe.get_doc("ToDo", todo.name)
  96. todo_doc.reference_type = doc.doctype
  97. todo_doc.reference_name = doc.name
  98. todo_doc.save()
  99. def link_open_events(ref_doctype, ref_docname, doc):
  100. events = get_open_events(ref_doctype, ref_docname)
  101. for event in events:
  102. event_doc = frappe.get_doc("Event", event.name)
  103. event_doc.add_participant(doc.doctype, doc.name)
  104. event_doc.save()
  105. @frappe.whitelist()
  106. def get_open_activities(ref_doctype, ref_docname):
  107. tasks = get_open_todos(ref_doctype, ref_docname)
  108. events = get_open_events(ref_doctype, ref_docname)
  109. return {"tasks": tasks, "events": events}
  110. def get_open_todos(ref_doctype, ref_docname):
  111. return frappe.get_all(
  112. "ToDo",
  113. filters={"reference_type": ref_doctype, "reference_name": ref_docname, "status": "Open"},
  114. fields=[
  115. "name",
  116. "description",
  117. "allocated_to",
  118. "date",
  119. ],
  120. )
  121. def get_open_events(ref_doctype, ref_docname):
  122. event = frappe.qb.DocType("Event")
  123. event_link = frappe.qb.DocType("Event Participants")
  124. query = (
  125. frappe.qb.from_(event)
  126. .join(event_link)
  127. .on(event_link.parent == event.name)
  128. .select(
  129. event.name,
  130. event.subject,
  131. event.event_category,
  132. event.starts_on,
  133. event.ends_on,
  134. event.description,
  135. )
  136. .where(
  137. (event_link.reference_doctype == ref_doctype)
  138. & (event_link.reference_docname == ref_docname)
  139. & (event.status == "Open")
  140. )
  141. )
  142. data = query.run(as_dict=True)
  143. return data
  144. def open_leads_opportunities_based_on_todays_event():
  145. event = frappe.qb.DocType("Event")
  146. event_link = frappe.qb.DocType("Event Participants")
  147. query = (
  148. frappe.qb.from_(event)
  149. .join(event_link)
  150. .on(event_link.parent == event.name)
  151. .select(event_link.reference_doctype, event_link.reference_docname)
  152. .where(
  153. (event_link.reference_doctype.isin(["Lead", "Opportunity"]))
  154. & (event.status == "Open")
  155. & (functions.Date(event.starts_on) == today())
  156. )
  157. )
  158. data = query.run(as_dict=True)
  159. for d in data:
  160. frappe.db.set_value(d.reference_doctype, d.reference_docname, "status", "Open")
  161. class CRMNote(Document):
  162. @frappe.whitelist()
  163. def add_note(self, note):
  164. self.append("notes", {"note": note, "added_by": frappe.session.user, "added_on": now()})
  165. self.save()
  166. notify_mentions(self.doctype, self.name, note)
  167. @frappe.whitelist()
  168. def edit_note(self, note, row_id):
  169. for d in self.notes:
  170. if cstr(d.name) == row_id:
  171. d.note = note
  172. d.db_update()
  173. @frappe.whitelist()
  174. def delete_note(self, row_id):
  175. for d in self.notes:
  176. if cstr(d.name) == row_id:
  177. self.remove(d)
  178. break
  179. self.save()