@salesforce/plugin-bre-to-cml 1.2.17 → 1.3.1
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/README.md +117 -4
- package/lib/commands/cml/convert/surcharge-rules.d.ts +12 -0
- package/lib/commands/cml/convert/surcharge-rules.js +79 -5
- package/lib/commands/cml/convert/surcharge-rules.js.map +1 -1
- package/lib/commands/cml/convert/underwriting-rules.d.ts +51 -3
- package/lib/commands/cml/convert/underwriting-rules.js +206 -13
- package/lib/commands/cml/convert/underwriting-rules.js.map +1 -1
- package/lib/commands/insurance/import/record-updates.d.ts +66 -0
- package/lib/commands/insurance/import/record-updates.js +239 -0
- package/lib/commands/insurance/import/record-updates.js.map +1 -0
- package/lib/shared/cml-operators.d.ts +9 -1
- package/lib/shared/cml-operators.js +23 -5
- package/lib/shared/cml-operators.js.map +1 -1
- package/lib/shared/insurance/confirm-org-changes.d.ts +49 -0
- package/lib/shared/insurance/confirm-org-changes.js +43 -0
- package/lib/shared/insurance/confirm-org-changes.js.map +1 -0
- package/lib/shared/insurance/insurance-cml-merge.d.ts +198 -5
- package/lib/shared/insurance/insurance-cml-merge.js +504 -28
- package/lib/shared/insurance/insurance-cml-merge.js.map +1 -1
- package/lib/shared/insurance/insurance-context-tags.d.ts +124 -0
- package/lib/shared/insurance/insurance-context-tags.js +210 -0
- package/lib/shared/insurance/insurance-context-tags.js.map +1 -0
- package/lib/shared/insurance/insurance-org.d.ts +12 -0
- package/lib/shared/insurance/insurance-org.js +38 -2
- package/lib/shared/insurance/insurance-org.js.map +1 -1
- package/lib/shared/insurance/insurance-rule-convert-command.d.ts +27 -0
- package/lib/shared/insurance/insurance-rule-convert-command.js +57 -4
- package/lib/shared/insurance/insurance-rule-convert-command.js.map +1 -1
- package/lib/shared/insurance/insurance-rule-generator.d.ts +101 -8
- package/lib/shared/insurance/insurance-rule-generator.js +293 -42
- package/lib/shared/insurance/insurance-rule-generator.js.map +1 -1
- package/lib/shared/insurance/models.d.ts +2 -1
- package/lib/shared/insurance/planned-change-mapper.d.ts +15 -0
- package/lib/shared/insurance/planned-change-mapper.js +51 -0
- package/lib/shared/insurance/planned-change-mapper.js.map +1 -0
- package/lib/shared/insurance/planned-change.d.ts +83 -0
- package/lib/shared/insurance/planned-change.js +74 -0
- package/lib/shared/insurance/planned-change.js.map +1 -0
- package/lib/shared/insurance/record-update-apply.d.ts +100 -0
- package/lib/shared/insurance/record-update-apply.js +303 -0
- package/lib/shared/insurance/record-update-apply.js.map +1 -0
- package/lib/shared/insurance/record-update-plan.d.ts +104 -0
- package/lib/shared/insurance/record-update-plan.js +397 -0
- package/lib/shared/insurance/record-update-plan.js.map +1 -0
- package/messages/cml.convert.surcharge-rules.md +3 -1
- package/messages/cml.convert.underwriting-rules.md +1 -1
- package/messages/insurance.import.record-updates.md +176 -0
- package/oclif.lock +25 -25
- package/oclif.manifest.json +95 -3
- package/package.json +16 -8
package/README.md
CHANGED
|
@@ -58,6 +58,18 @@ sf plugins
|
|
|
58
58
|
|
|
59
59
|
## Commands
|
|
60
60
|
|
|
61
|
+
> **Review generated files before you import them or apply them to records.** Everything this plugin
|
|
62
|
+
> emits — the `.cml` model, the association CSV, and the `_SurchargeUpdate.json` /
|
|
63
|
+
> `_UnderwritingUpdate.json` record-update plans — is the output of an automated conversion of your
|
|
64
|
+
> org's BRE data. Verifying that it expresses the logic you intend is your responsibility, not the
|
|
65
|
+
> plugin's. Two things are worth checking in particular. Conversion skips rules it cannot place and
|
|
66
|
+
> reports each one as a `SKIPPED` warning, so a generated model can be incomplete even when the
|
|
67
|
+
> command succeeds. And the import commands change the org: `as-expression-set` replaces the active
|
|
68
|
+
> model, and `record-updates` writes to records, where flipping `RuleEngineType` to
|
|
69
|
+
> `ConstraintEngine` stops the platform evaluating that record's BRE rules. Preview with
|
|
70
|
+
> `--dry-run`, read the preview rather than confirming past it, and validate the migrated rules
|
|
71
|
+
> behave as expected in a sandbox before running any of this against production.
|
|
72
|
+
|
|
61
73
|
### Insurance: merging surcharge rules into an existing model
|
|
62
74
|
|
|
63
75
|
`cml convert surcharge-rules` **always** merges generated surcharge rules into an org's existing
|
|
@@ -65,12 +77,49 @@ curated `ConstraintModel` — nesting each rule into its leaf product type with
|
|
|
65
77
|
pathed rule key — rather than building a fresh, flat model. It requires an existing CML model for the
|
|
66
78
|
resolved CML API.
|
|
67
79
|
|
|
80
|
+
> **Prerequisite:** each surcharge's parent `Surcharge.Code` must be set (non-null). The platform
|
|
81
|
+
> derives the leaf segment of the auto-generated `ProductSurcharge.RuleKey` from `Surcharge.Code`, and
|
|
82
|
+
> a surcharge with a null Code cannot be flipped to `ConstraintEngine` (the org raises a save-hook
|
|
83
|
+
> error). Populate `Surcharge.Code` before converting.
|
|
84
|
+
|
|
85
|
+
After importing the merged CML with `sf cml import as-expression-set`, apply the emitted `_SurchargeUpdate.json` (flips `RuleEngineType` → `ConstraintEngine`) with `sf insurance import record-updates`:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
$ sf insurance import record-updates --file data/SURCHARGE_CML_SurchargeUpdate.json --target-org myOrg --dry-run
|
|
89
|
+
$ sf insurance import record-updates --file data/SURCHARGE_CML_SurchargeUpdate.json --target-org myOrg
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The first run previews every planned change and writes nothing. The second prints the same preview and
|
|
93
|
+
asks for confirmation before applying; pass `--no-prompt` to skip the prompt in automation. The command
|
|
94
|
+
re-reads each record before writing, verifies its Name against the file, skips records that already
|
|
95
|
+
match (so re-running is safe), and reads back the platform-regenerated `RuleKey` to confirm the
|
|
96
|
+
surcharge will actually fire. Import the CML **before** applying the record updates — the RuleKey is
|
|
97
|
+
regenerated against the active model.
|
|
98
|
+
|
|
99
|
+
The same command applies an `_UnderwritingUpdate.json` file emitted by `sf cml convert underwriting-rules`.
|
|
100
|
+
|
|
101
|
+
You can also apply the flip directly with the Salesforce CLI — run one `sf data update record` call per
|
|
102
|
+
surcharge listed in `_SurchargeUpdate.json`, using the `id` from that file to set `RuleEngineType` →
|
|
103
|
+
`ConstraintEngine`:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
$ sf data update record \
|
|
107
|
+
--sobject ProductSurcharge \
|
|
108
|
+
--record-id <ID_FROM_SURCHARGEUPDATE_JSON> \
|
|
109
|
+
--values "RuleEngineType=ConstraintEngine" \
|
|
110
|
+
--target-org myOrg
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The platform regenerates `ProductSurcharge.RuleKey` on save, which requires the parent `Surcharge.Code`
|
|
114
|
+
to be non-null (per the prerequisite above).
|
|
115
|
+
|
|
68
116
|
<!-- commands -->
|
|
69
117
|
|
|
70
118
|
- [`sf cml convert prod-cfg-rules`](#sf-cml-convert-prod-cfg-rules)
|
|
71
119
|
- [`sf cml convert surcharge-rules`](#sf-cml-convert-surcharge-rules)
|
|
72
120
|
- [`sf cml convert underwriting-rules`](#sf-cml-convert-underwriting-rules)
|
|
73
121
|
- [`sf cml import as-expression-set`](#sf-cml-import-as-expression-set)
|
|
122
|
+
- [`sf insurance import record-updates`](#sf-insurance-import-record-updates)
|
|
74
123
|
|
|
75
124
|
## `sf cml convert prod-cfg-rules`
|
|
76
125
|
|
|
@@ -165,8 +214,14 @@ DESCRIPTION
|
|
|
165
214
|
file-only and never writes to the org. It requires an existing CML model to merge into and outputs a .cml file with
|
|
166
215
|
the full merged model, a header-only \_Associations.csv file, a \_RuleKeyMapping.json with the ProductSurcharge ID to
|
|
167
216
|
RuleKey mapping, and a \_SurchargeUpdate.json file enumerating the org-record changes. Review the files, then apply
|
|
168
|
-
the CML with `sf cml import as-expression-set` and apply the
|
|
169
|
-
|
|
217
|
+
the CML with `sf cml import as-expression-set` and apply the \_SurchargeUpdate.json file with `sf insurance import
|
|
218
|
+
record-updates` (in that order — the platform regenerates ProductSurcharge.RuleKey against the active model when
|
|
219
|
+
RuleEngineType flips).
|
|
220
|
+
|
|
221
|
+
The parent Surcharge's Code field must be set (non-null): the platform derives the leaf segment of the auto-generated
|
|
222
|
+
ProductSurcharge.RuleKey from Surcharge.Code, so the converter uses it to build a matching rule key. A surcharge whose
|
|
223
|
+
parent Surcharge has a null Code cannot be flipped to ConstraintEngine (the org raises a save-hook error) and will not
|
|
224
|
+
convert correctly — populate Surcharge.Code before converting.
|
|
170
225
|
|
|
171
226
|
EXAMPLES
|
|
172
227
|
$ sf cml convert surcharge-rules --cml-api SURCHARGE_CML --target-org myOrg
|
|
@@ -208,8 +263,8 @@ DESCRIPTION
|
|
|
208
263
|
command is file-only and never writes to the org: it outputs a .cml file with the constraint model, an
|
|
209
264
|
\_Associations.csv file for ExpressionSetConstraintObj records, a \_RuleKeyMapping.json with the UnderwritingRule ID
|
|
210
265
|
to RuleKey mapping, and a \_UnderwritingUpdate.json file enumerating the org-record changes. Review the files, then
|
|
211
|
-
apply the CML with `sf cml import as-expression-set` and apply the
|
|
212
|
-
|
|
266
|
+
apply the CML with `sf cml import as-expression-set` and apply the \_UnderwritingUpdate.json file with `sf insurance
|
|
267
|
+
import record-updates`.
|
|
213
268
|
|
|
214
269
|
EXAMPLES
|
|
215
270
|
$ sf cml convert underwriting-rules --cml-api UW_CML --target-org myOrg
|
|
@@ -252,4 +307,62 @@ EXAMPLES
|
|
|
252
307
|
$ sf cml import as-expression-set --cml-api MY_TEST --context-definition PricingTransactionCD2 --workspace-dir data --target-org tgtOrg
|
|
253
308
|
```
|
|
254
309
|
|
|
310
|
+
## `sf insurance import record-updates`
|
|
311
|
+
|
|
312
|
+
Applies a record-update file emitted by a cml convert command to the target org.
|
|
313
|
+
|
|
314
|
+
```
|
|
315
|
+
USAGE
|
|
316
|
+
$ sf insurance import record-updates -o <value> -f <value> [--json] [--flags-dir <value>] [--api-version <value>] [-p]
|
|
317
|
+
[--dry-run]
|
|
318
|
+
|
|
319
|
+
FLAGS
|
|
320
|
+
-f, --file=<value> (required) Path to the record-update JSON file emitted by a cml convert command.
|
|
321
|
+
-o, --target-org=<value> (required) Username or alias of the target org. Not required if the `target-org`
|
|
322
|
+
configuration variable is already set.
|
|
323
|
+
-p, --no-prompt Don't prompt for confirmation before applying the changes.
|
|
324
|
+
--api-version=<value> Override the api version used for api requests made by this command
|
|
325
|
+
--dry-run Show the planned changes and exit without writing anything to the org.
|
|
326
|
+
|
|
327
|
+
GLOBAL FLAGS
|
|
328
|
+
--flags-dir=<value> Import flag values from a directory.
|
|
329
|
+
--json Format output as json.
|
|
330
|
+
|
|
331
|
+
DESCRIPTION
|
|
332
|
+
Applies a record-update file emitted by a cml convert command to the target org.
|
|
333
|
+
|
|
334
|
+
Reads a `<cmlApi>_SurchargeUpdate.json` or `<cmlApi>_UnderwritingUpdate.json` file — the reviewable record-update plan
|
|
335
|
+
emitted by `sf cml convert surcharge-rules` / `sf cml convert underwriting-rules` — and applies its changes to the
|
|
336
|
+
org. Convert is file-only and never writes to the org; this command is the apply step.
|
|
337
|
+
|
|
338
|
+
The file is treated as untrusted input: it is structurally validated, every record is re-read from the org before
|
|
339
|
+
anything is written, and each record's Name (plus the rule apiName for underwriting rule updates) is cross-checked
|
|
340
|
+
against the file so an edited id cannot retarget a different record. Records whose org values already match are
|
|
341
|
+
skipped, which makes re-running the command safe and idempotent.
|
|
342
|
+
|
|
343
|
+
Before applying, the command prints every planned field-level change and asks for confirmation. Use --dry-run to
|
|
344
|
+
review the plan without writing, and --no-prompt to apply without confirmation in automation. Changes are applied in
|
|
345
|
+
order and are not rolled back, so a mid-apply failure can leave the org partially migrated; re-running is safe because
|
|
346
|
+
already-applied records are skipped.
|
|
347
|
+
|
|
348
|
+
Import the merged CML with `sf cml import as-expression-set` BEFORE applying a surcharge record-update file. The
|
|
349
|
+
platform regenerates ProductSurcharge.RuleKey when RuleEngineType flips, and this command verifies that regenerated
|
|
350
|
+
key against the key the CML rule was emitted under. That regeneration also requires the parent Surcharge.Code to be
|
|
351
|
+
non-null — a surcharge whose parent Surcharge has a null Code cannot be flipped to ConstraintEngine and the org raises
|
|
352
|
+
a save-hook error.
|
|
353
|
+
|
|
354
|
+
EXAMPLES
|
|
355
|
+
Review the planned changes without writing anything:
|
|
356
|
+
|
|
357
|
+
$ sf insurance import record-updates --file data/SURCHARGE_CML_SurchargeUpdate.json --target-org myOrg --dry-run
|
|
358
|
+
|
|
359
|
+
Apply the changes, confirming the preview interactively:
|
|
360
|
+
|
|
361
|
+
$ sf insurance import record-updates --file data/SURCHARGE_CML_SurchargeUpdate.json --target-org myOrg
|
|
362
|
+
|
|
363
|
+
Apply the changes without a confirmation prompt, for automation:
|
|
364
|
+
|
|
365
|
+
$ sf insurance import record-updates --file data/UW_CML_UnderwritingUpdate.json --target-org myOrg --no-prompt
|
|
366
|
+
```
|
|
367
|
+
|
|
255
368
|
<!-- commandsstop -->
|
|
@@ -41,5 +41,17 @@ export default class CmlConvertSurchargeRules extends InsuranceRuleConvertComman
|
|
|
41
41
|
* uses them to verify the surcharge will actually fire and to flag ProductCode/ProductPath drift.
|
|
42
42
|
*/
|
|
43
43
|
protected buildRecordUpdates(_records: ProductSurchargeRecord[], ruleKeyMapping: RuleKeyEntry[]): RecordUpdate[];
|
|
44
|
+
/**
|
|
45
|
+
* Resolves every context tag the surcharge rules reference against the ContextDefinition(s) this
|
|
46
|
+
* CML model is bound to, so a `Tag` condition can be DECLARED rather than emitted as a bare
|
|
47
|
+
* undeclared identifier (which makes the solver reject the entire model at deploy).
|
|
48
|
+
*
|
|
49
|
+
* Fails closed on every axis. A lookup error, an unbound model, an unresolvable tag or an
|
|
50
|
+
* ambiguous one all yield no binding, which leaves the rule to the absent-reference gate — the
|
|
51
|
+
* behaviour that existed before this resolution did. That asymmetry is deliberate: nothing at
|
|
52
|
+
* deploy validates a context binding, so a wrong one is silent, while a withheld rule is visible
|
|
53
|
+
* in the skip breakdown and simply stays on the rule engine.
|
|
54
|
+
*/
|
|
55
|
+
private resolveContextTagBindings;
|
|
44
56
|
}
|
|
45
57
|
export {};
|
|
@@ -17,7 +17,8 @@ import { Flags } from '@salesforce/sf-plugins-core';
|
|
|
17
17
|
import { Messages } from '@salesforce/core';
|
|
18
18
|
import { InsuranceRuleConvertCommand, } from '../../../shared/insurance/insurance-rule-convert-command.js';
|
|
19
19
|
import { decodeHtmlEntities } from '../../../shared/insurance/insurance-rule-generator.js';
|
|
20
|
-
import { buildPathedSurchargeRules, fetchExistingConstraintModel, fetchProductTypeTags, mergeSurchargeRules, splitProductPath, } from '../../../shared/insurance/insurance-cml-merge.js';
|
|
20
|
+
import { buildPathedSurchargeRules, fetchExistingConstraintModel, fetchProductTypeTags, fetchSurchargeCodes, mergeSurchargeRules, splitProductPath, UNCONVERTIBLE_SKIP_PREFIX, } from '../../../shared/insurance/insurance-cml-merge.js';
|
|
21
|
+
import { fetchContextTagBindings } from '../../../shared/insurance/insurance-context-tags.js';
|
|
21
22
|
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
22
23
|
const messages = Messages.loadMessages('@salesforce/plugin-bre-to-cml', 'cml.convert.surcharge-rules');
|
|
23
24
|
// eslint-disable-next-line sf-plugin/only-extend-SfCommand
|
|
@@ -78,6 +79,17 @@ export default class CmlConvertSurchargeRules extends InsuranceRuleConvertComman
|
|
|
78
79
|
productIds.add(id);
|
|
79
80
|
}
|
|
80
81
|
const productIdToType = await fetchProductTypeTags(conn, productIds);
|
|
82
|
+
// The platform derives the RuleKey leaf from the parent Surcharge.Code (carried as `surchargeId`
|
|
83
|
+
// in each RuleDefinition), NOT the rule apiName. Resolve those Codes so the emitted CML rule key
|
|
84
|
+
// matches the platform-generated ProductSurcharge.RuleKey exactly; otherwise the surcharge
|
|
85
|
+
// imports cleanly but never fires ("No active rule model found").
|
|
86
|
+
const surchargeIds = new Set();
|
|
87
|
+
for (const { ruleDef } of ruleDefs) {
|
|
88
|
+
if (ruleDef.surchargeId)
|
|
89
|
+
surchargeIds.add(ruleDef.surchargeId);
|
|
90
|
+
}
|
|
91
|
+
const surchargeIdToCode = await fetchSurchargeCodes(conn, surchargeIds);
|
|
92
|
+
const contextTagBindings = await this.resolveContextTagBindings(conn, ruleDefs, api);
|
|
81
93
|
// Capture the ProductCode path per surcharge so the emitted update file can carry it (same
|
|
82
94
|
// mapping buildPathedSurchargeRules uses for the rule key). Drift here would desync the platform
|
|
83
95
|
// RuleKey, so it is recorded for the apply-time check rather than discarded.
|
|
@@ -87,7 +99,12 @@ export default class CmlConvertSurchargeRules extends InsuranceRuleConvertComman
|
|
|
87
99
|
const codes = splitProductPath(record.ProductPath).map((id) => productIdToCode.get(id) ?? id);
|
|
88
100
|
this.surchargeProductCodes.set(record.Id, codes);
|
|
89
101
|
}
|
|
90
|
-
const rules = buildPathedSurchargeRules(this.keyPrefix, ruleDefs, productIdToCode, productIdToType
|
|
102
|
+
const rules = buildPathedSurchargeRules(this.keyPrefix, ruleDefs, productIdToCode, productIdToType, {
|
|
103
|
+
surchargeIdToCode,
|
|
104
|
+
attributeDataTypes: this.attributeDataTypes,
|
|
105
|
+
contextTagBindings,
|
|
106
|
+
onSurchargeCodeFallback: (recordName) => this.warn(`Could not resolve Surcharge.Code for ${recordName}; rule key leaf derived from apiName and may not match the platform-generated RuleKey (surcharge may silently not fire)`),
|
|
107
|
+
});
|
|
91
108
|
rules.forEach((r) => this.log(` -> ${r.recordName} => ${r.ruleKey} (type: ${r.typeName ?? 'UNRESOLVED'})`));
|
|
92
109
|
const { mergedCml, placements, skips, attributeWarnings } = mergeSurchargeRules(existing.cmlText, rules);
|
|
93
110
|
this.log(`\nMerge summary: ${placements.filter((p) => p.status === 'inserted').length} inserted, ${placements.filter((p) => p.status === 'replaced').length} updated in place, ${skips.length} skipped.`);
|
|
@@ -100,14 +117,30 @@ export default class CmlConvertSurchargeRules extends InsuranceRuleConvertComman
|
|
|
100
117
|
// they're staring at one duplicate or fifty missing-type-tag rules. Buckets match the merge
|
|
101
118
|
// module's skip-reason vocabulary; anything that doesn't match a known reason falls into "other".
|
|
102
119
|
if (skips.length > 0) {
|
|
103
|
-
const counts = {
|
|
120
|
+
const counts = {
|
|
121
|
+
duplicate: 0,
|
|
122
|
+
emptyPath: 0,
|
|
123
|
+
noTypeTag: 0,
|
|
124
|
+
typeBlockMissing: 0,
|
|
125
|
+
typeBlockAmbiguous: 0,
|
|
126
|
+
unconvertible: 0,
|
|
127
|
+
undeclaredAttribute: 0,
|
|
128
|
+
misplaced: 0,
|
|
129
|
+
other: 0,
|
|
130
|
+
};
|
|
104
131
|
for (const s of skips) {
|
|
105
|
-
if (s.reason.startsWith(
|
|
132
|
+
if (s.reason.startsWith(UNCONVERTIBLE_SKIP_PREFIX))
|
|
133
|
+
counts.unconvertible += 1;
|
|
134
|
+
else if (s.reason.startsWith('duplicate pathed rule key'))
|
|
106
135
|
counts.duplicate += 1;
|
|
107
136
|
else if (s.reason.startsWith('empty ProductPath'))
|
|
108
137
|
counts.emptyPath += 1;
|
|
109
138
|
else if (s.reason.startsWith('no CML type tag'))
|
|
110
139
|
counts.noTypeTag += 1;
|
|
140
|
+
else if (s.reason.startsWith('undeclared attribute'))
|
|
141
|
+
counts.undeclaredAttribute += 1;
|
|
142
|
+
else if (s.reason.startsWith('misplaced statement'))
|
|
143
|
+
counts.misplaced += 1;
|
|
111
144
|
else if (s.reason.includes('not found in existing model'))
|
|
112
145
|
counts.typeBlockMissing += 1;
|
|
113
146
|
else if (s.reason.includes('is ambiguous'))
|
|
@@ -117,7 +150,9 @@ export default class CmlConvertSurchargeRules extends InsuranceRuleConvertComman
|
|
|
117
150
|
}
|
|
118
151
|
this.log(`Skip breakdown: ${counts.duplicate} duplicate-key, ${counts.emptyPath} empty-ProductPath, ` +
|
|
119
152
|
`${counts.noTypeTag} no-type-tag, ${counts.typeBlockMissing} type-block-missing, ` +
|
|
120
|
-
`${counts.typeBlockAmbiguous} type-block-ambiguous, ${counts.
|
|
153
|
+
`${counts.typeBlockAmbiguous} type-block-ambiguous, ${counts.unconvertible} unconvertible, ` +
|
|
154
|
+
`${counts.undeclaredAttribute} undeclared-attribute, ${counts.misplaced} misplaced-statement, ` +
|
|
155
|
+
`${counts.other} other`);
|
|
121
156
|
}
|
|
122
157
|
const ruleKeyMapping = placements.map((p) => ({
|
|
123
158
|
recordId: p.rule.recordId,
|
|
@@ -163,5 +198,44 @@ export default class CmlConvertSurchargeRules extends InsuranceRuleConvertComman
|
|
|
163
198
|
productCodes: this.surchargeProductCodes.get(m.recordId),
|
|
164
199
|
}));
|
|
165
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* Resolves every context tag the surcharge rules reference against the ContextDefinition(s) this
|
|
203
|
+
* CML model is bound to, so a `Tag` condition can be DECLARED rather than emitted as a bare
|
|
204
|
+
* undeclared identifier (which makes the solver reject the entire model at deploy).
|
|
205
|
+
*
|
|
206
|
+
* Fails closed on every axis. A lookup error, an unbound model, an unresolvable tag or an
|
|
207
|
+
* ambiguous one all yield no binding, which leaves the rule to the absent-reference gate — the
|
|
208
|
+
* behaviour that existed before this resolution did. That asymmetry is deliberate: nothing at
|
|
209
|
+
* deploy validates a context binding, so a wrong one is silent, while a withheld rule is visible
|
|
210
|
+
* in the skip breakdown and simply stays on the rule engine.
|
|
211
|
+
*/
|
|
212
|
+
async resolveContextTagBindings(conn, ruleDefs, api) {
|
|
213
|
+
const tagNames = new Set();
|
|
214
|
+
for (const { ruleDef } of ruleDefs) {
|
|
215
|
+
for (const criteria of ruleDef.ruleCriteria ?? []) {
|
|
216
|
+
for (const condition of criteria.conditions ?? []) {
|
|
217
|
+
// Only a Tag condition (no attributeId) is a context reference. An Attribute condition
|
|
218
|
+
// names a product attribute and is never auto-declared.
|
|
219
|
+
if (!condition.attributeId && condition.contextTagName)
|
|
220
|
+
tagNames.add(condition.contextTagName);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (tagNames.size === 0)
|
|
225
|
+
return new Map();
|
|
226
|
+
try {
|
|
227
|
+
const bindings = await fetchContextTagBindings(conn, api, tagNames);
|
|
228
|
+
for (const tag of tagNames) {
|
|
229
|
+
if (bindings.has(tag))
|
|
230
|
+
continue;
|
|
231
|
+
this.warn(`Could not resolve context tag '${tag}' against the context definition bound to '${api}'; any rule referencing it will be withheld rather than emitted as an undeclared reference`);
|
|
232
|
+
}
|
|
233
|
+
return bindings;
|
|
234
|
+
}
|
|
235
|
+
catch (err) {
|
|
236
|
+
this.warn(`Could not resolve context tags (${err instanceof Error ? err.message : String(err)}); rules referencing a context tag will be withheld`);
|
|
237
|
+
return new Map();
|
|
238
|
+
}
|
|
239
|
+
}
|
|
166
240
|
}
|
|
167
241
|
//# sourceMappingURL=surcharge-rules.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"surcharge-rules.js","sourceRoot":"","sources":["../../../../src/commands/cml/convert/surcharge-rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AACpD,OAAO,EAAc,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EACL,2BAA2B,GAI5B,MAAM,6DAA6D,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uDAAuD,CAAC;AAC3F,OAAO,EACL,yBAAyB,EACzB,4BAA4B,EAC5B,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,
|
|
1
|
+
{"version":3,"file":"surcharge-rules.js","sourceRoot":"","sources":["../../../../src/commands/cml/convert/surcharge-rules.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { Connection } from '@salesforce/core';
|
|
1
2
|
import { ParsedRuleDefinition, RecordUpdate, RuleKeyEntry, RuleRecord } from '../../../shared/insurance/models.js';
|
|
2
|
-
import { InsuranceRuleConvertCommand, InsuranceRuleConvertResult } from '../../../shared/insurance/insurance-rule-convert-command.js';
|
|
3
|
+
import { InsuranceRuleConvertCommand, InsuranceRuleConvertContext, InsuranceRuleConvertResult, ParsedRuleEntry } from '../../../shared/insurance/insurance-rule-convert-command.js';
|
|
3
4
|
type UnderwritingRuleRecord = RuleRecord & {
|
|
4
5
|
ApiName: string | null;
|
|
5
6
|
DynamicRuleDefinition: string | null;
|
|
@@ -28,17 +29,64 @@ export default class CmlConvertUnderwritingRules extends InsuranceRuleConvertCom
|
|
|
28
29
|
protected readonly apiNamePrefix = "UW_";
|
|
29
30
|
protected readonly soql = "SELECT Id, Name, ApiName, DynamicRuleDefinition, ProductPath, RuleKey, UnderwritingRuleGroupId, UnderwritingRuleGroup.Name FROM UnderwritingRule WHERE RuleKey = null";
|
|
30
31
|
protected readonly recordUpdateKind: "underwriting-update";
|
|
32
|
+
/** Merge-skip reason per UnderwritingRule id, populated by {@link runMergeConvert}. */
|
|
33
|
+
private skipReasonByRecordId;
|
|
31
34
|
run(): Promise<CmlConvertUnderwritingRulesResult>;
|
|
35
|
+
/**
|
|
36
|
+
* Merge mode: read the org's existing ConstraintModel, compute each underwriting rule's pathed
|
|
37
|
+
* rule key (matching the platform's auto-generated RuleKey) and sanitized constraint name, and
|
|
38
|
+
* nest the `constraint <name> = (...)` statement into the correct existing leaf `type` block —
|
|
39
|
+
* instead of overwriting the curated model with a flat one. Mirrors CmlConvertSurchargeRules'
|
|
40
|
+
* runMergeConvert override.
|
|
41
|
+
*/
|
|
42
|
+
protected runMergeConvert(_ctx: InsuranceRuleConvertContext, conn: Connection, records: UnderwritingRuleRecord[], ruleDefs: ParsedRuleEntry[], productIdToCode: Map<string, string>, api: string, safeApi: string, workspaceDir: string): Promise<InsuranceRuleConvertResult>;
|
|
32
43
|
protected parseRecord(record: UnderwritingRuleRecord): ParsedRuleDefinition | null;
|
|
33
44
|
/**
|
|
34
45
|
* Pure transform — the file-only successor to the old live updateOrgRecords. Produces the exact
|
|
35
46
|
* org-record changes convert previously applied: (1) each UnderwritingRuleGroup flipped to
|
|
36
47
|
* RuleEngineType=ConstraintEngine, then (2) each BRE UnderwritingRule's DynamicRuleDefinition blob
|
|
37
|
-
* rewritten with the converted ruleKey (and
|
|
38
|
-
*
|
|
48
|
+
* rewritten with the converted ruleKey (and, only when this plan also flips that rule's group, the
|
|
49
|
+
* nested underwritingRuleGroup.ruleEngineType). Groups are emitted first so a faithful apply
|
|
50
|
+
* mirrors the original ordering, and so step (2) can read back which groups step (1) flipped. The blob
|
|
39
51
|
* rewrite uses a RAW JSON.parse of the org's stored value (NOT decodeHtmlEntities) — byte-for-byte
|
|
40
52
|
* the same mutation the live path performed.
|
|
53
|
+
*
|
|
54
|
+
* `ruleKeyMapping` is the authoritative "landed in the CML" set: runMergeConvert builds it from
|
|
55
|
+
* the merge's `placements` (inserted + replaced) only, so every skipped rule is absent from it.
|
|
41
56
|
*/
|
|
42
57
|
protected buildRecordUpdates(records: UnderwritingRuleRecord[], ruleKeyMapping: RuleKeyEntry[]): RecordUpdate[];
|
|
58
|
+
/**
|
|
59
|
+
* The withheld-flip warning for a partially-migrated group. This message is the only thing the
|
|
60
|
+
* operator has to act on, so it has to name a remedy rather than a symptom:
|
|
61
|
+
*
|
|
62
|
+
* The reason it most often quotes, `no CML type tag found for the leaf product of X`, names a
|
|
63
|
+
* symptom. `fetchProductTypeTags` reads that tag from ExpressionSetConstraintObj rows with
|
|
64
|
+
* ConstraintModelTagType='Type', so the remedy is to add the row binding that leaf Product2 to a
|
|
65
|
+
* type block — stated here rather than left to be reverse-engineered out of the merge internals.
|
|
66
|
+
*
|
|
67
|
+
* And "fix it and re-run" is the wrong instruction when the leaf product is not in the org's
|
|
68
|
+
* Product2 at all: nothing can bind a type tag to a product that is not there, so the group stays
|
|
69
|
+
* withheld however many times it is re-run. Convert already warned about exactly those ids while
|
|
70
|
+
* resolving product codes, so that case is separated out instead of folded into "fix and re-run".
|
|
71
|
+
*/
|
|
72
|
+
private partialGroupWarning;
|
|
73
|
+
/**
|
|
74
|
+
* Step (2) of the plan: rewrite each placed BRE rule's DynamicRuleDefinition blob. Uses a RAW
|
|
75
|
+
* JSON.parse of the org's stored value (NOT decodeHtmlEntities) and re-stringifies — byte-for-byte
|
|
76
|
+
* the same mutation the old live code path performed; the document is never reformatted or re-keyed.
|
|
77
|
+
*
|
|
78
|
+
* The nested `underwritingRuleGroup.ruleEngineType` is stamped ONLY when this same plan also flips
|
|
79
|
+
* that rule's group record. Setting it unconditionally left the plan internally inconsistent
|
|
80
|
+
* whenever a flip was withheld: the applied blob asserted ConstraintEngine while the group record
|
|
81
|
+
* it belongs to still carried its old RuleEngineType, and nothing in the apply preview surfaces
|
|
82
|
+
* the disagreement. Whether the platform READS the nested copy is not established — the sibling
|
|
83
|
+
* `underwritingRuleGroupId` is null in every stored blob and appears not to be maintained by the
|
|
84
|
+
* platform — so this is a consistency fix, not a known runtime failure. When the group is not
|
|
85
|
+
* flipped the nested value is left exactly as the org stored it: not deleted, not substituted.
|
|
86
|
+
*
|
|
87
|
+
* The `ruleKey` rewrite happens either way — it is what the placed constraint needs, and the
|
|
88
|
+
* reason the record update is still emitted for a withheld group's placed rules at all.
|
|
89
|
+
*/
|
|
90
|
+
private buildBlobRewrites;
|
|
43
91
|
}
|
|
44
92
|
export {};
|