@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.
Files changed (373) hide show
  1. package/dist/MoveTheWheelsRoot.js +177 -102
  2. package/dist/MoveTheWheelsRoutes.js +55 -11
  3. package/dist/_virtual/_rolldown/runtime.js +1 -1
  4. package/dist/components/ContainerEvidencePicker.js +143 -0
  5. package/dist/components/FreeTimeAgreementForm.js +496 -0
  6. package/dist/components/ReturnInstructionForm.js +108 -0
  7. package/dist/components/ReuseControls.js +91 -0
  8. package/dist/components/ReusePermissionForm.js +114 -0
  9. package/dist/components/ReuseProposalForm.js +455 -0
  10. package/dist/components/ReuseSourceFields.js +78 -0
  11. package/dist/components/consolidation/ConsolidationHistory.js +244 -0
  12. package/dist/components/consolidation/ConsolidationLotEditor.js +133 -0
  13. package/dist/components/consolidation/ConsolidationManifestWorkbench.js +143 -0
  14. package/dist/components/consolidation/ConsolidationPlanForm.js +172 -0
  15. package/dist/components/consolidation/ConsolidationPlanWorkbench.js +321 -0
  16. package/dist/components/consolidation/ConsolidationReportForm.js +94 -0
  17. package/dist/components/consolidation/ConsolidationReportsWorkbench.js +195 -0
  18. package/dist/components/consolidation/ConsolidationSummary.js +76 -0
  19. package/dist/components/consolidation/OriginalConsolidationHistory.js +112 -0
  20. package/dist/components/freight-cost/FreightDraftForm.js +213 -0
  21. package/dist/components/freight-cost/FreightFields.js +70 -0
  22. package/dist/components/freight-cost/FreightFxEditor.js +90 -0
  23. package/dist/components/freight-cost/FreightHistory.js +164 -0
  24. package/dist/components/freight-cost/FreightLineEditor.js +191 -0
  25. package/dist/components/freight-cost/FreightScopeEditor.js +72 -0
  26. package/dist/components/freight-cost/FreightTotals.js +66 -0
  27. package/dist/components/logistics-procedure/ProcedureDecisionForm.js +197 -0
  28. package/dist/components/logistics-procedure/ProcedureFields.js +31 -0
  29. package/dist/components/logistics-procedure/ProcedureHistory.js +177 -0
  30. package/dist/components/logistics-procedure/ProcedurePolicyForm.js +227 -0
  31. package/dist/components/logistics-procedure/ProcedurePolicyWorkbench.js +155 -0
  32. package/dist/components/logistics-procedure/ProcedureReviewWorkbench.js +221 -0
  33. package/dist/components/logistics-procedure/ProcedureRunWorkbench.js +190 -0
  34. package/dist/components/logistics-procedure/ProcedureSubjectPicker.js +130 -0
  35. package/dist/components/pending-pick/PendingPickDraft.js +84 -0
  36. package/dist/components/pending-pick/PendingPickHistory.js +113 -0
  37. package/dist/components/pending-pick/PickCapture.js +166 -0
  38. package/dist/components/pending-pick/PickLineSelection.js +111 -0
  39. package/dist/components/stock-binding/StockAssessmentDraft.js +48 -0
  40. package/dist/components/stock-binding/StockAssessmentHistory.js +61 -0
  41. package/dist/components/stock-binding/StockAssessmentSummary.js +199 -0
  42. package/dist/components/stock-binding/StockFactForm.js +232 -0
  43. package/dist/components/stock-observation/StockIssueForm.js +148 -0
  44. package/dist/components/stock-observation/StockIssueHistory.js +116 -0
  45. package/dist/components/stock-observation/StockIssueReadPanel.js +70 -0
  46. package/dist/components/trip-utilization/TripReportForm.js +118 -0
  47. package/dist/components/trip-utilization/TripReportHistory.js +54 -0
  48. package/dist/components/trip-utilization/TripReportSummary.js +216 -0
  49. package/dist/components/trip-utilization/TripSegmentFields.js +166 -0
  50. package/dist/generated/consolidation-operations.d.ts +1060 -0
  51. package/dist/generated/container-condition-operations.d.ts +868 -0
  52. package/dist/generated/container-operations.d.ts +356 -0
  53. package/dist/generated/empty-reuse-operations.d.ts +1578 -0
  54. package/dist/generated/free-time-operations.d.ts +938 -0
  55. package/dist/generated/freight-cost-operations.d.ts +716 -0
  56. package/dist/generated/logistics-procedure-operations.d.ts +938 -0
  57. package/dist/generated/pending-pick-operations.d.ts +1969 -0
  58. package/dist/generated/stock-binding-operations.d.ts +930 -0
  59. package/dist/generated/stock-observation-operations.d.ts +476 -0
  60. package/dist/generated/trip-utilization-operations.d.ts +651 -0
  61. package/dist/generated/wspace-operations.d.ts +143 -50
  62. package/dist/hooks/useConsolidationAction.js +119 -0
  63. package/dist/hooks/useContainerCondition.js +105 -0
  64. package/dist/hooks/useContainerLifecycle.js +192 -0
  65. package/dist/hooks/useEmptyReuseAction.js +45 -0
  66. package/dist/hooks/useFreightRecoveryAction.js +117 -0
  67. package/dist/hooks/useProcedureAction.js +119 -0
  68. package/dist/hooks/useProcedureSelection.js +53 -0
  69. package/dist/hooks/useReuseRecoveryAction.js +116 -0
  70. package/dist/movethewheels/components/ContainerEvidencePicker.d.ts +10 -0
  71. package/dist/movethewheels/components/FreeTimeAgreementForm.d.ts +14 -0
  72. package/dist/movethewheels/components/ReturnInstructionForm.d.ts +8 -0
  73. package/dist/movethewheels/components/ReuseControls.d.ts +42 -0
  74. package/dist/movethewheels/components/ReusePermissionForm.d.ts +9 -0
  75. package/dist/movethewheels/components/ReuseProposalForm.d.ts +11 -0
  76. package/dist/movethewheels/components/ReuseSourceFields.d.ts +9 -0
  77. package/dist/movethewheels/components/consolidation/ConsolidationHistory.d.ts +13 -0
  78. package/dist/movethewheels/components/consolidation/ConsolidationLotEditor.d.ts +6 -0
  79. package/dist/movethewheels/components/consolidation/ConsolidationManifestWorkbench.d.ts +8 -0
  80. package/dist/movethewheels/components/consolidation/ConsolidationPlanForm.d.ts +8 -0
  81. package/dist/movethewheels/components/consolidation/ConsolidationPlanWorkbench.d.ts +5 -0
  82. package/dist/movethewheels/components/consolidation/ConsolidationReportForm.d.ts +9 -0
  83. package/dist/movethewheels/components/consolidation/ConsolidationReportsWorkbench.d.ts +7 -0
  84. package/dist/movethewheels/components/consolidation/ConsolidationSummary.d.ts +6 -0
  85. package/dist/movethewheels/components/consolidation/OriginalConsolidationHistory.d.ts +8 -0
  86. package/dist/movethewheels/components/freight-cost/FreightDraftForm.d.ts +8 -0
  87. package/dist/movethewheels/components/freight-cost/FreightFields.d.ts +23 -0
  88. package/dist/movethewheels/components/freight-cost/FreightFxEditor.d.ts +6 -0
  89. package/dist/movethewheels/components/freight-cost/FreightHistory.d.ts +5 -0
  90. package/dist/movethewheels/components/freight-cost/FreightLineEditor.d.ts +8 -0
  91. package/dist/movethewheels/components/freight-cost/FreightScopeEditor.d.ts +6 -0
  92. package/dist/movethewheels/components/freight-cost/FreightTotals.d.ts +6 -0
  93. package/dist/movethewheels/components/logistics-procedure/ProcedureDecisionForm.d.ts +20 -0
  94. package/dist/movethewheels/components/logistics-procedure/ProcedureFields.d.ts +17 -0
  95. package/dist/movethewheels/components/logistics-procedure/ProcedureHistory.d.ts +7 -0
  96. package/dist/movethewheels/components/logistics-procedure/ProcedurePolicyForm.d.ts +10 -0
  97. package/dist/movethewheels/components/logistics-procedure/ProcedurePolicyWorkbench.d.ts +5 -0
  98. package/dist/movethewheels/components/logistics-procedure/ProcedureReviewWorkbench.d.ts +5 -0
  99. package/dist/movethewheels/components/logistics-procedure/ProcedureRunWorkbench.d.ts +6 -0
  100. package/dist/movethewheels/components/logistics-procedure/ProcedureSubjectPicker.d.ts +7 -0
  101. package/dist/movethewheels/components/pending-pick/PendingPickDraft.d.ts +16 -0
  102. package/dist/movethewheels/components/pending-pick/PendingPickHistory.d.ts +5 -0
  103. package/dist/movethewheels/components/pending-pick/PickCapture.d.ts +6 -0
  104. package/dist/movethewheels/components/pending-pick/PickLineSelection.d.ts +17 -0
  105. package/dist/movethewheels/components/stock-binding/StockAssessmentDraft.d.ts +13 -0
  106. package/dist/movethewheels/components/stock-binding/StockAssessmentHistory.d.ts +18 -0
  107. package/dist/movethewheels/components/stock-binding/StockAssessmentSummary.d.ts +9 -0
  108. package/dist/movethewheels/components/stock-binding/StockFactForm.d.ts +6 -0
  109. package/dist/movethewheels/components/stock-observation/StockIssueForm.d.ts +7 -0
  110. package/dist/movethewheels/components/stock-observation/StockIssueHistory.d.ts +7 -0
  111. package/dist/movethewheels/components/stock-observation/StockIssueReadPanel.d.ts +5 -0
  112. package/dist/movethewheels/components/trip-utilization/TripReportForm.d.ts +6 -0
  113. package/dist/movethewheels/components/trip-utilization/TripReportHistory.d.ts +14 -0
  114. package/dist/movethewheels/components/trip-utilization/TripReportSummary.d.ts +5 -0
  115. package/dist/movethewheels/components/trip-utilization/TripSegmentFields.d.ts +9 -0
  116. package/dist/movethewheels/hooks/useConsolidationAction.d.ts +19 -0
  117. package/dist/movethewheels/hooks/useContainerCondition.d.ts +21 -0
  118. package/dist/movethewheels/hooks/useContainerLifecycle.d.ts +40 -0
  119. package/dist/movethewheels/hooks/useEmptyReuseAction.d.ts +14 -0
  120. package/dist/movethewheels/hooks/useFreightRecoveryAction.d.ts +23 -0
  121. package/dist/movethewheels/hooks/useProcedureAction.d.ts +18 -0
  122. package/dist/movethewheels/hooks/useProcedureSelection.d.ts +51 -0
  123. package/dist/movethewheels/hooks/useReuseRecoveryAction.d.ts +18 -0
  124. package/dist/movethewheels/pages/ConsolidationPage.d.ts +1 -0
  125. package/dist/movethewheels/pages/ContainerConditionPage.d.ts +1 -0
  126. package/dist/movethewheels/pages/ContainersPage.d.ts +2 -0
  127. package/dist/movethewheels/pages/EmptyReusePage.d.ts +1 -0
  128. package/dist/movethewheels/pages/FreeTimePage.d.ts +1 -0
  129. package/dist/movethewheels/pages/FreightEstimatePage.d.ts +1 -0
  130. package/dist/movethewheels/pages/LogisticsProceduresPage.d.ts +1 -0
  131. package/dist/movethewheels/pages/PendingPickPage.d.ts +1 -0
  132. package/dist/movethewheels/pages/StockBindingPage.d.ts +1 -0
  133. package/dist/movethewheels/pages/StockObservationsPage.d.ts +1 -0
  134. package/dist/movethewheels/pages/TripUtilizationPage.d.ts +1 -0
  135. package/dist/movethewheels/utils/consolidationHistoryTarget.d.ts +12 -0
  136. package/dist/movethewheels/utils/consolidationInput.d.ts +15 -0
  137. package/dist/movethewheels/utils/consolidationLot.d.ts +3 -0
  138. package/dist/movethewheels/utils/consolidationPins.d.ts +20 -0
  139. package/dist/movethewheels/utils/consolidationRecovery.d.ts +5 -0
  140. package/dist/movethewheels/utils/consolidationReportHead.d.ts +5 -0
  141. package/dist/movethewheels/utils/freeTimeDate.d.ts +1 -0
  142. package/dist/movethewheels/utils/freightAcknowledgement.d.ts +2 -0
  143. package/dist/movethewheels/utils/freightDraft.d.ts +36 -0
  144. package/dist/movethewheels/utils/freightRecovery.d.ts +5 -0
  145. package/dist/movethewheels/utils/graphqlClient.d.ts +2 -1
  146. package/dist/movethewheels/utils/pendingPickDraft.d.ts +8 -0
  147. package/dist/movethewheels/utils/procedureInput.d.ts +18 -0
  148. package/dist/movethewheels/utils/procedureRecovery.d.ts +5 -0
  149. package/dist/movethewheels/utils/reuseAttempt.d.ts +7 -0
  150. package/dist/movethewheels/utils/reuseForm.d.ts +6 -0
  151. package/dist/movethewheels/utils/reuseRecovery.d.ts +26 -0
  152. package/dist/movethewheels/utils/stockBindingForm.d.ts +23 -0
  153. package/dist/movethewheels/utils/stockBindingLabels.d.ts +10 -0
  154. package/dist/movethewheels/utils/stockObservationForm.d.ts +5 -0
  155. package/dist/movethewheels/utils/tripDraftContext.d.ts +25 -0
  156. package/dist/movethewheels/utils/tripUtilizationForm.d.ts +6 -0
  157. package/dist/node_modules/@react-leaflet/core/lib/component.js +5 -5
  158. package/dist/node_modules/fast-equals/dist/es/index.js +87 -74
  159. package/dist/node_modules/leaflet/dist/leaflet-src.js +8 -5
  160. package/dist/node_modules/lodash/_Stack.js +2 -1
  161. package/dist/node_modules/lucide-react/dist/esm/icons/clipboard-list.js +35 -0
  162. package/dist/node_modules/lucide-react/dist/esm/icons/repeat-2.js +22 -0
  163. package/dist/node_modules/react-leaflet/lib/MapContainer.js +3 -3
  164. package/dist/node_modules/react-smooth/es6/Animate.js +2 -2
  165. package/dist/node_modules/recharts/es6/cartesian/Area.js +13 -13
  166. package/dist/node_modules/recharts/es6/cartesian/Bar.js +9 -9
  167. package/dist/node_modules/recharts/es6/cartesian/Brush.js +12 -12
  168. package/dist/node_modules/recharts/es6/cartesian/CartesianAxis.js +7 -7
  169. package/dist/node_modules/recharts/es6/cartesian/CartesianGrid.js +13 -13
  170. package/dist/node_modules/recharts/es6/cartesian/ErrorBar.js +4 -4
  171. package/dist/node_modules/recharts/es6/cartesian/Line.js +10 -10
  172. package/dist/node_modules/recharts/es6/cartesian/ReferenceArea.js +3 -3
  173. package/dist/node_modules/recharts/es6/cartesian/ReferenceDot.js +3 -3
  174. package/dist/node_modules/recharts/es6/cartesian/ReferenceLine.js +4 -4
  175. package/dist/node_modules/recharts/es6/cartesian/XAxis.js +3 -3
  176. package/dist/node_modules/recharts/es6/cartesian/YAxis.js +3 -3
  177. package/dist/node_modules/recharts/es6/chart/AccessibilityManager.js +1 -1
  178. package/dist/node_modules/recharts/es6/chart/generateCategoricalChart.js +22 -22
  179. package/dist/node_modules/recharts/es6/component/Cursor.js +1 -1
  180. package/dist/node_modules/recharts/es6/component/DefaultLegendContent.js +11 -11
  181. package/dist/node_modules/recharts/es6/component/DefaultTooltipContent.js +6 -6
  182. package/dist/node_modules/recharts/es6/component/Label.js +14 -14
  183. package/dist/node_modules/recharts/es6/component/LabelList.js +6 -6
  184. package/dist/node_modules/recharts/es6/component/Legend.js +5 -5
  185. package/dist/node_modules/recharts/es6/component/ResponsiveContainer.js +3 -3
  186. package/dist/node_modules/recharts/es6/component/Text.js +2 -2
  187. package/dist/node_modules/recharts/es6/component/Tooltip.js +3 -3
  188. package/dist/node_modules/recharts/es6/component/TooltipBoundingBox.js +2 -2
  189. package/dist/node_modules/recharts/es6/container/Layer.js +2 -2
  190. package/dist/node_modules/recharts/es6/container/Surface.js +2 -2
  191. package/dist/node_modules/recharts/es6/context/chartLayoutContext.js +2 -2
  192. package/dist/node_modules/recharts/es6/polar/Pie.js +13 -13
  193. package/dist/node_modules/recharts/es6/polar/PolarAngleAxis.js +8 -8
  194. package/dist/node_modules/recharts/es6/polar/PolarRadiusAxis.js +6 -6
  195. package/dist/node_modules/recharts/es6/shape/Cross.js +1 -1
  196. package/dist/node_modules/recharts/es6/shape/Curve.js +1 -1
  197. package/dist/node_modules/recharts/es6/shape/Dot.js +1 -1
  198. package/dist/node_modules/recharts/es6/shape/Polygon.js +4 -4
  199. package/dist/node_modules/recharts/es6/shape/Rectangle.js +4 -4
  200. package/dist/node_modules/recharts/es6/shape/Sector.js +1 -1
  201. package/dist/node_modules/recharts/es6/shape/Symbols.js +1 -1
  202. package/dist/node_modules/recharts/es6/shape/Trapezoid.js +4 -4
  203. package/dist/node_modules/recharts/es6/util/ActiveShapeUtils.js +9 -9
  204. package/dist/node_modules/recharts/es6/util/BarUtils.js +1 -1
  205. package/dist/node_modules/recharts/es6/util/CartesianUtils.js +1 -1
  206. package/dist/node_modules/recharts/es6/util/PolarUtils.js +1 -1
  207. package/dist/node_modules/recharts/es6/util/ReactUtils.js +2 -2
  208. package/dist/node_modules/recharts/es6/util/ReduceCSSCalc.js +1 -1
  209. package/dist/node_modules/recharts/es6/util/types.js +1 -1
  210. package/dist/node_modules/{react-is → recharts/node_modules/react-is}/cjs/react-is.development.js +2 -2
  211. package/dist/node_modules/{react-is → recharts/node_modules/react-is}/cjs/react-is.production.min.js +2 -2
  212. package/dist/node_modules/{react-is → recharts/node_modules/react-is}/index.js +2 -2
  213. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +97 -18
  214. package/dist/node_modules/zustand/esm/middleware.js +2 -2
  215. package/dist/pages/ConsolidationPage.js +76 -0
  216. package/dist/pages/ContainerConditionPage.js +972 -0
  217. package/dist/pages/ContainersPage.js +522 -0
  218. package/dist/pages/EmptyReusePage.js +777 -0
  219. package/dist/pages/FreeTimePage.js +657 -0
  220. package/dist/pages/FreightEstimatePage.js +284 -0
  221. package/dist/pages/LogisticsProceduresPage.js +100 -0
  222. package/dist/pages/PendingPickPage.js +155 -0
  223. package/dist/pages/StockBindingPage.js +236 -0
  224. package/dist/pages/StockObservationsPage.js +168 -0
  225. package/dist/pages/TripUtilizationPage.js +227 -0
  226. package/dist/src/generated/consolidation-operations.js +505 -0
  227. package/dist/src/generated/container-condition-operations.js +208 -0
  228. package/dist/src/generated/container-operations.js +101 -0
  229. package/dist/src/generated/empty-reuse-operations.js +749 -0
  230. package/dist/src/generated/free-time-operations.js +235 -0
  231. package/dist/src/generated/freight-cost-operations.js +325 -0
  232. package/dist/src/generated/logistics-procedure-operations.js +362 -0
  233. package/dist/src/generated/pending-pick-operations.js +1128 -0
  234. package/dist/src/generated/stock-binding-operations.js +175 -0
  235. package/dist/src/generated/stock-observation-operations.js +93 -0
  236. package/dist/src/generated/trip-utilization-operations.js +140 -0
  237. package/dist/src/generated/wspace-operations.js +708 -0
  238. package/dist/utils/consolidationHistoryTarget.js +27 -0
  239. package/dist/utils/consolidationInput.js +21 -0
  240. package/dist/utils/consolidationLot.js +29 -0
  241. package/dist/utils/consolidationPins.js +13 -0
  242. package/dist/utils/consolidationRecovery.js +40 -0
  243. package/dist/utils/consolidationReportHead.js +18 -0
  244. package/dist/utils/freeTimeDate.js +26 -0
  245. package/dist/utils/freightAcknowledgement.js +8 -0
  246. package/dist/utils/freightDraft.js +125 -0
  247. package/dist/utils/freightRecovery.js +36 -0
  248. package/dist/utils/graphqlClient.js +28 -28
  249. package/dist/utils/pendingPickDraft.js +46 -0
  250. package/dist/utils/procedureInput.js +43 -0
  251. package/dist/utils/procedureRecovery.js +42 -0
  252. package/dist/utils/reuseAttempt.js +20 -0
  253. package/dist/utils/reuseForm.js +25 -0
  254. package/dist/utils/reuseRecovery.js +71 -0
  255. package/dist/utils/stockBindingForm.js +142 -0
  256. package/dist/utils/stockBindingLabels.js +23 -0
  257. package/dist/utils/stockObservationForm.js +55 -0
  258. package/dist/utils/tripDraftContext.js +19 -0
  259. package/dist/utils/tripUtilizationForm.js +60 -0
  260. package/package.json +19 -5
  261. package/src/generated/consolidation-operations.ts +1138 -0
  262. package/src/generated/container-condition-operations.ts +771 -0
  263. package/src/generated/container-operations.ts +376 -0
  264. package/src/generated/empty-reuse-operations.ts +1648 -0
  265. package/src/generated/free-time-operations.ts +814 -0
  266. package/src/generated/freight-cost-operations.ts +753 -0
  267. package/src/generated/logistics-procedure-operations.ts +1047 -0
  268. package/src/generated/pending-pick-operations.ts +1508 -0
  269. package/src/generated/stock-binding-operations.ts +631 -0
  270. package/src/generated/stock-observation-operations.ts +373 -0
  271. package/src/generated/trip-utilization-operations.ts +500 -0
  272. package/src/generated/wspace-operations.ts +116 -0
  273. package/src/movethewheels/MoveTheWheelsRoot.tsx +79 -0
  274. package/src/movethewheels/MoveTheWheelsRoutes.tsx +22 -0
  275. package/src/movethewheels/components/ContainerEvidencePicker.tsx +146 -0
  276. package/src/movethewheels/components/FreeTimeAgreementForm.tsx +483 -0
  277. package/src/movethewheels/components/ReturnInstructionForm.tsx +102 -0
  278. package/src/movethewheels/components/ReuseControls.tsx +138 -0
  279. package/src/movethewheels/components/ReusePermissionForm.tsx +123 -0
  280. package/src/movethewheels/components/ReuseProposalForm.tsx +484 -0
  281. package/src/movethewheels/components/ReuseSourceFields.tsx +80 -0
  282. package/src/movethewheels/components/consolidation/ConsolidationHistory.tsx +159 -0
  283. package/src/movethewheels/components/consolidation/ConsolidationLotEditor.tsx +144 -0
  284. package/src/movethewheels/components/consolidation/ConsolidationManifestWorkbench.tsx +168 -0
  285. package/src/movethewheels/components/consolidation/ConsolidationPlanForm.tsx +185 -0
  286. package/src/movethewheels/components/consolidation/ConsolidationPlanWorkbench.tsx +395 -0
  287. package/src/movethewheels/components/consolidation/ConsolidationReportForm.tsx +124 -0
  288. package/src/movethewheels/components/consolidation/ConsolidationReportsWorkbench.tsx +233 -0
  289. package/src/movethewheels/components/consolidation/ConsolidationSummary.tsx +84 -0
  290. package/src/movethewheels/components/consolidation/OriginalConsolidationHistory.tsx +133 -0
  291. package/src/movethewheels/components/freight-cost/FreightDraftForm.tsx +224 -0
  292. package/src/movethewheels/components/freight-cost/FreightFields.tsx +91 -0
  293. package/src/movethewheels/components/freight-cost/FreightFxEditor.tsx +98 -0
  294. package/src/movethewheels/components/freight-cost/FreightHistory.tsx +91 -0
  295. package/src/movethewheels/components/freight-cost/FreightLineEditor.tsx +192 -0
  296. package/src/movethewheels/components/freight-cost/FreightScopeEditor.tsx +64 -0
  297. package/src/movethewheels/components/freight-cost/FreightTotals.tsx +68 -0
  298. package/src/movethewheels/components/logistics-procedure/ProcedureDecisionForm.tsx +204 -0
  299. package/src/movethewheels/components/logistics-procedure/ProcedureFields.tsx +43 -0
  300. package/src/movethewheels/components/logistics-procedure/ProcedureHistory.tsx +102 -0
  301. package/src/movethewheels/components/logistics-procedure/ProcedurePolicyForm.tsx +226 -0
  302. package/src/movethewheels/components/logistics-procedure/ProcedurePolicyWorkbench.tsx +174 -0
  303. package/src/movethewheels/components/logistics-procedure/ProcedureReviewWorkbench.tsx +278 -0
  304. package/src/movethewheels/components/logistics-procedure/ProcedureRunWorkbench.tsx +292 -0
  305. package/src/movethewheels/components/logistics-procedure/ProcedureSubjectPicker.tsx +111 -0
  306. package/src/movethewheels/components/pending-pick/PendingPickDraft.tsx +82 -0
  307. package/src/movethewheels/components/pending-pick/PendingPickHistory.tsx +93 -0
  308. package/src/movethewheels/components/pending-pick/PickCapture.tsx +70 -0
  309. package/src/movethewheels/components/pending-pick/PickLineSelection.tsx +130 -0
  310. package/src/movethewheels/components/stock-binding/StockAssessmentDraft.tsx +52 -0
  311. package/src/movethewheels/components/stock-binding/StockAssessmentHistory.tsx +56 -0
  312. package/src/movethewheels/components/stock-binding/StockAssessmentSummary.tsx +108 -0
  313. package/src/movethewheels/components/stock-binding/StockFactForm.tsx +186 -0
  314. package/src/movethewheels/components/stock-observation/StockIssueForm.tsx +103 -0
  315. package/src/movethewheels/components/stock-observation/StockIssueHistory.tsx +96 -0
  316. package/src/movethewheels/components/stock-observation/StockIssueReadPanel.tsx +72 -0
  317. package/src/movethewheels/components/trip-utilization/TripReportForm.tsx +116 -0
  318. package/src/movethewheels/components/trip-utilization/TripReportHistory.tsx +51 -0
  319. package/src/movethewheels/components/trip-utilization/TripReportSummary.tsx +127 -0
  320. package/src/movethewheels/components/trip-utilization/TripSegmentFields.tsx +118 -0
  321. package/src/movethewheels/hooks/useConsolidationAction.ts +196 -0
  322. package/src/movethewheels/hooks/useContainerCondition.ts +129 -0
  323. package/src/movethewheels/hooks/useContainerLifecycle.ts +291 -0
  324. package/src/movethewheels/hooks/useEmptyReuseAction.ts +72 -0
  325. package/src/movethewheels/hooks/useFreightRecoveryAction.ts +201 -0
  326. package/src/movethewheels/hooks/useProcedureAction.ts +196 -0
  327. package/src/movethewheels/hooks/useProcedureSelection.ts +75 -0
  328. package/src/movethewheels/hooks/useReuseRecoveryAction.ts +192 -0
  329. package/src/movethewheels/pages/ConsolidationPage.tsx +70 -0
  330. package/src/movethewheels/pages/ContainerConditionPage.tsx +959 -0
  331. package/src/movethewheels/pages/ContainersPage.tsx +490 -0
  332. package/src/movethewheels/pages/EmptyReusePage.tsx +823 -0
  333. package/src/movethewheels/pages/FreeTimePage.tsx +720 -0
  334. package/src/movethewheels/pages/FreightEstimatePage.tsx +353 -0
  335. package/src/movethewheels/pages/LogisticsProceduresPage.tsx +86 -0
  336. package/src/movethewheels/pages/PendingPickPage.tsx +226 -0
  337. package/src/movethewheels/pages/StockBindingPage.tsx +299 -0
  338. package/src/movethewheels/pages/StockObservationsPage.tsx +181 -0
  339. package/src/movethewheels/pages/TripUtilizationPage.tsx +315 -0
  340. package/src/movethewheels/utils/consolidationHistoryTarget.ts +39 -0
  341. package/src/movethewheels/utils/consolidationInput.ts +70 -0
  342. package/src/movethewheels/utils/consolidationLot.ts +24 -0
  343. package/src/movethewheels/utils/consolidationPins.ts +52 -0
  344. package/src/movethewheels/utils/consolidationRecovery.ts +88 -0
  345. package/src/movethewheels/utils/consolidationReportHead.ts +29 -0
  346. package/src/movethewheels/utils/freeTimeDate.ts +31 -0
  347. package/src/movethewheels/utils/freightAcknowledgement.ts +31 -0
  348. package/src/movethewheels/utils/freightDraft.ts +170 -0
  349. package/src/movethewheels/utils/freightRecovery.ts +79 -0
  350. package/src/movethewheels/utils/graphqlClient.ts +14 -5
  351. package/src/movethewheels/utils/pendingPickDraft.ts +61 -0
  352. package/src/movethewheels/utils/procedureInput.ts +98 -0
  353. package/src/movethewheels/utils/procedureRecovery.ts +92 -0
  354. package/src/movethewheels/utils/reuseAttempt.ts +29 -0
  355. package/src/movethewheels/utils/reuseForm.ts +30 -0
  356. package/src/movethewheels/utils/reuseRecovery.ts +151 -0
  357. package/src/movethewheels/utils/stockBindingForm.ts +209 -0
  358. package/src/movethewheels/utils/stockBindingLabels.ts +41 -0
  359. package/src/movethewheels/utils/stockObservationForm.ts +73 -0
  360. package/src/movethewheels/utils/tripDraftContext.ts +61 -0
  361. package/src/movethewheels/utils/tripUtilizationForm.ts +105 -0
  362. package/src/operations/condition/container-condition.graphql +41 -0
  363. package/src/operations/consolidation/consolidation.graphql +490 -0
  364. package/src/operations/container/container-lifecycle.graphql +80 -0
  365. package/src/operations/empty-reuse/empty-reuse.graphql +737 -0
  366. package/src/operations/free-time/free-time.graphql +47 -0
  367. package/src/operations/freight-cost/freight.graphql +6 -0
  368. package/src/operations/logistics-procedure/procedure.graphql +15 -0
  369. package/src/operations/pending-pick/pending-pick.graphql +1122 -0
  370. package/src/operations/stock-binding/stock-binding.graphql +160 -0
  371. package/src/operations/stock-observation/stock-observation.graphql +20 -0
  372. package/src/operations/trip-utilization/trip-utilization.graphql +126 -0
  373. package/src/operations/wspace/container-evidence.graphql +6 -0
