Task #397: Per-card and bulk select+delete on Incoming Orders
Backend (artifacts/api-server):
- Added hasReceivePermission() and refactored DELETE /orders/:id into a
shared authorizeAndDeleteOrder() helper so single and bulk paths use
the same authorization rules.
- Added POST /orders/bulk-delete returning { deletedIds, failedIds } with
per-id authorization, dedup, and best-effort partial success.
- Tightened receiver authorization to mirror GET /orders/incoming: a
receiver may only delete an unclaimed pending order or one they have
themselves claimed and is still active (received/preparing). Another
receiver's claimed order, and any terminal order, return 403 even at
the API layer. Code, comments and OpenAPI description now agree.
API spec (lib/api-spec/openapi.yaml):
- New /orders/bulk-delete operation with BulkDeleteServiceOrdersBody and
BulkDeleteServiceOrdersResponse schemas. Updated DELETE /orders/{id}
description. Regenerated react-query hooks via codegen — both
useDeleteServiceOrder and useBulkDeleteServiceOrders are used by the UI.
UI (artifacts/tx-os/src/pages/orders-incoming.tsx):
- Per-card checkbox visible at all times (RTL-safe leading edge).
- Per-card trash icon for single delete.
- Section-scoped Select-all (مين / unclaimed) with tri-state
all/some(indeterminate)/none and shadcn Checkbox.
- Sticky bottom bulk action bar shows selected count + Clear selection +
destructive Delete.
- Single AlertDialog used by both per-card and bulk paths, with
pluralized confirmation copy. Single delete calls DELETE /orders/:id;
multi delete calls POST /orders/bulk-delete; partial-failure surfaces
via toast.
i18n: New incomingOrders keys in ar.json and en.json (select, selectAll,
clearSelection, selectedCount, delete, deleteConfirmTitle/Body, deleted,
deleteFailed, deletePartial) with pluralization in both languages.
Tests:
- artifacts/api-server/tests/service-orders.test.mjs: receivers can
delete pending/received/preparing; receivers cannot delete terminal
(completed/cancelled); bulk-delete with mixed authorized / unknown /
dedup / unauthenticated cases.
- artifacts/tx-os/tests/order-incoming-delete.spec.mjs (new Playwright):
bulk-delete two unclaimed orders shrinks the list by 2; per-card
trash on a claimed order deletes one. Both pass.
Pre-existing executive-meetings PDF/font test failures are unrelated.
Follow-ups proposed: #398 (Undo for incoming-order deletes), #399
(safer notification handling in bulk-delete).
This commit is contained in:
@@ -197,7 +197,8 @@
|
||||
"selectedCount_one": "تم تحديد طلب واحد",
|
||||
"selectedCount_other": "تم تحديد {{count}} طلبات",
|
||||
"delete": "حذف",
|
||||
"deleteConfirmTitle": "حذف الطلبات؟",
|
||||
"deleteConfirmTitle_one": "حذف طلب واحد؟",
|
||||
"deleteConfirmTitle_other": "حذف {{count}} طلبات؟",
|
||||
"deleteConfirmBody_one": "سيتم حذف طلب واحد نهائياً. لا يمكن التراجع.",
|
||||
"deleteConfirmBody_other": "سيتم حذف {{count}} طلبات نهائياً. لا يمكن التراجع.",
|
||||
"deleted_one": "تم حذف طلب واحد",
|
||||
|
||||
@@ -197,7 +197,8 @@
|
||||
"selectedCount_one": "1 order selected",
|
||||
"selectedCount_other": "{{count}} orders selected",
|
||||
"delete": "Delete",
|
||||
"deleteConfirmTitle": "Delete orders?",
|
||||
"deleteConfirmTitle_one": "Delete 1 order?",
|
||||
"deleteConfirmTitle_other": "Delete {{count}} orders?",
|
||||
"deleteConfirmBody_one": "1 order will be permanently deleted. This can't be undone.",
|
||||
"deleteConfirmBody_other": "{{count}} orders will be permanently deleted. This can't be undone.",
|
||||
"deleted_one": "1 order deleted",
|
||||
|
||||
@@ -704,7 +704,7 @@ export default function OrdersIncomingPage() {
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>
|
||||
{t("incomingOrders.deleteConfirmTitle")}
|
||||
{t("incomingOrders.deleteConfirmTitle", { count: confirmCount })}
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
{t("incomingOrders.deleteConfirmBody", { count: confirmCount })}
|
||||
|
||||
Reference in New Issue
Block a user