diff --git a/custom_ui/api/db/estimates.py b/custom_ui/api/db/estimates.py index f39c191..ab1a9af 100644 --- a/custom_ui/api/db/estimates.py +++ b/custom_ui/api/db/estimates.py @@ -91,7 +91,7 @@ def get_estimate_from_address(full_address): # return build_success_response(quotation) # else: # return build_error_response("No quotation found for the given address.", 404) - + # @frappe.whitelist() # def send_estimate_email(estimate_name): # print("DEBUG: Queuing email send job for estimate:", estimate_name) @@ -103,31 +103,31 @@ def get_estimate_from_address(full_address): # ) # return build_success_response("Email queued for sending.") -@frappe.whitelist() +@frappe.whitelist() def send_estimate_email(estimate_name): # def send_estimate_email_job(estimate_name): try: print("DEBUG: Sending estimate email for:", estimate_name) quotation = frappe.get_doc("Quotation", estimate_name) - + party_exists = frappe.db.exists(quotation.quotation_to, quotation.party_name) if not party_exists: return build_error_response("No email found for the customer.", 400) party = frappe.get_doc(quotation.quotation_to, quotation.party_name) - + email = None if (getattr(party, 'email_id', None)): email = party.email_id elif (getattr(party, 'contact_ids', None) and len(party.email_ids) > 0): primary = next((e for e in party.email_ids if e.is_primary), None) email = primary.email_id if primary else party.email_ids[0].email_id - + if not email and quotation.custom_installation_address: address = frappe.get_doc("Address", quotation.custom_installation_address) email = getattr(address, 'email_id', None) if not email: return build_error_response("No email found for the customer or address.", 400) - + # email = "casey@shilohcode.com" template_name = "Quote with Actions - SNW" template = frappe.get_doc("Email Template", template_name) @@ -161,6 +161,30 @@ def send_estimate_email(estimate_name): print(f"DEBUG: Error in send_estimate_email: {str(e)}") return build_error_response(str(e), 500) + +@frappe.whitelist() +def manual_response(name, response): + """Update the response for an estimate in the UI.""" + print("DEBUG: RESPONSE_RECEIVED:", name, response) + try: + if not frappe.db.exists("Quotation", name): + raise Exception("Estimate not found.") + estimate = frappe.get_doc("Quotation", name) + if estimate.docstatus != 1: + raise Exception("Estimate must be submitted to update response.") + accepted = True if response == "Accepted" else False + new_status = "Estimate Accepted" if accepted else "Lost" + + estimate.custom_response = response + estimate.custom_current_status = new_status + estimate.status = "Ordered" if accepted else "Closed" + estimate.flags.ignore_permissions = True + print("DEBUG: Updating estimate with response:", response, "and status:", new_status) + estimate.save() + except Exception as e: + return e + + @frappe.whitelist(allow_guest=True) def update_response(name, response): """Update the response for a given estimate.""" @@ -181,7 +205,7 @@ def update_response(name, response): estimate.flags.ignore_permissions = True print("DEBUG: Updating estimate with response:", response, "and status:", new_status) estimate.save() - + if accepted: template = "custom_ui/templates/estimates/accepted.html" if check_if_customer(estimate.party_name): @@ -200,8 +224,8 @@ def update_response(name, response): html = frappe.render_template(template, {"error_message": str(e)}) return Response(html, mimetype="text/html") - - + + @frappe.whitelist() def upsert_estimate(data): @@ -209,19 +233,19 @@ def upsert_estimate(data): try: data = json.loads(data) if isinstance(data, str) else data print("DEBUG: Upsert estimate data:", data) - + estimate_name = data.get("estimate_name") - + # If estimate_name exists, update existing estimate if estimate_name: print(f"DEBUG: Updating existing estimate: {estimate_name}") estimate = frappe.get_doc("Quotation", estimate_name) - + # Update fields estimate.custom_installation_address = data.get("address_name") estimate.party_name = data.get("contact_name") estimate.custom_requires_half_payment = data.get("requires_half_payment", 0) - + # Clear existing items and add new ones estimate.items = [] for item in data.get("items", []): @@ -230,11 +254,11 @@ def upsert_estimate(data): "item_code": item.get("item_code"), "qty": item.get("qty"), }) - + estimate.save() print(f"DEBUG: Estimate updated: {estimate.name}") return build_success_response(estimate.as_dict()) - + # Otherwise, create new estimate else: print("DEBUG: Creating new estimate") @@ -261,4 +285,4 @@ def upsert_estimate(data): except Exception as e: print(f"DEBUG: Error in upsert_estimate: {str(e)}") return build_error_response(str(e), 500) - \ No newline at end of file + diff --git a/frontend/src/api.js b/frontend/src/api.js index 2641421..30454e4 100644 --- a/frontend/src/api.js +++ b/frontend/src/api.js @@ -11,6 +11,7 @@ const FRAPPE_GET_ESTIMATES_METHOD = "custom_ui.api.db.estimates.get_estimate_tab const FRAPPE_GET_ESTIMATE_BY_ADDRESS_METHOD = "custom_ui.api.db.estimates.get_estimate_from_address"; const FRAPPE_SEND_ESTIMATE_EMAIL_METHOD = "custom_ui.api.db.estimates.send_estimate_email"; const FRAPPE_LOCK_ESTIMATE_METHOD = "custom_ui.api.db.estimates.lock_estimate"; +const FRAPPE_ESTIMATE_UPDATE_RESPONSE_METHOD = "custom_ui.api.db.estimates.manual_response"; // Job methods const FRAPPE_GET_JOBS_METHOD = "custom_ui.api.db.get_jobs"; const FRAPPE_UPSERT_JOB_METHOD = "custom_ui.api.db.jobs.upsert_job"; @@ -203,6 +204,10 @@ class Api { return await this.request(FRAPPE_LOCK_ESTIMATE_METHOD, { estimateName }); } + static async updateEstimateResponse(estimateName, response) { + return await this.request(FRAPPE_ESTIMATE_UPDATE_RESPONSE_METHOD, {name: estimateName, response}); + } + // ============================================================================ // JOB / PROJECT METHODS // ============================================================================ diff --git a/frontend/src/components/pages/Estimate.vue b/frontend/src/components/pages/Estimate.vue index 368a64f..e6b1275 100644 --- a/frontend/src/components/pages/Estimate.vue +++ b/frontend/src/components/pages/Estimate.vue @@ -2,6 +2,7 @@