From 20b3c1166f52d57daae3cff0b1924810d8398728 Mon Sep 17 00:00:00 2001 From: rocketdebris Date: Fri, 7 Nov 2025 15:28:22 -0500 Subject: [PATCH] Added Job Modal. --- custom_ui/api/db.py | 53 +-- frontend/src/App.vue | 2 + frontend/src/api.js | 8 + frontend/src/components/SideBar.vue | 4 +- .../src/components/modals/CreateJobModal.vue | 324 ++++++++++++++++++ 5 files changed, 369 insertions(+), 22 deletions(-) create mode 100644 frontend/src/components/modals/CreateJobModal.vue diff --git a/custom_ui/api/db.py b/custom_ui/api/db.py index dca46d0..a01bbef 100644 --- a/custom_ui/api/db.py +++ b/custom_ui/api/db.py @@ -160,6 +160,17 @@ def get_clients(options): "data": tableRows if options["for_table"] else clients } + +@frappe.whitelist() +def upsert_estimate(data): + pass + + +@frappe.whitelist() +def upsert_job(data): + pass + + @frappe.whitelist() def upsert_client(data): data = json.loads(data) @@ -330,10 +341,10 @@ def get_warranty_claims(options): } options = {**defaultOptions, **options} print("DEBUG: Final warranty options:", options) - + warranties = [] tableRows = [] - + # Map frontend field names to backend field names for Warranty Claim doctype def map_warranty_field_name(frontend_field): field_mapping = { @@ -350,7 +361,7 @@ def get_warranty_claims(options): "warrantyStatus": "warranty_amc_status" } return field_mapping.get(frontend_field, frontend_field) - + # Process filters from PrimeVue format to Frappe format processed_filters = {} if options["filters"]: @@ -359,12 +370,12 @@ def get_warranty_claims(options): if filter_obj["value"] is not None and filter_obj["value"] != "": # Map frontend field names to backend field names backend_field = map_warranty_field_name(field_name) - + # Handle different match modes match_mode = filter_obj.get("matchMode", "contains") if isinstance(match_mode, str): match_mode = match_mode.lower() - + if match_mode in ("contains", "contains"): processed_filters[backend_field] = ["like", f"%{filter_obj['value']}%"] elif match_mode in ("startswith", "startsWith"): @@ -376,7 +387,7 @@ def get_warranty_claims(options): else: # Default to contains processed_filters[backend_field] = ["like", f"%{filter_obj['value']}%"] - + # Process sorting order_by = None if options.get("sorting") and options["sorting"]: @@ -390,31 +401,31 @@ def get_warranty_claims(options): # Map frontend field to backend field backend_sort_field = map_warranty_field_name(sort_field) order_by = f"{backend_sort_field} {sort_direction}" - + print("DEBUG: Processed warranty filters:", processed_filters) print("DEBUG: Warranty order by:", order_by) - + count = frappe.db.count("Warranty Claim", filters=processed_filters) print("DEBUG: Total warranty claims count:", count) - + warranty_claims = frappe.db.get_all( - "Warranty Claim", - fields=options["fields"], + "Warranty Claim", + fields=options["fields"], filters=processed_filters, limit=options["page_size"], start=(options["page"] - 1) * options["page_size"], order_by=order_by ) - + for warranty in warranty_claims: warranty_obj = {} tableRow = {} - + tableRow["id"] = warranty["name"] tableRow["warrantyId"] = warranty["name"] tableRow["customer"] = warranty.get("customer_name", "") tableRow["serviceAddress"] = warranty.get("service_address", warranty.get("address_display", "")) - + # Extract a brief description from the complaint HTML complaint_text = warranty.get("complaint", "") if complaint_text: @@ -426,7 +437,7 @@ def get_warranty_claims(options): tableRow["issueDescription"] = clean_text else: tableRow["issueDescription"] = "" - + tableRow["status"] = warranty.get("status", "") tableRow["complaintDate"] = warranty.get("complaint_date", "") tableRow["complaintRaisedBy"] = warranty.get("complaint_raised_by", "") @@ -434,7 +445,7 @@ def get_warranty_claims(options): tableRow["territory"] = warranty.get("territory", "") tableRow["resolutionDate"] = warranty.get("resolution_date", "") tableRow["warrantyStatus"] = warranty.get("warranty_amc_status", "") - + # Add priority based on status and date (can be customized) if warranty.get("status") == "Open": # Calculate priority based on complaint date @@ -444,7 +455,7 @@ def get_warranty_claims(options): complaint_date = datetime.strptime(complaint_date, "%Y-%m-%d").date() elif isinstance(complaint_date, datetime): complaint_date = complaint_date.date() - + days_old = (date.today() - complaint_date).days if days_old > 7: tableRow["priority"] = "High" @@ -456,12 +467,12 @@ def get_warranty_claims(options): tableRow["priority"] = "Medium" else: tableRow["priority"] = "Low" - + tableRows.append(tableRow) - + warranty_obj["warranty_claim"] = warranty warranties.append(warranty_obj) - + return { "pagination": { "total": count, @@ -470,4 +481,4 @@ def get_warranty_claims(options): "total_pages": (count + options["page_size"] - 1) // options["page_size"] }, "data": tableRows if options["for_table"] else warranties - } \ No newline at end of file + } diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 5ffbcc7..b768b61 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -3,6 +3,7 @@ import { IconoirProvider } from "@iconoir/vue"; import SideBar from "./components/SideBar.vue"; import CreateClientModal from "./components/modals/CreateClientModal.vue"; import CreateEstimateModal from "./components/modals/CreateEstimateModal.vue"; +import CreateJobModal from "./components/modals/CreateJobModal.vue"; import GlobalLoadingOverlay from "./components/common/GlobalLoadingOverlay.vue"; import ScrollPanel from "primevue/scrollpanel"; @@ -28,6 +29,7 @@ import ScrollPanel from "primevue/scrollpanel"; + diff --git a/frontend/src/api.js b/frontend/src/api.js index 910362d..f10b96f 100644 --- a/frontend/src/api.js +++ b/frontend/src/api.js @@ -4,6 +4,7 @@ const ZIPPOPOTAMUS_BASE_URL = "https://api.zippopotam.us/us"; const FRAPPE_PROXY_METHOD = "custom_ui.api.proxy.request"; const FRAPPE_UPSERT_CLIENT_METHOD = "custom_ui.api.db.upsert_client"; const FRAPPE_UPSERT_ESTIMATE_METHOD = "custom_ui.api.db.upsert_estimate"; +const FRAPPE_UPSERT_JOB_METHOD = "custom_ui.api.db.upsert_job"; class Api { static async request(frappeMethod, args = {}) { @@ -417,6 +418,13 @@ class Api { return result; } + static async createJob(jobData) { + const payload = DataUtils.toSnakeCaseObject(jobData); + const result = await this.request(FRAPPE_UPSERT_JOB_METHOD, { data: payload }); + console.log("DEBUG: API - Created Job: ", result); + return result + } + // External API calls /** diff --git a/frontend/src/components/SideBar.vue b/frontend/src/components/SideBar.vue index d2603f1..090e301 100644 --- a/frontend/src/components/SideBar.vue +++ b/frontend/src/components/SideBar.vue @@ -40,7 +40,9 @@ const createButtons = ref([ { label: "Job", command: () => { - frappe.new_doc("Job"); + //frappe.new_doc("Job"); + console.log("New Job"); + modalStore.openModal("createJob"); }, }, { diff --git a/frontend/src/components/modals/CreateJobModal.vue b/frontend/src/components/modals/CreateJobModal.vue new file mode 100644 index 0000000..6040186 --- /dev/null +++ b/frontend/src/components/modals/CreateJobModal.vue @@ -0,0 +1,324 @@ + + + + +