@burdenoff/microfe-movethewheels 2026.1011.1 → 2026.1011.2

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 (30) hide show
  1. package/dist/MoveTheWheelsRoot.js +5 -0
  2. package/dist/MoveTheWheelsRoutes.js +54 -50
  3. package/dist/generated/shipment-status-authority-operations.d.ts +4473 -0
  4. package/dist/hooks/useEpod.js +85 -77
  5. package/dist/hooks/useShipmentStatusAuthority.js +127 -0
  6. package/dist/hooks/useTracking.js +15 -14
  7. package/dist/hooks/useTrackingEventQuality.js +43 -17
  8. package/dist/movethewheels/hooks/useEpod.d.ts +23 -0
  9. package/dist/movethewheels/hooks/useShipmentStatusAuthority.d.ts +23 -0
  10. package/dist/movethewheels/hooks/useTrackingEventQuality.d.ts +5 -0
  11. package/dist/movethewheels/pages/ShipmentStatusAuthorityPage.d.ts +1 -0
  12. package/dist/movethewheels/utils/shipmentStatusDraft.d.ts +45 -0
  13. package/dist/pages/DeliveryCapturePage.js +181 -116
  14. package/dist/pages/ShipmentStatusAuthorityPage.js +563 -0
  15. package/dist/pages/TrackingEventQualityPage.js +6 -1
  16. package/dist/src/generated/shipment-status-authority-operations.js +86 -0
  17. package/dist/utils/shipmentStatusDraft.js +41 -0
  18. package/package.json +5 -4
  19. package/src/generated/shipment-status-authority-operations.ts +5503 -0
  20. package/src/movethewheels/MoveTheWheelsRoot.tsx +6 -0
  21. package/src/movethewheels/MoveTheWheelsRoutes.tsx +2 -0
  22. package/src/movethewheels/hooks/useEpod.ts +47 -12
  23. package/src/movethewheels/hooks/useShipmentStatusAuthority.ts +179 -0
  24. package/src/movethewheels/hooks/useTracking.ts +27 -12
  25. package/src/movethewheels/hooks/useTrackingEventQuality.ts +42 -0
  26. package/src/movethewheels/pages/DeliveryCapturePage.tsx +113 -6
  27. package/src/movethewheels/pages/ShipmentStatusAuthorityPage.tsx +639 -0
  28. package/src/movethewheels/pages/TrackingEventQualityPage.tsx +13 -2
  29. package/src/movethewheels/utils/shipmentStatusDraft.ts +118 -0
  30. package/src/operations/shipment-status-authority/status.graphql +80 -0
