@salesforce/plugin-bre-to-cml 1.3.0 → 1.3.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.
Files changed (50) hide show
  1. package/README.md +117 -4
  2. package/lib/commands/cml/convert/surcharge-rules.d.ts +12 -0
  3. package/lib/commands/cml/convert/surcharge-rules.js +79 -5
  4. package/lib/commands/cml/convert/surcharge-rules.js.map +1 -1
  5. package/lib/commands/cml/convert/underwriting-rules.d.ts +41 -2
  6. package/lib/commands/cml/convert/underwriting-rules.js +141 -17
  7. package/lib/commands/cml/convert/underwriting-rules.js.map +1 -1
  8. package/lib/commands/insurance/import/record-updates.d.ts +66 -0
  9. package/lib/commands/insurance/import/record-updates.js +239 -0
  10. package/lib/commands/insurance/import/record-updates.js.map +1 -0
  11. package/lib/shared/cml-operators.d.ts +9 -1
  12. package/lib/shared/cml-operators.js +23 -5
  13. package/lib/shared/cml-operators.js.map +1 -1
  14. package/lib/shared/insurance/confirm-org-changes.d.ts +49 -0
  15. package/lib/shared/insurance/confirm-org-changes.js +43 -0
  16. package/lib/shared/insurance/confirm-org-changes.js.map +1 -0
  17. package/lib/shared/insurance/insurance-cml-merge.d.ts +100 -13
  18. package/lib/shared/insurance/insurance-cml-merge.js +355 -54
  19. package/lib/shared/insurance/insurance-cml-merge.js.map +1 -1
  20. package/lib/shared/insurance/insurance-context-tags.d.ts +124 -0
  21. package/lib/shared/insurance/insurance-context-tags.js +210 -0
  22. package/lib/shared/insurance/insurance-context-tags.js.map +1 -0
  23. package/lib/shared/insurance/insurance-org.d.ts +12 -0
  24. package/lib/shared/insurance/insurance-org.js +38 -2
  25. package/lib/shared/insurance/insurance-org.js.map +1 -1
  26. package/lib/shared/insurance/insurance-rule-convert-command.d.ts +27 -0
  27. package/lib/shared/insurance/insurance-rule-convert-command.js +57 -4
  28. package/lib/shared/insurance/insurance-rule-convert-command.js.map +1 -1
  29. package/lib/shared/insurance/insurance-rule-generator.d.ts +101 -8
  30. package/lib/shared/insurance/insurance-rule-generator.js +293 -42
  31. package/lib/shared/insurance/insurance-rule-generator.js.map +1 -1
  32. package/lib/shared/insurance/models.d.ts +2 -1
  33. package/lib/shared/insurance/planned-change-mapper.d.ts +15 -0
  34. package/lib/shared/insurance/planned-change-mapper.js +51 -0
  35. package/lib/shared/insurance/planned-change-mapper.js.map +1 -0
  36. package/lib/shared/insurance/planned-change.d.ts +83 -0
  37. package/lib/shared/insurance/planned-change.js +74 -0
  38. package/lib/shared/insurance/planned-change.js.map +1 -0
  39. package/lib/shared/insurance/record-update-apply.d.ts +100 -0
  40. package/lib/shared/insurance/record-update-apply.js +303 -0
  41. package/lib/shared/insurance/record-update-apply.js.map +1 -0
  42. package/lib/shared/insurance/record-update-plan.d.ts +104 -0
  43. package/lib/shared/insurance/record-update-plan.js +397 -0
  44. package/lib/shared/insurance/record-update-plan.js.map +1 -0
  45. package/messages/cml.convert.surcharge-rules.md +3 -1
  46. package/messages/cml.convert.underwriting-rules.md +1 -1
  47. package/messages/insurance.import.record-updates.md +176 -0
  48. package/oclif.lock +28 -28
  49. package/oclif.manifest.json +127 -35
  50. package/package.json +16 -8
