@Transactional
public WorkOrder pickupWorkOrder(Long workOrderId) {
// Find the work order
WorkOrder workOrder = workOrderRepository.findById(workOrderId)
.orElseThrow(() -> new IllegalArgumentException("Work order not found: " + workOrderId));
// Mark work order as PICKED_UP
workOrder.setStatus("PICKED_UP");
// Mark ALL ski items in this order as PICKED_UP
if (workOrder.getSkiItems() != null && !workOrder.getSkiItems().isEmpty()) {
for (SkiItem skiItem : workOrder.getSkiItems()) {
skiItem.setStatus("PICKED_UP");
}
}
return workOrderRepository.save(workOrder);
}What this does:
- When "Ready for Pickup" is clicked
- Work order status changes to PICKED_UP
- ALL ski items in that order are also marked PICKED_UP
- Single transaction ensures all-or-nothing update
- Cascade saves all changes to database
<select class="ski-status-select"
data-ski-id="${ski.id}"
onchange="updateSkiStatus(${orderId}, ${ski.id}, this.value)"
${ski.status === "PICKED_UP" ? "disabled" : ""}>
<option value="PENDING">PENDING</option>
<option value="IN_PROGRESS">IN_PROGRESS</option>
<option value="DONE">DONE</option>
<option value="PICKED_UP">PICKED_UP</option>
</select>What this does:
- Shows PICKED_UP as option in dropdown
- Disables dropdown if status is already PICKED_UP
- Prevents changing status on picked-up items
${order.status === "PICKED_UP" ?
'<div style="color: #28a745; margin-top: 10px; font-weight: bold;">✓ Order has been picked up</div>'
: ''}What this does:
- Shows green checkmark message when order is picked up
- Users immediately see pickup confirmation
const allDone = order.skiItems.every(ski => ski.status === "DONE");
const allPickedUp = order.skiItems.every(ski => ski.status === "PICKED_UP");
// Show button only if: all items DONE AND not yet picked up
pickupBtn.style.display = (allDone && !allPickedUp) ? "block" : "none";What this does:
- Button appears only when all items are DONE
- Button disappears after order is picked up
- Prevents clicking pickup multiple times
User Actions:
- Complete all ski items (set status to DONE)
- "Ready for Pickup" button appears
- User clicks "Ready for Pickup"
Backend Processing:
- POST /workorders/{id}/pickup is called
- WorkOrderService.pickupWorkOrder() is executed
- Work order status → PICKED_UP
- All ski items status → PICKED_UP
- Database updated (cascade handles all items)
- Response returned with updated statuses
Frontend Response:
- Modal closes
- fetchWorkOrders() is called
- Main list refreshes
- Order shows PICKED_UP badge
- All items show PICKED_UP badge
- Progress shows "3/3 items done"
- "Ready for Pickup" button hidden
User Actions:
- Customer John Doe calls with 2 new skis
- System creates new order with John's email/phone
Backend Processing:
- POST /workorders is called
- WorkOrderService.createOrMergeWorkOrder() is executed
- Find customer: john@example.com → Found
- Find open order: findMostRecentOpenWorkOrder(customer)
- Previous order status: PICKED_UP
- Check: status != PICKED_UP? NO
- Result: Order not found (it's closed)
- Action: CREATE NEW WORK ORDER
- Order 2 created
- Status: RECEIVED
- Add ski items with PENDING status
- Save and return Order 2
Frontend Display:
- New order appears in list
- Order 1: PICKED_UP, all items PICKED_UP
- Order 2: RECEIVED, all items PENDING
- Progress for Order 2: 0/2 items done
User Actions:
- Customer John Doe calls while Order 1 is in progress
- System gets new items for John's email/phone
Backend Processing:
- POST /workorders is called
- WorkOrderService.createOrMergeWorkOrder() is executed
- Find customer: john@example.com → Found
- Find open order: findMostRecentOpenWorkOrder(customer)
- Previous order status: RECEIVED (or DONE)
- Check: status != PICKED_UP? YES
- Result: Order found!
- Action: MERGE NEW ITEMS INTO ORDER 1
- Add new ski items to existing Order 1
- New items get PENDING status
- Recalculate Order 1 status
- Save and return Order 1 (with merged items)
Frontend Display:
- Order 1 updated
- Now has more items
- Progress updated to reflect new total
- No new notification sent (already notified)
PENDING (yellow) - New, not started
IN_PROGRESS (blue) - Being worked on
DONE (green) - Completed, waiting for pickup
PICKED_UP (cyan) - Customer has picked up
RECEIVED (purple) - Has items in progress
DONE (green) - All items done, ready for pickup
PICKED_UP (cyan) - Customer picked up order
If order.status == PICKED_UP:
→ NEW ORDER (don't merge)
If order.status != PICKED_UP:
→ MERGE items into existing order
1. Create order: John Doe (john@example.com)
- Ski 1: Rossignol Experience 80 (WAXING)
- Ski 2: Atomic Vantage (TUNE)
2. Work on items:
Update Ski 1 → IN_PROGRESS
Update Ski 2 → IN_PROGRESS
Progress: 0/2
3. Complete items:
Update Ski 1 → DONE
Update Ski 2 → DONE
Progress: 2/2
Order Status: DONE (auto)
4. Click "Manage Status"
Modal shows: [DONE] [DONE]
"Ready for Pickup" button visible ✓
5. Click "Ready for Pickup"
POST /workorders/1/pickup
6. Verify:
Order status: PICKED_UP ✓
Ski 1 status: PICKED_UP ✓
Ski 2 status: PICKED_UP ✓
Dropdowns: DISABLED ✓
Message: "✓ Order has been picked up" ✓
1. From Test 1: Order 1 is PICKED_UP
2. Same customer new items:
Create order: John Doe (john@example.com)
- Ski 3: Head Absolut (MOUNT)
3. System processes:
Find customer: john@example.com → Found
Find open order: NO (Order 1 is PICKED_UP)
Action: CREATE NEW
4. Verify:
Order 2 created ✓
Order 2 status: RECEIVED ✓
Ski 3 status: PENDING ✓
NOT merged into Order 1 ✓
1. Create Order 1: Jane Smith (jane@example.com)
- Ski 1: Volkl Mantra (REPAIR)
Order 1 status: RECEIVED
2. Same customer new items:
Create order: Jane Smith (jane@example.com)
- Ski 2: Head Absolut (MOUNT)
3. System processes:
Find customer: jane@example.com → Found
Find open order: YES (Order 1 is RECEIVED)
Action: MERGE
4. Verify:
Order 1 still exists
Now has 2 items ✓
Both items: PENDING ✓
Progress: 0/2 items done ✓
No Order 2 created ✓
{
"id": 1,
"status": "PICKED_UP",
"createdAt": "2026-01-31T11:00:00",
"customerId": 1,
"customerName": "John Doe",
"customerEmail": "john@example.com",
"customerPhone": "5551234567",
"skiItems": [
{
"id": 1,
"skiMake": "Rossignol",
"skiModel": "Experience 80",
"serviceType": "WAXING",
"status": "PICKED_UP"
},
{
"id": 2,
"skiMake": "Atomic",
"skiModel": "Vantage",
"serviceType": "TUNE",
"status": "PICKED_UP"
}
]
}Backend:
✅ src/main/java/com/finetune/app/service/WorkOrderService.java
└─ Updated pickupWorkOrder() to mark ski items as PICKED_UP
Frontend:
✅ src/main/resources/static/index.html
├─ Added PICKED_UP option to status dropdown
├─ Disabled dropdown when status is PICKED_UP
├─ Added "Order has been picked up" message
├─ Updated "Ready for Pickup" button logic
└─ Added pickup button check for already-picked-up orders
- Code compiles (no errors)
- No database schema changes needed
- Status dropdown includes PICKED_UP
- Status dropdown disabled when PICKED_UP
- Pickup button appears only when: all items DONE & not PICKED_UP
- Pickup button disappears after clicking
- Modal message shows when order picked up
- All ski items marked PICKED_UP on pickup
- Merge logic prevents merging into PICKED_UP orders
- New orders created for same customer after pickup
- Cascade saves all items together
cd C:\Users\Hoya\Desktop\FineTune
mvnw.cmd clean package
mvnw.cmd spring-boot:runhttp://localhost:8080
- All status updates work ✓
- Pickup button appears when ready ✓
- Items marked as PICKED_UP ✓
- New orders not merged ✓
| Component | Change | Impact |
|---|---|---|
| WorkOrderService.pickupWorkOrder() | Marks items PICKED_UP | Order completely closed |
| HTML Status Dropdown | Added PICKED_UP option | Can see final status |
| HTML Dropdown Disable | Disabled when PICKED_UP | Read-only for picked-up items |
| Modal Message | Shows pickup confirmation | User sees clear feedback |
| Pickup Button Logic | Checks all items DONE & not PICKED_UP | Button shows/hides correctly |
| Merge Prevention | Checks != PICKED_UP | No merging after pickup |
Your ski work order system now has:
- ✅ Individual ski item status tracking (PENDING → IN_PROGRESS → DONE → PICKED_UP)
- ✅ Work order automatic status calculation
- ✅ "Ready for Pickup" button that marks everything as picked up
- ✅ Merge prevention for picked-up orders
- ✅ New orders created for returning customers with picked-up orders
- ✅ Clean UI with disabled controls on picked-up items
- ✅ Clear status badges and feedback messages
Ready to deploy!