diff --git a/westech_r2/__pycache__/__init__.cpython-312.pyc b/westech_r2/__pycache__/__init__.cpython-312.pyc
deleted file mode 100644
index 0b2fbe3..0000000
Binary files a/westech_r2/__pycache__/__init__.cpython-312.pyc and /dev/null differ
diff --git a/westech_r2/__pycache__/hooks.cpython-312.pyc b/westech_r2/__pycache__/hooks.cpython-312.pyc
deleted file mode 100644
index 1438909..0000000
Binary files a/westech_r2/__pycache__/hooks.cpython-312.pyc and /dev/null differ
diff --git a/westech_r2/api/__init__.py b/westech_r2/api/__init__.py
index 9219fdc..99e389c 100644
--- a/westech_r2/api/__init__.py
+++ b/westech_r2/api/__init__.py
@@ -1,2 +1,3 @@
from westech_r2.api import sales
+from westech_r2.api import receiving_api
diff --git a/westech_r2/api/__pycache__/__init__.cpython-312.pyc b/westech_r2/api/__pycache__/__init__.cpython-312.pyc
deleted file mode 100644
index 5dd511c..0000000
Binary files a/westech_r2/api/__pycache__/__init__.cpython-312.pyc and /dev/null differ
diff --git a/westech_r2/api/__pycache__/optimize_routes.cpython-312.pyc b/westech_r2/api/__pycache__/optimize_routes.cpython-312.pyc
deleted file mode 100644
index 2be405b..0000000
Binary files a/westech_r2/api/__pycache__/optimize_routes.cpython-312.pyc and /dev/null differ
diff --git a/westech_r2/api/__pycache__/sales.cpython-312.pyc b/westech_r2/api/__pycache__/sales.cpython-312.pyc
deleted file mode 100644
index 57d58b9..0000000
Binary files a/westech_r2/api/__pycache__/sales.cpython-312.pyc and /dev/null differ
diff --git a/westech_r2/api/receiving_api.py b/westech_r2/api/receiving_api.py
new file mode 100644
index 0000000..07b203f
--- /dev/null
+++ b/westech_r2/api/receiving_api.py
@@ -0,0 +1,322 @@
+import json
+import frappe
+from frappe.utils import today, getdate, add_days
+from datetime import timedelta
+
+@frappe.whitelist()
+def get_pickups(date=None):
+ """Fetch scheduled pickups with optional date filter.
+ Returns pickups, calendar (next 30 days), and weekly chart data."""
+ filters = []
+ if date:
+ filters.append(["Scheduled Pickup", "pickup_date", "=", date])
+
+ fields = [
+ "name", "pickup_date", "pickup_type", "status", "truck", "stop_order",
+ "customer_number", "company_name",
+ "contact_name", "contact_phone", "contact_email",
+ "address_line", "city", "state", "zip_code",
+ "latitude", "longitude",
+ "estimated_items", "estimated_weight", "load_contents",
+ "num_labels", "data_status", "red_r2",
+ "notes", "legacy_notes", "needs_aor", "needs_cod",
+ ]
+
+ pickups = frappe.get_list("Scheduled Pickup",
+ fields=fields,
+ filters=filters if filters else None,
+ order_by="pickup_date asc, stop_order asc",
+ limit_page_length=500,
+ )
+
+ # Build calendar data (next 30 days)
+ from_date = getdate(today())
+ to_date = add_days(from_date, 30)
+
+ all_pickups = frappe.get_list("Scheduled Pickup",
+ fields=["pickup_date"],
+ filters=[["Scheduled Pickup", "pickup_date", ">=", str(from_date)],
+ ["Scheduled Pickup", "pickup_date", "<=", str(to_date)]],
+ limit_page_length=500,
+ )
+
+ pickup_counts = {}
+ for p in all_pickups:
+ d = p.get("pickup_date", "")
+ if d:
+ pickup_counts[d] = pickup_counts.get(d, 0) + 1
+
+ calendar = []
+ for i in range(30):
+ d = add_days(from_date, i)
+ ds = str(d)
+ calendar.append({"date": ds, "count": pickup_counts.get(ds, 0)})
+
+ # Build weekly chart data (last 12 weeks)
+ weekly = []
+ for i in range(11, -1, -1):
+ week_start = add_days(from_date, -(from_date.weekday() + 7 * i))
+ week_end = add_days(week_start, 6)
+ count = 0
+ for d_str, c in pickup_counts.items():
+ try:
+ d = getdate(d_str)
+ if week_start <= d <= week_end:
+ count += c
+ except (ValueError, TypeError):
+ pass
+ weekly.append({"label": week_start.strftime("%m/%d"), "count": count})
+
+ return {
+ "pickups": pickups,
+ "calendar": calendar,
+ "weekly": weekly,
+ }
+
+
+@frappe.whitelist()
+def auto_route(date=None):
+ """Auto-assign pickups to trucks based on capacity and proximity."""
+ if not date:
+ date = today()
+
+ pickups = frappe.get_list("Scheduled Pickup",
+ filters={"pickup_date": date},
+ fields=["name", "company_name", "estimated_items", "estimated_weight",
+ "latitude", "longitude", "pickup_type"],
+ limit_page_length=200,
+ )
+
+ if not pickups:
+ return {"success": True, "assigned": 0}
+
+ trucks = ["Truck 1", "Truck 2", "Truck 3"]
+ sorted_p = sorted(pickups, key=lambda p: (float(p.get("latitude") or 0), float(p.get("longitude") or 0)))
+ n = len(sorted_p)
+ assigned = 0
+
+ for i, p in enumerate(sorted_p):
+ if p.get("pickup_type") == "Drop-off":
+ truck = ""
+ else:
+ truck = trucks[i % 3] if n <= 3 else trucks[min(i * 3 // n, 2)]
+
+ doc = frappe.get_doc("Scheduled Pickup", p["name"])
+ doc.truck = truck
+ doc.status = "Routed" if truck else "Scheduled"
+ doc.stop_order = i + 1
+ doc.save()
+ assigned += 1
+
+ frappe.db.commit()
+ return {"success": True, "assigned": assigned}
+
+
+@frappe.whitelist()
+def get_checkins():
+ """Fetch completed check-ins."""
+ checkins = frappe.get_list("Scheduled Pickup",
+ filters={"status": ["in", ["Complete", "In Progress"]]},
+ fields=["name", "pickup_date", "pickup_type", "status",
+ "company_name", "customer_number",
+ "estimated_items", "estimated_weight", "load_contents",
+ "data_status", "red_r2", "notes"],
+ order_by="pickup_date desc",
+ limit_page_length=100,
+ )
+ return {"checkins": checkins}
+
+
+@frappe.whitelist()
+def cor_report():
+ """Generate Certificate of Recycling report."""
+ pickups = frappe.get_list("Scheduled Pickup",
+ filters={"status": "Complete"},
+ fields=["name", "pickup_date", "company_name", "customer_number",
+ "estimated_items", "estimated_weight", "load_contents",
+ "data_status", "red_r2", "needs_aor", "needs_cod"],
+ order_by="pickup_date desc",
+ limit_page_length=200,
+ )
+
+ html = "
No completed loads found.
"
+
+ html += ""
+ frappe.local.response["type"] = "html"
+ frappe.local.response["page_content"] = html
+
+
+@frappe.whitelist()
+def print_route_sheet(date=None):
+ """Generate printable route sheet."""
+ if not date:
+ date = today()
+
+ filters = {"pickup_date": date} if date else {}
+ pickups = frappe.get_list("Scheduled Pickup",
+ filters=filters,
+ fields=["name", "pickup_date", "pickup_type", "status", "truck", "stop_order",
+ "company_name", "contact_name", "contact_phone", "contact_email",
+ "address_line", "city", "state", "zip_code",
+ "estimated_items", "estimated_weight", "load_contents",
+ "data_status", "red_r2", "needs_aor", "needs_cod", "notes"],
+ order_by="truck asc, stop_order asc",
+ limit_page_length=200,
+ )
+
+ trucks = {}
+ unassigned = []
+ for p in pickups:
+ t = p.get("truck", "")
+ if t and t != "Unassigned":
+ trucks.setdefault(t, []).append(p)
+ else:
+ unassigned.append(p)
+
+ html = "⚠️ This is a PLACEHOLDER template. Replace with actual Green Sheet layout once the form spec is provided.
'
+
+ for p in pickups:
+ html += '')
- .html('
' + frappe.utils.escape_html(c.customer_name || c.name) + ' ' +
- (c.address_line1 ? '
' + frappe.utils.escape_html(c.address_line1) : '') +
- (c.city ? ', ' + c.city : '') +
- (c.phone ? '
' + c.phone + ' ' : ''));
- item.on("click", function() { fillForm(c); });
- list.append(item);
- });
- $("#no-match").hide();
- } else {
- $("#no-match").show();
- }
- }
- });
- }
-
- $("#intake-search").on("input", function() {
- clearTimeout(searchTimer);
- searchTimer = setTimeout(doSearch, 300);
- });
-
- $("#btn-add-new").click(function() {
- clearForm();
- $("#cust-name").val($("#intake-search").val());
- $("#cust-status").text("Adding new customer...");
- });
-
- $("#btn-save-cust").click(function() {
- var data = {
- customer_name: $("#cust-name").val(),
- customer_number: $("#cust-number").val(),
- phone: $("#cust-phone").val(),
- address_line1: $("#cust-address").val(),
- city: $("#cust-city").val(),
- state: $("#cust-state").val(),
- pincode: $("#cust-zip").val(),
- contact_persons: $("#cust-contacts").val(),
- email_id: $("#cust-email").val(),
- hours_of_operation: $("#cust-hours").val()
- };
- if (currentCustomer && currentCustomer.name) {
- data.name = currentCustomer.name;
- }
- frappe.call({
- method: "westech_r2.page.customer-intake.customer-intake.create_customer_from_intake",
- args: {data: JSON.stringify(data)},
- callback: function(r) {
- if (r.message && r.message.status === "ok") {
- currentCustomer = {name: r.message.customer, customer_name: data.customer_name};
- $("#cust-status").text("Saved: " + r.message.customer);
- frappe.show_alert("Customer saved", 3);
- } else {
- frappe.show_alert("Error saving customer", 5);
- }
- }
- });
- });
-
- $("#btn-create-pallet").click(function() {
- if (!currentCustomer || !currentCustomer.name) {
- frappe.msgprint("Please select or save a customer first.");
- return;
- }
- frappe.call({
- method: "westech_r2.page.customer-intake.customer-intake.create_pallet",
- args: {
- data: JSON.stringify({
- customer: currentCustomer.name,
- customer_number: $("#cust-number").val(),
- data_status: $("#pallet-data-status").val(),
- status: $("#pallet-status").val(),
- inbound_weight: $("#pallet-weight").val()
- })
- },
- callback: function(r) {
- if (r.message && r.message.status === "ok") {
- frappe.msgprint("Pallet created: " + r.message.pallet);
- $("#cust-status").text("Pallet: " + r.message.pallet);
- }
- }
- });
- });
-};
diff --git a/westech_r2/westech_r2/page/customer_intake/customer_intake.py b/westech_r2/westech_r2/page/customer_intake/customer_intake.py
deleted file mode 100644
index 544f5be..0000000
--- a/westech_r2/westech_r2/page/customer_intake/customer_intake.py
+++ /dev/null
@@ -1,84 +0,0 @@
-import frappe
-from frappe import _
-
-@frappe.whitelist()
-def search_customers(q=""):
- if not q or len(q) < 2:
- return []
- q = q.strip().lower()
- customers = frappe.db.sql("""
- SELECT c.name, c.customer_name, c.customer_number, c.phone, c.email_id,
- a.address_line1, a.city, a.state, a.pincode
- FROM tabCustomer c
- LEFT JOIN tabDynamic Link dl ON dl.link_doctype = 'Customer' AND dl.link_name = c.name AND dl.parenttype = 'Address'
- LEFT JOIN tabAddress a ON a.name = dl.parent
- WHERE LOWER(c.customer_name) LIKE %s OR LOWER(c.customer_number) LIKE %s OR LOWER(c.phone) LIKE %s
- ORDER BY c.customer_name
- LIMIT 20
- """, ("%" + q + "%", "%" + q + "%", "%" + q + "%"), as_dict=True)
- return customers
-
-@frappe.whitelist()
-def get_customer(name):
- if not name:
- return {}
- cust = frappe.get_doc("Customer", name)
- result = cust.as_dict()
- addr = frappe.db.sql("""
- SELECT a.address_line1, a.city, a.state, a.pincode, a.phone
- FROM tabAddress a
- JOIN tabDynamic Link dl ON dl.parent = a.name AND dl.link_doctype = 'Customer' AND dl.link_name = %s
- LIMIT 1
- """, (name,), as_dict=True)
- if addr:
- result.update({
- "address_line1": addr[0].address_line1,
- "city": addr[0].city,
- "state": addr[0].state,
- "pincode": addr[0].pincode,
- "address_phone": addr[0].phone
- })
- return result
-
-@frappe.whitelist()
-def create_customer_from_intake(data):
- data = frappe.parse_json(data)
- if not data.get("customer_name"):
- frappe.throw(_("Customer name required"))
- customer = frappe.new_doc("Customer")
- customer.customer_name = data.get("customer_name")
- customer.customer_group = data.get("customer_group", "IT Recycling")
- customer.customer_type = "Company"
- customer.customer_number = data.get("customer_number")
- customer.phone = data.get("phone")
- customer.email_id = data.get("email_id")
- customer.legacy_notes = data.get("legacy_notes")
- customer.hours_of_operation = data.get("hours_of_operation")
- customer.contact_persons = data.get("contact_persons")
- customer.save()
- if data.get("address_line1") or data.get("city"):
- addr = frappe.new_doc("Address")
- addr.address_title = customer.customer_name
- addr.address_type = "Billing"
- addr.address_line1 = data.get("address_line1", "Unknown")
- addr.city = data.get("city", "Unknown")
- addr.state = data.get("state", "")
- addr.pincode = data.get("pincode", "")
- addr.country = "United States"
- addr.append("links", {"link_doctype": "Customer", "link_name": customer.name})
- addr.save()
- return {"status": "ok", "customer": customer.name}
-
-@frappe.whitelist()
-def create_pallet(data):
- data = frappe.parse_json(data)
- if not data.get("customer"):
- frappe.throw(_("Customer required"))
- pallet = frappe.new_doc("Pallet")
- pallet.customer = data.get("customer")
- pallet.customer_number = data.get("customer_number")
- pallet.data_status = data.get("data_status", "D0")
- pallet.status = data.get("status", "Received")
- pallet.inbound_weight = data.get("inbound_weight", "")
- pallet.save()
- return {"status": "ok", "pallet": pallet.name}
diff --git a/westech_r2/westech_r2/page/customer_records/__init__.py b/westech_r2/westech_r2/page/customer_records/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/westech_r2/westech_r2/page/customer_records/customer-records.json b/westech_r2/westech_r2/page/customer_records/customer-records.json
deleted file mode 100644
index 1fbb98a..0000000
--- a/westech_r2/westech_r2/page/customer_records/customer-records.json
+++ /dev/null
@@ -1 +0,0 @@
-{"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/westech_r2/page/customer_records/customer_records.html b/westech_r2/westech_r2/page/customer_records/customer_records.html
deleted file mode 100644
index fd9d8f2..0000000
--- a/westech_r2/westech_r2/page/customer_records/customer_records.html
+++ /dev/null
@@ -1,227 +0,0 @@
-
-
-
-
Modify Records
-
-
- Save
-
- 0 of 0
-
- <
- >
- <<
- >>
- Delete
- Print
-
-
-
-
-
- SEARCH:
-
- Address
- Company Name
- Contact Person
- Phone
- Email
- City
- Zip
- Record #
-
- FOR
-
- Search!
- Reset
-
-
diff --git a/westech_r2/westech_r2/page/customer_records/customer_records.js b/westech_r2/westech_r2/page/customer_records/customer_records.js
deleted file mode 100644
index 2bef1e7..0000000
--- a/westech_r2/westech_r2/page/customer_records/customer_records.js
+++ /dev/null
@@ -1,7 +0,0 @@
-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
deleted file mode 100644
index d89235b..0000000
--- a/westech_r2/westech_r2/page/customer_records/customer_records.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "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
diff --git a/westech_r2/westech_r2/page/customer_records/customer_records.py b/westech_r2/westech_r2/page/customer_records/customer_records.py
deleted file mode 100644
index 008840e..0000000
--- a/westech_r2/westech_r2/page/customer_records/customer_records.py
+++ /dev/null
@@ -1,85 +0,0 @@
-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/westech_r2/page/ebay-pricing/__init__.py b/westech_r2/westech_r2/page/ebay-pricing/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/westech_r2/westech_r2/page/ebay-pricing/ebay-pricing.css b/westech_r2/westech_r2/page/ebay-pricing/ebay-pricing.css
deleted file mode 100644
index 8b27534..0000000
--- a/westech_r2/westech_r2/page/ebay-pricing/ebay-pricing.css
+++ /dev/null
@@ -1,5 +0,0 @@
-.badge-fresh { background-color: #28a745; }
-.badge-aging { background-color: #ffc107; color: #212529; }
-.badge-expired { background-color: #dc3545; }
-.badge-needs { background-color: #fd7e14; }
-.badge-error { background-color: #6c757d; }
diff --git a/westech_r2/westech_r2/page/ebay-pricing/ebay-pricing.html b/westech_r2/westech_r2/page/ebay-pricing/ebay-pricing.html
deleted file mode 100644
index 4015bfb..0000000
--- a/westech_r2/westech_r2/page/ebay-pricing/ebay-pricing.html
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
diff --git a/westech_r2/westech_r2/page/ebay-pricing/ebay-pricing.js b/westech_r2/westech_r2/page/ebay-pricing/ebay-pricing.js
deleted file mode 100644
index 1414078..0000000
--- a/westech_r2/westech_r2/page/ebay-pricing/ebay-pricing.js
+++ /dev/null
@@ -1,323 +0,0 @@
-frappe.pages['ebay-pricing'].on_page_load = function(wrapper) {
- var page = frappe.ui.make_app_page({
- parent: wrapper,
- title: __('eBay Pricing'),
- single_column: true
- });
-
- let $container = $(`
-
-
-
-
-
- Batch Size
-
- 10
- 25
- 50
- 100
- All
-
-
- Price Batch
-
-
-
-
-
-
-
-
Apply Pricing to Inventory
-
-
- Select Item to apply pricing...
-
-
-
- Apply Pricing
-
-
- Apply All
-
-
-
-
-
Pricing Status
-
-
Click Apply All to see stats
-
-
-
-
-
-
-
-
-
Search for a model or run batch pricing
-
-
-
`).appendTo(page.main);
-
- // Load item dropdown
- load_item_dropdown();
-
- // Event handlers
- $container.find('#ebay-search-btn').on('click', function() {
- let query = $container.find('#ebay-search-input').val().trim();
- if (!query) {
- frappe.msgprint(__('Enter a model to search'));
- return;
- }
- search_ebay(query);
- });
-
- $container.find('#ebay-search-input').on('keypress', function(e) {
- if (e.which === 13) {
- $container.find('#ebay-search-btn').trigger('click');
- }
- });
-
- $container.find('#ebay-batch-btn').on('click', function() {
- let size = $container.find('#ebay-batch-size').val();
- run_batch(size);
- });
-
- $container.find('#ebay-apply-btn').on('click', function() {
- let item = $container.find('#ebay-apply-item').val();
- if (!item) {
- frappe.msgprint(__('Select an Item first'));
- return;
- }
- apply_pricing(item);
- });
-
- $container.find('#ebay-apply-all-btn').on('click', function() {
- apply_pricing_all();
- });
-
- function load_item_dropdown() {
- frappe.call({
- method: 'frappe.client.get_list',
- args: {
- doctype: 'Item',
- filters: {
- 'disabled': 0,
- 'item_group': ['in', ['Laptop', 'Desktop', 'Tablet', 'Phone', 'Workstation']]
- },
- fields: ['name', 'item_name'],
- limit: 1000
- },
- callback: function(r) {
- if (r.message) {
- let $select = $container.find('#ebay-apply-item');
- r.message.forEach(item => {
- $select.append(`
${item.item_name || item.name} `);
- });
- }
- }
- });
- }
-
- function search_ebay(query) {
- frappe.call({
- method: 'westech_r2.api.ebay_pricing.search_model',
- args: { query: query },
- freeze: true,
- freeze_message: __('Searching eBay sold listings...'),
- callback: function(r) {
- if (r.message && r.message.results) {
- render_results(r.message);
- } else {
- let msg = (r.message && r.message.message) || __('No results found');
- frappe.msgprint(msg);
- }
- }
- });
- }
-
- function run_batch(size) {
- frappe.call({
- method: 'westech_r2.api.ebay_pricing.run_batch',
- args: { batch_size: size },
- freeze: true,
- freeze_message: __('Running batch pricing...'),
- callback: function(r) {
- if (r.message) {
- frappe.msgprint(__('Batch complete: {0} priced, {1} failed, {2} skipped',
- [r.message.priced, r.message.failed, r.message.skipped]));
- load_recent_pricing();
- }
- }
- });
- }
-
- function apply_pricing(item_code) {
- frappe.call({
- method: 'westech_r2.api.ebay_pricing.batch_apply_pricing',
- args: { item_code: item_code },
- freeze: true,
- freeze_message: __('Applying pricing to Serial Nos...'),
- callback: function(r) {
- if (r.message) {
- render_pricing_stats(r.message);
- frappe.msgprint(__('Pricing applied: {0} priced, {1} commodity, {2} needs grading',
- [r.message.priced, r.message.commodity, r.message.needs_grading]));
- }
- }
- });
- }
-
- function apply_pricing_all() {
- frappe.call({
- method: 'westech_r2.api.ebay_pricing.batch_apply_pricing',
- args: { batch_size: 1000 },
- freeze: true,
- freeze_message: __('Applying pricing to all Serial Nos...'),
- callback: function(r) {
- if (r.message) {
- render_pricing_stats(r.message);
- frappe.msgprint(__('Batch pricing applied: {0} priced, {1} commodity, {2} needs grading, {3} errors',
- [r.message.priced, r.message.commodity, r.message.needs_grading, r.message.errors]));
- }
- }
- });
- }
-
- function render_pricing_stats(stats) {
- let html = `
-
- Priced ${stats.priced || 0}
- Commodity ${stats.commodity || 0}
- Needs Grading ${stats.needs_grading || 0}
- Needs Price Point ${stats.needs_price_point || 0}
- Errors ${stats.errors || 0}
-
- `;
- $container.find('#pricing-stats').html(html);
- }
-
- function render_results(data) {
- let $area = $container.find('#ebay-results-area').empty();
- if (!data.results || !data.results.length) {
- $area.html(`
No results
`);
- return;
- }
-
- let html = `
-
- Title
- Price
- Condition
- Sold
- Shipping
-
- `;
- data.results.forEach(item => {
- html += `
- ${frappe.utils.escape_html(item.title || '')}
- $${(item.price || 0).toFixed(2)}
- ${frappe.utils.escape_html(item.condition || '')}
- ${item.sold || ''}
- ${item.shipping || ''}
- `;
- });
- html += `
`;
-
- if (data.pricing) {
- html += `
-
Pricing Summary
-
-
Low: $${data.pricing.price_low}
-
High: $${data.pricing.price_high}
-
Average: $${data.pricing.price_average}
-
Median: $${data.pricing.price_auction}
-
-
-
Source: ${data.pricing.source}
-
Samples: ${data.pricing.sample_count}
-
-
`;
- }
-
- $area.html(html);
- }
-
- function load_recent_pricing() {
- frappe.call({
- method: 'westech_r2.api.ebay_pricing.get_recent_pricing',
- args: { limit: 50 },
- callback: function(r) {
- if (r.message) {
- render_pricing_grid(r.message);
- }
- }
- });
- }
-
- function render_pricing_grid(items) {
- let $area = $container.find('#ebay-results-area');
- if (!items || !items.length) {
- $area.html(`
No pricing data yet
`);
- return;
- }
-
- let html = `
Recent Pricing Results
-
-
- Manufacturer
- Model
- Status
- Age
- Low
- High
- Avg
- Samples
- Source
- Last Priced
-
- `;
-
- items.forEach(row => {
- let status_class = 'badge-needs';
- if (row.pricing_status === 'Priced') status_class = 'badge-fresh';
- else if (row.pricing_status === 'Manual Override') status_class = 'badge-fresh';
- else if (row.pricing_status === 'Expired') status_class = 'badge-expired';
- else if (row.pricing_status === 'Error') status_class = 'badge-error';
-
- let age = row.days_since_pricing || 0;
- let age_badge = age < 90 ? 'badge-fresh' : (age < 120 ? 'badge-aging' : 'badge-expired');
-
- html += `
- ${frappe.utils.escape_html(row.manufacturer || '')}
- ${frappe.utils.escape_html(row.model || '')}
- ${row.pricing_status}
- ${age} days
- $${row.price_low || ''}
- $${row.price_high || ''}
- $${row.price_average || ''}
- ${row.sample_count || ''}
- ${row.source || ''}
- ${frappe.datetime.str_to_user(row.scraped_at) || ''}
- `;
- });
-
- html += `
`;
- $area.html(html);
- }
-
- load_recent_pricing();
-};
diff --git a/westech_r2/westech_r2/page/ebay-pricing/ebay-pricing.json b/westech_r2/westech_r2/page/ebay-pricing/ebay-pricing.json
deleted file mode 100644
index ab9d81b..0000000
--- a/westech_r2/westech_r2/page/ebay-pricing/ebay-pricing.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "creation": "2026-05-17 05:30:00.000000",
- "docstatus": 0,
- "doctype": "Page",
- "icon": "fa fa-tags",
- "modified": "2026-05-17 05:30:00.000000",
- "modified_by": "Administrator",
- "module": "Westech R2",
- "name": "ebay-pricing",
- "owner": "Administrator",
- "page_name": "ebay-pricing",
- "roles": [
- {
- "role": "System Manager"
- },
- {
- "role": "Stock User"
- },
- {
- "role": "Sales User"
- }
- ],
- "standard": "Yes",
- "system_page": 0,
- "title": "eBay Pricing"
-}
\ No newline at end of file
diff --git a/westech_r2/westech_r2/page/ebay-pricing/ebay-pricing.py b/westech_r2/westech_r2/page/ebay-pricing/ebay-pricing.py
deleted file mode 100644
index 4053179..0000000
--- a/westech_r2/westech_r2/page/ebay-pricing/ebay-pricing.py
+++ /dev/null
@@ -1 +0,0 @@
-# eBay Pricing desk page
diff --git a/westech_r2/westech_r2/page/ebay-pricing/ebay_pricing.css b/westech_r2/westech_r2/page/ebay-pricing/ebay_pricing.css
deleted file mode 100644
index 8b27534..0000000
--- a/westech_r2/westech_r2/page/ebay-pricing/ebay_pricing.css
+++ /dev/null
@@ -1,5 +0,0 @@
-.badge-fresh { background-color: #28a745; }
-.badge-aging { background-color: #ffc107; color: #212529; }
-.badge-expired { background-color: #dc3545; }
-.badge-needs { background-color: #fd7e14; }
-.badge-error { background-color: #6c757d; }
diff --git a/westech_r2/westech_r2/page/ebay-pricing/ebay_pricing.html b/westech_r2/westech_r2/page/ebay-pricing/ebay_pricing.html
deleted file mode 100644
index 4015bfb..0000000
--- a/westech_r2/westech_r2/page/ebay-pricing/ebay_pricing.html
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
diff --git a/westech_r2/westech_r2/page/ebay-pricing/ebay_pricing.js b/westech_r2/westech_r2/page/ebay-pricing/ebay_pricing.js
deleted file mode 120000
index 8cd44b0..0000000
--- a/westech_r2/westech_r2/page/ebay-pricing/ebay_pricing.js
+++ /dev/null
@@ -1 +0,0 @@
-ebay-pricing.js
\ No newline at end of file
diff --git a/westech_r2/westech_r2/page/ebay-pricing/ebay_pricing.json b/westech_r2/westech_r2/page/ebay-pricing/ebay_pricing.json
deleted file mode 120000
index d388217..0000000
--- a/westech_r2/westech_r2/page/ebay-pricing/ebay_pricing.json
+++ /dev/null
@@ -1 +0,0 @@
-ebay-pricing.json
\ No newline at end of file
diff --git a/westech_r2/westech_r2/page/ebay-pricing/ebay_pricing.py b/westech_r2/westech_r2/page/ebay-pricing/ebay_pricing.py
deleted file mode 100644
index 4053179..0000000
--- a/westech_r2/westech_r2/page/ebay-pricing/ebay_pricing.py
+++ /dev/null
@@ -1 +0,0 @@
-# eBay Pricing desk page
diff --git a/westech_r2/westech_r2/page/eim_portal/__init__.py b/westech_r2/westech_r2/page/eim_portal/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/westech_r2/westech_r2/page/eim_portal/eim-portal.css b/westech_r2/westech_r2/page/eim_portal/eim-portal.css
deleted file mode 100644
index 8b13789..0000000
--- a/westech_r2/westech_r2/page/eim_portal/eim-portal.css
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/westech_r2/westech_r2/page/eim_portal/eim-portal.js b/westech_r2/westech_r2/page/eim_portal/eim-portal.js
deleted file mode 100644
index 9d84ac1..0000000
--- a/westech_r2/westech_r2/page/eim_portal/eim-portal.js
+++ /dev/null
@@ -1,4 +0,0 @@
-frappe.pages["eim-portal"].on_page_load = function(wrapper) {
- wrapper.innerHTML = '
Redirecting to EIM Device Portal...
';
- setTimeout(function() { window.location.href = "https://eim.diagalon.com"; }, 500);
-};
diff --git a/westech_r2/westech_r2/page/eim_portal/eim-portal.json b/westech_r2/westech_r2/page/eim_portal/eim-portal.json
deleted file mode 100644
index c06f7bd..0000000
--- a/westech_r2/westech_r2/page/eim_portal/eim-portal.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "creation": "2026-05-09 14:00:00",
- "docstatus": 0,
- "doctype": "Page",
- "idx": 0,
- "modified": "2026-05-09 14:00:00",
- "modified_by": "Administrator",
- "module": "Westech R2",
- "name": "eim-portal",
- "owner": "Administrator",
- "standard": "Yes",
- "title": "EIM Device Portal"
-}
diff --git a/westech_r2/westech_r2/page/eim_portal/eim-portal.py b/westech_r2/westech_r2/page/eim_portal/eim-portal.py
deleted file mode 100644
index 9d9e209..0000000
--- a/westech_r2/westech_r2/page/eim_portal/eim-portal.py
+++ /dev/null
@@ -1,5 +0,0 @@
-import frappe
-
-def get_context(context):
- frappe.local.flags.redirect_location = "https://eim.diagalon.com"
- raise frappe.Redirect
diff --git a/westech_r2/westech_r2/page/eim_portal/eim_portal.js b/westech_r2/westech_r2/page/eim_portal/eim_portal.js
deleted file mode 100644
index e5cbdea..0000000
--- a/westech_r2/westech_r2/page/eim_portal/eim_portal.js
+++ /dev/null
@@ -1,7 +0,0 @@
-frappe.pages['eim-portal'].on_page_load = function(wrapper) {
- var page = frappe.ui.make_app_page({
- parent: wrapper,
- title: 'EIM Device Portal',
- single_column: true
- });
-}
\ No newline at end of file
diff --git a/westech_r2/westech_r2/page/eim_portal/eim_portal.json b/westech_r2/westech_r2/page/eim_portal/eim_portal.json
deleted file mode 100644
index 1330152..0000000
--- a/westech_r2/westech_r2/page/eim_portal/eim_portal.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "content": null,
- "creation": "2026-05-09 14:00:00",
- "docstatus": 0,
- "doctype": "Page",
- "idx": 0,
- "modified": "2026-05-09 15:09:48.653878",
- "modified_by": "Administrator",
- "module": "Westech R2",
- "name": "eim-portal",
- "owner": "Administrator",
- "page_name": "eim-portal",
- "roles": [
- {
- "role": "All"
- }
- ],
- "script": null,
- "standard": "Yes",
- "style": null,
- "system_page": 0,
- "title": "EIM Device Portal"
-}
\ No newline at end of file
diff --git a/westech_r2/westech_r2/page/intake/__init__.py b/westech_r2/westech_r2/page/intake/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/westech_r2/westech_r2/page/intake/intake.css b/westech_r2/westech_r2/page/intake/intake.css
deleted file mode 100644
index c5f45ab..0000000
--- a/westech_r2/westech_r2/page/intake/intake.css
+++ /dev/null
@@ -1,11 +0,0 @@
-.intake-station .card { border: 1px solid #e0e0e0; border-radius: 8px; overflow: hidden; }
-.intake-station .card-header { padding: 15px; }
-.intake-station .card-body { padding: 20px; }
-.intake-station .form-group { margin-bottom: 15px; }
-.intake-station .form-control { border-radius: 4px; padding: 8px 12px; font-size: 16px; }
-.intake-station .form-control:focus { border-color: #6f42c1; box-shadow: 0 0 0 0.2rem rgba(111,66,193,0.25); }
-.intake-station label { font-weight: 600; margin-bottom: 4px; }
-.intake-station h5 { margin-bottom: 15px; padding-bottom: 8px; border-bottom: 2px solid #e0e0e0; }
-.intake-station .table th { background: #f8f9fa; }
-.intake-station .btn-primary { background: linear-gradient(135deg, #6f42c1, #28a745) !important; border: none !important; }
-.intake-station .label { font-size: 0.85em; }
\ No newline at end of file
diff --git a/westech_r2/westech_r2/page/intake/intake.js b/westech_r2/westech_r2/page/intake/intake.js
deleted file mode 100644
index 0242040..0000000
--- a/westech_r2/westech_r2/page/intake/intake.js
+++ /dev/null
@@ -1,772 +0,0 @@
-frappe.pages['intake'].on_page_load = function(wrapper) {
- var page = frappe.ui.make_app_page({
- parent: wrapper,
- title: 'Intake Station',
- single_column: true
- });
-
- page.set_primary_action('New Intake', function() {
- show_intake_form();
- }, 'add');
-
- page.add_inner_button('Refresh', function() {
- load_recent_pallets();
- });
-
- $(wrapper).find('.layout-main-section').html(`
-
-
-
-
-
-
-
-
-
-
- Status
- Customer #
- Driver
- Received
- RED/R2
- Items
- Weight
- Actions
-
-
-
- Loading...
-
-
-
-
-
-
- `);
-
- // Build ERPNext Link controls for Customer Number and Supplier
- setup_link_controls();
-
- set_today_date();
- load_recent_pallets();
-
- $('#received_date').on('change', function() {
- var d = new Date($(this).val() + 'T12:00:00');
- var days = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
- $('#weekday').val(days[d.getDay()] || '');
- });
-
- $('#intake-form').on('submit', function(e) {
- e.preventDefault();
- save_pallet();
- });
-
- $('#btn-cancel').on('click', function() {
- $('#intake-form-container').hide();
- $('#recent-pallets').show();
- clear_form();
- });
-
- $('#btn-print-labels').on('click', function() {
- print_labels();
- });
-};
-
-// ── ERPNext Link Controls ──────────────────────────────────────────────
-
-var customer_number_control = null;
-var supplier_control = null;
-
-function setup_link_controls() {
- // Customer Number — Link to Supplier, searching by name (which IS the customer number)
- customer_number_control = frappe.ui.form.make_control({
- parent: $('#customer-number-control'),
- df: {
- fieldtype: 'Link',
- fieldname: 'customer_number',
- options: 'Customer',
- label: 'Customer Number',
- reqd: 1,
- placeholder: 'Search customer number...',
- onchange: function() {
- var val = customer_number_control.get_value();
- if (val) {
- fetch_customer_details(val);
- } else {
- clear_customer_fields();
- }
- }
- },
- only_input: true,
- });
- customer_number_control.refresh();
- // Style to match form
- $('#customer-number-control .control-input').css('margin', '0');
- $('#customer-number-control .help-box').remove();
-
- // Supplier (Driver) — Link to Supplier for driver name
- supplier_control = frappe.ui.form.make_control({
- parent: $('#supplier-control'),
- df: {
- fieldtype: 'Link',
- fieldname: 'supplier',
- options: 'Customer',
- label: 'Driver',
- placeholder: 'Search driver...',
- onchange: function() {
- var val = supplier_control.get_value();
- if (val && val !== customer_number_control.get_value()) {
- // Driver selected separately — don't override customer_number
- }
- }
- },
- only_input: true,
- });
- supplier_control.refresh();
- $('#supplier-control .control-input').css('margin', '0');
- $('#supplier-control .help-box').remove();
-}
-
-function fetch_customer_details(customer_name) {
- frappe.call({
- method: 'frappe.client.get',
- args: {doctype: 'Customer', name: customer_name},
- callback: function(r) {
- if (r.message) {
- var c = r.message;
- // Auto-fill company name
- if (c.customer_name && !$('#company_name').val()) {
- $('#company_name').val(c.customer_name);
- }
- // Auto-fill custom CRM fields
- if (c.contact_persons && !$('#contact_persons').val()) {
- $('#contact_persons').val(c.contact_persons);
- }
- if (c.hours_of_operation && !$('#hours_of_operation').val()) {
- $('#hours_of_operation').val(c.hours_of_operation);
- }
- if (c.legacy_notes && !$('#legacy_notes').val()) {
- $('#legacy_notes').val(c.legacy_notes);
- }
- // Driver is independent — don't auto-populate from customer number
-
- // Fill contact fields from Supplier doc's native fields first
- // ERPNext auto-populates these from the primary Contact/Address
- if (c.customer_primary_contact) {
- // Fetch the Contact doc for name/phone/email
- frappe.call({
- method: 'frappe.client.get',
- args: {doctype: 'Contact', name: c.customer_primary_contact},
- callback: function(cr) {
- if (cr.message) {
- var ct = cr.message;
- var full_name = [ct.first_name, ct.last_name].filter(Boolean).join(' ');
- if (full_name && !$('#contact_name').val()) {
- $('#contact_name').val(full_name);
- }
- if (ct.email_id && !$('#contact_email').val()) {
- $('#contact_email').val(ct.email_id);
- }
- if (ct.phone && !$('#contact_number').val()) {
- $('#contact_number').val(ct.phone);
- }
- }
- }
- });
- } else {
- // Fallback: use Supplier-level fields (mobile_no, email_id)
- if (c.mobile_no && !$('#contact_number').val()) {
- $('#contact_number').val(c.mobile_no);
- }
- if (c.email_id && !$('#contact_email').val()) {
- $('#contact_email').val(c.email_id);
- }
-
- // Last resort: search for any linked Contact
- frappe.call({
- method: 'frappe.client.get_list',
- args: {
- doctype: 'Contact',
- filters: [['Dynamic Link', 'link_name', '=', customer_name]],
- fields: ['name', 'first_name', 'last_name', 'email_id', 'phone'],
- limit_page_length: 1
- },
- callback: function(cr) {
- if (cr.message && cr.message.length > 0) {
- var c = cr.message[0];
- var full_name = [c.first_name, c.last_name].filter(Boolean).join(' ');
- if (full_name && !$('#contact_name').val()) {
- $('#contact_name').val(full_name);
- }
- if (c.email_id && !$('#contact_email').val()) {
- $('#contact_email').val(c.email_id);
- }
- if (c.phone && !$('#contact_number').val()) {
- $('#contact_number').val(c.phone);
- }
- }
- }
- });
- }
-
- // Fill address from Supplier doc's primary_address or linked Address
- if (c.primary_address && !$('#address_line').val()) {
- $('#address_line').val(c.primary_address);
- } else if (c.customer_primary_address) {
- frappe.call({
- method: 'frappe.client.get',
- args: {doctype: 'Address', name: c.customer_primary_address},
- callback: function(ar) {
- if (ar.message) {
- var a = ar.message;
- var addr = [a.address_line1, a.address_line2, a.city, a.state].filter(Boolean).join(', ');
- if (addr && !$('#address_line').val()) {
- $('#address_line').val(addr);
- }
- }
- }
- });
- } else {
- // Fallback: search for any linked Address
- frappe.call({
- method: 'frappe.client.get_list',
- args: {
- doctype: 'Address',
- filters: [['Dynamic Link', 'link_name', '=', customer_name]],
- fields: ['name', 'address_line1', 'city', 'state'],
- limit_page_length: 1
- },
- callback: function(ar) {
- if (ar.message && ar.message.length > 0) {
- var a = ar.message[0];
- var addr = [a.address_line1, a.city, a.state].filter(Boolean).join(', ');
- if (addr && !$('#address_line').val()) {
- $('#address_line').val(addr);
- }
- }
- }
- });
- }
- }
- }
- });
-}
-
-function clear_customer_fields() {
- $('#company_name').val('');
- $('#contact_name').val('');
- $('#contact_number').val('');
- $('#contact_email').val('');
- $('#address_line').val('');
- if (supplier_control) supplier_control.set_value('');
-}
-
-// ── Form Helpers ──────────────────────────────────────────────────────
-
-function set_today_date() {
- var today = new Date().toISOString().split('T')[0];
- $('#received_date').val(today);
- $('#received_date').trigger('change');
-}
-
-function show_intake_form() {
- $('#intake-form-container').show();
- $('#recent-pallets').hide();
- set_today_date();
- // Focus the customer number control
- setTimeout(function() {
- if (customer_number_control) {
- customer_number_control.$input.focus();
- }
- }, 200);
-}
-
-function clear_form() {
- $('#intake-form input[type="text"], #intake-form input[type="tel"], #intake-form input[type="email"], #intake-form input[type="number"], #intake-form input[type="date"], #intake-form textarea').val('');
- $('#legacy_notes').val('');
- $('#intake-form select').val('');
- $('#total_items').val('0');
- $('#num_labels').val('1');
- $('#amount').val('0');
- $('#needs_aor').prop('checked', false);
- $('#needs_cod').prop('checked', false);
- $('#btn-print-labels').prop('disabled', true);
- $('#save-status').text('');
- $('#intake-form-container').data('pallet-name', '');
- if (customer_number_control) customer_number_control.set_value('');
- if (supplier_control) supplier_control.set_value('');
-}
-
-function save_pallet() {
- var pallet_name = $('#intake-form-container').data('pallet-name');
- var is_new = !pallet_name;
-
- var data = {
- doctype: 'Pallet',
- received_date: $('#received_date').val(),
- customer_number: customer_number_control ? customer_number_control.get_value() : '',
- customer: customer_number_control ? customer_number_control.get_value() : '',
- supplier: supplier_control ? supplier_control.get_value() : '',
- company_name: $('#company_name').val(),
- pickup: $('#pickup').val(),
- data_status: $('#data_status').val(),
- red_r2: $('#red_r2').val(),
- barcode: $('#barcode').val(),
- total_items: parseInt($('#total_items').val()) || 0,
- num_labels: parseInt($('#num_labels').val()) || 1,
- contact_name: $('#contact_name').val(),
- contact_persons: $('#contact_persons').val(),
- contact_number: $('#contact_number').val(),
- contact_email: $('#contact_email').val(),
- address_line: $('#address_line').val(),
- hours_of_operation: $('#hours_of_operation').val(),
- legacy_notes: $('#legacy_notes').val(),
- weights: $('#weights').val(),
- invoice_check_request: $('#invoice_check_request').val(),
- amount: parseFloat($('#amount').val()) || 0,
- paid_received: $('#paid_received').val(),
- needs_aor: $('#needs_aor').is(':checked') ? 1 : 0,
- needs_cod: $('#needs_cod').is(':checked') ? 1 : 0,
- notes: $('#notes').val(),
- status: 'Received'
- };
-
- if (!is_new) {
- data.name = pallet_name;
- }
-
- frappe.call({
- method: is_new ? 'frappe.client.insert' : 'frappe.client.update',
- args: { doc: data },
- callback: function(r) {
- if (r.message) {
- var name = r.message.name;
- $('#save-status').html('
Saved as Intake ' + name + '');
- $('#btn-print-labels').prop('disabled', false);
- if (is_new) {
- $('#intake-form-container').data('pallet-name', name);
- }
- }
- },
- error: function(r) {
- var msg = 'Unknown error';
- if (r && r._server_messages) {
- try {
- var msgs = JSON.parse(r._server_messages);
- if (msgs && msgs.length) {
- var errObj = JSON.parse(msgs[0]);
- msg = errObj.message || msg;
- }
- } catch(e) {}
- }
- $('#save-status').html('
Error: ' + msg + '');
- }
- });
-}
-
-function load_recent_pallets() {
- frappe.call({
- method: 'frappe.client.get_list',
- args: {
- doctype: 'Pallet',
- fields: ['name', 'pallet_number', 'status', 'customer_number', 'company_name', 'supplier', 'received_date', 'red_r2', 'total_items', 'weights', 'notes', 'needs_aor', 'needs_cod'],
- limit_page_length: 20,
- order_by: 'creation desc'
- },
- callback: function(r) {
- var tbody = $('#pallet-tbody');
- tbody.empty();
- if (!r.message || r.message.length === 0) {
- tbody.append('
No pallets yet ');
- return;
- }
- r.message.forEach(function(p) {
- var status_class = {
- 'Received': 'info',
- 'Sorting': 'warning',
- 'Processing': 'primary',
- 'Complete': 'success',
- 'Shipped': 'default'
- }[p.status] || 'default';
-
- tbody.append(
- '
' +
- '' + (p.status || 'Received') + ' ' +
- '' + (p.customer_number || '') + ' ' +
- '' + (p.supplier || '') + ' ' +
- '' + (p.received_date || '') + ' ' +
- '' + (p.red_r2 || '') +
- (p.needs_aor ? ' AoR ' : '') +
- (p.needs_cod ? ' COD ' : '') +
- ' ' +
- '' + (p.total_items || 0) + ' ' +
- '' + (p.weights || '') + ' ' +
- '' +
- ' ' +
- ' ' +
- ' ' +
- ' '
- );
- });
- }
- });
-}
-
-function edit_pallet(name) {
- frappe.call({
- method: 'frappe.client.get',
- args: {doctype: 'Pallet', name: name},
- callback: function(r) {
- if (r.message) {
- var d = r.message;
- $('#intake-form-container').show();
- $('#recent-pallets').hide();
- $('#intake-form-container').data('pallet-name', name);
- $('#received_date').val(d.received_date || '');
- if (customer_number_control) customer_number_control.set_value(d.customer_number || '');
- if (supplier_control) supplier_control.set_value(d.supplier || '');
- $('#company_name').val(d.company_name || '');
- $('#pickup').val(d.pickup || '');
- $('#data_status').val(d.data_status || '');
- $('#red_r2').val(d.red_r2 || '');
- $('#barcode').val(d.barcode || '');
- $('#total_items').val(d.total_items || 0);
- $('#num_labels').val(d.num_labels || 1);
- $('#contact_name').val(d.contact_name || '');
- $('#contact_number').val(d.contact_number || '');
- $('#contact_email').val(d.contact_email || '');
- $('#address_line').val(d.address_line || '');
- $('#weights').val(d.weights || '');
- $('#invoice_check_request').val(d.invoice_check_request || '');
- $('#amount').val(d.amount || 0);
- $('#paid_received').val(d.paid_received || '');
- $('#needs_aor').prop('checked', d.needs_aor === 1);
- $('#needs_cod').prop('checked', d.needs_cod === 1);
- $('#notes').val(d.notes || '');
- $('#received_date').trigger('change');
- $('#btn-print-labels').prop('disabled', false);
- }
- }
- });
-}
-
-function print_labels() {
- var pallet_name = $('#intake-form-container').data('pallet-name');
- if (!pallet_name) return;
- print_pallet_labels(pallet_name);
-}
-
-function print_pallet_labels(name) {
- frappe.call({
- method: 'frappe.client.get',
- args: {doctype: 'Pallet', name: name},
- callback: function(r) {
- if (r.message) {
- generate_zpl_label(r.message);
- }
- }
- });
-}
-
-function generate_zpl_label(d) {
- var label_count = d.num_labels || 1;
- var date_str = d.received_date || '';
- var driver = d.supplier || '';
- var customer_num = d.customer_number || '';
- var red_r2 = d.red_r2 || '';
- var weight = d.weights || '';
- var pallet_num = d.pallet_number || d.name || '';
- var qr_url = window.location.origin + '/app/pallet/' + (d.name || pallet_num);
-
- var logo_url = window.location.origin + '/files/COR_html_952bb51d.png';
-
- var labels_html = '';
- for (var i = 1; i <= label_count; i++) {
- labels_html += '
';
- labels_html += '';
- labels_html += '
';
- labels_html += '
';
- labels_html += '
';
- labels_html += '
Pallet #: ' + pallet_num + '
';
- if (customer_num) {
- labels_html += '
Customer #: ' + customer_num + '
';
- }
- labels_html += '
Received: ' + date_str + '
';
- labels_html += '
Driver: ' + driver + '
';
- labels_html += '
Weight: ' + weight + '
';
- labels_html += '
Items: ' + (d.total_items || 0) + '
';
- labels_html += '
';
- labels_html += '
';
- labels_html += '
';
- if (red_r2) {
- labels_html += '
' + red_r2 + '
';
- }
- labels_html += '';
- labels_html += '
';
- }
-
- var existing = document.getElementById('label-preview-overlay');
- if (existing) existing.remove();
-
- var overlay = document.createElement('div');
- overlay.id = 'label-preview-overlay';
- overlay.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.6);z-index:9999;display:flex;align-items:center;justify-content:center;';
-
- var modal = document.createElement('div');
- modal.style.cssText = 'background:#fff;border-radius:8px;padding:20px;max-height:90vh;overflow-y:auto;box-shadow:0 4px 20px rgba(0,0,0,0.3);max-width:95vw;';
-
- var title = document.createElement('h3');
- title.textContent = 'Label Preview — Pallet ' + pallet_num + ' (' + label_count + ' label' + (label_count > 1 ? 's' : '') + ')';
- title.style.cssText = 'margin:0 0 15px 0;font-size:16pt;';
-
- var btnGroup = document.createElement('div');
- btnGroup.style.cssText = 'margin-bottom:15px;display:flex;gap:10px;';
-
- var printBtn = document.createElement('button');
- printBtn.className = 'btn btn-primary';
- printBtn.innerHTML = '
Print Labels';
- printBtn.onclick = function() {
- var pw = window.open('', '_blank');
- pw.document.write('
Labels — Pallet ' + pallet_num + ' ');
- pw.document.write('