@@ -0,0 +1,176 @@
1
+ # summary
2
+
3
+ Applies a record-update file emitted by a cml convert command to the target org.
4
+
5
+ # description
6
+
7
+ Reads a `<cmlApi>_SurchargeUpdate.json` or `<cmlApi>_UnderwritingUpdate.json` file — the reviewable record-update plan emitted by `sf cml convert surcharge-rules` / `sf cml convert underwriting-rules` — and applies its changes to the org. Convert is file-only and never writes to the org; this command is the apply step.
8
+
9
+ The file is treated as untrusted input: it is structurally validated, every record is re-read from the org before anything is written, and each record's Name (plus the rule apiName for underwriting rule updates) is cross-checked against the file so an edited id cannot retarget a different record. Records whose org values already match are skipped, which makes re-running the command safe and idempotent.
10
+
11
+ Before applying, the command prints every planned field-level change and asks for confirmation. Use --dry-run to review the plan without writing, and --no-prompt to apply without confirmation in automation. Changes are applied in order and are not rolled back, so a mid-apply failure can leave the org partially migrated; re-running is safe because already-applied records are skipped.
12
+
13
+ Import the merged CML with `sf cml import as-expression-set` BEFORE applying a surcharge record-update file. The platform regenerates ProductSurcharge.RuleKey when RuleEngineType flips, and this command verifies that regenerated key against the key the CML rule was emitted under. That regeneration also requires the parent Surcharge.Code to be non-null — a surcharge whose parent Surcharge has a null Code cannot be flipped to ConstraintEngine and the org raises a save-hook error.
14
+
15
+ # examples
16
+
17
+ - Review the planned changes without writing anything:
18
+
19
+ <%= config.bin %> <%= command.id %> --file data/SURCHARGE_CML_SurchargeUpdate.json --target-org myOrg --dry-run
20
+
21
+ - Apply the changes, confirming the preview interactively:
22
+
23
+ <%= config.bin %> <%= command.id %> --file data/SURCHARGE_CML_SurchargeUpdate.json --target-org myOrg
24
+
25
+ - Apply the changes without a confirmation prompt, for automation:
26
+
27
+ <%= config.bin %> <%= command.id %> --file data/UW_CML_UnderwritingUpdate.json --target-org myOrg --no-prompt
28
+
29
+ # flags.file.summary
30
+
31
+ Path to the record-update JSON file emitted by a cml convert command.
32
+
33
+ # flags.no-prompt.summary
34
+
35
+ Don't prompt for confirmation before applying the changes.
36
+
37
+ # flags.dry-run.summary
38
+
39
+ Show the planned changes and exit without writing anything to the org.
40
+
41
+ # info.nothingToApply
42
+
43
+ The file contains no updates. Nothing to apply.
44
+
45
+ # info.dryRun
46
+
47
+ Dry run only — no changes were applied.
48
+
49
+ # info.applySummary
50
+
51
+ Records: %s updated, %s skipped (already current), %s failed.
52
+
53
+ # warn.header
54
+
55
+ These changes will be applied to %s
56
+
57
+ # warn.summary
58
+
59
+ %s to update, %s already current (will be skipped) in org %s.
60
+
61
+ # warn.notTransactional
62
+
63
+ Changes are applied in order and are NOT rolled back; a mid-apply failure can leave the org partially migrated.
64
+
65
+ # warn.outcomeUnknown
66
+
67
+ OUTCOME UNKNOWN %s (%s): %s. The request failed after it was sent, so the org may or may not hold this change; re-read the record before re-running.
68
+
69
+ # warn.skippingPrompt
70
+
71
+ Proceeding without confirmation because --no-prompt was passed.
72
+
73
+ # confirm.apply
74
+
75
+ Apply these changes to the org
76
+
77
+ # error.unreadableFile
78
+
79
+ Couldn't read the record-update file %s. %s
80
+
81
+ # error.unreadableFile.actions
82
+
83
+ - Check that the path points at a readable file (not a directory) and that you have permission to read it.
84
+
85
+ # error.invalidFile
86
+
87
+ Invalid record-update file. %s
88
+
89
+ # error.invalidFile.actions
90
+
91
+ - Regenerate the file with the matching `sf cml convert` command, or correct the reported problem by hand.
92
+
93
+ # error.duplicateRecordId
94
+
95
+ Invalid record-update file: the same record appears in it more than once. %s
96
+
97
+ # error.duplicateRecordId.actions
98
+
99
+ - Keep exactly one entry per record. If the repeated entries set different values, decide which value you intend and delete the others: a preview that shows one record twice, with two different outcomes, isn't something you can consent to.
100
+ - Regenerate the file with the matching `sf cml convert` command if you can't tell which of the entries is the correct one.
101
+
102
+ # error.recordIdentityMismatch
103
+
104
+ Refusing to apply: the org state doesn't match the record-update file.
105
+
106
+ %s
107
+
108
+ # error.recordIdentityMismatch.actions
109
+
110
+ - Regenerate the record-update file against this org, or hand-correct each reported entry so its id and name both match the record you mean to update. A record that was simply renamed in the org needs its `name` corrected, not its `id`.
111
+
112
+ # error.unreadableOrgBlob
113
+
114
+ Refusing to apply: the DynamicRuleDefinition stored in the org can't be parsed, so the identity check that keeps this write off the wrong record couldn't run.
115
+
116
+ %s
117
+
118
+ # error.unreadableOrgBlob.actions
119
+
120
+ - Read the record's DynamicRuleDefinition out of the org (`sf data query --query "SELECT Id, Name, DynamicRuleDefinition FROM UnderwritingRule WHERE Id = '<id>'" --target-org <org>`) and repair or restore it, then re-run. Regenerating the record-update file won't help: convert reads the same unparseable value.
121
+ - Drop the reported records from the file if you want to migrate the rest first; the records left in it are applied normally.
122
+
123
+ # error.identityCheckUnavailable
124
+
125
+ Refusing to apply: an identity check this command relies on couldn't run, so it can't confirm it would write to the right record. This is a defect in the plugin, not in your file.
126
+
127
+ %s
128
+
129
+ # error.identityCheckUnavailable.actions
130
+
131
+ - Report this to the plugin maintainers with the message above and the command you ran. Editing the record-update file can't affect it — the missing data is a field the plugin failed to read back from the org.
132
+ - Nothing was written: the check runs before any write, so the org is exactly as it was. Re-running, with or without --dry-run, refuses in the same place until the defect is fixed.
133
+
134
+ # error.confirmationRequired
135
+
136
+ Confirmation is required to apply changes to the org, but the terminal isn't interactive.
137
+
138
+ # error.confirmationRequired.actions
139
+
140
+ - Run again with --no-prompt to apply without confirmation (consider --dry-run first), or run interactively.
141
+
142
+ # error.confirmationRequiredJson
143
+
144
+ Confirmation is required to apply changes to the org, but the confirmation prompt is suppressed under --json because prompting would write prompt text into the JSON output stream.
145
+
146
+ # error.confirmationRequiredJson.actions
147
+
148
+ - Run again with --no-prompt to apply without confirmation, or with --dry-run to review the planned changes without writing.
149
+
150
+ # error.aborted
151
+
152
+ Aborted. No changes were applied to the org.
153
+
154
+ # error.applyFailures
155
+
156
+ %s of the record updates failed and %s succeeded. The org is partially migrated: the updates that succeeded are not rolled back.
157
+
158
+ # error.applyFailures.actions
159
+
160
+ - Fix the reported errors, then re-run (already-applied records are skipped): %s
161
+
162
+ # error.applyFailuresNoneApplied
163
+
164
+ %s of the record updates failed and none were applied, so this run left the org unchanged.
165
+
166
+ # error.applyFailuresNoneApplied.actions
167
+
168
+ - Fix the reported errors, then re-run. Nothing needs undoing first, because nothing was written: %s
169
+
170
+ # error.applyFailuresOutcomeUnknown
171
+
172
+ %s of the record updates failed and %s succeeded. %s of the failures happened after the request had been sent, so whether the org holds those changes is unknown; any update that did succeed is not rolled back.
173
+
174
+ # error.applyFailuresOutcomeUnknown.actions
175
+
176
+ - Re-read the records reported above as OUTCOME UNKNOWN to find out whether the org holds them, then fix the reported errors and re-run (already-applied records are skipped): %s
package/oclif.lock CHANGED
@@ -1068,10 +1068,10 @@
1068
1068
  wordwrap "^1.0.0"