@@ -0,0 +1,118 @@
1
+ export interface ShipmentSourceDraft {
2
+ integrationId: string;
3
+ basisTrackingEventId: string;
4
+ maxSourceAgeSeconds: string;
5
+ maxFutureSkewSeconds: string;
6
+ reason: string;
7
+ }
8
+
9
+ export function statusDecisionReason(value: string): string {
10
+ const reason = value.trim();
11
+ if (!reason || reason.length > 1000) throw new Error('Enter a reason of 1–1000 characters.');
12
+ return reason;
13
+ }
14
+
15
+ function explicitSeconds(value: string, minimum: number, maximum: number, label: string): number {
16
+ if (!/^\d+$/.test(value.trim()))
17
+ throw new Error(`${label} must be an explicit whole number of seconds.`);
18
+ const result = Number(value.trim());
19
+ if (!Number.isSafeInteger(result) || result < minimum || result > maximum)
20
+ throw new Error(`${label} must be between ${minimum} and ${maximum} seconds.`);
21
+ return result;
22
+ }
23
+
24
+ export function shipmentSourceInput(draft: ShipmentSourceDraft, expectedStatusRevision: number) {
25
+ if (!draft.integrationId || !draft.basisTrackingEventId)
26
+ throw new Error('Choose one integration and one recorded basis event.');
27
+ return {
28
+ expectedStatusRevision,
29
+ integrationId: draft.integrationId,
30
+ basisTrackingEventId: draft.basisTrackingEventId,
31
+ maxSourceAgeSeconds: explicitSeconds(
32
+ draft.maxSourceAgeSeconds,
33
+ 1,
34
+ 2592000,
35
+ 'Maximum source age'
36
+ ),
37
+ maxFutureSkewSeconds: explicitSeconds(
38
+ draft.maxFutureSkewSeconds,
39
+ 0,
40
+ 86400,
41
+ 'Allowed future skew'
42
+ ),
43
+ reason: statusDecisionReason(draft.reason),
44
+ };
45
+ }
46
+
47
+ interface StatusAcknowledgement {
48
+ id: string;
49
+ status: string;
50
+ statusRevision: number;
51
+ statusAuthority: string;
52
+ statusAuthorityEpoch: number;
53
+ designatedIntegrationId?: string | null;
54
+ statusBasisEventId?: string | null;
55
+ statusBasisSourceTime?: string | null;
56
+ maxSourceAgeSeconds?: number | null;
57
+ maxFutureSkewSeconds?: number | null;
58
+ }
59
+
60
+ export function sourceStatusAcknowledged(
61
+ actual: StatusAcknowledgement | null | undefined,
62
+ expected: {
63
+ id: string;
64
+ epoch: number;
65
+ input: ReturnType<typeof shipmentSourceInput>;
66
+ basis: { id: string; eventType: string; providerEventTime?: string | null } | undefined;
67
+ }
68
+ ): boolean {
69
+ const statuses: Record<string, string> = {
70
+ PICKED_UP: 'PICKED_UP',
71
+ IN_TRANSIT: 'IN_TRANSIT',
72
+ ARRIVED: 'IN_TRANSIT',
73
+ DEPARTED: 'IN_TRANSIT',
74
+ OUT_FOR_DELIVERY: 'IN_TRANSIT',
75
+ DELIVERED: 'DELIVERED',
76
+ FAILED: 'FAILED',
77
+ RETURNED: 'RETURNED',
78
+ };
79
+ const basis = expected.basis;
80
+ const time = basis?.providerEventTime ? Date.parse(basis.providerEventTime) : NaN;
81
+ return (
82
+ !!actual &&
83
+ !!basis &&
84
+ Number.isFinite(time) &&
85
+ actual.id === expected.id &&
86
+ actual.statusRevision === expected.input.expectedStatusRevision + 1 &&
87
+ actual.statusAuthority === 'INTEGRATION_EVENT_TIME' &&
88
+ actual.statusAuthorityEpoch === expected.epoch + 1 &&
89
+ actual.designatedIntegrationId === expected.input.integrationId &&
90
+ actual.statusBasisEventId === basis.id &&
91
+ basis.id === expected.input.basisTrackingEventId &&
92
+ typeof actual.statusBasisSourceTime === 'string' &&
93
+ Date.parse(actual.statusBasisSourceTime) === time &&
94
+ actual.maxSourceAgeSeconds === expected.input.maxSourceAgeSeconds &&
95
+ actual.maxFutureSkewSeconds === expected.input.maxFutureSkewSeconds &&
96
+ typeof statuses[basis.eventType] === 'string' &&
97
+ actual.status === statuses[basis.eventType]
98
+ );
99
+ }
100
+
101
+ export function manualStatusAcknowledged(
102
+ actual: StatusAcknowledgement | null | undefined,
103
+ expected: { id: string; revision: number; epoch: number; status: string }
104
+ ): boolean {
105
+ return (
106
+ !!actual &&
107
+ actual.id === expected.id &&
108
+ actual.statusRevision === expected.revision + 1 &&
109
+ actual.status === expected.status &&
110
+ actual.statusAuthority === 'MANUAL_HOLD' &&
111
+ actual.statusAuthorityEpoch === expected.epoch + 1 &&
112
+ actual.designatedIntegrationId === null &&
113
+ actual.statusBasisEventId === null &&
114
+ actual.statusBasisSourceTime === null &&
115
+ actual.maxSourceAgeSeconds === null &&
116
+ actual.maxFutureSkewSeconds === null
117
+ );
118
+ }
@@ -0,0 +1,80 @@
1
+ fragment ShipmentStatusAuthorityFields on MtwShipment {
2
+ id
3
+ shipmentNumber
4
+ status
5
+ statusRevision
6
+ statusAuthority
7
+ statusAuthorityEpoch
8
+ designatedIntegrationId
9
+ statusBasisEventId
10
+ statusBasisSourceTime
11
+ maxSourceAgeSeconds
12
+ maxFutureSkewSeconds
13
+ }
14
+
15
+ query StatusAuthorityShipments($filter: ShipmentFilterInput, $pagination: PaginationInput!) {
16
+ shipments(filter: $filter, pagination: $pagination) {
17
+ ...ShipmentStatusAuthorityFields
18
+ }
19
+ }
20
+
21
+ query StatusAuthorityDetail($id: ID!, $pagination: PaginationInput!, $evidencePagination: PaginationInput!) {
22
+ shipment(id: $id) {
23
+ ...ShipmentStatusAuthorityFields
24
+ trackingEvents(pagination: $evidencePagination) {
25
+ id
26
+ eventType
27
+ sourceIntegrationId
28
+ sourceTimestampProvenance
29
+ providerEventTime
30
+ serverReceivedAt
31
+ timestamp
32
+ }
33
+ }
34
+ shipmentStatusDecisions(shipmentId: $id, pagination: $pagination) {
35
+ id
36
+ origin
37
+ outcome
38
+ heldReason
39
+ observedRevision
40
+ resultRevision
41
+ priorStatus
42
+ resultStatus
43
+ trackingEventId
44
+ proofId
45
+ reason
46
+ recordedAt
47
+ configuredIntegrationId
48
+ configuredMaxSourceAgeSeconds
49
+ configuredMaxFutureSkewSeconds
50
+ }
51
+ }
52
+
53
+ query StatusAuthoritySources($pagination: PaginationInput!) {
54
+ integrations(pagination: $pagination) {
55
+ id
56
+ name
57
+ provider
58
+ status
59
+ }
60
+ }
61
+
62
+ mutation StatusAuthorityConfigure($id: ID!, $input: ConfigureShipmentStatusSourceInput!) {
63
+ configureShipmentStatusSource(id: $id, input: $input) {
64
+ ...ShipmentStatusAuthorityFields
65
+ }
66
+ }
67
+
68
+ mutation StatusAuthorityManual($id: ID!, $input: UpdateShipmentInput!) {
69
+ updateShipment(id: $id, input: $input) {
70
+ ...ShipmentStatusAuthorityFields
71
+ }
72
+ }
73
+
74
+ query StatusAuthorityOwnedDelivery($deliveryJobId: ID!) {
75
+ myEpodShipmentStatus(deliveryJobId: $deliveryJobId) {
76
+ id
77
+ status
78
+ statusRevision
79
+ }
80
+ }