@burdenoff/microfe-movethewheels 2026.1016.3 → 2026.1016.4

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 (88) hide show
  1. package/README.md +10 -0
  2. package/dist/MoveTheWheelsRoot.js +5 -0
  3. package/dist/MoveTheWheelsRoutes.js +25 -21
  4. package/dist/components/ContainerEvidencePicker.js +55 -55
  5. package/dist/components/FleetAlertsPanel.js +2 -2
  6. package/dist/components/freight-invoice/InvoiceForm.js +366 -0
  7. package/dist/components/freight-invoice/InvoiceResults.js +240 -0
  8. package/dist/generated/consolidation-operations.d.ts +195 -265
  9. package/dist/generated/container-condition-operations.d.ts +124 -187
  10. package/dist/generated/container-operations.d.ts +59 -85
  11. package/dist/generated/empty-reuse-operations.d.ts +165 -271
  12. package/dist/generated/free-time-operations.d.ts +120 -184
  13. package/dist/generated/freight-cost-operations.d.ts +307 -476
  14. package/dist/generated/freight-invoice-operations.d.ts +1447 -0
  15. package/dist/generated/logistics-procedure-operations.d.ts +100 -156
  16. package/dist/generated/pending-pick-operations.d.ts +769 -1025
  17. package/dist/generated/shipment-status-authority-operations.d.ts +82 -103
  18. package/dist/generated/stock-binding-operations.d.ts +188 -260
  19. package/dist/generated/stock-observation-operations.d.ts +103 -138
  20. package/dist/generated/tracking-quality-operations.d.ts +27 -41
  21. package/dist/generated/trip-utilization-operations.d.ts +137 -185
  22. package/dist/generated/wspace-operations.d.ts +628 -2272
  23. package/dist/generated/wspace-types.d.ts +4 -23
  24. package/dist/hooks/useInvoiceComparisonRecovery.js +118 -0
  25. package/dist/movethewheels/components/ContainerEvidencePicker.d.ts +2 -1
  26. package/dist/movethewheels/components/freight-invoice/InvoiceForm.d.ts +19 -0
  27. package/dist/movethewheels/components/freight-invoice/InvoiceResults.d.ts +9 -0
  28. package/dist/movethewheels/hooks/useFleet.d.ts +1 -1
  29. package/dist/movethewheels/hooks/useFleetIntelligence.d.ts +1 -1
  30. package/dist/movethewheels/hooks/useInvoiceComparisonRecovery.d.ts +22 -0
  31. package/dist/movethewheels/hooks/useProcedureSelection.d.ts +1 -3
  32. package/dist/movethewheels/pages/FreightInvoicePage.d.ts +10 -0
  33. package/dist/movethewheels/utils/driverLicenseExpiry.d.ts +6 -0
  34. package/dist/movethewheels/utils/invoiceComparison.d.ts +32 -0
  35. package/dist/pages/DriverDetailsPage.js +306 -282
  36. package/dist/pages/FreightEstimatePage.js +1 -0
  37. package/dist/pages/FreightInvoicePage.js +346 -0
  38. package/dist/src/generated/consolidation-operations.js +3961 -503
  39. package/dist/src/generated/container-condition-operations.js +2968 -206
  40. package/dist/src/generated/container-operations.js +997 -99
  41. package/dist/src/generated/empty-reuse-operations.js +4811 -747
  42. package/dist/src/generated/free-time-operations.js +2824 -233
  43. package/dist/src/generated/freight-cost-operations.js +4852 -812
  44. package/dist/src/generated/freight-invoice-operations.js +4894 -0
  45. package/dist/src/generated/logistics-procedure-operations.js +2707 -360
  46. package/dist/src/generated/pending-pick-operations.js +8244 -1196
  47. package/dist/src/generated/shipment-status-authority-operations.js +1157 -84
  48. package/dist/src/generated/stock-binding-operations.js +2779 -173
  49. package/dist/src/generated/stock-observation-operations.js +1274 -91
  50. package/dist/src/generated/tracking-quality-operations.js +407 -42
  51. package/dist/src/generated/trip-utilization-operations.js +1765 -138
  52. package/dist/src/generated/wspace-operations.js +428 -706
  53. package/dist/utils/driverLicenseExpiry.js +14 -0
  54. package/dist/utils/invoiceComparison.js +272 -0
  55. package/package.json +29 -29
  56. package/src/generated/consolidation-operations.ts +60 -559
  57. package/src/generated/container-condition-operations.ts +63 -265
  58. package/src/generated/container-operations.ts +37 -132
  59. package/src/generated/empty-reuse-operations.ts +83 -824
  60. package/src/generated/free-time-operations.ts +55 -284
  61. package/src/generated/freight-cost-operations.ts +42 -848
  62. package/src/generated/freight-invoice-operations.ts +830 -0
  63. package/src/generated/logistics-procedure-operations.ts +60 -414
  64. package/src/generated/pending-pick-operations.ts +48 -1239
  65. package/src/generated/shipment-status-authority-operations.ts +33 -113
  66. package/src/generated/stock-binding-operations.ts +29 -198
  67. package/src/generated/stock-observation-operations.ts +24 -111
  68. package/src/generated/tracking-quality-operations.ts +19 -57
  69. package/src/generated/trip-utilization-operations.ts +32 -166
  70. package/src/generated/wspace-operations.ts +284 -2906
  71. package/src/generated/wspace-types.ts +2 -8
  72. package/src/movethewheels/MoveTheWheelsRoot.tsx +6 -0
  73. package/src/movethewheels/MoveTheWheelsRoutes.tsx +2 -0
  74. package/src/movethewheels/components/ContainerEvidencePicker.tsx +12 -4
  75. package/src/movethewheels/components/FleetAlertsPanel.tsx +4 -2
  76. package/src/movethewheels/components/freight-invoice/InvoiceForm.tsx +412 -0
  77. package/src/movethewheels/components/freight-invoice/InvoiceResults.tsx +162 -0
  78. package/src/movethewheels/hooks/useFleet.ts +1 -1
  79. package/src/movethewheels/hooks/useFleetIntelligence.ts +5 -1
  80. package/src/movethewheels/hooks/useInvoiceComparisonRecovery.ts +227 -0
  81. package/src/movethewheels/pages/DriverDetailsPage.tsx +35 -9
  82. package/src/movethewheels/pages/FreightEstimatePage.tsx +1 -0
  83. package/src/movethewheels/pages/FreightInvoicePage.tsx +477 -0
  84. package/src/movethewheels/utils/driverLicenseExpiry.ts +25 -0
  85. package/src/movethewheels/utils/invoiceComparison.ts +520 -0
  86. package/src/operations/freight-invoice/comparison.graphql +40 -0
  87. package/src/operations/wspace/freight-invoice-evidence.graphql +6 -0
  88. package/patches/braces@3.0.3.patch +0 -87