1069
1069
  wrap-ansi "^7.0.0"
1070
1070
 
1071
- "@oclif/plugin-command-snapshot@^5.3.33":
1072
- version "5.3.33"
1073
- resolved "https://registry.yarnpkg.com/@oclif/plugin-command-snapshot/-/plugin-command-snapshot-5.3.33.tgz#36f6cc1b8b9154e6087f9f7f8a3a83b0c089198f"
1074
- integrity sha512-Djtpaf6tO73cWMLXY+i7SZgfkVz3zRFZ1rwTKrAQZ55gN22zjHn0QXc181dtEGYcVb+laYJGHo/epvDntySi3g==
1071
+ "@oclif/plugin-command-snapshot@^5.3.35":
1072
+ version "5.3.35"
1073
+ resolved "https://registry.yarnpkg.com/@oclif/plugin-command-snapshot/-/plugin-command-snapshot-5.3.35.tgz#0bb1f3627a4d3209c5bd41089dbfffefbf94a60e"
1074
+ integrity sha512-IIj6zISG1muLLSpPI560n6Q2F4njN+OFTP/PXp+sdGxrB0pT/NtuRQ6DXwo0fvOX2AA6aG7HMLNYRO5h5feGJg==
1075
1075
  dependencies:
1076
1076
  "@oclif/core" "^4"
1077
1077
  ansis "^3.17.0"
@@ -1128,10 +1128,10 @@
1128
1128
  strip-ansi "^7.2.0"
1129
1129
  wrap-ansi "^9.0.2"
1130
1130
 
1131
- "@oclif/test@^4.1.21":
1132
- version "4.1.21"
1133
- resolved "https://registry.yarnpkg.com/@oclif/test/-/test-4.1.21.tgz#3c46cfd7671df4019e7d9a43be94509d827fe285"
1134
- integrity sha512-3Hsqv1mo7P/n8qXKJ4nLTYISA3oPzXGZDc4R9ioi5hpK1lQ7UI1ZcLkt0aKJ1qMKrYStzk20IWhcPRT0Vpteyw==
1131
+ "@oclif/test@^4.1.22":
1132
+ version "4.1.22"
1133
+ resolved "https://registry.yarnpkg.com/@oclif/test/-/test-4.1.22.tgz#5a0db873e91b6267b0360619970069f456ba3378"
1134
+ integrity sha512-szaFr78p60axV6ECky9U2SMABE0g1JQpV3qyRjuPCt0pyAlgEzXodLnk99coqE1mny2qYlOU440dd37Xd/AQUA==
1135
1135
  dependencies:
