feat: add item-level order confirmation/decline support
Per Letzshop API, each inventory unit must be confirmed/declined individually.
This enables partial confirmation (some items confirmed, others declined).
Admin API endpoints:
- POST /vendors/{id}/orders/{id}/confirm - confirm all items
- POST /vendors/{id}/orders/{id}/reject - decline all items
- POST /vendors/{id}/orders/{id}/items/{id}/confirm - confirm single item
- POST /vendors/{id}/orders/{id}/items/{id}/decline - decline single item
Order detail modal now shows:
- Product name, EAN, SKU, MPN, price per item
- Per-item state badge (unconfirmed/confirmed/declined)
- Per-item confirm/decline buttons for pending items
- Bulk confirm/decline all buttons
Order status logic:
- If all items declined -> order is "declined"
- If any item confirmed -> order is "confirmed"
- Partial confirmation supported
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -403,6 +403,56 @@ class LetzshopOrderService:
|
||||
order.sync_status = "rejected"
|
||||
return order
|
||||
|
||||
def update_inventory_unit_state(
|
||||
self, order: LetzshopOrder, item_id: str, state: str
|
||||
) -> LetzshopOrder:
|
||||
"""
|
||||
Update the state of a single inventory unit in an order.
|
||||
|
||||
Args:
|
||||
order: The order containing the inventory unit.
|
||||
item_id: The inventory unit ID to update.
|
||||
state: The new state (confirmed_available, confirmed_unavailable).
|
||||
|
||||
Returns:
|
||||
The updated order.
|
||||
"""
|
||||
if not order.inventory_units:
|
||||
return order
|
||||
|
||||
# Update the specific item's state
|
||||
updated_units = []
|
||||
for unit in order.inventory_units:
|
||||
if unit.get("id") == item_id:
|
||||
unit["state"] = state
|
||||
updated_units.append(unit)
|
||||
|
||||
order.inventory_units = updated_units
|
||||
|
||||
# Check if all items are now processed and update order status accordingly
|
||||
all_confirmed = all(
|
||||
u.get("state") in ("confirmed_available", "confirmed_unavailable", "returned")
|
||||
for u in updated_units
|
||||
)
|
||||
|
||||
if all_confirmed:
|
||||
# Determine order status based on item states
|
||||
has_available = any(
|
||||
u.get("state") == "confirmed_available" for u in updated_units
|
||||
)
|
||||
all_unavailable = all(
|
||||
u.get("state") == "confirmed_unavailable" for u in updated_units
|
||||
)
|
||||
|
||||
if all_unavailable:
|
||||
order.sync_status = "rejected"
|
||||
order.rejected_at = datetime.now(UTC)
|
||||
elif has_available:
|
||||
order.sync_status = "confirmed"
|
||||
order.confirmed_at = datetime.now(UTC)
|
||||
|
||||
return order
|
||||
|
||||
def set_order_tracking(
|
||||
self,
|
||||
order: LetzshopOrder,
|
||||
|
||||
Reference in New Issue
Block a user