Fix 2024 pallet numbering and update pallet-list page
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,51 +1,82 @@
|
||||
<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 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 tr:hover { background: #f5f5f5; }
|
||||
.status-received { color: #2196F3; }
|
||||
.status-sorting { color: #FF9800; }
|
||||
.status-processing { color: #9C27B0; }
|
||||
.status-complete { color: #4CAF50; }
|
||||
.status-shipped { color: #607D8B; }
|
||||
.pallet-table tr.new-row { background: #FFF9E6 !important; }
|
||||
.pallet-table a { color: #2F5496; text-decoration: none; font-weight: 600; }
|
||||
.status-received { color: #2196F3; font-weight: 600; }
|
||||
.status-sorting { color: #FF9800; font-weight: 600; }
|
||||
.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>
|
||||
|
||||
<div class="search-box">
|
||||
<input type="text" id="pallet-search" placeholder="Search pallet #...">
|
||||
<div class="pallet-list-page">
|
||||
<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">
|
||||
<option value="">All</option>
|
||||
<option value="">All Statuses</option>
|
||||
<option value="Received">Received</option>
|
||||
<option value="Sorting">Sorting</option>
|
||||
<option value="Processing">Processing</option>
|
||||
<option value="Complete">Complete</option>
|
||||
<option value="Shipped">Shipped</option>
|
||||
</select>
|
||||
</div>
|
||||
<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 class="pallet-table-container">
|
||||
<div class="pallet-table-container">
|
||||
<table class="pallet-table" id="pallet-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Pallet #</th>
|
||||
<th>Date Reserved</th>
|
||||
<th>Rec. Date</th>
|
||||
<th>Customer #</th>
|
||||
<th>Company</th>
|
||||
<th>Lbs</th>
|
||||
<th>Who</th>
|
||||
<th>Items</th>
|
||||
<th>QTY Sale</th>
|
||||
<th>Lbs Sale</th>
|
||||
<th>Finish Date</th>
|
||||
<th data-sort="pallet_number">Pallet # ⇅</th>
|
||||
<th data-sort="date_reserved">Date Reserved ⇅</th>
|
||||
<th data-sort="received_date">Rec. Date ⇅</th>
|
||||
<th data-sort="customer_number">Customer # ⇅</th>
|
||||
<th data-sort="inbound_weight">Lbs ⇅</th>
|
||||
<th data-sort="tester">Who ⇅</th>
|
||||
<th data-sort="description">Items Tested ⇅</th>
|
||||
<th data-sort="qty_to_sales">QTY Sale ⇅</th>
|
||||
<th data-sort="weight_to_sales">Lbs Sale ⇅</th>
|
||||
<th data-sort="finish_date">Finish Date ⇅</th>
|
||||
<th>Status</th>
|
||||
<th>Notes</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<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>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="pallet-pagination" style="margin-top:12px;"\u003e</div>
|
||||
<div class="pallet-pagination" id="pallet-pagination"></div>
|
||||
</div>
|
||||
|
||||
@@ -1,50 +1,40 @@
|
||||
import frappe
|
||||
import json
|
||||
|
||||
@frappe.whitelist()
|
||||
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_size = int(page_size)
|
||||
offset = (page - 1) * page_size
|
||||
|
||||
# Base filters
|
||||
filters = [
|
||||
["Pallet", "pallet_number", "is", "set"],
|
||||
["Pallet", "date_reserved", "is", "set"],
|
||||
]
|
||||
# Only pallets with dates (filters empty rows)
|
||||
conditions = ["pallet_number IS NOT NULL", "pallet_number != ", "date_reserved IS NOT NULL"]
|
||||
|
||||
# Junk filter (same as EIM)
|
||||
junk = ["", "0", "0000", "N/A", "TBD", "null"]
|
||||
conditions.append("pallet_number NOT IN ( + , .join(junk) + )")
|
||||
|
||||
if status_filter:
|
||||
filters.append(["Pallet", "status", "=", status_filter])
|
||||
conditions.append("status = {0}".format(frappe.db.escape(status_filter)))
|
||||
if search:
|
||||
filters.append(["Pallet", "pallet_number", "like", f"%{search}%"])
|
||||
conditions.append("pallet_number LIKE %{0}%".format(frappe.db.escape(search)))
|
||||
|
||||
fields = [
|
||||
"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"
|
||||
]
|
||||
where_clause = " AND ".join(conditions)
|
||||
|
||||
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
|
||||
count_result = frappe.get_list(
|
||||
"Pallet",
|
||||
filters=filters,
|
||||
fields=["count(*) as total"],
|
||||
as_list=True
|
||||
)
|
||||
total = count_result[0][0] if count_result else 0
|
||||
|
||||
# Get pallets
|
||||
pallets = frappe.get_list(
|
||||
"Pallet",
|
||||
filters=filters,
|
||||
fields=fields,
|
||||
order_by=order_by,
|
||||
limit_page_length=page_size,
|
||||
limit_start=offset
|
||||
)
|
||||
# Get pallets - convert pallet_number to unsigned int for numeric sort
|
||||
# Use natural sort: convert to int for proper numeric ordering
|
||||
pallets = frappe.db.sql("""
|
||||
SELECT
|
||||
name, pallet_number, date_reserved, received_date,
|
||||
customer_number, inbound_weight, tester,
|
||||
description, qty_to_sales, weight_to_sales, finish_date, notes, status
|
||||
FROM tabPallet
|
||||
WHERE {0}
|
||||
ORDER BY CAST(pallet_number AS UNSIGNED) {1}
|
||||
LIMIT {2} OFFSET {3}
|
||||
""".format(where_clause, sort_dir, page_size, offset), as_dict=True)
|
||||
|
||||
return {
|
||||
"pallets": pallets,
|
||||
@@ -52,12 +42,3 @@ def get_pallets(page=1, page_size=100, sort_field="pallet_number", sort_dir="des
|
||||
"page": page,
|
||||
"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}"}
|
||||
|
||||
Reference in New Issue
Block a user