@burdenoff/microfe-movethewheels 2026.930.5 → 2026.1010.1
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/dist/MoveTheWheelsRoot.js +177 -102
- package/dist/MoveTheWheelsRoutes.js +55 -11
- package/dist/_virtual/_rolldown/runtime.js +1 -1
- package/dist/components/ContainerEvidencePicker.js +143 -0
- package/dist/components/FreeTimeAgreementForm.js +496 -0
- package/dist/components/ReturnInstructionForm.js +108 -0
- package/dist/components/ReuseControls.js +91 -0
- package/dist/components/ReusePermissionForm.js +114 -0
- package/dist/components/ReuseProposalForm.js +455 -0
- package/dist/components/ReuseSourceFields.js +78 -0
- package/dist/components/consolidation/ConsolidationHistory.js +244 -0
- package/dist/components/consolidation/ConsolidationLotEditor.js +133 -0
- package/dist/components/consolidation/ConsolidationManifestWorkbench.js +143 -0
- package/dist/components/consolidation/ConsolidationPlanForm.js +172 -0
- package/dist/components/consolidation/ConsolidationPlanWorkbench.js +321 -0
- package/dist/components/consolidation/ConsolidationReportForm.js +94 -0
- package/dist/components/consolidation/ConsolidationReportsWorkbench.js +195 -0
- package/dist/components/consolidation/ConsolidationSummary.js +76 -0
- package/dist/components/consolidation/OriginalConsolidationHistory.js +112 -0
- package/dist/components/freight-cost/FreightDraftForm.js +213 -0
- package/dist/components/freight-cost/FreightFields.js +70 -0
- package/dist/components/freight-cost/FreightFxEditor.js +90 -0
- package/dist/components/freight-cost/FreightHistory.js +164 -0
- package/dist/components/freight-cost/FreightLineEditor.js +191 -0
- package/dist/components/freight-cost/FreightScopeEditor.js +72 -0
- package/dist/components/freight-cost/FreightTotals.js +66 -0
- package/dist/components/logistics-procedure/ProcedureDecisionForm.js +197 -0
- package/dist/components/logistics-procedure/ProcedureFields.js +31 -0
- package/dist/components/logistics-procedure/ProcedureHistory.js +177 -0
- package/dist/components/logistics-procedure/ProcedurePolicyForm.js +227 -0
- package/dist/components/logistics-procedure/ProcedurePolicyWorkbench.js +155 -0
- package/dist/components/logistics-procedure/ProcedureReviewWorkbench.js +221 -0
- package/dist/components/logistics-procedure/ProcedureRunWorkbench.js +190 -0
- package/dist/components/logistics-procedure/ProcedureSubjectPicker.js +130 -0
- package/dist/components/pending-pick/PendingPickDraft.js +84 -0
- package/dist/components/pending-pick/PendingPickHistory.js +113 -0
- package/dist/components/pending-pick/PickCapture.js +166 -0
- package/dist/components/pending-pick/PickLineSelection.js +111 -0
- package/dist/components/stock-binding/StockAssessmentDraft.js +48 -0
- package/dist/components/stock-binding/StockAssessmentHistory.js +61 -0
- package/dist/components/stock-binding/StockAssessmentSummary.js +199 -0
- package/dist/components/stock-binding/StockFactForm.js +232 -0
- package/dist/components/stock-observation/StockIssueForm.js +148 -0
- package/dist/components/stock-observation/StockIssueHistory.js +116 -0
- package/dist/components/stock-observation/StockIssueReadPanel.js +70 -0
- package/dist/components/trip-utilization/TripReportForm.js +118 -0
- package/dist/components/trip-utilization/TripReportHistory.js +54 -0
- package/dist/components/trip-utilization/TripReportSummary.js +216 -0
- package/dist/components/trip-utilization/TripSegmentFields.js +166 -0
- package/dist/generated/consolidation-operations.d.ts +1060 -0
- package/dist/generated/container-condition-operations.d.ts +868 -0
- package/dist/generated/container-operations.d.ts +356 -0
- package/dist/generated/empty-reuse-operations.d.ts +1578 -0
- package/dist/generated/free-time-operations.d.ts +938 -0
- package/dist/generated/freight-cost-operations.d.ts +716 -0
- package/dist/generated/logistics-procedure-operations.d.ts +938 -0
- package/dist/generated/pending-pick-operations.d.ts +1969 -0
- package/dist/generated/stock-binding-operations.d.ts +930 -0
- package/dist/generated/stock-observation-operations.d.ts +476 -0
- package/dist/generated/trip-utilization-operations.d.ts +651 -0
- package/dist/generated/wspace-operations.d.ts +143 -50
- package/dist/hooks/useConsolidationAction.js +119 -0
- package/dist/hooks/useContainerCondition.js +105 -0
- package/dist/hooks/useContainerLifecycle.js +192 -0
- package/dist/hooks/useEmptyReuseAction.js +45 -0
- package/dist/hooks/useFreightRecoveryAction.js +117 -0
- package/dist/hooks/useProcedureAction.js +119 -0
- package/dist/hooks/useProcedureSelection.js +53 -0
- package/dist/hooks/useReuseRecoveryAction.js +116 -0
- package/dist/movethewheels/components/ContainerEvidencePicker.d.ts +10 -0
- package/dist/movethewheels/components/FreeTimeAgreementForm.d.ts +14 -0
- package/dist/movethewheels/components/ReturnInstructionForm.d.ts +8 -0
- package/dist/movethewheels/components/ReuseControls.d.ts +42 -0
- package/dist/movethewheels/components/ReusePermissionForm.d.ts +9 -0
- package/dist/movethewheels/components/ReuseProposalForm.d.ts +11 -0
- package/dist/movethewheels/components/ReuseSourceFields.d.ts +9 -0
- package/dist/movethewheels/components/consolidation/ConsolidationHistory.d.ts +13 -0
- package/dist/movethewheels/components/consolidation/ConsolidationLotEditor.d.ts +6 -0
- package/dist/movethewheels/components/consolidation/ConsolidationManifestWorkbench.d.ts +8 -0
- package/dist/movethewheels/components/consolidation/ConsolidationPlanForm.d.ts +8 -0
- package/dist/movethewheels/components/consolidation/ConsolidationPlanWorkbench.d.ts +5 -0
- package/dist/movethewheels/components/consolidation/ConsolidationReportForm.d.ts +9 -0
- package/dist/movethewheels/components/consolidation/ConsolidationReportsWorkbench.d.ts +7 -0
- package/dist/movethewheels/components/consolidation/ConsolidationSummary.d.ts +6 -0
- package/dist/movethewheels/components/consolidation/OriginalConsolidationHistory.d.ts +8 -0
- package/dist/movethewheels/components/freight-cost/FreightDraftForm.d.ts +8 -0
- package/dist/movethewheels/components/freight-cost/FreightFields.d.ts +23 -0
- package/dist/movethewheels/components/freight-cost/FreightFxEditor.d.ts +6 -0
- package/dist/movethewheels/components/freight-cost/FreightHistory.d.ts +5 -0
- package/dist/movethewheels/components/freight-cost/FreightLineEditor.d.ts +8 -0
- package/dist/movethewheels/components/freight-cost/FreightScopeEditor.d.ts +6 -0
- package/dist/movethewheels/components/freight-cost/FreightTotals.d.ts +6 -0
- package/dist/movethewheels/components/logistics-procedure/ProcedureDecisionForm.d.ts +20 -0
- package/dist/movethewheels/components/logistics-procedure/ProcedureFields.d.ts +17 -0
- package/dist/movethewheels/components/logistics-procedure/ProcedureHistory.d.ts +7 -0
- package/dist/movethewheels/components/logistics-procedure/ProcedurePolicyForm.d.ts +10 -0
- package/dist/movethewheels/components/logistics-procedure/ProcedurePolicyWorkbench.d.ts +5 -0
- package/dist/movethewheels/components/logistics-procedure/ProcedureReviewWorkbench.d.ts +5 -0
- package/dist/movethewheels/components/logistics-procedure/ProcedureRunWorkbench.d.ts +6 -0
- package/dist/movethewheels/components/logistics-procedure/ProcedureSubjectPicker.d.ts +7 -0
- package/dist/movethewheels/components/pending-pick/PendingPickDraft.d.ts +16 -0
- package/dist/movethewheels/components/pending-pick/PendingPickHistory.d.ts +5 -0
- package/dist/movethewheels/components/pending-pick/PickCapture.d.ts +6 -0
- package/dist/movethewheels/components/pending-pick/PickLineSelection.d.ts +17 -0
- package/dist/movethewheels/components/stock-binding/StockAssessmentDraft.d.ts +13 -0
- package/dist/movethewheels/components/stock-binding/StockAssessmentHistory.d.ts +18 -0
- package/dist/movethewheels/components/stock-binding/StockAssessmentSummary.d.ts +9 -0
- package/dist/movethewheels/components/stock-binding/StockFactForm.d.ts +6 -0
- package/dist/movethewheels/components/stock-observation/StockIssueForm.d.ts +7 -0
- package/dist/movethewheels/components/stock-observation/StockIssueHistory.d.ts +7 -0
- package/dist/movethewheels/components/stock-observation/StockIssueReadPanel.d.ts +5 -0
- package/dist/movethewheels/components/trip-utilization/TripReportForm.d.ts +6 -0
- package/dist/movethewheels/components/trip-utilization/TripReportHistory.d.ts +14 -0
- package/dist/movethewheels/components/trip-utilization/TripReportSummary.d.ts +5 -0
- package/dist/movethewheels/components/trip-utilization/TripSegmentFields.d.ts +9 -0
- package/dist/movethewheels/hooks/useConsolidationAction.d.ts +19 -0
- package/dist/movethewheels/hooks/useContainerCondition.d.ts +21 -0
- package/dist/movethewheels/hooks/useContainerLifecycle.d.ts +40 -0
- package/dist/movethewheels/hooks/useEmptyReuseAction.d.ts +14 -0
- package/dist/movethewheels/hooks/useFreightRecoveryAction.d.ts +23 -0
- package/dist/movethewheels/hooks/useProcedureAction.d.ts +18 -0
- package/dist/movethewheels/hooks/useProcedureSelection.d.ts +51 -0
- package/dist/movethewheels/hooks/useReuseRecoveryAction.d.ts +18 -0
- package/dist/movethewheels/pages/ConsolidationPage.d.ts +1 -0
- package/dist/movethewheels/pages/ContainerConditionPage.d.ts +1 -0
- package/dist/movethewheels/pages/ContainersPage.d.ts +2 -0
- package/dist/movethewheels/pages/EmptyReusePage.d.ts +1 -0
- package/dist/movethewheels/pages/FreeTimePage.d.ts +1 -0
- package/dist/movethewheels/pages/FreightEstimatePage.d.ts +1 -0
- package/dist/movethewheels/pages/LogisticsProceduresPage.d.ts +1 -0
- package/dist/movethewheels/pages/PendingPickPage.d.ts +1 -0
- package/dist/movethewheels/pages/StockBindingPage.d.ts +1 -0
- package/dist/movethewheels/pages/StockObservationsPage.d.ts +1 -0
- package/dist/movethewheels/pages/TripUtilizationPage.d.ts +1 -0
- package/dist/movethewheels/utils/consolidationHistoryTarget.d.ts +12 -0
- package/dist/movethewheels/utils/consolidationInput.d.ts +15 -0
- package/dist/movethewheels/utils/consolidationLot.d.ts +3 -0
- package/dist/movethewheels/utils/consolidationPins.d.ts +20 -0
- package/dist/movethewheels/utils/consolidationRecovery.d.ts +5 -0
- package/dist/movethewheels/utils/consolidationReportHead.d.ts +5 -0
- package/dist/movethewheels/utils/freeTimeDate.d.ts +1 -0
- package/dist/movethewheels/utils/freightAcknowledgement.d.ts +2 -0
- package/dist/movethewheels/utils/freightDraft.d.ts +36 -0
- package/dist/movethewheels/utils/freightRecovery.d.ts +5 -0
- package/dist/movethewheels/utils/graphqlClient.d.ts +2 -1
- package/dist/movethewheels/utils/pendingPickDraft.d.ts +8 -0
- package/dist/movethewheels/utils/procedureInput.d.ts +18 -0
- package/dist/movethewheels/utils/procedureRecovery.d.ts +5 -0
- package/dist/movethewheels/utils/reuseAttempt.d.ts +7 -0
- package/dist/movethewheels/utils/reuseForm.d.ts +6 -0
- package/dist/movethewheels/utils/reuseRecovery.d.ts +26 -0
- package/dist/movethewheels/utils/stockBindingForm.d.ts +23 -0
- package/dist/movethewheels/utils/stockBindingLabels.d.ts +10 -0
- package/dist/movethewheels/utils/stockObservationForm.d.ts +5 -0
- package/dist/movethewheels/utils/tripDraftContext.d.ts +25 -0
- package/dist/movethewheels/utils/tripUtilizationForm.d.ts +6 -0
- package/dist/node_modules/@react-leaflet/core/lib/component.js +5 -5
- package/dist/node_modules/fast-equals/dist/es/index.js +87 -74
- package/dist/node_modules/leaflet/dist/leaflet-src.js +8 -5
- package/dist/node_modules/lodash/_Stack.js +2 -1
- package/dist/node_modules/lucide-react/dist/esm/icons/clipboard-list.js +35 -0
- package/dist/node_modules/lucide-react/dist/esm/icons/repeat-2.js +22 -0
- package/dist/node_modules/react-leaflet/lib/MapContainer.js +3 -3
- package/dist/node_modules/react-smooth/es6/Animate.js +2 -2
- package/dist/node_modules/recharts/es6/cartesian/Area.js +13 -13
- package/dist/node_modules/recharts/es6/cartesian/Bar.js +9 -9
- package/dist/node_modules/recharts/es6/cartesian/Brush.js +12 -12
- package/dist/node_modules/recharts/es6/cartesian/CartesianAxis.js +7 -7
- package/dist/node_modules/recharts/es6/cartesian/CartesianGrid.js +13 -13
- package/dist/node_modules/recharts/es6/cartesian/ErrorBar.js +4 -4
- package/dist/node_modules/recharts/es6/cartesian/Line.js +10 -10
- package/dist/node_modules/recharts/es6/cartesian/ReferenceArea.js +3 -3
- package/dist/node_modules/recharts/es6/cartesian/ReferenceDot.js +3 -3
- package/dist/node_modules/recharts/es6/cartesian/ReferenceLine.js +4 -4
- package/dist/node_modules/recharts/es6/cartesian/XAxis.js +3 -3
- package/dist/node_modules/recharts/es6/cartesian/YAxis.js +3 -3
- package/dist/node_modules/recharts/es6/chart/AccessibilityManager.js +1 -1
- package/dist/node_modules/recharts/es6/chart/generateCategoricalChart.js +22 -22
- package/dist/node_modules/recharts/es6/component/Cursor.js +1 -1
- package/dist/node_modules/recharts/es6/component/DefaultLegendContent.js +11 -11
- package/dist/node_modules/recharts/es6/component/DefaultTooltipContent.js +6 -6
- package/dist/node_modules/recharts/es6/component/Label.js +14 -14
- package/dist/node_modules/recharts/es6/component/LabelList.js +6 -6
- package/dist/node_modules/recharts/es6/component/Legend.js +5 -5
- package/dist/node_modules/recharts/es6/component/ResponsiveContainer.js +3 -3
- package/dist/node_modules/recharts/es6/component/Text.js +2 -2
- package/dist/node_modules/recharts/es6/component/Tooltip.js +3 -3
- package/dist/node_modules/recharts/es6/component/TooltipBoundingBox.js +2 -2
- package/dist/node_modules/recharts/es6/container/Layer.js +2 -2
- package/dist/node_modules/recharts/es6/container/Surface.js +2 -2
- package/dist/node_modules/recharts/es6/context/chartLayoutContext.js +2 -2
- package/dist/node_modules/recharts/es6/polar/Pie.js +13 -13
- package/dist/node_modules/recharts/es6/polar/PolarAngleAxis.js +8 -8
- package/dist/node_modules/recharts/es6/polar/PolarRadiusAxis.js +6 -6
- package/dist/node_modules/recharts/es6/shape/Cross.js +1 -1
- package/dist/node_modules/recharts/es6/shape/Curve.js +1 -1
- package/dist/node_modules/recharts/es6/shape/Dot.js +1 -1
- package/dist/node_modules/recharts/es6/shape/Polygon.js +4 -4
- package/dist/node_modules/recharts/es6/shape/Rectangle.js +4 -4
- package/dist/node_modules/recharts/es6/shape/Sector.js +1 -1
- package/dist/node_modules/recharts/es6/shape/Symbols.js +1 -1
- package/dist/node_modules/recharts/es6/shape/Trapezoid.js +4 -4
- package/dist/node_modules/recharts/es6/util/ActiveShapeUtils.js +9 -9
- package/dist/node_modules/recharts/es6/util/BarUtils.js +1 -1
- package/dist/node_modules/recharts/es6/util/CartesianUtils.js +1 -1
- package/dist/node_modules/recharts/es6/util/PolarUtils.js +1 -1
- package/dist/node_modules/recharts/es6/util/ReactUtils.js +2 -2
- package/dist/node_modules/recharts/es6/util/ReduceCSSCalc.js +1 -1
- package/dist/node_modules/recharts/es6/util/types.js +1 -1
- package/dist/node_modules/{react-is → recharts/node_modules/react-is}/cjs/react-is.development.js +2 -2
- package/dist/node_modules/{react-is → recharts/node_modules/react-is}/cjs/react-is.production.min.js +2 -2
- package/dist/node_modules/{react-is → recharts/node_modules/react-is}/index.js +2 -2
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +97 -18
- package/dist/node_modules/zustand/esm/middleware.js +2 -2
- package/dist/pages/ConsolidationPage.js +76 -0
- package/dist/pages/ContainerConditionPage.js +972 -0
- package/dist/pages/ContainersPage.js +522 -0
- package/dist/pages/EmptyReusePage.js +777 -0
- package/dist/pages/FreeTimePage.js +657 -0
- package/dist/pages/FreightEstimatePage.js +284 -0
- package/dist/pages/LogisticsProceduresPage.js +100 -0
- package/dist/pages/PendingPickPage.js +155 -0
- package/dist/pages/StockBindingPage.js +236 -0
- package/dist/pages/StockObservationsPage.js +168 -0
- package/dist/pages/TripUtilizationPage.js +227 -0
- package/dist/src/generated/consolidation-operations.js +505 -0
- package/dist/src/generated/container-condition-operations.js +208 -0
- package/dist/src/generated/container-operations.js +101 -0
- package/dist/src/generated/empty-reuse-operations.js +749 -0
- package/dist/src/generated/free-time-operations.js +235 -0
- package/dist/src/generated/freight-cost-operations.js +325 -0
- package/dist/src/generated/logistics-procedure-operations.js +362 -0
- package/dist/src/generated/pending-pick-operations.js +1128 -0
- package/dist/src/generated/stock-binding-operations.js +175 -0
- package/dist/src/generated/stock-observation-operations.js +93 -0
- package/dist/src/generated/trip-utilization-operations.js +140 -0
- package/dist/src/generated/wspace-operations.js +708 -0
- package/dist/utils/consolidationHistoryTarget.js +27 -0
- package/dist/utils/consolidationInput.js +21 -0
- package/dist/utils/consolidationLot.js +29 -0
- package/dist/utils/consolidationPins.js +13 -0
- package/dist/utils/consolidationRecovery.js +40 -0
- package/dist/utils/consolidationReportHead.js +18 -0
- package/dist/utils/freeTimeDate.js +26 -0
- package/dist/utils/freightAcknowledgement.js +8 -0
- package/dist/utils/freightDraft.js +125 -0
- package/dist/utils/freightRecovery.js +36 -0
- package/dist/utils/graphqlClient.js +28 -28
- package/dist/utils/pendingPickDraft.js +46 -0
- package/dist/utils/procedureInput.js +43 -0
- package/dist/utils/procedureRecovery.js +42 -0
- package/dist/utils/reuseAttempt.js +20 -0
- package/dist/utils/reuseForm.js +25 -0
- package/dist/utils/reuseRecovery.js +71 -0
- package/dist/utils/stockBindingForm.js +142 -0
- package/dist/utils/stockBindingLabels.js +23 -0
- package/dist/utils/stockObservationForm.js +55 -0
- package/dist/utils/tripDraftContext.js +19 -0
- package/dist/utils/tripUtilizationForm.js +60 -0
- package/package.json +19 -5
- package/src/generated/consolidation-operations.ts +1138 -0
- package/src/generated/container-condition-operations.ts +771 -0
- package/src/generated/container-operations.ts +376 -0
- package/src/generated/empty-reuse-operations.ts +1648 -0
- package/src/generated/free-time-operations.ts +814 -0
- package/src/generated/freight-cost-operations.ts +753 -0
- package/src/generated/logistics-procedure-operations.ts +1047 -0
- package/src/generated/pending-pick-operations.ts +1508 -0
- package/src/generated/stock-binding-operations.ts +631 -0
- package/src/generated/stock-observation-operations.ts +373 -0
- package/src/generated/trip-utilization-operations.ts +500 -0
- package/src/generated/wspace-operations.ts +116 -0
- package/src/movethewheels/MoveTheWheelsRoot.tsx +79 -0
- package/src/movethewheels/MoveTheWheelsRoutes.tsx +22 -0
- package/src/movethewheels/components/ContainerEvidencePicker.tsx +146 -0
- package/src/movethewheels/components/FreeTimeAgreementForm.tsx +483 -0
- package/src/movethewheels/components/ReturnInstructionForm.tsx +102 -0
- package/src/movethewheels/components/ReuseControls.tsx +138 -0
- package/src/movethewheels/components/ReusePermissionForm.tsx +123 -0
- package/src/movethewheels/components/ReuseProposalForm.tsx +484 -0
- package/src/movethewheels/components/ReuseSourceFields.tsx +80 -0
- package/src/movethewheels/components/consolidation/ConsolidationHistory.tsx +159 -0
- package/src/movethewheels/components/consolidation/ConsolidationLotEditor.tsx +144 -0
- package/src/movethewheels/components/consolidation/ConsolidationManifestWorkbench.tsx +168 -0
- package/src/movethewheels/components/consolidation/ConsolidationPlanForm.tsx +185 -0
- package/src/movethewheels/components/consolidation/ConsolidationPlanWorkbench.tsx +395 -0
- package/src/movethewheels/components/consolidation/ConsolidationReportForm.tsx +124 -0
- package/src/movethewheels/components/consolidation/ConsolidationReportsWorkbench.tsx +233 -0
- package/src/movethewheels/components/consolidation/ConsolidationSummary.tsx +84 -0
- package/src/movethewheels/components/consolidation/OriginalConsolidationHistory.tsx +133 -0
- package/src/movethewheels/components/freight-cost/FreightDraftForm.tsx +224 -0
- package/src/movethewheels/components/freight-cost/FreightFields.tsx +91 -0
- package/src/movethewheels/components/freight-cost/FreightFxEditor.tsx +98 -0
- package/src/movethewheels/components/freight-cost/FreightHistory.tsx +91 -0
- package/src/movethewheels/components/freight-cost/FreightLineEditor.tsx +192 -0
- package/src/movethewheels/components/freight-cost/FreightScopeEditor.tsx +64 -0
- package/src/movethewheels/components/freight-cost/FreightTotals.tsx +68 -0
- package/src/movethewheels/components/logistics-procedure/ProcedureDecisionForm.tsx +204 -0
- package/src/movethewheels/components/logistics-procedure/ProcedureFields.tsx +43 -0
- package/src/movethewheels/components/logistics-procedure/ProcedureHistory.tsx +102 -0
- package/src/movethewheels/components/logistics-procedure/ProcedurePolicyForm.tsx +226 -0
- package/src/movethewheels/components/logistics-procedure/ProcedurePolicyWorkbench.tsx +174 -0
- package/src/movethewheels/components/logistics-procedure/ProcedureReviewWorkbench.tsx +278 -0
- package/src/movethewheels/components/logistics-procedure/ProcedureRunWorkbench.tsx +292 -0
- package/src/movethewheels/components/logistics-procedure/ProcedureSubjectPicker.tsx +111 -0
- package/src/movethewheels/components/pending-pick/PendingPickDraft.tsx +82 -0
- package/src/movethewheels/components/pending-pick/PendingPickHistory.tsx +93 -0
- package/src/movethewheels/components/pending-pick/PickCapture.tsx +70 -0
- package/src/movethewheels/components/pending-pick/PickLineSelection.tsx +130 -0
- package/src/movethewheels/components/stock-binding/StockAssessmentDraft.tsx +52 -0
- package/src/movethewheels/components/stock-binding/StockAssessmentHistory.tsx +56 -0
- package/src/movethewheels/components/stock-binding/StockAssessmentSummary.tsx +108 -0
- package/src/movethewheels/components/stock-binding/StockFactForm.tsx +186 -0
- package/src/movethewheels/components/stock-observation/StockIssueForm.tsx +103 -0
- package/src/movethewheels/components/stock-observation/StockIssueHistory.tsx +96 -0
- package/src/movethewheels/components/stock-observation/StockIssueReadPanel.tsx +72 -0
- package/src/movethewheels/components/trip-utilization/TripReportForm.tsx +116 -0
- package/src/movethewheels/components/trip-utilization/TripReportHistory.tsx +51 -0
- package/src/movethewheels/components/trip-utilization/TripReportSummary.tsx +127 -0
- package/src/movethewheels/components/trip-utilization/TripSegmentFields.tsx +118 -0
- package/src/movethewheels/hooks/useConsolidationAction.ts +196 -0
- package/src/movethewheels/hooks/useContainerCondition.ts +129 -0
- package/src/movethewheels/hooks/useContainerLifecycle.ts +291 -0
- package/src/movethewheels/hooks/useEmptyReuseAction.ts +72 -0
- package/src/movethewheels/hooks/useFreightRecoveryAction.ts +201 -0
- package/src/movethewheels/hooks/useProcedureAction.ts +196 -0
- package/src/movethewheels/hooks/useProcedureSelection.ts +75 -0
- package/src/movethewheels/hooks/useReuseRecoveryAction.ts +192 -0
- package/src/movethewheels/pages/ConsolidationPage.tsx +70 -0
- package/src/movethewheels/pages/ContainerConditionPage.tsx +959 -0
- package/src/movethewheels/pages/ContainersPage.tsx +490 -0
- package/src/movethewheels/pages/EmptyReusePage.tsx +823 -0
- package/src/movethewheels/pages/FreeTimePage.tsx +720 -0
- package/src/movethewheels/pages/FreightEstimatePage.tsx +353 -0
- package/src/movethewheels/pages/LogisticsProceduresPage.tsx +86 -0
- package/src/movethewheels/pages/PendingPickPage.tsx +226 -0
- package/src/movethewheels/pages/StockBindingPage.tsx +299 -0
- package/src/movethewheels/pages/StockObservationsPage.tsx +181 -0
- package/src/movethewheels/pages/TripUtilizationPage.tsx +315 -0
- package/src/movethewheels/utils/consolidationHistoryTarget.ts +39 -0
- package/src/movethewheels/utils/consolidationInput.ts +70 -0
- package/src/movethewheels/utils/consolidationLot.ts +24 -0
- package/src/movethewheels/utils/consolidationPins.ts +52 -0
- package/src/movethewheels/utils/consolidationRecovery.ts +88 -0
- package/src/movethewheels/utils/consolidationReportHead.ts +29 -0
- package/src/movethewheels/utils/freeTimeDate.ts +31 -0
- package/src/movethewheels/utils/freightAcknowledgement.ts +31 -0
- package/src/movethewheels/utils/freightDraft.ts +170 -0
- package/src/movethewheels/utils/freightRecovery.ts +79 -0
- package/src/movethewheels/utils/graphqlClient.ts +14 -5
- package/src/movethewheels/utils/pendingPickDraft.ts +61 -0
- package/src/movethewheels/utils/procedureInput.ts +98 -0
- package/src/movethewheels/utils/procedureRecovery.ts +92 -0
- package/src/movethewheels/utils/reuseAttempt.ts +29 -0
- package/src/movethewheels/utils/reuseForm.ts +30 -0
- package/src/movethewheels/utils/reuseRecovery.ts +151 -0
- package/src/movethewheels/utils/stockBindingForm.ts +209 -0
- package/src/movethewheels/utils/stockBindingLabels.ts +41 -0
- package/src/movethewheels/utils/stockObservationForm.ts +73 -0
- package/src/movethewheels/utils/tripDraftContext.ts +61 -0
- package/src/movethewheels/utils/tripUtilizationForm.ts +105 -0
- package/src/operations/condition/container-condition.graphql +41 -0
- package/src/operations/consolidation/consolidation.graphql +490 -0
- package/src/operations/container/container-lifecycle.graphql +80 -0
- package/src/operations/empty-reuse/empty-reuse.graphql +737 -0
- package/src/operations/free-time/free-time.graphql +47 -0
- package/src/operations/freight-cost/freight.graphql +6 -0
- package/src/operations/logistics-procedure/procedure.graphql +15 -0
- package/src/operations/pending-pick/pending-pick.graphql +1122 -0
- package/src/operations/stock-binding/stock-binding.graphql +160 -0
- package/src/operations/stock-observation/stock-observation.graphql +20 -0
- package/src/operations/trip-utilization/trip-utilization.graphql +126 -0
- package/src/operations/wspace/container-evidence.graphql +6 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { Kind, parse, print, type DocumentNode } from 'graphql';
|
|
2
|
+
import { resolveGraphqlUrl } from './graphqlClient';
|
|
3
|
+
|
|
4
|
+
export const REUSE_RECOVERY_STORAGE = 'movethewheels.empty-reuse.unresolved.v1';
|
|
5
|
+
const MAX_BYTES = 200_000;
|
|
6
|
+
const operations = new Set([
|
|
7
|
+
'RecordReturnInstruction',
|
|
8
|
+
'RecordReuseProposal',
|
|
9
|
+
'RecordReuseApproval',
|
|
10
|
+
'AcceptReuseReservation',
|
|
11
|
+
'TerminateReuseReservation',
|
|
12
|
+
]);
|
|
13
|
+
export interface ReuseRecoveryScope {
|
|
14
|
+
actorId: string;
|
|
15
|
+
workspaceId: string;
|
|
16
|
+
tenantId: string;
|
|
17
|
+
organizationId: string;
|
|
18
|
+
gateway: string;
|
|
19
|
+
projectId: string | null;
|
|
20
|
+
}
|
|
21
|
+
export interface ReuseRecovery {
|
|
22
|
+
version: 1;
|
|
23
|
+
scope: ReuseRecoveryScope;
|
|
24
|
+
operation: string;
|
|
25
|
+
input: Record<string, unknown>;
|
|
26
|
+
key: string;
|
|
27
|
+
success: string;
|
|
28
|
+
}
|
|
29
|
+
function object(value: unknown): value is Record<string, unknown> {
|
|
30
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
31
|
+
}
|
|
32
|
+
/** Claims are context comparison metadata only; the gateway remains the authentication authority. */
|
|
33
|
+
export function reuseRecoveryScope(
|
|
34
|
+
actorId: string | undefined,
|
|
35
|
+
workspaceId: string | undefined,
|
|
36
|
+
tenantId: string | undefined,
|
|
37
|
+
gateway: string | undefined,
|
|
38
|
+
workspaceToken: string | undefined
|
|
39
|
+
): ReuseRecoveryScope | null {
|
|
40
|
+
if (!actorId || !workspaceId || !workspaceToken) return null;
|
|
41
|
+
try {
|
|
42
|
+
const encoded = workspaceToken.split('.')[1];
|
|
43
|
+
const claims: unknown = JSON.parse(atob(encoded.replace(/-/g, '+').replace(/_/g, '/')));
|
|
44
|
+
if (
|
|
45
|
+
!object(claims) ||
|
|
46
|
+
claims.sub !== actorId ||
|
|
47
|
+
claims.workspaceId !== workspaceId ||
|
|
48
|
+
typeof claims.organizationId !== 'string' ||
|
|
49
|
+
!claims.organizationId ||
|
|
50
|
+
!Object.hasOwn(claims, 'projectId')
|
|
51
|
+
)
|
|
52
|
+
return null;
|
|
53
|
+
const project = claims.projectId;
|
|
54
|
+
if (project !== null && project !== undefined && typeof project !== 'string') return null;
|
|
55
|
+
return {
|
|
56
|
+
actorId,
|
|
57
|
+
workspaceId,
|
|
58
|
+
tenantId: tenantId ?? '',
|
|
59
|
+
organizationId: claims.organizationId,
|
|
60
|
+
gateway: resolveGraphqlUrl(gateway),
|
|
61
|
+
projectId: project ?? null,
|
|
62
|
+
};
|
|
63
|
+
} catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** Stable across token renewal; changing an owner/project context resets unsent forms. */
|
|
68
|
+
export function reuseRecoveryContextKey(scope: ReuseRecoveryScope | null): string {
|
|
69
|
+
return JSON.stringify(scope);
|
|
70
|
+
}
|
|
71
|
+
export function sameReuseRecoveryScope(
|
|
72
|
+
a: ReuseRecoveryScope,
|
|
73
|
+
b: ReuseRecoveryScope | null
|
|
74
|
+
): boolean {
|
|
75
|
+
return (
|
|
76
|
+
b !== null &&
|
|
77
|
+
a.actorId === b.actorId &&
|
|
78
|
+
a.workspaceId === b.workspaceId &&
|
|
79
|
+
a.tenantId === b.tenantId &&
|
|
80
|
+
a.organizationId === b.organizationId &&
|
|
81
|
+
a.gateway === b.gateway &&
|
|
82
|
+
a.projectId === b.projectId
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
export function decodeReuseRecovery(
|
|
86
|
+
raw: string | null,
|
|
87
|
+
documents: readonly DocumentNode[]
|
|
88
|
+
): ReuseRecovery | null {
|
|
89
|
+
if (!raw || new TextEncoder().encode(raw).byteLength > MAX_BYTES) return null;
|
|
90
|
+
try {
|
|
91
|
+
const value: unknown = JSON.parse(raw);
|
|
92
|
+
if (!object(value) || value.version !== 1 || !object(value.scope) || !object(value.input))
|
|
93
|
+
return null;
|
|
94
|
+
const scope = value.scope;
|
|
95
|
+
if (
|
|
96
|
+
typeof scope.actorId !== 'string' ||
|
|
97
|
+
typeof scope.workspaceId !== 'string' ||
|
|
98
|
+
typeof scope.tenantId !== 'string' ||
|
|
99
|
+
typeof scope.organizationId !== 'string' ||
|
|
100
|
+
typeof scope.gateway !== 'string' ||
|
|
101
|
+
!scope.actorId ||
|
|
102
|
+
!scope.workspaceId ||
|
|
103
|
+
(scope.projectId !== null && typeof scope.projectId !== 'string')
|
|
104
|
+
)
|
|
105
|
+
return null;
|
|
106
|
+
if (typeof value.operation !== 'string' || !documents.some((d) => print(d) === value.operation))
|
|
107
|
+
return null;
|
|
108
|
+
const definitions = parse(value.operation).definitions;
|
|
109
|
+
const op = definitions.find((d) => d.kind === Kind.OPERATION_DEFINITION);
|
|
110
|
+
if (
|
|
111
|
+
!op ||
|
|
112
|
+
op.kind !== Kind.OPERATION_DEFINITION ||
|
|
113
|
+
op.operation !== 'mutation' ||
|
|
114
|
+
!op.name ||
|
|
115
|
+
!operations.has(op.name.value)
|
|
116
|
+
)
|
|
117
|
+
return null;
|
|
118
|
+
if (
|
|
119
|
+
typeof value.key !== 'string' ||
|
|
120
|
+
!value.key ||
|
|
121
|
+
value.key.length > 200 ||
|
|
122
|
+
typeof value.success !== 'string' ||
|
|
123
|
+
value.success.length > 500
|
|
124
|
+
)
|
|
125
|
+
return null;
|
|
126
|
+
// Storage is untrusted. Only the current owning operation document may be executed.
|
|
127
|
+
return {
|
|
128
|
+
version: 1,
|
|
129
|
+
scope: {
|
|
130
|
+
actorId: scope.actorId,
|
|
131
|
+
workspaceId: scope.workspaceId,
|
|
132
|
+
tenantId: scope.tenantId,
|
|
133
|
+
organizationId: scope.organizationId,
|
|
134
|
+
gateway: scope.gateway,
|
|
135
|
+
projectId: scope.projectId,
|
|
136
|
+
},
|
|
137
|
+
operation: value.operation,
|
|
138
|
+
input: value.input,
|
|
139
|
+
key: value.key,
|
|
140
|
+
success: value.success,
|
|
141
|
+
};
|
|
142
|
+
} catch {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
export function encodeReuseRecovery(value: ReuseRecovery): string {
|
|
147
|
+
const text = JSON.stringify(value);
|
|
148
|
+
if (new TextEncoder().encode(text).byteLength > MAX_BYTES)
|
|
149
|
+
throw new Error('This request is too large to retain safely.');
|
|
150
|
+
return text;
|
|
151
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
RecordMtwStockBindingAssessmentInput,
|
|
3
|
+
StockSourceContextFragment,
|
|
4
|
+
StockAssessmentFragment,
|
|
5
|
+
} from '../../generated/stock-binding-operations';
|
|
6
|
+
import { freeTimeIso } from './freeTimeDate';
|
|
7
|
+
import type { SelectedEvidence } from '../components/ContainerEvidencePicker';
|
|
8
|
+
|
|
9
|
+
export interface StockDraftPin {
|
|
10
|
+
inventoryItemId: string;
|
|
11
|
+
expectedCargoItemId: string;
|
|
12
|
+
expectedWarehouseId: string;
|
|
13
|
+
expectedLocationId: string | null;
|
|
14
|
+
expectedCompositionEpoch: number;
|
|
15
|
+
expectedInventoryUpdatedAt: string;
|
|
16
|
+
expectedCargoUpdatedAt: string;
|
|
17
|
+
expectedWarehouseUpdatedAt: string;
|
|
18
|
+
expectedLocationUpdatedAt: string | null;
|
|
19
|
+
expectedPreviousAssessmentId: string | null;
|
|
20
|
+
expectedVersion: number;
|
|
21
|
+
label: string;
|
|
22
|
+
}
|
|
23
|
+
export type StockFactDraft = Pick<
|
|
24
|
+
RecordMtwStockBindingAssessmentInput,
|
|
25
|
+
'effectiveAt' | 'facts' | 'evidence'
|
|
26
|
+
>;
|
|
27
|
+
export function stockContextLabel(row: StockSourceContextFragment): string {
|
|
28
|
+
return `${row.warehouse?.name ?? 'Warehouse unavailable'} (${row.warehouse?.code ?? 'unknown code'}) / ${row.cargoItem?.name ?? 'Cargo unavailable'} (${row.cargoItem?.sku ?? 'unknown SKU'}) / ${row.locationId === null ? 'Unbinned' : (row.location?.locationCode ?? 'Bin unavailable')}`;
|
|
29
|
+
}
|
|
30
|
+
export function stockDraftPin(
|
|
31
|
+
row: StockSourceContextFragment,
|
|
32
|
+
predecessor: StockAssessmentFragment | null
|
|
33
|
+
): StockDraftPin {
|
|
34
|
+
if (
|
|
35
|
+
!row.cargoItem ||
|
|
36
|
+
!row.warehouse ||
|
|
37
|
+
row.cargoItem.id !== row.cargoItemId ||
|
|
38
|
+
row.warehouse.id !== row.warehouseId ||
|
|
39
|
+
(row.locationId === null
|
|
40
|
+
? row.location != null
|
|
41
|
+
: !row.location ||
|
|
42
|
+
row.location.id !== row.locationId ||
|
|
43
|
+
row.location.warehouseId !== row.warehouseId)
|
|
44
|
+
)
|
|
45
|
+
throw new Error(
|
|
46
|
+
'This stock line is missing a current owner. Refresh and review it before recording.'
|
|
47
|
+
);
|
|
48
|
+
if (
|
|
49
|
+
!Number.isInteger(row.compositionEpoch) ||
|
|
50
|
+
row.compositionEpoch < 0 ||
|
|
51
|
+
row.compositionEpoch > 2147483647
|
|
52
|
+
)
|
|
53
|
+
throw new Error(
|
|
54
|
+
'The current continuity revision is unavailable. Refresh and review this stock line.'
|
|
55
|
+
);
|
|
56
|
+
if (predecessor && predecessor.inventoryItemId !== row.id)
|
|
57
|
+
throw new Error('The previous assessment belongs to another stock line.');
|
|
58
|
+
return {
|
|
59
|
+
inventoryItemId: row.id,
|
|
60
|
+
expectedCompositionEpoch: row.compositionEpoch,
|
|
61
|
+
expectedCargoItemId: row.cargoItemId,
|
|
62
|
+
expectedWarehouseId: row.warehouseId,
|
|
63
|
+
expectedLocationId: row.locationId ?? null,
|
|
64
|
+
expectedInventoryUpdatedAt: row.updatedAt,
|
|
65
|
+
expectedCargoUpdatedAt: row.cargoItem.updatedAt,
|
|
66
|
+
expectedWarehouseUpdatedAt: row.warehouse.updatedAt,
|
|
67
|
+
expectedLocationUpdatedAt: row.location?.updatedAt ?? null,
|
|
68
|
+
expectedPreviousAssessmentId: predecessor?.id ?? null,
|
|
69
|
+
expectedVersion: predecessor?.version ?? 0,
|
|
70
|
+
label: stockContextLabel(row),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
export function stockContextMatches(
|
|
74
|
+
pin: StockDraftPin,
|
|
75
|
+
row: StockSourceContextFragment | null | undefined,
|
|
76
|
+
predecessor: StockAssessmentFragment | null
|
|
77
|
+
): boolean {
|
|
78
|
+
if (!row) return false;
|
|
79
|
+
try {
|
|
80
|
+
const current = stockDraftPin(row, predecessor);
|
|
81
|
+
// current contains only the declared pin keys; UI-only generation metadata is excluded.
|
|
82
|
+
return Object.entries(current).every(
|
|
83
|
+
([name, value]) => name === 'label' || pin[name as keyof StockDraftPin] === value
|
|
84
|
+
);
|
|
85
|
+
} catch {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export function inputForStockDraft(
|
|
90
|
+
draft: StockFactDraft,
|
|
91
|
+
pin: StockDraftPin,
|
|
92
|
+
row: StockSourceContextFragment | null | undefined,
|
|
93
|
+
predecessor: StockAssessmentFragment | null
|
|
94
|
+
): Omit<RecordMtwStockBindingAssessmentInput, 'idempotencyKey'> {
|
|
95
|
+
if (!stockContextMatches(pin, row, predecessor))
|
|
96
|
+
throw new Error(
|
|
97
|
+
'This stock line or its recorded history changed. Refresh and review a new draft.'
|
|
98
|
+
);
|
|
99
|
+
return {
|
|
100
|
+
inventoryItemId: pin.inventoryItemId,
|
|
101
|
+
expectedCompositionEpoch: pin.expectedCompositionEpoch,
|
|
102
|
+
expectedCargoItemId: pin.expectedCargoItemId,
|
|
103
|
+
expectedWarehouseId: pin.expectedWarehouseId,
|
|
104
|
+
expectedLocationId: pin.expectedLocationId,
|
|
105
|
+
expectedInventoryUpdatedAt: pin.expectedInventoryUpdatedAt,
|
|
106
|
+
expectedCargoUpdatedAt: pin.expectedCargoUpdatedAt,
|
|
107
|
+
expectedWarehouseUpdatedAt: pin.expectedWarehouseUpdatedAt,
|
|
108
|
+
expectedLocationUpdatedAt: pin.expectedLocationUpdatedAt,
|
|
109
|
+
expectedPreviousAssessmentId: pin.expectedPreviousAssessmentId,
|
|
110
|
+
expectedVersion: pin.expectedVersion,
|
|
111
|
+
...draft,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function optionalText(data: FormData, name: string, max = 255): string | null {
|
|
115
|
+
const value = data.get(name);
|
|
116
|
+
if (value === null || value === '') return null;
|
|
117
|
+
if (typeof value !== 'string') throw new Error('Enter text source facts.');
|
|
118
|
+
const text = value.trim();
|
|
119
|
+
if (!text) return null;
|
|
120
|
+
if (text.length > max) throw new Error(`${name} exceeds ${max} characters.`);
|
|
121
|
+
return text;
|
|
122
|
+
}
|
|
123
|
+
function optionalDate(data: FormData, name: string): string | null {
|
|
124
|
+
const text = optionalText(data, name);
|
|
125
|
+
return text === null ? null : freeTimeIso(text);
|
|
126
|
+
}
|
|
127
|
+
function choice<T extends string>(data: FormData, name: string, allowed: readonly T[]): T {
|
|
128
|
+
const selected = allowed.find((value) => value === data.get(name));
|
|
129
|
+
if (!selected) throw new Error(`Choose a declared ${name}.`);
|
|
130
|
+
return selected;
|
|
131
|
+
}
|
|
132
|
+
export function readStockFactDraft(data: FormData, evidence: SelectedEvidence[]): StockFactDraft {
|
|
133
|
+
const validityPolicy = choice(data, 'validityPolicy', [
|
|
134
|
+
'UNKNOWN',
|
|
135
|
+
'TIME_BOUNDED',
|
|
136
|
+
'NO_REQUIRED_EXPIRY',
|
|
137
|
+
] as const);
|
|
138
|
+
const from = optionalDate(data, 'validityFrom'),
|
|
139
|
+
until = optionalDate(data, 'validityUntil');
|
|
140
|
+
if (
|
|
141
|
+
(validityPolicy === 'NO_REQUIRED_EXPIRY' && until !== null) ||
|
|
142
|
+
(from && until && Date.parse(from) >= Date.parse(until))
|
|
143
|
+
)
|
|
144
|
+
throw new Error('Source validity cutoff or chronology contradicts its declaration.');
|
|
145
|
+
const lotPresent = choice(data, 'lotPresent', ['UNKNOWN', 'REPORTED'] as const) === 'REPORTED';
|
|
146
|
+
const expiryPolicy = lotPresent
|
|
147
|
+
? choice(data, 'expiryPolicy', ['UNKNOWN', 'TIME_BOUNDED', 'NO_REQUIRED_EXPIRY'] as const)
|
|
148
|
+
: 'UNKNOWN';
|
|
149
|
+
const expiresAt = optionalDate(data, 'expiresAt');
|
|
150
|
+
if (lotPresent && expiryPolicy === 'NO_REQUIRED_EXPIRY' && expiresAt !== null)
|
|
151
|
+
throw new Error('No-required-expiry lot cannot have a cutoff.');
|
|
152
|
+
if (!evidence.length || evidence.length > 10)
|
|
153
|
+
throw new Error('Choose 1–10 exact evidence versions from shared Files.');
|
|
154
|
+
return {
|
|
155
|
+
effectiveAt: freeTimeIso(optionalText(data, 'effectiveAt') ?? ''),
|
|
156
|
+
evidence: evidence.map(({ fileId, versionId }) => ({ fileId, versionId })),
|
|
157
|
+
facts: {
|
|
158
|
+
scope: choice(data, 'scope', ['UNKNOWN', 'WHOLE_LINE', 'UNSUPPORTED_MIXED_LOT'] as const),
|
|
159
|
+
source: {
|
|
160
|
+
reference: optionalText(data, 'sourceReference'),
|
|
161
|
+
revision: optionalText(data, 'sourceRevision', 120),
|
|
162
|
+
},
|
|
163
|
+
countUnit:
|
|
164
|
+
choice(data, 'unitPresent', ['UNKNOWN', 'COUNT_UNIT'] as const) === 'COUNT_UNIT'
|
|
165
|
+
? {
|
|
166
|
+
kind: 'COUNT_UNIT',
|
|
167
|
+
reference: optionalText(data, 'unitReference'),
|
|
168
|
+
revision: optionalText(data, 'unitRevision', 120),
|
|
169
|
+
}
|
|
170
|
+
: null,
|
|
171
|
+
scanMapping: {
|
|
172
|
+
reportedItemLabel: optionalText(data, 'itemLabel'),
|
|
173
|
+
reportedBinLabel: optionalText(data, 'binLabel'),
|
|
174
|
+
mappingReference: optionalText(data, 'mappingReference'),
|
|
175
|
+
mappingRevision: optionalText(data, 'mappingRevision', 120),
|
|
176
|
+
},
|
|
177
|
+
declaredLotPolicy: choice(data, 'lotPolicy', [
|
|
178
|
+
'UNKNOWN',
|
|
179
|
+
'REQUIRED',
|
|
180
|
+
'NOT_REQUIRED',
|
|
181
|
+
] as const),
|
|
182
|
+
lot: lotPresent
|
|
183
|
+
? {
|
|
184
|
+
reference: optionalText(data, 'lotReference'),
|
|
185
|
+
revision: optionalText(data, 'lotRevision', 120),
|
|
186
|
+
declaredDisposition: choice(data, 'lotDisposition', [
|
|
187
|
+
'UNKNOWN',
|
|
188
|
+
'RELEASED',
|
|
189
|
+
'HELD',
|
|
190
|
+
'EXPIRED',
|
|
191
|
+
] as const),
|
|
192
|
+
expiry: {
|
|
193
|
+
policy: expiryPolicy,
|
|
194
|
+
expiresAt,
|
|
195
|
+
sourceReference: optionalText(data, 'expiryReference'),
|
|
196
|
+
sourceRevision: optionalText(data, 'expiryRevision', 120),
|
|
197
|
+
},
|
|
198
|
+
}
|
|
199
|
+
: null,
|
|
200
|
+
sourceValidity: {
|
|
201
|
+
policy: validityPolicy,
|
|
202
|
+
from,
|
|
203
|
+
until,
|
|
204
|
+
sourceReference: optionalText(data, 'validityReference'),
|
|
205
|
+
sourceRevision: optionalText(data, 'validityRevision', 120),
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export function stockCompletenessLabel(status: string): string {
|
|
2
|
+
if (status === 'SOURCE_FACTS_ONLY') return 'Reported facts';
|
|
3
|
+
if (status === 'INCOMPLETE') return 'Missing facts';
|
|
4
|
+
if (status === 'UNSUPPORTED_MIXED_LOT') return 'Mixed lots need separate handling';
|
|
5
|
+
return 'Unknown';
|
|
6
|
+
}
|
|
7
|
+
export function stockFactLabel(value: string | null | undefined): string {
|
|
8
|
+
if (!value || value === 'UNKNOWN') return 'Unknown';
|
|
9
|
+
if (value === 'NO_REQUIRED_EXPIRY') return 'Source reports no required expiry';
|
|
10
|
+
if (value === 'COUNT_UNIT') return 'Explicit count unit';
|
|
11
|
+
if (value === 'UNSUPPORTED_MIXED_LOT') return 'Mixed lots need separate handling';
|
|
12
|
+
const text = value.toLowerCase().replaceAll('_', ' ');
|
|
13
|
+
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
14
|
+
}
|
|
15
|
+
export function stockMissingFactLabel(value: string): string {
|
|
16
|
+
const text = value
|
|
17
|
+
.toLowerCase()
|
|
18
|
+
.replaceAll('_', ' ')
|
|
19
|
+
.replace(/^declared /, 'Reported ')
|
|
20
|
+
.replace(/ unknown$/, ' is unknown');
|
|
21
|
+
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function stockContinuityLabel(
|
|
25
|
+
assessment: { inventoryItemId: string; capturedCompositionEpoch?: number | null },
|
|
26
|
+
current?: { id: string; compositionEpoch: number } | null
|
|
27
|
+
): string {
|
|
28
|
+
if (assessment.capturedCompositionEpoch == null) return 'Continuity revision not recorded.';
|
|
29
|
+
const captured = `Recorded continuity revision: ${assessment.capturedCompositionEpoch}.`;
|
|
30
|
+
if (
|
|
31
|
+
!current ||
|
|
32
|
+
current.id !== assessment.inventoryItemId ||
|
|
33
|
+
!Number.isInteger(current.compositionEpoch) ||
|
|
34
|
+
current.compositionEpoch < 0 ||
|
|
35
|
+
current.compositionEpoch > 2147483647
|
|
36
|
+
)
|
|
37
|
+
return `${captured} Current comparison unavailable.`;
|
|
38
|
+
return current.compositionEpoch === assessment.capturedCompositionEpoch
|
|
39
|
+
? `${captured} Matches the displayed stock revision.`
|
|
40
|
+
: `${captured} Stock context changed since this record.`;
|
|
41
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { RecordMtwStockObservationInput } from '../../generated/stock-observation-operations';
|
|
2
|
+
|
|
3
|
+
function text(form: FormData, name: string, max: number, required = false): string | null {
|
|
4
|
+
const value = form.get(name);
|
|
5
|
+
if (typeof value !== 'string') throw new Error('Reported field is missing.');
|
|
6
|
+
const normalized = value.trim();
|
|
7
|
+
if (normalized.length > max || (required && !normalized))
|
|
8
|
+
throw new Error('Check the reported field length.');
|
|
9
|
+
return normalized || null;
|
|
10
|
+
}
|
|
11
|
+
/** Blank remains unknown, explicit zero remains zero; no inferred stock adjustment. */
|
|
12
|
+
export function reportedCount(value: string): number | null {
|
|
13
|
+
const clean = value.trim();
|
|
14
|
+
if (!clean) return null;
|
|
15
|
+
if (!/^\d+$/.test(clean)) throw new Error('Reported count must be a whole number or blank.');
|
|
16
|
+
const count = Number(clean);
|
|
17
|
+
if (!Number.isSafeInteger(count) || count > 2147483647)
|
|
18
|
+
throw new Error('Reported count is outside the supported range.');
|
|
19
|
+
return count;
|
|
20
|
+
}
|
|
21
|
+
function reportedInstant(value: string): string | null {
|
|
22
|
+
if (!value) return null;
|
|
23
|
+
const time = new Date(value);
|
|
24
|
+
if (!Number.isFinite(time.getTime()) || time.getTime() > Date.now())
|
|
25
|
+
throw new Error('Reported observation time must be valid and no later than now.');
|
|
26
|
+
return time.toISOString();
|
|
27
|
+
}
|
|
28
|
+
export function stockObservationInput(
|
|
29
|
+
inventoryItemId: string,
|
|
30
|
+
form: FormData
|
|
31
|
+
): Omit<RecordMtwStockObservationInput, 'idempotencyKey'> {
|
|
32
|
+
const kind = text(form, 'kind', 40, true);
|
|
33
|
+
const scope = text(form, 'countScope', 40, true);
|
|
34
|
+
if (
|
|
35
|
+
kind !== 'COUNT_DISCREPANCY' &&
|
|
36
|
+
kind !== 'DAMAGE' &&
|
|
37
|
+
kind !== 'IDENTITY_UNCERTAIN' &&
|
|
38
|
+
kind !== 'OTHER'
|
|
39
|
+
)
|
|
40
|
+
throw new Error('Choose a supported issue.');
|
|
41
|
+
if (scope !== 'WHOLE_LINE' && scope !== 'UNKNOWN')
|
|
42
|
+
throw new Error('Choose a supported count scope.');
|
|
43
|
+
const fileId = text(form, 'fileId', 255),
|
|
44
|
+
versionId = text(form, 'versionId', 255);
|
|
45
|
+
if (!!fileId !== !!versionId)
|
|
46
|
+
throw new Error('Enter both exact file and version references, or leave both blank.');
|
|
47
|
+
const unitReference = text(form, 'unitReference', 255),
|
|
48
|
+
unitRevision = text(form, 'unitRevision', 255);
|
|
49
|
+
const sourceReference = text(form, 'sourceReference', 255),
|
|
50
|
+
sourceRevision = text(form, 'sourceRevision', 255);
|
|
51
|
+
const countUnit = form.get('countUnit');
|
|
52
|
+
if (countUnit !== 'COUNT_UNIT' && countUnit !== 'UNKNOWN')
|
|
53
|
+
throw new Error('Choose a supported reported unit.');
|
|
54
|
+
if (countUnit === 'UNKNOWN' && (unitReference || unitRevision))
|
|
55
|
+
throw new Error('Select count unit before supplying its references.');
|
|
56
|
+
return {
|
|
57
|
+
inventoryItemId,
|
|
58
|
+
kind,
|
|
59
|
+
countScope: scope,
|
|
60
|
+
observedCount: reportedCount(text(form, 'observedCount', 32) ?? ''),
|
|
61
|
+
reportedCountUnit:
|
|
62
|
+
countUnit === 'COUNT_UNIT'
|
|
63
|
+
? { kind: 'COUNT_UNIT', reference: unitReference, revision: unitRevision }
|
|
64
|
+
: null,
|
|
65
|
+
source:
|
|
66
|
+
sourceReference || sourceRevision
|
|
67
|
+
? { reference: sourceReference, revision: sourceRevision }
|
|
68
|
+
: null,
|
|
69
|
+
reportedObservedAt: reportedInstant(text(form, 'reportedObservedAt', 50) ?? ''),
|
|
70
|
+
reason: text(form, 'reason', 1000, true) ?? '',
|
|
71
|
+
evidenceDeclarations: fileId && versionId ? [{ fileId, versionId }] : [],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { RecordMtwTripUtilizationReportInput } from '../../generated/trip-utilization-operations';
|
|
2
|
+
import type { TripReportDraft } from './tripUtilizationForm';
|
|
3
|
+
export interface TripDraftContext {
|
|
4
|
+
routeId: string;
|
|
5
|
+
routeUpdatedAt: string;
|
|
6
|
+
vehicleId: string;
|
|
7
|
+
vehicleUpdatedAt: string;
|
|
8
|
+
routeName: string;
|
|
9
|
+
vehicleNumber: string;
|
|
10
|
+
}
|
|
11
|
+
interface RouteContext {
|
|
12
|
+
id: string;
|
|
13
|
+
updatedAt: string;
|
|
14
|
+
vehicleId?: string | null;
|
|
15
|
+
}
|
|
16
|
+
interface VehicleContext {
|
|
17
|
+
id: string;
|
|
18
|
+
updatedAt: string;
|
|
19
|
+
}
|
|
20
|
+
export function tripRouteStillMatches(
|
|
21
|
+
pin: TripDraftContext,
|
|
22
|
+
route: RouteContext | null | undefined
|
|
23
|
+
): boolean {
|
|
24
|
+
return (
|
|
25
|
+
!!route &&
|
|
26
|
+
route.id === pin.routeId &&
|
|
27
|
+
route.updatedAt === pin.routeUpdatedAt &&
|
|
28
|
+
route.vehicleId === pin.vehicleId
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
export function tripContextStillMatches(
|
|
32
|
+
pin: TripDraftContext,
|
|
33
|
+
route: RouteContext | null | undefined,
|
|
34
|
+
vehicle: VehicleContext | null | undefined
|
|
35
|
+
): boolean {
|
|
36
|
+
return (
|
|
37
|
+
tripRouteStillMatches(pin, route) &&
|
|
38
|
+
!!vehicle &&
|
|
39
|
+
vehicle.id === pin.vehicleId &&
|
|
40
|
+
vehicle.updatedAt === pin.vehicleUpdatedAt
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
/** Fresh reads verify captured intent; they never replace the vehicle or revisions entered against. */
|
|
44
|
+
export function inputForTripDraft(
|
|
45
|
+
draft: TripReportDraft,
|
|
46
|
+
pin: TripDraftContext,
|
|
47
|
+
route: RouteContext | null | undefined,
|
|
48
|
+
vehicle: VehicleContext | null | undefined
|
|
49
|
+
): Omit<RecordMtwTripUtilizationReportInput, 'idempotencyKey'> {
|
|
50
|
+
if (!tripContextStillMatches(pin, route, vehicle))
|
|
51
|
+
throw new Error(
|
|
52
|
+
'Route assignment or revision changed since this draft began. Refresh context, review the route and vehicle, and start a new report; the entered measurements will not be reassigned automatically.'
|
|
53
|
+
);
|
|
54
|
+
return {
|
|
55
|
+
...draft,
|
|
56
|
+
routeId: pin.routeId,
|
|
57
|
+
vehicleId: pin.vehicleId,
|
|
58
|
+
expectedRouteUpdatedAt: pin.routeUpdatedAt,
|
|
59
|
+
expectedVehicleUpdatedAt: pin.vehicleUpdatedAt,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
RecordMtwTripUtilizationReportInput,
|
|
3
|
+
MtwTripUtilizationBasis,
|
|
4
|
+
MtwTripUtilizationCoverage,
|
|
5
|
+
} from '../../generated/trip-utilization-operations';
|
|
6
|
+
import type { SelectedEvidence } from '../components/ContainerEvidencePicker';
|
|
7
|
+
import { freeTimeIso } from './freeTimeDate';
|
|
8
|
+
import { reuseText } from './reuseForm';
|
|
9
|
+
export type TripReportDraft = Omit<
|
|
10
|
+
RecordMtwTripUtilizationReportInput,
|
|
11
|
+
'routeId' | 'vehicleId' | 'expectedRouteUpdatedAt' | 'expectedVehicleUpdatedAt' | 'idempotencyKey'
|
|
12
|
+
>;
|
|
13
|
+
export function tripQuantity(text: string, maximum: number, positive = false): number | null {
|
|
14
|
+
if (!text.trim()) return null;
|
|
15
|
+
if (!/^(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/.test(text.trim()))
|
|
16
|
+
throw new Error('Enter a nonnegative measurement, or leave it blank for UNKNOWN.');
|
|
17
|
+
const number = Number(text);
|
|
18
|
+
if (
|
|
19
|
+
!Number.isFinite(number) ||
|
|
20
|
+
number > maximum ||
|
|
21
|
+
(number === 0 && /[1-9]/.test(text.trim().split(/[eE]/)[0] ?? '')) ||
|
|
22
|
+
(positive ? number <= 0 : number < 0)
|
|
23
|
+
)
|
|
24
|
+
throw new Error(
|
|
25
|
+
`Measurement must be ${positive ? 'positive' : 'nonnegative'}, finite and no greater than ${maximum}.`
|
|
26
|
+
);
|
|
27
|
+
return number;
|
|
28
|
+
}
|
|
29
|
+
function choice<T extends string>(text: string, choices: readonly T[], label: string): T {
|
|
30
|
+
const found = choices.find((item) => item === text);
|
|
31
|
+
if (!found) throw new Error(`Choose ${label}.`);
|
|
32
|
+
return found;
|
|
33
|
+
}
|
|
34
|
+
export function readTripDraft(
|
|
35
|
+
values: FormData,
|
|
36
|
+
ids: string[],
|
|
37
|
+
basis: MtwTripUtilizationBasis,
|
|
38
|
+
coverage: MtwTripUtilizationCoverage,
|
|
39
|
+
evidence: SelectedEvidence[]
|
|
40
|
+
): TripReportDraft {
|
|
41
|
+
if (!evidence.length) throw new Error('Select exact readable evidence versions for the report.');
|
|
42
|
+
const intervalFrom = freeTimeIso(reuseText(values, 'intervalFrom'));
|
|
43
|
+
const intervalUntil = freeTimeIso(reuseText(values, 'intervalUntil'));
|
|
44
|
+
if (intervalFrom > intervalUntil)
|
|
45
|
+
throw new Error('The report interval must end at or after its start.');
|
|
46
|
+
const segments = ids.map((segmentId, index) => {
|
|
47
|
+
const text = (field: string) => reuseText(values, `${segmentId}.${field}`);
|
|
48
|
+
const observed = text('observedAt');
|
|
49
|
+
const observedAt = observed ? freeTimeIso(observed) : null;
|
|
50
|
+
if (
|
|
51
|
+
basis === 'OBSERVED' &&
|
|
52
|
+
(!observedAt || observedAt < intervalFrom || observedAt > intervalUntil)
|
|
53
|
+
)
|
|
54
|
+
throw new Error(
|
|
55
|
+
`Segment ${index + 1}: observation time must be within the reported interval.`
|
|
56
|
+
);
|
|
57
|
+
return {
|
|
58
|
+
segmentId,
|
|
59
|
+
sequence: index + 1,
|
|
60
|
+
loadedState: choice(
|
|
61
|
+
text('loadedState'),
|
|
62
|
+
['EMPTY', 'LOADED', 'UNKNOWN'] as const,
|
|
63
|
+
'explicit load state'
|
|
64
|
+
),
|
|
65
|
+
distanceKm: tripQuantity(text('distanceKm'), 10000000),
|
|
66
|
+
payloadKg: tripQuantity(text('payloadKg'), 1000000000),
|
|
67
|
+
payloadCapacityKg: tripQuantity(text('payloadCapacityKg'), 1000000000, true),
|
|
68
|
+
cubeM3: tripQuantity(text('cubeM3'), 1000000000),
|
|
69
|
+
cubeCapacityM3: tripQuantity(text('cubeCapacityM3'), 1000000000, true),
|
|
70
|
+
source: {
|
|
71
|
+
reference: text('reference'),
|
|
72
|
+
revision: text('revision'),
|
|
73
|
+
observedAt,
|
|
74
|
+
distanceBasis: choice(
|
|
75
|
+
text('distanceBasis'),
|
|
76
|
+
basis === 'OBSERVED'
|
|
77
|
+
? (['MEASURED'] as const)
|
|
78
|
+
: (['PROVIDER_ESTIMATE', 'OPERATOR_ESTIMATE'] as const),
|
|
79
|
+
'distance source basis'
|
|
80
|
+
),
|
|
81
|
+
loadBasis: choice(
|
|
82
|
+
text('loadBasis'),
|
|
83
|
+
basis === 'OBSERVED'
|
|
84
|
+
? (['MEASURED'] as const)
|
|
85
|
+
: (['MEASURED', 'SOURCE_CONFIRMED_PLAN'] as const),
|
|
86
|
+
'load source basis'
|
|
87
|
+
),
|
|
88
|
+
capacityBasis: choice(
|
|
89
|
+
text('capacityBasis'),
|
|
90
|
+
['RATED', 'MEASURED'] as const,
|
|
91
|
+
'capacity source basis'
|
|
92
|
+
),
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
return {
|
|
97
|
+
tripId: reuseText(values, 'tripReference'),
|
|
98
|
+
basis,
|
|
99
|
+
declaredCoverage: coverage,
|
|
100
|
+
intervalFrom,
|
|
101
|
+
intervalUntil,
|
|
102
|
+
segments,
|
|
103
|
+
evidence: evidence.map(({ fileId, versionId }) => ({ fileId, versionId })),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
fragment ConditionEvidence on MtwContainerEvidence { fileId versionId sha256Hash checkedAt }
|
|
2
|
+
fragment InspectionSummary on MtwContainerInspection {
|
|
3
|
+
id containerId inspectedAt inspectorActorId templateVersion examinationScheme nextExaminationAt acepReference
|
|
4
|
+
cargoCategory suitability cscPlateVersionId examinationVersionId defectCount severeDefectCount resolvedDefectIds evidence { ...ConditionEvidence }
|
|
5
|
+
}
|
|
6
|
+
fragment HoldSummary on MtwContainerHold {
|
|
7
|
+
id containerId inspectionId reason heldAt status version defectIds releasedAt updatedAt evidence { ...ConditionEvidence }
|
|
8
|
+
}
|
|
9
|
+
fragment QualificationSummary on MtwInspectorQualification {
|
|
10
|
+
id subjectActorId issuerName credentialReference validFrom validUntil scopes status version
|
|
11
|
+
verifierActorId reviewedAt issuerConfirmationReference reviewNote revokedAt revocationReason
|
|
12
|
+
evidence { ...ConditionEvidence } reviewEvidence { ...ConditionEvidence }
|
|
13
|
+
}
|
|
14
|
+
query ConditionContainers($pagination: MtwContainerPagination) {
|
|
15
|
+
mtwContainerPage(pagination: $pagination) { items { id containerNumber equipmentType } hasMore nextOffset }
|
|
16
|
+
}
|
|
17
|
+
query ConditionInspections($containerId: ID!, $pagination: MtwContainerPagination) {
|
|
18
|
+
mtwContainerInspectionPage(containerId: $containerId, pagination: $pagination) { items { ...InspectionSummary } hasMore nextOffset }
|
|
19
|
+
}
|
|
20
|
+
query ConditionHolds($containerId: ID!, $pagination: MtwContainerPagination) {
|
|
21
|
+
mtwContainerHoldPage(containerId: $containerId, pagination: $pagination) { items { ...HoldSummary } hasMore nextOffset }
|
|
22
|
+
}
|
|
23
|
+
query ConditionDefects($inspectionId: ID!, $pagination: MtwContainerPagination) {
|
|
24
|
+
mtwContainerDefectPage(inspectionId: $inspectionId, pagination: $pagination) { items { id code severity details } hasMore nextOffset }
|
|
25
|
+
}
|
|
26
|
+
query ConditionRepairs($holdId: ID!, $pagination: MtwContainerPagination) {
|
|
27
|
+
mtwContainerRepairPage(holdId: $holdId, pagination: $pagination) { items { id completedAt workDescription defectIds evidence { ...ConditionEvidence } } hasMore nextOffset }
|
|
28
|
+
}
|
|
29
|
+
query ConditionReleases($containerId: ID!, $pagination: MtwContainerPagination) {
|
|
30
|
+
mtwContainerReleaseDecisionPage(containerId: $containerId, pagination: $pagination) { items { id holdId inspectionId qualificationId resolutionReview decidedAt evidence { ...ConditionEvidence } } hasMore nextOffset }
|
|
31
|
+
}
|
|
32
|
+
query ConditionQualifications($pagination: MtwContainerPagination) {
|
|
33
|
+
mtwContainerQualificationPage(pagination: $pagination) { items { ...QualificationSummary } hasMore nextOffset }
|
|
34
|
+
}
|
|
35
|
+
mutation RecordInspection($input: RecordMtwContainerInspectionInput!) { recordMtwContainerInspection(input: $input) { ...InspectionSummary } }
|
|
36
|
+
mutation CreateConditionHold($input: HoldMtwContainerInput!) { holdMtwContainer(input: $input) { ...HoldSummary } }
|
|
37
|
+
mutation RecordConditionRepair($input: RecordMtwContainerRepairInput!) { recordMtwContainerRepair(input: $input) { id } }
|
|
38
|
+
mutation SubmitInspectorQualification($input: SubmitMtwInspectorQualificationInput!) { submitMtwInspectorQualification(input: $input) { ...QualificationSummary } }
|
|
39
|
+
mutation ReviewInspectorQualification($input: VerifyMtwInspectorQualificationInput!) { verifyMtwInspectorQualification(input: $input) { ...QualificationSummary } }
|
|
40
|
+
mutation RevokeInspectorQualification($input: RevokeMtwInspectorQualificationInput!) { revokeMtwInspectorQualification(input: $input) { ...QualificationSummary } }
|
|
41
|
+
mutation ReleaseConditionHold($input: ReleaseMtwContainerHoldInput!) { releaseMtwContainerHold(input: $input) { id decidedAt } }
|