ngx-t-forms-types 0.0.33 → 0.0.35
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/dist/interfaces/Import/ImportIdentity.d.ts +32 -0
- package/dist/interfaces/Import/ImportIdentity.js +1 -0
- package/dist/interfaces/Import/ImportProgress.d.ts +12 -1
- package/dist/interfaces/Import/ImportRowState.d.ts +52 -1
- package/dist/interfaces/Import/index.d.ts +2 -1
- package/dist/interfaces/formInput/IMscoaAccount.d.ts +41 -0
- package/dist/schemas/MscoaConfigSchema.d.ts +6 -0
- package/dist/schemas/MscoaConfigSchema.js +16 -2
- package/dist/skillet/input-members.d.ts +3 -0
- package/dist/skillet/members/mscoa.d.ts +11 -0
- package/dist/skillet/members/mscoa.js +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How an import session decides that two rows are the same record.
|
|
3
|
+
*
|
|
4
|
+
* Passed to the import controller's `runImport` / `runMultipleInputImport`
|
|
5
|
+
* as per-import data — which fields identify a record in *this* form — not
|
|
6
|
+
* as application configuration. Only rows of the one session are compared;
|
|
7
|
+
* records already persisted are the server's to check.
|
|
8
|
+
*
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
export interface ImportIdentity {
|
|
12
|
+
/**
|
|
13
|
+
* `formControlName`s that together identify a record (for a multiple-input
|
|
14
|
+
* import: the child inputs' `formControlName`s). A row whose values for all
|
|
15
|
+
* of them repeat an earlier row's is a duplicate of that row. Empty or
|
|
16
|
+
* absent disables duplicate detection. A name the form does not have
|
|
17
|
+
* rejects the run rather than matching nothing.
|
|
18
|
+
*/
|
|
19
|
+
readonly distinctKeys: readonly string[];
|
|
20
|
+
/**
|
|
21
|
+
* What to do with a duplicate.
|
|
22
|
+
*
|
|
23
|
+
* - `skip` — the row is never processed: no tower, no fetches. It is
|
|
24
|
+
* reported with status `duplicate` and `duplicateOf` naming the row it
|
|
25
|
+
* repeats. The default.
|
|
26
|
+
* - `flag` — the row is processed and validated like any other and keeps
|
|
27
|
+
* its real status; only `duplicateOf` marks it. For hosts that want to
|
|
28
|
+
* show what the duplicate contained. Such a row still must not be
|
|
29
|
+
* imported.
|
|
30
|
+
*/
|
|
31
|
+
readonly onDuplicate?: 'skip' | 'flag';
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -14,7 +14,11 @@ export interface ImportProgress {
|
|
|
14
14
|
pending: number;
|
|
15
15
|
/** Rows currently processing. */
|
|
16
16
|
processing: number;
|
|
17
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* `valid` + `overridable` + `invalid` + rows held with status `duplicate` —
|
|
19
|
+
* i.e. rows that reached an outcome. `complete + error === total` once a
|
|
20
|
+
* run has finished, duplicates included.
|
|
21
|
+
*/
|
|
18
22
|
complete: number;
|
|
19
23
|
/** Rows that settled with no errors. */
|
|
20
24
|
valid: number;
|
|
@@ -24,6 +28,13 @@ export interface ImportProgress {
|
|
|
24
28
|
invalid: number;
|
|
25
29
|
/** Rows that threw before settling. */
|
|
26
30
|
error: number;
|
|
31
|
+
/**
|
|
32
|
+
* Rows recognised as repeating an earlier row (`duplicateOf` set). Under
|
|
33
|
+
* the default `skip` policy these carry status `duplicate` and are counted
|
|
34
|
+
* in `complete`; under `flag` they keep their real status and are counted
|
|
35
|
+
* there as well.
|
|
36
|
+
*/
|
|
37
|
+
duplicate: number;
|
|
27
38
|
/** Underlying array — useful for rendering per-row UI. */
|
|
28
39
|
rows: ImportRowState[];
|
|
29
40
|
}
|
|
@@ -13,12 +13,19 @@
|
|
|
13
13
|
* pre-process error (a row carrying both blocking and overridable errors is
|
|
14
14
|
* `invalid`, not `overridable`).
|
|
15
15
|
* - `error` — `_processRow` threw before settle (tower init failure, etc.).
|
|
16
|
+
* - `duplicate` — the row repeats an earlier row of the session on the
|
|
17
|
+
* fields the import was given as its identity (`ImportIdentity`), and is
|
|
18
|
+
* held out of the import; {@link ImportRowState.duplicateOf} names the row
|
|
19
|
+
* it repeats. A row skipped before its tower was built has no other
|
|
20
|
+
* verdict; one recognised only after it settled keeps its settled value
|
|
21
|
+
* and errors under this status. Under `onDuplicate: 'flag'` a duplicate
|
|
22
|
+
* keeps its real status instead and only `duplicateOf` marks it.
|
|
16
23
|
*
|
|
17
24
|
* Upstreamed from `ngx-t-forms` per DECISIONS.md D-016.
|
|
18
25
|
*
|
|
19
26
|
* @public
|
|
20
27
|
*/
|
|
21
|
-
export type ImportRowStatus = 'pending' | 'processing' | 'valid' | 'overridable' | 'invalid' | 'error';
|
|
28
|
+
export type ImportRowStatus = 'pending' | 'processing' | 'valid' | 'overridable' | 'invalid' | 'error' | 'duplicate';
|
|
22
29
|
/**
|
|
23
30
|
* Per-row state recorded throughout an import session.
|
|
24
31
|
*
|
|
@@ -63,4 +70,48 @@ export interface ImportRowState {
|
|
|
63
70
|
colErrors?: Record<string, string>;
|
|
64
71
|
/** Free-form message attached when `status === 'error'`. */
|
|
65
72
|
errorMessage?: string;
|
|
73
|
+
/**
|
|
74
|
+
* formControlName → the cells of a choice field (select, autocomplete,
|
|
75
|
+
* paginated selection table) whose text matched MORE THAN ONE of the
|
|
76
|
+
* field's options, with the options it could be. The import accepts an
|
|
77
|
+
* option's visible label (or, for a table, any of its column values) in
|
|
78
|
+
* place of its stored value; a unique match is substituted silently, a
|
|
79
|
+
* tie is reported here so the user can pick, and the row stays `invalid`
|
|
80
|
+
* (`colErrors` carries `ambiguousOption:<text>`) until each is settled.
|
|
81
|
+
* A multi-select cell lists one entry per unsettled value.
|
|
82
|
+
*/
|
|
83
|
+
optionChoices?: Record<string, ImportOptionChoice[]>;
|
|
84
|
+
/**
|
|
85
|
+
* The `rowIndex` of the earlier row this row repeats, when the session was
|
|
86
|
+
* given an `ImportIdentity` and this row's identity matches. Always the
|
|
87
|
+
* LOWEST index of the matching group — first wins — so the relation is
|
|
88
|
+
* stable and a host can offer "go to row N". Set under both duplicate
|
|
89
|
+
* policies; under `skip` the row's `status` is `duplicate` as well. Cleared
|
|
90
|
+
* when a re-run changes the identities so that the row no longer repeats
|
|
91
|
+
* anything.
|
|
92
|
+
*/
|
|
93
|
+
duplicateOf?: number;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* One option an imported cell could stand for.
|
|
97
|
+
*
|
|
98
|
+
* @public
|
|
99
|
+
*/
|
|
100
|
+
export interface ImportOptionCandidate {
|
|
101
|
+
/** The value the form stores when this option is chosen. */
|
|
102
|
+
value: unknown;
|
|
103
|
+
/** What the form shows for the option — its label, or a table row's column values. */
|
|
104
|
+
label: string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* An imported cell (or one value of a multi-select cell) whose text matched
|
|
108
|
+
* several options of a choice field. See {@link ImportRowState.optionChoices}.
|
|
109
|
+
*
|
|
110
|
+
* @public
|
|
111
|
+
*/
|
|
112
|
+
export interface ImportOptionChoice {
|
|
113
|
+
/** The text as it was imported. */
|
|
114
|
+
text: string;
|
|
115
|
+
/** The options it matched, in the field's option order. */
|
|
116
|
+
candidates: ImportOptionCandidate[];
|
|
66
117
|
}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export { ImportRowState, ImportRowStatus } from './ImportRowState.js';
|
|
1
|
+
export { ImportOptionCandidate, ImportOptionChoice, ImportRowState, ImportRowStatus } from './ImportRowState.js';
|
|
2
2
|
export { ImportProgress } from './ImportProgress.js';
|
|
3
|
+
export { ImportIdentity } from './ImportIdentity.js';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { MscoaValuetValidationErrors } from "../environment/IStoreFunctions.js";
|
|
2
2
|
import { IBasicFormInput } from "./BasicFormInputInterface.js";
|
|
3
|
+
import { MinInputMapInput } from "./MinimumInputRequiredInterface.js";
|
|
3
4
|
import { ScoaInnerInput } from "./MscoaInput.js";
|
|
4
5
|
export interface IVersion {
|
|
5
6
|
versionNumber: number;
|
|
@@ -120,6 +121,34 @@ export interface IIncludedSegmentConfig {
|
|
|
120
121
|
additionalAccounts: string[];
|
|
121
122
|
segmentExtension: boolean;
|
|
122
123
|
id: string;
|
|
124
|
+
/**
|
|
125
|
+
* Optional account-path limit for the picker: a colon-separated path into this
|
|
126
|
+
* segment's branch of the account tree, e.g.
|
|
127
|
+
* `Net Assets:Reserves and Funds:Revaluation Reserve`. When set, the account
|
|
128
|
+
* picker shows only that branch — its ancestors stay visible as context but
|
|
129
|
+
* cannot be selected — so only accounts at or beneath it can be chosen.
|
|
130
|
+
*
|
|
131
|
+
* Absent or empty means every branch of the segment is selectable, which is
|
|
132
|
+
* exactly how every segment saved before this member existed behaves. A path
|
|
133
|
+
* the loaded tree does not contain is ignored the same way, so a stale limit
|
|
134
|
+
* can never lock a segment out of every account.
|
|
135
|
+
*/
|
|
136
|
+
limitToChildOfAccount?: string;
|
|
137
|
+
/**
|
|
138
|
+
* Optional dynamic source for {@link IIncludedSegmentConfig.limitToChildOfAccount}:
|
|
139
|
+
* another form input whose CURRENT value supplies the account path at the
|
|
140
|
+
* moment the picker opens. Shaped exactly like a required-input `mapTo`
|
|
141
|
+
* binding ({@link MinInputMapInput}); the runtime reads the input by `inputId`
|
|
142
|
+
* from the form the MSCOA field belongs to (an account-level custom input of
|
|
143
|
+
* the same MSCOA field is reachable too).
|
|
144
|
+
*
|
|
145
|
+
* The mapped value is honoured when it is a string — or an array of strings,
|
|
146
|
+
* one per level — naming a branch that exists in the segment tree. Otherwise
|
|
147
|
+
* the fixed `limitToChildOfAccount` applies when it resolves, and failing that
|
|
148
|
+
* every branch stays selectable. The mapping can therefore never lock the
|
|
149
|
+
* segment on its own, and an unfilled source input falls back gracefully.
|
|
150
|
+
*/
|
|
151
|
+
limitToChildOfAccountMapTo?: MinInputMapInput;
|
|
123
152
|
}
|
|
124
153
|
/**
|
|
125
154
|
* How the {@link IDualCashExclusionConfig.rules} combine into one verdict.
|
|
@@ -198,6 +227,18 @@ export interface IScoaInputConfig {
|
|
|
198
227
|
* non-Dual accounting bases.
|
|
199
228
|
*/
|
|
200
229
|
dualCashExclusion?: IDualCashExclusionConfig;
|
|
230
|
+
/**
|
|
231
|
+
* Opt-in: lets the user pick an account at ANY level of the tree, not only a
|
|
232
|
+
* posting-level one (`PostingLevel === 'Y'`, plus `BreakDownAllowed === 'Y'`
|
|
233
|
+
* on the PROJECT segment). Absent or `false` keeps the posting-level
|
|
234
|
+
* restriction every input had before this member existed.
|
|
235
|
+
*
|
|
236
|
+
* The restriction is enforced by the picker alone — nothing downstream
|
|
237
|
+
* re-validates posting level — so enabling it widens what a form can capture,
|
|
238
|
+
* and a consumer that posts the captured account to a ledger must be prepared
|
|
239
|
+
* for a group-level account.
|
|
240
|
+
*/
|
|
241
|
+
allowNonPostingLevelAccount?: boolean;
|
|
201
242
|
}
|
|
202
243
|
export interface IGetTreeResponse {
|
|
203
244
|
message: string;
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import Joi from 'joi';
|
|
2
|
+
/**
|
|
3
|
+
* Joi shape of the `MinInputMapInput` a segment may name as the dynamic source
|
|
4
|
+
* of its account-path limit. `inputId` is the only member the runtime reads;
|
|
5
|
+
* the other three are the descriptive half the builder stamps alongside it.
|
|
6
|
+
*/
|
|
7
|
+
export declare const AccountPathLimitSourceSchema: Joi.ObjectSchema<any>;
|
|
2
8
|
export declare const IncludedSegmentConfigSchema: Joi.ObjectSchema<any>;
|
|
3
9
|
export declare const DualCashExclusionRuleSchema: Joi.ObjectSchema<any>;
|
|
4
10
|
export declare const DualCashExclusionConfigSchema: Joi.ObjectSchema<any>;
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import Joi from 'joi';
|
|
2
2
|
import { AccountingBasis } from '../interfaces/formInput/IMscoaAccount.js';
|
|
3
|
+
/**
|
|
4
|
+
* Joi shape of the `MinInputMapInput` a segment may name as the dynamic source
|
|
5
|
+
* of its account-path limit. `inputId` is the only member the runtime reads;
|
|
6
|
+
* the other three are the descriptive half the builder stamps alongside it.
|
|
7
|
+
*/
|
|
8
|
+
export const AccountPathLimitSourceSchema = Joi.object({
|
|
9
|
+
inputId: Joi.string().required(),
|
|
10
|
+
formControlName: Joi.string().allow('').optional(),
|
|
11
|
+
dataType: Joi.string().allow('').optional(),
|
|
12
|
+
element: Joi.string().allow('').optional()
|
|
13
|
+
});
|
|
3
14
|
export const IncludedSegmentConfigSchema = Joi.object({
|
|
4
15
|
segment: Joi.string(),
|
|
5
16
|
customSegment: Joi.string().optional(),
|
|
@@ -10,7 +21,9 @@ export const IncludedSegmentConfigSchema = Joi.object({
|
|
|
10
21
|
inheritValueFromAccrual: Joi.boolean().optional(),
|
|
11
22
|
vatSelectonActive: Joi.boolean().optional(),
|
|
12
23
|
segmentExtension: Joi.boolean().required(),
|
|
13
|
-
id: Joi.string().required()
|
|
24
|
+
id: Joi.string().required(),
|
|
25
|
+
limitToChildOfAccount: Joi.string().allow('').optional(),
|
|
26
|
+
limitToChildOfAccountMapTo: AccountPathLimitSourceSchema.optional()
|
|
14
27
|
});
|
|
15
28
|
export const DualCashExclusionRuleSchema = Joi.object({
|
|
16
29
|
id: Joi.string().optional(),
|
|
@@ -32,7 +45,8 @@ export const MscoaInputConfigSchema = Joi.object({
|
|
|
32
45
|
accountingBasis: Joi.string().valid(...Object.values(AccountingBasis)).optional(),
|
|
33
46
|
extensionAccountsForSegments: Joi.array().items(Joi.string()).optional(),
|
|
34
47
|
showAllSegments: Joi.boolean().required(),
|
|
35
|
-
dualCashExclusion: DualCashExclusionConfigSchema.optional()
|
|
48
|
+
dualCashExclusion: DualCashExclusionConfigSchema.optional(),
|
|
49
|
+
allowNonPostingLevelAccount: Joi.boolean().optional()
|
|
36
50
|
});
|
|
37
51
|
export function validateMscoaInputConfig(value) {
|
|
38
52
|
const { error, value: validatedValue } = MscoaInputConfigSchema.validate(value);
|
|
@@ -237,6 +237,7 @@ export declare const draftMemberSchemas: {
|
|
|
237
237
|
inheritValueFromAccrual: import("@hashbrownai/core/src/schema/base").SchemaForUnion<boolean | null>;
|
|
238
238
|
vatSelectonActive: import("@hashbrownai/core/src/schema/base").SchemaForUnion<boolean | null>;
|
|
239
239
|
segmentExtension: s.BooleanType;
|
|
240
|
+
limitToChildOfAccount: import("@hashbrownai/core/src/schema/base").SchemaForUnion<string | null>;
|
|
240
241
|
}>>;
|
|
241
242
|
cashSegments: import("@hashbrownai/core/src/schema/base").SchemaForUnion<{
|
|
242
243
|
segment: string;
|
|
@@ -248,9 +249,11 @@ export declare const draftMemberSchemas: {
|
|
|
248
249
|
inheritValueFromAccrual: boolean | null;
|
|
249
250
|
vatSelectonActive: boolean | null;
|
|
250
251
|
segmentExtension: boolean;
|
|
252
|
+
limitToChildOfAccount: string | null;
|
|
251
253
|
}[] | null>;
|
|
252
254
|
accountValueLabel: s.EnumType<string[]>;
|
|
253
255
|
showAllSegments: s.BooleanType;
|
|
256
|
+
allowNonPostingLevelAccount: import("@hashbrownai/core/src/schema/base").SchemaForUnion<boolean | null>;
|
|
254
257
|
extensionAccountsForSegments: s.ArrayType<s.StringType>;
|
|
255
258
|
dualCashExclusion: import("@hashbrownai/core/src/schema/base").SchemaForUnion<{
|
|
256
259
|
rules: {
|
|
@@ -58,6 +58,12 @@ import { AssertNever } from '../internal/coupling.js';
|
|
|
58
58
|
* `string | undefined`. The builder's segment form declares it
|
|
59
59
|
* `Validators.required`, so a row without one cannot be saved by hand either.
|
|
60
60
|
* Narrower than the interface is the permitted direction; wider is not.
|
|
61
|
+
*
|
|
62
|
+
* `limitToChildOfAccountMapTo` — the run-time binding that reads a segment's
|
|
63
|
+
* account-path limit off another form input — is not offered, for the reason
|
|
64
|
+
* `inputs` is not: it cross-references an input by id, and ids are stamped by
|
|
65
|
+
* the builder after generation. The fixed `limitToChildOfAccount` path IS
|
|
66
|
+
* offered; the binding is authored in the builder's segment editor.
|
|
61
67
|
*/
|
|
62
68
|
export interface MscoaSegmentDraft {
|
|
63
69
|
segment: string;
|
|
@@ -69,6 +75,7 @@ export interface MscoaSegmentDraft {
|
|
|
69
75
|
inheritValueFromAccrual: boolean | null;
|
|
70
76
|
vatSelectonActive: boolean | null;
|
|
71
77
|
segmentExtension: boolean;
|
|
78
|
+
limitToChildOfAccount: string | null;
|
|
72
79
|
}
|
|
73
80
|
export interface MscoaDualCashExclusionRuleDraft {
|
|
74
81
|
pattern: string;
|
|
@@ -89,6 +96,7 @@ export interface MscoaConfigDraft {
|
|
|
89
96
|
extensionAccountsForSegments: string[];
|
|
90
97
|
showAllSegments: boolean;
|
|
91
98
|
dualCashExclusion: MscoaDualCashExclusionDraft | null;
|
|
99
|
+
allowNonPostingLevelAccount: boolean | null;
|
|
92
100
|
}
|
|
93
101
|
/**
|
|
94
102
|
* `DualCashExclusionMatchMode` is a string-union type with no runtime object to
|
|
@@ -130,6 +138,7 @@ export declare const mscoaConfigSchema: s.ObjectType<{
|
|
|
130
138
|
inheritValueFromAccrual: import("@hashbrownai/core/src/schema/base").SchemaForUnion<boolean | null>;
|
|
131
139
|
vatSelectonActive: import("@hashbrownai/core/src/schema/base").SchemaForUnion<boolean | null>;
|
|
132
140
|
segmentExtension: s.BooleanType;
|
|
141
|
+
limitToChildOfAccount: import("@hashbrownai/core/src/schema/base").SchemaForUnion<string | null>;
|
|
133
142
|
}>>;
|
|
134
143
|
cashSegments: import("@hashbrownai/core/src/schema/base").SchemaForUnion<{
|
|
135
144
|
segment: string;
|
|
@@ -141,9 +150,11 @@ export declare const mscoaConfigSchema: s.ObjectType<{
|
|
|
141
150
|
inheritValueFromAccrual: boolean | null;
|
|
142
151
|
vatSelectonActive: boolean | null;
|
|
143
152
|
segmentExtension: boolean;
|
|
153
|
+
limitToChildOfAccount: string | null;
|
|
144
154
|
}[] | null>;
|
|
145
155
|
accountValueLabel: s.EnumType<string[]>;
|
|
146
156
|
showAllSegments: s.BooleanType;
|
|
157
|
+
allowNonPostingLevelAccount: import("@hashbrownai/core/src/schema/base").SchemaForUnion<boolean | null>;
|
|
147
158
|
extensionAccountsForSegments: s.ArrayType<s.StringType>;
|
|
148
159
|
dualCashExclusion: import("@hashbrownai/core/src/schema/base").SchemaForUnion<{
|
|
149
160
|
rules: {
|
|
@@ -57,6 +57,7 @@ const segmentSchema = s.object('One segment of the chart of accounts the user pi
|
|
|
57
57
|
// form already persisted with it.
|
|
58
58
|
vatSelectonActive: optional(s.boolean('Adds the VAT-status column to the account chart. It applies to the ITEM segment, which is the only one carrying a VAT treatment; leave null elsewhere.')),
|
|
59
59
|
segmentExtension: s.boolean('True for an extra level authored under a segment rather than a segment of the published chart. An extension row is keyed by customSegment and may reuse a segment key another row already claims; an ordinary row may not.'),
|
|
60
|
+
limitToChildOfAccount: optional(s.string('Optional colon-separated path into this segment\'s branch of the chart, such as "Net Assets:Reserves and Funds:Revaluation Reserve". When set, the user can only pick accounts at or beneath that branch; the levels above it are shown for context but cannot be selected. Use it when the form captures one known category — a specific reserve, one asset class — and the account must not fall outside it. Leave null to offer the whole segment, which is the usual case. A path the chart does not contain is ignored and the whole segment is offered anyway, so guess nothing: name a branch only when the request states it.')),
|
|
60
61
|
});
|
|
61
62
|
/**
|
|
62
63
|
* One cash-exclusion rule.
|
|
@@ -104,6 +105,7 @@ export const mscoaConfigSchema = s.object(describe('How this control asks the us
|
|
|
104
105
|
cashSegments: optional(s.array('The segments captured on the cash side. Only meaningful when the accounting basis is cash or dual; leave null for an accrual-only input. A cash row that mirrors an accrual one should normally set inheritValueFromAccrual rather than ask the user twice.', segmentSchema)),
|
|
105
106
|
accountValueLabel: s.enumeration(`Which field of the account identifies it to the user, everywhere this control shows one. Choose the field an administrator would read back in the chart of accounts. ${ACCOUNT_VALUE_LABEL_GLOSS}.`, ACCOUNT_VALUE_LABEL_ENTRIES),
|
|
106
107
|
showAllSegments: s.boolean('True reflects every segment of the loaded account tree, read-only, instead of only the ones listed here — the application reconciles the list against the tree, so segments authored here are kept but not exclusive. False shows exactly the segments listed and nothing else, which is the usual choice.'),
|
|
108
|
+
allowNonPostingLevelAccount: optional(s.boolean('True lets the user pick an account at any level of the chart, not only a posting-level account. Leave null — posting-level accounts only, the default every existing input has — unless the request says a group account must be selectable, such as a budget captured at a summary line.')),
|
|
107
109
|
extensionAccountsForSegments: s.array('Names of extra account columns this control offers on top of the ordinary account, each becoming a column on the chart. A segment opts into one by naming it in its own additionalAccounts. Leave empty when the control captures ordinary accounts only.', s.string('An extension-account name, such as a counter-account this form also captures.')),
|
|
108
110
|
dualCashExclusion: optional(s.object('Dual basis only: when the cash side is NOT required, despite the basis asking for both. Leave null to require both sides always, which is the default behaviour and the right answer unless the form has a stated exception.', {
|
|
109
111
|
rules: optional(s.array('The conditions tested against the accounts the user selected on the accrual side. A rule whose pattern does not compile never matches, so it can never suppress the cash side by accident.', dualCashExclusionRuleSchema)),
|