@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,315 @@
|
|
|
1
|
+
import { useRef, useState } from 'react';
|
|
2
|
+
import { Gauge } from 'lucide-react';
|
|
3
|
+
import { PageLayout } from '../components/PageLayout';
|
|
4
|
+
import { Button } from '../components/ui';
|
|
5
|
+
import { PinnedSelect, ReusePager, ReuseState, reuseCard } from '../components/ReuseControls';
|
|
6
|
+
import { TripReportForm } from '../components/trip-utilization/TripReportForm';
|
|
7
|
+
import { TripReportHistory } from '../components/trip-utilization/TripReportHistory';
|
|
8
|
+
import { useMoveTheWheels } from '../providers/MoveTheWheelsProvider';
|
|
9
|
+
import { useConditionApi, useConditionQuery } from '../hooks/useContainerCondition';
|
|
10
|
+
import { useEmptyReuseAction } from '../hooks/useEmptyReuseAction';
|
|
11
|
+
import type { TripReportDraft } from '../utils/tripUtilizationForm';
|
|
12
|
+
import {
|
|
13
|
+
inputForTripDraft,
|
|
14
|
+
tripRouteStillMatches,
|
|
15
|
+
tripContextStillMatches,
|
|
16
|
+
type TripDraftContext,
|
|
17
|
+
} from '../utils/tripDraftContext';
|
|
18
|
+
import {
|
|
19
|
+
UtilizationRoutesDocument,
|
|
20
|
+
UtilizationCurrentRouteDocument,
|
|
21
|
+
UtilizationCurrentVehicleDocument,
|
|
22
|
+
UtilizationReportsDocument,
|
|
23
|
+
RecordUtilizationReportDocument,
|
|
24
|
+
type UtilizationRoutesQuery,
|
|
25
|
+
type UtilizationCurrentRouteQuery,
|
|
26
|
+
type UtilizationCurrentVehicleQuery,
|
|
27
|
+
type UtilizationReportsQuery,
|
|
28
|
+
type UtilizationReportFragment,
|
|
29
|
+
type RecordUtilizationReportMutation,
|
|
30
|
+
} from '../../generated/trip-utilization-operations';
|
|
31
|
+
export default function TripUtilizationPage() {
|
|
32
|
+
const { workspaceId, tenantId, currentUser, apiGatewayUrl } = useMoveTheWheels();
|
|
33
|
+
return (
|
|
34
|
+
<PageLayout
|
|
35
|
+
title="Reported trip utilization"
|
|
36
|
+
subtitle="Measured or estimated segment facts, separate ratios and immutable source history."
|
|
37
|
+
icon={<Gauge aria-hidden="true" />}
|
|
38
|
+
>
|
|
39
|
+
<TripUtilizationWorkbench
|
|
40
|
+
key={`${workspaceId}:${tenantId}:${currentUser?.id}:${apiGatewayUrl}`}
|
|
41
|
+
/>
|
|
42
|
+
</PageLayout>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
function TripUtilizationWorkbench() {
|
|
46
|
+
const [routeOffset, setRouteOffset] = useState(0);
|
|
47
|
+
const [reportOffset, setReportOffset] = useState(0);
|
|
48
|
+
const [routeSelection, setRouteSelection] = useState<{ id: string; label: string } | null>(null);
|
|
49
|
+
const [draftContext, setDraftContext] = useState<
|
|
50
|
+
(TripDraftContext & { generation: string }) | null
|
|
51
|
+
>(null);
|
|
52
|
+
const [contextMismatch, setContextMismatch] = useState(false);
|
|
53
|
+
const [selected, setSelected] = useState<UtilizationReportFragment | null>(null);
|
|
54
|
+
const checkingNow = useRef(false);
|
|
55
|
+
const [checking, setChecking] = useState(false);
|
|
56
|
+
const [error, setError] = useState<string | null>(null);
|
|
57
|
+
const actions = useEmptyReuseAction();
|
|
58
|
+
const request = useConditionApi();
|
|
59
|
+
const routes = useConditionQuery<UtilizationRoutesQuery>(
|
|
60
|
+
UtilizationRoutesDocument,
|
|
61
|
+
{ pagination: { limit: 25, offset: routeOffset } },
|
|
62
|
+
actions.revision
|
|
63
|
+
);
|
|
64
|
+
const current = useConditionQuery<UtilizationCurrentRouteQuery>(
|
|
65
|
+
UtilizationCurrentRouteDocument,
|
|
66
|
+
routeSelection ? { id: routeSelection.id } : null,
|
|
67
|
+
actions.revision
|
|
68
|
+
);
|
|
69
|
+
const route = current.data?.route;
|
|
70
|
+
const reports = useConditionQuery<UtilizationReportsQuery>(
|
|
71
|
+
UtilizationReportsDocument,
|
|
72
|
+
routeSelection
|
|
73
|
+
? { routeId: routeSelection.id, pagination: { limit: 25, offset: reportOffset } }
|
|
74
|
+
: null,
|
|
75
|
+
actions.revision
|
|
76
|
+
);
|
|
77
|
+
const busy = actions.busy || checking;
|
|
78
|
+
const routePage = routes.data
|
|
79
|
+
? {
|
|
80
|
+
total: routes.data.routesCount,
|
|
81
|
+
limit: 25,
|
|
82
|
+
offset: routeOffset,
|
|
83
|
+
hasMore: routeOffset + routes.data.routes.length < routes.data.routesCount,
|
|
84
|
+
nextOffset: routeOffset + 25,
|
|
85
|
+
}
|
|
86
|
+
: undefined;
|
|
87
|
+
const routeOptions =
|
|
88
|
+
routes.data?.routes.map((item) => ({
|
|
89
|
+
id: item.id,
|
|
90
|
+
label: `${item.name} — ${item.status} — ${item.vehicle?.vehicleNumber ?? 'No assigned vehicle'}`,
|
|
91
|
+
})) ?? [];
|
|
92
|
+
if (routeSelection && !routeOptions.some((item) => item.id === routeSelection.id))
|
|
93
|
+
routeOptions.unshift({
|
|
94
|
+
id: routeSelection.id,
|
|
95
|
+
label: `${route?.name ?? routeSelection.label} — selected outside this page`,
|
|
96
|
+
});
|
|
97
|
+
const displayedContextChanged =
|
|
98
|
+
!!draftContext &&
|
|
99
|
+
!!current.data &&
|
|
100
|
+
!tripContextStillMatches(draftContext, route, route?.vehicle);
|
|
101
|
+
const record = async (draft: TripReportDraft) => {
|
|
102
|
+
if (checkingNow.current) return;
|
|
103
|
+
if (!draftContext)
|
|
104
|
+
throw new Error('Review the displayed route and assigned vehicle before starting a report.');
|
|
105
|
+
const pin = draftContext;
|
|
106
|
+
checkingNow.current = true;
|
|
107
|
+
setChecking(true);
|
|
108
|
+
setError(null);
|
|
109
|
+
try {
|
|
110
|
+
const latest = await request<UtilizationCurrentRouteQuery>(UtilizationCurrentRouteDocument, {
|
|
111
|
+
id: pin.routeId,
|
|
112
|
+
});
|
|
113
|
+
const freshRoute = latest.route;
|
|
114
|
+
if (!tripRouteStillMatches(pin, freshRoute)) {
|
|
115
|
+
setContextMismatch(true);
|
|
116
|
+
throw new Error(
|
|
117
|
+
'The route or assigned vehicle changed since this draft began. Refresh context and review it before starting a new report. No measurements were rebound.'
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
const vehicleResult = await request<UtilizationCurrentVehicleQuery>(
|
|
121
|
+
UtilizationCurrentVehicleDocument,
|
|
122
|
+
{ id: pin.vehicleId }
|
|
123
|
+
);
|
|
124
|
+
if (!tripContextStillMatches(pin, freshRoute, vehicleResult.vehicle))
|
|
125
|
+
setContextMismatch(true);
|
|
126
|
+
const input = inputForTripDraft(draft, pin, freshRoute, vehicleResult.vehicle);
|
|
127
|
+
const result = await actions.run<RecordUtilizationReportMutation>(
|
|
128
|
+
RecordUtilizationReportDocument,
|
|
129
|
+
input,
|
|
130
|
+
'Immutable operator report recorded; assignments and operational state unchanged.'
|
|
131
|
+
);
|
|
132
|
+
if (result) {
|
|
133
|
+
setSelected(result.recordMtwTripUtilizationReport);
|
|
134
|
+
setReportOffset(0);
|
|
135
|
+
}
|
|
136
|
+
} catch (failure) {
|
|
137
|
+
setError(
|
|
138
|
+
failure instanceof Error ? failure.message : 'Unable to verify the captured report context.'
|
|
139
|
+
);
|
|
140
|
+
throw failure;
|
|
141
|
+
} finally {
|
|
142
|
+
checkingNow.current = false;
|
|
143
|
+
setChecking(false);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
return (
|
|
147
|
+
<div className="min-w-0 space-y-6 break-words">
|
|
148
|
+
<p className="rounded border p-4 text-sm">
|
|
149
|
+
These are operator-reported interval facts. COMPLETE coverage and measured/source labels are
|
|
150
|
+
declarations, not independently certified whole-trip measurements. Ratios do not establish
|
|
151
|
+
axle/road legality, physical packing, dispatch feasibility, fuel consumption or savings.
|
|
152
|
+
This page does not assign work or start a route.
|
|
153
|
+
</p>
|
|
154
|
+
<section className={reuseCard} aria-label="Choose route and current assigned vehicle">
|
|
155
|
+
<h2 className="text-lg font-semibold">Route and assigned vehicle</h2>
|
|
156
|
+
<PinnedSelect
|
|
157
|
+
label="Route"
|
|
158
|
+
value={routeSelection?.id ?? ''}
|
|
159
|
+
disabled={busy || actions.uncertain}
|
|
160
|
+
options={routeOptions}
|
|
161
|
+
onChange={(id) => {
|
|
162
|
+
const row = routes.data?.routes.find((item) => item.id === id);
|
|
163
|
+
setRouteSelection(row ? { id: row.id, label: row.name } : null);
|
|
164
|
+
setDraftContext(null);
|
|
165
|
+
setContextMismatch(false);
|
|
166
|
+
setSelected(null);
|
|
167
|
+
setReportOffset(0);
|
|
168
|
+
setError(null);
|
|
169
|
+
actions.discardAttempt();
|
|
170
|
+
}}
|
|
171
|
+
/>
|
|
172
|
+
<ReuseState {...routes} />
|
|
173
|
+
<ReusePager
|
|
174
|
+
page={routePage}
|
|
175
|
+
offset={routeOffset}
|
|
176
|
+
onChange={setRouteOffset}
|
|
177
|
+
busy={busy || routes.loading}
|
|
178
|
+
/>
|
|
179
|
+
{routeSelection && (
|
|
180
|
+
<p>
|
|
181
|
+
Selected route {route?.name ?? routeSelection.label}.{' '}
|
|
182
|
+
{route
|
|
183
|
+
? `Current status ${route.status}; revision ${route.updatedAt}.`
|
|
184
|
+
: 'Current record not loaded; new report blocked.'}
|
|
185
|
+
</p>
|
|
186
|
+
)}
|
|
187
|
+
<ReuseState {...current} />
|
|
188
|
+
{route && (
|
|
189
|
+
<p>
|
|
190
|
+
Currently assigned vehicle:{' '}
|
|
191
|
+
{route.vehicle
|
|
192
|
+
? `${route.vehicle.vehicleNumber}${route.vehicle.licensePlate ? ` (${route.vehicle.licensePlate})` : ''} — ${route.vehicle.type} — ${route.vehicle.status}; revision ${route.vehicle.updatedAt}`
|
|
193
|
+
: 'unavailable / unassigned'}
|
|
194
|
+
. Assignment changes belong to the existing route workflow.
|
|
195
|
+
</p>
|
|
196
|
+
)}
|
|
197
|
+
<Button
|
|
198
|
+
type="button"
|
|
199
|
+
variant="outline"
|
|
200
|
+
disabled={busy}
|
|
201
|
+
onClick={() => {
|
|
202
|
+
setContextMismatch(false);
|
|
203
|
+
setError(null);
|
|
204
|
+
actions.refresh();
|
|
205
|
+
}}
|
|
206
|
+
>
|
|
207
|
+
Refresh current context and history
|
|
208
|
+
</Button>
|
|
209
|
+
</section>
|
|
210
|
+
{routeSelection && (
|
|
211
|
+
<>
|
|
212
|
+
<section className={reuseCard} aria-label="Record reported utilization">
|
|
213
|
+
<h2 className="text-lg font-semibold">Record interval facts</h2>
|
|
214
|
+
<p className="text-sm">
|
|
215
|
+
Start a report only after reviewing the displayed route and assigned vehicle. The
|
|
216
|
+
draft retains those identities and revisions. Fresh reads verify them; they do not
|
|
217
|
+
substitute a new vehicle or retag entered measurements.
|
|
218
|
+
</p>
|
|
219
|
+
{draftContext && (
|
|
220
|
+
<p>
|
|
221
|
+
Draft context: {draftContext.routeName} / {draftContext.vehicleNumber}; route
|
|
222
|
+
revision {draftContext.routeUpdatedAt}; vehicle revision{' '}
|
|
223
|
+
{draftContext.vehicleUpdatedAt}.
|
|
224
|
+
</p>
|
|
225
|
+
)}
|
|
226
|
+
{(contextMismatch || displayedContextChanged) && (
|
|
227
|
+
<p role="alert">
|
|
228
|
+
The draft context changed. Unsaved measurement fields are cleared. Refresh and
|
|
229
|
+
review the current context before starting a replacement report. An uncertain
|
|
230
|
+
original request remains separate.
|
|
231
|
+
</p>
|
|
232
|
+
)}
|
|
233
|
+
{actions.uncertain && (
|
|
234
|
+
<p>
|
|
235
|
+
Resolve the uncertain original request or explicitly abandon it after inspecting
|
|
236
|
+
history before starting another draft.
|
|
237
|
+
</p>
|
|
238
|
+
)}
|
|
239
|
+
<Button
|
|
240
|
+
type="button"
|
|
241
|
+
variant="outline"
|
|
242
|
+
disabled={
|
|
243
|
+
busy ||
|
|
244
|
+
actions.uncertain ||
|
|
245
|
+
contextMismatch ||
|
|
246
|
+
current.loading ||
|
|
247
|
+
!route?.vehicle ||
|
|
248
|
+
route.vehicleId !== route.vehicle.id
|
|
249
|
+
}
|
|
250
|
+
onClick={() => {
|
|
251
|
+
if (!route?.vehicle || route.vehicleId !== route.vehicle.id) return;
|
|
252
|
+
setDraftContext({
|
|
253
|
+
routeId: route.id,
|
|
254
|
+
routeUpdatedAt: route.updatedAt,
|
|
255
|
+
vehicleId: route.vehicle.id,
|
|
256
|
+
vehicleUpdatedAt: route.vehicle.updatedAt,
|
|
257
|
+
routeName: route.name,
|
|
258
|
+
vehicleNumber: route.vehicle.vehicleNumber,
|
|
259
|
+
generation: crypto.randomUUID(),
|
|
260
|
+
});
|
|
261
|
+
setContextMismatch(false);
|
|
262
|
+
setError(null);
|
|
263
|
+
}}
|
|
264
|
+
>
|
|
265
|
+
Review current context and start a new report
|
|
266
|
+
</Button>
|
|
267
|
+
{draftContext && !contextMismatch && !displayedContextChanged && (
|
|
268
|
+
<TripReportForm
|
|
269
|
+
key={`${draftContext.generation}:${draftContext.routeId}:${draftContext.routeUpdatedAt}:${draftContext.vehicleId}:${draftContext.vehicleUpdatedAt}`}
|
|
270
|
+
busy={
|
|
271
|
+
busy ||
|
|
272
|
+
actions.uncertain ||
|
|
273
|
+
current.loading ||
|
|
274
|
+
!route?.vehicleId ||
|
|
275
|
+
!route.vehicle
|
|
276
|
+
}
|
|
277
|
+
onSubmit={record}
|
|
278
|
+
/>
|
|
279
|
+
)}
|
|
280
|
+
</section>
|
|
281
|
+
<TripReportHistory
|
|
282
|
+
query={reports}
|
|
283
|
+
offset={reportOffset}
|
|
284
|
+
onPage={setReportOffset}
|
|
285
|
+
selected={selected}
|
|
286
|
+
onSelect={setSelected}
|
|
287
|
+
busy={busy}
|
|
288
|
+
/>
|
|
289
|
+
</>
|
|
290
|
+
)}
|
|
291
|
+
{error && <p role="alert">{error}</p>}
|
|
292
|
+
{actions.error && <p role="alert">{actions.error}</p>}
|
|
293
|
+
{actions.notice && <p role="status">{actions.notice}</p>}
|
|
294
|
+
{actions.uncertain && (
|
|
295
|
+
<div className="space-y-3 rounded border p-4">
|
|
296
|
+
<p>
|
|
297
|
+
Result may be uncertain. Inspect refreshed history first. Retry original request sends
|
|
298
|
+
the original submitted body, route/vehicle revisions and key, ignoring edited form
|
|
299
|
+
fields. A new submitted semantic payload starts a new key. Attempts are not retained
|
|
300
|
+
after a browser reload.
|
|
301
|
+
</p>
|
|
302
|
+
<Button type="button" variant="outline" disabled={busy} onClick={actions.refresh}>
|
|
303
|
+
Refresh report history
|
|
304
|
+
</Button>
|
|
305
|
+
<Button type="button" disabled={busy} onClick={actions.retryOriginal}>
|
|
306
|
+
Retry original request
|
|
307
|
+
</Button>
|
|
308
|
+
<Button type="button" variant="outline" disabled={busy} onClick={actions.discardAttempt}>
|
|
309
|
+
Abandon retry after inspecting history
|
|
310
|
+
</Button>
|
|
311
|
+
</div>
|
|
312
|
+
)}
|
|
313
|
+
</div>
|
|
314
|
+
);
|
|
315
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { print } from 'graphql';
|
|
2
|
+
import {
|
|
3
|
+
SaveConsolidationPlanDocument,
|
|
4
|
+
RecordConsolidationObservationDocument,
|
|
5
|
+
SaveConsolidationManifestDocument,
|
|
6
|
+
} from '../../generated/consolidation-operations';
|
|
7
|
+
import {
|
|
8
|
+
sameReuseRecoveryScope,
|
|
9
|
+
type ReuseRecovery,
|
|
10
|
+
type ReuseRecoveryScope,
|
|
11
|
+
} from './reuseRecovery';
|
|
12
|
+
|
|
13
|
+
export type OriginalConsolidationHistoryTarget =
|
|
14
|
+
| { kind: 'plan'; shipmentId: string; planReference: string }
|
|
15
|
+
| { kind: 'observation' | 'manifest'; planId: string };
|
|
16
|
+
|
|
17
|
+
function reference(value: unknown): value is string {
|
|
18
|
+
return typeof value === 'string' && value.trim().length > 0 && value.length <= 200;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Retained input supplies read targets only in its original context; it never rebinds a draft. */
|
|
22
|
+
export function originalConsolidationHistoryTarget(
|
|
23
|
+
pending: ReuseRecovery | null,
|
|
24
|
+
scope: ReuseRecoveryScope | null
|
|
25
|
+
): OriginalConsolidationHistoryTarget | null {
|
|
26
|
+
if (!pending || !sameReuseRecoveryScope(pending.scope, scope)) return null;
|
|
27
|
+
if (pending.operation === print(SaveConsolidationPlanDocument)) {
|
|
28
|
+
const { shipmentId, planReference } = pending.input;
|
|
29
|
+
return reference(shipmentId) && reference(planReference)
|
|
30
|
+
? { kind: 'plan', shipmentId, planReference }
|
|
31
|
+
: null;
|
|
32
|
+
}
|
|
33
|
+
if (!reference(pending.input.planId)) return null;
|
|
34
|
+
if (pending.operation === print(RecordConsolidationObservationDocument))
|
|
35
|
+
return { kind: 'observation', planId: pending.input.planId };
|
|
36
|
+
if (pending.operation === print(SaveConsolidationManifestDocument))
|
|
37
|
+
return { kind: 'manifest', planId: pending.input.planId };
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { object, localProcedureInstant } from './procedureInput';
|
|
2
|
+
export const consolidationInstant = localProcedureInstant;
|
|
3
|
+
export function nullableText(value: string): string | null {
|
|
4
|
+
return value.trim() || null;
|
|
5
|
+
}
|
|
6
|
+
/** Keep decimal source text exact. Blank facts are unknown, and explicit zero remains zero. */
|
|
7
|
+
export function consolidationQuantity(value: string): string | null {
|
|
8
|
+
const text = value.trim();
|
|
9
|
+
if (!text) return null;
|
|
10
|
+
if (!/^(?:0|[1-9]\d{0,19})(?:\.\d{1,6})?$/.test(text))
|
|
11
|
+
throw new Error('Use a nonnegative decimal with at most six decimal places.');
|
|
12
|
+
return text;
|
|
13
|
+
}
|
|
14
|
+
export function sameConsolidationPin(
|
|
15
|
+
a: { id: string; version: number } | null,
|
|
16
|
+
b: { id: string; version: number } | null
|
|
17
|
+
): boolean {
|
|
18
|
+
return a?.id === b?.id && a?.version === b?.version;
|
|
19
|
+
}
|
|
20
|
+
/** Require the scoped immutable acknowledgement before clearing the original request. */
|
|
21
|
+
export function consolidationAcknowledgement(
|
|
22
|
+
result: Record<string, unknown>,
|
|
23
|
+
input: Record<string, unknown>,
|
|
24
|
+
actorId?: string
|
|
25
|
+
): boolean {
|
|
26
|
+
const field =
|
|
27
|
+
'facts' in input
|
|
28
|
+
? 'saveMtwConsolidationPlan'
|
|
29
|
+
: 'kind' in input
|
|
30
|
+
? 'recordMtwConsolidationObservation'
|
|
31
|
+
: 'saveMtwConsolidationManifest';
|
|
32
|
+
const row = result[field];
|
|
33
|
+
if (
|
|
34
|
+
!object(row) ||
|
|
35
|
+
typeof row.id !== 'string' ||
|
|
36
|
+
!row.id.trim() ||
|
|
37
|
+
row.createdBy !== actorId ||
|
|
38
|
+
typeof input.expectedVersion !== 'number' ||
|
|
39
|
+
!Number.isInteger(input.expectedVersion) ||
|
|
40
|
+
input.expectedVersion < 0 ||
|
|
41
|
+
row.version !== input.expectedVersion + 1 ||
|
|
42
|
+
row.previousVersionId !== input.expectedPreviousVersionId
|
|
43
|
+
)
|
|
44
|
+
return false;
|
|
45
|
+
if ('facts' in input)
|
|
46
|
+
return (
|
|
47
|
+
row.shipmentId === input.shipmentId &&
|
|
48
|
+
row.cycleId === input.cycleId &&
|
|
49
|
+
row.planReference === input.planReference &&
|
|
50
|
+
object(row.sourceCapture) &&
|
|
51
|
+
row.sourceCapture.shipmentUpdatedAt === input.expectedShipmentUpdatedAt &&
|
|
52
|
+
row.sourceCapture.cycleVersion === input.expectedCycleVersion
|
|
53
|
+
);
|
|
54
|
+
if ('kind' in input)
|
|
55
|
+
return (
|
|
56
|
+
row.planId === input.planId &&
|
|
57
|
+
row.lotId === input.lotId &&
|
|
58
|
+
row.kind === input.kind &&
|
|
59
|
+
row.issueReference === input.issueReference &&
|
|
60
|
+
row.reportedQuantity === input.reportedQuantity &&
|
|
61
|
+
Number.isInteger(row.receiptSequence)
|
|
62
|
+
);
|
|
63
|
+
return (
|
|
64
|
+
row.planId === input.planId &&
|
|
65
|
+
row.observationSequence === input.expectedObservationSequence &&
|
|
66
|
+
object(row.snapshot) &&
|
|
67
|
+
row.snapshot.planId === input.planId &&
|
|
68
|
+
row.snapshot.observationSequence === input.expectedObservationSequence
|
|
69
|
+
);
|
|
70
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { MtwConsolidationLotInput } from '../../generated/consolidation-operations';
|
|
2
|
+
export function emptyConsolidationLot(): MtwConsolidationLotInput {
|
|
3
|
+
return {
|
|
4
|
+
id: crypto.randomUUID(),
|
|
5
|
+
supplierReference: '',
|
|
6
|
+
lotReference: '',
|
|
7
|
+
consignmentReference: '',
|
|
8
|
+
sourceRevision: '',
|
|
9
|
+
quantityBasis: 'UNKNOWN',
|
|
10
|
+
unitReference: null,
|
|
11
|
+
unitRevision: null,
|
|
12
|
+
balanceRevision: null,
|
|
13
|
+
reportedAvailableQuantity: null,
|
|
14
|
+
plannedQuantity: null,
|
|
15
|
+
grossKg: null,
|
|
16
|
+
cubeM3: null,
|
|
17
|
+
originReference: null,
|
|
18
|
+
destinationReference: null,
|
|
19
|
+
importerReference: null,
|
|
20
|
+
transportReference: null,
|
|
21
|
+
documentReference: null,
|
|
22
|
+
source: { reference: null, revision: null },
|
|
23
|
+
};
|
|
24
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ConsolidationContainersQuery,
|
|
3
|
+
ConsolidationCyclesQuery,
|
|
4
|
+
ConsolidationShipmentQuery,
|
|
5
|
+
} from '../../generated/consolidation-operations';
|
|
6
|
+
import { sameConsolidationPin } from './consolidationInput';
|
|
7
|
+
export type ConsolidationContextPin = {
|
|
8
|
+
shipmentId: string;
|
|
9
|
+
shipmentUpdatedAt: string;
|
|
10
|
+
cycleId: string;
|
|
11
|
+
cycleVersion: number;
|
|
12
|
+
containerId: string;
|
|
13
|
+
};
|
|
14
|
+
export function matchesConsolidationContext(
|
|
15
|
+
pin: ConsolidationContextPin,
|
|
16
|
+
shipment: ConsolidationShipmentQuery['shipment'],
|
|
17
|
+
cycle: ConsolidationCyclesQuery['mtwContainerCyclePage']['items'][number] | null
|
|
18
|
+
): boolean {
|
|
19
|
+
return (
|
|
20
|
+
!!shipment &&
|
|
21
|
+
!!cycle &&
|
|
22
|
+
shipment.id === pin.shipmentId &&
|
|
23
|
+
shipment.updatedAt === pin.shipmentUpdatedAt &&
|
|
24
|
+
cycle.id === pin.cycleId &&
|
|
25
|
+
cycle.containerId === pin.containerId &&
|
|
26
|
+
cycle.shipmentId === pin.shipmentId &&
|
|
27
|
+
cycle.version === pin.cycleVersion &&
|
|
28
|
+
cycle.status === 'OPEN'
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
export function assertConsolidationPredecessor(
|
|
32
|
+
pin: { id: string; version: number } | null,
|
|
33
|
+
current: { id: string; version: number } | null
|
|
34
|
+
): void {
|
|
35
|
+
if (!sameConsolidationPin(pin, current))
|
|
36
|
+
throw new Error('Recorded history changed. Refresh and review before opening a new form.');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type ConsolidationContainerOption = Pick<
|
|
40
|
+
ConsolidationContainersQuery['mtwContainerPage']['items'][number],
|
|
41
|
+
'id' | 'containerNumber' | 'equipmentType'
|
|
42
|
+
>;
|
|
43
|
+
/** Retain the selected label across pagination without asserting current source validity. */
|
|
44
|
+
export function offPageConsolidationContainer(
|
|
45
|
+
selectedId: string,
|
|
46
|
+
selected: ConsolidationContainerOption | null,
|
|
47
|
+
visible: readonly ConsolidationContainerOption[]
|
|
48
|
+
): ConsolidationContainerOption | null {
|
|
49
|
+
return selected?.id === selectedId && !visible.some((row) => row.id === selectedId)
|
|
50
|
+
? selected
|
|
51
|
+
: null;
|
|
52
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { print } from 'graphql';
|
|
2
|
+
import {
|
|
3
|
+
SaveConsolidationPlanDocument,
|
|
4
|
+
RecordConsolidationObservationDocument,
|
|
5
|
+
SaveConsolidationManifestDocument,
|
|
6
|
+
} from '../../generated/consolidation-operations';
|
|
7
|
+
import type { ReuseRecovery } from './reuseRecovery';
|
|
8
|
+
export const CONSOLIDATION_RECOVERY_STORAGE = 'movethewheels.consolidation.unresolved.v1';
|
|
9
|
+
export function decodeConsolidationRecovery(raw: string | null): ReuseRecovery | null {
|
|
10
|
+
if (!raw || new TextEncoder().encode(raw).byteLength > 200000) return null;
|
|
11
|
+
try {
|
|
12
|
+
const value: unknown = JSON.parse(raw);
|
|
13
|
+
if (
|
|
14
|
+
typeof value !== 'object' ||
|
|
15
|
+
value === null ||
|
|
16
|
+
!('version' in value) ||
|
|
17
|
+
value.version !== 1 ||
|
|
18
|
+
!('scope' in value) ||
|
|
19
|
+
!('input' in value) ||
|
|
20
|
+
!('operation' in value) ||
|
|
21
|
+
typeof value.operation !== 'string' ||
|
|
22
|
+
![
|
|
23
|
+
SaveConsolidationPlanDocument,
|
|
24
|
+
RecordConsolidationObservationDocument,
|
|
25
|
+
SaveConsolidationManifestDocument,
|
|
26
|
+
].some((item) => print(item) === value.operation) ||
|
|
27
|
+
!('key' in value) ||
|
|
28
|
+
typeof value.key !== 'string' ||
|
|
29
|
+
!value.key ||
|
|
30
|
+
value.key.length > 200 ||
|
|
31
|
+
!('success' in value) ||
|
|
32
|
+
typeof value.success !== 'string' ||
|
|
33
|
+
value.success.length > 500
|
|
34
|
+
)
|
|
35
|
+
return null;
|
|
36
|
+
if (
|
|
37
|
+
typeof value.input !== 'object' ||
|
|
38
|
+
value.input === null ||
|
|
39
|
+
Array.isArray(value.input) ||
|
|
40
|
+
typeof value.scope !== 'object' ||
|
|
41
|
+
value.scope === null
|
|
42
|
+
)
|
|
43
|
+
return null;
|
|
44
|
+
const scope = value.scope;
|
|
45
|
+
if (
|
|
46
|
+
!('actorId' in scope) ||
|
|
47
|
+
typeof scope.actorId !== 'string' ||
|
|
48
|
+
!scope.actorId ||
|
|
49
|
+
!('workspaceId' in scope) ||
|
|
50
|
+
typeof scope.workspaceId !== 'string' ||
|
|
51
|
+
!scope.workspaceId ||
|
|
52
|
+
!('tenantId' in scope) ||
|
|
53
|
+
typeof scope.tenantId !== 'string' ||
|
|
54
|
+
!('organizationId' in scope) ||
|
|
55
|
+
typeof scope.organizationId !== 'string' ||
|
|
56
|
+
!scope.organizationId ||
|
|
57
|
+
!('gateway' in scope) ||
|
|
58
|
+
typeof scope.gateway !== 'string' ||
|
|
59
|
+
!('projectId' in scope) ||
|
|
60
|
+
(scope.projectId !== null && typeof scope.projectId !== 'string')
|
|
61
|
+
)
|
|
62
|
+
return null;
|
|
63
|
+
return {
|
|
64
|
+
version: 1,
|
|
65
|
+
scope: {
|
|
66
|
+
actorId: scope.actorId,
|
|
67
|
+
workspaceId: scope.workspaceId,
|
|
68
|
+
tenantId: scope.tenantId,
|
|
69
|
+
organizationId: scope.organizationId,
|
|
70
|
+
gateway: scope.gateway,
|
|
71
|
+
projectId: scope.projectId,
|
|
72
|
+
},
|
|
73
|
+
operation: value.operation,
|
|
74
|
+
// The owning document is exact and input is an object; field authority remains backend-validated.
|
|
75
|
+
input: structuredClone(value.input) as Record<string, unknown>,
|
|
76
|
+
key: value.key,
|
|
77
|
+
success: value.success,
|
|
78
|
+
};
|
|
79
|
+
} catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export function encodeConsolidationRecovery(attempt: ReuseRecovery): string {
|
|
84
|
+
const raw = JSON.stringify(attempt);
|
|
85
|
+
if (!decodeConsolidationRecovery(raw))
|
|
86
|
+
throw new Error('Cannot safely retain this consolidation request. Nothing was sent.');
|
|
87
|
+
return raw;
|
|
88
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConsolidationObservationsDocument,
|
|
3
|
+
type ConsolidationObservationsQuery,
|
|
4
|
+
type MtwConsolidationReportKind,
|
|
5
|
+
} from '../../generated/consolidation-operations';
|
|
6
|
+
type Report = ConsolidationObservationsQuery['mtwConsolidationObservationPage']['items'][number];
|
|
7
|
+
export async function findConsolidationReportHead(
|
|
8
|
+
request: <T>(
|
|
9
|
+
document: typeof ConsolidationObservationsDocument,
|
|
10
|
+
variables: Record<string, unknown>
|
|
11
|
+
) => Promise<T>,
|
|
12
|
+
planId: string,
|
|
13
|
+
lotId: string,
|
|
14
|
+
kind: MtwConsolidationReportKind
|
|
15
|
+
): Promise<Report | null> {
|
|
16
|
+
// Receipt ordering makes the first matching row the current cumulative chain head.
|
|
17
|
+
for (let offset = 0; offset < 500; offset += 25) {
|
|
18
|
+
const page = await request<ConsolidationObservationsQuery>(ConsolidationObservationsDocument, {
|
|
19
|
+
planId,
|
|
20
|
+
pagination: { limit: 25, offset },
|
|
21
|
+
});
|
|
22
|
+
const head = page.mtwConsolidationObservationPage.items.find(
|
|
23
|
+
(row) => row.lotId === lotId && row.kind === kind
|
|
24
|
+
);
|
|
25
|
+
if (head) return head;
|
|
26
|
+
if (!page.mtwConsolidationObservationPage.hasMore) return null;
|
|
27
|
+
}
|
|
28
|
+
throw new Error('History exceeds the supported review window. No report will be sent.');
|
|
29
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function freeTimeIso(value: string): string {
|
|
2
|
+
const parts =
|
|
3
|
+
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d{1,3})?(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/i.exec(
|
|
4
|
+
value
|
|
5
|
+
);
|
|
6
|
+
if (!parts)
|
|
7
|
+
throw new Error('Use an ISO date and time with seconds and Z or an explicit timezone offset.');
|
|
8
|
+
const year = Number(parts[1]);
|
|
9
|
+
const month = Number(parts[2]);
|
|
10
|
+
const day = Number(parts[3]);
|
|
11
|
+
const leap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
12
|
+
const days = [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
13
|
+
if (
|
|
14
|
+
month < 1 ||
|
|
15
|
+
month > 12 ||
|
|
16
|
+
day < 1 ||
|
|
17
|
+
day > (days[month - 1] ?? 0) ||
|
|
18
|
+
Number(parts[4]) > 23 ||
|
|
19
|
+
Number(parts[5]) > 59 ||
|
|
20
|
+
Number(parts[6]) > 59
|
|
21
|
+
)
|
|
22
|
+
throw new Error(
|
|
23
|
+
'Enter a real calendar date and time; invalid dates are not moved to another day.'
|
|
24
|
+
);
|
|
25
|
+
if (!/(?:Z|[+-]\d{2}:\d{2})$/i.test(value))
|
|
26
|
+
throw new Error('Include Z or an explicit timezone offset.');
|
|
27
|
+
const date = new Date(value);
|
|
28
|
+
if (!Number.isFinite(date.getTime()))
|
|
29
|
+
throw new Error('Enter a valid time with an explicit timezone.');
|
|
30
|
+
return date.toISOString();
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Validate the minimum immutable receipt identity before resolving a retained request. */
|
|
2
|
+
export function matchesFreightAcknowledgement(
|
|
3
|
+
result: unknown,
|
|
4
|
+
input: Record<string, unknown>
|
|
5
|
+
): boolean {
|
|
6
|
+
if (
|
|
7
|
+
typeof result !== 'object' ||
|
|
8
|
+
result === null ||
|
|
9
|
+
!('saveMtwFreightEstimate' in result) ||
|
|
10
|
+
typeof result.saveMtwFreightEstimate !== 'object' ||
|
|
11
|
+
result.saveMtwFreightEstimate === null
|
|
12
|
+
)
|
|
13
|
+
return false;
|
|
14
|
+
const receipt = result.saveMtwFreightEstimate;
|
|
15
|
+
return (
|
|
16
|
+
'id' in receipt &&
|
|
17
|
+
typeof receipt.id === 'string' &&
|
|
18
|
+
receipt.id.trim().length > 0 &&
|
|
19
|
+
'shipmentId' in receipt &&
|
|
20
|
+
receipt.shipmentId === input.shipmentId &&
|
|
21
|
+
'estimateReference' in receipt &&
|
|
22
|
+
receipt.estimateReference === input.estimateReference &&
|
|
23
|
+
'version' in receipt &&
|
|
24
|
+
Number.isInteger(input.expectedVersion) &&
|
|
25
|
+
typeof input.expectedVersion === 'number' &&
|
|
26
|
+
input.expectedVersion >= 0 &&
|
|
27
|
+
receipt.version === input.expectedVersion + 1 &&
|
|
28
|
+
'previousVersionId' in receipt &&
|
|
29
|
+
receipt.previousVersionId === input.expectedPreviousVersionId
|
|
30
|
+
);
|
|
31
|
+
}
|