@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.
- package/agents/overview-surfaces.md +16 -10
- package/dist/components/overview/widgets/LineItemsWidget.svelte +4 -0
- package/dist/components/overview/widgets/LineItemsWidget.svelte.d.ts.map +1 -1
- package/dist/components/overview/widgets/data.d.ts +2 -0
- package/dist/components/overview/widgets/data.d.ts.map +1 -1
- package/dist/components/overview/widgets/line-totals.d.ts +20 -5
- package/dist/components/overview/widgets/line-totals.d.ts.map +1 -1
- package/dist/components/overview/widgets/line-totals.js +42 -21
- package/dist/components/screens/record-header.d.ts +19 -3
- package/dist/components/screens/record-header.d.ts.map +1 -1
- package/dist/components/screens/record-header.js +9 -3
- package/package.json +14 -14
|
@@ -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
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
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;
|
|
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
|
|
6
|
-
* Lines
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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:
|
|
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
|
|
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
|
|
6
|
-
* Lines
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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
|
|
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
|
-
//
|
|
88
|
-
//
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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({
|
|
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
|
|
107
|
-
|
|
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 (
|
|
117
|
-
if (subtotalRecorded !== null && subtotalRecorded !==
|
|
135
|
+
if (netFromLines !== null) {
|
|
136
|
+
if (subtotalRecorded !== null && subtotalRecorded !== netFromLines) {
|
|
118
137
|
mismatch = {
|
|
119
138
|
field: 'subtotal',
|
|
120
139
|
recorded: subtotalRecorded,
|
|
121
|
-
lines:
|
|
140
|
+
lines: netFromLines,
|
|
122
141
|
};
|
|
123
142
|
}
|
|
124
|
-
else if (subtotalRecorded === null &&
|
|
125
|
-
|
|
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
|
|
38
|
-
* `
|
|
39
|
-
*
|
|
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":"
|
|
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
|
|
99
|
-
* `
|
|
100
|
-
*
|
|
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.
|
|
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.
|
|
209
|
-
"@happyvertical/smrt-mcp-apps": "0.56.
|
|
210
|
-
"@happyvertical/smrt-types": "0.56.
|
|
211
|
-
"@happyvertical/smrt-ui": "0.56.
|
|
212
|
-
"@happyvertical/smrt-web": "0.56.
|
|
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.
|
|
248
|
-
"@happyvertical/smrt-chat": "0.56.
|
|
249
|
-
"@happyvertical/smrt-content": "0.56.
|
|
250
|
-
"@happyvertical/smrt-core": "0.56.
|
|
251
|
-
"@happyvertical/smrt-reports": "0.56.
|
|
252
|
-
"@happyvertical/smrt-scanner": "0.56.
|
|
253
|
-
"@happyvertical/smrt-tenancy": "0.56.
|
|
254
|
-
"@happyvertical/smrt-users": "0.56.
|
|
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",
|