From 0c1bb52f1b902f7fe0f94297028d09145098cce8 Mon Sep 17 00:00:00 2001 From: Casey Date: Sat, 13 Dec 2025 08:23:03 -0600 Subject: [PATCH] fix client creation --- custom_ui/api/db/clients.py | 153 ++++++------ custom_ui/install.py | 34 ++- frontend/src/App.vue | 4 +- frontend/src/components/CompanySelector.vue | 6 +- frontend/src/components/SideBar.vue | 14 +- frontend/src/components/SidebarSpeedDial.vue | 1 + .../clientSubPages/ClientInformationForm.vue | 228 ++++++++++++------ frontend/src/stores/company.js | 4 +- frontend/src/stores/theme.js | 22 +- 9 files changed, 305 insertions(+), 161 deletions(-) diff --git a/custom_ui/api/db/clients.py b/custom_ui/api/db/clients.py index 1f88aee..5c9ff5a 100644 --- a/custom_ui/api/db/clients.py +++ b/custom_ui/api/db/clients.py @@ -136,67 +136,67 @@ def get_client(client_name): @frappe.whitelist() def get_clients_table_data(filters={}, sortings=[], page=1, page_size=10): """Get paginated client table data with filtering and sorting support.""" - try: + # try: - print("DEBUG: Raw client table query received:", { - "filters": filters, - "sortings": sortings, - "page": page, - "page_size": page_size - }) + # print("DEBUG: Raw client table query received:", { + # "filters": filters, + # "sortings": sortings, + # "page": page, + # "page_size": page_size + # }) - processed_filters, processed_sortings, is_or, page, page_size = process_query_conditions(filters, sortings, page, page_size) - print("DEBUG: Processed filters:", processed_filters) - print("DEBUG: Processed sortings:", processed_sortings) - # Handle count with proper OR filter support - if is_or: - count = frappe.db.sql(*get_count_or_filters("Address", processed_filters))[0][0] - else: - count = frappe.db.count("Address", filters=processed_filters) + # processed_filters, processed_sortings, is_or, page, page_size = process_query_conditions(filters, sortings, page, page_size) + # print("DEBUG: Processed filters:", processed_filters) + # print("DEBUG: Processed sortings:", processed_sortings) + # # Handle count with proper OR filter support + # if is_or: + # count = frappe.db.sql(*get_count_or_filters("Address", processed_filters))[0][0] + # else: + # count = frappe.db.count("Address", filters=processed_filters) - print("DEBUG: Count of addresses matching filters:", count) + # print("DEBUG: Count of addresses matching filters:", count) - address_names = frappe.db.get_all( - "Address", - fields=["name"], - filters=processed_filters if not is_or else None, - or_filters=processed_filters if is_or else None, - limit=page_size, - start=(page - 1) * page_size, - order_by=processed_sortings - ) + # address_names = frappe.db.get_all( + # "Address", + # fields=["name"], + # filters=processed_filters if not is_or else None, + # or_filters=processed_filters if is_or else None, + # limit=page_size, + # start=(page - 1) * page_size, + # order_by=processed_sortings + # ) - addresses = [frappe.get_doc("Address", addr["name"]).as_dict() for addr in address_names] - tableRows = [] - for address in addresses: - tableRow = {} - links = address.links - customer_links = [link for link in links if link.link_doctype == "Customer"] if links else None - customer_name = address.get("custom_customer_to_bill") - if not customer_name and not customer_links: - print("DEBUG: No customer links found and no customer to bill.") - customer_name = "N/A" - elif not customer_name and customer_links: - print("DEBUG: No customer to bill. Customer links found:", customer_links) - customer_name = customer_links[0].link_name - tableRow["id"] = address["name"] - tableRow["customer_name"] = customer_name - tableRow["address"] = ( - f"{address['address_line1']}" - f"{' ' + address['address_line2'] if address['address_line2'] else ''} " - f"{address['city']}, {address['state']} {address['pincode']}" - ) - tableRow["appointment_scheduled_status"] = address.custom_onsite_meeting_scheduled - tableRow["estimate_sent_status"] = address.custom_estimate_sent_status - tableRow["job_status"] = address.custom_job_status - tableRow["payment_received_status"] = address.custom_payment_received_status - tableRows.append(tableRow) - tableDataDict = build_datatable_dict(data=tableRows, count=count, page=page, page_size=page_size) - return build_success_response(tableDataDict) - except frappe.ValidationError as ve: - return build_error_response(str(ve), 400) - except Exception as e: - return build_error_response(str(e), 500) + # addresses = [frappe.get_doc("Address", addr["name"]).as_dict() for addr in address_names] + # tableRows = [] + # for address in addresses: + # tableRow = {} + # links = address.links + # customer_links = [link for link in links if link.link_doctype == "Customer"] if links else None + # customer_name = address.get("custom_customer_to_bill") + # if not customer_name and not customer_links: + # print("DEBUG: No customer links found and no customer to bill.") + # customer_name = "N/A" + # elif not customer_name and customer_links: + # print("DEBUG: No customer to bill. Customer links found:", customer_links) + # customer_name = customer_links[0].link_name + # tableRow["id"] = address["name"] + # tableRow["customer_name"] = customer_name + # tableRow["address"] = ( + # f"{address['address_line1']}" + # f"{' ' + address['address_line2'] if address['address_line2'] else ''} " + # f"{address['city']}, {address['state']} {address['pincode']}" + # ) + # tableRow["appointment_scheduled_status"] = address.custom_onsite_meeting_scheduled + # tableRow["estimate_sent_status"] = address.custom_estimate_sent_status + # tableRow["job_status"] = address.custom_job_status + # tableRow["payment_received_status"] = address.custom_payment_received_status + # tableRows.append(tableRow) + # tableDataDict = build_datatable_dict(data=tableRows, count=count, page=page, page_size=page_size) + # return build_success_response(tableDataDict) + # 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() @@ -207,27 +207,37 @@ def upsert_client(data): # Handle customer creation/update print("#####DEBUG: Upsert client data received:", data) + print("#####DEBUG: Checking for existing customer with name:", data.get("customer_name")) customer = frappe.db.exists("Customer", {"customer_name": data.get("customer_name")}) + if not customer: - new_lead_data = {"doctype": "Lead"} + print("#####DEBUG: No existing customer found. Checking for existing lead") + customer = frappe.db.exists("Lead", {"lead_name": data.get("customer_name")}) + else: + print("#####DEBUG: Existing customer found:", customer) + + if not customer: + print("#####DEBUG: No existing lead found. Creating new lead.") is_individual = data.get("customer_type") == "Individual" + primary_contact = next((c for c in data.get("contacts", []) if c.get("is_primary")), None) if not primary_contact: return build_error_response("Primary contact information is required to create a new customer.", 400) - if is_individual: - # Grab the contact that has is_primary true - new_lead_data["first_name"] = primary_contact.get("first_name") - new_lead_data["last_name"] = primary_contact.get("last_name") - else: - new_lead_data["company_name"] = data.get("customer_name") - new_lead_data["email_id"] = primary_contact.get("email") - new_lead_data["phone"] = primary_contact.get("phone_number") - new_client_doc = frappe.get_doc({ - "doctype": "Lead", - "customer_name": data.get("customer_name"), - "customer_type": data.get("customer_type") - }).insert(ignore_permissions=True) + print("#####DEBUG: Primary contact found:", primary_contact) + + new_lead_data = { + "doctype": "Lead", + "lead_name": data.get("customer_name"), + "first_name": primary_contact.get("first_name"), + "last_name": primary_contact.get("last_name"), + "email_id": primary_contact.get("email"), + "phone": primary_contact.get("phone_number"), + "customer_type": data.get("customer_type"), + "company": data.get("company") + } + print("#####DEBUG: New lead data prepared:", new_lead_data) + new_client_doc = frappe.get_doc(new_lead_data).insert(ignore_permissions=True) else: new_client_doc = frappe.get_doc("Customer", data.get("customer_name")) print(f"#####DEBUG: {new_client_doc.doctype}:", new_client_doc.as_dict()) @@ -265,6 +275,7 @@ def upsert_client(data): contact_data = json.loads(contact_data) print("#####DEBUG: Processing contact data:", contact_data) contact_exists = frappe.db.exists("Contact", {"email_id": contact_data.get("email"), "phone": contact_data.get("phone_number")}) + print("Contact exists check:", contact_exists) if not contact_exists: contact_doc = frappe.get_doc({ "doctype": "Contact", @@ -288,7 +299,7 @@ def upsert_client(data): }).insert(ignore_permissions=True) print("Created new contact:", contact_doc.as_dict()) else: - contact_doc = frappe.get_doc("Contact", {"email_id": data.get("email")}) + contact_doc = frappe.get_doc("Contact", {"email_id": contact_data.get("email"), "phone": contact_data.get("phone_number")}) print("Contact already exists:", contact_doc.as_dict()) contact_docs.append(contact_doc) diff --git a/custom_ui/install.py b/custom_ui/install.py index 4608a1e..eaf8bf3 100644 --- a/custom_ui/install.py +++ b/custom_ui/install.py @@ -1,5 +1,6 @@ import os import subprocess +import sys import frappe from .utils import create_module @@ -70,6 +71,15 @@ def add_custom_fields(): print("\nšŸ”§ Adding custom fields to Address doctype...") custom_fields = { + "Lead": [ + dict( + fieldname="customer_type", + label="Customer Type", + fieldtype="Select", + options="Individual\nCompany\nPartnership", + insert_after="lead_name" + ) + ], "Address": [ dict( fieldname="full_address", @@ -315,21 +325,29 @@ def update_address_fields(): filled_length = int(bar_length * index // total_addresses) bar = 'ā–ˆ' * filled_length + 'ā–‘' * (bar_length - filled_length) - # Print a three-line, refreshing progress block to avoid terminal wrap + # Print a three-line, refreshing progress block without adding new lines each loop progress_line = f"šŸ“Š Progress: [{bar}] {progress_percentage:3d}% ({index}/{total_addresses})" counters_line = f" Fields updated: {total_field_updates} | Addresses updated: {addresses_updated}" detail_line = f" Processing: {name[:40]}..." if index == 1: - # Save cursor position at the start of the progress block - print("\033[s", end='') + # First render: write the three lines + sys.stdout.write( + f"\r\033[K{progress_line}\n" + f"\033[K{counters_line}\n" + f"\033[K{detail_line}" + ) else: - # Restore to the saved cursor position to rewrite the three-line block - print("\033[u", end='') + # Move cursor up 3 lines, then rewrite each line in place + sys.stdout.write("\033[2F") + sys.stdout.write(f"\r\033[K{progress_line}\n") + sys.stdout.write(f"\033[K{counters_line}\n") + sys.stdout.write(f"\033[K{detail_line}") - print(f"\r\033[K{progress_line}") - print(f"\r\033[K{counters_line}") - print(f"\r\033[K{detail_line}", end='' if index != total_addresses else '\n', flush=True) + if index == total_addresses: + sys.stdout.write("\n") + + sys.stdout.flush() should_update = False address = frappe.get_doc("Address", name) diff --git a/frontend/src/App.vue b/frontend/src/App.vue index afbda38..9908ed4 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -1,7 +1,6 @@ @@ -41,7 +41,7 @@ const fontSize = computed(() => { } .company-select { - width: 170px; + width: 100%; } :deep(.p-select) { diff --git a/frontend/src/components/SideBar.vue b/frontend/src/components/SideBar.vue index c18f739..4f5e0d2 100644 --- a/frontend/src/components/SideBar.vue +++ b/frontend/src/components/SideBar.vue @@ -3,6 +3,7 @@ import { ref, nextTick } from "vue"; import { useRouter } from "vue-router"; import { useModalStore } from "@/stores/modal"; import { useNotificationStore } from "@/stores/notifications-primevue" +import CompanySelector from "./CompanySelector.vue"; import { Home, Community, @@ -153,6 +154,9 @@ const handleCategoryClick = (category) => {