1136
1136
  ansis "^3.17.0"
1137
1137
  debug "^4.4.3"
@@ -1167,12 +1167,12 @@
1167
1167
  resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8"
1168
1168
  integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==
1169
1169
 
1170
- "@salesforce/cli-plugins-testkit@^5.3.64":
1171
- version "5.3.64"
1172
- resolved "https://registry.yarnpkg.com/@salesforce/cli-plugins-testkit/-/cli-plugins-testkit-5.3.64.tgz#6c28fefc787f83096cb274e38fc855727ffa13f3"
1173
- integrity sha512-4jUPow+oOr2Jp3s3QKCS1Aw9qs9AV2sIuk3YvWz9gMd7Y3/wVROG4C5OelfnrClGocxDAOVaCgJrTSoF0VQzUg==
1170
+ "@salesforce/cli-plugins-testkit@^5.3.66":
1171
+ version "5.3.66"
1172
+ resolved "https://registry.yarnpkg.com/@salesforce/cli-plugins-testkit/-/cli-plugins-testkit-5.3.66.tgz#918a61e62092495bb9fadd1dee38e281d4e7b334"
1173
+ integrity sha512-xmco8MRlrpPmj2n9LZ8hkp0aWWDXbFDvNzTOC6h/z756PSu+g3ERNsW+HwXiyrirMd7rH7IalKSMcNXgWS/f3w==
1174
1174
  dependencies:
1175
- "@salesforce/core" "^8.31.2"
1175
+ "@salesforce/core" "^8.32.6"
1176
1176
  "@salesforce/kit" "^3.2.6"
1177
1177
  "@salesforce/ts-types" "^2.0.11"
1178
1178
  "@types/shelljs" "^0.10.0"
@@ -1183,7 +1183,7 @@
1183
1183
  strip-ansi "6.0.1"
1184
1184
  ts-retry-promise "^0.8.1"
1185
1185
 
1186
- "@salesforce/core@^8.23.1", "@salesforce/core@^8.31.2", "@salesforce/core@^8.31.4", "@salesforce/core@^8.32.6":
1186
+ "@salesforce/core@^8.23.1", "@salesforce/core@^8.31.4", "@salesforce/core@^8.32.6":
1187
1187
  version "8.32.6"
1188
1188
  resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-8.32.6.tgz#2824dc917888dc040995dfef3a9e83d41fafbdea"
1189
1189
  integrity sha512-ZR973WoqCgi6cR58WhgokbHVZOaADNKHiuM1FAwS5pTLQnC91xYi04i2e/gpAX2AUf7Ya6zjbusYtZNpSyKKAQ==
@@ -1252,10 +1252,10 @@
1252
1252
  dependencies:
1253
1253
  "@salesforce/ts-types" "^2.0.12"
1254
1254
 
1255
- "@salesforce/plugin-command-reference@^3.1.131":
1256
- version "3.1.131"
1257
- resolved "https://registry.yarnpkg.com/@salesforce/plugin-command-reference/-/plugin-command-reference-3.1.131.tgz#642bc96a550540e1cec0b44b76d53d0b40360ea9"
1258
- integrity sha512-CGNwVXCnsZa+X70apV0HUUOyQSf8w1jyG3GhPBv3Gh0X+Dppartlc3tsmkkYO1s9VbYgsTv0nTaaScsMVeFxcA==
1255
+ "@salesforce/plugin-command-reference@^3.1.132":
1256
+ version "3.1.132"
1257
+ resolved "https://registry.yarnpkg.com/@salesforce/plugin-command-reference/-/plugin-command-reference-3.1.132.tgz#b40af2618d13466728211b7b88b312a2104c5b4f"
1258
+ integrity sha512-khxcwV+djsdN7pa2gRQjy3Xvn5RJ4/AqCdvsIfU70bZKo2LqjHK9O+Pkz0F7ci2ao4nyamRlyL9C6rpKPg+N+g==
1259
1259
  dependencies:
1260
1260
  "@oclif/core" "^4"
1261
1261
  "@salesforce/core" "^8.32.6"
@@ -3314,9 +3314,9 @@ extend@^3.0.2:
3314
3314
  integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
3315
3315
 
3316
3316
  fast-copy@^3.0.2:
3317
- version "3.0.2"
3318
- resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.2.tgz#59c68f59ccbcac82050ba992e0d5c389097c9d35"
3319
- integrity sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==
3317
+ version "3.1.0"
3318
+ resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.1.0.tgz#1787743b5384319d62ee72a01720345104226802"
3319
+ integrity sha512-IuCOCDFM1F/s4LtG7Bjr3yUUwPHybyhqN74xk2cMYoP51vVeErMy8+6HGFchi/+45lW8uzhs6lBeEqks2GWt6A==
3320
3320
 
