update
This commit is contained in:
parent
84a91359d8
commit
6c703c2c3b
55 changed files with 1130 additions and 358 deletions
|
|
@ -127,83 +127,83 @@ def check_client_exists(client_name):
|
|||
def get_client_status_counts(weekly=False, week_start_date=None, week_end_date=None):
|
||||
"""Get counts of clients by status categories with optional weekly filtering."""
|
||||
# Build base filters for date range if weekly filtering is enabled
|
||||
try:
|
||||
base_filters = {}
|
||||
if weekly and week_start_date and week_end_date:
|
||||
# Assuming you have a date field to filter by - adjust the field name as needed
|
||||
# Common options: creation, modified, custom_date_field, etc.
|
||||
base_filters["creation"] = ["between", [week_start_date, week_end_date]]
|
||||
# try:
|
||||
# base_filters = {}
|
||||
# if weekly and week_start_date and week_end_date:
|
||||
# # Assuming you have a date field to filter by - adjust the field name as needed
|
||||
# # Common options: creation, modified, custom_date_field, etc.
|
||||
# base_filters["creation"] = ["between", [week_start_date, week_end_date]]
|
||||
|
||||
# Helper function to merge base filters with status filters
|
||||
def get_filters(status_field, status_value):
|
||||
filters = {status_field: status_value}
|
||||
filters.update(base_filters)
|
||||
return filters
|
||||
# # Helper function to merge base filters with status filters
|
||||
# def get_filters(status_field, status_value):
|
||||
# filters = {status_field: status_value}
|
||||
# filters.update(base_filters)
|
||||
# return filters
|
||||
|
||||
onsite_meeting_scheduled_status_counts = {
|
||||
"label": "On-Site Meeting Scheduled",
|
||||
"not_started": frappe.db.count("Address", filters=get_filters("custom_onsite_meeting_scheduled", "Not Started")),
|
||||
"in_progress": frappe.db.count("Address", filters=get_filters("custom_onsite_meeting_scheduled", "In Progress")),
|
||||
"completed": frappe.db.count("Address", filters=get_filters("custom_onsite_meeting_scheduled", "Completed"))
|
||||
}
|
||||
# onsite_meeting_scheduled_status_counts = {
|
||||
# "label": "On-Site Meeting Scheduled",
|
||||
# "not_started": frappe.db.count("Address", filters=get_filters("custom_onsite_meeting_scheduled", "Not Started")),
|
||||
# "in_progress": frappe.db.count("Address", filters=get_filters("custom_onsite_meeting_scheduled", "In Progress")),
|
||||
# "completed": frappe.db.count("Address", filters=get_filters("custom_onsite_meeting_scheduled", "Completed"))
|
||||
# }
|
||||
|
||||
estimate_sent_status_counts = {
|
||||
"label": "Estimate Sent",
|
||||
"not_started": frappe.db.count("Address", filters=get_filters("custom_estimate_sent_status", "Not Started")),
|
||||
"in_progress": frappe.db.count("Address", filters=get_filters("custom_estimate_sent_status", "In Progress")),
|
||||
"completed": frappe.db.count("Address", filters=get_filters("custom_estimate_sent_status", "Completed"))
|
||||
}
|
||||
# estimate_sent_status_counts = {
|
||||
# "label": "Estimate Sent",
|
||||
# "not_started": frappe.db.count("Address", filters=get_filters("custom_estimate_sent_status", "Not Started")),
|
||||
# "in_progress": frappe.db.count("Address", filters=get_filters("custom_estimate_sent_status", "In Progress")),
|
||||
# "completed": frappe.db.count("Address", filters=get_filters("custom_estimate_sent_status", "Completed"))
|
||||
# }
|
||||
|
||||
job_status_counts = {
|
||||
"label": "Job Status",
|
||||
"not_started": frappe.db.count("Address", filters=get_filters("custom_job_status", "Not Started")),
|
||||
"in_progress": frappe.db.count("Address", filters=get_filters("custom_job_status", "In Progress")),
|
||||
"completed": frappe.db.count("Address", filters=get_filters("custom_job_status", "Completed"))
|
||||
}
|
||||
# job_status_counts = {
|
||||
# "label": "Job Status",
|
||||
# "not_started": frappe.db.count("Address", filters=get_filters("custom_job_status", "Not Started")),
|
||||
# "in_progress": frappe.db.count("Address", filters=get_filters("custom_job_status", "In Progress")),
|
||||
# "completed": frappe.db.count("Address", filters=get_filters("custom_job_status", "Completed"))
|
||||
# }
|
||||
|
||||
payment_received_status_counts = {
|
||||
"label": "Payment Received",
|
||||
"not_started": frappe.db.count("Address", filters=get_filters("custom_payment_received_status", "Not Started")),
|
||||
"in_progress": frappe.db.count("Address", filters=get_filters("custom_payment_received_status", "In Progress")),
|
||||
"completed": frappe.db.count("Address", filters=get_filters("custom_payment_received_status", "Completed"))
|
||||
}
|
||||
# payment_received_status_counts = {
|
||||
# "label": "Payment Received",
|
||||
# "not_started": frappe.db.count("Address", filters=get_filters("custom_payment_received_status", "Not Started")),
|
||||
# "in_progress": frappe.db.count("Address", filters=get_filters("custom_payment_received_status", "In Progress")),
|
||||
# "completed": frappe.db.count("Address", filters=get_filters("custom_payment_received_status", "Completed"))
|
||||
# }
|
||||
|
||||
status_dicts = [
|
||||
onsite_meeting_scheduled_status_counts,
|
||||
estimate_sent_status_counts,
|
||||
job_status_counts,
|
||||
payment_received_status_counts
|
||||
]
|
||||
# status_dicts = [
|
||||
# onsite_meeting_scheduled_status_counts,
|
||||
# estimate_sent_status_counts,
|
||||
# job_status_counts,
|
||||
# payment_received_status_counts
|
||||
# ]
|
||||
|
||||
categories = []
|
||||
for status_dict in status_dicts:
|
||||
category = {
|
||||
"label": status_dict["label"],
|
||||
"statuses": [
|
||||
{
|
||||
"color": "red",
|
||||
"label": "Not Started",
|
||||
"count": status_dict["not_started"]
|
||||
},
|
||||
{
|
||||
"color": "yellow",
|
||||
"label": "In Progress",
|
||||
"count": status_dict["in_progress"]
|
||||
},
|
||||
{
|
||||
"color": "green",
|
||||
"label": "Completed",
|
||||
"count": status_dict["completed"]
|
||||
}
|
||||
]
|
||||
}
|
||||
categories.append(category)
|
||||
# categories = []
|
||||
# for status_dict in status_dicts:
|
||||
# category = {
|
||||
# "label": status_dict["label"],
|
||||
# "statuses": [
|
||||
# {
|
||||
# "color": "red",
|
||||
# "label": "Not Started",
|
||||
# "count": status_dict["not_started"]
|
||||
# },
|
||||
# {
|
||||
# "color": "yellow",
|
||||
# "label": "In Progress",
|
||||
# "count": status_dict["in_progress"]
|
||||
# },
|
||||
# {
|
||||
# "color": "green",
|
||||
# "label": "Completed",
|
||||
# "count": status_dict["completed"]
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
# categories.append(category)
|
||||
|
||||
return build_success_response(categories)
|
||||
except frappe.ValidationError as ve:
|
||||
return build_error_response(str(ve), 400)
|
||||
except Exception as e:
|
||||
return build_error_response(str(e), 500)
|
||||
return build_success_response("success")
|
||||
# except frappe.ValidationError as ve:
|
||||
# return build_error_response(str(ve), 400)
|
||||
# except Exception as e:
|
||||
# return build_error_response(str(e), 500)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
|
|
@ -682,4 +682,142 @@ def find_primary_contact_or_throw(contacts):
|
|||
if contact.get("is_primary"):
|
||||
print("#####DEBUG: Primary contact found:", contact)
|
||||
return contact
|
||||
raise ValueError("No primary contact found in contacts list.")
|
||||
raise ValueError("No primary contact found in contacts list.")
|
||||
|
||||
|
||||
def find_contact_in_list(contact_docs, contact_ref):
|
||||
"""Find a contact document in a list by matching first_name, last_name, and email."""
|
||||
if not isinstance(contact_ref, dict):
|
||||
return None
|
||||
ref_first = contact_ref.get("first_name", "")
|
||||
ref_last = contact_ref.get("last_name", "")
|
||||
ref_email = contact_ref.get("email", "")
|
||||
for doc in contact_docs:
|
||||
if (doc.first_name == ref_first and
|
||||
doc.last_name == ref_last and
|
||||
(doc.email_id == ref_email or doc.custom_email == ref_email)):
|
||||
return doc
|
||||
return None
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_client_contacts_addresses(client_name, company, contacts=[], addresses=[]):
|
||||
"""Create or link contacts and addresses for an existing client.
|
||||
|
||||
If a contact or address already exists, it will be linked to the client
|
||||
instead of creating a duplicate.
|
||||
"""
|
||||
if isinstance(contacts, str):
|
||||
contacts = json.loads(contacts)
|
||||
if isinstance(addresses, str):
|
||||
addresses = json.loads(addresses)
|
||||
print(f"DEBUG: create_client_contacts_addresses called with client_name: {client_name}, company: {company}")
|
||||
try:
|
||||
client_doc = ClientService.get_client_or_throw(client_name)
|
||||
|
||||
# Build list of existing client contacts (preserves frontend index order)
|
||||
existing_contact_docs = [frappe.get_doc("Contact", link.contact) for link in client_doc.contacts]
|
||||
|
||||
# Process new contacts
|
||||
new_contact_docs = []
|
||||
for contact in contacts:
|
||||
contact_doc = check_and_get_contact(
|
||||
contact.get("first_name"),
|
||||
contact.get("last_name"),
|
||||
contact.get("email"),
|
||||
contact.get("phone_number")
|
||||
)
|
||||
if not contact_doc:
|
||||
contact_doc = ContactService.create({
|
||||
"first_name": contact.get("first_name"),
|
||||
"last_name": contact.get("last_name"),
|
||||
"role": contact.get("contact_role", "Other"),
|
||||
"custom_email": contact.get("email"),
|
||||
"is_primary_contact": 1 if contact.get("is_primary") else 0,
|
||||
"customer_type": client_doc.doctype,
|
||||
"customer_name": client_doc.name,
|
||||
"email_ids": [{
|
||||
"email_id": contact.get("email"),
|
||||
"is_primary": 1
|
||||
}],
|
||||
"phone_nos": [{
|
||||
"phone": contact.get("phone_number"),
|
||||
"is_primary_phone": 1,
|
||||
"is_primary_mobile_no": 1
|
||||
}]
|
||||
})
|
||||
ContactService.link_contact_to_customer(contact_doc, client_doc.doctype, client_doc.name)
|
||||
ClientService.append_link_v2(client_doc.name, "contacts", {"contact": contact_doc.name})
|
||||
new_contact_docs.append(contact_doc)
|
||||
|
||||
# Combined contact list: existing client contacts + newly created/linked contacts
|
||||
# Address contact indices reference this combined list
|
||||
all_contact_docs = existing_contact_docs + new_contact_docs
|
||||
|
||||
# Process addresses
|
||||
address_docs = []
|
||||
for address in addresses:
|
||||
filters = {
|
||||
"address_line1": address.get("address_line1"),
|
||||
"city": address.get("city"),
|
||||
"pincode": address.get("pincode")
|
||||
}
|
||||
if address.get("address_line2"):
|
||||
filters["address_line2"] = address.get("address_line2")
|
||||
|
||||
existing_address = frappe.db.exists("Address", filters)
|
||||
if existing_address:
|
||||
address_doc = frappe.get_doc("Address", existing_address)
|
||||
else:
|
||||
address_doc = AddressService.create({
|
||||
"address_title": AddressService.build_address_title(client_name, address),
|
||||
"address_line1": address.get("address_line1"),
|
||||
"address_line2": address.get("address_line2"),
|
||||
"city": address.get("city"),
|
||||
"state": address.get("state"),
|
||||
"pincode": address.get("pincode"),
|
||||
"country": "United States",
|
||||
"address_type": "Service",
|
||||
"custom_billing_address": 0,
|
||||
"is_primary_address": 0,
|
||||
"is_service_address": 1,
|
||||
"customer_type": client_doc.doctype,
|
||||
"customer_name": client_doc.name
|
||||
})
|
||||
|
||||
# Add company if not already present
|
||||
if company not in [c.company for c in address_doc.companies]:
|
||||
address_doc.append("companies", {"company": company})
|
||||
address_doc.save(ignore_permissions=True)
|
||||
|
||||
# Link address to customer
|
||||
AddressService.link_address_to_customer(address_doc, client_doc.doctype, client_doc.name)
|
||||
|
||||
# Link selected contacts to address
|
||||
for contact_ref in address.get("contacts", []):
|
||||
if not contact_ref:
|
||||
continue
|
||||
# Contact references are dicts with first_name, last_name, email
|
||||
contact_doc = find_contact_in_list(all_contact_docs, contact_ref)
|
||||
if contact_doc:
|
||||
AddressService.link_address_to_contact(address_doc, contact_doc.name)
|
||||
ContactService.link_contact_to_address(contact_doc, address_doc.name)
|
||||
|
||||
# Set primary contact for address
|
||||
primary_ref = address.get("primary_contact")
|
||||
if primary_ref:
|
||||
primary_contact = find_contact_in_list(all_contact_docs, primary_ref)
|
||||
if primary_contact:
|
||||
AddressService.set_primary_contact(address_doc.name, primary_contact.name)
|
||||
|
||||
# Link address to client
|
||||
ClientService.append_link_v2(client_doc.name, "properties", {"address": address_doc.name})
|
||||
address_docs.append(address_doc)
|
||||
|
||||
return build_success_response({
|
||||
"contacts": [c.as_dict() for c in new_contact_docs],
|
||||
"addresses": [a.as_dict() for a in address_docs],
|
||||
"message": "Contacts and addresses created/linked successfully."
|
||||
})
|
||||
except Exception as e:
|
||||
return build_error_response(str(e), 500)
|
||||
Loading…
Add table
Add a link
Reference in a new issue