Fix 2024 pallet numbering and update pallet-list page

This commit is contained in:
Westech Admin
2026-05-19 21:28:52 +00:00
parent 73e7df4735
commit fe91302ff5
5 changed files with 97 additions and 85 deletions
+54 -23
View File
@@ -1,51 +1,82 @@
<style> <style>
.pallet-table-container { padding: 0; overflow-x: auto; } .pallet-list-page { font-family: Helvetica Neue, Arial, sans-serif; }
.pallet-list-page h2 { color: #2F5496; margin-bottom: 16px; font-size: 20px; }
.pallet-search-box { margin-bottom: 16px; display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.pallet-search-box input, .pallet-search-box select {
padding: 6px 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 13px;
}
.pallet-search-box button {
padding: 6px 14px; border: 1px solid #ddd; border-radius: 4px; cursor: pointer;
font-size: 13px; background: white;
}
.pallet-search-box button.btn-primary { background: #2F5496; color: white; border-color: #2F5496; }
.pallet-search-box button.btn-success { background: #548235; color: white; border-color: #548235; }
.pallet-table-container { padding: 0; overflow-x: auto; background: white; border-radius: 4px; }
.pallet-table { width: 100%; border-collapse: collapse; font-size: 13px; } .pallet-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.pallet-table th { background: #3cc062; color: white; padding: 8px 10px; text-align: left; cursor: pointer; } .pallet-table th {
background: #2F5496; color: white; padding: 8px 10px; text-align: left;
cursor: pointer; white-space: nowrap; font-weight: 500;
}
.pallet-table td { padding: 5px 10px; border-bottom: 1px solid #eee; } .pallet-table td { padding: 5px 10px; border-bottom: 1px solid #eee; }
.pallet-table tr:hover { background: #f5f5f5; } .pallet-table tr:hover { background: #f5f5f5; }
.status-received { color: #2196F3; } .pallet-table tr.new-row { background: #FFF9E6 !important; }
.status-sorting { color: #FF9800; } .pallet-table a { color: #2F5496; text-decoration: none; font-weight: 600; }
.status-processing { color: #9C27B0; } .status-received { color: #2196F3; font-weight: 600; }
.status-complete { color: #4CAF50; } .status-sorting { color: #FF9800; font-weight: 600; }
.status-shipped { color: #607D8B; } .status-processing { color: #9C27B0; font-weight: 600; }
.status-complete { color: #4CAF50; font-weight: 600; }
.status-shipped { color: #607D8B; font-weight: 600; }
.pallet-pagination { margin-top: 12px; display: flex; gap: 5px; align-items: center; }
.pallet-pagination button {
padding: 5px 12px; border: 1px solid #ddd; background: white; cursor: pointer;
border-radius: 4px; font-size: 13px; color: #2F5496;
}
.pallet-pagination button.active { background: #2F5496; color: white; border-color: #2F5496; }
.pallet-pagination button:disabled { opacity: 0.5; cursor: not-allowed; }
.pallet-count { margin-left: auto; color: #666; font-size: 13px; }
</style> </style>
<div class="search-box"> <div class="pallet-list-page">
<input type="text" id="pallet-search" placeholder="Search pallet #..."> <h2>📦 Pallet List</h2>
<div class="pallet-search-box">
<input type="text" id="pallet-search" placeholder="Search pallet #..." style="max-width:200px;">
<select id="status-filter"> <select id="status-filter">
<option value="">All</option> <option value="">All Statuses</option>
<option value="Received">Received</option> <option value="Received">Received</option>
<option value="Sorting">Sorting</option> <option value="Sorting">Sorting</option>
<option value="Processing">Processing</option> <option value="Processing">Processing</option>
<option value="Complete">Complete</option> <option value="Complete">Complete</option>
<option value="Shipped">Shipped</option> <option value="Shipped">Shipped</option>
</select> </select>
<button class="btn btn-default" id="btn-clear">✕ Clear</button>
<button class="btn btn-success" id="btn-export">⬇ Export CSV</button>
<span class="pallet-count" id="pallet-count"></span>
</div> </div>
<div class="pallet-table-container"> <div class="pallet-table-container">
<table class="pallet-table" id="pallet-table"> <table class="pallet-table" id="pallet-table">
<thead> <thead>
<tr> <tr>
<th>Pallet #</th> <th data-sort="pallet_number">Pallet #</th>
<th>Date Reserved</th> <th data-sort="date_reserved">Date Reserved</th>
<th>Rec. Date</th> <th data-sort="received_date">Rec. Date</th>
<th>Customer #</th> <th data-sort="customer_number">Customer #</th>
<th>Company</th> <th data-sort="inbound_weight">Lbs ⇅</th>
<th>Lbs</th> <th data-sort="tester">Who ⇅</th>
<th>Who</th> <th data-sort="description">Items Tested ⇅</th>
<th>Items</th> <th data-sort="qty_to_sales">QTY Sale ⇅</th>
<th>QTY Sale</th> <th data-sort="weight_to_sales">Lbs Sale</th>
<th>Lbs Sale</th> <th data-sort="finish_date">Finish Date ⇅</th>
<th>Finish Date</th>
<th>Status</th> <th>Status</th>
<th>Notes</th> <th>Notes</th>
</tr> </tr>
</thead> </thead>
<tbody id="pallet-tbody"> <tbody id="pallet-tbody">
<tr><td colspan="13" style="text-align:center;padding:40px;">Loading...</td></tr> <tr><td colspan="12" style="text-align:center;padding:40px;color:#666;">Loading...</td></tr>
</tbody> </tbody>
</table> </table>
</div> </div>
<div id="pallet-pagination" style="margin-top:12px;"\u003e</div> <div class="pallet-pagination" id="pallet-pagination"></div>
</div>
+23 -42
View File
@@ -1,50 +1,40 @@
import frappe import frappe
import json
@frappe.whitelist() @frappe.whitelist()
def get_pallets(page=1, page_size=100, sort_field="pallet_number", sort_dir="desc", status_filter="", search=""): def get_pallets(page=1, page_size=100, sort_field="pallet_number", sort_dir="desc", status_filter="", search=""):
"""Fetch pallets from ERPNext with filters."""
page = int(page) page = int(page)
page_size = int(page_size) page_size = int(page_size)
offset = (page - 1) * page_size offset = (page - 1) * page_size
# Base filters # Only pallets with dates (filters empty rows)
filters = [ conditions = ["pallet_number IS NOT NULL", "pallet_number != ", "date_reserved IS NOT NULL"]
["Pallet", "pallet_number", "is", "set"],
["Pallet", "date_reserved", "is", "set"], # Junk filter (same as EIM)
] junk = ["", "0", "0000", "N/A", "TBD", "null"]
conditions.append("pallet_number NOT IN ( + , .join(junk) + )")
if status_filter: if status_filter:
filters.append(["Pallet", "status", "=", status_filter]) conditions.append("status = {0}".format(frappe.db.escape(status_filter)))
if search: if search:
filters.append(["Pallet", "pallet_number", "like", f"%{search}%"]) conditions.append("pallet_number LIKE %{0}%".format(frappe.db.escape(search)))
fields = [ where_clause = " AND ".join(conditions)
"name", "pallet_number", "date_reserved", "received_date",
"customer_number", "company_name", "inbound_weight", "tester",
"description", "qty_to_sales", "weight_to_sales", "finish_date", "notes", "status"
]
order_by = f"{sort_field} {sort_dir}" # Get total
total = frappe.db.sql("""SELECT COUNT(*) FROM tabPallet WHERE {0}""".format(where_clause))[0][0]
# Get total count # Get pallets - convert pallet_number to unsigned int for numeric sort
count_result = frappe.get_list( # Use natural sort: convert to int for proper numeric ordering
"Pallet", pallets = frappe.db.sql("""
filters=filters, SELECT
fields=["count(*) as total"], name, pallet_number, date_reserved, received_date,
as_list=True customer_number, inbound_weight, tester,
) description, qty_to_sales, weight_to_sales, finish_date, notes, status
total = count_result[0][0] if count_result else 0 FROM tabPallet
WHERE {0}
# Get pallets ORDER BY CAST(pallet_number AS UNSIGNED) {1}
pallets = frappe.get_list( LIMIT {2} OFFSET {3}
"Pallet", """.format(where_clause, sort_dir, page_size, offset), as_dict=True)
filters=filters,
fields=fields,
order_by=order_by,
limit_page_length=page_size,
limit_start=offset
)
return { return {
"pallets": pallets, "pallets": pallets,
@@ -52,12 +42,3 @@ def get_pallets(page=1, page_size=100, sort_field="pallet_number", sort_dir="des
"page": page, "page": page,
"page_size": page_size "page_size": page_size
} }
@frappe.whitelist()
def update_pallet(docname, field, value):
"""Update a single field on a Pallet."""
pallet = frappe.get_doc("Pallet", docname)
pallet.set(field, value)
pallet.save(ignore_permissions=True)
frappe.db.commit()
return {"status": "ok", "message": f"Updated {field}"}