@salesforce/afv-skills 1.63.0 → 1.65.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-gpt-email-generation-configure/SKILL.md +312 -0
- package/skills/agentforce-offline-experimentation-run/SKILL.md +253 -0
- package/skills/agentforce-offline-experimentation-run/scripts/build_report.py +796 -0
- package/skills/agentforce-offline-experimentation-run/scripts/resolve-token.sh +111 -0
- package/skills/agentforce-offline-experimentation-run/scripts/sfap_replay.py +1053 -0
- package/skills/agentforce-wizard-ui-forecasting-analytics-components-configure/SKILL.md +64 -0
- package/skills/agentforce-wizard-ui-sales-einstein-components-configure/SKILL.md +46 -0
- package/skills/automation-company-profile-info-query/SKILL.md +51 -0
- package/skills/automation-digital-wallet-configure/SKILL.md +689 -0
- package/skills/automation-flow-coordinate/SKILL.md +95 -0
- package/skills/automation-flow-coordinate/references/elements/action-call/action-call.md +1569 -0
- package/skills/automation-flow-coordinate/references/elements/action-call/conversation-messaging.md +96 -0
- package/skills/automation-flow-coordinate/references/elements/action-call/examples/send-sms-message.json +23 -0
- package/skills/automation-flow-coordinate/references/elements/action-call/examples/send-to-journey-no-fields.json +31 -0
- package/skills/automation-flow-coordinate/references/elements/action-call/send-to-journey.md +179 -0
- package/skills/automation-flow-coordinate/references/elements/exit-rule/examples/event-email-link-click.json +13 -0
- package/skills/automation-flow-coordinate/references/elements/exit-rule/exit-rule.md +83 -0
- package/skills/automation-flow-coordinate/references/elements/forward-to-bot-or-agent/examples/forward-to-bot-or-agent.json +69 -0
- package/skills/automation-flow-coordinate/references/elements/forward-to-bot-or-agent/forward-to-bot-or-agent.md +274 -0
- package/skills/automation-flow-coordinate/references/elements/start/audience-common.md +192 -0
- package/skills/automation-flow-coordinate/references/elements/start/automation-event-triggered.md +130 -0
- package/skills/automation-flow-coordinate/references/elements/start/data-cloud-data-change-triggered.md +92 -0
- package/skills/automation-flow-coordinate/references/elements/start/form-submission-triggered.md +88 -0
- package/skills/automation-flow-coordinate/references/elements/start/segment-triggered.md +152 -0
- package/skills/automation-flow-coordinate/references/elements/start/start.md +539 -0
- package/skills/automation-flow-coordinate/references/elements/subflow/subflow.md +152 -0
- package/skills/automation-flow-coordinate/references/elements/wait/wait.md +497 -0
- package/skills/automation-flow-coordinate/references/recipes/author/author.md +868 -0
- package/skills/automation-flow-coordinate/references/recipes/summarize/element-generic.md +300 -0
- package/skills/automation-flow-coordinate/references/recipes/summarize/reference-resolution.md +292 -0
- package/skills/automation-flow-coordinate/references/recipes/summarize/summarize.md +323 -0
- package/skills/automation-flow-coordinate/references/recipes/testing/examples/debug-output-template.md +109 -0
- package/skills/automation-flow-coordinate/references/recipes/testing/shape.md +219 -0
- package/skills/automation-flow-coordinate/references/recipes/testing/shared-stages/intent-analyzer.md +180 -0
- package/skills/automation-flow-coordinate/references/recipes/testing/workflows/debug.md +175 -0
- package/skills/automation-flow-coordinate/references/recipes/testing/workflows/promote.md +255 -0
- package/skills/automation-flow-coordinate/references/recipes/testing/workflows/save-debug.md +212 -0
- package/skills/automation-flow-coordinate/references/resources/variable/variable.md +171 -0
- package/skills/automation-flow-coordinate/references/shared/anti-patterns.md +786 -0
- package/skills/automation-flow-coordinate/references/shared/end/end.md +267 -0
- package/skills/automation-flow-coordinate/references/shared/flow-type-resolver/eval/README.md +69 -0
- package/skills/automation-flow-coordinate/references/shared/flow-type-resolver/eval/predictions.jsonl +80 -0
- package/skills/automation-flow-coordinate/references/shared/flow-type-resolver/eval/prompts.jsonl +116 -0
- package/skills/automation-flow-coordinate/references/shared/flow-type-resolver/flow-type-resolver.md +321 -0
- package/skills/automation-flow-coordinate/references/shared/flow-type-resolver/taxonomy.json +320 -0
- package/skills/automation-flow-coordinate/references/shared/server-functions.md +597 -0
- package/skills/automation-sandbox-post-copy-config-generate/SKILL.md +21 -11
- package/skills/automation-sandbox-post-copy-config-generate/assets/config_template.json +10 -0
- package/skills/automation-sandbox-post-copy-config-generate/assets/json_schema.json +33 -1
- package/skills/automation-sandbox-post-copy-config-generate/references/configuration_catalog.md +44 -1
- package/skills/automation-sandbox-post-copy-configure/SKILL.md +132 -124
- package/skills/automation-sandbox-post-copy-configure/references/flow_activation_path.md +151 -0
- package/skills/automation-sandbox-post-copy-configure/references/scheduled_apex_path.md +55 -9
- package/skills/automotive-cloud-appraisal-management-settings-configure/SKILL.md +69 -0
- package/skills/automotive-cloud-dealer-essentials-configure/SKILL.md +78 -0
- package/skills/automotive-cloud-ground-agent-data-pipelines-configure/SKILL.md +373 -0
- package/skills/automotive-cloud-ground-mfg-agent-data-pipelines-configure/SKILL.md +273 -0
- package/skills/automotive-cloud-mfg-agent-data-pipelines-configure/SKILL.md +259 -0
- package/skills/automotive-cloud-mfg-sales-concierge-agent-create/SKILL.md +369 -0
- package/skills/automotive-cloud-mfg-sales-concierge-foundation-configure/SKILL.md +542 -0
- package/skills/automotive-cloud-mfg-sales-concierge-foundation-coordinate/SKILL.md +159 -0
- package/skills/automotive-cloud-mfg-sales-concierge-orchestrator-agent-create/SKILL.md +349 -0
- package/skills/automotive-cloud-mfg-sales-concierge-orchestrator-configure/SKILL.md +505 -0
- package/skills/automotive-cloud-sales-concierge-agent-create/SKILL.md +380 -0
- package/skills/automotive-cloud-sales-concierge-foundation-configure/SKILL.md +567 -0
- package/skills/automotive-cloud-sales-concierge-foundation-coordinate/SKILL.md +159 -0
- package/skills/automotive-cloud-sales-concierge-orchestrator-agent-create/SKILL.md +360 -0
- package/skills/automotive-cloud-sales-concierge-orchestrator-configure/SKILL.md +539 -0
- package/skills/automotive-cloud-sales-concierge-search-grounding-configure/SKILL.md +358 -0
- package/skills/commerce-b2b-merchant-quote-configure/SKILL.md +602 -0
- package/skills/commerce-b2b-store-configure/SKILL.md +251 -0
- package/skills/commerce-credit-memo-create/SKILL.md +139 -0
- package/skills/commerce-delivery-business-hours-configure/SKILL.md +277 -0
- package/skills/commerce-delivery-estimation-apply/SKILL.md +155 -0
- package/skills/commerce-delivery-estimation-configure/SKILL.md +377 -0
- package/skills/commerce-delivery-routing-specs-integrate/SKILL.md +174 -0
- package/skills/commerce-estimate-bopis-query/SKILL.md +279 -0
- package/skills/commerce-estimate-delivery-date-query/SKILL.md +349 -0
- package/skills/commerce-fees-apply/SKILL.md +227 -0
- package/skills/commerce-fulfillment-routing-analyze/SKILL.md +200 -0
- package/skills/commerce-guest-buyer-create/SKILL.md +173 -0
- package/skills/commerce-location-bopis-configure/SKILL.md +378 -0
- package/skills/commerce-location-business-hours-configure/SKILL.md +235 -0
- package/skills/commerce-location-delivery-processing-time-configure/SKILL.md +309 -0
- package/skills/commerce-location-graph-integrate/SKILL.md +131 -0
- package/skills/commerce-location-shipping-carrier-method-configure/SKILL.md +755 -0
- package/skills/commerce-location-temporary-operating-hours-configure/SKILL.md +331 -0
- package/skills/commerce-merchant-buyer-groups-configure/SKILL.md +579 -0
- package/skills/commerce-merchant-buyer-user-onboarding-create/SKILL.md +626 -0
- package/skills/commerce-merchant-catalog-configure/SKILL.md +614 -0
- package/skills/commerce-merchant-extension-provider-configure/SKILL.md +368 -0
- package/skills/commerce-merchant-insights-account-health-churn-analyze/SKILL.md +118 -0
- package/skills/commerce-merchant-insights-inventory-returns-analyze/SKILL.md +65 -0
- package/skills/commerce-merchant-insights-order-shopper-get/SKILL.md +90 -0
- package/skills/commerce-merchant-insights-product-performance-analyze/SKILL.md +72 -0
- package/skills/commerce-merchant-insights-query/SKILL.md +279 -0
- package/skills/commerce-merchant-storefront-guest-access-configure/SKILL.md +656 -0
- package/skills/commerce-order-summary-change-apply/SKILL.md +375 -0
- package/skills/commerce-product-details-get/SKILL.md +363 -0
- package/skills/commerce-product-search/SKILL.md +563 -0
- package/skills/commerce-react-storefront-create/SKILL.md +350 -0
- package/skills/commerce-return-order-summary-create/SKILL.md +513 -0
- package/skills/commerce-search-relevance-analyze/SKILL.md +757 -0
- package/skills/commerce-temporary-processing-time-override-create/SKILL.md +274 -0
- package/skills/communications-initial-setup-configure/SKILL.md +630 -0
- package/skills/communications-multisite-configure/SKILL.md +571 -0
- package/skills/communications-revenue-cloud-settings-configure/SKILL.md +74 -0
- package/skills/communications-smb-fiber-catalog-create/SKILL.md +413 -0
- package/skills/communications-tmf-integrate/SKILL.md +1368 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/SKILL.md +54 -107
- package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/copy.json +1 -1
- package/skills/consumer-goods-promotion-bo-api-deploy/references/conventions-and-payload-rules.md +82 -5
- package/skills/consumer-goods-promotion-bo-api-deploy/references/generate-and-wire.md +35 -2
- package/skills/consumer-goods-promotion-bo-api-deploy/references/preflight-and-seed-queries.md +149 -0
- package/skills/consumer-goods-promotion-bo-api-deploy/references/smoke-and-verify.md +17 -1
- package/skills/consumer-goods-visit-activity-act4-questions-assign/SKILL.md +448 -0
- package/skills/consumer-goods-visit-activity-act5-standard-create/SKILL.md +269 -0
- package/skills/consumer-goods-visit-activity-act6-assortment-configure/SKILL.md +271 -0
- package/skills/consumer-goods-visit-activity-act7-account-scoping-create/SKILL.md +382 -0
- package/skills/consumer-goods-visit-activity-act8-plan-attach-create/SKILL.md +373 -0
- package/skills/consumer-goods-visit-activity-act9-proof-validate/SKILL.md +389 -0
- package/skills/consumer-goods-visit-and-activity-act1-specification-create/SKILL.md +338 -0
- package/skills/consumer-goods-visit-and-activity-act2-template-create/SKILL.md +547 -0
- package/skills/consumer-goods-visit-and-activity-act3-definition-create/SKILL.md +346 -0
- package/skills/consumer-goods-visit-and-activity-configure/SKILL.md +1110 -0
- package/skills/crm-analytics-adoption-insights-configure/SKILL.md +224 -0
- package/skills/crm-analytics-custom-report-type-lightning-configure/SKILL.md +418 -0
- package/skills/crm-analytics-dashboards-configure/SKILL.md +731 -0
- package/skills/crm-analytics-operational-analytics-metadata-bridge-migrate/SKILL.md +233 -0
- package/skills/crm-analytics-report-notifications-ui-configure/SKILL.md +184 -0
- package/skills/crm-analytics-sharing-inheritance-coverage-analyze/SKILL.md +167 -0
- package/skills/crm-analytics-sonic-getting-started-configure/SKILL.md +55 -0
- package/skills/crm-analytics-tableau-next-app-deploy/SKILL.md +1350 -0
- package/skills/crm-analytics-tableau-next-c360-basemodel-validate/SKILL.md +1862 -0
- package/skills/crm-analytics-tableau-next-datacloud-validate/SKILL.md +83 -0
- package/skills/crm-analytics-tableau-next-provisioning-validate/SKILL.md +81 -0
- package/skills/data360-activation-create/SKILL.md +104 -0
- package/skills/data360-activation-external-platform-get/SKILL.md +49 -0
- package/skills/data360-activation-target-create/SKILL.md +93 -0
- package/skills/data360-activation-v2-create/SKILL.md +456 -0
- package/skills/data360-audience-dmo-get/SKILL.md +38 -0
- package/skills/data360-calculated-affinity-create/SKILL.md +82 -0
- package/skills/data360-calculated-insight-create/SKILL.md +148 -0
- package/skills/data360-catalog-metadata-create/SKILL.md +183 -0
- package/skills/data360-code-extension-create/SKILL.md +115 -0
- package/skills/data360-communication-capping-create/SKILL.md +227 -0
- package/skills/data360-connection-create/SKILL.md +491 -0
- package/skills/data360-content-lens-create/SKILL.md +181 -0
- package/skills/data360-data-action-create/SKILL.md +126 -0
- package/skills/data360-data-action-target-create/SKILL.md +181 -0
- package/skills/data360-data-clean-room-create/SKILL.md +238 -0
- package/skills/data360-data-governance-create/SKILL.md +746 -0
- package/skills/data360-data-graph-create/SKILL.md +82 -0
- package/skills/data360-data-harmonized-model-object-reference-create/SKILL.md +38 -0
- package/skills/data360-data-lake-object-create/SKILL.md +207 -0
- package/skills/data360-data-model-object-catalog-get/SKILL.md +49 -0
- package/skills/data360-data-model-object-create/SKILL.md +128 -0
- package/skills/data360-data-model-object-mapping-create/SKILL.md +106 -0
- package/skills/data360-data-space-create/SKILL.md +161 -0
- package/skills/data360-data-streams-create/SKILL.md +324 -0
- package/skills/data360-engagement-signal-get/SKILL.md +38 -0
- package/skills/data360-experiment-create/SKILL.md +82 -0
- package/skills/data360-goal-based-campaign-create/SKILL.md +192 -0
- package/skills/data360-harmonization-process-history-get/SKILL.md +38 -0
- package/skills/data360-harmonized-unstructured-dmo-create/SKILL.md +84 -0
- package/skills/data360-identity-resolution-create/SKILL.md +115 -0
- package/skills/data360-intelligent-document-processing-create/SKILL.md +148 -0
- package/skills/data360-knowledge-graph-construction-create/SKILL.md +93 -0
- package/skills/data360-knowledge-graph-create/SKILL.md +216 -0
- package/skills/data360-knowledge-space-mcp-configure/SKILL.md +475 -0
- package/skills/data360-machine-learning-mcp-configure/SKILL.md +697 -0
- package/skills/data360-multi-org-mcp-configure/SKILL.md +117 -0
- package/skills/data360-secondary-index-mcp-configure/SKILL.md +126 -0
- package/skills/data360-segment-mcp-configure/SKILL.md +159 -0
- package/skills/data360-semantic-calculated-dimension-mcp-configure/SKILL.md +93 -0
- package/skills/data360-semantic-calculated-measurement-mcp-configure/SKILL.md +93 -0
- package/skills/data360-semantic-data-object-mcp-configure/SKILL.md +93 -0
- package/skills/data360-semantic-dimension-mcp-configure/SKILL.md +38 -0
- package/skills/data360-semantic-engine-mcp-configure/SKILL.md +62 -0
- package/skills/data360-semantic-measurement-mcp-configure/SKILL.md +38 -0
- package/skills/data360-semantic-metric-mcp-configure/SKILL.md +93 -0
- package/skills/data360-semantic-model-mcp-configure/SKILL.md +115 -0
- package/skills/data360-standard-mapping-mcp-configure/SKILL.md +38 -0
- package/skills/data360-tenant-lifecycle-mcp-configure/SKILL.md +73 -0
- package/skills/dx-devops-conflict-resolve/SKILL.md +1 -5
- package/skills/dx-devops-pipeline-manage/SKILL.md +1 -5
- package/skills/dx-devops-project-manage/SKILL.md +1 -5
- package/skills/dx-devops-promote/SKILL.md +1 -5
- package/skills/dx-devops-request-status/SKILL.md +1 -5
- package/skills/dx-lifecycle-center/SKILL.md +120 -0
- package/skills/dx-lifecycle-center/examples/workflows.md +175 -0
- package/skills/dx-lifecycle-center/references/connect-api.md +123 -0
- package/skills/dx-lifecycle-center/references/connect-org.md +184 -0
- package/skills/dx-lifecycle-center/references/deploy.md +153 -0
- package/skills/dx-lifecycle-center/references/error-handling.md +21 -0
- package/skills/dx-lifecycle-center/references/hub-org.md +37 -0
- package/skills/dx-lifecycle-center/references/list-orgs.md +99 -0
- package/skills/dx-lifecycle-center/references/request-body.md +75 -0
- package/skills/dx-lifecycle-center/references/troubleshooting.md +31 -0
- package/skills/dx-lifecycle-center/scripts/poll-deploy-status.sh +200 -0
- package/skills/dx-lifecycle-center/scripts/resolve-environment.sh +120 -0
- package/skills/dx-org-devhub-configure/SKILL.md +1 -3
- package/skills/dx-org-shape-manage/SKILL.md +1 -5
- package/skills/dx-org-snapshot-manage/SKILL.md +1 -3
- package/skills/education-cloud-academic-calendar-generate/SKILL.md +1 -3
- package/skills/education-cloud-course-catalog-migrate/SKILL.md +1 -3
- package/skills/education-cloud-domain-configure/SKILL.md +1 -3
- package/skills/education-cloud-multi-campus-configure/SKILL.md +1 -3
- package/skills/education-cloud-student-recruitment-agent-configure/SKILL.md +1 -5
- package/skills/experience-afv-query/SKILL.md +234 -0
- package/skills/experience-agentforce-vibes-in-react-configure/SKILL.md +63 -0
- package/skills/experience-apex-components-configure/SKILL.md +69 -0
- package/skills/experience-apex-pages-configure/SKILL.md +107 -0
- package/skills/experience-app-home-configure/SKILL.md +76 -0
- package/skills/experience-aura-lightning-out-access-configure/SKILL.md +58 -0
- package/skills/experience-briefcase-configure/SKILL.md +287 -0
- package/skills/experience-community-flexi-page-list-create/SKILL.md +74 -0
- package/skills/experience-community-template-definition-list-query/SKILL.md +48 -0
- package/skills/experience-community-theme-definition-list-query/SKILL.md +38 -0
- package/skills/experience-content-assets-configure/SKILL.md +86 -0
- package/skills/experience-custom-domain-create/SKILL.md +727 -0
- package/skills/experience-defer-rendering-workspace-page-setup-configure/SKILL.md +41 -0
- package/skills/experience-field-service-app-builder-configure/SKILL.md +187 -0
- package/skills/experience-flow-category-configure/SKILL.md +117 -0
- package/skills/experience-formula-configure/SKILL.md +358 -0
- package/skills/experience-global-actions-configure/SKILL.md +69 -0
- package/skills/experience-global-publisher-layouts-configure/SKILL.md +79 -0
- package/skills/experience-instrumentation-configure/SKILL.md +64 -0
- package/skills/experience-lex-engagement-configure/SKILL.md +50 -0
- package/skills/experience-lightning-bolt-open/SKILL.md +12 -0
- package/skills/experience-lightning-out-configure/SKILL.md +129 -0
- package/skills/experience-lightning-preview-configure/SKILL.md +67 -0
- package/skills/experience-lightning-types-query/SKILL.md +98 -0
- package/skills/experience-malware-scan-configure/SKILL.md +71 -0
- package/skills/experience-my-salesforce-configure/SKILL.md +126 -0
- package/skills/experience-navigation-menus-configure/SKILL.md +235 -0
- package/skills/experience-notification-types-configure/SKILL.md +206 -0
- package/skills/experience-notifications-configure/SKILL.md +75 -0
- package/skills/experience-record-discovery-query/SKILL.md +227 -0
- package/skills/experience-regenerate-previews-open/SKILL.md +94 -0
- package/skills/experience-sales-cloud-mab-configure/SKILL.md +254 -0
- package/skills/experience-schema-builder-open/SKILL.md +38 -0
- package/skills/experience-simple-record-home-configure/SKILL.md +110 -0
- package/skills/experience-static-resources-configure/SKILL.md +74 -0
- package/skills/experience-ui-bundle-2gp-deploy/SKILL.md +1 -3
- package/skills/experience-ui-bundle-features-generate/SKILL.md +1 -5
- package/skills/experience-ui-bundle-mfa-configure/SKILL.md +1 -3
- package/skills/field-service-data-capture-form-deployer-configure/SKILL.md +23 -2
- package/skills/field-service-data-capture-form-designer-configure/SKILL.md +13 -3
- package/skills/field-service-data-capture-migrate/SKILL.md +1 -3
- package/skills/field-service-mobile-branding-configure/SKILL.md +17 -3
- package/skills/field-service-objective-designer-configure/SKILL.md +72 -379
- package/skills/field-service-prework-brief-deployer-configure/SKILL.md +10 -537
- package/skills/field-service-scheduling-policy-designer-query/SKILL.md +65 -1093
- package/skills/{field-service-setup-orchestrator-get → field-service-setup-coordinate}/SKILL.md +18 -3
- package/skills/field-service-sobject-create-configure/SKILL.md +13 -213
- package/skills/field-service-voice-to-form-configure/SKILL.md +40 -11
- package/skills/field-service-work-plan-configure/SKILL.md +253 -0
- package/skills/field-service-work-rule-designer-configure/SKILL.md +121 -95
- package/skills/fsc-actionable-segmentation-settings-configure/SKILL.md +180 -0
- package/skills/fsc-digital-origination-bre-decision-matrix-foundation-create/SKILL.md +196 -0
- package/skills/fsc-digital-origination-bre-disclosures-consent-configure/SKILL.md +106 -0
- package/skills/fsc-digital-origination-bre-document-upload-configure/SKILL.md +96 -0
- package/skills/fsc-digital-origination-bre-permissions-assign/SKILL.md +111 -0
- package/skills/fsc-digital-origination-bre-setup-coordinate/SKILL.md +250 -0
- package/skills/fsc-digital-origination-bre-stp-eligibility-configure/SKILL.md +122 -0
- package/skills/fsc-digital-origination-coordinate/SKILL.md +653 -0
- package/skills/fsc-digital-origination-demo-run/SKILL.md +225 -0
- package/skills/fsc-digital-origination-execution-guardrails-validate/SKILL.md +112 -0
- package/skills/fsc-digital-origination-initial-setup-configure/SKILL.md +396 -0
- package/skills/fsc-digital-origination-pricing-setup-coordinate/SKILL.md +336 -0
- package/skills/fsc-digital-origination-pricing-setup-data-foundation-create/SKILL.md +208 -0
- package/skills/fsc-digital-origination-pricing-setup-procedure-create/SKILL.md +375 -0
- package/skills/fsc-digital-origination-product-setup-act1-permissions-assign/SKILL.md +83 -0
- package/skills/fsc-digital-origination-product-setup-coordinate/SKILL.md +248 -0
- package/skills/fsc-digital-origination-sample-data-create/SKILL.md +206 -0
- package/skills/fsc-document-checklist-settings-configure/SKILL.md +57 -0
- package/skills/fsc-flexible-hierarchy-configure/SKILL.md +148 -0
- package/skills/fsc-flexible-hierarchy-foundation-configure/SKILL.md +1430 -0
- package/skills/fsc-flexible-hierarchy-graph-config-create/SKILL.md +471 -0
- package/skills/fsc-flexible-hierarchy-rule-based-graph-deploy/SKILL.md +429 -0
- package/skills/fsc-pricing-product-configurator-configure/SKILL.md +150 -0
- package/skills/fsc-pricing-salesforce-omnistudio-switch/SKILL.md +123 -0
- package/skills/fsc-product-act2-catalog-categories-create/SKILL.md +82 -0
- package/skills/fsc-product-act3-attributes-create/SKILL.md +249 -0
- package/skills/fsc-product-act4-classification-assignment-create/SKILL.md +196 -0
- package/skills/fsc-product-act5-considerations-get/SKILL.md +44 -0
- package/skills/fsc-stage-management-apex-flow-deploy/SKILL.md +384 -0
- package/skills/fsc-stage-management-compliant-data-sharing-configure/SKILL.md +144 -0
- package/skills/fsc-stage-management-decision-matrices-create/SKILL.md +107 -0
- package/skills/fsc-stage-management-definition-assignments-create/SKILL.md +189 -0
- package/skills/fsc-stage-management-definition-create/SKILL.md +108 -0
- package/skills/fsc-stage-management-permissions-assign/SKILL.md +143 -0
- package/skills/fsc-stage-management-transitions-configure/SKILL.md +139 -0
- package/skills/health-cloud-appt-booking-config-configure/SKILL.md +135 -0
- package/skills/health-cloud-appt-booking-url-config-configure/SKILL.md +134 -0
- package/skills/health-cloud-care-provider-affl-role-config-configure/SKILL.md +136 -0
- package/skills/health-cloud-care-provider-search-config-configure/SKILL.md +134 -0
- package/skills/health-cloud-care-requests-create/SKILL.md +178 -0
- package/skills/health-cloud-initial-configure/SKILL.md +511 -0
- package/skills/health-cloud-patient-appointment-scheduling-configure/SKILL.md +1374 -0
- package/skills/health-cloud-provider-search-settings-configure/SKILL.md +924 -0
- package/skills/health-cloud-referral-management-coordinate/SKILL.md +513 -0
- package/skills/health-cloud-timeline-configure/SKILL.md +622 -0
- package/skills/health-cloud-virtual-visit-config-configure/SKILL.md +135 -0
- package/skills/industries-account-score-settings-query/SKILL.md +78 -0
- package/skills/industries-actionable-list-data-sources-dmo-configure/SKILL.md +177 -0
- package/skills/industries-ad-product-availability-search/SKILL.md +399 -0
- package/skills/industries-advanced-account-forecast-settings-configure/SKILL.md +628 -0
- package/skills/industries-advanced-therapy-management-settings-configure/SKILL.md +73 -0
- package/skills/industries-atm-settings-starter-configure/SKILL.md +76 -0
- package/skills/industries-batch-document-ai-configure/SKILL.md +196 -0
- package/skills/industries-behavioral-health-app-settings-configure/SKILL.md +71 -0
- package/skills/industries-branch-management-settings-configure/SKILL.md +89 -0
- package/skills/industries-bre-decision-table-access-configure/SKILL.md +367 -0
- package/skills/industries-brokerage-settings-configure/SKILL.md +41 -0
- package/skills/industries-calendar-sync-settings-configure/SKILL.md +89 -0
- package/skills/industries-care-request-settings-configure/SKILL.md +218 -0
- package/skills/industries-case-management-intelligence-settings-configure/SKILL.md +54 -0
- package/skills/industries-catalog-process-attributes-products-configure/SKILL.md +380 -0
- package/skills/industries-catalog-process-fulfillment-configure/SKILL.md +216 -0
- package/skills/industries-catalog-process-intake-configure/SKILL.md +219 -0
- package/skills/industries-catalog-process-knowledge-configure/SKILL.md +153 -0
- package/skills/industries-catalog-process-preprocessor-configure/SKILL.md +168 -0
- package/skills/industries-cds-general-settings-configure/SKILL.md +69 -0
- package/skills/industries-claim-financial-settings-configure/SKILL.md +169 -0
- package/skills/industries-clinical-data-model-settings-configure/SKILL.md +136 -0
- package/skills/industries-clinical-data-model-settings-starter-configure/SKILL.md +105 -0
- package/skills/industries-collection-plan-settings-configure/SKILL.md +132 -0
- package/skills/industries-comms-service-console-settings-configure/SKILL.md +159 -0
- package/skills/industries-compliance-configure/SKILL.md +102 -0
- package/skills/industries-compliance-document-extraction-setup-configure/SKILL.md +76 -0
- package/skills/industries-contact-center-app-layout-configure/SKILL.md +88 -0
- package/skills/industries-contact-center-components-configure/SKILL.md +96 -0
- package/skills/industries-contact-center-path-knowledge-configure/SKILL.md +95 -0
- package/skills/industries-contact-center-user-access-assign/SKILL.md +96 -0
- package/skills/industries-course-waitlist-config-configure/SKILL.md +162 -0
- package/skills/industries-crisis-center-settings-configure/SKILL.md +84 -0
- package/skills/industries-custom-object-settings-configure/SKILL.md +94 -0
- package/skills/industries-data-cloud-integration-configure/SKILL.md +88 -0
- package/skills/industries-data-space-feature-mappings-configure/SKILL.md +245 -0
- package/skills/industries-decision-matrix-builder-configure/SKILL.md +78 -0
- package/skills/industries-decision-table-hbase-configure/SKILL.md +87 -0
- package/skills/industries-decision-table-version-configure/SKILL.md +74 -0
- package/skills/industries-decision-tables-builder-configure/SKILL.md +253 -0
- package/skills/industries-decision-tables-configure/SKILL.md +439 -0
- package/skills/industries-energy-utilities-configure/SKILL.md +251 -0
- package/skills/industries-eu-cloud-multisite-configure/SKILL.md +1008 -0
- package/skills/industries-eu-new-connections-configure/SKILL.md +30 -0
- package/skills/industries-explainability-msg-template-configure/SKILL.md +135 -0
- package/skills/industries-expression-set-message-token-configure/SKILL.md +135 -0
- package/skills/industries-field-service-settings-configure/SKILL.md +82 -0
- package/skills/industries-form-framework-settings-configure/SKILL.md +30 -0
- package/skills/industries-fsc-ai-settings-configure/SKILL.md +57 -0
- package/skills/industries-fsc-association-engine-settings-configure/SKILL.md +172 -0
- package/skills/industries-fsc-b2b-settings-configure/SKILL.md +61 -0
- package/skills/industries-fsc-insurance-settings-configure/SKILL.md +58 -0
- package/skills/industries-fsc-visa-fulfillment-setup-configure/SKILL.md +103 -0
- package/skills/industries-fsc-wealth-agent-settings-configure/SKILL.md +117 -0
- package/skills/industries-fsc-wealth-settings-configure/SKILL.md +99 -0
- package/skills/industries-fundraising-gift-entry-settings-configure/SKILL.md +120 -0
- package/skills/industries-fundraising-rfm-configure/SKILL.md +128 -0
- package/skills/industries-fundraising-settings-configure/SKILL.md +145 -0
- package/skills/industries-fundraising-source-code-gen-configure/SKILL.md +299 -0
- package/skills/industries-google-maps-api-key-settings-configure/SKILL.md +87 -0
- package/skills/industries-grantmaking-intelligence-settings-open/SKILL.md +58 -0
- package/skills/industries-hc-score-category-settings-configure/SKILL.md +167 -0
- package/skills/industries-health-engagement-settings-configure/SKILL.md +218 -0
- package/skills/industries-home-health-agentforce-setup-configure/SKILL.md +131 -0
- package/skills/industries-home-health-bundling-policy-create/SKILL.md +50 -0
- package/skills/industries-home-health-entity-labels-configure/SKILL.md +29 -0
- package/skills/industries-home-health-fsl-package-deploy/SKILL.md +71 -0
- package/skills/industries-home-health-fsl-settings-validate/SKILL.md +27 -0
- package/skills/industries-home-health-guided-setup-care-and-skill-get/SKILL.md +80 -0
- package/skills/industries-home-health-guided-setup-configure/SKILL.md +836 -0
- package/skills/industries-home-health-guided-setup-enable-org-fsl-get/SKILL.md +55 -0
- package/skills/industries-home-health-guided-setup-get-org-ready-get/SKILL.md +61 -0
- package/skills/industries-home-health-licenses-assign/SKILL.md +27 -0
- package/skills/industries-home-health-operating-hours-create/SKILL.md +40 -0
- package/skills/industries-home-health-scheduling-policy-create/SKILL.md +41 -0
- package/skills/industries-home-health-service-objective-create/SKILL.md +22 -0
- package/skills/industries-home-health-skills-create/SKILL.md +31 -0
- package/skills/industries-home-health-users-create/SKILL.md +29 -0
- package/skills/industries-icm-act3-toggles-configure/SKILL.md +198 -0
- package/skills/industries-icm-act5-genai-suggested-assessments-configure/SKILL.md +361 -0
- package/skills/industries-icm-act6-mcg-integration-configure/SKILL.md +550 -0
- package/skills/industries-integrated-care-management-configure/SKILL.md +168 -0
- package/skills/industries-object-enablement-configure/SKILL.md +86 -0
- package/skills/industries-tpm-system-processing-service-configure/SKILL.md +64 -0
- package/skills/insurance-brokerage-agency-billing-configure/SKILL.md +1 -3
- package/skills/integration-apex-settings-configure/SKILL.md +61 -0
- package/skills/marketing-e360-email-archiving-configure/SKILL.md +73 -0
- package/skills/marketing-message-test/SKILL.md +1 -3
- package/skills/nonprofit-fundraising-configure/SKILL.md +240 -0
- package/skills/nonprofit-fundraising-configure/references/gotchas.md +26 -0
- package/skills/nonprofit-fundraising-configure/references/mcp-invocation.md +678 -0
- package/skills/nonprofit-fundraising-configure/references/permission-targeting.md +35 -0
- package/skills/nonprofit-volunteer-management-model-get/SKILL.md +166 -0
- package/skills/nonprofit-volunteer-management-model-get/references/entities.md +315 -0
- package/skills/nonprofit-volunteer-management-model-get/references/relationships.md +175 -0
- package/skills/nonprofit-volunteer-management-model-get/references/themes.md +143 -0
- package/skills/nonprofit-volunteer-management-records-create/SKILL.md +121 -0
- package/skills/nonprofit-volunteer-management-records-create/references/field-guide.md +284 -0
- package/skills/nonprofit-volunteer-management-records-create/references/mcp-invocation.md +248 -0
- package/skills/nonprofit-volunteer-management-records-create/references/review-format.md +140 -0
- package/skills/nonprofit-volunteer-management-records-create/scripts/expand-series.py +632 -0
- package/skills/nonprofit-volunteer-management-records-create/scripts/render-review-table.py +419 -0
- package/skills/nonprofit-volunteer-management-records-create/scripts/tests/test_expand_series.py +690 -0
- package/skills/nonprofit-volunteer-management-records-create/scripts/tests/test_render_review_table.py +421 -0
- package/skills/nonprofit-volunteer-management-structure-generate/SKILL.md +119 -0
- package/skills/nonprofit-volunteer-management-structure-generate/references/configuration-decisions.md +159 -0
- package/skills/nonprofit-volunteer-management-structure-generate/references/discovery-interview.md +137 -0
- package/skills/nonprofit-volunteer-management-structure-generate/references/edge-cases.md +48 -0
- package/skills/nonprofit-volunteer-management-structure-generate/references/mcp-invocation.md +75 -0
- package/skills/nonprofit-volunteer-management-structure-generate/references/plan-output.md +141 -0
- package/skills/platform-custom-field-generate/SKILL.md +1 -0
- package/skills/platform-custom-field-generate/references/advanced-picklists.md +5 -5
- package/skills/platform-custom-metadata-type-generate/SKILL.md +3 -0
- package/skills/platform-custom-object-generate/SKILL.md +4 -0
- package/skills/platform-custom-permissions-configure/SKILL.md +687 -0
- package/skills/platform-custom-setting-generate/SKILL.md +3 -0
- package/skills/platform-datamask-run/SKILL.md +1 -5
- package/skills/platform-label-workbench-import-create/SKILL.md +67 -0
- package/skills/platform-permission-set-generate/SKILL.md +3 -0
- package/skills/platform-privacy-agent-settings-configure/SKILL.md +752 -0
- package/skills/platform-salesforce-connect-adapter-generate/SKILL.md +1 -3
- package/skills/platform-sandbox-configure/SKILL.md +1 -3
- package/skills/platform-value-set-generate/SKILL.md +3 -0
- package/skills/sales-call-scoring-configure/SKILL.md +1 -5
- package/skills/service-agentforce-channel-configure/SKILL.md +1 -3
- package/skills/service-agentforce-human-escalation-configure/SKILL.md +1 -3
- package/skills/service-catalog-template-coordinate/SKILL.md +1 -3
- package/skills/service-concierge-portal-generate/SKILL.md +1 -3
- package/skills/service-email-to-case-configure/SKILL.md +1 -5
- package/skills/service-itsm-agentic-setup-agent-runtime-access-assign/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-agentforce-coordinate/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-agentforce-studio-configure/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-agentforce-studio-validate/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-cmdb-access-assign/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-cmdb-bundle-deploy/SKILL.md +1 -5
- package/skills/service-itsm-agentic-setup-cmdb-configure/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-cmdb-discovery-configure/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-employee-agent-configure/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-incident-sla-configure/SKILL.md +1 -0
- package/skills/service-itsm-agentic-setup-itsm-agentforce-permset-assign/SKILL.md +1 -3
- package/skills/service-itsm-agentic-setup-uel-user-create/SKILL.md +1 -9
- package/skills/service-itsm-incident-mgmt-configure/SKILL.md +1 -5
- package/skills/service-itsm-incident-priority-configure/SKILL.md +1 -3
- package/skills/service-itsm-slack-itservice-configure/SKILL.md +1 -3
- package/skills/service-itsm-swarming-configure/SKILL.md +1 -3
- package/skills/service-itsm-teams-configure/SKILL.md +1 -3
- package/skills/service-itsm-teams-debug/SKILL.md +1 -3
- package/skills/service-itsm-teams-employee-agent-configure/SKILL.md +1 -3
- package/skills/service-itsm-teams-itdesk-configure/SKILL.md +1 -3
- package/skills/service-itsm-teams-itservice-configure/SKILL.md +1 -3
- package/skills/service-native-voice-recording-transcription-configure/SKILL.md +1 -3
- package/skills/service-omni-agent-users-create/SKILL.md +1 -3
- package/skills/service-omni-agent-work-sharing-configure/SKILL.md +1 -3
- package/skills/service-omni-attribute-routing-configure/SKILL.md +1 -3
- package/skills/service-omni-base-settings-configure/SKILL.md +1 -3
- package/skills/service-omni-channel-inventory-analyze/SKILL.md +1 -3
- package/skills/service-omni-channel-limits-analyze/SKILL.md +1 -3
- package/skills/service-omni-channel-setup-coordinate/SKILL.md +1 -3
- package/skills/service-omni-command-center-analyze/SKILL.md +1 -3
- package/skills/service-omni-command-center-configure/SKILL.md +1 -3
- package/skills/service-omni-permission-set-assign/SKILL.md +1 -3
- package/skills/service-omni-presence-status-deploy/SKILL.md +1 -3
- package/skills/service-omni-presence-user-config-deploy/SKILL.md +1 -3
- package/skills/service-omni-queue-deploy/SKILL.md +1 -3
- package/skills/service-omni-queue-members-assign/SKILL.md +1 -3
- package/skills/service-omni-queue-routing-config-deploy/SKILL.md +1 -3
- package/skills/service-omni-routing-flow-deploy/SKILL.md +1 -3
- package/skills/service-omni-service-channel-configure/SKILL.md +1 -3
- package/skills/service-omni-sidebar-configure/SKILL.md +1 -3
- package/skills/service-omni-skills-based-routing-configure/SKILL.md +1 -3
- package/skills/service-omni-supervisor-config-deploy/SKILL.md +1 -3
- package/skills/service-omni-supervisor-permset-assign/SKILL.md +1 -3
- package/skills/service-omni-supervisor-surface-deploy/SKILL.md +1 -3
- package/skills/service-omni-supervisor-users-create/SKILL.md +1 -3
- package/skills/service-omni-work-skill-routing-configure/SKILL.md +1 -3
- package/skills/tableau-next-asset-create/README.md +0 -65
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: industries-ad-product-availability-search
|
|
3
|
+
description: "Use this skill when users want to use when a media sales planner wants to browse / filter media ad products (by price, targeting, price book, currency, media category/type, or search phrase) and then verify inventory availability. Also use when a media sales planner wants to browse / filter media ad products (by price, targeting, price book, currency, media category/type, or search phrase) and then verify inventory availability. Trigger when users mention media, product, discovery, inventory, verification."
|
|
4
|
+
metadata:
|
|
5
|
+
version: "1.0"
|
|
6
|
+
accessCheck: "(IndustriesMedia.orgHasMediaCloudAccess) || (IndustriesMedia.orgHasMediaCloudAgentforceEnabled) || (IndustriesMedia.orgHasMediaCloudUltra) || (IndustriesMedia.userCanAccessMediaCloudAgentforce)"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Querying Media Product Discovery Inventory Verification
|
|
10
|
+
|
|
11
|
+
## When to Use This Skill
|
|
12
|
+
|
|
13
|
+
Use when a media sales planner wants to browse / filter media ad products (by price, targeting, price book, currency, media category/type, or search phrase) and then verify inventory availability. Trigger on intents like "Browse media ad products priced between $X and $Y", "Filter media ad products", "Give me media ad products which have targeting …". FIRST check whether the prompt already names filter criteria; if not, ask the user to enter criteria manually or pull them from an RFP record. Phase 1 also asks the user which product family/families to filter by (listing all families on the org when none was named) and keeps only discovered products in those families, grouped per family. Phase 1 filters the catalog; Phase 2 derives the products' distinct unit types (UnitOfMeasure.Name, e.g. Impressions / Fixed Units / SOV%) and lets the user pick at most 2 (default Impressions), then checks inventory over a flight window for each selected unit type, dimensioning on Media Channel × Product × Targeting, aggregates capacity per unit type per duration type, shows per-product max availability within each unit type, and validates a requested quantity against its unit type's max — never summing or comparing across unit types. Empty product list or empty capacity are valid, non-error answers — report them plainly, never fabricate numbers. Browse media ad products. Filter media ad products. Discover, list, or find media ad products in the existing catalog by price range, price book, currency, media type or media category (e.g. Digital, CTV, Display, Audio, Video), targeting, or search phrase. Search media ad products by channel and price range. This browses EXISTING media ad products.
|
|
14
|
+
|
|
15
|
+
## Critical Constraints
|
|
16
|
+
|
|
17
|
+
**Preconditions:**
|
|
18
|
+
|
|
19
|
+
- Org has Media Cloud Agentforce enabled (provisioned org perm). (check: `IndustriesMedia.orgHasMediaCloudAgentforceEnabled`)
|
|
20
|
+
- Caller can access Media Cloud Agentforce (AccessAgentforceForMediaCloud permission set — user perm UseAgentforceForMedia + PSL AgentforceForMediaPsl). Gates the Get Media Products Flow. (check: `IndustriesMedia.userCanAccessMediaCloudAgentforce`)
|
|
21
|
+
- Org has Media Cloud data/inventory access — gates AdSpace / AdSpaceCapacity and the /connect/media/inventory/* Connect APIs. (check: `Media Cloud access`)
|
|
22
|
+
- Org has Media Cloud Ultra (Media Plans). The read-only inventory Connect API (/connect/media/inventory/ad-space-availability) gates on orgHasMediaCloudAccess OR orgHasMediaCloudUltra, so Ultra orgs reach the same surface. (check: `Media Cloud Ultra enabled`)
|
|
23
|
+
- A price book with active PricebookEntry rows in the target currency/range exists. (check: `udd:exists:Pricebook2`)
|
|
24
|
+
- Ad-targeting reference data (AdTargetCategory / AdTargetSegmentValue) with product associations exists. (check: `udd:exists:AdTargetSegmentValue`)
|
|
25
|
+
- AdSpace + AdSpaceCapacity records loaded for the flight window (else Phase 2 is empty). (check: `udd:exists:AdSpaceCapacity`)
|
|
26
|
+
- RFP branch only — RequestForProposal + RequestForPrpsSummaryVer records exist for the account. (check: `udd:exists:RequestForProposal`)
|
|
27
|
+
|
|
28
|
+
**Operational rules:**
|
|
29
|
+
|
|
30
|
+
- FRONT-END (criteria gathering). The Get Media Products Flow filters on exactly THREE bases the user can mix and match (combined = AND / intersection): (A) BY PRODUCT NAME — a search phrase (product Name CONTAINS it); (B) BY PRICE — a min AND a max price (both needed; a missing bound defaults to 0, giving an empty 0-0 window), in a price book (defaults "Standard Price Book") and currency (defaults USD); optional media type and/or media category refine it and are reachable ONLY through this price base (so a media-type-only or media-category-only browse still needs a price window — use a wide one, e.g. 0 to 999999999); (C) BY TARGETING — ANY kind of targeting. MENU LABEL: when presenting this base in a menu or list of options, its label is EXACTLY the single word "Targeting" — never "Audience targeting", "Ad targeting", or any category name; the examples below are illustrations of what a facet may contain, NOT the label and NOT an allow-list. The user picks "Targeting" and supplies one or more targeting facets; each facet may name up to three parts: a targeting CATEGORY (the broad type, e.g. "Geo Targeting", "OS Targeting", "Audience Targeting" / "Demographics" — whatever the org defines), a category SEGMENT (the dimension within it, e.g. "Age", "Country", "Gender", "Operating System"), and a segment VALUE (the concrete value, e.g. "21 to 29", "India", "iOS"). The segment VALUE is the only MANDATORY part of this base — category and category-segment are optional refinements that narrow it. Accept whatever targeting the user gives, in either shape: fully qualified ("Geo Targeting: Country: India. Audience Targeting (Demographics): Age: 21 to 29") or value-first with the qualifier implied ("Age: 21 to 29, Country: India", or even bare "21 to 29, India"). Do NOT restrict to any one category — the examples above are illustrative, not an allow-list. (1) Inspect the prompt for any of these criteria. If present, set choice criteria-source=mentioned-in-prompt, MAP each detected value to its base — phrase → (A); any price/book/currency/media-type/media-category → (B); any segment value/category/category-segment → (C) — and go to Phase 1. Echo back to the user the criteria you detected and which base each maps to, so a misread is caught before discovery. (2) If absent, ask: enter criteria manually, or pull from an RFP record. (3) manual → PRESENT the three bases above to the user as a structured menu (name each base, its REQUIRED field(s), its optional refinements, and that they can combine bases), then collect values; do NOT dump a flat field list. Remind the user that media type/category need a price range, and that price needs both a min and a max. The Phase-2 flight window (start and end dates) and at least one media channel are REQUIRED for Phase 2 (inventory verification), not for Phase 1: gather them when known, but their absence does NOT block product discovery — never default or assume either, and gate on both only at Phase-2 entry (resolve-media-channel enforces the channel gate; the availability steps enforce the flight window). (4) rfp-record → run resolve-account → list-recent-rfps → list-summary-versions → describe-summary-fields → read-summary-fields. describe-summary-fields discovers WHICH field API name on this org's RequestForPrpsSummaryVer holds each of the four roles (targeting, media channel, flight start date, flight end date) — field names are org-specific and NOT hardcoded (commonly Product_Targeting_Details__c / Media_Channels__c / Start_Date__c / End_Date__c, but confirm, never assume): auto-detect candidates by name/label token, then present the determined mapping for all four roles and REQUIRE the user to confirm or correct it — a mandatory blocking gate, never skipped even when a match looks obvious (token match can mislink, e.g. a geography field to the audience role), and no field is read or threaded forward until the user confirms. If the user names a field they MUST give the exact field API NAME which is validated against the describe output (no match → re-ask; only a verbatim, user-confirmed describe field name is ever threaded into read-summary-fields). Then surface the confirmed targeting field's value as the targeting filter and ask if the user wants to add more criteria. Take the flight window from the confirmed start/end-date fields, but if EITHER is missing (null), ASK the user for it — never default a flight date (the flight window is enforced at Phase-2 entry, not Phase 1). Likewise take the media channel(s) from the confirmed channel field if present, but do NOT block Phase 1 on it — the channel is gathered here when the RFP carries it and otherwise asked for at Phase-2 entry (resolve-media-channel); never default or invent a channel. PHASE 1: resolve targeting with human-in-the-loop (resolve-targeting-ids) — the segment VALUE (AdTargetSegmentValue) is MANDATORY (ask for it if only a category/category segment was given); for every targeting facet AND every media channel try an EXACT match first, and on no exact match fuzzy-search and WAIT for the user to confirm the suggestion before discovery — never silently fall back or guess; if a segment-value Name is non-unique, ask the user which to pick; always show the user all three (segment value, category, category segment) in any targeting prompt. Media channel is NOT resolved in Phase 1 — product discovery and the family filter do not consume a channel, so Phase 1 completes without one; the channel is a Phase-2 entry gate (see PHASE 2 below). Then RESOLVE THE PRODUCT FAMILY FILTER (list-available-product-families): enumerate ALL product families on the org (SELECT Family FROM Product2 WHERE IsActive=true GROUP BY Family — this lists every family, media and non-media, and is deliberately NOT scoped to media products); if the user already named a family, validate it (exact → fuzzy → confirm) and skip the prompt, otherwise present the list (rendering a null family as "(No family set)") and ASK the user to pick ONE OR MORE families — never default to one, never invent a value. Then discover-products-by-criteria — BUILD productSearchCriteriaList from the criteria actually gathered (tokens are exactly "SearchPhrase" / "PriceRange" / "Targeting", case-sensitive, in that fixed order, intersected; NEVER "AdTarget" or "Keyword"), send only the fields for the selected bases (omit the rest — an unbound placeholder or unknown key faults the Flow), and pass targeting Names (NOT Ids) as JSON arrays. If the shortlist is empty, stop and report — do NOT run Phase 2. Then filter-to-selected-families — the Get Media Products Flow returns each product as {Id, Name} ONLY (Family is never projected out), so re-query Product2 by the shortlist Ids (SELECT Id,Name,Family FROM Product2 WHERE Id IN (...) AND Family IN (selected)) to keep ONLY products whose Family is among the user's picks, group the survivors per family, report how many were dropped for being in other families, and carry ONLY the surviving media_product_names into Phase 2. If none survive the family filter, stop and report (do NOT fall back to the unfiltered list). PHASE 2: FIRST resolve the media channel (resolve-media-channel) — it is REQUIRED for Phase 2 (but NOT Phase 1), treated with the same strict gate as the flight window: if none was detected in the prompt or the RFP summary, ASK the user and WAIT for at least one confirmed channel before any availability call — never default, assume, or run Phase 2 without a channel dimension (for every channel Name try an EXACT match first, and on no exact match fuzzy-search and WAIT for the user to confirm the suggestion; never silently drop or guess a channel). If the user cannot or will not name a channel, STOP Phase 2 and report that a channel is required (the Phase-1 shortlist still stands). THEN resolve-available-unit-types — derive the DISTINCT UnitOfMeasure.Name values carried by the AdSpaces of the shortlisted products (unit type is intrinsic to each AdSpace via AdSpace.UnitOfMeasureId → UnitOfMeasure.Name, NOT to the product). If more than 2 distinct unit types exist, present them all and ask the user to pick at most 2; if 2 or fewer exist, use them as-is (no prompt); if none can be derived, default to the single unit type "Impressions". Then, FOR EACH selected unit type, call /connect/media/inventory/ad-space-availability THREE times (durationType Daily, Weekly, Monthly) — so the availability calls fan out over (duration × selected unit type) — dimensioning adSpaceDimensionList on the Media Channel × Product × Targeting cross-product (single-value dimensions collapse to a top-level filter). unitType is a single scalar per call — it cannot carry multiple values, so each selected unit type is its own set of calls. Then aggregate-capacity-per-duration-type sums per product per unit type per duration type and takes the max across durations WITHIN each unit type; finally validate-requested-quantity compares the user's quantity — supplied WITH its unit type — to that unit type's max. Never sum across duration types, and never sum or compare across DIFFERENT unit types (Impressions and SOV% are not additive). Before the availability calls, confirm the endpoint path + current version via discover + describe rather than pinning a version. EFFICIENCY + SIZE GATE (see the plan-and-run-availability step for the full contract). First PRUNE DURATIONS — compute the flight-window span in days = endDate - startDate + 1. Always call Daily. Call Weekly ONLY if span >= 7. Call Monthly ONLY if span >= 28 (28, the shortest month — NOT 30/31; a 27-day window in a 28-day February would else wrongly skip a valid Monthly record). This is lossless: a pruned duration provably returns no row for the window, and the aggregation takes a MAX over durations, so max(kept, 0-for-pruned) is unchanged. It only skips durations that CANNOT match, never a duration that merely might be empty. Then apply the MANY-PRODUCTS GATE — after Phase 1, count the family-filtered shortlist (filter-to-selected-families media_product_names — the TOTAL across all selected families, not per-family). If it has MORE THAN 5 products, STOP and offer the user exactly TWO options: (1) filter on more criteria to narrow the shortlist [PREFERRED — fewer, more relevant products; rerun Phase 1 with a tighter criterion]; (2) name up to 5 specific products to check inventory for now — the user may PICK from the displayed shortlist OR FREE-TYPE product names, matched back to the shortlist (exact first, then fuzzy/contains with the user confirming the suggestion; drop anything matching nothing and say so — never invent a product not in the shortlist). Enforce the cap of 5: if the user names more than 5, ask them to trim to 5. NEVER silently check only "the first N" and present it as the whole answer, and never batch/stream across the whole shortlist. Run the kept (durationType x selected unitType) calls for the named set CONCURRENTLY (they are independent read-only calls; bounded retry on transient failure). The named-products check is USER-DRIVEN and REPEATABLE: after showing a round's results, ask the user whether to (a) validate a requested quantity against those products, or (b) check inventory for OTHER products — in which case they name the next up to 5 and the round repeats — and loop until the user is done. If the shortlist is 5 or fewer, skip the gate and check all of them directly.
|
|
31
|
+
|
|
32
|
+
## Verification Checklist
|
|
33
|
+
|
|
34
|
+
After every write operation, confirm the effect by re-reading state:
|
|
35
|
+
|
|
36
|
+
- After `filter-to-selected-families`, `resolve-media-channel`, `resolve-available-unit-types`, `plan-and-run-availability`: call `check-availability-daily` (`POST /connect/media/inventory/ad-space-availability`)
|
|
37
|
+
- After `filter-to-selected-families`, `resolve-media-channel`, `resolve-available-unit-types`, `plan-and-run-availability`: call `check-availability-weekly` (`POST /connect/media/inventory/ad-space-availability`)
|
|
38
|
+
- After `filter-to-selected-families`, `resolve-media-channel`, `resolve-available-unit-types`, `plan-and-run-availability`: call `check-availability-monthly` (`POST /connect/media/inventory/ad-space-availability`)
|
|
39
|
+
|
|
40
|
+
## Operations Reference
|
|
41
|
+
|
|
42
|
+
Operations grouped by purpose. Use these as the building blocks for the workflows above.
|
|
43
|
+
|
|
44
|
+
### Summary
|
|
45
|
+
|
|
46
|
+
| Operation | Purpose | Status | Call | Depends on |
|
|
47
|
+
|-----------|---------|--------|------|------------|
|
|
48
|
+
| `resolve-account` | read | implemented | `GET /services/data/v67.0/query` | — |
|
|
49
|
+
| `list-recent-rfps` | read | implemented | `GET /services/data/v67.0/query` | `resolve-account` |
|
|
50
|
+
| `list-summary-versions` | read | implemented | `GET /services/data/v67.0/query` | `list-recent-rfps` |
|
|
51
|
+
| `describe-summary-fields` | read | implemented | `GET /services/data/v67.0/sobjects/RequestForPrpsSummaryVer/describe` | `list-summary-versions` |
|
|
52
|
+
| `read-summary-fields` | read | implemented | `GET /services/data/v67.0/query` | `describe-summary-fields` |
|
|
53
|
+
| `resolve-targeting-ids` | read | implemented | `GET /services/data/v67.0/query` | — |
|
|
54
|
+
| `resolve-targeting-category-id` | read | implemented | `GET /services/data/v67.0/query` | `resolve-targeting-ids` |
|
|
55
|
+
| `resolve-media-channel` | read | implemented | `GET /services/data/v67.0/query` | — |
|
|
56
|
+
| `list-available-product-families` | read | implemented | `GET /services/data/v67.0/query` | — |
|
|
57
|
+
| `discover-products-by-criteria` | read | implemented | `POST /services/data/v67.0/actions/custom/flow/media_opp_flows__GetMediaProducts` | `resolve-targeting-ids`, `resolve-targeting-category-id` |
|
|
58
|
+
| `filter-to-selected-families` | read | implemented | `GET /services/data/v67.0/query` | `discover-products-by-criteria`, `list-available-product-families` |
|
|
59
|
+
| `resolve-available-unit-types` | read | implemented | `GET /services/data/v67.0/query` | `filter-to-selected-families` |
|
|
60
|
+
| `plan-and-run-availability` | validate | — | — | `filter-to-selected-families`, `resolve-media-channel`, `resolve-available-unit-types` |
|
|
61
|
+
| `check-availability-daily` | verify | implemented | `POST /connect/media/inventory/ad-space-availability` | `filter-to-selected-families`, `resolve-media-channel`, `resolve-available-unit-types`, `plan-and-run-availability` |
|
|
62
|
+
| `check-availability-weekly` | verify | implemented | `POST /connect/media/inventory/ad-space-availability` | `filter-to-selected-families`, `resolve-media-channel`, `resolve-available-unit-types`, `plan-and-run-availability` |
|
|
63
|
+
| `check-availability-monthly` | verify | implemented | `POST /connect/media/inventory/ad-space-availability` | `filter-to-selected-families`, `resolve-media-channel`, `resolve-available-unit-types`, `plan-and-run-availability` |
|
|
64
|
+
| `aggregate-capacity-per-duration-type` | validate | — | — | `plan-and-run-availability`, `check-availability-daily`, `check-availability-weekly`, `check-availability-monthly` |
|
|
65
|
+
| `validate-requested-quantity` | validate | — | — | `aggregate-capacity-per-duration-type` |
|
|
66
|
+
|
|
67
|
+
### Dependency graph
|
|
68
|
+
|
|
69
|
+
```mermaid
|
|
70
|
+
graph TD
|
|
71
|
+
resolve_account["resolve-account (read)"]
|
|
72
|
+
list_recent_rfps["list-recent-rfps (read)"]
|
|
73
|
+
list_summary_versions["list-summary-versions (read)"]
|
|
74
|
+
describe_summary_fields["describe-summary-fields (read)"]
|
|
75
|
+
read_summary_fields["read-summary-fields (read)"]
|
|
76
|
+
resolve_targeting_ids["resolve-targeting-ids (read)"]
|
|
77
|
+
resolve_targeting_category_id["resolve-targeting-category-id (read)"]
|
|
78
|
+
resolve_media_channel["resolve-media-channel (read)"]
|
|
79
|
+
list_available_product_families["list-available-product-families (read)"]
|
|
80
|
+
discover_products_by_criteria["discover-products-by-criteria (read)"]
|
|
81
|
+
filter_to_selected_families["filter-to-selected-families (read)"]
|
|
82
|
+
resolve_available_unit_types["resolve-available-unit-types (read)"]
|
|
83
|
+
plan_and_run_availability["plan-and-run-availability (validate)"]
|
|
84
|
+
check_availability_daily["check-availability-daily (verify)"]
|
|
85
|
+
check_availability_weekly["check-availability-weekly (verify)"]
|
|
86
|
+
check_availability_monthly["check-availability-monthly (verify)"]
|
|
87
|
+
aggregate_capacity_per_duration_type["aggregate-capacity-per-duration-type (validate)"]
|
|
88
|
+
validate_requested_quantity["validate-requested-quantity (validate)"]
|
|
89
|
+
resolve_account --> list_recent_rfps
|
|
90
|
+
list_recent_rfps --> list_summary_versions
|
|
91
|
+
list_summary_versions --> describe_summary_fields
|
|
92
|
+
describe_summary_fields --> read_summary_fields
|
|
93
|
+
resolve_targeting_ids --> resolve_targeting_category_id
|
|
94
|
+
resolve_targeting_ids --> discover_products_by_criteria
|
|
95
|
+
resolve_targeting_category_id --> discover_products_by_criteria
|
|
96
|
+
discover_products_by_criteria --> filter_to_selected_families
|
|
97
|
+
list_available_product_families --> filter_to_selected_families
|
|
98
|
+
filter_to_selected_families --> resolve_available_unit_types
|
|
99
|
+
filter_to_selected_families --> plan_and_run_availability
|
|
100
|
+
resolve_media_channel --> plan_and_run_availability
|
|
101
|
+
resolve_available_unit_types --> plan_and_run_availability
|
|
102
|
+
filter_to_selected_families --> check_availability_daily
|
|
103
|
+
resolve_media_channel --> check_availability_daily
|
|
104
|
+
resolve_available_unit_types --> check_availability_daily
|
|
105
|
+
plan_and_run_availability --> check_availability_daily
|
|
106
|
+
filter_to_selected_families --> check_availability_weekly
|
|
107
|
+
resolve_media_channel --> check_availability_weekly
|
|
108
|
+
resolve_available_unit_types --> check_availability_weekly
|
|
109
|
+
plan_and_run_availability --> check_availability_weekly
|
|
110
|
+
filter_to_selected_families --> check_availability_monthly
|
|
111
|
+
resolve_media_channel --> check_availability_monthly
|
|
112
|
+
resolve_available_unit_types --> check_availability_monthly
|
|
113
|
+
plan_and_run_availability --> check_availability_monthly
|
|
114
|
+
plan_and_run_availability --> aggregate_capacity_per_duration_type
|
|
115
|
+
check_availability_daily --> aggregate_capacity_per_duration_type
|
|
116
|
+
check_availability_weekly --> aggregate_capacity_per_duration_type
|
|
117
|
+
check_availability_monthly --> aggregate_capacity_per_duration_type
|
|
118
|
+
aggregate_capacity_per_duration_type --> validate_requested_quantity
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Read operations
|
|
122
|
+
|
|
123
|
+
#### `resolve-account`
|
|
124
|
+
|
|
125
|
+
Find the Account the RFP belongs to. The only typed input in the RFP walk.
|
|
126
|
+
|
|
127
|
+
**Call:** `GET /services/data/v67.0/query` — status: `implemented`
|
|
128
|
+
|
|
129
|
+
**Inputs:**
|
|
130
|
+
|
|
131
|
+
- `accountName` *(`String`)* — The advertiser account name, e.g. "Priyanka Sharma".
|
|
132
|
+
- `q` *(`string`)*
|
|
133
|
+
|
|
134
|
+
#### `list-recent-rfps`
|
|
135
|
+
|
|
136
|
+
List the newest 5 RequestForProposal records for the account; the user picks one. SummaryId on each RFP is the FK to that RFP's ACTIVE summary version.
|
|
137
|
+
|
|
138
|
+
**Call:** `GET /services/data/v67.0/query` — status: `implemented`
|
|
139
|
+
|
|
140
|
+
**Inputs:**
|
|
141
|
+
|
|
142
|
+
- `account_id` *(`String`)* — Account Id from resolve-account.
|
|
143
|
+
- **Source:** output of `resolve-account`
|
|
144
|
+
- `q` *(`string`)*
|
|
145
|
+
|
|
146
|
+
**Depends on:** `resolve-account`
|
|
147
|
+
|
|
148
|
+
#### `list-summary-versions`
|
|
149
|
+
|
|
150
|
+
List all RequestForPrpsSummaryVer versions for the chosen RFP, newest first. Flag the version whose Id equals the RFP's SummaryId as the active version.
|
|
151
|
+
|
|
152
|
+
**Call:** `GET /services/data/v67.0/query` — status: `implemented`
|
|
153
|
+
|
|
154
|
+
**Inputs:**
|
|
155
|
+
|
|
156
|
+
- `rfpId` *(`String`)* — Chosen RequestForProposal Id.
|
|
157
|
+
- `activeSummaryId` *(`String`)* — The chosen RFP's SummaryId — the active summary version's Id.
|
|
158
|
+
- `q` *(`string`)*
|
|
159
|
+
|
|
160
|
+
**Depends on:** `list-recent-rfps`
|
|
161
|
+
|
|
162
|
+
#### `describe-summary-fields`
|
|
163
|
+
|
|
164
|
+
Describe RequestForPrpsSummaryVer and resolve WHICH field API name on this org's summary object holds each of the four filter roles — targeting, media channel, flight start date, flight end date — before reading them. Field API names are org-specific (custom __c fields, namespaced, or standard), so they are NOT hardcoded: they are discovered here, then the determined mapping is presented to the user for MANDATORY confirmation (a blocking gate — the user can confirm or correct any field before it is used), and only a verbatim, user-confirmed describe field name is ever threaded into read-summary-fields.
|
|
165
|
+
|
|
166
|
+
**Call:** `GET /services/data/v67.0/sobjects/RequestForPrpsSummaryVer/describe` — status: `implemented`
|
|
167
|
+
|
|
168
|
+
**Inputs:**
|
|
169
|
+
|
|
170
|
+
- `userNamedFields` *(`Map`)* — Source: user input. OPTIONAL — any field API names the user explicitly named for a role (e.g. {"targeting": "Product_Targeting_Details__c"}). Each MUST be a field API NAME (not a label) and is only accepted if it exactly matches a describe field name.
|
|
171
|
+
|
|
172
|
+
**Depends on:** `list-summary-versions`
|
|
173
|
+
|
|
174
|
+
#### `read-summary-fields`
|
|
175
|
+
|
|
176
|
+
Read the filter-relevant fields off the chosen RequestForPrpsSummaryVer using the field API names CONFIRMED in describe-summary-fields — targeting (free-text), media channel (free-text), flight start date, flight end date — plus the standard Budget and CurrencyIsoCode. The four role field names are NOT hardcoded here; they are the verbatim describe names threaded from describe-summary-fields (commonly Product_Targeting_Details__c / Media_Channels__c / Start_Date__c / End_Date__c, but org-specific).
|
|
177
|
+
|
|
178
|
+
**Call:** `GET /services/data/v67.0/query` — status: `implemented`
|
|
179
|
+
|
|
180
|
+
**Inputs:**
|
|
181
|
+
|
|
182
|
+
- `summaryVersionId` *(`String`)* — Chosen summary version Id.
|
|
183
|
+
- `targetingFieldName` *(`String`)* — CONFIRMED targeting field API name from describe-summary-fields. When present it MUST be a verbatim describe fields[*].name (validated to exist on the object). OPTIONAL — unset when the user confirmed in the (2) gate that no field maps to this role; when unset, OMIT it from the SELECT. Targeting is not mandatory for the workflow: an unmapped targeting role simply means the Targeting branch isn't seeded from the RFP — the user may still filter by price/name, or supply targeting values manually if they want that branch (do NOT force-collect a targeting value).
|
|
184
|
+
- **Source:** output of `describe-summary-fields`
|
|
185
|
+
- `channelFieldName` *(`String`)* — CONFIRMED media-channel field API name from describe-summary-fields. When present it MUST be a verbatim describe fields[*].name (validated to exist on the object). OPTIONAL — unset when the user confirmed in the (2) gate that no field maps to this role; when unset, OMIT it from the SELECT and collect the channel value from the user instead.
|
|
186
|
+
- **Source:** output of `describe-summary-fields`
|
|
187
|
+
- `startDateFieldName` *(`String`)* — CONFIRMED flight-start-date field API name from describe-summary-fields. When present it MUST be a verbatim describe fields[*].name (validated to exist on the object). OPTIONAL — unset when no date field maps to this role; when unset, OMIT it from the SELECT and ask the user for the flight start date instead.
|
|
188
|
+
- **Source:** output of `describe-summary-fields`
|
|
189
|
+
- `endDateFieldName` *(`String`)* — CONFIRMED flight-end-date field API name from describe-summary-fields. When present it MUST be a verbatim describe fields[*].name (validated to exist on the object). OPTIONAL — unset when no date field maps to this role; when unset, OMIT it from the SELECT and ask the user for the flight end date instead.
|
|
190
|
+
- **Source:** output of `describe-summary-fields`
|
|
191
|
+
- `selectColumns` *(`String`)* — DERIVED (built by the agent, not hardcoded) — the comma-joined SELECT column list substituted into the {selectColumns} placeholder in the invocation path. Built from ONLY the confirmed-mapped role field names among targetingFieldName, channelFieldName, startDateFieldName, endDateFieldName (each included IFF set), plus the always-present standard columns Budget and CurrencyIsoCode. An unmapped role contributes NO column (no empty placeholder, no leading/trailing/double comma). Every name MUST be a verbatim describe fields[*].name confirmed in describe-summary-fields — never a hardcoded or guessed field. Example with only targeting + channel mapped: "Target_Audience__c,Target_Channels__c,Budget,CurrencyIsoCode". Same author-built pattern as discover-products-by-criteria's productSearchCriteriaList.
|
|
192
|
+
- `q` *(`string`)*
|
|
193
|
+
|
|
194
|
+
**Depends on:** `describe-summary-fields`
|
|
195
|
+
|
|
196
|
+
#### `resolve-targeting-ids`
|
|
197
|
+
|
|
198
|
+
RESOLVE the targeting inputs before Phase 1, with fuzzy matching and human-in-the-loop confirmation. CONDITIONAL (machine-guarded): this step runs ONLY when targeting-scope == with-targeting (i.e. "Targeting" is among the selected productSearchCriteriaList tokens) — a SearchPhrase-only or PriceRange-only browse selects without-targeting, whose skip_steps drops this step. The segment VALUE (AdTargetSegmentValue) is MANDATORY within the Targeting branch; category and category segment are supporting context. For each candidate segment-value Name, try an EXACT match first; if it is missing, fuzzy-search and ASK the user to confirm before proceeding; if the Name is non-unique, ASK the user which to pick. The Flow resolves Names to Ids itself, so Phase 1 receives NAMES; Phase 2 dimensions on the same confirmed Names (and, when available, their category), so a wrong or unconfirmed Name silently drops its inventory combination. The query also traverses the AdTargetSegmentValue → AdTargetCategorySegment → AdTargetCategory chain to pull category + category-segment context for every candidate.
|
|
199
|
+
|
|
200
|
+
**Call:** `GET /services/data/v67.0/query` — status: `implemented`
|
|
201
|
+
|
|
202
|
+
**Inputs:**
|
|
203
|
+
|
|
204
|
+
- `candidateSegmentValues` *(`String[]`)* — ALL candidate AdTargetSegmentValue Names parsed from every targeting facet (of ANY targeting type) of the RFP Product_Targeting_Details__c or supplied manually, e.g. ["21 to 29","outdoor activities","hiking","India"] — each already normalised to the bare stored value (dimension qualifier such as "Age " stripped, "Country: India" reduced to "India"). NOT just the first facet. CONDITIONAL (machine-guarded): this whole step runs ONLY when targeting-scope == with-targeting — a SearchPhrase-only or PriceRange-only browse selects without-targeting and never reaches it (skip_steps). WITHIN the Targeting branch the segment value IS compulsory: if the branch is used but only a category / category segment was given (no segment value), ASK the user for the segment value before proceeding.
|
|
205
|
+
- `targetingCategory` *(`String`)* — Optional targeting CATEGORY term for ANY targeting type the org defines — e.g. "Audience Targeting", "Geo Targeting", "OS Targeting", or any other (these are examples, not a fixed set). When given, it is fuzzy-matched (exact→LIKE→confirm) too and used to disambiguate a non-unique segment-value Name. If the user supplies several facets with different categories, apply this per facet.
|
|
206
|
+
- `targetingCategorySegment` *(`String`)* — Optional targeting CATEGORY SEGMENT term (the dimension label within a category) for ANY targeting type — e.g. "Age", "Country", "Gender", "Operating System", or any other the org defines (examples, not a fixed set). When given, it is fuzzy-matched (exact→LIKE→confirm) too and used to disambiguate a non-unique segment-value Name. If the user supplies several facets with different category segments, apply this per facet.
|
|
207
|
+
- `q` *(`string`)*
|
|
208
|
+
|
|
209
|
+
**Output:** confirmed_segment_names is the FLAT list of confirmed AdTargetSegmentValue Names that Phase 1's Flow consumes. category_segment_names is the CATEGORY SEGMENT dimension labels (records[*].TargetCategorySegment.Name — e.g. "Age", "Country"), which ride the direct FK and are reliably populated. segment_category_ids is the DISTINCT set of records[*].TargetCategorySegmentId values — the input the NEXT step (resolve-targeting-category-id) feeds to the AdAvailableTargetSegment junction to resolve the parent CATEGORY. NOTE: this step deliberately no longer emits category_names or targeting_pairs — the CATEGORY (e.g. "Geo Targeting") does NOT ride the direct FK records[*].TargetCategorySegment.TargetCategory.Name (that column is null for Audience/Geo/OS segments; only Linear-Demography DMAs populate it), so it is resolved authoritatively from the junction in resolve-targeting-category-id and both category_names and targeting_pairs are emitted THERE. Do not read a category from this step's direct-FK column.
|
|
210
|
+
|
|
211
|
+
#### `resolve-targeting-category-id`
|
|
212
|
+
|
|
213
|
+
CONDITIONAL (machine-guarded): this step is part of the Targeting branch and runs ONLY when targeting-scope == with-targeting (i.e. "Targeting" is among the selected productSearchCriteriaList tokens) — a SearchPhrase-only or PriceRange-only browse selects without-targeting, whose skip_steps drops this step AND resolve-targeting-ids, so it never renders an empty IN-clause. The downstream discovery step simply omits the (already-optional) AdTargetCategories / targeting_pairs inputs. WITHIN the Targeting branch it always has segment_ids to resolve. Resolve the parent CATEGORY (e.g. "Geo Targeting", "Audience Targeting") for the confirmed segments, then build the two forms the rest of the workflow consumes: category_names (the Phase-1 Flow's optional AdTargetCategories refinement) and targeting_pairs (the Phase-2 targeting axis, each segment value bound to ITS OWN category). The segment↔category relationship is MANY-TO-MANY, so it lives in the junction AdAvailableTargetSegment — NOT on the direct FK AdTargetCategorySegment.TargetCategoryId (which is null for Audience/Geo/OS segments; only Linear-Demography DMAs populate it). This step is the SINGLE SOURCE OF TRUTH for the category: a null on the earlier direct-FK column is a FALSE negative resolved here, and a segment ABSENT from the junction is the only real "no category" signal. Query every distinct TargetCategorySegmentId from resolve-targeting-ids in ONE IN-clause, dedupe the rows (the junction returns one row per product availability, so a (segment,category) pair repeats), and build a segmentId→categoryName map.
|
|
214
|
+
|
|
215
|
+
**Call:** `GET /services/data/v67.0/query` — status: `implemented`
|
|
216
|
+
|
|
217
|
+
**Inputs:**
|
|
218
|
+
|
|
219
|
+
- `segment_ids` *(`String[]`)* — The DISTINCT TargetCategorySegmentId values from resolve-targeting-ids (segment_category_ids), single-quoted for the IN clause, e.g. ('<segmentId1>','<segmentId2>'). One per confirmed segment value's category-segment; de-duplicate before building the IN-list. REQUIRED here because this step only executes inside the Targeting branch (guarded by applies_when: targeting-scope == with-targeting). A SearchPhrase-only or PriceRange-only browse selects without-targeting, which skips this whole step via the choice's skip_steps — so the step never renders an empty IN-clause. WHEN it runs, resolve-targeting-ids has always confirmed at least one segment value (and thus its TargetCategorySegmentId), so segment_ids is guaranteed non-empty.
|
|
220
|
+
- **Source:** output of `resolve-targeting-ids`
|
|
221
|
+
- `q` *(`string`)*
|
|
222
|
+
|
|
223
|
+
**Depends on:** `resolve-targeting-ids`
|
|
224
|
+
|
|
225
|
+
#### `resolve-media-channel`
|
|
226
|
+
|
|
227
|
+
Resolve the Media Channel Name(s) for the Phase-2 AdSpace filter. Media channel is REQUIRED for inventory verification (Phase 2) — treated with the same strict gate as the flight window — but it is NOT required for Phase 1 (product discovery and the family filter do not consume it). This is the FIRST Phase-2 step: it runs after the Phase-1 shortlist is settled and gates entry to inventory verification. If no channel was detected in the prompt or the RFP summary the workflow ASKS the user and WAITS for at least one confirmed channel before any availability call (see agent_guidance). For each supplied/entered channel Name, confirm it exists via an exact match; if none matches, fuzzy-search and ask the user to confirm before the availability calls. Never guess a channel, never silently drop one, and never run Phase 2 with no channel.
|
|
228
|
+
|
|
229
|
+
**Call:** `GET /services/data/v67.0/query` — status: `implemented`
|
|
230
|
+
|
|
231
|
+
**Inputs:**
|
|
232
|
+
|
|
233
|
+
- `candidateChannelNames` *(`String[]`)* — Media Channel Names parsed from the free-text Media_Channels__c or supplied by the user (split on comma/semicolon/newline/" and "). REQUIRED for Phase 2 — if none is present, ASK the user and WAIT for at least one channel before any availability call; never run Phase 2 with no channel (see agent_guidance). Not needed for Phase 1.
|
|
234
|
+
- `q` *(`string`)*
|
|
235
|
+
|
|
236
|
+
#### `list-available-product-families`
|
|
237
|
+
|
|
238
|
+
PRE-DISCOVERY FAMILY GATE. Enumerate the product families present on the org so the user can scope discovery to one or more families, then feed only the picked families into the post-discovery filter. Product2.Family is an org-configured picklist (DYNAMICENUM) — there is NO fixed set of family values and no "media" flag on the record — so the family list is read LIVE from org data with a GROUP BY, never hardcoded. This lists ALL families on the org (media and non-media alike); it is NOT scoped to media/ad products. The Get Media Products Flow returns each product as {Id, Name} only (Family is never projected out of the Flow), so family selection is applied AFTER discovery in filter-to-selected-families using the selection made here.
|
|
239
|
+
|
|
240
|
+
**Call:** `GET /services/data/v67.0/query` — status: `implemented`
|
|
241
|
+
|
|
242
|
+
**Inputs:**
|
|
243
|
+
|
|
244
|
+
- `mentionedFamily` *(`String[]`)* — OPTIONAL — any product family/families the user already named in the prompt or that were read from an RFP summary. When present, they are VALIDATED against the enumerated available_families (exact → fuzzy → confirm) and the multi-select prompt is skipped; when absent, the user is asked to pick from available_families. Never thread an unvalidated family forward.
|
|
245
|
+
- `q` *(`string`)*
|
|
246
|
+
|
|
247
|
+
#### `discover-products-by-criteria`
|
|
248
|
+
|
|
249
|
+
PHASE 1 filter. Invoke the "Get Media Products" Flow with WHICHEVER of the three filter bases the gathered criteria imply. The Flow has exactly 3 case-sensitive base tokens — "SearchPhrase" (product Name CONTAINS a phrase), "PriceRange" (UnitPrice BETWEEN min/max in a named price book; also carries the optional mediaType / mediaCategory refinements), and "Targeting" (audience segment / category / category-segment) — processed in the fixed order SearchPhrase → PriceRange → Targeting. The first selected token seeds the result set and each additional token INTERSECTS it (AND, never union). productSearchCriteriaList is built by the agent from the criteria actually supplied, so all 9 documented filtering ways are reachable (e.g. ["SearchPhrase"] name-only, ["PriceRange"] price-only, ["Targeting"] targeting-only, ["PriceRange","Targeting"] combined). CRITICAL: the ad-targeting token is "Targeting", NOT "AdTarget"; the search-phrase token is "SearchPhrase", NOT "Keyword" (an unrecognised token silently yields 0 products); targeting inputs are NAMES (not Ids) sent as JSON arrays.
|
|
250
|
+
|
|
251
|
+
**Call:** `POST /services/data/v67.0/actions/custom/flow/media_opp_flows__GetMediaProducts` — status: `implemented`
|
|
252
|
+
|
|
253
|
+
**Inputs:**
|
|
254
|
+
|
|
255
|
+
- `MinimumProductPrice` *(`Double`)* — Inclusive lower bound of the product unit price (omit if not price-filtering).
|
|
256
|
+
- `MaximumProductPrice` *(`Double`)* — Inclusive upper bound of the product unit price.
|
|
257
|
+
- `AdTargetSegmentValues` *(`String[]`)* — Array of AdTargetSegmentValue NAMES (e.g. ["21 to 29"]) — NOT Ids. MUST be a JSON array. Source: resolve-targeting-ids confirmed_segment_names. At least one of AdTargetSegmentValues / AdTargetCategories / AdTargetCategorySegments is needed for the Targeting branch to filter.
|
|
258
|
+
- `AdTargetCategories` *(`String[]`)* — Array of AdTargetCategory NAMES (e.g. ["Geo Targeting"]) — NOT Ids. JSON array. Source: resolve-targeting-category-id category_names (the distinct non-null categories resolved from the AdAvailableTargetSegment junction — NOT the direct-FK column, which is null for most segments). Optional refinement of the Targeting branch (matched Name LIKE) — PASS IT whenever the junction resolved any non-null category; OMIT the key when there are none (do not send [] or null).
|
|
259
|
+
- `AdTargetCategorySegments` *(`String[]`)* — Array of AdTargetCategorySegment NAMES (e.g. ["Age","Country"]) — NOT Ids. JSON array. Source: resolve-targeting-ids category_segment_names (the confirmed non-null category segments). Optional refinement of the Targeting branch (matched Name LIKE), and a real, accepted Flow input variable — PASS IT whenever resolve-targeting-ids resolved any non-null category segment (common on this org even when category is null); OMIT the key when there are none (do not send [] or null).
|
|
260
|
+
- `priceBookName` *(`String`)* — NAME of the price book to search (the Flow resolves the name). REQUIRED when "PriceRange" is in productSearchCriteriaList; omit otherwise. Defaults to "Standard Price Book" when price-filtering.
|
|
261
|
+
- `currencyIsoCode` *(`String`)* — ISO 4217 currency code matching the PricebookEntry currency. Used with the "PriceRange" branch; defaults to USD when price-filtering. Omit otherwise.
|
|
262
|
+
- `productSearchPhrase` *(`String`)* — Product-name search phrase. REQUIRED when "SearchPhrase" is in productSearchCriteriaList (Name CONTAINS the phrase); omit otherwise.
|
|
263
|
+
- `mediaCategory` *(`String`)* — Optional media category (ProductCategory.Name, matched EXACT and VALIDATED — an invalid value faults the Flow). Only read when "PriceRange" is selected.
|
|
264
|
+
- `mediaType` *(`String`)* — Optional media type (Product.Family, matched EXACT and VALIDATED — an invalid value faults the Flow). Only read when "PriceRange" is selected.
|
|
265
|
+
- `productSearchCriteriaList` *(`String[]`)* — The base tokens to run, BUILT BY THE AGENT from the criteria actually gathered (not hardcoded). Case-sensitive; valid tokens are exactly "SearchPhrase", "PriceRange", "Targeting". Add "SearchPhrase" iff a productSearchPhrase was given; add "PriceRange" iff any of MinimumProductPrice / MaximumProductPrice / priceBookName / mediaType / mediaCategory apply; add "Targeting" iff any AdTargetSegmentValues / AdTargetCategories / AdTargetCategorySegments apply. Emit tokens in the fixed processing order SearchPhrase → PriceRange → Targeting. Multiple tokens INTERSECT (AND). NEVER "AdTarget"; NEVER "Keyword".
|
|
266
|
+
|
|
267
|
+
**Depends on:** `resolve-targeting-ids`, `resolve-targeting-category-id`
|
|
268
|
+
|
|
269
|
+
#### `filter-to-selected-families`
|
|
270
|
+
|
|
271
|
+
POST-DISCOVERY FAMILY FILTER + GROUPING. Intersect the Phase-1 shortlist against the families the user chose in list-available-product-families, and carry ONLY the surviving products into Phase 2. The Get Media Products Flow returns each product as {Id, Name} only — Product2.Family is NEVER projected out of the Flow — so this step re-queries Product2 by the shortlist Ids to read each product's Family and keep those whose Family is in selected_families. It then groups the survivors by family for display. This is the single place the family filter takes effect; every Phase-2 step consumes this step's media_product_names in place of the raw Flow output. Runs only when list-available-product-families produced a selection.
|
|
272
|
+
|
|
273
|
+
**Call:** `GET /services/data/v67.0/query` — status: `implemented`
|
|
274
|
+
|
|
275
|
+
**Inputs:**
|
|
276
|
+
|
|
277
|
+
- `product_ids` *(`String[]`)* — The Phase-1 shortlist Product2 Ids from discover-products-by-criteria (parsed from each productList entry's Id) — the set to intersect against the selected families. Single-quote each Id for the IN clause (Ids are opaque 15/18-char keys with no special characters, but keep the same single-quote-and-URL-encode discipline used for the family values below).
|
|
278
|
+
- **Source:** output of `discover-products-by-criteria`
|
|
279
|
+
- `selected_families` *(`String[]`)* — The confirmed family Names the user chose in list-available-product-families (selected_families). Product2.Family is an org-configured value that may legitimately contain an apostrophe (e.g. "Men's") or other reserved characters, so before building the IN-list SOQL-escape each value — replace every backslash with a double backslash, then every apostrophe with a backslash-apostrophe — then single-quote it and URL-encode the whole assembled query before dispatch (an unescaped apostrophe yields invalid SOQL and reserved characters corrupt the GET URL). When the user opted to include "(No family set)", handle null separately (see agent_guidance) — an IN-list cannot match null.
|
|
280
|
+
- `q` *(`string`)*
|
|
281
|
+
|
|
282
|
+
**Depends on:** `discover-products-by-criteria`, `list-available-product-families`
|
|
283
|
+
|
|
284
|
+
#### `resolve-available-unit-types`
|
|
285
|
+
|
|
286
|
+
DERIVE which unit types (UnitOfMeasure.Name) the availability calls should run for. Unit type is intrinsic to each AdSpace via AdSpace.UnitOfMeasureId → UnitOfMeasure.Name (NOT to the product — one product's AdSpaces can span Impressions, Fixed Units, SOV%), and the Connect API takes exactly one unitType per call, so the set of unit types must be resolved up front and each drives its own Daily/Weekly/Monthly calls. Query the DISTINCT UnitOfMeasure.Name across the AdSpaces of the shortlisted products. SELECTION RULE: if MORE THAN 2 distinct unit types come back, present ALL of them to the user and ask them to select AT MOST 2; if 2 or fewer come back, use them as-is with no prompt; if the query yields none, default to the single unit type ["Impressions"]. This step is the ONLY place unit types are chosen; every check-availability-* call consumes the result.
|
|
287
|
+
|
|
288
|
+
**Call:** `GET /services/data/v67.0/query` — status: `implemented`
|
|
289
|
+
|
|
290
|
+
**Inputs:**
|
|
291
|
+
|
|
292
|
+
- `productNames` *(`String[]`)* — The family-filtered shortlist Product Names from filter-to-selected-families (media_product_names) — the SAME product set the availability calls dimension on. Source: output of filter-to-selected-families (NOT the raw discover-products-by-criteria output — the family filter has already been applied).
|
|
293
|
+
- **Source:** output of `filter-to-selected-families`
|
|
294
|
+
- `q` *(`string`)*
|
|
295
|
+
|
|
296
|
+
**Depends on:** `filter-to-selected-families`
|
|
297
|
+
|
|
298
|
+
### Verify operations
|
|
299
|
+
|
|
300
|
+
#### `check-availability-daily`
|
|
301
|
+
|
|
302
|
+
Availability for capacity duration type DAILY over the flight window. Returns each matched AdSpace's contained, active DAILY AdSpaceCapacity records. Dimension on the Media Channel × Product × Targeting cross-product. This Connect API has no Agentforce Action wrapper — call it directly, at the version-free path.
|
|
303
|
+
|
|
304
|
+
**Call:** `POST /connect/media/inventory/ad-space-availability` — status: `implemented`
|
|
305
|
+
|
|
306
|
+
**Inputs:**
|
|
307
|
+
|
|
308
|
+
- `startDate` *(`Date`)* — Flight start (yyyy-MM-dd). NEVER defaulted or assumed — always a real value the user gave. RFP path: use the summary Start_Date__c ONLY if it is non-null; if it is missing, ASK the user. Manual path: ALWAYS ask the user. Do not proceed to the availability calls without a confirmed start date. Source: user-confirmed flight window (asked directly, or read from a non-null RFP summary Start_Date__c); threaded through plan-and-run-availability, not an upstream step output.
|
|
309
|
+
- `endDate` *(`Date`)* — Flight end (yyyy-MM-dd). NEVER defaulted or assumed — always a real value the user gave. RFP path: use the summary End_Date__c ONLY if it is non-null; if it is missing, ASK the user. Manual path: ALWAYS ask the user. Must be on or after startDate. Do not proceed to the availability calls without a confirmed end date. Source: user-confirmed flight window (asked directly, or read from a non-null RFP summary End_Date__c); threaded through plan-and-run-availability, not an upstream step output.
|
|
310
|
+
- `unitType` *(`String`)* — The SINGLE UnitOfMeasure.Name for THIS call — one value from resolve-available-unit-types' selected_unit_types. This step runs ONCE PER selected unit type (the API takes one unitType per call, never an array). Source: output of resolve-available-unit-types. Matched by exact equality against UnitOfMeasure.Name, so it must be a real org value (Impressions when nothing else was derived).
|
|
311
|
+
- **Source:** output of `resolve-available-unit-types`
|
|
312
|
+
- `productNames` *(`String[]`)* — Product Names from Phase 1 — one axis of the cross-product.
|
|
313
|
+
- `channelNames` *(`String[]`)* — ALL CONFIRMED Media Channel Names from resolve-media-channel (confirmed_channel_names) — never the raw multi-channel string and never just the first. Source: output of resolve-media-channel. REQUIRED and never empty — resolve-media-channel blocks Phase 2 until at least one channel is confirmed, so this axis always carries a value. Second axis: with 2+ channels this fans out into multiple cross-product OR-entries so an AdSpace on any listed channel is found.
|
|
314
|
+
- **Source:** output of `resolve-media-channel`
|
|
315
|
+
- `targetingPairs` *(`object[]`)* — The confirmed targeting as PAIRED records from resolve-targeting-category-id's targeting_pairs (every parsed facet — Age, Interests, Geo-Country — NOT just one), each { segmentValue: <AdTargetSegmentValue Name>, category: <that value's junction-resolved AdTargetCategory Name, OMITTED when the junction returned no row> } — the third axis. Each pair keeps a category bound to ITS OWN segment value, replacing the old two parallel arrays (targetingNames + targetingCategoryNames) so a segment can never be zipped to the wrong category or emit an empty category filter. With 2+ pairs this axis fans out into multiple cross-product entries; inventory is often seeded on the Geo/Interest facet, so passing only the Age facet would miss it.
|
|
316
|
+
- **Source:** output of `resolve-targeting-category-id`
|
|
317
|
+
|
|
318
|
+
**Depends on:** `filter-to-selected-families`, `resolve-media-channel`, `resolve-available-unit-types`, `plan-and-run-availability`
|
|
319
|
+
|
|
320
|
+
#### `check-availability-weekly`
|
|
321
|
+
|
|
322
|
+
Availability for capacity duration type WEEKLY over the flight window. Returns each matched AdSpace's contained, active WEEKLY AdSpaceCapacity records. Dimension on the Media Channel × Product × Targeting cross-product. This Connect API has no Agentforce Action wrapper — call it directly, at the version-free path.
|
|
323
|
+
|
|
324
|
+
**Call:** `POST /connect/media/inventory/ad-space-availability` — status: `implemented`
|
|
325
|
+
|
|
326
|
+
**Inputs:**
|
|
327
|
+
|
|
328
|
+
- `startDate` *(`Date`)* — Flight start (yyyy-MM-dd). NEVER defaulted or assumed — always a real value the user gave. RFP path: use the summary Start_Date__c ONLY if it is non-null; if it is missing, ASK the user. Manual path: ALWAYS ask the user. Do not proceed to the availability calls without a confirmed start date. Source: user-confirmed flight window (asked directly, or read from a non-null RFP summary Start_Date__c); threaded through plan-and-run-availability, not an upstream step output.
|
|
329
|
+
- `endDate` *(`Date`)* — Flight end (yyyy-MM-dd). NEVER defaulted or assumed — always a real value the user gave. RFP path: use the summary End_Date__c ONLY if it is non-null; if it is missing, ASK the user. Manual path: ALWAYS ask the user. Must be on or after startDate. Do not proceed to the availability calls without a confirmed end date. Source: user-confirmed flight window (asked directly, or read from a non-null RFP summary End_Date__c); threaded through plan-and-run-availability, not an upstream step output.
|
|
330
|
+
- `unitType` *(`String`)* — The SINGLE UnitOfMeasure.Name for THIS call — one value from resolve-available-unit-types' selected_unit_types. This step runs ONCE PER selected unit type (the API takes one unitType per call, never an array). Source: output of resolve-available-unit-types. Matched by exact equality against UnitOfMeasure.Name, so it must be a real org value (Impressions when nothing else was derived).
|
|
331
|
+
- **Source:** output of `resolve-available-unit-types`
|
|
332
|
+
- `productNames` *(`String[]`)* — Product Names from Phase 1 — one axis of the cross-product.
|
|
333
|
+
- `channelNames` *(`String[]`)* — ALL CONFIRMED Media Channel Names from resolve-media-channel (confirmed_channel_names) — never the raw multi-channel string and never just the first. Source: output of resolve-media-channel. REQUIRED and never empty — resolve-media-channel blocks Phase 2 until at least one channel is confirmed, so this axis always carries a value. Second axis: with 2+ channels this fans out into multiple cross-product OR-entries so an AdSpace on any listed channel is found.
|
|
334
|
+
- **Source:** output of `resolve-media-channel`
|
|
335
|
+
- `targetingPairs` *(`object[]`)* — The confirmed targeting as PAIRED records from resolve-targeting-category-id's targeting_pairs (every parsed facet — Age, Interests, Geo-Country — NOT just one), each { segmentValue: <AdTargetSegmentValue Name>, category: <that value's junction-resolved AdTargetCategory Name, OMITTED when the junction returned no row> } — the third axis. Each pair keeps a category bound to ITS OWN segment value, replacing the old two parallel arrays (targetingNames + targetingCategoryNames) so a segment can never be zipped to the wrong category or emit an empty category filter. With 2+ pairs this axis fans out into multiple cross-product entries; inventory is often seeded on the Geo/Interest facet, so passing only the Age facet would miss it.
|
|
336
|
+
- **Source:** output of `resolve-targeting-category-id`
|
|
337
|
+
|
|
338
|
+
**Depends on:** `filter-to-selected-families`, `resolve-media-channel`, `resolve-available-unit-types`, `plan-and-run-availability`
|
|
339
|
+
|
|
340
|
+
#### `check-availability-monthly`
|
|
341
|
+
|
|
342
|
+
Availability for capacity duration type MONTHLY over the flight window. Returns each matched AdSpace's contained, active MONTHLY AdSpaceCapacity records. Dimension on the Media Channel × Product × Targeting cross-product. This Connect API has no Agentforce Action wrapper — call it directly, at the version-free path.
|
|
343
|
+
|
|
344
|
+
**Call:** `POST /connect/media/inventory/ad-space-availability` — status: `implemented`
|
|
345
|
+
|
|
346
|
+
**Inputs:**
|
|
347
|
+
|
|
348
|
+
- `startDate` *(`Date`)* — Flight start (yyyy-MM-dd). NEVER defaulted or assumed — always a real value the user gave. RFP path: use the summary Start_Date__c ONLY if it is non-null; if it is missing, ASK the user. Manual path: ALWAYS ask the user. Do not proceed to the availability calls without a confirmed start date. Source: user-confirmed flight window (asked directly, or read from a non-null RFP summary Start_Date__c); threaded through plan-and-run-availability, not an upstream step output.
|
|
349
|
+
- `endDate` *(`Date`)* — Flight end (yyyy-MM-dd). NEVER defaulted or assumed — always a real value the user gave. RFP path: use the summary End_Date__c ONLY if it is non-null; if it is missing, ASK the user. Manual path: ALWAYS ask the user. Must be on or after startDate. Do not proceed to the availability calls without a confirmed end date. Source: user-confirmed flight window (asked directly, or read from a non-null RFP summary End_Date__c); threaded through plan-and-run-availability, not an upstream step output.
|
|
350
|
+
- `unitType` *(`String`)* — The SINGLE UnitOfMeasure.Name for THIS call — one value from resolve-available-unit-types' selected_unit_types. This step runs ONCE PER selected unit type (the API takes one unitType per call, never an array). Source: output of resolve-available-unit-types. Matched by exact equality against UnitOfMeasure.Name, so it must be a real org value (Impressions when nothing else was derived).
|
|
351
|
+
- **Source:** output of `resolve-available-unit-types`
|
|
352
|
+
- `productNames` *(`String[]`)* — Product Names from Phase 1 — one axis of the cross-product.
|
|
353
|
+
- `channelNames` *(`String[]`)* — ALL CONFIRMED Media Channel Names from resolve-media-channel (confirmed_channel_names) — never the raw multi-channel string and never just the first. Source: output of resolve-media-channel. REQUIRED and never empty — resolve-media-channel blocks Phase 2 until at least one channel is confirmed, so this axis always carries a value. Second axis: with 2+ channels this fans out into multiple cross-product OR-entries so an AdSpace on any listed channel is found.
|
|
354
|
+
- **Source:** output of `resolve-media-channel`
|
|
355
|
+
- `targetingPairs` *(`object[]`)* — The confirmed targeting as PAIRED records from resolve-targeting-category-id's targeting_pairs (every parsed facet — Age, Interests, Geo-Country — NOT just one), each { segmentValue: <AdTargetSegmentValue Name>, category: <that value's junction-resolved AdTargetCategory Name, OMITTED when the junction returned no row> } — the third axis. Each pair keeps a category bound to ITS OWN segment value, replacing the old two parallel arrays (targetingNames + targetingCategoryNames) so a segment can never be zipped to the wrong category or emit an empty category filter. With 2+ pairs this axis fans out into multiple cross-product entries; inventory is often seeded on the Geo/Interest facet, so passing only the Age facet would miss it.
|
|
356
|
+
- **Source:** output of `resolve-targeting-category-id`
|
|
357
|
+
|
|
358
|
+
**Depends on:** `filter-to-selected-families`, `resolve-media-channel`, `resolve-available-unit-types`, `plan-and-run-availability`
|
|
359
|
+
|
|
360
|
+
### Other operations
|
|
361
|
+
|
|
362
|
+
#### `plan-and-run-availability`
|
|
363
|
+
|
|
364
|
+
ORCHESTRATION ONLY (no API call). This step decides WHICH check-availability-* calls to run and over WHICH products, then drives them. It changes efficiency, never the numbers: the aggregation is identical and order-independent. Two levers: DURATION PRUNING — from the flight window, keep only the duration types that can return a row (Daily always; Weekly iff span >= 7 days; Monthly iff span >= 28 days). MANY-PRODUCTS GATE — if the Phase-1 shortlist has MORE THAN 5 products, STOP and ask the user to either (1) filter on more criteria to narrow it, or (2) name up to 5 products to check now (pick from the shortlist or free-type, matched back exact→fuzzy→confirm); never silently truncate to "the first N". The named check is user-driven and repeatable — after a round's results the user may name the next up to 5, so this step re-runs per round with that round's product set. If the shortlist is 5 or fewer, skip the gate and check all of them. The kept durationTypes drive which of check-availability-daily/weekly/monthly actually run; the round's named (or full, when <= 5) product set is the productNames each call carries, and those calls run concurrently.
|
|
365
|
+
|
|
366
|
+
**Inputs:**
|
|
367
|
+
|
|
368
|
+
- `startDate` *(`Date`)* — Flight start (yyyy-MM-dd) — same confirmed value the check-availability-* steps use. Source: user-confirmed flight window (asked directly, or read from a non-null RFP summary Start_Date__c); not an upstream step output.
|
|
369
|
+
- `endDate` *(`Date`)* — Flight end (yyyy-MM-dd) — same confirmed value the check-availability-* steps use. Source: user-confirmed flight window (asked directly, or read from a non-null RFP summary End_Date__c); not an upstream step output.
|
|
370
|
+
- `productNames` *(`String[]`)* — The family-filtered Phase-1 shortlist (filter-to-selected-families media_product_names) — the axis the size gate applies to. When it has more than 5 products the user narrows it (filter more) or names up to 5 to check this round. Source: output of filter-to-selected-families (the >5 gate counts this family-filtered TOTAL, not the raw discovery count and not per-family).
|
|
371
|
+
- `channelNames` *(`String[]`)* — Confirmed channel Names — a REQUIRED axis of the cross-product each availability call dimensions on (never empty; resolve-media-channel blocks Phase 2 until at least one channel is confirmed). Source: output of resolve-media-channel.
|
|
372
|
+
- `targetingPairs` *(`object[]`)* — Confirmed targeting_pairs — an axis of the cross-product each availability call dimensions on (may be empty). Source: output of resolve-targeting-category-id.
|
|
373
|
+
- `selectedUnitTypes` *(`String[]`)* — selected_unit_types from resolve-available-unit-types — each kept duration call runs once per unit type.
|
|
374
|
+
- **Source:** output of `resolve-available-unit-types`
|
|
375
|
+
|
|
376
|
+
**Depends on:** `filter-to-selected-families`, `resolve-media-channel`, `resolve-available-unit-types`
|
|
377
|
+
|
|
378
|
+
#### `aggregate-capacity-per-duration-type`
|
|
379
|
+
|
|
380
|
+
EXPLICIT AGGREGATION (the Connect API does not aggregate). Aggregate CLIENT-SIDE from the NESTED availability_details ($.adSpaceAvailabilityDetails) — each entry carries its owning AdSpace.Product.Name on the PARENT and its capacity rows in the child capacityAvailabilityDetails[]. Group by (product × UNIT TYPE) using that parent Product Name and the unitType the call was made with; do NOT flatten the rows first (flattening discards the product name — the rows themselves carry only AdSpaceId, never the product). Dedup rows by their row Id WITHIN a (product, unitType, duration) bucket before summing (the same AdSpace can appear under two OR-entries, so its rows can repeat and would double-count). For each unit type and duration type, SUM TotalCapacity and AvailableCapacity per product across all its channel×targeting combos and all contained days. Then, per product per UNIT TYPE, compute the MAX across the three per-duration-type available sums — the headline available quantity for that unit type over the flight window. Capacities in DIFFERENT unit types (Impressions vs SOV% vs Fixed Units) are NOT the same measure — never sum or max across unit types; keep every unit type as its own line. No API call.
|
|
381
|
+
|
|
382
|
+
**Inputs:**
|
|
383
|
+
|
|
384
|
+
- `availabilityResultsByUnitType` *(`object[]`)* — One record PER selected unit type, each tagging its unitType alongside the three duration results: { unitType, dailyAvailabilityDetails, weeklyAvailabilityDetails, monthlyAvailabilityDetails }. Each *AvailabilityDetails is the availability_details ($.adSpaceAvailabilityDetails) from the matching check-availability-* call MADE WITH THAT unitType — the NESTED structure: each entry has the parent AdSpace.Product.Name plus a child capacityAvailabilityDetails[] of rows (each row has Id, TotalCapacity, AvailableCapacity, StartDate, EndDate, AdSpaceId). NOT a pre-flattened row list. Source: check-availability-daily/weekly/monthly, grouped by the unitType each ran with (from resolve-available-unit-types' selected_unit_types).
|
|
385
|
+
- **Source:** output of `resolve-available-unit-types`
|
|
386
|
+
|
|
387
|
+
**Depends on:** `plan-and-run-availability`, `check-availability-daily`, `check-availability-weekly`, `check-availability-monthly`
|
|
388
|
+
|
|
389
|
+
#### `validate-requested-quantity`
|
|
390
|
+
|
|
391
|
+
Ask the user for the requested quantity AND the unit type it is expressed in, then compare it against that SAME unit type's max-available per product (from aggregate-capacity-per-duration-type). A quantity is only meaningful paired with a unit type — 50,000 Impressions and 50,000 SOV% are different asks — so the comparison is always within one unit type; never compare a requested quantity against a different unit type's capacity. No API call.
|
|
392
|
+
|
|
393
|
+
**Inputs:**
|
|
394
|
+
|
|
395
|
+
- `requestedQuantity` *(`Double`)* — The quantity the user wants to book, in the unit type given by requestedUnitType.
|
|
396
|
+
- `requestedUnitType` *(`String`)* — The unit type the requested quantity is expressed in — MUST be one of resolve-available-unit-types' selected_unit_types (present it as a choice if the user did not say). Determines which unit type's aggregated max the quantity is checked against; a quantity with no unit type cannot be validated. If only one unit type was selected, default to it (still state which unit type the check used).
|
|
397
|
+
- `aggregated` *(`object`)* — aggregated_by_product_unit_and_duration from the previous step (per product per unit type).
|
|
398
|
+
|
|
399
|
+
**Depends on:** `aggregate-capacity-per-duration-type`
|