@@ -0,0 +1,170 @@
1
+ import type {
2
+ MtwFreightFactsInput,
3
+ MtwFreightLineInput,
4
+ MtwFreightFxInput,
5
+ SaveMtwFreightEstimateInput,
6
+ } from '../../generated/freight-cost-operations';
7
+ export const freightCategories = [
8
+ 'BASE_FREIGHT',
9
+ 'FUEL',
10
+ 'PRE_CARRIAGE',
11
+ 'ON_CARRIAGE',
12
+ 'ORIGIN_HANDLING',
13
+ 'DESTINATION_HANDLING',
14
+ 'INSURANCE',
15
+ 'ACCESSORIAL',
16
+ 'TAX_ESTIMATE',
17
+ 'DUTY_ESTIMATE',
18
+ 'BROKER',
19
+ 'FREE_TIME_EXPOSURE',
20
+ 'OTHER',
21
+ ] as const;
22
+ export const freightLabel = (value: string): string =>
23
+ value
24
+ .toLowerCase()
25
+ .replaceAll('_', ' ')
26
+ .replace(/^./, (c) => c.toUpperCase());
27
+ export const freightNullable = (value: string): string | null => value.trim() || null;
28
+ /** Money never passes through Number; sourced fixed amounts must fit the declared scale exactly. */
29
+ export function fixedFreightMinor(value: string, digits: number): string | null {
30
+ if (!value.trim()) return null;
31
+ if (
32
+ !/^(0|[1-9][0-9]{0,19})(\.[0-9]+)?$/.test(value) ||
33
+ !Number.isInteger(digits) ||
34
+ digits < 0 ||
35
+ digits > 4
36
+ )
37
+ throw new Error('Use a nonnegative decimal amount in the stated currency convention.');
38
+ const [whole, fraction = ''] = value.split('.');
39
+ if (fraction.length > digits)
40
+ throw new Error(
41
+ 'The sourced amount has more decimal places than the recorded currency convention.'
42
+ );
43
+ return (
44
+ BigInt(whole) * 10n ** BigInt(digits) +
45
+ BigInt(fraction.padEnd(digits, '0') || '0')
46
+ ).toString();
47
+ }
48
+ /** Match supported decimal zero spellings without rounding or accepting invalid quantities. */
49
+ export function isFreightDecimalZero(value: string | null | undefined): boolean {
50
+ return (
51
+ typeof value === 'string' &&
52
+ /^(0|[1-9][0-9]{0,19})(\.[0-9]{1,18})?$/.test(value) &&
53
+ BigInt(value.replace('.', '')) === 0n
54
+ );
55
+ }
56
+ export function freightMoney(minor: string | null | undefined, digits: number): string {
57
+ if (minor === null || minor === undefined) return 'Unknown';
58
+ const value = BigInt(minor)
59
+ .toString()
60
+ .padStart(digits + 1, '0');
61
+ return digits ? `${value.slice(0, -digits)}.${value.slice(-digits)}` : value;
62
+ }
63
+ export function freightInstant(value: string): string {
64
+ const date = new Date(value);
65
+ if (!value || !Number.isFinite(date.getTime())) throw new Error('Choose a valid date and time.');
66
+ const result = date.toISOString();
67
+ if (!/^[0-9]{4}-/.test(result)) throw new Error('Use a four-digit year.');
68
+ return result;
69
+ }
70
+ export function freightLocalTime(value: string): string {
71
+ const date = new Date(value);
72
+ return new Date(date.getTime() - date.getTimezoneOffset() * 60000).toISOString().slice(0, 19);
73
+ }
74
+ export function newFreightLine(): MtwFreightLineInput {
75
+ return {
76
+ id: crypto.randomUUID(),
77
+ category: 'BASE_FREIGHT',
78
+ description: 'Base freight',
79
+ payerReference: null,
80
+ payerLabel: null,
81
+ disposition: 'UNKNOWN',
82
+ inclusionParentLineId: null,
83
+ currency: { code: 'USD', minorUnitDigits: 2 },
84
+ amountBasis: 'UNKNOWN',
85
+ quantity: null,
86
+ unit: null,
87
+ unitRateMajor: null,
88
+ amountMinor: null,
89
+ zeroReason: null,
90
+ sourceReference: null,
91
+ sourceRevision: null,
92
+ };
93
+ }
94
+ export function newFreightFacts(): MtwFreightFactsInput {
95
+ return {
96
+ kind: 'ESTIMATE',
97
+ title: 'Freight cost estimate',
98
+ commercialScope: '',
99
+ sourceReference: '',
100
+ sourceRevision: '',
101
+ pricingAt: new Date().toISOString(),
102
+ quotedAt: null,
103
+ validFrom: null,
104
+ validUntil: null,
105
+ reportingCurrency: null,
106
+ rounding: 'HALF_UP_LINE',
107
+ lines: [newFreightLine()],
108
+ requirements: freightCategories.map((category) => ({
109
+ category,
110
+ status: 'UNKNOWN',
111
+ reason: null,
112
+ sourceReference: null,
113
+ sourceRevision: null,
114
+ })),
115
+ fx: [],
116
+ };
117
+ }
118
+ export function newFreightFx(): MtwFreightFxInput {
119
+ const now = new Date().toISOString();
120
+ return {
121
+ fromCurrency: { code: 'USD', minorUnitDigits: 2 },
122
+ toCurrency: { code: 'EUR', minorUnitDigits: 2 },
123
+ rate: '',
124
+ observedAt: now,
125
+ effectiveFrom: now,
126
+ effectiveUntil: now,
127
+ sourceReference: '',
128
+ sourceRevision: '',
129
+ };
130
+ }
131
+ export interface FreightDraftPin {
132
+ shipmentId: string;
133
+ shipmentUpdatedAt: string;
134
+ estimateReference: string;
135
+ previousId: string | null;
136
+ version: number;
137
+ }
138
+ export function freightPinMatches(
139
+ pin: FreightDraftPin,
140
+ shipment: { id: string; updatedAt: string } | null | undefined,
141
+ latest: { id: string; version: number } | null
142
+ ): boolean {
143
+ return (
144
+ shipment?.id === pin.shipmentId &&
145
+ shipment.updatedAt === pin.shipmentUpdatedAt &&
146
+ (latest?.id ?? null) === pin.previousId &&
147
+ (latest?.version ?? 0) === pin.version
148
+ );
149
+ }
150
+ export function freightSaveInput(
151
+ pin: FreightDraftPin,
152
+ shipment: { id: string; updatedAt: string } | null | undefined,
153
+ latest: { id: string; version: number } | null,
154
+ facts: MtwFreightFactsInput,
155
+ evidence: SaveMtwFreightEstimateInput['evidence']
156
+ ): Omit<SaveMtwFreightEstimateInput, 'idempotencyKey'> {
157
+ if (!freightPinMatches(pin, shipment, latest))
158
+ throw new Error(
159
+ 'The shipment or cost history changed. Refresh and review before starting a new draft.'
160
+ );
161
+ return {
162
+ shipmentId: pin.shipmentId,
163
+ estimateReference: pin.estimateReference,
164
+ expectedShipmentUpdatedAt: pin.shipmentUpdatedAt,
165
+ expectedPreviousVersionId: pin.previousId,
166
+ expectedVersion: pin.version,
167
+ facts: structuredClone(facts),
168
+ evidence: structuredClone(evidence),
169
+ };
170
+ }
@@ -0,0 +1,79 @@
1
+ import { print } from 'graphql';
2
+ import { SaveFreightCostsDocument } from '../../generated/freight-cost-operations';
3
+ import type { ReuseRecovery } from './reuseRecovery';
4
+ export const FREIGHT_RECOVERY_STORAGE = 'movethewheels.freight.unresolved.v1';
5
+ export function decodeFreightRecovery(raw: string | null): ReuseRecovery | null {
6
+ if (!raw || new TextEncoder().encode(raw).byteLength > 200000) return null;
7
+ try {
8
+ const value: unknown = JSON.parse(raw);
9
+ if (
10
+ typeof value !== 'object' ||
11
+ value === null ||
12
+ !('version' in value) ||
13
+ value.version !== 1 ||
14
+ !('scope' in value) ||
15
+ !('input' in value) ||
16
+ !('operation' in value) ||
17
+ value.operation !== print(SaveFreightCostsDocument) ||
18
+ !('key' in value) ||
19
+ typeof value.key !== 'string' ||
20
+ !value.key ||
21
+ value.key.length > 200 ||
22
+ !('success' in value) ||
23
+ typeof value.success !== 'string' ||
24
+ value.success.length > 500
25
+ )
26
+ return null;
27
+ if (
28
+ typeof value.input !== 'object' ||
29
+ value.input === null ||
30
+ Array.isArray(value.input) ||
31
+ typeof value.scope !== 'object' ||
32
+ value.scope === null
33
+ )
34
+ return null;
35
+ const scope = value.scope;
36
+ if (
37
+ !('actorId' in scope) ||
38
+ typeof scope.actorId !== 'string' ||
39
+ !scope.actorId ||
40
+ !('workspaceId' in scope) ||
41
+ typeof scope.workspaceId !== 'string' ||
42
+ !scope.workspaceId ||
43
+ !('tenantId' in scope) ||
44
+ typeof scope.tenantId !== 'string' ||
45
+ !('organizationId' in scope) ||
46
+ typeof scope.organizationId !== 'string' ||
47
+ !scope.organizationId ||
48
+ !('gateway' in scope) ||
49
+ typeof scope.gateway !== 'string' ||
50
+ !('projectId' in scope) ||
51
+ (scope.projectId !== null && typeof scope.projectId !== 'string')
52
+ )
53
+ return null;
54
+ return {
55
+ version: 1,
56
+ scope: {
57
+ actorId: scope.actorId,
58
+ workspaceId: scope.workspaceId,
59
+ tenantId: scope.tenantId,
60
+ organizationId: scope.organizationId,
61
+ gateway: scope.gateway,
62
+ projectId: scope.projectId,
63
+ },
64
+ operation: value.operation,
65
+ // The owning document is exact and input is an object; field authority remains backend-validated.
66
+ input: structuredClone(value.input) as Record<string, unknown>,
67
+ key: value.key,
68
+ success: value.success,
69
+ };
70
+ } catch {
71
+ return null;
72
+ }
73
+ }
74
+ export function encodeFreightRecovery(attempt: ReuseRecovery): string {
75
+ const raw = JSON.stringify(attempt);
76
+ if (!decodeFreightRecovery(raw))
77
+ throw new Error('Cannot safely retain this freight request. Nothing was sent.');
78
+ return raw;
79
+ }
@@ -1,3 +1,5 @@
1
+ export type GraphQLAttemptPolicy = 'RETRY_TRANSIENT' | 'SINGLE_ATTEMPT';
2
+
1
3
  interface GraphQLRequestOptions {
2
4
  apiGatewayUrl?: string;
3
5
  authToken?: string;
@@ -106,7 +108,8 @@ function releaseSlot(): void {
106
108
  export async function executeGraphQL<TData>(
107
109
  options: GraphQLRequestOptions,
108
110
  query: string,
109
- variables?: Record<string, unknown>
111
+ variables?: Record<string, unknown>,
112
+ attemptPolicy: GraphQLAttemptPolicy = 'RETRY_TRANSIENT'
110
113
  ): Promise<TData> {
111
114
  const url = resolveGraphqlUrl(options.apiGatewayUrl);
112
115
  const headers: Record<string, string> = {
@@ -126,7 +129,12 @@ export async function executeGraphQL<TData>(
126
129
  // and always release the slot when this call settles (success or failure).
127
130
  await acquireSlot();
128
131
  try {
129
- return await runWithRetries<TData>(url, headers, body);
132
+ return await runWithRetries<TData>(
133
+ url,
134
+ headers,
135
+ body,
136
+ attemptPolicy === 'SINGLE_ATTEMPT' ? 0 : MAX_RETRIES
137
+ );
130
138
  } finally {
131
139
  releaseSlot();
132
140
  }
@@ -148,12 +156,13 @@ async function readGraphqlErrorMessage(response: Response): Promise<string | nul
148
156
  async function runWithRetries<TData>(
149
157
  url: string,
150
158
  headers: Record<string, string>,
151
- body: string
159
+ body: string,
160
+ retries: number
152
161
  ): Promise<TData> {
153
162
  let lastError: Error = new Error('GraphQL request failed');
154
163
 
155
- for (let attempt = 0; attempt <= MAX_RETRIES; attempt += 1) {
156
- const canRetry = attempt < MAX_RETRIES;
164
+ for (let attempt = 0; attempt <= retries; attempt += 1) {
165
+ const canRetry = attempt < retries;
157
166
  // Exponential backoff with jitter before each retry (not the first attempt).
158
167
  if (attempt > 0)
159
168
  await sleep(Math.min(250 * 2 ** (attempt - 1), 2000) + Math.floor(Math.random() * 150));
@@ -0,0 +1,61 @@
1
+ import type {
2
+ CreateMtwPickTaskIntentInput,
3
+ MtwPickIntentLinePinInput,
4
+ PickLineFragment,
5
+ PickPreparationQuery,
6
+ } from '../../generated/pending-pick-operations';
7
+
8
+ type Context = PickPreparationQuery['mtwPickPreparation'];
9
+ export type PendingPickInput = Omit<CreateMtwPickTaskIntentInput, 'idempotencyKey'>;
10
+ function pin(line: PickLineFragment): MtwPickIntentLinePinInput {
11
+ return {
12
+ inventoryItemId: line.inventoryItemId,
13
+ expectedCargoItemId: line.cargoItemId,
14
+ expectedWarehouseId: line.warehouseId,
15
+ expectedLocationId: line.locationId,
16
+ expectedInventoryUpdatedAt: line.inventoryUpdatedAt,
17
+ expectedCargoUpdatedAt: line.cargoUpdatedAt,
18
+ expectedWarehouseUpdatedAt: line.warehouseUpdatedAt,
19
+ expectedLocationUpdatedAt: line.locationUpdatedAt,
20
+ expectedCompositionEpoch: line.compositionEpoch,
21
+ expectedRecordedAssessmentId: line.recordedProfile?.id ?? null,
22
+ expectedApplicableAssessmentId: line.applicableProfile?.id ?? null,
23
+ expectedObservationSequence: line.observationSequence,
24
+ };
25
+ }
26
+ export function pendingContextSignature(context: Context): string {
27
+ return JSON.stringify(
28
+ ['source', 'destination'].map((side) => {
29
+ const line = side === 'source' ? context.source : context.destination;
30
+ return { pin: pin(line), issues: line.unresolvedObservationIds, gaps: line.reviewGaps };
31
+ })
32
+ );
33
+ }
34
+ export function pendingPickInput(
35
+ context: Context,
36
+ count: string,
37
+ reason: string
38
+ ): PendingPickInput {
39
+ const requestedQuantity = Number(count);
40
+ if (
41
+ !/^[1-9]\d*$/.test(count) ||
42
+ !Number.isSafeInteger(requestedQuantity) ||
43
+ requestedQuantity > 2147483647
44
+ )
45
+ throw new Error('Enter a positive whole count up to 2147483647.');
46
+ const note = reason.trim();
47
+ if (!note || note.length > 1000) throw new Error('Enter a reason up to 1000 characters.');
48
+ const source = pin(context.source),
49
+ destination = pin(context.destination);
50
+ if (
51
+ source.inventoryItemId === destination.inventoryItemId ||
52
+ source.expectedLocationId === destination.expectedLocationId ||
53
+ source.expectedWarehouseId !== destination.expectedWarehouseId ||
54
+ source.expectedCargoItemId !== destination.expectedCargoItemId
55
+ )
56
+ throw new Error('Choose two distinct bins for the same cargo and warehouse.');
57
+ return { source, destination, requestedQuantity, note };
58
+ }
59
+ export function pendingPickMatches(draftSignature: string, current: Context): boolean {
60
+ return draftSignature === pendingContextSignature(current);
61
+ }
@@ -0,0 +1,98 @@
1
+ import type {
2
+ MtwProcedureScopeInput,
3
+ MtwProcedureStep,
4
+ } from '../../generated/logistics-procedure-operations';
5
+ export const procedureSteps: readonly MtwProcedureStep[] = [
6
+ 'RETURN_INSTRUCTION_REVIEW',
7
+ 'CONDITION_HOLDS_REVIEW',
8
+ 'BOOKING_ROAD_RETURN_REVIEW',
9
+ ];
10
+ export const stepLabel: Record<MtwProcedureStep, string> = {
11
+ RETURN_INSTRUCTION_REVIEW: 'Return instruction',
12
+ CONDITION_HOLDS_REVIEW: 'Condition and holds',
13
+ BOOKING_ROAD_RETURN_REVIEW: 'Booking, road access and retained return',
14
+ };
15
+ export function object(value: unknown): value is Record<string, unknown> {
16
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
17
+ }
18
+ export function procedureAcknowledgement(
19
+ result: Record<string, unknown>,
20
+ input: Record<string, unknown>,
21
+ actorId?: string
22
+ ): boolean {
23
+ const field =
24
+ 'templateReference' in input
25
+ ? 'publishMtwProcedureVersion'
26
+ : 'expectedCycleVersion' in input
27
+ ? 'startMtwProcedureExecution'
28
+ : input.stepDecisionId
29
+ ? input.kind
30
+ ? 'recordMtwProcedureDeviation'
31
+ : 'revokeMtwProcedureDeviation'
32
+ : 'recordMtwProcedureStep';
33
+ const row = result[field];
34
+ if (!object(row) || typeof row.id !== 'string' || !row.id) return false;
35
+ if ('expectedCycleVersion' in input)
36
+ return (
37
+ row.executorActorId === actorId &&
38
+ row.proposalId === input.proposalId &&
39
+ row.procedureVersionId === input.procedureVersionId &&
40
+ object(row.subject) &&
41
+ row.subject.cycleVersion === input.expectedCycleVersion &&
42
+ row.subject.proposalRevision === input.expectedProposalRevision
43
+ );
44
+ if (typeof input.expectedVersion !== 'number' || row.version !== input.expectedVersion + 1)
45
+ return false;
46
+ if ('templateReference' in input)
47
+ return (
48
+ row.templateReference === input.templateReference &&
49
+ row.previousVersionId === input.expectedPreviousId &&
50
+ row.kind === input.kind
51
+ );
52
+ return (
53
+ row.executionId === input.executionId &&
54
+ (input.stepDecisionId
55
+ ? row.stepDecisionId === input.stepDecisionId &&
56
+ row.previousDeviationId === input.expectedPreviousId
57
+ : row.step === input.step && row.previousDecisionId === input.expectedPreviousId) &&
58
+ row.kind === (input.kind ?? 'REVOKED')
59
+ );
60
+ }
61
+ /** Local input never supplies readiness, actor identity, execution or custody facts. */
62
+ export function localProcedureInstant(value: string): string {
63
+ if (!/^\d{4}-\d\d-\d\dT\d\d:\d\d(?::\d\d(?:\.\d{1,3})?)?$/.test(value))
64
+ throw new Error('Enter a complete local date and time.');
65
+ const date = new Date(value);
66
+ if (!Number.isFinite(date.valueOf())) throw new Error('Enter a valid date and time.');
67
+ const pad = (v: number) => String(v).padStart(2, '0');
68
+ const local = `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
69
+ if (local !== value.slice(0, 16))
70
+ throw new Error('This local time is invalid or skipped by daylight saving.');
71
+ return date.toISOString();
72
+ }
73
+ export function scopeInput(
74
+ scope: Omit<MtwProcedureScopeInput, 'declaredJurisdictions'> & { declaredJurisdictions: string[] }
75
+ ): MtwProcedureScopeInput {
76
+ if (
77
+ scope.declaredJurisdictions.length < 1 ||
78
+ scope.declaredJurisdictions.length > 10 ||
79
+ new Set(scope.declaredJurisdictions).size !== scope.declaredJurisdictions.length
80
+ )
81
+ throw new Error('Enter one to ten distinct jurisdiction references.');
82
+ return {
83
+ handoffLocationReference: scope.handoffLocationReference,
84
+ equipmentType: scope.equipmentType,
85
+ cargoCategory: scope.cargoCategory,
86
+ equipmentOwnerReference: scope.equipmentOwnerReference,
87
+ declaredLaneReference: scope.declaredLaneReference,
88
+ declaredJurisdictions: [...scope.declaredJurisdictions],
89
+ sourceReference: scope.sourceReference,
90
+ sourceRevision: scope.sourceRevision,
91
+ };
92
+ }
93
+ export function chainMatches(
94
+ pin: { id: string; version: number } | null,
95
+ current: { id: string; version: number } | null
96
+ ): boolean {
97
+ return pin?.id === current?.id && pin?.version === current?.version;
98
+ }
@@ -0,0 +1,92 @@
1
+ import { print } from 'graphql';
2
+ import {
3
+ PublishProcedureDocument,
4
+ StartProcedureDocument,
5
+ RecordProcedureStepDocument,
6
+ RecordProcedureDeviationDocument,
7
+ RevokeProcedureDeviationDocument,
8
+ } from '../../generated/logistics-procedure-operations';
9
+ import type { ReuseRecovery } from './reuseRecovery';
10
+ export const PROCEDURE_RECOVERY_STORAGE = 'movethewheels.procedure.unresolved.v1';
11
+ export function decodeProcedureRecovery(raw: string | null): ReuseRecovery | null {
12
+ if (!raw || new TextEncoder().encode(raw).byteLength > 200000) return null;
13
+ try {
14
+ const value: unknown = JSON.parse(raw);
15
+ if (
16
+ typeof value !== 'object' ||
17
+ value === null ||
18
+ !('version' in value) ||
19
+ value.version !== 1 ||
20
+ !('scope' in value) ||
21
+ !('input' in value) ||
22
+ !('operation' in value) ||
23
+ typeof value.operation !== 'string' ||
24
+ ![
25
+ PublishProcedureDocument,
26
+ StartProcedureDocument,
27
+ RecordProcedureStepDocument,
28
+ RecordProcedureDeviationDocument,
29
+ RevokeProcedureDeviationDocument,
30
+ ].some((item) => print(item) === value.operation) ||
31
+ !('key' in value) ||
32
+ typeof value.key !== 'string' ||
33
+ !value.key ||
34
+ value.key.length > 200 ||
35
+ !('success' in value) ||
36
+ typeof value.success !== 'string' ||
37
+ value.success.length > 500
38
+ )
39
+ return null;
40
+ if (
41
+ typeof value.input !== 'object' ||
42
+ value.input === null ||
43
+ Array.isArray(value.input) ||
44
+ typeof value.scope !== 'object' ||
45
+ value.scope === null
46
+ )
47
+ return null;
48
+ const scope = value.scope;
49
+ if (
50
+ !('actorId' in scope) ||
51
+ typeof scope.actorId !== 'string' ||
52
+ !scope.actorId ||
53
+ !('workspaceId' in scope) ||
54
+ typeof scope.workspaceId !== 'string' ||
55
+ !scope.workspaceId ||
56
+ !('tenantId' in scope) ||
57
+ typeof scope.tenantId !== 'string' ||
58
+ !('organizationId' in scope) ||
59
+ typeof scope.organizationId !== 'string' ||
60
+ !scope.organizationId ||
61
+ !('gateway' in scope) ||
62
+ typeof scope.gateway !== 'string' ||
63
+ !('projectId' in scope) ||
64
+ (scope.projectId !== null && typeof scope.projectId !== 'string')
65
+ )
66
+ return null;
67
+ return {
68
+ version: 1,
69
+ scope: {
70
+ actorId: scope.actorId,
71
+ workspaceId: scope.workspaceId,
72
+ tenantId: scope.tenantId,
73
+ organizationId: scope.organizationId,
74
+ gateway: scope.gateway,
75
+ projectId: scope.projectId,
76
+ },
77
+ operation: value.operation,
78
+ // The owning document is exact and input is an object; field authority remains backend-validated.
79
+ input: structuredClone(value.input) as Record<string, unknown>,
80
+ key: value.key,
81
+ success: value.success,
82
+ };
83
+ } catch {
84
+ return null;
85
+ }
86
+ }
87
+ export function encodeProcedureRecovery(attempt: ReuseRecovery): string {
88
+ const raw = JSON.stringify(attempt);
89
+ if (!decodeProcedureRecovery(raw))
90
+ throw new Error('Cannot safely retain this procedure request. Nothing was sent.');
91
+ return raw;
92
+ }
@@ -0,0 +1,29 @@
1
+ /** Stores one submitted intent. Reads may refresh versions without changing an uncertain retry. */
2
+ export interface ReuseAttempt {
3
+ fingerprint: string;
4
+ input: Record<string, unknown>;
5
+ key: string;
6
+ }
7
+ export function reuseAttempt(
8
+ previous: ReuseAttempt | null,
9
+ operation: string,
10
+ input: Record<string, unknown>,
11
+ createKey: () => string
12
+ ): ReuseAttempt {
13
+ const intent = Object.fromEntries(
14
+ Object.entries(input).filter(
15
+ ([name]) =>
16
+ ![
17
+ 'expectedVersion',
18
+ 'expectedCycleVersion',
19
+ 'expectedProposalRevision',
20
+ 'expectedRouteUpdatedAt',
21
+ 'expectedVehicleUpdatedAt',
22
+ ].includes(name)
23
+ )
24
+ );
25
+ const fingerprint = JSON.stringify({ operation, input: intent });
26
+ return previous?.fingerprint === fingerprint
27
+ ? previous
28
+ : { fingerprint, input: structuredClone(input), key: createKey() };
29
+ }
@@ -0,0 +1,30 @@
1
+ import type { MtwReuseSourceAttestationInput } from '../../generated/empty-reuse-operations';
2
+ import type { SelectedEvidence } from '../components/ContainerEvidencePicker';
3
+ import { freeTimeIso } from './freeTimeDate';
4
+ export function reuseText(values: FormData, name: string) {
5
+ return String(values.get(name) ?? '').trim();
6
+ }
7
+ export function reuseInteger(values: FormData, name: string) {
8
+ const s = reuseText(values, name);
9
+ if (!/^\d+$/.test(s) || !Number.isSafeInteger(Number(s)) || Number(s) > 2147483647)
10
+ throw new Error(`${name}: enter a whole number between 0 and 2147483647.`);
11
+ return Number(s);
12
+ }
13
+ export function readReuseSource(
14
+ values: FormData,
15
+ name: string,
16
+ evidence: SelectedEvidence[]
17
+ ): MtwReuseSourceAttestationInput | undefined {
18
+ if (reuseText(values, `${name}.recorded`) !== 'yes') return undefined;
19
+ const ids = values.getAll(`${name}.evidence`).map((value) => String(value));
20
+ if (!ids.length || ids.some((id) => !evidence.some((item) => item.versionId === id)))
21
+ throw new Error(`Select current proposal evidence for ${name}.`);
22
+ return {
23
+ sourceReference: reuseText(values, `${name}.reference`),
24
+ sourceRevision: reuseText(values, `${name}.revision`),
25
+ observedAt: freeTimeIso(reuseText(values, `${name}.observed`)),
26
+ validFrom: freeTimeIso(reuseText(values, `${name}.from`)),
27
+ validUntil: freeTimeIso(reuseText(values, `${name}.until`)),
28
+ evidenceVersionIds: ids,
29
+ };
30
+ }