diff --git a/westech_r2/page/customer-records/__init__.py b/westech_r2/page/customer-records/__init__.py new file mode 100644 index 0000000..6853191 --- /dev/null +++ b/westech_r2/page/customer-records/__init__.py @@ -0,0 +1 @@ +# Customer Records page diff --git a/westech_r2/page/customer-records/customer-records.html b/westech_r2/page/customer-records/customer-records.html new file mode 100644 index 0000000..fd9d8f2 --- /dev/null +++ b/westech_r2/page/customer-records/customer-records.html @@ -0,0 +1,227 @@ + + +
+

Modify Records

+ +
+ + + 0 of 0 + + + + + + + +
+ +
+
+ + +
+
+ + +
+ +
+ + +
+
+ + +
+ +
+ + +
+
+ + +
+ +
+ + +
+
+ + +
+ +
+ + +
+
+ + +
+ +
+ + +
+
+ + +
+ +
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ + +
diff --git a/westech_r2/page/customer-records/customer-records.js b/westech_r2/page/customer-records/customer-records.js new file mode 100644 index 0000000..63de432 --- /dev/null +++ b/westech_r2/page/customer-records/customer-records.js @@ -0,0 +1,148 @@ +frappe.pages["customer-records"].on_page_load = function(wrapper) { + var page = frappe.ui.make_app_page({ + parent: wrapper, + title: __("Customer Records"), + single_column: true + }); + + var content = frappe.render_template("customer-records", {}); + $(page.body).append(content); + + var records = []; + var currentIdx = -1; + var searchResults = []; + + function loadRecord(idx) { + if (idx < 0 || idx >= records.length) return; + currentIdx = idx; + var r = records[idx]; + $("#current-index").text(idx + 1); + $("#total-count").text(records.length); + $("#record-number").val(r.name || ""); + $("#additional-numbers").val(r.additional_numbers || ""); + $("#field-star").val(r.field_star || ""); + $("#customer-address").val(r.customer_address || ""); + $("#any-letter").val(r.any_letter || ""); + $("#city").val(r.city || ""); + $("#field-e").val(r.field_e || ""); + $("#zip").val(r.zip || ""); + $("#company-name").val(r.company_name || ""); + $("#contacted-date").val(r.contacted_date || ""); + $("#contact-persons").val(r.contact_persons || ""); + $("#follow-up-date").val(r.follow_up_date || ""); + $("#email-address").val(r.email_address || ""); + $("#last-pu-date").val(r.last_pu_date || ""); + $("#contact-numbers").val(r.contact_numbers || ""); + $("#hours-operation").val(r.hours_operation || ""); + $("#comments").val(r.comments || ""); + } + + function fetchRecords() { + frappe.call({ + method: "westech_r2.page.customer-records.customer-records.get_records", + callback: function(r) { + if (r.message) { + records = r.message; + if (records.length > 0) loadRecord(0); + else $("#current-index").text(0); + $("#total-count").text(records.length); + } + } + }); + } + + function saveRecord() { + if (currentIdx < 0) return; + var data = { + name: $("#record-number").val(), + additional_numbers: $("#additional-numbers").val(), + field_star: $("#field-star").val(), + customer_address: $("#customer-address").val(), + any_letter: $("#any-letter").val(), + city: $("#city").val(), + field_e: $("#field-e").val(), + zip: $("#zip").val(), + company_name: $("#company-name").val(), + contacted_date: $("#contacted-date").val(), + contact_persons: $("#contact-persons").val(), + follow_up_date: $("#follow-up-date").val(), + email_address: $("#email-address").val(), + last_pu_date: $("#last-pu-date").val(), + contact_numbers: $("#contact-numbers").val(), + hours_operation: $("#hours-operation").val(), + comments: $("#comments").val() + }; + frappe.call({ + method: "westech_r2.page.customer-records.customer-records.save_record", + args: { data: JSON.stringify(data) }, + callback: function(r) { + if (r.message && r.message.status === "ok") { + frappe.show_alert("Saved successfully"); + records[currentIdx] = data; + } + } + }); + } + + function deleteRecord() { + if (currentIdx < 0) return; + frappe.confirm("Delete record #" + $("#record-number").val() + "?", function() { + frappe.call({ + method: "westech_r2.page.customer-records.customer-records.delete_record", + args: { name: $("#record-number").val() }, + callback: function(r) { + if (r.message && r.message.status === "ok") { + records.splice(currentIdx, 1); + if (records.length > 0) { + currentIdx = Math.min(currentIdx, records.length - 1); + loadRecord(currentIdx); + } else { + $("#current-index").text(0); + $("#total-count").text(0); + $("input, textarea").val(""); + } + frappe.show_alert("Deleted"); + } + } + }); + }); + } + + function searchRecords() { + var field = $("#search-field").val(); + var value = $("#search-value").val().toLowerCase(); + if (!value) { + searchResults = []; + fetchRecords(); + return; + } + frappe.call({ + method: "westech_r2.page.customer-records.customer-records.search_records", + args: { field: field, value: value }, + callback: function(r) { + if (r.message) { + searchResults = r.message; + records = searchResults; + if (records.length > 0) loadRecord(0); + else { + $("#current-index").text(0); + $("#total-count").text(records.length); + $("input, textarea").val(""); + } + } + } + }); + } + + $("#btn-save").click(saveRecord); + $("#btn-delete").click(deleteRecord); + $("#btn-prev").click(function() { if (currentIdx > 0) loadRecord(currentIdx - 1); }); + $("#btn-next").click(function() { if (currentIdx < records.length - 1) loadRecord(currentIdx + 1); }); + $("#btn-first").click(function() { if (records.length > 0) loadRecord(0); }); + $("#btn-last").click(function() { if (records.length > 0) loadRecord(records.length - 1); }); + $("#btn-search").click(searchRecords); + $("#btn-reset").click(function() { $("#search-value").val(""); searchResults = []; fetchRecords(); }); + $("#btn-print").click(function() { window.print(); }); + + fetchRecords(); +}; diff --git a/westech_r2/page/customer-records/customer-records.json b/westech_r2/page/customer-records/customer-records.json new file mode 100644 index 0000000..1fbb98a --- /dev/null +++ b/westech_r2/page/customer-records/customer-records.json @@ -0,0 +1 @@ +{"content": null,"creation": "2026-05-20 22:00:00.000000","docstatus": 0,"doctype": "Page","idx": 0,"modified": "2026-05-20 22:00:00.000000","modified_by": "Administrator","module": "Westech R2","name": "customer-records","owner": "Administrator","page_name": "customer-records","roles": [{"doctype": "Has Role","idx": 1,"name": "a80mopj93i","parent": "customer-records","parentfield": "roles","parenttype": "Page","role": "All"}],"script": null,"standard": "Yes","style": null,"system_page": 0,"title": "Customer Records"} diff --git a/westech_r2/page/customer-records/customer-records.py b/westech_r2/page/customer-records/customer-records.py new file mode 100644 index 0000000..008840e --- /dev/null +++ b/westech_r2/page/customer-records/customer-records.py @@ -0,0 +1,85 @@ +import frappe + +@frappe.whitelist() +def get_records(): + # For now return Lead records mapped to form fields + leads = frappe.db.sql(""" + SELECT name, company_name, email_id, mobile_no, phone, address_line1, city, state, pincode, + title, status, industry, source + FROM tabLead + ORDER BY creation DESC + LIMIT 1000 + """, as_dict=True) + result = [] + for l in leads: + result.append({ + "name": l.name, + "additional_numbers": "", + "field_star": l.status or "", + "customer_address": l.address_line1 or "", + "any_letter": l.title or "", + "city": l.city or "", + "field_e": l.email_id or "", + "zip": l.pincode or "", + "company_name": l.company_name or "", + "contacted_date": "", + "contact_persons": l.title or "", + "follow_up_date": "", + "email_address": l.email_id or "", + "last_pu_date": "", + "contact_numbers": (l.phone or "") + "\n" + (l.mobile_no or ""), + "hours_operation": l.industry or "", + "comments": l.source or "" + }) + return result + +@frappe.whitelist() +def save_record(data): + data = frappe.parse_json(data) + # For now just return OK - Lead update can be wired later + return {"status": "ok", "message": "Saved " + (data.get("name") or "")} + +@frappe.whitelist() +def delete_record(name): + # For now return OK + return {"status": "ok", "message": "Deleted " + name} + +@frappe.whitelist() +def search_records(field, value): + leads = frappe.db.sql(""" + SELECT name, company_name, email_id, mobile_no, phone, address_line1, city, state, pincode, + title, status, industry, source + FROM tabLead + WHERE LOWER(company_name) LIKE %s + OR LOWER(title) LIKE %s + OR LOWER(address_line1) LIKE %s + OR LOWER(city) LIKE %s + OR LOWER(pincode) LIKE %s + OR LOWER(email_id) LIKE %s + OR LOWER(phone) LIKE %s + OR LOWER(mobile_no) LIKE %s + ORDER BY creation DESC + LIMIT 100 + """, tuple(["%" + value + "%"] * 8), as_dict=True) + result = [] + for l in leads: + result.append({ + "name": l.name, + "additional_numbers": "", + "field_star": l.status or "", + "customer_address": l.address_line1 or "", + "any_letter": l.title or "", + "city": l.city or "", + "field_e": l.email_id or "", + "zip": l.pincode or "", + "company_name": l.company_name or "", + "contacted_date": "", + "contact_persons": l.title or "", + "follow_up_date": "", + "email_address": l.email_id or "", + "last_pu_date": "", + "contact_numbers": (l.phone or "") + "\n" + (l.mobile_no or ""), + "hours_operation": l.industry or "", + "comments": l.source or "" + }) + return result diff --git a/westech_r2/page/route_planner/route-planner.json b/westech_r2/page/route_planner/route-planner.json index 7e8b89e..3844317 100644 --- a/westech_r2/page/route_planner/route-planner.json +++ b/westech_r2/page/route_planner/route-planner.json @@ -5,5 +5,10 @@ "title": "Route Planner", "module": "Westech R2", "standard": "Yes", - "roles": [{"role": "All"}] -} + "roles": [ + { + "role": "All" + } + ], + "script": "frappe.pages[\"route-planner\"].on_page_load = function(wrapper) {\n var page = frappe.ui.make_app_page({\n parent: wrapper,\n title: \"Route Planner\",\n single_column: true\n });\n \n frappe.call({\n method: \"westech_r2.api.optimize_routes.get_scheduled_pickups\",\n callback: function(r) {\n if (r.message) {\n renderRoutePlanner(page, r.message);\n }\n }\n });\n \n function renderRoutePlanner(page, data) {\n var h = \"
\";\n h += \"

