@open-mercato/core 0.10.1-develop.7709.1.046124599c → 0.10.1-develop.7714.1.9dbb8200d8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +2 -2
- package/dist/generated/entities/asn/index.js +19 -0
- package/dist/generated/entities/asn/index.js.map +7 -0
- package/dist/generated/entities/putaway_task/index.js +25 -0
- package/dist/generated/entities/putaway_task/index.js.map +7 -0
- package/dist/generated/entities/receiving_line/index.js +21 -0
- package/dist/generated/entities/receiving_line/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +4 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +34 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/communication_channels/lib/sanitize-channel-html.js +22 -3
- package/dist/modules/communication_channels/lib/sanitize-channel-html.js.map +2 -2
- package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.client.js +40 -11
- package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.client.js.map +2 -2
- package/dist/modules/customers/components/calendar/CalendarEventEditor.js +13 -2
- package/dist/modules/customers/components/calendar/CalendarEventEditor.js.map +2 -2
- package/dist/modules/wms/acl.js +2 -0
- package/dist/modules/wms/acl.js.map +2 -2
- package/dist/modules/wms/api/asns/[id]/complete/route.js +61 -0
- package/dist/modules/wms/api/asns/[id]/complete/route.js.map +7 -0
- package/dist/modules/wms/api/asns/[id]/receive/route.js +68 -0
- package/dist/modules/wms/api/asns/[id]/receive/route.js.map +7 -0
- package/dist/modules/wms/api/asns/route.js +197 -0
- package/dist/modules/wms/api/asns/route.js.map +7 -0
- package/dist/modules/wms/api/inventory/helpers.js +42 -34
- package/dist/modules/wms/api/inventory/helpers.js.map +2 -2
- package/dist/modules/wms/api/inventory/receive/route.js +1 -1
- package/dist/modules/wms/api/inventory/receive/route.js.map +2 -2
- package/dist/modules/wms/api/listEnrichers.js +23 -0
- package/dist/modules/wms/api/listEnrichers.js.map +2 -2
- package/dist/modules/wms/api/putaway-tasks/[id]/assign/route.js +56 -0
- package/dist/modules/wms/api/putaway-tasks/[id]/assign/route.js.map +7 -0
- package/dist/modules/wms/api/putaway-tasks/[id]/cancel/route.js +56 -0
- package/dist/modules/wms/api/putaway-tasks/[id]/cancel/route.js.map +7 -0
- package/dist/modules/wms/api/putaway-tasks/[id]/complete/route.js +65 -0
- package/dist/modules/wms/api/putaway-tasks/[id]/complete/route.js.map +7 -0
- package/dist/modules/wms/api/putaway-tasks/[id]/start/route.js +56 -0
- package/dist/modules/wms/api/putaway-tasks/[id]/start/route.js.map +7 -0
- package/dist/modules/wms/api/putaway-tasks/create-from-balance/route.js +51 -0
- package/dist/modules/wms/api/putaway-tasks/create-from-balance/route.js.map +7 -0
- package/dist/modules/wms/api/putaway-tasks/route.js +192 -0
- package/dist/modules/wms/api/putaway-tasks/route.js.map +7 -0
- package/dist/modules/wms/api/receiving-lines/route.js +180 -0
- package/dist/modules/wms/api/receiving-lines/route.js.map +7 -0
- package/dist/modules/wms/api/scan/putaway/route.js +104 -0
- package/dist/modules/wms/api/scan/putaway/route.js.map +7 -0
- package/dist/modules/wms/api/scan/receive/route.js +109 -0
- package/dist/modules/wms/api/scan/receive/route.js.map +7 -0
- package/dist/modules/wms/api/scan/resolve-location/route.js +89 -0
- package/dist/modules/wms/api/scan/resolve-location/route.js.map +7 -0
- package/dist/modules/wms/api/scan/resolve-lot/route.js +89 -0
- package/dist/modules/wms/api/scan/resolve-lot/route.js.map +7 -0
- package/dist/modules/wms/backend/wms/asns/[id]/page.js +9 -0
- package/dist/modules/wms/backend/wms/asns/[id]/page.js.map +7 -0
- package/dist/modules/wms/backend/wms/asns/[id]/page.meta.js +18 -0
- package/dist/modules/wms/backend/wms/asns/[id]/page.meta.js.map +7 -0
- package/dist/modules/wms/backend/wms/asns/page.js +9 -0
- package/dist/modules/wms/backend/wms/asns/page.js.map +7 -0
- package/dist/modules/wms/backend/wms/asns/page.meta.js +18 -0
- package/dist/modules/wms/backend/wms/asns/page.meta.js.map +7 -0
- package/dist/modules/wms/backend/wms/putaway/page.js +9 -0
- package/dist/modules/wms/backend/wms/putaway/page.js.map +7 -0
- package/dist/modules/wms/backend/wms/putaway/page.meta.js +18 -0
- package/dist/modules/wms/backend/wms/putaway/page.meta.js.map +7 -0
- package/dist/modules/wms/backend/wms/receiving/page.js +8 -0
- package/dist/modules/wms/backend/wms/receiving/page.js.map +7 -0
- package/dist/modules/wms/backend/wms/receiving/page.meta.js +18 -0
- package/dist/modules/wms/backend/wms/receiving/page.meta.js.map +7 -0
- package/dist/modules/wms/ce.js +27 -0
- package/dist/modules/wms/ce.js.map +2 -2
- package/dist/modules/wms/commands/asn.js +1746 -0
- package/dist/modules/wms/commands/asn.js.map +7 -0
- package/dist/modules/wms/commands/index.js +2 -0
- package/dist/modules/wms/commands/index.js.map +2 -2
- package/dist/modules/wms/commands/inventory-actions.js +347 -243
- package/dist/modules/wms/commands/inventory-actions.js.map +2 -2
- package/dist/modules/wms/commands/putaway.js +945 -0
- package/dist/modules/wms/commands/putaway.js.map +7 -0
- package/dist/modules/wms/commands/shared.js +51 -0
- package/dist/modules/wms/commands/shared.js.map +2 -2
- package/dist/modules/wms/components/backend/AssignPutawayTaskDialog.js +278 -0
- package/dist/modules/wms/components/backend/AssignPutawayTaskDialog.js.map +7 -0
- package/dist/modules/wms/components/backend/CompletePutawayTaskDialog.js +327 -0
- package/dist/modules/wms/components/backend/CompletePutawayTaskDialog.js.map +7 -0
- package/dist/modules/wms/components/backend/CreateAsnDialog.js +404 -0
- package/dist/modules/wms/components/backend/CreateAsnDialog.js.map +7 -0
- package/dist/modules/wms/components/backend/InventoryOperationsSection.js +16 -3
- package/dist/modules/wms/components/backend/InventoryOperationsSection.js.map +2 -2
- package/dist/modules/wms/components/backend/ReceiveAsnLineDialog.js +476 -0
- package/dist/modules/wms/components/backend/ReceiveAsnLineDialog.js.map +7 -0
- package/dist/modules/wms/components/backend/ReceiveInventoryDialog.js +2 -2
- package/dist/modules/wms/components/backend/ReceiveInventoryDialog.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsAsnDetailPage.js +524 -0
- package/dist/modules/wms/components/backend/WmsAsnDetailPage.js.map +7 -0
- package/dist/modules/wms/components/backend/WmsAsnsListPage.js +339 -0
- package/dist/modules/wms/components/backend/WmsAsnsListPage.js.map +7 -0
- package/dist/modules/wms/components/backend/WmsLocationDetailPage.js +5 -6
- package/dist/modules/wms/components/backend/WmsLocationDetailPage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsLotDetailPage.js +5 -6
- package/dist/modules/wms/components/backend/WmsLotDetailPage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsOperationalDashboardPage.js +14 -10
- package/dist/modules/wms/components/backend/WmsOperationalDashboardPage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsPutawayQueuePage.js +598 -0
- package/dist/modules/wms/components/backend/WmsPutawayQueuePage.js.map +7 -0
- package/dist/modules/wms/components/backend/WmsSkuDetailPage.js +5 -6
- package/dist/modules/wms/components/backend/WmsSkuDetailPage.js.map +2 -2
- package/dist/modules/wms/components/backend/asnCompleteOptimisticLock.js +32 -0
- package/dist/modules/wms/components/backend/asnCompleteOptimisticLock.js.map +7 -0
- package/dist/modules/wms/components/backend/asnReceivingLinesLoader.js +36 -0
- package/dist/modules/wms/components/backend/asnReceivingLinesLoader.js.map +7 -0
- package/dist/modules/wms/components/backend/inboundStatusUi.js +106 -0
- package/dist/modules/wms/components/backend/inboundStatusUi.js.map +7 -0
- package/dist/modules/wms/components/backend/inventoryMutationLoaders.js +17 -0
- package/dist/modules/wms/components/backend/inventoryMutationLoaders.js.map +2 -2
- package/dist/modules/wms/components/backend/putawayQueueOptimisticLock.js +14 -0
- package/dist/modules/wms/components/backend/putawayQueueOptimisticLock.js.map +7 -0
- package/dist/modules/wms/components/backend/useWmsInventoryMutationAccess.js +4 -0
- package/dist/modules/wms/components/backend/useWmsInventoryMutationAccess.js.map +2 -2
- package/dist/modules/wms/data/enrichers.js +117 -12
- package/dist/modules/wms/data/enrichers.js.map +2 -2
- package/dist/modules/wms/data/entities.js +150 -1
- package/dist/modules/wms/data/entities.js.map +2 -2
- package/dist/modules/wms/data/validators.js +214 -0
- package/dist/modules/wms/data/validators.js.map +2 -2
- package/dist/modules/wms/events.js +12 -1
- package/dist/modules/wms/events.js.map +2 -2
- package/dist/modules/wms/extension-points.js +3 -1
- package/dist/modules/wms/extension-points.js.map +2 -2
- package/dist/modules/wms/lib/asnReceiving.js +124 -0
- package/dist/modules/wms/lib/asnReceiving.js.map +7 -0
- package/dist/modules/wms/lib/asnVendor.js +52 -0
- package/dist/modules/wms/lib/asnVendor.js.map +7 -0
- package/dist/modules/wms/lib/flashMutationError.js +4 -0
- package/dist/modules/wms/lib/flashMutationError.js.map +2 -2
- package/dist/modules/wms/lib/inventoryDisplayUi.js +24 -0
- package/dist/modules/wms/lib/inventoryDisplayUi.js.map +2 -2
- package/dist/modules/wms/lib/inventoryPolicy.js +17 -0
- package/dist/modules/wms/lib/inventoryPolicy.js.map +2 -2
- package/dist/modules/wms/lib/loadOperationalDashboard.js +67 -1
- package/dist/modules/wms/lib/loadOperationalDashboard.js.map +2 -2
- package/dist/modules/wms/lib/putaway.js +141 -0
- package/dist/modules/wms/lib/putaway.js.map +7 -0
- package/dist/modules/wms/lib/roleFeatures.js +3 -1
- package/dist/modules/wms/lib/roleFeatures.js.map +2 -2
- package/dist/modules/wms/lib/salesOrderInventoryAutomation.js +99 -1
- package/dist/modules/wms/lib/salesOrderInventoryAutomation.js.map +2 -2
- package/dist/modules/wms/lib/scanResolve.js +147 -0
- package/dist/modules/wms/lib/scanResolve.js.map +7 -0
- package/dist/modules/wms/lib/wmsIntegrationToggles.js +1 -1
- package/dist/modules/wms/lib/wmsIntegrationToggles.js.map +2 -2
- package/dist/modules/wms/migrations/Migration20260812120000.js +43 -0
- package/dist/modules/wms/migrations/Migration20260812120000.js.map +7 -0
- package/dist/modules/wms/migrations/Migration20260812130000.js +30 -0
- package/dist/modules/wms/migrations/Migration20260812130000.js.map +7 -0
- package/dist/modules/wms/migrations/Migration20260822120000.js +17 -0
- package/dist/modules/wms/migrations/Migration20260822120000.js.map +7 -0
- package/dist/modules/wms/migrations/Migration20260822130000.js +17 -0
- package/dist/modules/wms/migrations/Migration20260822130000.js.map +7 -0
- package/dist/modules/wms/migrations/Migration20261029120000.js +13 -0
- package/dist/modules/wms/migrations/Migration20261029120000.js.map +7 -0
- package/dist/modules/wms/search.js +85 -0
- package/dist/modules/wms/search.js.map +2 -2
- package/dist/modules/wms/subscribers/asn-line-received-reevaluate-reservations.js +14 -0
- package/dist/modules/wms/subscribers/asn-line-received-reevaluate-reservations.js.map +7 -0
- package/dist/modules/wms/subscribers/invalidate-enricher-cache-asn.js +12 -0
- package/dist/modules/wms/subscribers/invalidate-enricher-cache-asn.js.map +7 -0
- package/dist/modules/wms/subscribers/procurement-goods-receipt-created.js +163 -0
- package/dist/modules/wms/subscribers/procurement-goods-receipt-created.js.map +7 -0
- package/dist/modules/wms/subscribers/putaway-completed-reevaluate-reservations.js +14 -0
- package/dist/modules/wms/subscribers/putaway-completed-reevaluate-reservations.js.map +7 -0
- package/dist/modules/wms/widgets/injection/sales-order-stock-context/widget.client.js +37 -8
- package/dist/modules/wms/widgets/injection/sales-order-stock-context/widget.client.js.map +2 -2
- package/generated/entities/asn/index.ts +8 -0
- package/generated/entities/putaway_task/index.ts +11 -0
- package/generated/entities/receiving_line/index.ts +9 -0
- package/generated/entities.ids.generated.ts +4 -1
- package/generated/entity-fields-registry.ts +34 -0
- package/package.json +7 -7
- package/src/modules/auth/i18n/de.json +2 -0
- package/src/modules/auth/i18n/en.json +2 -0
- package/src/modules/auth/i18n/es.json +2 -0
- package/src/modules/auth/i18n/ko.json +2 -0
- package/src/modules/auth/i18n/pl.json +2 -0
- package/src/modules/communication_channels/i18n/de.json +2 -0
- package/src/modules/communication_channels/i18n/en.json +2 -0
- package/src/modules/communication_channels/i18n/es.json +2 -0
- package/src/modules/communication_channels/i18n/ko.json +2 -0
- package/src/modules/communication_channels/i18n/pl.json +2 -0
- package/src/modules/communication_channels/lib/sanitize-channel-html.ts +23 -3
- package/src/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.client.tsx +44 -12
- package/src/modules/customers/components/calendar/CalendarEventEditor.tsx +16 -2
- package/src/modules/wms/acl.ts +2 -0
- package/src/modules/wms/api/asns/[id]/complete/route.ts +62 -0
- package/src/modules/wms/api/asns/[id]/receive/route.ts +74 -0
- package/src/modules/wms/api/asns/route.ts +200 -0
- package/src/modules/wms/api/inventory/helpers.ts +57 -34
- package/src/modules/wms/api/inventory/receive/route.ts +2 -1
- package/src/modules/wms/api/listEnrichers.ts +38 -0
- package/src/modules/wms/api/putaway-tasks/[id]/assign/route.ts +56 -0
- package/src/modules/wms/api/putaway-tasks/[id]/cancel/route.ts +56 -0
- package/src/modules/wms/api/putaway-tasks/[id]/complete/route.ts +66 -0
- package/src/modules/wms/api/putaway-tasks/[id]/start/route.ts +56 -0
- package/src/modules/wms/api/putaway-tasks/create-from-balance/route.ts +50 -0
- package/src/modules/wms/api/putaway-tasks/route.ts +199 -0
- package/src/modules/wms/api/receiving-lines/route.ts +180 -0
- package/src/modules/wms/api/scan/putaway/route.ts +108 -0
- package/src/modules/wms/api/scan/receive/route.ts +118 -0
- package/src/modules/wms/api/scan/resolve-location/route.ts +92 -0
- package/src/modules/wms/api/scan/resolve-lot/route.ts +92 -0
- package/src/modules/wms/backend/wms/asns/[id]/page.meta.ts +14 -0
- package/src/modules/wms/backend/wms/asns/[id]/page.tsx +5 -0
- package/src/modules/wms/backend/wms/asns/page.meta.ts +14 -0
- package/src/modules/wms/backend/wms/asns/page.tsx +5 -0
- package/src/modules/wms/backend/wms/putaway/page.meta.ts +14 -0
- package/src/modules/wms/backend/wms/putaway/page.tsx +5 -0
- package/src/modules/wms/backend/wms/receiving/page.meta.ts +14 -0
- package/src/modules/wms/backend/wms/receiving/page.tsx +5 -0
- package/src/modules/wms/ce.ts +27 -0
- package/src/modules/wms/commands/asn.ts +2122 -0
- package/src/modules/wms/commands/index.ts +2 -0
- package/src/modules/wms/commands/inventory-actions.ts +413 -243
- package/src/modules/wms/commands/putaway.ts +1169 -0
- package/src/modules/wms/commands/shared.ts +51 -0
- package/src/modules/wms/components/backend/AssignPutawayTaskDialog.tsx +328 -0
- package/src/modules/wms/components/backend/CompletePutawayTaskDialog.tsx +366 -0
- package/src/modules/wms/components/backend/CreateAsnDialog.tsx +427 -0
- package/src/modules/wms/components/backend/InventoryOperationsSection.tsx +20 -2
- package/src/modules/wms/components/backend/ReceiveAsnLineDialog.tsx +535 -0
- package/src/modules/wms/components/backend/ReceiveInventoryDialog.tsx +2 -2
- package/src/modules/wms/components/backend/WmsAsnDetailPage.tsx +647 -0
- package/src/modules/wms/components/backend/WmsAsnsListPage.tsx +407 -0
- package/src/modules/wms/components/backend/WmsLocationDetailPage.tsx +4 -5
- package/src/modules/wms/components/backend/WmsLotDetailPage.tsx +4 -5
- package/src/modules/wms/components/backend/WmsOperationalDashboardPage.tsx +12 -8
- package/src/modules/wms/components/backend/WmsPutawayQueuePage.tsx +677 -0
- package/src/modules/wms/components/backend/WmsSkuDetailPage.tsx +4 -5
- package/src/modules/wms/components/backend/asnCompleteOptimisticLock.ts +52 -0
- package/src/modules/wms/components/backend/asnReceivingLinesLoader.ts +83 -0
- package/src/modules/wms/components/backend/inboundStatusUi.ts +154 -0
- package/src/modules/wms/components/backend/inventoryMutationLoaders.ts +20 -0
- package/src/modules/wms/components/backend/putawayQueueOptimisticLock.ts +20 -0
- package/src/modules/wms/components/backend/useWmsInventoryMutationAccess.ts +4 -0
- package/src/modules/wms/data/enrichers.ts +175 -13
- package/src/modules/wms/data/entities.ts +155 -0
- package/src/modules/wms/data/validators.ts +256 -0
- package/src/modules/wms/events.ts +11 -0
- package/src/modules/wms/extension-points.ts +2 -0
- package/src/modules/wms/i18n/de.json +205 -3
- package/src/modules/wms/i18n/en.json +205 -3
- package/src/modules/wms/i18n/es.json +205 -3
- package/src/modules/wms/i18n/ko.json +205 -3
- package/src/modules/wms/i18n/pl.json +205 -3
- package/src/modules/wms/lib/asnReceiving.ts +226 -0
- package/src/modules/wms/lib/asnVendor.ts +80 -0
- package/src/modules/wms/lib/flashMutationError.ts +4 -0
- package/src/modules/wms/lib/inventoryDisplayUi.ts +46 -0
- package/src/modules/wms/lib/inventoryPolicy.ts +31 -1
- package/src/modules/wms/lib/loadOperationalDashboard.ts +89 -1
- package/src/modules/wms/lib/putaway.ts +210 -0
- package/src/modules/wms/lib/roleFeatures.ts +2 -0
- package/src/modules/wms/lib/salesOrderInventoryAutomation.ts +150 -1
- package/src/modules/wms/lib/scanResolve.ts +185 -0
- package/src/modules/wms/lib/wmsIntegrationToggles.ts +2 -1
- package/src/modules/wms/migrations/.snapshot-open-mercato.json +1000 -0
- package/src/modules/wms/migrations/Migration20260812120000.ts +43 -0
- package/src/modules/wms/migrations/Migration20260812130000.ts +28 -0
- package/src/modules/wms/migrations/Migration20260822120000.ts +17 -0
- package/src/modules/wms/migrations/Migration20260822130000.ts +15 -0
- package/src/modules/wms/migrations/Migration20261029120000.ts +11 -0
- package/src/modules/wms/search.ts +95 -0
- package/src/modules/wms/subscribers/asn-line-received-reevaluate-reservations.ts +21 -0
- package/src/modules/wms/subscribers/invalidate-enricher-cache-asn.ts +12 -0
- package/src/modules/wms/subscribers/procurement-goods-receipt-created.ts +238 -0
- package/src/modules/wms/subscribers/putaway-completed-reevaluate-reservations.ts +21 -0
- package/src/modules/wms/widgets/injection/sales-order-stock-context/widget.client.tsx +63 -13
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/wms/api/listEnrichers.ts"],
|
|
4
|
-
"sourcesContent": ["// Lightweight afterList enrichers shared across WMS list routes.\n//\n// These run inside `makeCrudRoute({ hooks: { afterList } })` and batch-resolve\n// foreign-key labels (e.g. warehouse_id -> warehouse_name) so backend tables\n// can render the human-readable label without N+1 lookups on the client.\n//\n// We deliberately use the `queryEngine` (entity-id-based) rather than ORM\n// entity classes so this file stays decoupled from `wms/data/entities`\n// internals and from the catalog ORM \u2014 same pattern used by High #5 in WMS\n// data enrichers.\n\nimport type { CrudCtx } from '@open-mercato/shared/lib/crud/factory'\nimport type { QueryEngine } from '@open-mercato/shared/lib/query/types'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { E } from '#generated/entities.ids.generated'\n\nconst logger = createLogger('wms')\n\ntype AnyListPayload = {\n items?: Array<Record<string, unknown>>\n}\n\ntype LookupRow = Record<string, unknown> & { id?: string | null }\n\nconst LOOKUP_BATCH_SIZE = 500\n\nfunction uniqueIdsFromKeys(\n items: Array<Record<string, unknown>>,\n keys: string[],\n): string[] {\n const set = new Set<string>()\n for (const item of items) {\n for (const key of keys) {\n const value = item?.[key]\n if (typeof value === 'string' && value.length > 0) set.add(value)\n }\n }\n return Array.from(set)\n}\n\n/**\n * Internal: batch-load `entityId` rows by primary id through the QueryEngine\n * and return them keyed by id. Splits requests into chunks of 500. Errors are\n * logged (with a `source` tag for grep-ability) and degrade to an empty map so\n * the surrounding list response still goes through.\n */\nasync function batchLoadById(\n ctx: CrudCtx,\n entityId: string,\n ids: string[],\n fields: string[],\n source: string,\n): Promise<Map<string, LookupRow>> {\n if (ids.length === 0) return new Map()\n const tenantId = ctx.auth?.tenantId\n if (!tenantId) return new Map()\n const queryEngine = ctx.container.resolve('queryEngine') as QueryEngine\n const map = new Map<string, LookupRow>()\n for (let offset = 0; offset < ids.length; offset += LOOKUP_BATCH_SIZE) {\n const slice = ids.slice(offset, offset + LOOKUP_BATCH_SIZE)\n try {\n const result = await queryEngine.query<LookupRow>(entityId, {\n tenantId,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? undefined,\n organizationIds: ctx.organizationIds ?? undefined,\n filters: { id: { $in: slice } },\n fields,\n page: { page: 1, pageSize: slice.length },\n })\n for (const row of result.items ?? []) {\n if (row?.id && typeof row.id === 'string') map.set(row.id, row)\n }\n } catch (err) {\n logger.warn('batch lookup failed', { source, entityId, err })\n }\n }\n return map\n}\n\nfunction decorateOnce(item: Record<string, unknown>, key: string, value: unknown): void {\n if (item[key] === undefined) item[key] = value\n}\n\n// ---------------------------------------------------------------------------\n// Warehouses\n// ---------------------------------------------------------------------------\n\ntype WarehouseRow = LookupRow & { name?: string | null; code?: string | null }\n\nconst WAREHOUSE_FIELDS = ['id', 'name', 'code']\n\n/**\n * Decorate list items with `warehouse_name` and `warehouse_code` when they\n * carry a `warehouse_id` column. Mutates `payload.items` in place.\n */\nexport async function attachWarehouseLabelsToListItems(\n payload: AnyListPayload,\n ctx: CrudCtx,\n): Promise<void> {\n const items = Array.isArray(payload?.items) ? payload.items : []\n if (items.length === 0) return\n const ids = uniqueIdsFromKeys(items, ['warehouse_id'])\n if (ids.length === 0) return\n const map = (await batchLoadById(\n ctx,\n E.wms.warehouse,\n ids,\n WAREHOUSE_FIELDS,\n 'warehouse',\n )) as Map<string, WarehouseRow>\n if (map.size === 0) return\n for (const item of items) {\n const id = item?.warehouse_id\n if (typeof id !== 'string' || !id) continue\n const row = map.get(id)\n if (!row) continue\n decorateOnce(item, 'warehouse_name', row.name ?? null)\n decorateOnce(item, 'warehouse_code', row.code ?? null)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Locations\n// ---------------------------------------------------------------------------\n\ntype LocationLookupRow = LookupRow & { code?: string | null; type?: string | null }\n\nconst LOCATION_FIELDS = ['id', 'code', 'type']\n\n/**\n * Decorate list items with location label/type for any of these foreign-key\n * columns: `location_id`, `location_from_id`, `location_to_id`. The decorated\n * fields follow the same prefix:\n *\n * location_id -> location_code, location_type\n * location_from_id -> location_from_code, location_from_type\n * location_to_id -> location_to_code, location_to_type\n *\n * Mutates `payload.items` in place.\n */\nexport async function attachLocationLabelsToListItems(\n payload: AnyListPayload,\n ctx: CrudCtx,\n): Promise<void> {\n const items = Array.isArray(payload?.items) ? payload.items : []\n if (items.length === 0) return\n const fkColumns = ['location_id', 'location_from_id', 'location_to_id']\n const ids = uniqueIdsFromKeys(items, fkColumns)\n if (ids.length === 0) return\n const map = (await batchLoadById(\n ctx,\n E.wms.warehouse_location,\n ids,\n LOCATION_FIELDS,\n 'location',\n )) as Map<string, LocationLookupRow>\n if (map.size === 0) return\n for (const item of items) {\n for (const fk of fkColumns) {\n const id = item?.[fk]\n if (typeof id !== 'string' || !id) continue\n const row = map.get(id)\n if (!row) continue\n const prefix = fk.replace(/_id$/, '')\n decorateOnce(item, `${prefix}_code`, row.code ?? null)\n decorateOnce(item, `${prefix}_type`, row.type ?? null)\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Catalog variants\n// ---------------------------------------------------------------------------\n\ntype VariantLookupRow = LookupRow & {\n name?: string | null\n sku?: string | null\n product_id?: string | null\n}\n\nconst VARIANT_FIELDS = ['id', 'name', 'sku', 'product_id']\n\n/**\n * Decorate list items with `variant_name`, `variant_sku`, and `product_id`\n * when they carry a `catalog_variant_id` column. Mutates `payload.items` in\n * place. Uses `queryEngine.query(E.catalog.catalog_product_variant, ...)`\n * rather than importing the catalog ORM entity directly, to keep the WMS\n * module decoupled from the catalog package internals.\n */\nexport async function attachVariantLabelsToListItems(\n payload: AnyListPayload,\n ctx: CrudCtx,\n): Promise<void> {\n const items = Array.isArray(payload?.items) ? payload.items : []\n if (items.length === 0) return\n const ids = uniqueIdsFromKeys(items, ['catalog_variant_id'])\n if (ids.length === 0) return\n const map = (await batchLoadById(\n ctx,\n E.catalog.catalog_product_variant,\n ids,\n VARIANT_FIELDS,\n 'variant',\n )) as Map<string, VariantLookupRow>\n if (map.size === 0) return\n for (const item of items) {\n const id = item?.catalog_variant_id\n if (typeof id !== 'string' || !id) continue\n const row = map.get(id)\n if (!row) continue\n decorateOnce(item, 'variant_name', row.name ?? null)\n decorateOnce(item, 'variant_sku', row.sku ?? null)\n decorateOnce(item, 'catalog_product_id', row.product_id ?? null)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Catalog products\n// ---------------------------------------------------------------------------\n\ntype ProductLookupRow = LookupRow & { title?: string | null; sku?: string | null }\n\nconst PRODUCT_FIELDS = ['id', 'title', 'sku']\n\n/**\n * Decorate list items with `product_title` and `product_sku` when they carry a\n * `catalog_product_id` column. Mutates `payload.items` in place.\n */\nexport async function attachProductLabelsToListItems(\n payload: AnyListPayload,\n ctx: CrudCtx,\n): Promise<void> {\n const items = Array.isArray(payload?.items) ? payload.items : []\n if (items.length === 0) return\n const ids = uniqueIdsFromKeys(items, ['catalog_product_id'])\n if (ids.length === 0) return\n const map = (await batchLoadById(\n ctx,\n E.catalog.catalog_product,\n ids,\n PRODUCT_FIELDS,\n 'product',\n )) as Map<string, ProductLookupRow>\n if (map.size === 0) return\n for (const item of items) {\n const id = item?.catalog_product_id\n if (typeof id !== 'string' || !id) continue\n const row = map.get(id)\n if (!row) continue\n decorateOnce(item, 'product_title', row.title ?? null)\n decorateOnce(item, 'product_sku', row.sku ?? null)\n }\n}\n\n/**\n * Decorate inventory profile rows with catalog product and variant labels.\n * Mutates `payload.items` in place.\n */\nexport async function attachInventoryProfileCatalogLabelsToListItems(\n payload: AnyListPayload,\n ctx: CrudCtx,\n): Promise<void> {\n await Promise.all([\n attachProductLabelsToListItems(payload, ctx),\n attachVariantLabelsToListItems(payload, ctx),\n ])\n}\n\n// ---------------------------------------------------------------------------\n// Reservation sources\n// ---------------------------------------------------------------------------\n\ntype SalesOrderLookupRow = LookupRow & { order_number?: string | null }\n\nconst SALES_ORDER_FIELDS = ['id', 'order_number']\n\n/**\n * Decorate reservation rows with `source_label` when the source can be resolved\n * to a human-readable reference (currently sales orders). Mutates\n * `payload.items` in place.\n */\nexport async function attachReservationSourceLabelsToListItems(\n payload: AnyListPayload,\n ctx: CrudCtx,\n): Promise<void> {\n const items = Array.isArray(payload?.items) ? payload.items : []\n if (items.length === 0) return\n\n const orderIds = uniqueIdsFromKeys(\n items.filter((item) => item?.source_type === 'order'),\n ['source_id'],\n )\n if (orderIds.length === 0) return\n\n const map = (await batchLoadById(\n ctx,\n E.sales.sales_order,\n orderIds,\n SALES_ORDER_FIELDS,\n 'reservation-source',\n )) as Map<string, SalesOrderLookupRow>\n if (map.size === 0) return\n\n for (const item of items) {\n if (item?.source_type !== 'order') continue\n const id = item?.source_id\n if (typeof id !== 'string' || !id) continue\n const row = map.get(id)\n const orderNumber = row?.order_number?.trim()\n if (orderNumber) decorateOnce(item, 'source_label', orderNumber)\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["// Lightweight afterList enrichers shared across WMS list routes.\n//\n// These run inside `makeCrudRoute({ hooks: { afterList } })` and batch-resolve\n// foreign-key labels (e.g. warehouse_id -> warehouse_name) so backend tables\n// can render the human-readable label without N+1 lookups on the client.\n//\n// We deliberately use the `queryEngine` (entity-id-based) rather than ORM\n// entity classes so this file stays decoupled from `wms/data/entities`\n// internals and from the catalog ORM \u2014 same pattern used by High #5 in WMS\n// data enrichers.\n\nimport type { CrudCtx } from '@open-mercato/shared/lib/crud/factory'\nimport type { QueryEngine } from '@open-mercato/shared/lib/query/types'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { E } from '#generated/entities.ids.generated'\n\nconst logger = createLogger('wms')\n\ntype AnyListPayload = {\n items?: Array<Record<string, unknown>>\n}\n\ntype LookupRow = Record<string, unknown> & { id?: string | null }\n\nconst LOOKUP_BATCH_SIZE = 500\n\nfunction uniqueIdsFromKeys(\n items: Array<Record<string, unknown>>,\n keys: string[],\n): string[] {\n const set = new Set<string>()\n for (const item of items) {\n for (const key of keys) {\n const value = item?.[key]\n if (typeof value === 'string' && value.length > 0) set.add(value)\n }\n }\n return Array.from(set)\n}\n\n/**\n * Internal: batch-load `entityId` rows by primary id through the QueryEngine\n * and return them keyed by id. Splits requests into chunks of 500. Errors are\n * logged (with a `source` tag for grep-ability) and degrade to an empty map so\n * the surrounding list response still goes through.\n */\nasync function batchLoadById(\n ctx: CrudCtx,\n entityId: string,\n ids: string[],\n fields: string[],\n source: string,\n): Promise<Map<string, LookupRow>> {\n if (ids.length === 0) return new Map()\n const tenantId = ctx.auth?.tenantId\n if (!tenantId) return new Map()\n const queryEngine = ctx.container.resolve('queryEngine') as QueryEngine\n const map = new Map<string, LookupRow>()\n for (let offset = 0; offset < ids.length; offset += LOOKUP_BATCH_SIZE) {\n const slice = ids.slice(offset, offset + LOOKUP_BATCH_SIZE)\n try {\n const result = await queryEngine.query<LookupRow>(entityId, {\n tenantId,\n organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? undefined,\n organizationIds: ctx.organizationIds ?? undefined,\n filters: { id: { $in: slice } },\n fields,\n page: { page: 1, pageSize: slice.length },\n })\n for (const row of result.items ?? []) {\n if (row?.id && typeof row.id === 'string') map.set(row.id, row)\n }\n } catch (err) {\n logger.warn('batch lookup failed', { source, entityId, err })\n }\n }\n return map\n}\n\nfunction decorateOnce(item: Record<string, unknown>, key: string, value: unknown): void {\n if (item[key] === undefined) item[key] = value\n}\n\n// ---------------------------------------------------------------------------\n// Warehouses\n// ---------------------------------------------------------------------------\n\ntype WarehouseRow = LookupRow & { name?: string | null; code?: string | null }\n\nconst WAREHOUSE_FIELDS = ['id', 'name', 'code']\n\n/**\n * Decorate list items with `warehouse_name` and `warehouse_code` when they\n * carry a `warehouse_id` column. Mutates `payload.items` in place.\n */\nexport async function attachWarehouseLabelsToListItems(\n payload: AnyListPayload,\n ctx: CrudCtx,\n): Promise<void> {\n const items = Array.isArray(payload?.items) ? payload.items : []\n if (items.length === 0) return\n const ids = uniqueIdsFromKeys(items, ['warehouse_id'])\n if (ids.length === 0) return\n const map = (await batchLoadById(\n ctx,\n E.wms.warehouse,\n ids,\n WAREHOUSE_FIELDS,\n 'warehouse',\n )) as Map<string, WarehouseRow>\n if (map.size === 0) return\n for (const item of items) {\n const id = item?.warehouse_id\n if (typeof id !== 'string' || !id) continue\n const row = map.get(id)\n if (!row) continue\n decorateOnce(item, 'warehouse_name', row.name ?? null)\n decorateOnce(item, 'warehouse_code', row.code ?? null)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Locations\n// ---------------------------------------------------------------------------\n\ntype LocationLookupRow = LookupRow & { code?: string | null; type?: string | null }\n\nconst LOCATION_FIELDS = ['id', 'code', 'type']\n\n/**\n * Decorate list items with location label/type for any of these foreign-key\n * columns: `location_id`, `location_from_id`, `location_to_id`. The decorated\n * fields follow the same prefix:\n *\n * location_id -> location_code, location_type\n * location_from_id -> location_from_code, location_from_type\n * location_to_id -> location_to_code, location_to_type\n *\n * Mutates `payload.items` in place.\n */\nexport async function attachLocationLabelsToListItems(\n payload: AnyListPayload,\n ctx: CrudCtx,\n): Promise<void> {\n const items = Array.isArray(payload?.items) ? payload.items : []\n if (items.length === 0) return\n const fkColumns = ['location_id', 'location_from_id', 'location_to_id']\n const ids = uniqueIdsFromKeys(items, fkColumns)\n if (ids.length === 0) return\n const map = (await batchLoadById(\n ctx,\n E.wms.warehouse_location,\n ids,\n LOCATION_FIELDS,\n 'location',\n )) as Map<string, LocationLookupRow>\n if (map.size === 0) return\n for (const item of items) {\n for (const fk of fkColumns) {\n const id = item?.[fk]\n if (typeof id !== 'string' || !id) continue\n const row = map.get(id)\n if (!row) continue\n const prefix = fk.replace(/_id$/, '')\n decorateOnce(item, `${prefix}_code`, row.code ?? null)\n decorateOnce(item, `${prefix}_type`, row.type ?? null)\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Catalog variants\n// ---------------------------------------------------------------------------\n\ntype VariantLookupRow = LookupRow & {\n name?: string | null\n sku?: string | null\n product_id?: string | null\n}\n\nconst VARIANT_FIELDS = ['id', 'name', 'sku', 'product_id']\n\n/**\n * Decorate list items with `variant_name`, `variant_sku`, and `product_id`\n * when they carry a `catalog_variant_id` column. Mutates `payload.items` in\n * place. Uses `queryEngine.query(E.catalog.catalog_product_variant, ...)`\n * rather than importing the catalog ORM entity directly, to keep the WMS\n * module decoupled from the catalog package internals.\n */\nexport async function attachVariantLabelsToListItems(\n payload: AnyListPayload,\n ctx: CrudCtx,\n): Promise<void> {\n const items = Array.isArray(payload?.items) ? payload.items : []\n if (items.length === 0) return\n const ids = uniqueIdsFromKeys(items, ['catalog_variant_id'])\n if (ids.length === 0) return\n const map = (await batchLoadById(\n ctx,\n E.catalog.catalog_product_variant,\n ids,\n VARIANT_FIELDS,\n 'variant',\n )) as Map<string, VariantLookupRow>\n if (map.size === 0) return\n for (const item of items) {\n const id = item?.catalog_variant_id\n if (typeof id !== 'string' || !id) continue\n const row = map.get(id)\n if (!row) continue\n decorateOnce(item, 'variant_name', row.name ?? null)\n decorateOnce(item, 'variant_sku', row.sku ?? null)\n decorateOnce(item, 'catalog_product_id', row.product_id ?? null)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Catalog products\n// ---------------------------------------------------------------------------\n\ntype ProductLookupRow = LookupRow & { title?: string | null; sku?: string | null }\n\nconst PRODUCT_FIELDS = ['id', 'title', 'sku']\n\n/**\n * Decorate list items with `product_title` and `product_sku` when they carry a\n * `catalog_product_id` column. Mutates `payload.items` in place.\n */\nexport async function attachProductLabelsToListItems(\n payload: AnyListPayload,\n ctx: CrudCtx,\n): Promise<void> {\n const items = Array.isArray(payload?.items) ? payload.items : []\n if (items.length === 0) return\n const ids = uniqueIdsFromKeys(items, ['catalog_product_id'])\n if (ids.length === 0) return\n const map = (await batchLoadById(\n ctx,\n E.catalog.catalog_product,\n ids,\n PRODUCT_FIELDS,\n 'product',\n )) as Map<string, ProductLookupRow>\n if (map.size === 0) return\n for (const item of items) {\n const id = item?.catalog_product_id\n if (typeof id !== 'string' || !id) continue\n const row = map.get(id)\n if (!row) continue\n decorateOnce(item, 'product_title', row.title ?? null)\n decorateOnce(item, 'product_sku', row.sku ?? null)\n }\n}\n\n/**\n * Decorate inventory profile rows with catalog product and variant labels.\n * Mutates `payload.items` in place.\n */\nexport async function attachInventoryProfileCatalogLabelsToListItems(\n payload: AnyListPayload,\n ctx: CrudCtx,\n): Promise<void> {\n await Promise.all([\n attachProductLabelsToListItems(payload, ctx),\n attachVariantLabelsToListItems(payload, ctx),\n ])\n}\n\n// ---------------------------------------------------------------------------\n// Customers (ASN vendors)\n// ---------------------------------------------------------------------------\n\ntype CustomerLookupRow = LookupRow & { display_name?: string | null }\n\nconst CUSTOMER_FIELDS = ['id', 'display_name']\n\n/**\n * Decorate list items with `vendor_name` when they carry a `vendor_id` column\n * referencing `customers.customer_entity` by UUID only (no ORM cross-module\n * relations). Mutates `payload.items` in place.\n */\nexport async function attachVendorLabelsToListItems(\n payload: AnyListPayload,\n ctx: CrudCtx,\n): Promise<void> {\n const items = Array.isArray(payload?.items) ? payload.items : []\n if (items.length === 0) return\n const ids = uniqueIdsFromKeys(items, ['vendor_id'])\n if (ids.length === 0) return\n const map = (await batchLoadById(\n ctx,\n E.customers.customer_entity,\n ids,\n CUSTOMER_FIELDS,\n 'vendor',\n )) as Map<string, CustomerLookupRow>\n if (map.size === 0) return\n for (const item of items) {\n const id = item?.vendor_id\n if (typeof id !== 'string' || !id) continue\n const row = map.get(id)\n if (!row) continue\n decorateOnce(item, 'vendor_name', row.display_name ?? null)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Reservation sources\n// ---------------------------------------------------------------------------\n\ntype SalesOrderLookupRow = LookupRow & { order_number?: string | null }\n\nconst SALES_ORDER_FIELDS = ['id', 'order_number']\n\n/**\n * Decorate reservation rows with `source_label` when the source can be resolved\n * to a human-readable reference (currently sales orders). Mutates\n * `payload.items` in place.\n */\nexport async function attachReservationSourceLabelsToListItems(\n payload: AnyListPayload,\n ctx: CrudCtx,\n): Promise<void> {\n const items = Array.isArray(payload?.items) ? payload.items : []\n if (items.length === 0) return\n\n const orderIds = uniqueIdsFromKeys(\n items.filter((item) => item?.source_type === 'order'),\n ['source_id'],\n )\n if (orderIds.length === 0) return\n\n const map = (await batchLoadById(\n ctx,\n E.sales.sales_order,\n orderIds,\n SALES_ORDER_FIELDS,\n 'reservation-source',\n )) as Map<string, SalesOrderLookupRow>\n if (map.size === 0) return\n\n for (const item of items) {\n if (item?.source_type !== 'order') continue\n const id = item?.source_id\n if (typeof id !== 'string' || !id) continue\n const row = map.get(id)\n const orderNumber = row?.order_number?.trim()\n if (orderNumber) decorateOnce(item, 'source_label', orderNumber)\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { readJsonSafe } from "@open-mercato/shared/lib/http/readJsonSafe";
|
|
3
|
+
import { putawayTaskAssignSchema } from "../../../../data/validators.js";
|
|
4
|
+
import { executeWmsCustomPostRoute } from "../../../inventory/helpers.js";
|
|
5
|
+
const metadata = {
|
|
6
|
+
POST: { requireAuth: true, requireFeatures: ["wms.manage_putaway"] }
|
|
7
|
+
};
|
|
8
|
+
const paramsSchema = z.object({
|
|
9
|
+
id: z.string().uuid()
|
|
10
|
+
});
|
|
11
|
+
async function POST(request, routeContext) {
|
|
12
|
+
const parsedParams = paramsSchema.parse(routeContext.params);
|
|
13
|
+
const body = await readJsonSafe(request, {});
|
|
14
|
+
const scopedRequest = new Request(request.url, {
|
|
15
|
+
method: "POST",
|
|
16
|
+
headers: request.headers,
|
|
17
|
+
body: JSON.stringify({ ...body, id: parsedParams.id })
|
|
18
|
+
});
|
|
19
|
+
return executeWmsCustomPostRoute({
|
|
20
|
+
request: scopedRequest,
|
|
21
|
+
routePath: `wms/putaway-tasks/${parsedParams.id}/assign`,
|
|
22
|
+
inputSchema: putawayTaskAssignSchema,
|
|
23
|
+
commandId: "wms.putaway-tasks.assign",
|
|
24
|
+
describeResource: (input) => ({
|
|
25
|
+
resourceKind: "wms.putawayTask",
|
|
26
|
+
resourceId: input.id
|
|
27
|
+
}),
|
|
28
|
+
mapSuccess: () => ({ ok: true })
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
const successSchema = z.object({ ok: z.literal(true) });
|
|
32
|
+
const errorSchema = z.object({ error: z.string() });
|
|
33
|
+
const openApi = {
|
|
34
|
+
tag: "WMS",
|
|
35
|
+
summary: "Assign putaway task",
|
|
36
|
+
methods: {
|
|
37
|
+
POST: {
|
|
38
|
+
summary: "Assign putaway task",
|
|
39
|
+
description: "Assigns a putaway task to a user.",
|
|
40
|
+
requestBody: { contentType: "application/json", schema: putawayTaskAssignSchema },
|
|
41
|
+
responses: [{ status: 200, description: "Putaway task assigned", schema: successSchema }],
|
|
42
|
+
errors: [
|
|
43
|
+
{ status: 400, description: "Validation failed", schema: errorSchema },
|
|
44
|
+
{ status: 401, description: "Unauthorized", schema: errorSchema },
|
|
45
|
+
{ status: 403, description: "Forbidden", schema: errorSchema },
|
|
46
|
+
{ status: 409, description: "Invalid putaway state", schema: errorSchema }
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
export {
|
|
52
|
+
POST,
|
|
53
|
+
metadata,
|
|
54
|
+
openApi
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../src/modules/wms/api/putaway-tasks/%5Bid%5D/assign/route.ts"],
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { putawayTaskAssignSchema } from '../../../../data/validators'\nimport { executeWmsCustomPostRoute } from '../../../inventory/helpers'\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['wms.manage_putaway'] },\n}\n\nconst paramsSchema = z.object({\n id: z.string().uuid(),\n})\n\nexport async function POST(request: Request, routeContext: { params: { id: string } }) {\n const parsedParams = paramsSchema.parse(routeContext.params)\n const body = await readJsonSafe<Record<string, unknown>>(request, {})\n const scopedRequest = new Request(request.url, {\n method: 'POST',\n headers: request.headers,\n body: JSON.stringify({ ...body, id: parsedParams.id }),\n })\n return executeWmsCustomPostRoute({\n request: scopedRequest,\n routePath: `wms/putaway-tasks/${parsedParams.id}/assign`,\n inputSchema: putawayTaskAssignSchema,\n commandId: 'wms.putaway-tasks.assign',\n describeResource: (input) => ({\n resourceKind: 'wms.putawayTask',\n resourceId: input.id,\n }),\n mapSuccess: () => ({ ok: true }),\n })\n}\n\nconst successSchema = z.object({ ok: z.literal(true) })\nconst errorSchema = z.object({ error: z.string() })\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'WMS',\n summary: 'Assign putaway task',\n methods: {\n POST: {\n summary: 'Assign putaway task',\n description: 'Assigns a putaway task to a user.',\n requestBody: { contentType: 'application/json', schema: putawayTaskAssignSchema },\n responses: [{ status: 200, description: 'Putaway task assigned', schema: successSchema }],\n errors: [\n { status: 400, description: 'Validation failed', schema: errorSchema },\n { status: 401, description: 'Unauthorized', schema: errorSchema },\n { status: 403, description: 'Forbidden', schema: errorSchema },\n { status: 409, description: 'Invalid putaway state', schema: errorSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,SAAS;AAElB,SAAS,oBAAoB;AAC7B,SAAS,+BAA+B;AACxC,SAAS,iCAAiC;AAEnC,MAAM,WAAW;AAAA,EACtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,oBAAoB,EAAE;AACrE;AAEA,MAAM,eAAe,EAAE,OAAO;AAAA,EAC5B,IAAI,EAAE,OAAO,EAAE,KAAK;AACtB,CAAC;AAED,eAAsB,KAAK,SAAkB,cAA0C;AACrF,QAAM,eAAe,aAAa,MAAM,aAAa,MAAM;AAC3D,QAAM,OAAO,MAAM,aAAsC,SAAS,CAAC,CAAC;AACpE,QAAM,gBAAgB,IAAI,QAAQ,QAAQ,KAAK;AAAA,IAC7C,QAAQ;AAAA,IACR,SAAS,QAAQ;AAAA,IACjB,MAAM,KAAK,UAAU,EAAE,GAAG,MAAM,IAAI,aAAa,GAAG,CAAC;AAAA,EACvD,CAAC;AACD,SAAO,0BAA0B;AAAA,IAC/B,SAAS;AAAA,IACT,WAAW,qBAAqB,aAAa,EAAE;AAAA,IAC/C,aAAa;AAAA,IACb,WAAW;AAAA,IACX,kBAAkB,CAAC,WAAW;AAAA,MAC5B,cAAc;AAAA,MACd,YAAY,MAAM;AAAA,IACpB;AAAA,IACA,YAAY,OAAO,EAAE,IAAI,KAAK;AAAA,EAChC,CAAC;AACH;AAEA,MAAM,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,IAAI,EAAE,CAAC;AACtD,MAAM,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAE3C,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,aAAa,EAAE,aAAa,oBAAoB,QAAQ,wBAAwB;AAAA,MAChF,WAAW,CAAC,EAAE,QAAQ,KAAK,aAAa,yBAAyB,QAAQ,cAAc,CAAC;AAAA,MACxF,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,YAAY;AAAA,QACrE,EAAE,QAAQ,KAAK,aAAa,gBAAgB,QAAQ,YAAY;AAAA,QAChE,EAAE,QAAQ,KAAK,aAAa,aAAa,QAAQ,YAAY;AAAA,QAC7D,EAAE,QAAQ,KAAK,aAAa,yBAAyB,QAAQ,YAAY;AAAA,MAC3E;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { readJsonSafe } from "@open-mercato/shared/lib/http/readJsonSafe";
|
|
3
|
+
import { putawayTaskCancelSchema } from "../../../../data/validators.js";
|
|
4
|
+
import { executeWmsCustomPostRoute } from "../../../inventory/helpers.js";
|
|
5
|
+
const metadata = {
|
|
6
|
+
POST: { requireAuth: true, requireFeatures: ["wms.manage_putaway"] }
|
|
7
|
+
};
|
|
8
|
+
const paramsSchema = z.object({
|
|
9
|
+
id: z.string().uuid()
|
|
10
|
+
});
|
|
11
|
+
async function POST(request, routeContext) {
|
|
12
|
+
const parsedParams = paramsSchema.parse(routeContext.params);
|
|
13
|
+
const body = await readJsonSafe(request, {});
|
|
14
|
+
const scopedRequest = new Request(request.url, {
|
|
15
|
+
method: "POST",
|
|
16
|
+
headers: request.headers,
|
|
17
|
+
body: JSON.stringify({ ...body, id: parsedParams.id })
|
|
18
|
+
});
|
|
19
|
+
return executeWmsCustomPostRoute({
|
|
20
|
+
request: scopedRequest,
|
|
21
|
+
routePath: `wms/putaway-tasks/${parsedParams.id}/cancel`,
|
|
22
|
+
inputSchema: putawayTaskCancelSchema,
|
|
23
|
+
commandId: "wms.putaway-tasks.cancel",
|
|
24
|
+
describeResource: (input) => ({
|
|
25
|
+
resourceKind: "wms.putawayTask",
|
|
26
|
+
resourceId: input.id
|
|
27
|
+
}),
|
|
28
|
+
mapSuccess: () => ({ ok: true })
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
const successSchema = z.object({ ok: z.literal(true) });
|
|
32
|
+
const errorSchema = z.object({ error: z.string() });
|
|
33
|
+
const openApi = {
|
|
34
|
+
tag: "WMS",
|
|
35
|
+
summary: "Cancel putaway task",
|
|
36
|
+
methods: {
|
|
37
|
+
POST: {
|
|
38
|
+
summary: "Cancel putaway task",
|
|
39
|
+
description: "Cancels an open or in-progress putaway task without moving stock.",
|
|
40
|
+
requestBody: { contentType: "application/json", schema: putawayTaskCancelSchema },
|
|
41
|
+
responses: [{ status: 200, description: "Putaway task cancelled", schema: successSchema }],
|
|
42
|
+
errors: [
|
|
43
|
+
{ status: 400, description: "Validation failed", schema: errorSchema },
|
|
44
|
+
{ status: 401, description: "Unauthorized", schema: errorSchema },
|
|
45
|
+
{ status: 403, description: "Forbidden", schema: errorSchema },
|
|
46
|
+
{ status: 409, description: "Invalid putaway state", schema: errorSchema }
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
export {
|
|
52
|
+
POST,
|
|
53
|
+
metadata,
|
|
54
|
+
openApi
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../src/modules/wms/api/putaway-tasks/%5Bid%5D/cancel/route.ts"],
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { putawayTaskCancelSchema } from '../../../../data/validators'\nimport { executeWmsCustomPostRoute } from '../../../inventory/helpers'\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['wms.manage_putaway'] },\n}\n\nconst paramsSchema = z.object({\n id: z.string().uuid(),\n})\n\nexport async function POST(request: Request, routeContext: { params: { id: string } }) {\n const parsedParams = paramsSchema.parse(routeContext.params)\n const body = await readJsonSafe<Record<string, unknown>>(request, {})\n const scopedRequest = new Request(request.url, {\n method: 'POST',\n headers: request.headers,\n body: JSON.stringify({ ...body, id: parsedParams.id }),\n })\n return executeWmsCustomPostRoute({\n request: scopedRequest,\n routePath: `wms/putaway-tasks/${parsedParams.id}/cancel`,\n inputSchema: putawayTaskCancelSchema,\n commandId: 'wms.putaway-tasks.cancel',\n describeResource: (input) => ({\n resourceKind: 'wms.putawayTask',\n resourceId: input.id,\n }),\n mapSuccess: () => ({ ok: true }),\n })\n}\n\nconst successSchema = z.object({ ok: z.literal(true) })\nconst errorSchema = z.object({ error: z.string() })\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'WMS',\n summary: 'Cancel putaway task',\n methods: {\n POST: {\n summary: 'Cancel putaway task',\n description: 'Cancels an open or in-progress putaway task without moving stock.',\n requestBody: { contentType: 'application/json', schema: putawayTaskCancelSchema },\n responses: [{ status: 200, description: 'Putaway task cancelled', schema: successSchema }],\n errors: [\n { status: 400, description: 'Validation failed', schema: errorSchema },\n { status: 401, description: 'Unauthorized', schema: errorSchema },\n { status: 403, description: 'Forbidden', schema: errorSchema },\n { status: 409, description: 'Invalid putaway state', schema: errorSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,SAAS;AAElB,SAAS,oBAAoB;AAC7B,SAAS,+BAA+B;AACxC,SAAS,iCAAiC;AAEnC,MAAM,WAAW;AAAA,EACtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,oBAAoB,EAAE;AACrE;AAEA,MAAM,eAAe,EAAE,OAAO;AAAA,EAC5B,IAAI,EAAE,OAAO,EAAE,KAAK;AACtB,CAAC;AAED,eAAsB,KAAK,SAAkB,cAA0C;AACrF,QAAM,eAAe,aAAa,MAAM,aAAa,MAAM;AAC3D,QAAM,OAAO,MAAM,aAAsC,SAAS,CAAC,CAAC;AACpE,QAAM,gBAAgB,IAAI,QAAQ,QAAQ,KAAK;AAAA,IAC7C,QAAQ;AAAA,IACR,SAAS,QAAQ;AAAA,IACjB,MAAM,KAAK,UAAU,EAAE,GAAG,MAAM,IAAI,aAAa,GAAG,CAAC;AAAA,EACvD,CAAC;AACD,SAAO,0BAA0B;AAAA,IAC/B,SAAS;AAAA,IACT,WAAW,qBAAqB,aAAa,EAAE;AAAA,IAC/C,aAAa;AAAA,IACb,WAAW;AAAA,IACX,kBAAkB,CAAC,WAAW;AAAA,MAC5B,cAAc;AAAA,MACd,YAAY,MAAM;AAAA,IACpB;AAAA,IACA,YAAY,OAAO,EAAE,IAAI,KAAK;AAAA,EAChC,CAAC;AACH;AAEA,MAAM,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,IAAI,EAAE,CAAC;AACtD,MAAM,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAE3C,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,aAAa,EAAE,aAAa,oBAAoB,QAAQ,wBAAwB;AAAA,MAChF,WAAW,CAAC,EAAE,QAAQ,KAAK,aAAa,0BAA0B,QAAQ,cAAc,CAAC;AAAA,MACzF,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,YAAY;AAAA,QACrE,EAAE,QAAQ,KAAK,aAAa,gBAAgB,QAAQ,YAAY;AAAA,QAChE,EAAE,QAAQ,KAAK,aAAa,aAAa,QAAQ,YAAY;AAAA,QAC7D,EAAE,QAAQ,KAAK,aAAa,yBAAyB,QAAQ,YAAY;AAAA,MAC3E;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { readJsonSafe } from "@open-mercato/shared/lib/http/readJsonSafe";
|
|
3
|
+
import { putawayTaskCompleteSchema } from "../../../../data/validators.js";
|
|
4
|
+
import { executeWmsCustomPostRoute } from "../../../inventory/helpers.js";
|
|
5
|
+
const metadata = {
|
|
6
|
+
// Floor ACL: stock-moving operators (`wms.adjust_inventory`) and managers both hold this.
|
|
7
|
+
// Command also allows `wms.manage_putaway` for any task, or adjust + assignee match.
|
|
8
|
+
POST: { requireAuth: true, requireFeatures: ["wms.adjust_inventory"] }
|
|
9
|
+
};
|
|
10
|
+
const paramsSchema = z.object({
|
|
11
|
+
id: z.string().uuid()
|
|
12
|
+
});
|
|
13
|
+
async function POST(request, routeContext) {
|
|
14
|
+
const parsedParams = paramsSchema.parse(routeContext.params);
|
|
15
|
+
const body = await readJsonSafe(request, {});
|
|
16
|
+
const scopedRequest = new Request(request.url, {
|
|
17
|
+
method: "POST",
|
|
18
|
+
headers: request.headers,
|
|
19
|
+
body: JSON.stringify({ ...body, id: parsedParams.id })
|
|
20
|
+
});
|
|
21
|
+
return executeWmsCustomPostRoute({
|
|
22
|
+
request: scopedRequest,
|
|
23
|
+
routePath: `wms/putaway-tasks/${parsedParams.id}/complete`,
|
|
24
|
+
inputSchema: putawayTaskCompleteSchema,
|
|
25
|
+
commandId: "wms.putaway-tasks.complete",
|
|
26
|
+
describeResource: (input) => ({
|
|
27
|
+
resourceKind: "wms.putawayTask",
|
|
28
|
+
resourceId: input.id
|
|
29
|
+
}),
|
|
30
|
+
mapSuccess: (result) => ({
|
|
31
|
+
ok: true,
|
|
32
|
+
movementId: result.movementId
|
|
33
|
+
})
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
const successSchema = z.object({
|
|
37
|
+
ok: z.literal(true),
|
|
38
|
+
movementId: z.string().uuid()
|
|
39
|
+
});
|
|
40
|
+
const errorSchema = z.object({ error: z.string() });
|
|
41
|
+
const openApi = {
|
|
42
|
+
tag: "WMS",
|
|
43
|
+
summary: "Complete putaway task",
|
|
44
|
+
methods: {
|
|
45
|
+
POST: {
|
|
46
|
+
summary: "Complete putaway task",
|
|
47
|
+
description: "Confirms putaway quantity and target location, then moves stock staging\u2192storage via an InventoryMovement of type putaway. Requires `wms.adjust_inventory`. Callers with `wms.manage_putaway` may complete any task; operators may complete only when the task is assigned to them.",
|
|
48
|
+
requestBody: { contentType: "application/json", schema: putawayTaskCompleteSchema },
|
|
49
|
+
responses: [{ status: 200, description: "Putaway completed", schema: successSchema }],
|
|
50
|
+
errors: [
|
|
51
|
+
{ status: 400, description: "Validation failed", schema: errorSchema },
|
|
52
|
+
{ status: 401, description: "Unauthorized", schema: errorSchema },
|
|
53
|
+
{ status: 403, description: "Forbidden", schema: errorSchema },
|
|
54
|
+
{ status: 409, description: "Invalid putaway state or insufficient stock", schema: errorSchema },
|
|
55
|
+
{ status: 422, description: "Invalid or inactive location", schema: errorSchema }
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
export {
|
|
61
|
+
POST,
|
|
62
|
+
metadata,
|
|
63
|
+
openApi
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../src/modules/wms/api/putaway-tasks/%5Bid%5D/complete/route.ts"],
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { putawayTaskCompleteSchema } from '../../../../data/validators'\nimport { executeWmsCustomPostRoute } from '../../../inventory/helpers'\n\nexport const metadata = {\n // Floor ACL: stock-moving operators (`wms.adjust_inventory`) and managers both hold this.\n // Command also allows `wms.manage_putaway` for any task, or adjust + assignee match.\n POST: { requireAuth: true, requireFeatures: ['wms.adjust_inventory'] },\n}\n\nconst paramsSchema = z.object({\n id: z.string().uuid(),\n})\n\nexport async function POST(request: Request, routeContext: { params: { id: string } }) {\n const parsedParams = paramsSchema.parse(routeContext.params)\n const body = await readJsonSafe<Record<string, unknown>>(request, {})\n const scopedRequest = new Request(request.url, {\n method: 'POST',\n headers: request.headers,\n body: JSON.stringify({ ...body, id: parsedParams.id }),\n })\n return executeWmsCustomPostRoute({\n request: scopedRequest,\n routePath: `wms/putaway-tasks/${parsedParams.id}/complete`,\n inputSchema: putawayTaskCompleteSchema,\n commandId: 'wms.putaway-tasks.complete',\n describeResource: (input) => ({\n resourceKind: 'wms.putawayTask',\n resourceId: input.id,\n }),\n mapSuccess: (result: { movementId: string }) => ({\n ok: true,\n movementId: result.movementId,\n }),\n })\n}\n\nconst successSchema = z.object({\n ok: z.literal(true),\n movementId: z.string().uuid(),\n})\nconst errorSchema = z.object({ error: z.string() })\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'WMS',\n summary: 'Complete putaway task',\n methods: {\n POST: {\n summary: 'Complete putaway task',\n description:\n 'Confirms putaway quantity and target location, then moves stock staging\u2192storage via an InventoryMovement of type putaway. Requires `wms.adjust_inventory`. Callers with `wms.manage_putaway` may complete any task; operators may complete only when the task is assigned to them.',\n requestBody: { contentType: 'application/json', schema: putawayTaskCompleteSchema },\n responses: [{ status: 200, description: 'Putaway completed', schema: successSchema }],\n errors: [\n { status: 400, description: 'Validation failed', schema: errorSchema },\n { status: 401, description: 'Unauthorized', schema: errorSchema },\n { status: 403, description: 'Forbidden', schema: errorSchema },\n { status: 409, description: 'Invalid putaway state or insufficient stock', schema: errorSchema },\n { status: 422, description: 'Invalid or inactive location', schema: errorSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,SAAS;AAElB,SAAS,oBAAoB;AAC7B,SAAS,iCAAiC;AAC1C,SAAS,iCAAiC;AAEnC,MAAM,WAAW;AAAA;AAAA;AAAA,EAGtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,sBAAsB,EAAE;AACvE;AAEA,MAAM,eAAe,EAAE,OAAO;AAAA,EAC5B,IAAI,EAAE,OAAO,EAAE,KAAK;AACtB,CAAC;AAED,eAAsB,KAAK,SAAkB,cAA0C;AACrF,QAAM,eAAe,aAAa,MAAM,aAAa,MAAM;AAC3D,QAAM,OAAO,MAAM,aAAsC,SAAS,CAAC,CAAC;AACpE,QAAM,gBAAgB,IAAI,QAAQ,QAAQ,KAAK;AAAA,IAC7C,QAAQ;AAAA,IACR,SAAS,QAAQ;AAAA,IACjB,MAAM,KAAK,UAAU,EAAE,GAAG,MAAM,IAAI,aAAa,GAAG,CAAC;AAAA,EACvD,CAAC;AACD,SAAO,0BAA0B;AAAA,IAC/B,SAAS;AAAA,IACT,WAAW,qBAAqB,aAAa,EAAE;AAAA,IAC/C,aAAa;AAAA,IACb,WAAW;AAAA,IACX,kBAAkB,CAAC,WAAW;AAAA,MAC5B,cAAc;AAAA,MACd,YAAY,MAAM;AAAA,IACpB;AAAA,IACA,YAAY,CAAC,YAAoC;AAAA,MAC/C,IAAI;AAAA,MACJ,YAAY,OAAO;AAAA,IACrB;AAAA,EACF,CAAC;AACH;AAEA,MAAM,gBAAgB,EAAE,OAAO;AAAA,EAC7B,IAAI,EAAE,QAAQ,IAAI;AAAA,EAClB,YAAY,EAAE,OAAO,EAAE,KAAK;AAC9B,CAAC;AACD,MAAM,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAE3C,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,aACE;AAAA,MACF,aAAa,EAAE,aAAa,oBAAoB,QAAQ,0BAA0B;AAAA,MAClF,WAAW,CAAC,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,cAAc,CAAC;AAAA,MACpF,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,YAAY;AAAA,QACrE,EAAE,QAAQ,KAAK,aAAa,gBAAgB,QAAQ,YAAY;AAAA,QAChE,EAAE,QAAQ,KAAK,aAAa,aAAa,QAAQ,YAAY;AAAA,QAC7D,EAAE,QAAQ,KAAK,aAAa,+CAA+C,QAAQ,YAAY;AAAA,QAC/F,EAAE,QAAQ,KAAK,aAAa,gCAAgC,QAAQ,YAAY;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { readJsonSafe } from "@open-mercato/shared/lib/http/readJsonSafe";
|
|
3
|
+
import { putawayTaskStartSchema } from "../../../../data/validators.js";
|
|
4
|
+
import { executeWmsCustomPostRoute } from "../../../inventory/helpers.js";
|
|
5
|
+
const metadata = {
|
|
6
|
+
POST: { requireAuth: true, requireFeatures: ["wms.manage_putaway"] }
|
|
7
|
+
};
|
|
8
|
+
const paramsSchema = z.object({
|
|
9
|
+
id: z.string().uuid()
|
|
10
|
+
});
|
|
11
|
+
async function POST(request, routeContext) {
|
|
12
|
+
const parsedParams = paramsSchema.parse(routeContext.params);
|
|
13
|
+
const body = await readJsonSafe(request, {});
|
|
14
|
+
const scopedRequest = new Request(request.url, {
|
|
15
|
+
method: "POST",
|
|
16
|
+
headers: request.headers,
|
|
17
|
+
body: JSON.stringify({ ...body, id: parsedParams.id })
|
|
18
|
+
});
|
|
19
|
+
return executeWmsCustomPostRoute({
|
|
20
|
+
request: scopedRequest,
|
|
21
|
+
routePath: `wms/putaway-tasks/${parsedParams.id}/start`,
|
|
22
|
+
inputSchema: putawayTaskStartSchema,
|
|
23
|
+
commandId: "wms.putaway-tasks.start",
|
|
24
|
+
describeResource: (input) => ({
|
|
25
|
+
resourceKind: "wms.putawayTask",
|
|
26
|
+
resourceId: input.id
|
|
27
|
+
}),
|
|
28
|
+
mapSuccess: () => ({ ok: true })
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
const successSchema = z.object({ ok: z.literal(true) });
|
|
32
|
+
const errorSchema = z.object({ error: z.string() });
|
|
33
|
+
const openApi = {
|
|
34
|
+
tag: "WMS",
|
|
35
|
+
summary: "Start putaway task",
|
|
36
|
+
methods: {
|
|
37
|
+
POST: {
|
|
38
|
+
summary: "Start putaway task",
|
|
39
|
+
description: "Marks a putaway task as in progress.",
|
|
40
|
+
requestBody: { contentType: "application/json", schema: putawayTaskStartSchema },
|
|
41
|
+
responses: [{ status: 200, description: "Putaway task started", schema: successSchema }],
|
|
42
|
+
errors: [
|
|
43
|
+
{ status: 400, description: "Validation failed", schema: errorSchema },
|
|
44
|
+
{ status: 401, description: "Unauthorized", schema: errorSchema },
|
|
45
|
+
{ status: 403, description: "Forbidden", schema: errorSchema },
|
|
46
|
+
{ status: 409, description: "Invalid putaway state", schema: errorSchema }
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
export {
|
|
52
|
+
POST,
|
|
53
|
+
metadata,
|
|
54
|
+
openApi
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../src/modules/wms/api/putaway-tasks/%5Bid%5D/start/route.ts"],
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { putawayTaskStartSchema } from '../../../../data/validators'\nimport { executeWmsCustomPostRoute } from '../../../inventory/helpers'\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['wms.manage_putaway'] },\n}\n\nconst paramsSchema = z.object({\n id: z.string().uuid(),\n})\n\nexport async function POST(request: Request, routeContext: { params: { id: string } }) {\n const parsedParams = paramsSchema.parse(routeContext.params)\n const body = await readJsonSafe<Record<string, unknown>>(request, {})\n const scopedRequest = new Request(request.url, {\n method: 'POST',\n headers: request.headers,\n body: JSON.stringify({ ...body, id: parsedParams.id }),\n })\n return executeWmsCustomPostRoute({\n request: scopedRequest,\n routePath: `wms/putaway-tasks/${parsedParams.id}/start`,\n inputSchema: putawayTaskStartSchema,\n commandId: 'wms.putaway-tasks.start',\n describeResource: (input) => ({\n resourceKind: 'wms.putawayTask',\n resourceId: input.id,\n }),\n mapSuccess: () => ({ ok: true }),\n })\n}\n\nconst successSchema = z.object({ ok: z.literal(true) })\nconst errorSchema = z.object({ error: z.string() })\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'WMS',\n summary: 'Start putaway task',\n methods: {\n POST: {\n summary: 'Start putaway task',\n description: 'Marks a putaway task as in progress.',\n requestBody: { contentType: 'application/json', schema: putawayTaskStartSchema },\n responses: [{ status: 200, description: 'Putaway task started', schema: successSchema }],\n errors: [\n { status: 400, description: 'Validation failed', schema: errorSchema },\n { status: 401, description: 'Unauthorized', schema: errorSchema },\n { status: 403, description: 'Forbidden', schema: errorSchema },\n { status: 409, description: 'Invalid putaway state', schema: errorSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,SAAS;AAElB,SAAS,oBAAoB;AAC7B,SAAS,8BAA8B;AACvC,SAAS,iCAAiC;AAEnC,MAAM,WAAW;AAAA,EACtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,oBAAoB,EAAE;AACrE;AAEA,MAAM,eAAe,EAAE,OAAO;AAAA,EAC5B,IAAI,EAAE,OAAO,EAAE,KAAK;AACtB,CAAC;AAED,eAAsB,KAAK,SAAkB,cAA0C;AACrF,QAAM,eAAe,aAAa,MAAM,aAAa,MAAM;AAC3D,QAAM,OAAO,MAAM,aAAsC,SAAS,CAAC,CAAC;AACpE,QAAM,gBAAgB,IAAI,QAAQ,QAAQ,KAAK;AAAA,IAC7C,QAAQ;AAAA,IACR,SAAS,QAAQ;AAAA,IACjB,MAAM,KAAK,UAAU,EAAE,GAAG,MAAM,IAAI,aAAa,GAAG,CAAC;AAAA,EACvD,CAAC;AACD,SAAO,0BAA0B;AAAA,IAC/B,SAAS;AAAA,IACT,WAAW,qBAAqB,aAAa,EAAE;AAAA,IAC/C,aAAa;AAAA,IACb,WAAW;AAAA,IACX,kBAAkB,CAAC,WAAW;AAAA,MAC5B,cAAc;AAAA,MACd,YAAY,MAAM;AAAA,IACpB;AAAA,IACA,YAAY,OAAO,EAAE,IAAI,KAAK;AAAA,EAChC,CAAC;AACH;AAEA,MAAM,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,IAAI,EAAE,CAAC;AACtD,MAAM,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAE3C,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,aAAa,EAAE,aAAa,oBAAoB,QAAQ,uBAAuB;AAAA,MAC/E,WAAW,CAAC,EAAE,QAAQ,KAAK,aAAa,wBAAwB,QAAQ,cAAc,CAAC;AAAA,MACvF,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,YAAY;AAAA,QACrE,EAAE,QAAQ,KAAK,aAAa,gBAAgB,QAAQ,YAAY;AAAA,QAChE,EAAE,QAAQ,KAAK,aAAa,aAAa,QAAQ,YAAY;AAAA,QAC7D,EAAE,QAAQ,KAAK,aAAa,yBAAyB,QAAQ,YAAY;AAAA,MAC3E;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { putawayTaskCreateFromBalanceSchema } from "../../../data/validators.js";
|
|
3
|
+
import { executeWmsCustomPostRoute } from "../../inventory/helpers.js";
|
|
4
|
+
const metadata = {
|
|
5
|
+
POST: { requireAuth: true, requireFeatures: ["wms.manage_putaway"] }
|
|
6
|
+
};
|
|
7
|
+
async function POST(request) {
|
|
8
|
+
return executeWmsCustomPostRoute({
|
|
9
|
+
request,
|
|
10
|
+
routePath: "wms/putaway-tasks/create-from-balance",
|
|
11
|
+
inputSchema: putawayTaskCreateFromBalanceSchema,
|
|
12
|
+
commandId: "wms.putaway-tasks.create-from-balance",
|
|
13
|
+
describeResource: (input) => ({
|
|
14
|
+
resourceKind: "wms.putawayTask",
|
|
15
|
+
resourceId: `${input.warehouseId}:${input.sourceLocationId}:${input.catalogVariantId}`
|
|
16
|
+
}),
|
|
17
|
+
mapSuccess: (result) => ({
|
|
18
|
+
ok: true,
|
|
19
|
+
taskId: result.taskId
|
|
20
|
+
})
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
const successSchema = z.object({
|
|
24
|
+
ok: z.literal(true),
|
|
25
|
+
taskId: z.string().uuid()
|
|
26
|
+
});
|
|
27
|
+
const errorSchema = z.object({ error: z.string() });
|
|
28
|
+
const openApi = {
|
|
29
|
+
tag: "WMS",
|
|
30
|
+
summary: "Create putaway task from balance",
|
|
31
|
+
methods: {
|
|
32
|
+
POST: {
|
|
33
|
+
summary: "Create putaway task from balance",
|
|
34
|
+
description: "Manually creates an open putaway task against existing staged stock.",
|
|
35
|
+
requestBody: { contentType: "application/json", schema: putawayTaskCreateFromBalanceSchema },
|
|
36
|
+
responses: [{ status: 200, description: "Putaway task created", schema: successSchema }],
|
|
37
|
+
errors: [
|
|
38
|
+
{ status: 400, description: "Validation failed", schema: errorSchema },
|
|
39
|
+
{ status: 401, description: "Unauthorized", schema: errorSchema },
|
|
40
|
+
{ status: 403, description: "Forbidden", schema: errorSchema },
|
|
41
|
+
{ status: 422, description: "Invalid location", schema: errorSchema }
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
export {
|
|
47
|
+
POST,
|
|
48
|
+
metadata,
|
|
49
|
+
openApi
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../src/modules/wms/api/putaway-tasks/create-from-balance/route.ts"],
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { putawayTaskCreateFromBalanceSchema } from '../../../data/validators'\nimport { executeWmsCustomPostRoute } from '../../inventory/helpers'\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['wms.manage_putaway'] },\n}\n\nexport async function POST(request: Request) {\n return executeWmsCustomPostRoute({\n request,\n routePath: 'wms/putaway-tasks/create-from-balance',\n inputSchema: putawayTaskCreateFromBalanceSchema,\n commandId: 'wms.putaway-tasks.create-from-balance',\n describeResource: (input) => ({\n resourceKind: 'wms.putawayTask',\n resourceId: `${input.warehouseId}:${input.sourceLocationId}:${input.catalogVariantId}`,\n }),\n mapSuccess: (result: { taskId: string }) => ({\n ok: true,\n taskId: result.taskId,\n }),\n })\n}\n\nconst successSchema = z.object({\n ok: z.literal(true),\n taskId: z.string().uuid(),\n})\nconst errorSchema = z.object({ error: z.string() })\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'WMS',\n summary: 'Create putaway task from balance',\n methods: {\n POST: {\n summary: 'Create putaway task from balance',\n description: 'Manually creates an open putaway task against existing staged stock.',\n requestBody: { contentType: 'application/json', schema: putawayTaskCreateFromBalanceSchema },\n responses: [{ status: 200, description: 'Putaway task created', schema: successSchema }],\n errors: [\n { status: 400, description: 'Validation failed', schema: errorSchema },\n { status: 401, description: 'Unauthorized', schema: errorSchema },\n { status: 403, description: 'Forbidden', schema: errorSchema },\n { status: 422, description: 'Invalid location', schema: errorSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,SAAS;AAElB,SAAS,0CAA0C;AACnD,SAAS,iCAAiC;AAEnC,MAAM,WAAW;AAAA,EACtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,oBAAoB,EAAE;AACrE;AAEA,eAAsB,KAAK,SAAkB;AAC3C,SAAO,0BAA0B;AAAA,IAC/B;AAAA,IACA,WAAW;AAAA,IACX,aAAa;AAAA,IACb,WAAW;AAAA,IACX,kBAAkB,CAAC,WAAW;AAAA,MAC5B,cAAc;AAAA,MACd,YAAY,GAAG,MAAM,WAAW,IAAI,MAAM,gBAAgB,IAAI,MAAM,gBAAgB;AAAA,IACtF;AAAA,IACA,YAAY,CAAC,YAAgC;AAAA,MAC3C,IAAI;AAAA,MACJ,QAAQ,OAAO;AAAA,IACjB;AAAA,EACF,CAAC;AACH;AAEA,MAAM,gBAAgB,EAAE,OAAO;AAAA,EAC7B,IAAI,EAAE,QAAQ,IAAI;AAAA,EAClB,QAAQ,EAAE,OAAO,EAAE,KAAK;AAC1B,CAAC;AACD,MAAM,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAE3C,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,aAAa;AAAA,MACb,aAAa,EAAE,aAAa,oBAAoB,QAAQ,mCAAmC;AAAA,MAC3F,WAAW,CAAC,EAAE,QAAQ,KAAK,aAAa,wBAAwB,QAAQ,cAAc,CAAC;AAAA,MACvF,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,YAAY;AAAA,QACrE,EAAE,QAAQ,KAAK,aAAa,gBAAgB,QAAQ,YAAY;AAAA,QAChE,EAAE,QAAQ,KAAK,aAAa,aAAa,QAAQ,YAAY;AAAA,QAC7D,EAAE,QAAQ,KAAK,aAAa,oBAAoB,QAAQ,YAAY;AAAA,MACtE;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { makeCrudRoute } from "@open-mercato/shared/lib/crud/factory";
|
|
3
|
+
import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
|
|
4
|
+
import { parseScopedCommandInput, resolveCrudRecordId } from "@open-mercato/shared/lib/api/scoped";
|
|
5
|
+
import { E } from "../../../../generated/entities.ids.generated.js";
|
|
6
|
+
import { PutawayTask } from "../../data/entities.js";
|
|
7
|
+
import { putawayTaskCreateSchema, putawayTaskUpdateSchema } from "../../data/validators.js";
|
|
8
|
+
import {
|
|
9
|
+
assertPutawayLifecycleFieldsForbidden,
|
|
10
|
+
buildPutawayTaskStatusFilter
|
|
11
|
+
} from "../../lib/putaway.js";
|
|
12
|
+
import { createPagedListResponseSchema, createWmsCrudOpenApi, defaultOkResponseSchema } from "../openapi.js";
|
|
13
|
+
const F = {
|
|
14
|
+
id: "id",
|
|
15
|
+
organization_id: "organization_id",
|
|
16
|
+
tenant_id: "tenant_id",
|
|
17
|
+
warehouse_id: "warehouse_id",
|
|
18
|
+
source_location_id: "source_location_id",
|
|
19
|
+
target_location_id: "target_location_id",
|
|
20
|
+
catalog_variant_id: "catalog_variant_id",
|
|
21
|
+
lot_id: "lot_id",
|
|
22
|
+
serial_number: "serial_number",
|
|
23
|
+
quantity: "quantity",
|
|
24
|
+
status: "status",
|
|
25
|
+
assigned_to: "assigned_to",
|
|
26
|
+
priority: "priority",
|
|
27
|
+
created_at: "created_at",
|
|
28
|
+
updated_at: "updated_at"
|
|
29
|
+
};
|
|
30
|
+
const routeMetadata = {
|
|
31
|
+
GET: { requireAuth: true, requireFeatures: ["wms.view"] },
|
|
32
|
+
POST: { requireAuth: true, requireFeatures: ["wms.manage_putaway"] },
|
|
33
|
+
PUT: { requireAuth: true, requireFeatures: ["wms.manage_putaway"] },
|
|
34
|
+
DELETE: { requireAuth: true, requireFeatures: ["wms.manage_putaway"] }
|
|
35
|
+
};
|
|
36
|
+
const metadata = routeMetadata;
|
|
37
|
+
const rawBodySchema = z.object({}).passthrough();
|
|
38
|
+
const listSchema = z.object({
|
|
39
|
+
page: z.coerce.number().min(1).default(1),
|
|
40
|
+
pageSize: z.coerce.number().min(1).max(100).default(25),
|
|
41
|
+
ids: z.string().optional(),
|
|
42
|
+
warehouseId: z.string().uuid().optional(),
|
|
43
|
+
// Single status or comma-separated (e.g. open,in_progress for the active queue).
|
|
44
|
+
status: z.string().optional(),
|
|
45
|
+
assignedTo: z.string().uuid().optional(),
|
|
46
|
+
catalogVariantId: z.string().uuid().optional(),
|
|
47
|
+
sortField: z.string().optional(),
|
|
48
|
+
sortDir: z.enum(["asc", "desc"]).optional()
|
|
49
|
+
}).passthrough();
|
|
50
|
+
const crud = makeCrudRoute({
|
|
51
|
+
metadata: routeMetadata,
|
|
52
|
+
orm: {
|
|
53
|
+
entity: PutawayTask,
|
|
54
|
+
idField: "id",
|
|
55
|
+
orgField: "organizationId",
|
|
56
|
+
tenantField: "tenantId",
|
|
57
|
+
softDeleteField: "deletedAt"
|
|
58
|
+
},
|
|
59
|
+
indexer: { entityType: E.wms.putaway_task },
|
|
60
|
+
list: {
|
|
61
|
+
schema: listSchema,
|
|
62
|
+
disableListCache: true,
|
|
63
|
+
entityId: E.wms.putaway_task,
|
|
64
|
+
fields: [
|
|
65
|
+
F.id,
|
|
66
|
+
F.organization_id,
|
|
67
|
+
F.tenant_id,
|
|
68
|
+
F.warehouse_id,
|
|
69
|
+
F.source_location_id,
|
|
70
|
+
F.target_location_id,
|
|
71
|
+
F.catalog_variant_id,
|
|
72
|
+
F.lot_id,
|
|
73
|
+
F.serial_number,
|
|
74
|
+
F.quantity,
|
|
75
|
+
F.status,
|
|
76
|
+
F.assigned_to,
|
|
77
|
+
F.priority,
|
|
78
|
+
F.created_at,
|
|
79
|
+
F.updated_at
|
|
80
|
+
],
|
|
81
|
+
sortFieldMap: {
|
|
82
|
+
status: F.status,
|
|
83
|
+
priority: F.priority,
|
|
84
|
+
createdAt: F.created_at,
|
|
85
|
+
updatedAt: F.updated_at,
|
|
86
|
+
quantity: F.quantity
|
|
87
|
+
},
|
|
88
|
+
buildFilters: async (query) => {
|
|
89
|
+
const filters = {};
|
|
90
|
+
if (typeof query.ids === "string" && query.ids.trim().length > 0) {
|
|
91
|
+
filters[F.id] = {
|
|
92
|
+
$in: query.ids.split(",").map((value) => value.trim()).filter((value) => value.length > 0)
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
if (typeof query.warehouseId === "string" && query.warehouseId.length > 0) {
|
|
96
|
+
filters[F.warehouse_id] = { $eq: query.warehouseId };
|
|
97
|
+
}
|
|
98
|
+
if (typeof query.status === "string" && query.status.length > 0) {
|
|
99
|
+
const statusFilter = buildPutawayTaskStatusFilter(query.status);
|
|
100
|
+
if (statusFilter) filters[F.status] = statusFilter;
|
|
101
|
+
}
|
|
102
|
+
if (typeof query.assignedTo === "string" && query.assignedTo.length > 0) {
|
|
103
|
+
filters[F.assigned_to] = { $eq: query.assignedTo };
|
|
104
|
+
}
|
|
105
|
+
if (typeof query.catalogVariantId === "string" && query.catalogVariantId.length > 0) {
|
|
106
|
+
filters[F.catalog_variant_id] = { $eq: query.catalogVariantId };
|
|
107
|
+
}
|
|
108
|
+
return filters;
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
actions: {
|
|
112
|
+
create: {
|
|
113
|
+
commandId: "wms.putaway-tasks.create",
|
|
114
|
+
schema: rawBodySchema,
|
|
115
|
+
mapInput: async ({ raw, ctx }) => {
|
|
116
|
+
const { translate } = await resolveTranslations();
|
|
117
|
+
return parseScopedCommandInput(putawayTaskCreateSchema, raw ?? {}, ctx, translate);
|
|
118
|
+
},
|
|
119
|
+
response: ({ result }) => ({ id: result?.taskId ?? null }),
|
|
120
|
+
status: 201
|
|
121
|
+
},
|
|
122
|
+
update: {
|
|
123
|
+
commandId: "wms.putaway-tasks.update",
|
|
124
|
+
schema: rawBodySchema,
|
|
125
|
+
mapInput: async ({ raw, ctx }) => {
|
|
126
|
+
const { translate } = await resolveTranslations();
|
|
127
|
+
assertPutawayLifecycleFieldsForbidden(raw);
|
|
128
|
+
return parseScopedCommandInput(putawayTaskUpdateSchema, raw ?? {}, ctx, translate);
|
|
129
|
+
},
|
|
130
|
+
response: () => ({ ok: true })
|
|
131
|
+
},
|
|
132
|
+
delete: {
|
|
133
|
+
commandId: "wms.putaway-tasks.delete",
|
|
134
|
+
schema: rawBodySchema,
|
|
135
|
+
mapInput: async ({ parsed, ctx }) => {
|
|
136
|
+
const { translate } = await resolveTranslations();
|
|
137
|
+
return { id: resolveCrudRecordId(parsed, ctx, translate) };
|
|
138
|
+
},
|
|
139
|
+
response: () => ({ ok: true })
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
const GET = crud.GET;
|
|
144
|
+
const POST = crud.POST;
|
|
145
|
+
const PUT = crud.PUT;
|
|
146
|
+
const DELETE = crud.DELETE;
|
|
147
|
+
const putawayTaskListItemSchema = z.object({
|
|
148
|
+
id: z.string().uuid().nullable().optional(),
|
|
149
|
+
organization_id: z.string().uuid().nullable().optional(),
|
|
150
|
+
tenant_id: z.string().uuid().nullable().optional(),
|
|
151
|
+
warehouse_id: z.string().uuid().nullable().optional(),
|
|
152
|
+
source_location_id: z.string().uuid().nullable().optional(),
|
|
153
|
+
target_location_id: z.string().uuid().nullable().optional(),
|
|
154
|
+
catalog_variant_id: z.string().uuid().nullable().optional(),
|
|
155
|
+
lot_id: z.string().uuid().nullable().optional(),
|
|
156
|
+
serial_number: z.string().nullable().optional(),
|
|
157
|
+
quantity: z.union([z.string(), z.number()]).nullable().optional(),
|
|
158
|
+
status: z.string().nullable().optional(),
|
|
159
|
+
assigned_to: z.string().uuid().nullable().optional(),
|
|
160
|
+
priority: z.union([z.string(), z.number()]).nullable().optional(),
|
|
161
|
+
created_at: z.string().nullable().optional(),
|
|
162
|
+
updated_at: z.string().nullable().optional()
|
|
163
|
+
});
|
|
164
|
+
const openApi = createWmsCrudOpenApi({
|
|
165
|
+
resourceName: "PutawayTask",
|
|
166
|
+
pluralName: "Putaway tasks",
|
|
167
|
+
querySchema: listSchema,
|
|
168
|
+
listResponseSchema: createPagedListResponseSchema(putawayTaskListItemSchema),
|
|
169
|
+
create: {
|
|
170
|
+
schema: putawayTaskCreateSchema,
|
|
171
|
+
description: "Creates an open putaway task after verifying available staging balance (on-hand minus reserved/allocated minus open/in-progress putaway commitments). Target location may be null until completion. Assignee changes use POST .../assign."
|
|
172
|
+
},
|
|
173
|
+
update: {
|
|
174
|
+
schema: putawayTaskUpdateSchema,
|
|
175
|
+
responseSchema: defaultOkResponseSchema,
|
|
176
|
+
description: "Updates putaway task fields (locations, quantity, priority, metadata). Status and assignedTo are lifecycle-only \u2014 use POST .../{assign,start,complete,cancel}."
|
|
177
|
+
},
|
|
178
|
+
del: {
|
|
179
|
+
schema: z.object({ id: z.string().uuid() }),
|
|
180
|
+
responseSchema: defaultOkResponseSchema,
|
|
181
|
+
description: "Soft-deletes a putaway task by id."
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
export {
|
|
185
|
+
DELETE,
|
|
186
|
+
GET,
|
|
187
|
+
POST,
|
|
188
|
+
PUT,
|
|
189
|
+
metadata,
|
|
190
|
+
openApi
|
|
191
|
+
};
|
|
192
|
+
//# sourceMappingURL=route.js.map
|