3321
3321
  fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
3322
3322
  version "3.1.3"
@@ -5488,10 +5488,10 @@ object.values@^1.2.1:
5488
5488
  define-properties "^1.2.1"
5489
5489
  es-object-atoms "^1.0.0"
5490
5490
 
5491
- oclif@^4.23.29:
5492
- version "4.23.29"
5493
- resolved "https://registry.yarnpkg.com/oclif/-/oclif-4.23.29.tgz#3b62399a0ce68370c9a6bebc6fb9eea776729f62"
5494
- integrity sha512-pUekmMh+wwIbFq3xX1EfkgZ7RuYuuSbdhJiB+20zqSfGE8Tt9T+K9br1/vmsaIOxfDo0Dw3jxLBk4JZOMFEMeQ==
5491
+ oclif@^4.23.30:
5492
+ version "4.23.30"
5493
+ resolved "https://registry.yarnpkg.com/oclif/-/oclif-4.23.30.tgz#d353a4eeb8b836214f3eaaa3f33c09c1468b2fd5"
5494
+ integrity sha512-x8sMRv606XqZAWEfGh981PP2JM4G2CKt4/z2KDntoNHljD8slfJ5sHaDFUQya9w6W8xOJDMFF3UaLAFFYHo13w==
5495
5495
  dependencies:
5496
5496
  "@aws-sdk/client-cloudfront" "^3.1079.0"
5497
5497
  "@aws-sdk/client-s3" "^3.1079.0"
@@ -7129,9 +7129,9 @@ undici-types@~7.10.0:
7129
7129
  integrity sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==
7130
7130
 
7131
7131
  undici@^8.5.0:
7132
- version "8.10.0"
7133
- resolved "https://registry.yarnpkg.com/undici/-/undici-8.10.0.tgz#67ed7c4087f0f40fba7bef3a46f2be80572f2473"
7134
- integrity sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ==
7132
+ version "8.11.2"
7133
+ resolved "https://registry.yarnpkg.com/undici/-/undici-8.11.2.tgz#b8f6f6504384ae535c8e46f8403fd8075f011d46"
7134
+ integrity sha512-u4UB2/IrKdU6lFxumHmmo1a3fCQO5tzQllRorfoRS63txhrB7xTpSn1PftwC4qEHkOaqP95fCWW4lJzwErwzhQ==
7135
7135
 
7136
7136
  unicorn-magic@^0.3.0:
7137
7137
  version "0.3.0"
