@salesforce/afv-skills 1.45.0 → 1.47.0
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/package.json +1 -1
- package/skills/agentforce-observe/SKILL.md +32 -4
- package/skills/agentforce-observe/references/ahm-alerts.md +719 -0
- package/skills/automation-flow-generate/SKILL.md +11 -5
- package/skills/consumer-goods-promotion-bo-api-deploy/SKILL.md +275 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/README.md +32 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/SetCommentValue.cls +75 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/SetCommentValue.cls-meta.xml +5 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/interview-answers.json +13 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/copy.json +10 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/create.json +20 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/update.json +16 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/references/conventions-and-payload-rules.md +273 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/references/generate-and-wire.md +236 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/references/reference-example-set-comment-value.md +132 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/references/smoke-and-verify.md +211 -0
- package/skills/dx-code-analyzer-configure/scripts/validate-config.sh +14 -10
- package/skills/dx-code-analyzer-run/scripts/apply-fixes.js +45 -4
- package/skills/dx-code-analyzer-run/scripts/describe-rule.js +52 -32
- package/skills/dx-devops-project-manage/SKILL.md +197 -0
- package/skills/dx-devops-project-manage/examples/common-workflows.md +197 -0
- package/skills/dx-devops-project-manage/references/cli-commands.md +295 -0
- package/skills/dx-devops-project-manage/scripts/create-project.sh +48 -0
- package/skills/dx-devops-project-manage/scripts/list-projects.sh +51 -0
- package/skills/dx-devops-project-manage/scripts/update-project.sh +96 -0
- package/skills/education-cloud-academic-calendar-generate/SKILL.md +225 -0
- package/skills/education-cloud-academic-calendar-generate/examples/quarter-calendar.json +47 -0
- package/skills/education-cloud-academic-calendar-generate/examples/sample-output.md +57 -0
- package/skills/education-cloud-academic-calendar-generate/examples/semester-calendar.json +54 -0
- package/skills/education-cloud-academic-calendar-generate/references/calendar-systems.md +127 -0
- package/skills/education-cloud-academic-calendar-generate/references/date-validation.md +222 -0
- package/skills/education-cloud-academic-calendar-generate/references/foundation_prerequisites.md +40 -0
- package/skills/education-cloud-academic-calendar-generate/scripts/validate_calendar_dates.py +143 -0
- package/skills/education-cloud-course-catalog-migrate/SKILL.md +321 -0
- package/skills/education-cloud-course-catalog-migrate/references/gotchas-detail.md +16 -0
- package/skills/education-cloud-course-catalog-migrate/references/gotchas.md +16 -0
- package/skills/education-cloud-course-catalog-migrate/references/large-catalog-handling.md +42 -0
- package/skills/education-cloud-course-catalog-migrate/scripts/batch_courses.py +36 -0
- package/skills/education-cloud-course-catalog-migrate/scripts/detect_linked_courses.py +51 -0
- package/skills/education-cloud-course-catalog-migrate/scripts/detect_modality_variants.py +48 -0
- package/skills/education-cloud-course-catalog-migrate/scripts/resolve_api_version.py +43 -0
- package/skills/education-cloud-course-catalog-migrate/scripts/split_course_code.py +39 -0
- package/skills/education-cloud-course-catalog-migrate/scripts/validate_completeness.py +54 -0
- package/skills/education-cloud-multi-campus-configure/references/foundation_prerequisites.md +3 -5
- package/skills/education-cloud-student-recruitment-agent-configure/SKILL.md +177 -0
- package/skills/education-cloud-student-recruitment-agent-configure/references/agent-and-subagents.md +151 -0
- package/skills/education-cloud-student-recruitment-agent-configure/references/customer-narration.md +34 -0
- package/skills/education-cloud-student-recruitment-agent-configure/references/execution-model.md +54 -0
- package/skills/education-cloud-student-recruitment-agent-configure/references/flows.md +82 -0
- package/skills/education-cloud-student-recruitment-agent-configure/references/grounding.md +199 -0
- package/skills/education-cloud-student-recruitment-agent-configure/references/permissions.md +183 -0
- package/skills/education-cloud-student-recruitment-agent-configure/references/platform-enablement.md +82 -0
- package/skills/education-cloud-student-recruitment-agent-configure/references/prerequisites.md +158 -0
- package/skills/education-cloud-student-recruitment-agent-configure/references/routing.md +141 -0
- package/skills/experience-cms-brand-apply/SKILL.md +5 -5
- package/skills/experience-cms-brand-create/SKILL.md +2 -2
- package/skills/experience-cms-content-generate/SKILL.md +1 -0
- package/skills/experience-cms-content-render/SKILL.md +173 -0
- package/skills/experience-cms-content-render/assets/angular/DetailPage.component.ts +25 -0
- package/skills/experience-cms-content-render/assets/angular/MediaRenderer.component.ts +133 -0
- package/skills/experience-cms-content-render/assets/angular/TypeList.component.ts +38 -0
- package/skills/experience-cms-content-render/assets/angular/TypeRenderer.component.ts +90 -0
- package/skills/experience-cms-content-render/assets/angular/cms-content.component.ts +248 -0
- package/skills/experience-cms-content-render/assets/angular/cms-item.service.ts +100 -0
- package/skills/experience-cms-content-render/assets/react/DetailPage.tsx +20 -0
- package/skills/experience-cms-content-render/assets/react/MediaRenderer.tsx +129 -0
- package/skills/experience-cms-content-render/assets/react/TypeList.tsx +40 -0
- package/skills/experience-cms-content-render/assets/react/TypeRenderer.tsx +64 -0
- package/skills/experience-cms-content-render/assets/react/heuristicRenderer.tsx +310 -0
- package/skills/experience-cms-content-render/assets/react/useCmsItem.ts +129 -0
- package/skills/experience-cms-content-render/assets/shared/cmsContentType.ts +49 -0
- package/skills/experience-cms-content-render/assets/shared/cmsCore.types.ts +96 -0
- package/skills/experience-cms-content-render/assets/shared/externalRefs.ts +55 -0
- package/skills/experience-cms-content-render/references/bulk-loading.md +60 -0
- package/skills/experience-cms-content-render/references/codegen-guardrails.md +111 -0
- package/skills/experience-cms-content-render/references/detail-pages.md +87 -0
- package/skills/experience-cms-content-render/references/embed-recipes.md +127 -0
- package/skills/experience-cms-content-render/references/failure-modes.md +96 -0
- package/skills/experience-cms-content-render/references/heuristic-render-rules.md +131 -0
- package/skills/experience-cms-content-render/references/init-scaffold.md +122 -0
- package/skills/experience-cms-content-render/references/interaction-model.md +173 -0
- package/skills/experience-cms-content-render/references/package-api.md +106 -0
- package/skills/experience-cms-content-render/references/schema-sync.md +114 -0
- package/skills/experience-cms-content-render/references/styling-scopes.md +65 -0
- package/skills/experience-cms-content-render/references/verify.md +49 -0
- package/skills/experience-cms-content-type-generate/SKILL.md +2 -2
- package/skills/experience-content-media-stock-image-search/SKILL.md +5 -4
- package/skills/experience-search-coordinate/SKILL.md +198 -0
- package/skills/experience-search-coordinate/assets/search-payload-template.json +25 -0
- package/skills/experience-search-coordinate/references/content-route.md +313 -0
- package/skills/experience-search-coordinate/references/content-type-discovery.md +57 -0
- package/skills/experience-search-coordinate/references/media-route.md +172 -0
- package/skills/experience-search-coordinate/references/scope-resolution.md +14 -0
- package/skills/experience-ui-bundle-localize/SKILL.md +1 -1
- package/skills/experience-ui-bundle-localize/references/i18n-setup.md +5 -3
- package/skills/experience-ui-bundle-project-generate/SKILL.md +18 -14
- package/skills/experience-ui-bundle-project-generate/references/angular-project-generate.md +22 -0
- package/skills/experience-ui-bundle-project-generate/references/react-project-generate.md +20 -0
- package/skills/experience-ui-bundle-salesforce-data-access/SKILL.md +58 -54
- package/skills/experience-ui-bundle-salesforce-data-access/references/caching.md +6 -0
- package/skills/experience-ui-bundle-salesforce-data-access/references/graphiti-cli.md +2 -2
- package/skills/experience-ui-bundle-salesforce-data-access/references/migration.md +6 -0
- package/skills/experience-ui-bundle-salesforce-data-access/references/rest-and-integration.md +2 -1
- package/skills/experience-ui-bundle-salesforce-data-access/references/sdk-api.md +6 -0
- package/skills/experience-ui-bundle-site-generate/SKILL.md +59 -8
- package/skills/experience-ui-bundle-site-generate/references/configure-metadata-digital-experience.md +8 -3
- package/skills/experience-ui-bundle-site-generate/references/configure-metadata-language-settings.md +120 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/SKILL.md +336 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/orchestration-flow.md +143 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-application-flexipage-mapping.md +127 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-deploy-commands.md +116 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-lifesci-metadata-deploy.md +111 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-overview.md +312 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-profile-layout-assignments.md +171 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-state-tracking.md +64 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-trigger-handlers.md +122 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-4-user-provisioning-overview.md +335 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-4-user-provisioning-user-provisioning-details.md +140 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-execution-state-and-recovery.md +196 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-metadata-cache-generation.md +155 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-overview.md +307 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-visit-creation-data.md +211 -0
- package/skills/life-sciences-fieldsalesrep-coordinate/references/state-machine-and-changes.md +108 -0
- package/skills/life-sciences-kam-coordinate/SKILL.md +241 -0
- package/skills/life-sciences-kam-coordinate/references/orchestration-flow.md +152 -0
- package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-application-flexipage-mapping.md +79 -0
- package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-deploy-commands.md +131 -0
- package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-kam-config-records.md +85 -0
- package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-lifesci-metadata-deploy.md +112 -0
- package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-overview.md +202 -0
- package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-profile-layout-assignments.md +67 -0
- package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-state-tracking.md +65 -0
- package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-trigger-handlers.md +123 -0
- package/skills/life-sciences-kam-coordinate/references/stage-4-participant-role-and-sprint.md +89 -0
- package/skills/life-sciences-kam-coordinate/references/stage-5-data-and-plan-templates-overview.md +337 -0
- package/skills/life-sciences-kam-coordinate/references/stage-5-data-creation-data.md +248 -0
- package/skills/life-sciences-kam-coordinate/references/stage-6-ipad-validation-script.md +35 -0
- package/skills/life-sciences-kam-coordinate/references/stage-6-metadata-cache-generation.md +155 -0
- package/skills/life-sciences-kam-coordinate/references/stage-6-user-provisioning-details.md +146 -0
- package/skills/life-sciences-kam-coordinate/references/stage-6-user-provisioning-overview.md +89 -0
- package/skills/life-sciences-kam-coordinate/references/state-machine-and-changes.md +114 -0
- package/skills/life-sciences-prerequisites-validate/SKILL.md +138 -0
- package/skills/life-sciences-prerequisites-validate/references/checks-org-settings.md +190 -0
- package/skills/life-sciences-prerequisites-validate/references/checks-user-and-package.md +211 -0
- package/skills/life-sciences-territory-configure/SKILL.md +217 -0
- package/skills/life-sciences-territory-configure/references/territory-metadata.md +262 -0
- package/skills/platform-apex-logs-debug/SKILL.md +7 -7
- package/skills/platform-custom-application-generate/SKILL.md +4 -4
- package/skills/platform-custom-object-generate/SKILL.md +7 -7
- package/skills/platform-custom-tab-generate/SKILL.md +1 -1
- package/skills/platform-dsar-policy-manage/SKILL.md +272 -0
- package/skills/platform-dsar-policy-manage/references/configure.md +106 -0
- package/skills/platform-dsar-policy-manage/references/export-and-history.md +123 -0
- package/skills/platform-dsar-policy-manage/references/gap-analysis-guide.md +150 -0
- package/skills/platform-dsar-policy-manage/references/gap-scan.md +129 -0
- package/skills/platform-dsar-policy-manage/references/headless-sor.md +59 -0
- package/skills/platform-dsar-policy-manage/references/report-format.md +59 -0
- package/skills/platform-dsar-policy-manage/scripts/tests/__init__.py +0 -0
- package/skills/platform-dsar-policy-manage/scripts/tests/test_validate_policy_tree.py +76 -0
- package/skills/platform-dsar-policy-manage/scripts/validate-policy-tree.py +130 -0
- package/skills/platform-flexipage-generate/SKILL.md +4 -0
- package/skills/platform-list-view-generate/SKILL.md +1 -0
- package/skills/platform-salesforce-connect-adapter-generate/SKILL.md +359 -0
- package/skills/platform-salesforce-connect-adapter-generate/references/official-examples.md +69 -0
- package/skills/platform-salesforce-connect-adapter-generate/references/scenarios.md +187 -0
- package/skills/platform-soql-query/SKILL.md +8 -8
- package/skills/platform-value-set-generate/SKILL.md +2 -2
- package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +20 -27
- package/skills/service-native-voice-recording-transcription-configure/SKILL.md +47 -27
- package/skills/service-native-voice-recording-transcription-configure/references/thunderbird-voice-settings.md +13 -9
- package/skills/service-native-voice-recording-transcription-configure/scripts/enable-recording-transcription.sh +104 -45
package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-trigger-handlers.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Trigger Handlers Reference
|
|
2
|
+
|
|
3
|
+
## Handler List
|
|
4
|
+
|
|
5
|
+
The following trigger handlers must be activated:
|
|
6
|
+
|
|
7
|
+
1. AffiliationUniquenessGenericHandler
|
|
8
|
+
2. AffiliationUniquenessHandler
|
|
9
|
+
3. HardAffiliationHandler
|
|
10
|
+
4. AffiliationReciprocalHandler
|
|
11
|
+
5. HealthcareProviderAffiliationHandler
|
|
12
|
+
6. AffiliationPrimaryChangeHandler
|
|
13
|
+
7. AffiliationAccountUpdateHandler
|
|
14
|
+
8. TerrAcctRcmdActionSharingHandler
|
|
15
|
+
9. TerrAccRcmActStatusUpdateHandler
|
|
16
|
+
10. CaseMSLQueueHandler
|
|
17
|
+
11. CaseChangeOwnershipHandler
|
|
18
|
+
12. CaseShareToCreatorHandler
|
|
19
|
+
13. StagePathPermissionsHandler
|
|
20
|
+
14. AccountPlanDeleteChildrenHandler
|
|
21
|
+
15. AccountPlanChangeStatusHandler
|
|
22
|
+
16. SetAccPlanPercentCompleteHandler
|
|
23
|
+
17. AcctPlanObjDeleteChildrenHandler
|
|
24
|
+
18. SetAccObjectPercentCompleteHandler
|
|
25
|
+
19. ActionPlanDeleteChildrenHandler
|
|
26
|
+
20. SetSprintPercentCompleteHandler
|
|
27
|
+
21. SetGoalAsgmtPercentCompleteHandler
|
|
28
|
+
22. SetActionPlanPercentCompleteHandler
|
|
29
|
+
23. AssessmentTaskDeleteAPItemHandler
|
|
30
|
+
24. AssessmentTaskSharingHandler
|
|
31
|
+
25. TerritoryBusinessPlanDeleteHandler
|
|
32
|
+
26. GoalAssignmentDeleteHandler
|
|
33
|
+
27. TerritoryBusPlanChangeStatusHandler
|
|
34
|
+
28. SetTerrBusPlanPrcntCompleteHandler
|
|
35
|
+
|
|
36
|
+
## Activation Method
|
|
37
|
+
|
|
38
|
+
Trigger handlers in Life Sciences Cloud are **`LifeScienceTriggerHandler`** records — a standard Tooling API entity (NOT a managed `lsc4ce__TriggerHandler__c` custom object). All queries and updates MUST use `--use-tooling-api`. Relevant fields:
|
|
39
|
+
|
|
40
|
+
- `DeveloperName` — the handler name (e.g. `AffiliationUniquenessGenericHandler`)
|
|
41
|
+
- `IsActive` — the active flag (Boolean)
|
|
42
|
+
- `ObjectApiName` — the object the handler runs on
|
|
43
|
+
|
|
44
|
+
> **Verified behavior:** the standard-API sobject name `lsc4ce__TriggerHandler__c` does NOT exist and returns `sObject type '...' is not supported`. `LifeScienceTriggerHandler` is only accessible via the Tooling API. A freshly-deployed org typically has ~185 handlers, all `IsActive=false` initially; the 28 below are the subset the starter config activates.
|
|
45
|
+
|
|
46
|
+
### Preferred: Query then Update (Tooling API)
|
|
47
|
+
|
|
48
|
+
First, get the handler's Id and current state:
|
|
49
|
+
```bash
|
|
50
|
+
sf data query --query "SELECT Id, DeveloperName, IsActive FROM LifeScienceTriggerHandler WHERE DeveloperName = '<HandlerName>'" --target-org <org> --use-tooling-api --json
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Then activate by Id:
|
|
54
|
+
```bash
|
|
55
|
+
sf data update record --sobject LifeScienceTriggerHandler --record-id <Id> --values "IsActive=true" --target-org <org> --use-tooling-api
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Batch: query all inactive IDs in one call, then update each
|
|
59
|
+
|
|
60
|
+
Individual query-then-update per handler is slow (each `sf` invocation has startup overhead; 28 sequential handlers can exceed 2 minutes). Fetch all still-inactive IDs in ONE query, then loop the updates.
|
|
61
|
+
|
|
62
|
+
> **STOP-GATE (do not drop the last handler).** Build the update loop so it processes **every** returned ID. Two failure modes to avoid: **(1)** a naive `while read` over a *captured* ID list drops the final ID when that list has no trailing newline (the classic "27 of 28" bug); **(2)** an unquoted `for id in $IDS` loop relies on **bash word-splitting**, which **zsh does NOT do by default** — under zsh the whole multiline blob stays a single `$id`, every update fails on an invalid record-id, and you get **"0 of 28"**. Do NOT use either. The portable, shell-agnostic, drop-safe pattern is to pipe `jq` (which newline-terminates every record, including the last) into `while IFS= read -r id` via **process substitution** `< <(...)`: it behaves identically in bash and zsh and keeps the loop in the current shell so the counter survives. After the loop, always re-run the Verification query below and confirm the active count equals the full handler count (28) before proceeding — if it is short, identify the straggler(s) by name and activate each individually.
|
|
63
|
+
|
|
64
|
+
Use a single query filtered to `IsActive = false` (already-active handlers are skipped automatically — re-running is safe but wasteful), then loop with one of the safe patterns:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
ORG=<org>
|
|
68
|
+
n=0; total=0
|
|
69
|
+
# Pipe jq (newline-terminates EVERY record, incl. the last) into `while read` via
|
|
70
|
+
# process substitution `< <(...)`. Portable across bash AND zsh; the loop stays in the
|
|
71
|
+
# current shell so $n/$total survive. Never `for id in $IDS` (zsh won't word-split it).
|
|
72
|
+
while IFS= read -r id; do
|
|
73
|
+
total=$((total+1))
|
|
74
|
+
sf data update record --sobject LifeScienceTriggerHandler --record-id "$id" \
|
|
75
|
+
--values "IsActive=true" --target-org "$ORG" --use-tooling-api >/dev/null && n=$((n+1))
|
|
76
|
+
echo " ...$n activated"
|
|
77
|
+
done < <(sf data query \
|
|
78
|
+
--query "SELECT Id FROM LifeScienceTriggerHandler WHERE IsActive = false AND DeveloperName IN ('AffiliationUniquenessGenericHandler','AffiliationUniquenessHandler','HardAffiliationHandler','AffiliationReciprocalHandler','HealthcareProviderAffiliationHandler','AffiliationPrimaryChangeHandler','AffiliationAccountUpdateHandler','TerrAcctRcmdActionSharingHandler','TerrAccRcmActStatusUpdateHandler','CaseMSLQueueHandler','CaseChangeOwnershipHandler','CaseShareToCreatorHandler','StagePathPermissionsHandler','AccountPlanDeleteChildrenHandler','AccountPlanChangeStatusHandler','SetAccPlanPercentCompleteHandler','AcctPlanObjDeleteChildrenHandler','SetAccObjectPercentCompleteHandler','ActionPlanDeleteChildrenHandler','SetSprintPercentCompleteHandler','SetGoalAsgmtPercentCompleteHandler','SetActionPlanPercentCompleteHandler','AssessmentTaskDeleteAPItemHandler','AssessmentTaskSharingHandler','TerritoryBusinessPlanDeleteHandler','GoalAssignmentDeleteHandler','TerritoryBusPlanChangeStatusHandler','SetTerrBusPlanPrcntCompleteHandler')" \
|
|
79
|
+
--target-org "$ORG" --use-tooling-api --json | jq -r '.result.records[].Id')
|
|
80
|
+
echo "Activated $n of $total inactive handler(s)."
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
If every one of the 28 was already active, the query returns zero rows and the loop is a no-op — that is a valid PASS, not a failure.
|
|
84
|
+
|
|
85
|
+
### Verification
|
|
86
|
+
|
|
87
|
+
After activation, confirm the active count equals the full handler count (28) — count directly rather than eyeballing rows:
|
|
88
|
+
```bash
|
|
89
|
+
sf data query --query "SELECT COUNT(Id) active FROM LifeScienceTriggerHandler WHERE IsActive = true AND DeveloperName IN ('AffiliationUniquenessGenericHandler','AffiliationUniquenessHandler','HardAffiliationHandler','AffiliationReciprocalHandler','HealthcareProviderAffiliationHandler','AffiliationPrimaryChangeHandler','AffiliationAccountUpdateHandler','TerrAcctRcmdActionSharingHandler','TerrAccRcmActStatusUpdateHandler','CaseMSLQueueHandler','CaseChangeOwnershipHandler','CaseShareToCreatorHandler','StagePathPermissionsHandler','AccountPlanDeleteChildrenHandler','AccountPlanChangeStatusHandler','SetAccPlanPercentCompleteHandler','AcctPlanObjDeleteChildrenHandler','SetAccObjectPercentCompleteHandler','ActionPlanDeleteChildrenHandler','SetSprintPercentCompleteHandler','SetGoalAsgmtPercentCompleteHandler','SetActionPlanPercentCompleteHandler','AssessmentTaskDeleteAPItemHandler','AssessmentTaskSharingHandler','TerritoryBusinessPlanDeleteHandler','GoalAssignmentDeleteHandler','TerritoryBusPlanChangeStatusHandler','SetTerrBusPlanPrcntCompleteHandler')" --target-org <org> --use-tooling-api --json
|
|
90
|
+
```
|
|
91
|
+
The returned `active` count MUST be **28**. If it is fewer, list the still-inactive names (query the same set with `IsActive = false`), activate each straggler individually, and re-run this count until it reads 28. Do NOT proceed to the next step while any handler is inactive.
|
|
92
|
+
|
|
93
|
+
### Error Handling
|
|
94
|
+
|
|
95
|
+
| Error | Cause | Resolution |
|
|
96
|
+
|-------|-------|------------|
|
|
97
|
+
| `sObject type 'lsc4ce__TriggerHandler__c' is not supported` | Wrong object name / missing tooling flag | Use `LifeScienceTriggerHandler` with `--use-tooling-api` |
|
|
98
|
+
| "No records found" | Handler `DeveloperName` doesn't exist in the org | The managed package may not have created it yet; skip and note |
|
|
99
|
+
| Command times out activating all 28 | Sequential per-handler `sf` calls are slow | Fetch all inactive IDs in one query, then loop updates (see the safe-loop patterns above); skip already-active ones |
|
|
100
|
+
| "27 of 28 activated" / last handler skipped | A `while read` over a *captured* list dropped the final unterminated line | Use the jq-piped `while IFS= read -r` via process substitution shown above; re-run the count check and activate any straggler individually |
|
|
101
|
+
| "0 of 28 activated" (loop ran once, all IDs mashed into one value) | An unquoted `for id in $IDS` loop under **zsh**, which does not word-split unquoted params — `$IDS` stayed one multiline string | Use the jq-piped `while IFS= read -r` via process substitution shown above (portable across bash/zsh); never rely on `for` word-splitting |
|
|
102
|
+
| "Insufficient access" | User lacks edit permission on the tooling entity | User needs appropriate permission set |
|
|
103
|
+
|
|
104
|
+
### Progress Reporting
|
|
105
|
+
|
|
106
|
+
Report activation progress:
|
|
107
|
+
```text
|
|
108
|
+
Activating trigger handlers: 15/28 complete...
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
If any handler fails, collect all failures and report at the end:
|
|
112
|
+
```text
|
|
113
|
+
3 handlers could not be activated:
|
|
114
|
+
- CaseMSLQueueHandler: No record found
|
|
115
|
+
- StagePathPermissionsHandler: Field not found
|
|
116
|
+
- AssessmentTaskSharingHandler: Insufficient access
|
|
117
|
+
|
|
118
|
+
25/28 handlers activated successfully.
|
|
119
|
+
Options:
|
|
120
|
+
1. Retry failed handlers
|
|
121
|
+
2. Skip and continue to next step
|
|
122
|
+
```
|
|
123
|
+
</content>
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Stage 4 — Participant Role & Sprint (KAM)
|
|
2
|
+
|
|
3
|
+
Creates two records that later KAM stages depend on: a `ParticipantRole` (used by Account Plan participation) and a `Sprint` (the execution window for the KAM plan). Run entirely as the **admin** (`--target-org <admin>`). This is Stage 4 of `life-sciences-kam-coordinate`; the coordinator invokes it after territories (Stage 3) are active.
|
|
4
|
+
|
|
5
|
+
Only the **name** of each record is shown to and confirmed with the admin (accept the default or supply a different name). Every other field is auto-derived and kept **internal — do NOT display it to the admin.**
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Record 1 — ParticipantRole
|
|
10
|
+
|
|
11
|
+
**Show the admin only the "Participant Role Name"** (default `Rep Execution Specialist`) and ask them to accept the default or supply a different name. This name is stored internally in the `MasterLabel` field — do **NOT** surface the field name "MasterLabel" to the admin, and do **NOT** show any of the internal fields below.
|
|
12
|
+
|
|
13
|
+
| Field | Value | Shown to admin? |
|
|
14
|
+
|-------|-------|-----------------|
|
|
15
|
+
| `MasterLabel` | the confirmed name, e.g. `Rep Execution Specialist` | Shown **as "Participant Role Name"** (never as "MasterLabel") |
|
|
16
|
+
| `DeveloperName` | derived from the name: replace spaces with `_`, e.g. `Rep_Execution_Specialist` | Internal — not shown |
|
|
17
|
+
| `IsActive` | `true` | Internal — not shown |
|
|
18
|
+
| `ParentObject` | `AccountPlan` | Internal — not shown |
|
|
19
|
+
| `DefaultAccessLevel` | `Edit` | Internal — not shown |
|
|
20
|
+
|
|
21
|
+
> **DeveloperName derivation:** take the confirmed Participant Role Name and replace every space with `_` (e.g. `Rep Execution Specialist` → `Rep_Execution_Specialist`). Compute it internally; never ask the admin for it.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
sf data create record --sobject ParticipantRole --target-org <admin> \
|
|
25
|
+
--values "MasterLabel='Rep Execution Specialist' DeveloperName=Rep_Execution_Specialist IsActive=true ParentObject=AccountPlan DefaultAccessLevel=Edit" --json
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
> `ParticipantRole` may be a Metadata/Tooling-backed entity in some orgs. If `sf data create record` reports the sObject is not createable via the data API, create it with the Tooling API (`--use-tooling-api`) or as metadata; the field values above are unchanged. Verify with a Tooling query if the standard query returns nothing.
|
|
29
|
+
|
|
30
|
+
### Verify
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
sf data query --query "SELECT Id, MasterLabel, DeveloperName, IsActive, ParentObject, DefaultAccessLevel FROM ParticipantRole WHERE DeveloperName = 'Rep_Execution_Specialist'" --target-org <admin> --json
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Expect exactly 1 record with `IsActive=true`. Capture its Id in `OrchestrationState`.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Record 2 — Sprint
|
|
41
|
+
|
|
42
|
+
Dates are relative to the run date. Compute them from the current date at run time — do **not** hardcode a date.
|
|
43
|
+
|
|
44
|
+
**Before creation, show the admin only the Sprint Name** (default `Sprint 1 – Immunexis P&T Prep`) and ask them to accept the default or supply a different name. Do **NOT** show the dates or `Status` before creation.
|
|
45
|
+
|
|
46
|
+
| Field | Value | Shown to admin? |
|
|
47
|
+
|-------|-------|-----------------|
|
|
48
|
+
| `Name` | the confirmed name, e.g. `Sprint 1 – Immunexis P&T Prep` | Shown before creation (accept default or change) |
|
|
49
|
+
| `EffectiveStartDate` | Today (run date) | Internal — not shown before creation |
|
|
50
|
+
| `EffectiveEndDate` | Start + 2 weeks (14 days) | Internal — not shown before creation |
|
|
51
|
+
| `Status` | `Not Started` | Internal — not shown before creation |
|
|
52
|
+
|
|
53
|
+
> **After the Sprint is created, display** its `Name`, Start Date, End Date, and Status to the admin — a post-creation summary. This is the only point at which the dates and `Status` are shown.
|
|
54
|
+
|
|
55
|
+
Derive the dates so the two-week window is exact:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
START=$(date +%F)
|
|
59
|
+
END=$(date -v+14d +%F 2>/dev/null || date -d "+14 days" +%F) # macOS / GNU date
|
|
60
|
+
sf data create record --sobject Sprint --target-org <admin> \
|
|
61
|
+
--values "Name='Sprint 1 – Immunexis P&T Prep' EffectiveStartDate=$START EffectiveEndDate=$END Status='Not Started'" --json
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
> The em dash in the name (`–`, U+2013) is intentional — keep it as written. Wrap the value in single quotes so the shell preserves it.
|
|
65
|
+
|
|
66
|
+
### Verify
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
sf data query --query "SELECT Id, Name, EffectiveStartDate, EffectiveEndDate, Status FROM Sprint ORDER BY CreatedDate DESC LIMIT 1" --target-org <admin> --json
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Expect the sprint with `Status='Not Started'` and a 14-day window. Capture its Id.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Confirmation Before Creating
|
|
77
|
+
|
|
78
|
+
For **each** record, show the admin **only its name** — the Participant Role Name and the Sprint Name — and ask them to accept the default or supply a different one. Do **NOT** show the internal/auto-derived fields (`DeveloperName`, `IsActive`, `ParentObject`, `DefaultAccessLevel`, the Sprint dates, `Status`) before creating. After the Sprint is created, display its `Name`, Start Date, End Date, and Status as a post-creation summary.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Gotchas
|
|
83
|
+
|
|
84
|
+
| Issue | Resolution |
|
|
85
|
+
|-------|------------|
|
|
86
|
+
| `date -v+14d` fails | That is BSD/macOS syntax; on GNU/Linux use `date -d "+14 days" +%F` (the command above tries both) |
|
|
87
|
+
| `DUPLICATE_DEVELOPER_NAME` on ParticipantRole | The role already exists (idempotent re-run) — query it and reuse rather than treating as an error |
|
|
88
|
+
| Em dash mangled in the Sprint name | Ensure the terminal/locale is UTF-8 and the value is single-quoted; re-create if it landed as `?` or `-` |
|
|
89
|
+
| `Status` rejected | The value must match the `SprintStatus` StandardValueSet confirmed in Stage 2 — `Not Started` is the default entry |
|
package/skills/life-sciences-kam-coordinate/references/stage-5-data-and-plan-templates-overview.md
ADDED
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
# Stage 5 — KAM Data & Plan Templates
|
|
2
|
+
|
|
3
|
+
This single stage creates all the KAM master data **and** the plan templates that back the account plan, all as the **admin** (`--target-org <admin>`). This is Stage 5 of `life-sciences-kam-coordinate`; the coordinator invokes it after the participant role and sprint (Stage 4) exist and the territories (Stage 3) are active.
|
|
4
|
+
|
|
5
|
+
The stage runs in two parts, in order:
|
|
6
|
+
|
|
7
|
+
- **Part A — KAM Data Creation**: the account, provider, address, territory-association, and product master data (from the starter-config CSVs + an explicit HCO account bundle).
|
|
8
|
+
- **Part B — Goals, Tasks, Measures & Action Plan Template**: the goal definitions, goal-product link, and the published, assigned action-plan template.
|
|
9
|
+
|
|
10
|
+
Part B links to the `LifeSciMarketableProduct` created in Part A, so run Part A first and capture its Ids.
|
|
11
|
+
|
|
12
|
+
## Stage Scope
|
|
13
|
+
|
|
14
|
+
- **In scope**: Part A objects (Account, HealthcareProvider, ContactPointAddress, ObjectTerritory2Association, ProviderAcctTerritoryInfo, Product2, LifeSciMarketableProduct, ProductTerritoryAvailability — **plus an HCO account bundle**) and Part B records (2 `GoalDefinition`, 1 `GoalDefinitionProduct`, 1 `ActionPlanTemplate` + auto `ActionPlanTemplateVersion`, 3 `ActionPlanTemplateItem`, 6 `ActionPlanTemplateItemValue`, publishing the version → Final, 1 `ActionPlanTemplateAssignment`, and the leaf-territory shares — 2 `GoalDefinitionShare` + 1 `ActionPlanTemplateShare` + 2 `ProviderAcctTerritoryInfoShare`)
|
|
15
|
+
- **Out of scope**: the Visit chain (not created in the KAM workflow), user provisioning + mobile metadata cache (Stage 6)
|
|
16
|
+
|
|
17
|
+
## Everything runs as the ADMIN
|
|
18
|
+
|
|
19
|
+
Unlike the field-sales-rep workflow, the KAM workflow creates **all** data as the **admin** (`--target-org <admin>`). The end user is not provisioned until Stage 6, so there is no rep to log in as and no rep/admin split. There is also **no manual iPad validation step** here — mobile metadata generation belongs to Stage 6.
|
|
20
|
+
|
|
21
|
+
## Required Inputs
|
|
22
|
+
|
|
23
|
+
- **Target org / admin**: the admin alias or username
|
|
24
|
+
- **Stage-3 level-3 territory Id**: captured by the coordinator in `OrchestrationState.territoryId` — used for `ObjectTerritory2Association`, `ProviderAcctTerritoryInfo`, and `ProductTerritoryAvailability`. This MUST be the same territory later assigned to the KAM user in Stage 6.
|
|
25
|
+
|
|
26
|
+
## Source folder
|
|
27
|
+
|
|
28
|
+
All Part A CSVs come from `.lsc-starter-config/LSStarterConfig/Data/`. This stage is a pure consumer of the shared folder — it MUST NOT download or delete it (the coordinator owns the single download and delete). If the folder is absent, stop and report it must be provisioned by the coordinator.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
# Part A — KAM Data Creation
|
|
33
|
+
|
|
34
|
+
## Workflow
|
|
35
|
+
|
|
36
|
+
1. **Read the live CSV for each object** — never hardcode values from the reference table. Full field-by-field mapping: `references/stage-5-data-creation-data.md`.
|
|
37
|
+
2. **Create the records in dependency order**, capturing each returned Id for downstream foreign keys:
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
HCP Account → HealthcareProvider → ContactPointAddress
|
|
41
|
+
→ ObjectTerritory2Association → ProviderAcctTerritoryInfo
|
|
42
|
+
HCO Account (Partners Healthcare) → HealthcareProvider → ContactPointAddress
|
|
43
|
+
→ ObjectTerritory2Association → ProviderAcctTerritoryInfo
|
|
44
|
+
Product2 → LifeSciMarketableProduct → ProductTerritoryAvailability
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
> The **HCO account bundle** (`Partners Healthcare` Account, its HealthcareProvider, ContactPointAddress, ObjectTerritory2Association, and ProviderAcctTerritoryInfo) uses explicit values, not the CSVs — both the Account and the HealthcareProvider use the `Health_Care_Organization` record type (query the RecordType Id by `DeveloperName`+`SobjectType` first). The HCO ContactPointAddress reuses the CSV address values with `ParentId` = the HCO Account, and the HCO OT2A/PATI reuse the CSV field values against the HCO Account and the **same Stage-3 level-3 territory**. See `references/stage-5-data-creation-data.md`.
|
|
48
|
+
|
|
49
|
+
Use `sf data create record --sobject <Object> --target-org <admin> --values "..." --json` for each, or a small tree/import if you prefer. Substitute the captured FK Ids and the Stage-3 `territoryId` where the reference marks a foreign key.
|
|
50
|
+
3. **Capture the `LifeSciMarketableProduct` Id and the `Account` Id** in `OrchestrationState` — Part B links `GoalDefinitionProduct.ProductId` to the LifeSciMarketableProduct.
|
|
51
|
+
|
|
52
|
+
## Part A Verification Gate
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
sf data query --query "SELECT Id FROM Account ORDER BY CreatedDate DESC LIMIT 1" --target-org <admin> --json
|
|
56
|
+
sf data query --query "SELECT Id FROM LifeSciMarketableProduct ORDER BY CreatedDate DESC LIMIT 1" --target-org <admin> --json
|
|
57
|
+
sf data query --query "SELECT Id, ProductId, TerritoryId FROM ProductTerritoryAvailability ORDER BY CreatedDate DESC LIMIT 1" --target-org <admin> --json
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
All three must return a record, and the `ProductTerritoryAvailability.TerritoryId` must equal the Stage-3 `territoryId`.
|
|
61
|
+
|
|
62
|
+
## Part A Rules / Constraints
|
|
63
|
+
|
|
64
|
+
| Constraint | Rationale |
|
|
65
|
+
|-----------|-----------|
|
|
66
|
+
| Create everything as the admin | No end user exists until Stage 6 |
|
|
67
|
+
| Do NOT create the Visit chain | KAM workflow has no visit data |
|
|
68
|
+
| Read the live CSV; never hardcode | CSV values may change between runs |
|
|
69
|
+
| Use the Stage-3 level-3 territory for all three territory FKs | The KAM user (Stage 6) is assigned this same territory; a mismatch hides all data |
|
|
70
|
+
| Do NOT download or delete `.lsc-starter-config/` | Owned by the coordinator |
|
|
71
|
+
|
|
72
|
+
## Part A Gotchas
|
|
73
|
+
|
|
74
|
+
| Issue | Resolution |
|
|
75
|
+
|-------|------------|
|
|
76
|
+
| `ProductTerritoryAvailability` created against the wrong territory | Re-create with `TerritoryId` = the Stage-3 `territoryId` (the one Stage 6 assigns to the user) |
|
|
77
|
+
| Product2 create fails on `RecordTypeId` | Do NOT set `RecordTypeId` on Product2 — it takes no record type |
|
|
78
|
+
| A create fails on an FLS-gated field | As admin this is rare; omit the offending non-required field and continue (see the per-object notes in the data reference) |
|
|
79
|
+
| `INVALID_CROSS_REFERENCE_KEY` on an FK | The parent record Id wasn't captured — re-query the parent and retry |
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
# Part B — Goals, Tasks, Measures & Action Plan Template
|
|
84
|
+
|
|
85
|
+
Creates the goal definitions, the goal-product link, and the action-plan template (with its items) that back the KAM account plan, then publishes it (by setting its version to `Final`) and assigns it. Run entirely as the **admin** (`--target-org <admin>`), immediately after Part A — Part B links to the Part A `LifeSciMarketableProduct`.
|
|
86
|
+
|
|
87
|
+
Only the record **names** are confirmed with the admin. All other fields are auto-derived from this reference and shown for confirmation.
|
|
88
|
+
|
|
89
|
+
## Step 1 — Two GoalDefinition records
|
|
90
|
+
|
|
91
|
+
Both are active. On `GoalDefinition` the active flag is **`Status`** (values `Active`/`Inactive`) — **not** `IsActive` (that field does not exist on this object). Set `Status=Active`. The goal-type field distinguishes them (`Strategic` vs `Individual`).
|
|
92
|
+
|
|
93
|
+
| # | Name | Goal type | Status | Confirmed? |
|
|
94
|
+
|---|------|-----------|--------|-----------|
|
|
95
|
+
| 1 | `Immunexis: Secure Q3 Formulary Position` | Strategic | Active | Name only |
|
|
96
|
+
| 2 | `Immunexis: Prepare Pharmacy & Therapeutics (P&T) Strategy` | Individual | Active | Name only |
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
sf data create record --sobject GoalDefinition --target-org <admin> \
|
|
100
|
+
--values "Name='Immunexis: Secure Q3 Formulary Position' Type=Strategic Status=Active" --json
|
|
101
|
+
sf data create record --sobject GoalDefinition --target-org <admin> \
|
|
102
|
+
--values "Name='Immunexis: Prepare Pharmacy & Therapeutics (P&T) Strategy' Type=Individual Status=Active" --json
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
> The goal-type field is the picklist that carries `Strategic`/`Individual`. If `Type` is rejected, describe the object (`sf sobject describe --sobject GoalDefinition`) and use the actual field name (e.g. `GoalType`); the values `Strategic`/`Individual` are unchanged. Capture **both** Ids — the **Strategic** goal (#1) is referenced by both `GoalDefinitionProduct` and `ActionPlanTemplateAssignment`.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Step 2 — GoalDefinitionProduct
|
|
110
|
+
|
|
111
|
+
Links the **Strategic** goal to the Part A product.
|
|
112
|
+
|
|
113
|
+
| Field | Value |
|
|
114
|
+
|-------|-------|
|
|
115
|
+
| `GoalDefinitionId` | Id of goal #1 (`Immunexis: Secure Q3 Formulary Position`) |
|
|
116
|
+
| `ProductId` | the Part A `LifeSciMarketableProduct` Id (Immunexis 5mg) — from `OrchestrationState` |
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
sf data create record --sobject GoalDefinitionProduct --target-org <admin> \
|
|
120
|
+
--values "GoalDefinitionId=<strategicGoalId> ProductId=<lifeSciMarketableProductId>" --json
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
> `ProductId` is the **LifeSciMarketableProduct** Id from Part A, not the Product2 Id.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Step 3 — ActionPlanTemplate
|
|
128
|
+
|
|
129
|
+
| Field | Value | Confirmed? |
|
|
130
|
+
|-------|-------|-----------|
|
|
131
|
+
| `Name` | `Immunexis: Formulary Submission & Review Prep` | Name only |
|
|
132
|
+
| `ActionPlanType` | `KAM` | Auto |
|
|
133
|
+
| `TargetEntityType` | `AccountPlanObjective` | Auto |
|
|
134
|
+
| `IsAdHocItemCreationEnabled` | `true` | Auto |
|
|
135
|
+
|
|
136
|
+
> **Do NOT set `Status` on create** — `ActionPlanTemplate.Status` is **read-only** (not writable on create or update). It defaults to `Draft`, and it is later driven to `Final` by publishing the version (Step 5), which propagates back to the template. Including `Status=Draft` here is rejected.
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
sf data create record --sobject ActionPlanTemplate --target-org <admin> \
|
|
140
|
+
--values "Name='Immunexis: Formulary Submission & Review Prep' ActionPlanType=KAM TargetEntityType=AccountPlanObjective IsAdHocItemCreationEnabled=true" --json
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Creating the template **auto-creates** an `ActionPlanTemplateVersion` (draft) — no `Status` flag is needed to trigger it. Query for it — the template items and the publish step operate on the version:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
sf data query --query "SELECT Id, ActionPlanTemplateId, Version, Status FROM ActionPlanTemplateVersion WHERE ActionPlanTemplateId = '<templateId>' ORDER BY CreatedDate DESC LIMIT 1" --target-org <admin> --json
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Capture the version Id.
|
|
150
|
+
|
|
151
|
+
> The version fields are **`Version`** (int) and **`Status`** (picklist) — the same `Status` the publish step (Step 5) updates to `Final`. Do **not** use `VersionNumber`/`VersionStatus`; those columns do not exist and the query silently returns null for them. If a query is rejected, `sf sobject describe --sobject ActionPlanTemplateVersion` and use the reported names.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Step 4 — Three ActionPlanTemplateItem records
|
|
156
|
+
|
|
157
|
+
All three: `ItemEntityType=AssessmentTask`, `IsActive=true`, linked to the template version.
|
|
158
|
+
|
|
159
|
+
| # | Name / Subject |
|
|
160
|
+
|---|----------------|
|
|
161
|
+
| 1 | `Identify key P&T committee members and influencers` |
|
|
162
|
+
| 2 | `Gather HEOR data supporting our value proposition` |
|
|
163
|
+
| 3 | `Compile the competitive landscape and formulary access gaps` |
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
sf data create record --sobject ActionPlanTemplateItem --target-org <admin> \
|
|
167
|
+
--values "ActionPlanTemplateVersionId=<versionId> Name='Identify key P&T committee members and influencers' ItemEntityType=AssessmentTask IsActive=true" --json
|
|
168
|
+
# …repeat for items 2 and 3
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**Capture each item's Id** — the `ActionPlanTemplateItemValue` records below reference it (`<item1Id>`, `<item2Id>`, `<item3Id>`).
|
|
172
|
+
|
|
173
|
+
> The item-name field may be `Name` or `Subject` depending on the org — describe `ActionPlanTemplateItem` if `Name` is rejected and use the reported field; the three strings are unchanged. The link field to the version may be `ActionPlanTemplateVersionId` (confirm via describe).
|
|
174
|
+
|
|
175
|
+
### Step 4b — Two ActionPlanTemplateItemValue per item
|
|
176
|
+
|
|
177
|
+
For **each** `ActionPlanTemplateItem`, create **two** `ActionPlanTemplateItemValue` records — one for the task **Name**, one for the task **Category**. All six share `IsActive=true` and are linked to their item via `ActionPlanTemplateItemId`. Do **not** set `ItemEntityType` on `ActionPlanTemplateItemValue` — it is read-only (derived from the parent item) and setting it fails with "Unable to create/update fields: ItemEntityType". The `Category` values (`Survey`/`Claim`) come from the `AssessmentTaskCategory` StandardValueSet confirmed in Stage 2.
|
|
178
|
+
|
|
179
|
+
| Item | `ActionPlanTemplateItemId` | `ItemEntityFieldName` | `Name` | `ValueLiteral` |
|
|
180
|
+
|------|---------------------------|-----------------------|--------|----------------|
|
|
181
|
+
| 1 — Identify key P&T committee members and influencers | `<item1Id>` | `AssessmentTask.Name` | `Name` | `Identify key P&T committee members and influencers` |
|
|
182
|
+
| 1 — Identify key P&T committee members and influencers | `<item1Id>` | `AssessmentTask.Category` | `Category` | `Survey` |
|
|
183
|
+
| 2 — Gather HEOR data supporting our value proposition | `<item2Id>` | `AssessmentTask.Name` | `Name` | `Gather HEOR data supporting our value proposition` |
|
|
184
|
+
| 2 — Gather HEOR data supporting our value proposition | `<item2Id>` | `AssessmentTask.Category` | `Category` | `Claim` |
|
|
185
|
+
| 3 — Compile the competitive landscape and formulary access gaps | `<item3Id>` | `AssessmentTask.Name` | `Name` | `Compile the competitive landscape and formulary access gaps` |
|
|
186
|
+
| 3 — Compile the competitive landscape and formulary access gaps | `<item3Id>` | `AssessmentTask.Category` | `Category` | `Survey` |
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# Item 1 — <item1Id>
|
|
190
|
+
sf data create record --sobject ActionPlanTemplateItemValue --target-org <admin> \
|
|
191
|
+
--values "ActionPlanTemplateItemId=<item1Id> ItemEntityFieldName=AssessmentTask.Name Name=Name ValueLiteral='Identify key P&T committee members and influencers' IsActive=true" --json
|
|
192
|
+
sf data create record --sobject ActionPlanTemplateItemValue --target-org <admin> \
|
|
193
|
+
--values "ActionPlanTemplateItemId=<item1Id> ItemEntityFieldName=AssessmentTask.Category Name=Category ValueLiteral='Survey' IsActive=true" --json
|
|
194
|
+
|
|
195
|
+
# Item 2 — <item2Id>
|
|
196
|
+
sf data create record --sobject ActionPlanTemplateItemValue --target-org <admin> \
|
|
197
|
+
--values "ActionPlanTemplateItemId=<item2Id> ItemEntityFieldName=AssessmentTask.Name Name=Name ValueLiteral='Gather HEOR data supporting our value proposition' IsActive=true" --json
|
|
198
|
+
sf data create record --sobject ActionPlanTemplateItemValue --target-org <admin> \
|
|
199
|
+
--values "ActionPlanTemplateItemId=<item2Id> ItemEntityFieldName=AssessmentTask.Category Name=Category ValueLiteral='Claim' IsActive=true" --json
|
|
200
|
+
|
|
201
|
+
# Item 3 — <item3Id>
|
|
202
|
+
sf data create record --sobject ActionPlanTemplateItemValue --target-org <admin> \
|
|
203
|
+
--values "ActionPlanTemplateItemId=<item3Id> ItemEntityFieldName=AssessmentTask.Name Name=Name ValueLiteral='Compile the competitive landscape and formulary access gaps' IsActive=true" --json
|
|
204
|
+
sf data create record --sobject ActionPlanTemplateItemValue --target-org <admin> \
|
|
205
|
+
--values "ActionPlanTemplateItemId=<item3Id> ItemEntityFieldName=AssessmentTask.Category Name=Category ValueLiteral='Survey' IsActive=true" --json
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
> Wrap each `ValueLiteral` in single quotes so the shell preserves spaces. Create all six values **before** publishing (Step 5) — a published template is immutable.
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Step 5 — Publish via the version (→ Final)
|
|
213
|
+
|
|
214
|
+
**Publishing is driven through the version, not the template.** `ActionPlanTemplate.Status` is read-only and cannot be updated directly; `ActionPlanTemplateVersion.Status` **is** updateable, and setting it to `Final` propagates the published state back to the parent template. Do this only after all three items and their six item values exist — a published version is immutable. Update the `ActionPlanTemplateVersion` record using the `<versionId>` captured in Step 3, **not** the `<templateId>`:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
sf data update record --sobject ActionPlanTemplateVersion --record-id <versionId> \
|
|
218
|
+
--values "Status=Final" --target-org <admin> --json
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
> Do **not** attempt `sf data update record --sobject ActionPlanTemplate ... Status=Final` — the template's `Status` is read-only and the update is rejected. The version is the only writable path.
|
|
222
|
+
|
|
223
|
+
Verify — the version reads `Final`, and the template's `Status` has propagated to `Final`:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
sf data query --query "SELECT Id, Status FROM ActionPlanTemplateVersion WHERE Id = '<versionId>'" --target-org <admin> --json
|
|
227
|
+
sf data query --query "SELECT Id, Status FROM ActionPlanTemplate WHERE Id = '<templateId>'" --target-org <admin> --json
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Both must return `Status='Final'`.
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Step 6 — ActionPlanTemplateAssignment
|
|
235
|
+
|
|
236
|
+
Assigns the published version to the **Strategic** goal. `ActionPlanTemplateAssignment` has **no `ActionPlanTemplateId` field** — it links to the template **through the version** via `ActionPlanTemplateVersionId` (required).
|
|
237
|
+
|
|
238
|
+
| Field | Value |
|
|
239
|
+
|-------|-------|
|
|
240
|
+
| `AssociatedObjectId` | Id of goal #1 (`Immunexis: Secure Q3 Formulary Position`) — the Strategic `GoalDefinition` |
|
|
241
|
+
| `ActionPlanTemplateVersionId` | the `<versionId>` captured in Step 3 (required) |
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
sf data create record --sobject ActionPlanTemplateAssignment --target-org <admin> \
|
|
245
|
+
--values "AssociatedObjectId=<strategicGoalId> ActionPlanTemplateVersionId=<versionId>" --json
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
> `AssociatedObjectId` points at the **Strategic** GoalDefinition; `ActionPlanTemplateVersionId` is the published version from Step 3. There is no `ActionPlanTemplateId` field on this object — `No such column 'ActionPlanTemplateId'` means you passed the template Id; use the version Id instead.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Step 7 — Share GoalDefinition, ActionPlanTemplate & ProviderAcctTerritoryInfo to the leaf territory
|
|
253
|
+
|
|
254
|
+
The two `GoalDefinition` records, the `ActionPlanTemplate`, and the two `ProviderAcctTerritoryInfo` records (HCP + HCO, from Part A) are owned by the **admin**. For the KAM user — assigned to the Stage-3 level-3 (leaf) territory in Stage 6 — to see them, grant the **territory** access via manual share records: one `GoalDefinitionShare` per goal, one `ActionPlanTemplateShare` for the template, and one `ProviderAcctTerritoryInfoShare` per PATI record.
|
|
255
|
+
|
|
256
|
+
Sharing to a territory means sharing to the territory's **Group**, not to the `Territory2` record. First resolve the group for the Stage-3 `territoryId`:
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
sf data query --query "SELECT Id, Type, RelatedId FROM Group WHERE RelatedId = '<territoryId>' AND Type IN ('Territory','TerritoryAndSubordinates')" --target-org <admin> --json
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Two groups come back — `Territory` (users of exactly this territory) and `TerritoryAndSubordinates`. For a leaf territory they resolve to the same users; use the **`Territory`** group Id (`<territoryGroupId>`).
|
|
263
|
+
|
|
264
|
+
Then create the share records — `AccessLevel=Edit`, `RowCause=Manual`:
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
# GoalDefinitionShare — one per GoalDefinition (Strategic + Individual)
|
|
268
|
+
sf data create record --sobject GoalDefinitionShare --target-org <admin> \
|
|
269
|
+
--values "ParentId=<strategicGoalId> UserOrGroupId=<territoryGroupId> AccessLevel=Edit RowCause=Manual" --json
|
|
270
|
+
sf data create record --sobject GoalDefinitionShare --target-org <admin> \
|
|
271
|
+
--values "ParentId=<individualGoalId> UserOrGroupId=<territoryGroupId> AccessLevel=Edit RowCause=Manual" --json
|
|
272
|
+
|
|
273
|
+
# ActionPlanTemplateShare — the template
|
|
274
|
+
sf data create record --sobject ActionPlanTemplateShare --target-org <admin> \
|
|
275
|
+
--values "ParentId=<templateId> UserOrGroupId=<territoryGroupId> AccessLevel=Edit RowCause=Manual" --json
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Then share the `ProviderAcctTerritoryInfo` records. Both PATI records (HCP + HCO) were created in Part A against the Stage-3 `<territoryId>`; query them and create one `ProviderAcctTerritoryInfoShare` per record:
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
# Fetch both PATI records for the Stage-3 territory (HCP + HCO)
|
|
282
|
+
sf data query --query "SELECT Id FROM ProviderAcctTerritoryInfo WHERE Territory2Id = '<territoryId>'" --target-org <admin> --json
|
|
283
|
+
|
|
284
|
+
# ProviderAcctTerritoryInfoShare — one per PATI Id returned above
|
|
285
|
+
sf data create record --sobject ProviderAcctTerritoryInfoShare --target-org <admin> \
|
|
286
|
+
--values "ParentId=<patiId> UserOrGroupId=<territoryGroupId> AccessLevel=Edit RowCause=Manual" --json
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
> The parent lookup on `GoalDefinitionShare`, `ActionPlanTemplateShare`, and `ProviderAcctTerritoryInfoShare` is **`ParentId`** (confirmed) — the record being shared. `AccessLevel` accepts `Read` or `Edit` for a manual share (`All` is reserved for the record owner). Share to the **Group** Id, never the `Territory2` Id directly — a `Territory2` Id in `UserOrGroupId` fails with `INVALID_CROSS_REFERENCE_KEY`. If the share fails with `insufficient access` on `RowCause`, drop `RowCause` (it defaults to `Manual`).
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## Part B Verification Gate
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
sf data query --query "SELECT Id, Status FROM ActionPlanTemplateVersion WHERE Status = 'Final' ORDER BY CreatedDate DESC LIMIT 1" --target-org <admin> --json
|
|
297
|
+
sf data query --query "SELECT Id, AssociatedObjectId, ActionPlanTemplateVersionId FROM ActionPlanTemplateAssignment ORDER BY CreatedDate DESC LIMIT 1" --target-org <admin> --json
|
|
298
|
+
sf data query --query "SELECT Id, ParentId, UserOrGroupId FROM GoalDefinitionShare WHERE RowCause = 'Manual' ORDER BY CreatedDate DESC LIMIT 2" --target-org <admin> --json
|
|
299
|
+
sf data query --query "SELECT Id, ParentId, UserOrGroupId FROM ActionPlanTemplateShare WHERE ParentId = '<templateId>' AND RowCause = 'Manual'" --target-org <admin> --json
|
|
300
|
+
sf data query --query "SELECT Id, ParentId, UserOrGroupId FROM ProviderAcctTerritoryInfoShare WHERE RowCause = 'Manual' ORDER BY LastModifiedDate DESC LIMIT 2" --target-org <admin> --json
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Expect a version with `Status='Final'` (the parent template's `Status` propagates to `Final`), an assignment whose `AssociatedObjectId` is the Strategic goal and whose `ActionPlanTemplateVersionId` is that published version, and the five share records (2 `GoalDefinitionShare` + 1 `ActionPlanTemplateShare` + 2 `ProviderAcctTerritoryInfoShare`) whose `UserOrGroupId` equals the leaf-territory `<territoryGroupId>`.
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Part B Rules / Constraints
|
|
308
|
+
|
|
309
|
+
| Constraint | Rationale |
|
|
310
|
+
|-----------|-----------|
|
|
311
|
+
| Run everything as admin | Setup-level configuration |
|
|
312
|
+
| Confirm only the record names; auto-derive the rest | Per spec, names are the only user-supplied values |
|
|
313
|
+
| Create all 3 items AND their 6 item values BEFORE publishing | A published (`Status=Final`) version is immutable — items/values can't be added after |
|
|
314
|
+
| Publish by updating the **version** to `Status=Final`, never the template | `ActionPlanTemplate.Status` is read-only; the version's `Status` is the only writable path and propagates to the template |
|
|
315
|
+
| `GoalDefinitionProduct.ProductId` = Part A LifeSciMarketableProduct | Not the Product2 Id |
|
|
316
|
+
| `GoalDefinitionProduct` + `ActionPlanTemplateAssignment` reference the **Strategic** goal | Per spec |
|
|
317
|
+
| Share both `GoalDefinition` records + the `ActionPlanTemplate` + both `ProviderAcctTerritoryInfo` records to the leaf-territory **Group** | Admin owns the records; the KAM user reaches them only through the territory share |
|
|
318
|
+
|
|
319
|
+
## Part B Gotchas
|
|
320
|
+
|
|
321
|
+
| Issue | Resolution |
|
|
322
|
+
|-------|------------|
|
|
323
|
+
| Field name rejected (`Type`, `Name`, version-link) | Describe the sObject and use the reported API name; the values/strings are unchanged |
|
|
324
|
+
| Can't add items after publish | Publish is one-way — create a new version/template if items were missed |
|
|
325
|
+
| `ActionPlanTemplate` create/update rejects `Status` | `Status` is read-only on this object — omit it on create (defaults to `Draft`); publish by updating the **version** to `Final`, which propagates to the template |
|
|
326
|
+
| `No such column 'ActionPlanTemplateId' on ... ActionPlanTemplateAssignment` | This object has no `ActionPlanTemplateId` field — link via `ActionPlanTemplateVersionId=<versionId>` (the published version), not the template Id |
|
|
327
|
+
| `GoalDefinitionProduct` create fails on ProductId | Use the LifeSciMarketableProduct Id from Part A, not Product2 |
|
|
328
|
+
| `GoalDefinition` create fails on `IsActive` (`No such column`) | `GoalDefinition` has no `IsActive` field — its active flag is `Status` (`Active`/`Inactive`). Use `Status=Active` |
|
|
329
|
+
| `Share` create fails with `INVALID_CROSS_REFERENCE_KEY` on `UserOrGroupId` | You passed the `Territory2` Id — pass the territory **Group** Id from the `Group WHERE RelatedId=<territoryId>` query instead |
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## Reference File Index
|
|
334
|
+
|
|
335
|
+
| File | When to read |
|
|
336
|
+
|------|-------------|
|
|
337
|
+
| `references/stage-5-data-creation-data.md` | Part A — object→CSV mapping, per-object field values, dependency chain |
|