Task #397: Per-card and bulk select+delete on Incoming Orders
Backend (artifacts/api-server):
- Added hasReceivePermission() helper and refactored DELETE /orders/:id
into shared authorizeAndDeleteOrder() 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 (per code review): receivers may only
delete pending/received/preparing orders; terminal (completed/cancelled)
orders remain the owner's cleanup responsibility. OpenAPI description
and the implementation 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 — useBulkDelete
ServiceOrders is now available.
UI (artifacts/tx-os/src/pages/orders-incoming.tsx):
- Selection mode toggle in the page header (RTL-safe).
- Per-card Checkbox plus a Select-all control.
- Sticky bottom action bar with destructive Delete and selected count.
- AlertDialog confirmation using pluralized i18n keys; toast surfaces
partial-failure results when some ids couldn't be deleted.
i18n: New incomingOrders keys in ar.json and en.json (select, selectAll,
clearSelection, selectedCount, delete, deleteConfirmTitle/Body, deleted,
deleteFailed, deletePartial) with pluralization.
Tests: Added two new tests in service-orders.test.mjs covering receiver
delete on incoming queue, receiver forbidden on terminal orders, and
bulk-delete with mixed authorized / unknown / dedup / unauthenticated
cases. Both pass. Pre-existing executive-meetings PDF/font test failures
are unrelated.
This commit is contained in:
@@ -1350,15 +1350,46 @@ paths:
|
||||
schema:
|
||||
$ref: "#/components/schemas/UserDeletionConflict"
|
||||
|
||||
/orders/bulk-delete:
|
||||
post:
|
||||
operationId: bulkDeleteServiceOrders
|
||||
tags: [orders]
|
||||
summary: Delete multiple service orders in one request
|
||||
description: |
|
||||
Deletes several orders in one round-trip. Authorization is still
|
||||
enforced per id using the same rules as DELETE /orders/{id}, so the
|
||||
client cannot bypass the permission check by batching. Returns a
|
||||
summary of which ids were deleted and which were rejected.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/BulkDeleteServiceOrdersBody"
|
||||
responses:
|
||||
"200":
|
||||
description: Bulk delete summary
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/BulkDeleteServiceOrdersResponse"
|
||||
"400":
|
||||
description: Validation error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ErrorResponse"
|
||||
|
||||
/orders/{id}:
|
||||
delete:
|
||||
operationId: deleteServiceOrder
|
||||
tags: [orders]
|
||||
summary: Delete a service order
|
||||
description: |
|
||||
Permanently deletes the order. Allowed when the caller owns the order
|
||||
AND it is in a terminal status (completed/cancelled), OR the caller is
|
||||
an admin (any status).
|
||||
Permanently deletes the order. Allowed when the caller is an admin,
|
||||
when the caller owns the order AND it is in a terminal status
|
||||
(completed/cancelled), OR when the caller holds the `orders.receive`
|
||||
permission (i.e. a receiver clearing items from their incoming queue).
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
@@ -3946,6 +3977,35 @@ components:
|
||||
required:
|
||||
- status
|
||||
|
||||
BulkDeleteServiceOrdersBody:
|
||||
type: object
|
||||
properties:
|
||||
ids:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
minItems: 1
|
||||
maxItems: 200
|
||||
required:
|
||||
- ids
|
||||
|
||||
BulkDeleteServiceOrdersResponse:
|
||||
type: object
|
||||
properties:
|
||||
deletedIds:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
description: Ids that were successfully deleted.
|
||||
failedIds:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
description: Ids that were skipped (not found, or caller is not authorized).
|
||||
required:
|
||||
- deletedIds
|
||||
- failedIds
|
||||
|
||||
ConversationWithDetails:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
Reference in New Issue
Block a user