@@ -1,5 +1,99 @@
1
1
  {
2
2
  "commands": {
3
+ "cml:import:as-expression-set": {
4
+ "aliases": [],
5
+ "args": {},
6
+ "description": "Review CM created by conversion command before doing import. \nThis command executes following logic:\n- Import one CML at a time\n- Upsert the Expression Set using the `cml-api` name\n- Read and upsert `ExpressionSetConstraintObj` rows from the `cml-api_associations.csv` file (resolving FKs)\n- Upload the CML blob",
7
+ "examples": [
8
+ "<%= config.bin %> <%= command.id %> --cml-api MY_TEST --context-definition PricingTransactionCD2 --workspace-dir data --target-org tgtOrg"
9
+ ],
10
+ "flags": {
11
+ "json": {
12
+ "description": "Format output as json.",
13
+ "helpGroup": "GLOBAL",
14
+ "name": "json",
15
+ "allowNo": false,
16
+ "type": "boolean"
17
+ },
18
+ "flags-dir": {
19
+ "helpGroup": "GLOBAL",
20
+ "name": "flags-dir",
21
+ "summary": "Import flag values from a directory.",
22
+ "hasDynamicHelp": false,
23
+ "multiple": false,
24
+ "type": "option"
25
+ },
26
+ "target-org": {
27
+ "char": "o",
28
+ "name": "target-org",
29
+ "noCacheDefault": true,
30
+ "required": true,
31
+ "summary": "Username or alias of the target org. Not required if the `target-org` configuration variable is already set.",
32
+ "hasDynamicHelp": true,
33
+ "multiple": false,
34
+ "type": "option"
35
+ },
36
+ "api-version": {
37
+ "description": "Override the api version used for api requests made by this command",
38
+ "name": "api-version",
39
+ "hasDynamicHelp": false,
40
+ "multiple": false,
41
+ "type": "option"
42
+ },
43
+ "context-definition": {
44
+ "char": "x",
45
+ "name": "context-definition",
46
+ "required": true,
47
+ "summary": "Context Definition name to be assocciated with the CML.",
48
+ "hasDynamicHelp": false,
49
+ "multiple": false,
50
+ "type": "option"
51
+ },
52
+ "cml-api": {
53
+ "char": "c",
54
+ "name": "cml-api",
55
+ "required": true,
56
+ "summary": "Unique CML API Name to be created.",
57
+ "hasDynamicHelp": false,
58
+ "multiple": false,
59
+ "type": "option"
60
+ },
61
+ "workspace-dir": {
62
+ "char": "d",
63
+ "name": "workspace-dir",
64
+ "summary": "Directory where converted CML and assocciations csv files are located.",
65
+ "hasDynamicHelp": false,
66
+ "multiple": false,
67
+ "type": "option"
68
+ }
69
+ },
70
+ "hasDynamicHelp": true,
71
+ "hiddenAliases": [],
72
+ "id": "cml:import:as-expression-set",
73
+ "pluginAlias": "@salesforce/plugin-bre-to-cml",
74
+ "pluginName": "@salesforce/plugin-bre-to-cml",
75
+ "pluginType": "core",
76
+ "strict": true,
77
+ "summary": "Imports CML and associations to the target org",
78
+ "enableJsonFlag": true,
79
+ "isESM": true,
80
+ "relativePath": [
81
+ "lib",
82
+ "commands",
83
+ "cml",
84
+ "import",
85
+ "as-expression-set.js"
86
+ ],
87
+ "aliasPermutations": [],
88
+ "permutations": [
89
+ "cml:import:as-expression-set",
90
+ "import:cml:as-expression-set",
91
+ "import:as-expression-set:cml",
92
+ "cml:as-expression-set:import",
93
+ "as-expression-set:cml:import",
94
+ "as-expression-set:import:cml"
95
+ ]
96
+ },
3
97
  "cml:convert:prod-cfg-rules": {
4
98
  "aliases": [],
5
99
  "args": {},
@@ -113,7 +207,7 @@
113
207
  "cml:convert:surcharge-rules": {
114
208
  "aliases": [],
115
209
  "args": {},
116
- "description": "Reads ProductSurcharge records from the org (or a JSON file), parses their RuleDefinition, and merges the generated surcharge rules into the org's existing curated ConstraintModel for the resolved CML API. Each surcharge rule is nested into its leaf product type with a platform-compatible pathed rule key (matching the RuleKey the platform auto-generates), so the rule actually fires for nested products instead of being silently dropped. The command is file-only and never writes to the org. It requires an existing CML model to merge into and outputs a .cml file with the full merged model, a header-only \\_Associations.csv file, a \\_RuleKeyMapping.json with the ProductSurcharge ID to RuleKey mapping, and a \\_SurchargeUpdate.json file enumerating the org-record changes. Review the files, then apply the CML with `sf cml import as-expression-set` and apply the org-record changes enumerated in the \\_SurchargeUpdate.json file to the org separately (in that order).",
210
+ "description": "Reads ProductSurcharge records from the org (or a JSON file), parses their RuleDefinition, and merges the generated surcharge rules into the org's existing curated ConstraintModel for the resolved CML API. Each surcharge rule is nested into its leaf product type with a platform-compatible pathed rule key (matching the RuleKey the platform auto-generates), so the rule actually fires for nested products instead of being silently dropped. The command is file-only and never writes to the org. It requires an existing CML model to merge into and outputs a .cml file with the full merged model, a header-only \\_Associations.csv file, a \\_RuleKeyMapping.json with the ProductSurcharge ID to RuleKey mapping, and a \\_SurchargeUpdate.json file enumerating the org-record changes. Review the files, then apply the CML with `sf cml import as-expression-set` and apply the \\_SurchargeUpdate.json file with `sf insurance import record-updates` (in that order — the platform regenerates ProductSurcharge.RuleKey against the active model when RuleEngineType flips).\n\nThe parent Surcharge's Code field must be set (non-null): the platform derives the leaf segment of the auto-generated ProductSurcharge.RuleKey from Surcharge.Code, so the converter uses it to build a matching rule key. A surcharge whose parent Surcharge has a null Code cannot be flipped to ConstraintEngine (the org raises a save-hook error) and will not convert correctly — populate Surcharge.Code before converting.",
117
211
  "examples": [
118
212
  "<%= config.bin %> <%= command.id %> --cml-api SURCHARGE_CML --target-org myOrg",
119
213
  "<%= config.bin %> <%= command.id %> --cml-api SURCHARGE_CML --surcharge-file path/to/surcharges.json --workspace-dir data --target-org myOrg"
@@ -212,7 +306,7 @@
212
306
  "cml:convert:underwriting-rules": {
213
307
  "aliases": [],
214
308
  "args": {},
215
- "description": "Reads UnderwritingRule records from the org (or a JSON file), parses their DynamicRuleDefinition, and generates CML constraints that evaluate underwriting eligibility. Each rule becomes a named constraint that returns true/false. The command is file-only and never writes to the org: it outputs a .cml file with the constraint model, an \\_Associations.csv file for ExpressionSetConstraintObj records, a \\_RuleKeyMapping.json with the UnderwritingRule ID to RuleKey mapping, and a \\_UnderwritingUpdate.json file enumerating the org-record changes. Review the files, then apply the CML with `sf cml import as-expression-set` and apply the org-record changes enumerated in the \\_UnderwritingUpdate.json file to the org separately.",
309
+ "description": "Reads UnderwritingRule records from the org (or a JSON file), parses their DynamicRuleDefinition, and generates CML constraints that evaluate underwriting eligibility. Each rule becomes a named constraint that returns true/false. The command is file-only and never writes to the org: it outputs a .cml file with the constraint model, an \\_Associations.csv file for ExpressionSetConstraintObj records, a \\_RuleKeyMapping.json with the UnderwritingRule ID to RuleKey mapping, and a \\_UnderwritingUpdate.json file enumerating the org-record changes. Review the files, then apply the CML with `sf cml import as-expression-set` and apply the \\_UnderwritingUpdate.json file with `sf insurance import record-updates`.",
216
310
  "examples": [
217
311
  "<%= config.bin %> <%= command.id %> --cml-api UW_CML --target-org myOrg",
218
312
  "<%= config.bin %> <%= command.id %> --cml-api UW_CML --uw-file data/underwriting.json --workspace-dir data --target-org myOrg"
@@ -308,12 +402,14 @@
308
402
  "underwriting-rules:convert:cml"
309
403
  ]
310
404
  },
311
- "cml:import:as-expression-set": {
405
+ "insurance:import:record-updates": {
312
406
  "aliases": [],
313
407
  "args": {},
314
- "description": "Review CM created by conversion command before doing import. \nThis command executes following logic:\n- Import one CML at a time\n- Upsert the Expression Set using the `cml-api` name\n- Read and upsert `ExpressionSetConstraintObj` rows from the `cml-api_associations.csv` file (resolving FKs)\n- Upload the CML blob",
408
+ "description": "Reads a `<cmlApi>_SurchargeUpdate.json` or `<cmlApi>_UnderwritingUpdate.json` file — the reviewable record-update plan emitted by `sf cml convert surcharge-rules` / `sf cml convert underwriting-rules` — and applies its changes to the org. Convert is file-only and never writes to the org; this command is the apply step.\n\nThe file is treated as untrusted input: it is structurally validated, every record is re-read from the org before anything is written, and each record's Name (plus the rule apiName for underwriting rule updates) is cross-checked against the file so an edited id cannot retarget a different record. Records whose org values already match are skipped, which makes re-running the command safe and idempotent.\n\nBefore applying, the command prints every planned field-level change and asks for confirmation. Use --dry-run to review the plan without writing, and --no-prompt to apply without confirmation in automation. Changes are applied in order and are not rolled back, so a mid-apply failure can leave the org partially migrated; re-running is safe because already-applied records are skipped.\n\nImport the merged CML with `sf cml import as-expression-set` BEFORE applying a surcharge record-update file. The platform regenerates ProductSurcharge.RuleKey when RuleEngineType flips, and this command verifies that regenerated key against the key the CML rule was emitted under. That regeneration also requires the parent Surcharge.Code to be non-null — a surcharge whose parent Surcharge has a null Code cannot be flipped to ConstraintEngine and the org raises a save-hook error.",
315
409
  "examples": [
316
- "<%= config.bin %> <%= command.id %> --cml-api MY_TEST --context-definition PricingTransactionCD2 --workspace-dir data --target-org tgtOrg"
410
+ "Review the planned changes without writing anything:\n<%= config.bin %> <%= command.id %> --file data/SURCHARGE_CML_SurchargeUpdate.json --target-org myOrg --dry-run",
411
+ "Apply the changes, confirming the preview interactively:\n<%= config.bin %> <%= command.id %> --file data/SURCHARGE_CML_SurchargeUpdate.json --target-org myOrg",
412
+ "Apply the changes without a confirmation prompt, for automation:\n<%= config.bin %> <%= command.id %> --file data/UW_CML_UnderwritingUpdate.json --target-org myOrg --no-prompt"
317
413
  ],
318
414
  "flags": {
319
415
  "json": {
@@ -348,60 +444,56 @@
348
444
  "multiple": false,
349
445
  "type": "option"
350
446
  },
351
- "context-definition": {
352
- "char": "x",
353
- "name": "context-definition",
447
+ "file": {
448
+ "char": "f",
449
+ "name": "file",
354
450
  "required": true,
355
- "summary": "Context Definition name to be assocciated with the CML.",
451
+ "summary": "Path to the record-update JSON file emitted by a cml convert command.",
356
452
  "hasDynamicHelp": false,
357
453
  "multiple": false,
358
454
  "type": "option"
359
455
  },
360
- "cml-api": {
361
- "char": "c",
362
- "name": "cml-api",
363
- "required": true,
364
- "summary": "Unique CML API Name to be created.",
365
- "hasDynamicHelp": false,
366
- "multiple": false,
367
- "type": "option"
456
+ "no-prompt": {
457
+ "char": "p",
458
+ "name": "no-prompt",
459
+ "summary": "Don't prompt for confirmation before applying the changes.",
460
+ "allowNo": false,
461
+ "type": "boolean"
368
462
  },
369
- "workspace-dir": {
370
- "char": "d",
371
- "name": "workspace-dir",
372
- "summary": "Directory where converted CML and assocciations csv files are located.",
373
- "hasDynamicHelp": false,
374
- "multiple": false,
375
- "type": "option"
463
+ "dry-run": {
464
+ "name": "dry-run",
465
+ "summary": "Show the planned changes and exit without writing anything to the org.",
466
+ "allowNo": false,
467
+ "type": "boolean"
376
468
  }
377
469
  },
378
470
  "hasDynamicHelp": true,
379
471
  "hiddenAliases": [],
380
- "id": "cml:import:as-expression-set",
472
+ "id": "insurance:import:record-updates",
381
473
  "pluginAlias": "@salesforce/plugin-bre-to-cml",
382
474
  "pluginName": "@salesforce/plugin-bre-to-cml",
383
475
  "pluginType": "core",
384
476
  "strict": true,
385
- "summary": "Imports CML and associations to the target org",
477
+ "summary": "Applies a record-update file emitted by a cml convert command to the target org.",
386
478
  "enableJsonFlag": true,
387
479
  "isESM": true,
388
480
  "relativePath": [
389
481
  "lib",
390
482
  "commands",
391
- "cml",
483
+ "insurance",
392
484
  "import",
393
- "as-expression-set.js"
485
+ "record-updates.js"
394
486
  ],
395
487
  "aliasPermutations": [],
396
488
  "permutations": [
397
- "cml:import:as-expression-set",
398
- "import:cml:as-expression-set",
399
- "import:as-expression-set:cml",
400
- "cml:as-expression-set:import",
401
- "as-expression-set:cml:import",
402
- "as-expression-set:import:cml"
489
+ "insurance:import:record-updates",
490
+ "import:insurance:record-updates",
491
+ "import:record-updates:insurance",
492
+ "insurance:record-updates:import",
493
+ "record-updates:insurance:import",
494
+ "record-updates:import:insurance"
403
495
  ]
404
496
  }
405
497
  },
406
- "version": "1.3.0"
498
+ "version": "1.3.2"
407
499
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@salesforce/plugin-bre-to-cml",
3
3
  "description": "Plugin for migrating BRE based configurator rules to CML.",
4
- "version": "1.3.0",
4
+ "version": "1.3.2",
5
5
  "salesforceRelease": "256.11",
6
6
  "dependencies": {
7
7
  "@oclif/core": "^4",
@@ -11,15 +11,15 @@
11
11
  "got": "12"
12
12
  },
13
13
  "devDependencies": {
14
- "@oclif/plugin-command-snapshot": "^5.3.33",
15
- "@oclif/test": "^4.1.21",
16
- "@salesforce/cli-plugins-testkit": "^5.3.64",
14
+ "@oclif/plugin-command-snapshot": "^5.3.35",
15
+ "@oclif/test": "^4.1.22",
16
+ "@salesforce/cli-plugins-testkit": "^5.3.66",
17
17
  "@salesforce/dev-scripts": "^11.0.4",
18
- "@salesforce/plugin-command-reference": "^3.1.131",
18
+ "@salesforce/plugin-command-reference": "^3.1.132",
19
19
  "@types/node": "^22.20.1",
20
20
  "eslint-config-salesforce-license": "^1.0.2",
21
21
  "eslint-plugin-sf-plugin": "^1.20.33",
22
- "oclif": "^4.23.29",
22
+ "oclif": "^4.23.30",
23
23
  "ts-node": "^10.9.2",
24
24
  "typescript": "^5.9.3"
25
25
  },
@@ -62,6 +62,14 @@
62
62
  "description": "description for cml.import"
63
63
  }
64
64
  }
65
+ },
66
+ "insurance": {
67
+ "description": "description for insurance",
68
+ "subtopics": {
69
+ "import": {
70
+ "description": "description for insurance.import"
71
+ }
72
+ }
65
73
  }
66
74
  },
67
75
  "flexibleTaxonomy": true
@@ -221,7 +229,7 @@
221
229
  "type": "module",
222
230
  "author": "George Kibilov",
223
231
  "sfdx": {
224
- "publicKeyUrl": "https://developer.salesforce.com/media/salesforce-cli/security/@salesforce/plugin-bre-to-cml/1.3.0.crt",
225
- "signatureUrl": "https://developer.salesforce.com/media/salesforce-cli/security/@salesforce/plugin-bre-to-cml/1.3.0.sig"
232
+ "publicKeyUrl": "https://developer.salesforce.com/media/salesforce-cli/security/@salesforce/plugin-bre-to-cml/1.3.2.crt",
233
+ "signatureUrl": "https://developer.salesforce.com/media/salesforce-cli/security/@salesforce/plugin-bre-to-cml/1.3.2.sig"
226
234
  }
227
235
  }