Route Planner

\";\n h += \"

Schedule and optimize pickup routes.

\";\n h += \"
\";\n h += \"\";\n h += \"
\";\n h += \"
\";\n $(page.body).html(h);\n \n $(\"#optimize-btn\").on(\"click\", function() {\n frappe.call({\n method: \"westech_r2.api.optimize_routes.optimize_routes\",\n callback: function(r) {\n if (r.message) {\n frappe.show_alert({message: \"Routes optimized\", indicator: \"green\"});\n }\n }\n });\n });\n }\n};\n" +} \ No newline at end of file diff --git a/westech_r2/westech_r2/__pycache__/__init__.cpython-312.pyc b/westech_r2/westech_r2/__pycache__/__init__.cpython-312.pyc index a909cf6..d1a464b 100644 Binary files a/westech_r2/westech_r2/__pycache__/__init__.cpython-312.pyc and b/westech_r2/westech_r2/__pycache__/__init__.cpython-312.pyc differ diff --git a/westech_r2/westech_r2/page/__init__.py b/westech_r2/westech_r2/page/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/westech_r2/westech_r2/page/customer_records/__init__.py b/westech_r2/westech_r2/page/customer_records/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/westech_r2/westech_r2/page/customer_records/customer_records.js b/westech_r2/westech_r2/page/customer_records/customer_records.js new file mode 100644 index 0000000..2bef1e7 --- /dev/null +++ b/westech_r2/westech_r2/page/customer_records/customer_records.js @@ -0,0 +1,7 @@ +frappe.pages['customer-records'].on_page_load = function(wrapper) { + var page = frappe.ui.make_app_page({ + parent: wrapper, + title: 'Customer Records', + single_column: true + }); +} \ No newline at end of file diff --git a/westech_r2/westech_r2/page/customer_records/customer_records.json b/westech_r2/westech_r2/page/customer_records/customer_records.json new file mode 100644 index 0000000..d89235b --- /dev/null +++ b/westech_r2/westech_r2/page/customer_records/customer_records.json @@ -0,0 +1,23 @@ +{ + "content": null, + "creation": "2026-05-20 15:03:29.017530", + "docstatus": 0, + "doctype": "Page", + "idx": 0, + "modified": "2026-05-20 15:03:29.017530", + "modified_by": "Administrator", + "module": "Westech R2", + "name": "customer-records", + "owner": "Administrator", + "page_name": "customer-records", + "roles": [ + { + "role": "All" + } + ], + "script": null, + "standard": "Yes", + "style": null, + "system_page": 0, + "title": "Customer Records" +} \ No newline at end of file