@happyvertical/smrt-svelte 0.56.1 → 0.56.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.
@@ -289,16 +289,22 @@ parent-filter vocabulary (`model`, `field`, `filter: 'parent'`, `sort`,
289
289
  `storedTotals` through `RecordScreen.lineItemStoredTotals`; its totals and
290
290
  per-component tax rows are displayed as persisted (with matching component
291
291
  rows grouped), never reconstructed from the visible lines. Without that
292
- optional snapshot, the widget preserves its legacy totals behavior: the lines
293
- in `sort` order, then the totals block
294
- (`lineItemTotals`, pure). The record's own subtotal / discount / tax /
295
- total are authoritative and shown as they are; one it lacks is computed
296
- from the lines (subtotal = sum of the line amounts, total = subtotal -
297
- discount + tax) and marked "(from the lines)"; discount and tax show when
298
- present and non-zero. When the record's subtotal (or, without one, its
299
- total) disagrees with the lines, a visible flag says "Lines add up to $X."
300
- beside the recorded figure — never a silent override. A partial page of
301
- lines is not compared.
292
+ optional snapshot, the widget shows the lines in `sort` order, then the
293
+ totals block (`lineItemTotals`, pure). The record's own subtotal /
294
+ discount / tax / total are authoritative and shown as they are; one it
295
+ lacks is computed from the lines and marked "(from the lines)"; discount
296
+ and tax show when present and non-zero. There is one money semantic
297
+ (#4010): line amounts are net of discount, or gross when the record's
298
+ `lineAmountType` (read by `recordTotals` when the view shows it) is
299
+ `inclusive`, with net = gross - tax; a record without one is `exclusive`.
300
+ subtotal = sum of the net lines, total = subtotal + tax, and the discount
301
+ is shown as "Includes discounts of" and never subtracted. An unavailable
302
+ tax (no field, or policy-hidden) is unknown rather than zero, so inclusive
303
+ lines then yield no net and no total is computed or compared from the
304
+ lines. When the record's subtotal (or, without one, its total) disagrees
305
+ with the lines, a visible flag says "Lines add up to $X." beside the
306
+ recorded figure — never a silent override. A partial page of lines is not
307
+ compared.
302
308
  - Tests: `__tests__/record-table.test.ts`, `__tests__/record-widgets.test.ts`,
303
309
  `__tests__/line-items.test.ts` (axe on both components), the records cases
304
310
  in `__tests__/widgets.test.ts`.
@@ -144,6 +144,9 @@ const LABELS = {
144
144
  {:else if result.lines.length > 0}
145
145
  <dl class="smrt-line-items__totals">
146
146
  {#each result.lines as line (line.key)}
147
+ {#if line.included}
148
+ <div class="smrt-line-items__total smrt-line-items__total--muted"><dt>{t(M['ui.overview.line_items.discount_included'])} {money(Math.abs(line.value))}</dt></div>
149
+ {:else}
147
150
  <div class="smrt-line-items__total" class:smrt-line-items__total--grand={line.key === 'total'}>
148
151
  <dt>
149
152
  {t(LABELS[line.key])}
@@ -151,6 +154,7 @@ const LABELS = {
151
154
  </dt>
152
155
  <dd>{line.key === 'discount' ? `−${money(line.value)}` : money(line.value)}</dd>
153
156
  </div>
157
+ {/if}
154
158
  {/each}
155
159
  </dl>
156
160
  {/if}
@@ -1 +1 @@
1
- {"version":3,"file":"LineItemsWidget.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/overview/widgets/LineItemsWidget.svelte.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAY,KAAK,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAgK/D,QAAA,MAAM,eAAe,+EAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"LineItemsWidget.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/overview/widgets/LineItemsWidget.svelte.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAY,KAAK,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAoK/D,QAAA,MAAM,eAAe,+EAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
@@ -129,6 +129,8 @@ export interface LineItemsWidgetData {
129
129
  discount?: number | null;
130
130
  tax?: number | null;
131
131
  total?: number | null;
132
+ /** How the lines treat tax; absent means `exclusive`. */
133
+ lineAmountType?: 'exclusive' | 'inclusive' | 'none' | null;
132
134
  };
133
135
  /** Frozen document-money snapshot supplied by a domain host. */
134
136
  storedTotals?: {
@@ -1 +1 @@
1
- {"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../../../src/components/overview/widgets/data.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../../../src/components/overview/widgets/data.ts"],"names":[],"mappings":"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"}
@@ -2,20 +2,33 @@
2
2
  * The totals block of a document's line items (#3718 record page), pure and
3
3
  * Node-tested. The record's own subtotal / discount / tax / total are
4
4
  * authoritative and shown as they are; a missing one is computed from the
5
- * lines (subtotal = sum of line amounts, total = subtotal - discount + tax).
6
- * Lines that add up to the recorded total are tax-inclusive and agree.
7
- * When the record's figures disagree with the lines, the block flags it
8
- * ("Lines add up to $X") instead of silently overriding either side.
5
+ * lines. When the record's figures disagree with the lines, the block flags
6
+ * it ("Lines add up to $X") instead of silently overriding either side.
7
+ *
8
+ * One money semantic (#4010), smrt-commerce's document money: line amounts
9
+ * are net of discount, or gross (tax included) when the record's
10
+ * `lineAmountType` is `inclusive`, where net = gross - tax. A record without
11
+ * a `lineAmountType` is `exclusive`. subtotal = sum of the net lines,
12
+ * total = subtotal + tax, and the discount is already inside the lines: it
13
+ * is shown as included and never subtracted. An unavailable tax (no field,
14
+ * or one the policy hides) is unknown, never zero, so no figure that needs
15
+ * it is computed or compared from the lines.
9
16
  *
10
17
  * Money is integer minor units throughout.
11
18
  */
19
+ /** How a document's line amounts treat tax (smrt-commerce `lineAmountType`). */
20
+ export type LineAmountType = 'exclusive' | 'inclusive' | 'none';
12
21
  /** The record's own totals fields (`subtotal` / `discount` / `tax` / `total` roles). */
13
22
  export interface LineItemsTotals {
14
23
  subtotal?: number | null;
15
24
  discount?: number | null;
16
25
  tax?: number | null;
17
26
  total?: number | null;
27
+ /** The record's `lineAmountType`; absent means `exclusive`. */
28
+ lineAmountType?: LineAmountType | null;
18
29
  }
30
+ /** Whether `value` is a `lineAmountType` the totals block understands. */
31
+ export declare function isLineAmountType(value: unknown): value is LineAmountType;
19
32
  /** A frozen per-component tax row supplied by a domain host. */
20
33
  export interface StoredTaxComponent {
21
34
  taxComponentId: string;
@@ -34,7 +47,7 @@ export interface StoredLineItemsTotals extends LineItemsTotals {
34
47
  discount: number;
35
48
  tax: number;
36
49
  total: number;
37
- lineAmountType: 'exclusive' | 'inclusive' | 'none';
50
+ lineAmountType: LineAmountType;
38
51
  roundingScope: 'line' | 'document';
39
52
  /** Whether an inclusive taxed document should expose its net subtotal. */
40
53
  showNetSubtotal?: boolean;
@@ -57,6 +70,8 @@ export interface LineTotalLine {
57
70
  value: number;
58
71
  /** Computed here (the record has no such field or value), not read from the record. */
59
72
  computed: boolean;
73
+ /** Already inside the subtotal (the discount): shown, not subtracted. */
74
+ included?: boolean;
60
75
  }
61
76
  export interface LineTotalsMismatch {
62
77
  /** The record figure the lines disagree with. */
@@ -1 +1 @@
1
- {"version":3,"file":"line-totals.d.ts","sourceRoot":"","sources":["../../../../src/components/overview/widgets/line-totals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,wFAAwF;AACxF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,gEAAgE;AAChE,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAsB,SAAQ,eAAe;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,WAAW,GAAG,WAAW,GAAG,MAAM,CAAC;IACnD,aAAa,EAAE,MAAM,GAAG,UAAU,CAAC;IACnC,0EAA0E;IAC1E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,EAAE,SAAS,kBAAkB,EAAE,CAAC;CACtC;AAED,sEAAsE;AACtE,MAAM,WAAW,uBAAwB,SAAQ,kBAAkB;CAAG;AAEtE,4EAA4E;AAC5E,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,qBAAqB,CAchC;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,SAAS,kBAAkB,EAAE,GACnC,uBAAuB,EAAE,CA0B3B;AAED,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,UAAU,GAAG,KAAK,GAAG,OAAO,CAAC;AAErE,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,YAAY,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,uFAAuF;IACvF,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC;IAC5B,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,oEAAoE;IACpE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACrC;AAQD,yFAAyF;AACzF,wBAAgB,cAAc,CAAC,OAAO,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,GAAG,IAAI,CAUzE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,eAAe,GAAG,SAAS,EACnC,OAAO,EAAE,MAAM,GAAG,IAAI,GACrB,gBAAgB,CA2DlB"}
1
+ {"version":3,"file":"line-totals.d.ts","sourceRoot":"","sources":["../../../../src/components/overview/widgets/line-totals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,gFAAgF;AAChF,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,WAAW,GAAG,MAAM,CAAC;AAEhE,wFAAwF;AACxF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;CACxC;AAED,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAExE;AAED,gEAAgE;AAChE,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAsB,SAAQ,eAAe;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,cAAc,CAAC;IAC/B,aAAa,EAAE,MAAM,GAAG,UAAU,CAAC;IACnC,0EAA0E;IAC1E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,EAAE,SAAS,kBAAkB,EAAE,CAAC;CACtC;AAED,sEAAsE;AACtE,MAAM,WAAW,uBAAwB,SAAQ,kBAAkB;CAAG;AAEtE,4EAA4E;AAC5E,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,qBAAqB,CAYhC;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,SAAS,kBAAkB,EAAE,GACnC,uBAAuB,EAAE,CA0B3B;AAED,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,UAAU,GAAG,KAAK,GAAG,OAAO,CAAC;AAErE,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,YAAY,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,uFAAuF;IACvF,QAAQ,EAAE,OAAO,CAAC;IAClB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC;IAC5B,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,oEAAoE;IACpE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACrC;AAQD,yFAAyF;AACzF,wBAAgB,cAAc,CAAC,OAAO,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,GAAG,IAAI,CAUzE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,eAAe,GAAG,SAAS,EACnC,OAAO,EAAE,MAAM,GAAG,IAAI,GACrB,gBAAgB,CAwElB"}
@@ -2,21 +2,30 @@
2
2
  * The totals block of a document's line items (#3718 record page), pure and
3
3
  * Node-tested. The record's own subtotal / discount / tax / total are
4
4
  * authoritative and shown as they are; a missing one is computed from the
5
- * lines (subtotal = sum of line amounts, total = subtotal - discount + tax).
6
- * Lines that add up to the recorded total are tax-inclusive and agree.
7
- * When the record's figures disagree with the lines, the block flags it
8
- * ("Lines add up to $X") instead of silently overriding either side.
5
+ * lines. When the record's figures disagree with the lines, the block flags
6
+ * it ("Lines add up to $X") instead of silently overriding either side.
7
+ *
8
+ * One money semantic (#4010), smrt-commerce's document money: line amounts
9
+ * are net of discount, or gross (tax included) when the record's
10
+ * `lineAmountType` is `inclusive`, where net = gross - tax. A record without
11
+ * a `lineAmountType` is `exclusive`. subtotal = sum of the net lines,
12
+ * total = subtotal + tax, and the discount is already inside the lines: it
13
+ * is shown as included and never subtracted. An unavailable tax (no field,
14
+ * or one the policy hides) is unknown, never zero, so no figure that needs
15
+ * it is computed or compared from the lines.
9
16
  *
10
17
  * Money is integer minor units throughout.
11
18
  */
19
+ /** Whether `value` is a `lineAmountType` the totals block understands. */
20
+ export function isLineAmountType(value) {
21
+ return value === 'exclusive' || value === 'inclusive' || value === 'none';
22
+ }
12
23
  /** Whether untrusted widget data is a complete persisted money snapshot. */
13
24
  export function isStoredLineItemsTotals(value) {
14
25
  if (!value || typeof value !== 'object' || Array.isArray(value))
15
26
  return false;
16
27
  const record = value;
17
- return ((record.lineAmountType === 'exclusive' ||
18
- record.lineAmountType === 'inclusive' ||
19
- record.lineAmountType === 'none') &&
28
+ return (isLineAmountType(record.lineAmountType) &&
20
29
  (record.roundingScope === 'line' || record.roundingScope === 'document') &&
21
30
  Number.isSafeInteger(record.subtotal) &&
22
31
  Number.isSafeInteger(record.discount) &&
@@ -79,17 +88,22 @@ export function sumLineAmounts(amounts) {
79
88
  * (`null` when the lines are a partial page and the host sent no sum).
80
89
  */
81
90
  export function lineItemTotals(record, lineSum) {
91
+ const inclusive = record?.lineAmountType === 'inclusive';
82
92
  const subtotalRecorded = money(record?.subtotal);
83
93
  const discount = money(record?.discount);
84
94
  const tax = money(record?.tax);
85
95
  const totalRecorded = money(record?.total);
86
96
  const lines = [];
87
- // Line amounts may be tax-inclusive (smrt-commerce's are: qty x price -
88
- // discount + tax), so lines adding up to the recorded total agree with the
89
- // record, and a missing subtotal is backed out of that total, not the sum.
90
- const inclusive = lineSum !== null && totalRecorded !== null && lineSum === totalRecorded;
91
- const subtotal = subtotalRecorded ??
92
- (inclusive ? totalRecorded + (discount ?? 0) - (tax ?? 0) : lineSum);
97
+ // Inclusive lines are gross: net = gross - tax. Without the tax there is
98
+ // no net to derive from them.
99
+ const netFromLines = lineSum === null
100
+ ? null
101
+ : inclusive
102
+ ? tax === null
103
+ ? null
104
+ : lineSum - tax
105
+ : lineSum;
106
+ const subtotal = subtotalRecorded ?? netFromLines;
93
107
  if (subtotal !== null) {
94
108
  lines.push({
95
109
  key: 'subtotal',
@@ -98,13 +112,18 @@ export function lineItemTotals(record, lineSum) {
98
112
  });
99
113
  }
100
114
  if (discount !== null && discount !== 0) {
101
- lines.push({ key: 'discount', value: discount, computed: false });
115
+ lines.push({
116
+ key: 'discount',
117
+ value: discount,
118
+ computed: false,
119
+ included: true,
120
+ });
102
121
  }
103
122
  if (tax !== null && tax !== 0) {
104
123
  lines.push({ key: 'tax', value: tax, computed: false });
105
124
  }
106
- const computedTotal = subtotal === null ? null : subtotal - (discount ?? 0) + (tax ?? 0);
107
- const total = totalRecorded ?? computedTotal;
125
+ const total = totalRecorded ??
126
+ (subtotal === null || tax === null ? null : subtotal + tax);
108
127
  if (total !== null) {
109
128
  lines.push({
110
129
  key: 'total',
@@ -113,16 +132,18 @@ export function lineItemTotals(record, lineSum) {
113
132
  });
114
133
  }
115
134
  let mismatch = null;
116
- if (lineSum !== null && !inclusive) {
117
- if (subtotalRecorded !== null && subtotalRecorded !== lineSum) {
135
+ if (netFromLines !== null) {
136
+ if (subtotalRecorded !== null && subtotalRecorded !== netFromLines) {
118
137
  mismatch = {
119
138
  field: 'subtotal',
120
139
  recorded: subtotalRecorded,
121
- lines: lineSum,
140
+ lines: netFromLines,
122
141
  };
123
142
  }
124
- else if (subtotalRecorded === null && totalRecorded !== null) {
125
- const fromLines = lineSum - (discount ?? 0) + (tax ?? 0);
143
+ else if (subtotalRecorded === null &&
144
+ totalRecorded !== null &&
145
+ tax !== null) {
146
+ const fromLines = netFromLines + tax;
126
147
  if (fromLines !== totalRecorded) {
127
148
  mismatch = {
128
149
  field: 'total',
@@ -1,3 +1,17 @@
1
+ /**
2
+ * The record page header (#3718 record page), pure and Node-tested: the
3
+ * heading, the monospace identifier, the status and two to four key facts,
4
+ * all read by role from the fields the screen may show (so a field the
5
+ * policy omits can never reach the header).
6
+ *
7
+ * - Heading: the `title` prop, else a document's kind and identifier
8
+ * ("Order GRA-3159", never the customer), else the title-role field, else
9
+ * the identifier, else the class name.
10
+ * - Facts, in order: the party (a link), the lead date, the total money (the
11
+ * `total` role, else the first money field), then a contact (email, then
12
+ * phone) while there is room. Empty values are skipped.
13
+ */
14
+ import { type LineAmountType } from '../overview/widgets/line-totals.js';
1
15
  import { type ScreenFieldRoles } from './roles.js';
2
16
  import type { ScreenCollectionDefinition, ScreenField, ScreenRecord } from './types.js';
3
17
  export type RecordFactKind = 'party' | 'date' | 'money' | 'contact';
@@ -34,9 +48,10 @@ export declare function deriveRecordHeader(definition: ScreenCollectionDefinitio
34
48
  }): RecordHeaderModel;
35
49
  /**
36
50
  * The record's own totals, read by role (`subtotal`, `discount`, `tax`,
37
- * `total`): what the line-items totals block shows as authoritative. With
38
- * `visible` (the policy-filtered view fields), a field the policy omits is
39
- * never read.
51
+ * `total`): what the line-items totals block shows as authoritative, plus
52
+ * the record's `lineAmountType` when it has a valid one, which tells the
53
+ * block whether the lines are gross (#4010). With `visible` (the
54
+ * policy-filtered view fields), a field the policy omits is never read.
40
55
  */
41
56
  export declare function recordTotals(record: ScreenRecord, roles: ScreenFieldRoles, visible?: readonly {
42
57
  name: string;
@@ -45,6 +60,7 @@ export declare function recordTotals(record: ScreenRecord, roles: ScreenFieldRol
45
60
  discount?: number | null;
46
61
  tax?: number | null;
47
62
  total?: number | null;
63
+ lineAmountType?: LineAmountType;
48
64
  };
49
65
  /** Fields holding a totals role (`subtotal` / `discount` / `tax` / `total`). */
50
66
  export declare function totalsFields(roles: ScreenFieldRoles): string[];
@@ -1 +1 @@
1
- {"version":3,"file":"record-header.d.ts","sourceRoot":"","sources":["../../../src/components/screens/record-header.ts"],"names":[],"mappings":"AAcA,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,KAAK,EACV,0BAA0B,EAC1B,WAAW,EACX,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;AAEpE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,iBAAiB,EAAE,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,iEAAiE;IACjE,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,kCAAkC;AAClC,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAYzC;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,0BAA0B,EACtC,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,gBAAgB,EACvB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClD,iBAAiB,CAyEnB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,gBAAgB,EACvB,OAAO,CAAC,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GACpC;IACD,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAcA;AAED,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,EAAE,CAM9D"}
1
+ {"version":3,"file":"record-header.d.ts","sourceRoot":"","sources":["../../../src/components/screens/record-header.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAEL,KAAK,cAAc,EACpB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,KAAK,EACV,0BAA0B,EAC1B,WAAW,EACX,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;AAEpE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,iBAAiB,EAAE,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,iEAAiE;IACjE,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,kCAAkC;AAClC,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAYzC;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,0BAA0B,EACtC,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,gBAAgB,EACvB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClD,iBAAiB,CAyEnB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,gBAAgB,EACvB,OAAO,CAAC,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GACpC;IACD,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC,CA0BA;AAED,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,EAAE,CAM9D"}
@@ -11,6 +11,7 @@
11
11
  * `total` role, else the first money field), then a contact (email, then
12
12
  * phone) while there is room. Empty values are skipped.
13
13
  */
14
+ import { isLineAmountType, } from '../overview/widgets/line-totals.js';
14
15
  import { screenTitles } from './fields.js';
15
16
  import { isDocumentLike } from './roles.js';
16
17
  /** Most key facts in a header. */
@@ -95,9 +96,10 @@ export function deriveRecordHeader(definition, fields, record, roles, options =
95
96
  }
96
97
  /**
97
98
  * The record's own totals, read by role (`subtotal`, `discount`, `tax`,
98
- * `total`): what the line-items totals block shows as authoritative. With
99
- * `visible` (the policy-filtered view fields), a field the policy omits is
100
- * never read.
99
+ * `total`): what the line-items totals block shows as authoritative, plus
100
+ * the record's `lineAmountType` when it has a valid one, which tells the
101
+ * block whether the lines are gross (#4010). With `visible` (the
102
+ * policy-filtered view fields), a field the policy omits is never read.
101
103
  */
102
104
  export function recordTotals(record, roles, visible) {
103
105
  const out = {};
@@ -110,6 +112,10 @@ export function recordTotals(record, roles, visible) {
110
112
  out[role] =
111
113
  typeof value === 'number' && Number.isSafeInteger(value) ? value : null;
112
114
  }
115
+ if (isLineAmountType(record.lineAmountType) &&
116
+ (!visible || visible.some((f) => f.name === 'lineAmountType'))) {
117
+ out.lineAmountType = record.lineAmountType;
118
+ }
113
119
  return out;
114
120
  }
115
121
  /** Fields holding a totals role (`subtotal` / `discount` / `tax` / `total`). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-svelte",
3
- "version": "0.56.1",
3
+ "version": "0.56.2",
4
4
  "smrtJsdoc": "strict",
5
5
  "description": "Svelte 5 components for SMRT user management - auth, users, tenants, roles, permissions, groups",
6
6
  "type": "module",
@@ -205,11 +205,11 @@
205
205
  },
206
206
  "dependencies": {
207
207
  "@happyvertical/logger": "^0.103.7",
208
- "@happyvertical/smrt-languages": "0.56.1",
209
- "@happyvertical/smrt-mcp-apps": "0.56.1",
210
- "@happyvertical/smrt-types": "0.56.1",
211
- "@happyvertical/smrt-ui": "0.56.1",
212
- "@happyvertical/smrt-web": "0.56.1",
208
+ "@happyvertical/smrt-languages": "0.56.2",
209
+ "@happyvertical/smrt-mcp-apps": "0.56.2",
210
+ "@happyvertical/smrt-types": "0.56.2",
211
+ "@happyvertical/smrt-ui": "0.56.2",
212
+ "@happyvertical/smrt-web": "0.56.2",
213
213
  "@tanstack/db": "^0.6.14",
214
214
  "@tanstack/svelte-db": "^0.1.91",
215
215
  "esm-env": "^1.2.2"
@@ -244,14 +244,14 @@
244
244
  }
245
245
  },
246
246
  "devDependencies": {
247
- "@happyvertical/smrt-agents": "0.56.1",
248
- "@happyvertical/smrt-chat": "0.56.1",
249
- "@happyvertical/smrt-content": "0.56.1",
250
- "@happyvertical/smrt-core": "0.56.1",
251
- "@happyvertical/smrt-reports": "0.56.1",
252
- "@happyvertical/smrt-scanner": "0.56.1",
253
- "@happyvertical/smrt-tenancy": "0.56.1",
254
- "@happyvertical/smrt-users": "0.56.1",
247
+ "@happyvertical/smrt-agents": "0.56.2",
248
+ "@happyvertical/smrt-chat": "0.56.2",
249
+ "@happyvertical/smrt-content": "0.56.2",
250
+ "@happyvertical/smrt-core": "0.56.2",
251
+ "@happyvertical/smrt-reports": "0.56.2",
252
+ "@happyvertical/smrt-scanner": "0.56.2",
253
+ "@happyvertical/smrt-tenancy": "0.56.2",
254
+ "@happyvertical/smrt-users": "0.56.2",
255
255
  "@happyvertical/speech": "^0.103.7",
256
256
  "@sveltejs/package": "^2.5.8",
257
257
  "@sveltejs/vite-plugin-svelte": "^7.3.0",