feat: Add Set Orders on Boxes feature with debouncing and page refresh

- Created warehouse_orders.py module with 8 order management functions
- Added /warehouse/set-orders-on-boxes route and 7 API endpoints
- Implemented 4-tab interface: assign, find, move, and view orders
- Changed assign input from dropdown to text field with BOX validation
- Fixed location join issue in warehouse.py (use boxes_crates.location_id)
- Added debouncing flag to prevent multiple rapid form submissions
- Added page refresh after successful order assignment
- Disabled assign button during processing
- Added page refresh with 2 second delay for UX feedback
- Added CP code validation in inventory page
- Improved modal styling with theme support
- Fixed set_boxes_locations page to refresh box info after assignments
This commit is contained in:
Quality App Developer
2026-02-02 01:06:03 +02:00
parent 39a3a0084c
commit f54e1bebc3
7 changed files with 1986 additions and 52 deletions

View File

@@ -722,6 +722,7 @@
async function assignBoxToLocationTab0() {
const locationCode = document.getElementById('location-code-input-tab0').value.trim();
const boxNumber = document.getElementById('box-number-input-tab0').value.trim();
if (!currentBoxId_Tab0) {
showAlert('alert-tab0', 'Please search for a box first', 'error');
@@ -751,8 +752,36 @@
const data = await response.json();
if (data.success) {
showAlert('alert-tab0', data.message, 'success');
setTimeout(() => clearTab0(), 1500);
showAlert('alert-tab0', data.message + ' - Refreshing box info...', 'success');
// Clear location input but keep box number to refresh details
document.getElementById('location-code-input-tab0').value = '';
document.getElementById('assign-section-tab0').style.display = 'none';
// Automatically refresh box details after a brief delay
setTimeout(async () => {
try {
const searchResponse = await fetch('{{ url_for("warehouse.api_search_box") }}', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ box_number: boxNumber })
});
const searchData = await searchResponse.json();
if (searchData.success) {
document.getElementById('display-box-number-tab0').textContent = searchData.box.box_number;
document.getElementById('display-box-status-tab0').textContent = searchData.box.status;
document.getElementById('display-box-location-tab0').textContent = searchData.box.location_code || 'Unassigned';
document.getElementById('box-info-tab0').classList.add('show');
showAlert('alert-tab0', 'Box updated successfully', 'success');
}
} catch (error) {
console.error('Error refreshing box:', error);
}
}, 800);
} else {
showAlert('alert-tab0', data.message || 'Error assigning box', 'error');
}
@@ -932,6 +961,7 @@
}
async function moveBoxTab2() {
const locationCode = document.getElementById('location-code-input-tab2').value.trim();
const newLocationCode = document.getElementById('new-location-input-tab2').value.trim();
if (!currentBoxId_Tab2) {
@@ -962,8 +992,45 @@
const data = await response.json();
if (data.success) {
showAlert('alert-tab2', data.message, 'success');
setTimeout(() => clearTab2(), 1500);
showAlert('alert-tab2', data.message + ' - Refreshing location...', 'success');
// Clear the selection but keep the location code to show updated list
document.getElementById('new-location-input-tab2').value = '';
document.getElementById('move-section-tab2').style.display = 'none';
document.getElementById('selected-box-display-tab2').textContent = '-';
currentBoxId_Tab2 = null;
// Automatically refresh and show the updated location list after a brief delay
setTimeout(async () => {
try {
const searchResponse = await fetch('{{ url_for("warehouse.api_search_location") }}', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ location_code: locationCode })
});
const searchData = await searchResponse.json();
if (searchData.success) {
document.getElementById('display-location-code-tab2').textContent = searchData.location.location_code;
document.getElementById('display-boxes-count-tab2').textContent = searchData.boxes.length;
document.getElementById('location-info-tab2').classList.add('show');
if (searchData.boxes.length > 0) {
displayBoxesTab2(searchData.boxes);
document.getElementById('boxes-list-tab2').classList.add('show');
showAlert('alert-tab2', `Location updated - ${searchData.boxes.length} box(es) found`, 'success');
} else {
document.getElementById('boxes-list-tab2').classList.remove('show');
showAlert('alert-tab2', `Location "${locationCode}" is now empty`, 'warning');
}
}
} catch (error) {
console.error('Error refreshing location:', error);
}
}, 800);
} else {
showAlert('alert-tab2', data.message || 'Error moving box', 'error');
}