155 lines
9.4 KiB
Python
155 lines
9.4 KiB
Python
import frappe
|
|
from frappe.model.document import Document
|
|
from .db_service import DbService
|
|
from erpnext.crm.doctype.lead.lead import make_customer
|
|
from .address_service import AddressService
|
|
from .contact_service import ContactService
|
|
from .estimate_service import EstimateService
|
|
from .onsite_meeting_service import OnSiteMeetingService
|
|
|
|
class ClientService:
|
|
|
|
@staticmethod
|
|
def get_client_or_throw(client_name: str) -> Document:
|
|
"""Retrieve a Client document (Customer or Lead) or throw an error if it does not exist."""
|
|
doctype = ClientService.get_client_doctype(client_name)
|
|
return DbService.get_or_throw(doctype, client_name)
|
|
|
|
@staticmethod
|
|
def get_client_doctype(client_name: str) -> str:
|
|
"""Determine if the client is a Customer or Lead."""
|
|
if DbService.exists("Customer", client_name):
|
|
return "Customer"
|
|
elif DbService.exists("Lead", client_name):
|
|
return "Lead"
|
|
else:
|
|
raise ValueError(f"Client with name {client_name} does not exist as Customer or Lead.")
|
|
|
|
@staticmethod
|
|
def set_primary_contact(client_name: str, contact_name: str):
|
|
"""Set the primary contact for a client (Customer or Lead)."""
|
|
print(f"DEBUG: Setting primary contact for client {client_name} to contact {contact_name}")
|
|
client_doctype = ClientService.get_client_doctype(client_name)
|
|
frappe.db.set_value(client_doctype, client_name, "primary_contact", contact_name)
|
|
print(f"DEBUG: Set primary contact for client {client_name} to contact {contact_name}")
|
|
|
|
@staticmethod
|
|
def append_link(client_name: str, field: str, link_doctype: str, link_name: str):
|
|
"""Set a link field for a client (Customer or Lead)."""
|
|
print(f"DEBUG: Setting link field {field} for client {client_name} to {link_doctype} {link_name}")
|
|
client_doctype = ClientService.get_client_doctype(client_name)
|
|
client_doc = frappe.get_doc(client_doctype, client_name)
|
|
client_doc.append(field, {
|
|
link_doctype.lower(): link_name
|
|
})
|
|
client_doc.save(ignore_permissions=True)
|
|
print(f"DEBUG: Set link field {field} for client {client_doc.get('name')} to {link_doctype} {link_name}")
|
|
|
|
@staticmethod
|
|
def append_link_v2(client_name: str, field: str, link: dict):
|
|
"""Set a link field for a client (Customer or Lead) using a link dictionary."""
|
|
print(f"DEBUG: Setting link field {field} for client {client_name} with link data {link}")
|
|
client_doctype = ClientService.get_client_doctype(client_name)
|
|
client_doc = DbService.get_or_throw(client_doctype, client_name)
|
|
print("DEBUG: Appending link:", link)
|
|
client_doc.append(field, link)
|
|
print("DEBUG: Saving client document after appending link.")
|
|
client_doc.save(ignore_permissions=True)
|
|
print(f"DEBUG: Set link field {field} for client {client_doc.get('name')} with link data {link}")
|
|
|
|
@staticmethod
|
|
def convert_lead_to_customer(
|
|
lead_name: str,
|
|
update_quotations: bool = True,
|
|
update_addresses: bool = True,
|
|
update_contacts: bool = True,
|
|
update_onsite_meetings: bool = True,
|
|
update_companies: bool = True
|
|
) -> Document:
|
|
"""Convert a Lead to a Customer."""
|
|
print(f"DEBUG: Converting Lead {lead_name} to Customer")
|
|
try:
|
|
lead_doc = DbService.get_or_throw("Lead", lead_name)
|
|
print(f"DEBUG: Retrieved Lead document: {lead_doc.name}")
|
|
|
|
print("DEBUG: RUNNING make_customer()")
|
|
customer_doc = make_customer(lead_doc.name)
|
|
print(f"DEBUG: make_customer() returned document type: {type(customer_doc)}")
|
|
print(f"DEBUG: Customer doc name: {customer_doc.name if hasattr(customer_doc, 'name') else 'NO NAME'}")
|
|
customer_doc.custom_billing_address = lead_doc.custom_billing_address
|
|
print("DEBUG: Calling customer_doc.insert()")
|
|
customer_doc.insert(ignore_permissions=True)
|
|
print(f"DEBUG: Customer inserted successfully: {customer_doc.name}")
|
|
|
|
frappe.db.commit()
|
|
print("DEBUG: Database committed after customer insert")
|
|
print("DEBUG: CREATED CUSTOMER:", customer_doc.as_dict())
|
|
if update_addresses:
|
|
print("DEBUG: Lead_doc addresses:", lead_doc.get("addresses", []))
|
|
print(f"DEBUG: Updating addresses. Count: {len(lead_doc.get('properties', []))}")
|
|
for address in lead_doc.get("properties", []):
|
|
try:
|
|
print(f"DEBUG: Processing address: {address.get('address')}")
|
|
ClientService.append_link_v2(customer_doc.name, "properties", {"address": address.get("address")})
|
|
address_doc = AddressService.get_or_throw(address.get("address"))
|
|
AddressService.link_address_to_customer(address_doc, "Customer", customer_doc.name)
|
|
print(f"DEBUG: Linked address {address.get('address')} to customer")
|
|
except Exception as e:
|
|
print(f"ERROR: Failed to link address {address.get('address')}: {str(e)}")
|
|
frappe.log_error(f"Address linking error: {str(e)}", "convert_lead_to_customer")
|
|
|
|
if update_contacts:
|
|
print(f"DEBUG: Updating contacts. Count: {len(lead_doc.get('contacts', []))}")
|
|
for contact in lead_doc.get("contacts", []):
|
|
try:
|
|
print(f"DEBUG: Processing contact: {contact.get('contact')}")
|
|
ClientService.append_link_v2(customer_doc.name, "contacts", {"contact": contact.get("contact")})
|
|
contact_doc = ContactService.get_or_throw(contact.get("contact"))
|
|
ContactService.link_contact_to_customer(contact_doc, "Customer", customer_doc.name)
|
|
print(f"DEBUG: Linked contact {contact.get('contact')} to customer")
|
|
except Exception as e:
|
|
print(f"ERROR: Failed to link contact {contact.get('contact')}: {str(e)}")
|
|
frappe.log_error(f"Contact linking error: {str(e)}", "convert_lead_to_customer")
|
|
|
|
if update_quotations:
|
|
print(f"DEBUG: Updating quotations. Count: {len(lead_doc.get('quotations', []))}")
|
|
for quotation in lead_doc.get("quotations", []):
|
|
try:
|
|
print(f"DEBUG: Processing quotation: {quotation.get('quotation')}")
|
|
ClientService.append_link_v2(customer_doc.name, "quotations", {"quotation": quotation.get("quotation")})
|
|
quotation_doc = EstimateService.get_or_throw(quotation.get("quotation"))
|
|
EstimateService.link_estimate_to_customer(quotation_doc, "Customer", customer_doc.name)
|
|
print(f"DEBUG: Linked quotation {quotation.get('quotation')} to customer")
|
|
except Exception as e:
|
|
print(f"ERROR: Failed to link quotation {quotation.get('quotation')}: {str(e)}")
|
|
frappe.log_error(f"Quotation linking error: {str(e)}", "convert_lead_to_customer")
|
|
|
|
if update_onsite_meetings:
|
|
print(f"DEBUG: Updating onsite meetings. Count: {len(lead_doc.get('onsite_meetings', []))}")
|
|
for meeting in lead_doc.get("onsite_meetings", []):
|
|
try:
|
|
print(f"DEBUG: Processing onsite meeting: {meeting.get('onsite_meeting')}")
|
|
meeting_doc = DbService.get_or_throw("On-Site Meeting",meeting.get("onsite_meeting"))
|
|
ClientService.append_link_v2(customer_doc.name, "onsite_meetings", {"onsite_meeting": meeting.get("onsite_meeting")})
|
|
OnSiteMeetingService.link_onsite_meeting_to_customer(meeting_doc, "Customer", customer_doc.name)
|
|
print(f"DEBUG: Linked onsite meeting {meeting.get('onsite_meeting')} to customer")
|
|
except Exception as e:
|
|
print(f"ERROR: Failed to link onsite meeting {meeting.get('onsite_meeting')}: {str(e)}")
|
|
frappe.log_error(f"Onsite meeting linking error: {str(e)}", "convert_lead_to_customer")
|
|
if update_companies:
|
|
print(f"DEBUG: Updating companies. Count: {len(lead_doc.get('companies', []))}")
|
|
for company in lead_doc.get("companies", []):
|
|
try:
|
|
print(f"DEBUG: Processing company: {company.get('company')}")
|
|
ClientService.append_link_v2(customer_doc.name, "companies", {"company": company.get("company")})
|
|
print(f"DEBUG: Linked company {company.get('company')} to customer")
|
|
except Exception as e:
|
|
print(f"ERROR: Failed to link company {company.get('company')}: {str(e)}")
|
|
frappe.log_error(f"Company linking error: {str(e)}", "convert_lead_to_customer")
|
|
print(f"DEBUG: Converted Lead {lead_name} to Customer {customer_doc.name}")
|
|
return customer_doc
|
|
|
|
except Exception as e:
|
|
print(f"ERROR: Exception in convert_lead_to_customer: {str(e)}")
|
|
frappe.log_error(f"convert_lead_to_customer failed: {str(e)}", "ClientService")
|
|
raise |