@@ -0,0 +1,366 @@
1
+ import { Button as e } from "../ui.js";
2
+ import { ContainerEvidencePicker as t } from "../ContainerEvidencePicker.js";
3
+ import { FreightCurrency as n, FreightSelect as r, FreightText as i } from "../freight-cost/FreightFields.js";
4
+ import { fixedFreightMinor as a, freightMoney as o } from "../../utils/freightDraft.js";
5
+ import { invoiceCanonical as s, invoiceFactsInput as c, matchesInvoicePreview as l } from "../../utils/invoiceComparison.js";
6
+ import { InvoiceResults as u } from "./InvoiceResults.js";
7
+ import { useEffect as d, useRef as f, useState as p } from "react";
8
+ import { jsx as m, jsxs as h } from "react/jsx-runtime";
9
+ //#region src/movethewheels/components/freight-invoice/InvoiceForm.tsx
10
+ function g() {
11
+ return {
12
+ schemaVersion: 1,
13
+ supplierReference: null,
14
+ supplierLabel: null,
15
+ invoiceReference: null,
16
+ sourceReference: "",
17
+ sourceRevision: "",
18
+ invoiceDate: null,
19
+ currency: {
20
+ code: "",
21
+ minorUnitDigits: 2
22
+ },
23
+ rows: [{
24
+ id: crypto.randomUUID(),
25
+ description: "",
26
+ estimateLineId: null,
27
+ currency: {
28
+ code: "",
29
+ minorUnitDigits: 2
30
+ },
31
+ payerReference: null,
32
+ payerLabel: null,
33
+ quantity: null,
34
+ unit: null,
35
+ unitRateMajor: null,
36
+ amountMinor: null,
37
+ zeroReason: null
38
+ }]
39
+ };
40
+ }
41
+ function _(e) {
42
+ return {
43
+ id: e.id,
44
+ estimateReference: e.estimateReference,
45
+ version: e.version,
46
+ kind: e.facts.kind,
47
+ sourceReference: e.facts.sourceReference,
48
+ sourceRevision: e.facts.sourceRevision,
49
+ quotedAt: e.facts.quotedAt,
50
+ validFrom: e.facts.validFrom,
51
+ validUntil: e.facts.validUntil,
52
+ acceptance: "NOT_ESTABLISHED"
53
+ };
54
+ }
55
+ function v({ estimate: v, previous: y, disabled: b, canRecord: x, onPreview: S, onSave: C }) {
56
+ let [w, T] = p(() => y ? structuredClone(y.facts) : g()), [E, D] = p([]), [O, k] = p(""), [A, j] = p(null), [M, N] = p(null), [P, F] = p(!1), I = f(null), L = f(!0), R = f(!1);
57
+ d(() => (L.current = !0, () => {
58
+ L.current = !1;
59
+ }), []);
60
+ let z = s({
61
+ facts: w,
62
+ evidence: E.map(({ fileId: e, versionId: t }) => ({
63
+ fileId: e,
64
+ versionId: t
65
+ })),
66
+ estimateId: v.id
67
+ }), B = A?.body === z ? A.value : null, V = (e) => T({
68
+ ...w,
69
+ ...e
70
+ }), H = (e, t) => V({ rows: w.rows.map((n) => n.id === e ? {
71
+ ...n,
72
+ ...t
73
+ } : n) }), U = async () => {
74
+ if (R.current || b || !I.current?.reportValidity()) return;
75
+ R.current = !0, F(!0), N(null);
76
+ let e = z;
77
+ try {
78
+ let t = c(w), n = await S({
79
+ shipmentId: v.shipmentId,
80
+ estimateVersionId: v.id,
81
+ facts: t,
82
+ evidence: E.map(({ fileId: e, versionId: t }) => ({
83
+ fileId: e,
84
+ versionId: t
85
+ }))
86
+ });
87
+ if (!l(n, t, _(v))) throw Error("The preview did not match these reported facts and exact estimate. Nothing was sent.");
88
+ L.current && j({
89
+ body: e,
90
+ value: n
91
+ });
92
+ } catch (e) {
93
+ L.current && N(e instanceof Error ? e.message : "Unable to preview the reported facts.");
94
+ } finally {
95
+ R.current = !1, L.current && F(!1);
96
+ }
97
+ };
98
+ return /* @__PURE__ */ h("form", {
99
+ ref: I,
100
+ className: "min-w-0 space-y-5",
101
+ "aria-label": "Manual invoice comparison",
102
+ onSubmit: (e) => {
103
+ if (e.preventDefault(), !(!B || B.recordable !== !0 || b || !x || R.current)) {
104
+ N(null);
105
+ try {
106
+ let e = c(w);
107
+ C({
108
+ shipmentId: v.shipmentId,
109
+ estimateVersionId: v.id,
110
+ facts: e,
111
+ evidence: E.map(({ fileId: e, versionId: t }) => ({
112
+ fileId: e,
113
+ versionId: t
114
+ })),
115
+ expectedRevision: y?.revision ?? 0,
116
+ expectedPreviousComparisonId: y?.id ?? null,
117
+ correctionReason: y && O.trim() || null
118
+ }, _(v)).catch(() => N("The original request remains retained; inspect read-only recovery."));
119
+ } catch (e) {
120
+ N(e instanceof Error ? e.message : "Review the reported source fields. Nothing was sent.");
121
+ }
122
+ }
123
+ },
124
+ children: [
125
+ /* @__PURE__ */ h("fieldset", {
126
+ disabled: b || P,
127
+ className: "min-w-0 space-y-5",
128
+ children: [
129
+ /* @__PURE__ */ m("legend", {
130
+ className: "text-lg font-semibold",
131
+ children: y ? "Append an immutable correction" : "Reported supplier invoice"
132
+ }),
133
+ /* @__PURE__ */ m("p", { children: "Blank means unknown, never zero. This is a manual comparison, not approval or payment. No FX, credits or split allocation." }),
134
+ /* @__PURE__ */ h("p", { children: [
135
+ "Exact pinned ",
136
+ v.facts.kind.toLowerCase(),
137
+ ": ",
138
+ v.estimateReference,
139
+ " / version",
140
+ " ",
141
+ v.version,
142
+ "; ",
143
+ v.facts.title,
144
+ ". Source validity: ",
145
+ v.validityAtRead,
146
+ ". Acceptance is not established."
147
+ ] }),
148
+ /* @__PURE__ */ h("div", {
149
+ className: "grid min-w-0 gap-3 md:grid-cols-2",
150
+ children: [
151
+ /* @__PURE__ */ m(i, {
152
+ label: "Supplier source reference",
153
+ value: w.supplierReference ?? "",
154
+ disabled: !!y,
155
+ onChange: (e) => V({ supplierReference: e })
156
+ }),
157
+ /* @__PURE__ */ m(i, {
158
+ label: "Supplier label",
159
+ value: w.supplierLabel ?? "",
160
+ onChange: (e) => V({ supplierLabel: e })
161
+ }),
162
+ /* @__PURE__ */ m(i, {
163
+ label: "Invoice reference",
164
+ value: w.invoiceReference ?? "",
165
+ disabled: !!y,
166
+ onChange: (e) => V({ invoiceReference: e })
167
+ }),
168
+ /* @__PURE__ */ m(i, {
169
+ label: "Invoice source reference",
170
+ value: w.sourceReference,
171
+ required: !0,
172
+ onChange: (e) => V({ sourceReference: e })
173
+ }),
174
+ /* @__PURE__ */ m(i, {
175
+ label: "Invoice source revision",
176
+ value: w.sourceRevision,
177
+ required: !0,
178
+ onChange: (e) => V({ sourceRevision: e })
179
+ }),
180
+ /* @__PURE__ */ m(i, {
181
+ label: "Invoice source date (optional)",
182
+ type: "date",
183
+ value: w.invoiceDate ?? "",
184
+ onChange: (e) => V({ invoiceDate: e || null })
185
+ })
186
+ ]
187
+ }),
188
+ /* @__PURE__ */ m(n, {
189
+ label: "Invoice currency",
190
+ value: w.currency,
191
+ onChange: (e) => V({
192
+ currency: e,
193
+ rows: w.rows.map((t) => ({
194
+ ...t,
195
+ currency: e,
196
+ amountMinor: null,
197
+ zeroReason: null
198
+ }))
199
+ })
200
+ }),
201
+ w.rows.map((t, n) => /* @__PURE__ */ h("fieldset", {
202
+ className: "min-w-0 space-y-3 rounded border p-3",
203
+ children: [
204
+ /* @__PURE__ */ h("legend", {
205
+ className: "font-semibold",
206
+ children: ["Reported row ", n + 1]
207
+ }),
208
+ /* @__PURE__ */ m(i, {
209
+ label: `Row ${n + 1} description`,
210
+ value: t.description,
211
+ required: !0,
212
+ onChange: (e) => H(t.id, { description: e })
213
+ }),
214
+ /* @__PURE__ */ h(r, {
215
+ label: `Row ${n + 1} exact estimate mapping`,
216
+ value: t.estimateLineId ?? "",
217
+ onChange: (e) => H(t.id, { estimateLineId: e || null }),
218
+ children: [/* @__PURE__ */ m("option", {
219
+ value: "",
220
+ children: "Unmatched invoice row"
221
+ }), v.facts.lines.map((e) => /* @__PURE__ */ h("option", {
222
+ value: e.id,
223
+ children: [
224
+ e.description,
225
+ " / ",
226
+ e.id,
227
+ " / ",
228
+ e.disposition
229
+ ]
230
+ }, e.id))]
231
+ }),
232
+ /* @__PURE__ */ h("div", {
233
+ className: "grid min-w-0 gap-3 md:grid-cols-2",
234
+ children: [
235
+ /* @__PURE__ */ m(i, {
236
+ label: `Row ${n + 1} payer source reference`,
237
+ value: t.payerReference ?? "",
238
+ onChange: (e) => H(t.id, { payerReference: e })
239
+ }),
240
+ /* @__PURE__ */ m(i, {
241
+ label: `Row ${n + 1} payer label`,
242
+ value: t.payerLabel ?? "",
243
+ onChange: (e) => H(t.id, { payerLabel: e })
244
+ }),
245
+ /* @__PURE__ */ h("label", {
246
+ className: "block text-sm",
247
+ children: [
248
+ "Row ",
249
+ n + 1,
250
+ " supplied amount (",
251
+ t.currency.code || "declare currency",
252
+ ")",
253
+ /* @__PURE__ */ m("input", {
254
+ className: "mt-1 min-h-11 w-full rounded border p-2",
255
+ "aria-label": `Row ${n + 1} supplied amount`,
256
+ inputMode: "decimal",
257
+ defaultValue: t.amountMinor == null ? "" : o(t.amountMinor, t.currency.minorUnitDigits),
258
+ onChange: (e) => {
259
+ try {
260
+ H(t.id, { amountMinor: a(e.target.value, t.currency.minorUnitDigits) }), e.target.setCustomValidity("");
261
+ } catch (n) {
262
+ H(t.id, { amountMinor: null }), e.target.setCustomValidity(n instanceof Error ? n.message : "Invalid sourced amount.");
263
+ }
264
+ }
265
+ }, `${t.currency.code}:${t.currency.minorUnitDigits}`)
266
+ ]
267
+ }),
268
+ /* @__PURE__ */ m(i, {
269
+ label: `Row ${n + 1} zero source reason`,
270
+ value: t.zeroReason ?? "",
271
+ onChange: (e) => H(t.id, { zeroReason: e })
272
+ }),
273
+ /* @__PURE__ */ m(i, {
274
+ label: `Row ${n + 1} supplied quantity`,
275
+ value: t.quantity ?? "",
276
+ onChange: (e) => H(t.id, { quantity: e })
277
+ }),
278
+ /* @__PURE__ */ m(i, {
279
+ label: `Row ${n + 1} explicit unit`,
280
+ value: t.unit ?? "",
281
+ onChange: (e) => H(t.id, { unit: e })
282
+ }),
283
+ /* @__PURE__ */ m(i, {
284
+ label: `Row ${n + 1} supplied unit rate`,
285
+ value: t.unitRateMajor ?? "",
286
+ onChange: (e) => H(t.id, { unitRateMajor: e })
287
+ })
288
+ ]
289
+ }),
290
+ /* @__PURE__ */ h("p", { children: [
291
+ w.currency.code || "currency unknown",
292
+ " / decimal places",
293
+ " ",
294
+ w.currency.minorUnitDigits,
295
+ ". Amount stays as supplied, not quantity × rate."
296
+ ] }),
297
+ /* @__PURE__ */ h(e, {
298
+ type: "button",
299
+ variant: "outline",
300
+ disabled: w.rows.length === 1,
301
+ onClick: () => V({ rows: w.rows.filter((e) => e.id !== t.id) }),
302
+ children: ["Remove row ", n + 1]
303
+ })
304
+ ]
305
+ }, t.id)),
306
+ /* @__PURE__ */ m(e, {
307
+ type: "button",
308
+ variant: "outline",
309
+ disabled: w.rows.length >= 100,
310
+ onClick: () => V({ rows: [...w.rows, {
311
+ id: crypto.randomUUID(),
312
+ description: "",
313
+ estimateLineId: null,
314
+ currency: { ...w.currency },
315
+ payerReference: null,
316
+ payerLabel: null,
317
+ quantity: null,
318
+ unit: null,
319
+ unitRateMajor: null,
320
+ amountMinor: null,
321
+ zeroReason: null
322
+ }] }),
323
+ children: "Add reported row"
324
+ }),
325
+ /* @__PURE__ */ m(t, {
326
+ currentOnly: !0,
327
+ value: E,
328
+ onChange: D,
329
+ description: "Choose current readable ACTIVE Files versions with an integrity fingerprint. The server rechecks eligibility when recording; no binary is uploaded here."
330
+ }),
331
+ y && /* @__PURE__ */ m(i, {
332
+ label: "Correction source reason",
333
+ value: O,
334
+ required: !1,
335
+ onChange: k
336
+ }),
337
+ /* @__PURE__ */ h("div", {
338
+ className: "flex flex-wrap gap-3",
339
+ children: [/* @__PURE__ */ m(e, {
340
+ type: "button",
341
+ variant: "outline",
342
+ onClick: () => void U(),
343
+ children: "Preview reported comparison"
344
+ }), /* @__PURE__ */ m(e, {
345
+ type: "submit",
346
+ disabled: !x || B?.recordable !== !0 || !E.length || !!y && !O.trim(),
347
+ children: "Record immutable comparison"
348
+ })]
349
+ })
350
+ ]
351
+ }),
352
+ !x && /* @__PURE__ */ m("p", { children: "Shipment update permission is required to record; structural preview remains read-only." }),
353
+ P && /* @__PURE__ */ m("p", {
354
+ role: "status",
355
+ children: "Comparing the exact recorded facts…"
356
+ }),
357
+ M && /* @__PURE__ */ m("p", {
358
+ role: "alert",
359
+ children: M
360
+ }),
361
+ B && /* @__PURE__ */ m(u, { value: B })
362
+ ]
363
+ });
364
+ }
365
+ //#endregion
366
+ export { v as InvoiceForm };
@@ -0,0 +1,240 @@
1
+ import { reuseCard as e } from "../ReuseControls.js";
2
+ import { freightLabel as t } from "../../utils/freightDraft.js";
3
+ import { invoiceMoney as n, invoiceRowDifference as r } from "../../utils/invoiceComparison.js";
4
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
5
+ //#region src/movethewheels/components/freight-invoice/InvoiceResults.tsx
6
+ function o({ value: o }) {
7
+ let { estimate: s, outcome: c } = o;
8
+ return /* @__PURE__ */ a("section", {
9
+ className: e,
10
+ "aria-label": "Invoice comparison results",
11
+ children: [
12
+ /* @__PURE__ */ i("h2", {
13
+ className: "text-lg font-semibold",
14
+ children: "Recorded-fact comparison"
15
+ }),
16
+ /* @__PURE__ */ a("p", { children: [
17
+ "Exact ",
18
+ s.kind.toLowerCase(),
19
+ " ",
20
+ s.estimateReference,
21
+ ", version ",
22
+ s.version,
23
+ ". Source ",
24
+ s.sourceReference,
25
+ " / ",
26
+ s.sourceRevision,
27
+ "."
28
+ ] }),
29
+ /* @__PURE__ */ a("p", { children: [
30
+ "Quote date ",
31
+ s.quotedAt ?? "Unknown",
32
+ "; source validity",
33
+ " ",
34
+ s.validFrom ?? "Unknown",
35
+ " to ",
36
+ s.validUntil ?? "Unknown",
37
+ ". Acceptance is not established by this comparison."
38
+ ] }),
39
+ "recordable" in o && /* @__PURE__ */ a("p", {
40
+ role: "status",
41
+ children: [
42
+ "Structural preview only.",
43
+ " ",
44
+ o.recordable ? "Source structure is recordable; current permission and Files eligibility are checked when recording." : `Not recordable: ${o.blockers.map(t).join(", ")}.`
45
+ ]
46
+ }),
47
+ /* @__PURE__ */ i("p", {
48
+ className: "font-medium",
49
+ children: c.allLinesMatched ? "All explicitly compared rows and expected coverage agree under this method." : "Differences or unknown coverage remain."
50
+ }),
51
+ /* @__PURE__ */ i("p", { children: "This is not an all-in cost, contracted-rate audit, liability finding, invoice approval or payment." }),
52
+ c.rows.map((e, n) => /* @__PURE__ */ a("article", {
53
+ className: "min-w-0 space-y-2 rounded border p-3",
54
+ children: [
55
+ /* @__PURE__ */ a("h3", {
56
+ className: "font-medium",
57
+ children: [
58
+ "Row ",
59
+ n + 1,
60
+ ":",
61
+ " ",
62
+ o.facts.rows.find((t) => t.id === e.invoiceLineId)?.description ?? "Reported charge"
63
+ ]
64
+ }),
65
+ /* @__PURE__ */ i("p", { children: e.estimateLineId ? "Mapped to the selected estimate row." : "No estimate row mapped." }),
66
+ /* @__PURE__ */ i("p", { children: e.flags.map(t).join(" · ") }),
67
+ e.reasons.length > 0 && /* @__PURE__ */ a("p", { children: ["Unknown reasons: ", e.reasons.map(t).join(", ")] }),
68
+ /* @__PURE__ */ a("p", { children: ["Comparable amount difference: ", r(o, e.invoiceLineId)] })
69
+ ]
70
+ }, e.invoiceLineId)),
71
+ c.missingExpectedLineIds.map((e) => /* @__PURE__ */ a("p", { children: [
72
+ "Missing expected line: ",
73
+ e,
74
+ ". An unknown value is not treated as zero."
75
+ ] }, e)),
76
+ c.unknownExpectedCoverage.map((e) => /* @__PURE__ */ a("p", { children: [
77
+ "Unknown expected-charge coverage: ",
78
+ e.estimateLineId,
79
+ ". This is not a proven missing charge."
80
+ ] }, e.estimateLineId)),
81
+ /* @__PURE__ */ a("section", {
82
+ className: "space-y-2",
83
+ children: [
84
+ /* @__PURE__ */ i("h3", {
85
+ className: "font-semibold",
86
+ children: "Comparable pairs only"
87
+ }),
88
+ c.comparableSubtotals.length === 0 && /* @__PURE__ */ i("p", { children: "No bounded comparable subtotal." }),
89
+ c.comparableSubtotals.map((e) => /* @__PURE__ */ a("p", { children: [
90
+ "Payer",
91
+ " ",
92
+ o.facts.rows.find((t) => t.payerReference === e.payerReference)?.payerLabel ?? e.payerReference,
93
+ ": estimate ",
94
+ n(e.estimateMinor, e.currency),
95
+ ", invoice",
96
+ " ",
97
+ n(e.invoiceMinor, e.currency),
98
+ ", difference",
99
+ " ",
100
+ n(e.deltaMinor, e.currency),
101
+ ". Included rows",
102
+ " ",
103
+ e.invoiceLineIds.map((e) => o.facts.rows.find((t) => t.id === e)?.description ?? "Reported charge").join(", "),
104
+ ". Other rows are omitted."
105
+ ] }, JSON.stringify([e.currency, e.payerReference])))
106
+ ]
107
+ }),
108
+ [["Declared estimate subtotals", o.estimateDeclaredSubtotals], ["Declared invoice subtotals", o.invoiceDeclaredSubtotals]].map(([e, t]) => /* @__PURE__ */ a("section", {
109
+ className: "space-y-2",
110
+ children: [/* @__PURE__ */ i("h3", {
111
+ className: "font-semibold",
112
+ children: e
113
+ }), t.map((e, t) => /* @__PURE__ */ a("p", { children: [
114
+ "Payer ",
115
+ e.payerLabel ?? "Unknown",
116
+ " (",
117
+ e.payerReference ?? "Unknown reference",
118
+ ");",
119
+ " ",
120
+ "known ",
121
+ n(e.knownAmountMinor, e.currency),
122
+ "; total",
123
+ " ",
124
+ n(e.totalAmountMinor, e.currency),
125
+ "."
126
+ ] }, JSON.stringify([
127
+ e.currency,
128
+ e.payerReference,
129
+ t
130
+ ])))]
131
+ }, e))
132
+ ]
133
+ });
134
+ }
135
+ function s({ record: e }) {
136
+ return /* @__PURE__ */ a("section", {
137
+ className: "min-w-0 space-y-4 break-words",
138
+ children: [
139
+ /* @__PURE__ */ a("h2", {
140
+ className: "text-lg font-semibold",
141
+ children: ["Immutable comparison revision ", e.revision]
142
+ }),
143
+ /* @__PURE__ */ a("p", { children: [
144
+ "Invoice ",
145
+ e.facts.invoiceReference,
146
+ "; supplier",
147
+ " ",
148
+ e.facts.supplierLabel ?? "Unknown label",
149
+ " (",
150
+ e.facts.supplierReference,
151
+ "). Source",
152
+ " ",
153
+ e.facts.sourceReference,
154
+ " / ",
155
+ e.facts.sourceRevision,
156
+ "; invoice date",
157
+ " ",
158
+ e.facts.invoiceDate ?? "Unknown",
159
+ "."
160
+ ] }),
161
+ /* @__PURE__ */ a("p", { children: [
162
+ "Recorded ",
163
+ e.recordedAt,
164
+ " by ",
165
+ e.createdBy,
166
+ ", ",
167
+ t(e.actorProvenance),
168
+ "; on behalf of ",
169
+ e.onBehalfOf ?? "Not declared",
170
+ ". Method ",
171
+ e.methodVersion,
172
+ "."
173
+ ] }),
174
+ e.correctionReason && /* @__PURE__ */ a("p", { children: [
175
+ "Correction reason: ",
176
+ e.correctionReason,
177
+ "; predecessor ",
178
+ e.previousComparisonId,
179
+ "."
180
+ ] }),
181
+ /* @__PURE__ */ a("details", { children: [/* @__PURE__ */ i("summary", {
182
+ className: "min-h-11 cursor-pointer font-medium",
183
+ children: "Original reported rows and exact evidence"
184
+ }), /* @__PURE__ */ a("div", {
185
+ className: "space-y-3",
186
+ children: [e.facts.rows.map((e) => /* @__PURE__ */ a("article", {
187
+ className: "rounded border p-3",
188
+ children: [
189
+ /* @__PURE__ */ a("h3", { children: [
190
+ e.description,
191
+ " (",
192
+ e.id,
193
+ ")"
194
+ ] }),
195
+ /* @__PURE__ */ a("p", { children: [
196
+ "Mapping ",
197
+ e.estimateLineId ?? "Unmatched",
198
+ "; amount",
199
+ " ",
200
+ n(e.amountMinor, e.currency),
201
+ "; payer ",
202
+ e.payerLabel ?? "Unknown",
203
+ " (",
204
+ e.payerReference ?? "Unknown reference",
205
+ ")."
206
+ ] }),
207
+ /* @__PURE__ */ a("p", { children: [
208
+ "Quantity ",
209
+ e.quantity ?? "Unknown",
210
+ " ",
211
+ e.unit ?? "unknown unit",
212
+ "; supplied rate",
213
+ " ",
214
+ e.unitRateMajor ?? "Unknown",
215
+ ". Invoice amount was not recalculated."
216
+ ] }),
217
+ e.zeroReason && /* @__PURE__ */ a("p", { children: ["Zero reason: ", e.zeroReason] })
218
+ ]
219
+ }, e.id)), e.evidence.map((e) => /* @__PURE__ */ a("p", {
220
+ className: "break-all",
221
+ children: [
222
+ "File ",
223
+ e.fileId,
224
+ ", exact version ",
225
+ e.versionId,
226
+ "; SHA256 ",
227
+ e.sha256Hash,
228
+ "; checked",
229
+ " ",
230
+ e.checkedAt,
231
+ ". Point-in-time eligibility only."
232
+ ]
233
+ }, e.versionId))]
234
+ })] }),
235
+ /* @__PURE__ */ i(o, { value: e })
236
+ ]
237
+ });
238
+ }
239
+ //#endregion
240
+ export { s as InvoiceHistoryRecord, o as InvoiceResults };