Solution: SteelForge Industries
Work in Progress
This content is currently being reviewed for accuracy and will be updated soon.
Architecture Decisions
Three decisions carry the most weight at a CTA review board. Each has meaningful trade-offs and a plausible rejected alternative.
Decision 1: SAP Integration: Middleware-Brokered with Split Patterns
Decision: Deploy an integration middleware layer (MuleSoft or equivalent) between Salesforce and SAP S/4HANA. Use REST OData calls for real-time order submission and availability checks, plus scheduled batch jobs for product catalog and pricing synchronization. The middleware decouples both systems and owns all retry, logging, and error management.
Why this wins: The 30-second order submission SLA requires synchronous REST. The 4-hour price sync SLA works fine as a scheduled batch. The restriction against SAP initiating outbound calls (Req 16) means Salesforce must poll SAP for status updates, and middleware orchestrates that polling without coupling the two systems directly. The morning order window blackout (7-9 AM CT) must block batch runs but cannot block real-time order submissions; middleware enforces this scheduling logic cleanly.
Rejected alternative: Direct Salesforce-to-SAP OData calls via Named Credentials without middleware. This works for simple integrations but creates an unmanageable hairball at scale: Salesforce owns all retry logic, there is no centralized error log, each Apex callout must handle its own timeout and circuit-breaker behavior, and the CIO’s daily health dashboard would need to aggregate errors from Apex logs rather than a purpose-built integration layer. The integration specialist on this team could not maintain that architecture.
Trade-off: Middleware adds cost, a new operational dependency, and requires the SI to configure and govern it. That cost is justified here by 5,000 SKUs, 140+ daily orders, three integration points, and a two-admin internal IT team that cannot troubleshoot custom Apex callout chains.
Decision 2: Product Catalog: Custom Object Hierarchy with Attribute Partitioning
Decision: Model the 3-level catalog as three custom objects: Product_Family__c, Product_Line__c, and a junction to standard Product2 for the SKU layer. Per-line attribute sets are captured as separate child objects (Structural_Attributes__c, Flat_Attributes__c, Tubular_Attributes__c) with a lookup to Product2, not as fields on the SKU record itself.
Why this wins: The requirement explicitly rules out a single 200-field flat table (Req 2). Keeping attributes in per-line child objects means each product type has a clean, typed schema. Adding a new product line in the future means creating a new attribute object, not altering the core product record. Product2 remains the orderable entity so it works naturally with Orders, Price Books, and the portal catalog page.
Rejected alternative: A key-value EAV (Entity-Attribute-Value) pattern using a generic Attribute__c object with Name and Value text fields. This handles arbitrary attribute sets but destroys reportability: you cannot filter “all W8x31 beams with A36 grade” without a SOQL join that crosses the governor limit. Manufacturing scenarios require attribute-level filtering in both the portal and reports.
Trade-off: Per-line child objects require more schema work upfront and require developers to build per-line Lightning components for the detail page. The benefit is typed, queryable, reportable attributes that stay within governor limits.
Decision 3: Dealer Portal: Experience Cloud with Account Hierarchy and Permission Set License Segmentation
Decision: Build the dealer portal on Experience Cloud using Customer Community Plus licenses. Enforce dealer data isolation through a combination of account ownership (each dealer is a portal Account; external users are Contacts on that Account), portal role hierarchy scoped under the account owner, and OWD settings that restrict cross-account visibility.
Why this wins: The parent-child hierarchy requirement (Req 21) maps directly to the Experience Cloud portal role hierarchy, where parent dealer users hold a role that is hierarchically above all child-location roles within the same account hierarchy. Salesforce sharing cascades through portal roles under the account owner, giving parent users visibility into child-location records. Tier-based pricing isolation (Req 22) is enforced through separate Pricebook2 records (one per tier); the Apex controller queries only the pricebook assigned to the dealer’s tier. No cross-tier pricebook is ever queried.
Rejected alternative: A Partner Community license model. Partner Community is designed for resellers working on Opportunities and is priced and structured around the partner sales motion, not self-service order placement. Customer Community Plus is the right fit: it supports account hierarchies, is priced per login or per member, and supports the Cases and Orders the portal needs.
Trade-off: Customer Community Plus requires careful role hierarchy design. With 200 dealers and parent-child structures, the community role hierarchy must be planned before any accounts are created. Retrofitting roles is painful. Design the hierarchy in sprint 1.
System Landscape
Data Model
Account Hierarchy
Dealers are modeled on the standard Account object using Salesforce’s native parent-child account relationship (ParentId). The Experience Cloud role hierarchy mirrors this structure.
| Object | Purpose | Key Fields |
|---|---|---|
| Account | Each dealer company | Type (Dealer), Dealer_Tier__c (1/2/3), Source_System__c, Legacy_CRM_ID__c |
| Account (child) | Branch/location of a dealer | ParentId pointing to parent dealer |
| Contact | Dealer contacts, internal users | Email, Phone, Last_Activity_Date__c (migration flag) |
3-Level Product Catalog
| Object | Level | Key Fields |
|---|---|---|
Product_Family__c | Level 1 | Name, Family_Code__c, Description__c |
Product_Line__c | Level 2 | Name, Product_Family__c (lookup), Line_Code__c |
Product2 | Level 3 (SKU) | ProductCode (part number), Product_Line__c (lookup), Lifecycle_Status__c (Active/Discontinued/End-of-Life), Superseded_By__c (self-lookup), SAP_Material_ID__c |
Per-line attribute child objects (each has a lookup to Product2):
| Object | Product Line | Key Fields |
|---|---|---|
Structural_Attributes__c | Structural | Grade_Spec__c, Nominal_Dimensions__c, Weight_Per_Unit_Length__c, Surface_Treatment__c |
Flat_Attributes__c | Flat | Line-specific dimensions and treatment fields |
Tubular_Attributes__c | Tubular | Line-specific wall thickness, OD, and grade fields |
Inventory and Pricing
| Object | Purpose | Key Fields |
|---|---|---|
Inventory_Location__c | Availability per storage location | Product__c, Location__c (Pittsburgh/Birmingham/Columbus), Available_Qty__c, Last_Synced__c, Is_Stale__c |
PricebookEntry | Standard SF object: one per product per pricebook | Read-only to reps via FLS; synced from SAP |
Three pricebooks map to Tier 1, Tier 2, and Tier 3. An additional pricebook holds promotional prices. All are read-only for internal users; SAP remains the write authority.
Order and Case Objects
| Object | Purpose | Key Fields |
|---|---|---|
Order (standard) | SAP order reference in Salesforce | SAP_Order_ID__c, Status__c (picklist mirroring SAP states), AccountId, Submitted_By__c, Submission_Status__c (Queued/Submitted/Failed) |
OrderItem (standard) | Line items | Product2Id, PricebookEntryId (required), Quantity, Requested_Delivery_Date__c |
Shipment_Tracking__c | FreightBridge tracking per order | Order__c, Tracking_Number__c, Carrier_Status__c, Last_Poll_Time__c, EDD__c |
Case | Dealer product inquiries and service requests | AccountId, Origin (Portal), Status, SLA_Acknowledge_By__c, SLA_Resolve_By__c |
Integration_Error_Log__c | All integration failures | System__c, Payload__c, Error_Time__c, Retry_Count__c, Resolution_Status__c |
Integration Architecture
SAP: Product Catalog and Pricing Sync (Batch)
- Scheduled middleware job runs every 4 hours during business hours (not during 7-9 AM CT)
- Queries SAP OData for materials changed since last run; creates or updates
Product2and linked attribute records - New SKUs appear within 24 hours (Req 13); price changes within 4 hours (Req 13)
- Pricing updates flow into PricebookEntry records; FLS prevents rep write access
- Batch window avoids 7-9 AM peak order window per CIO directive (Req 16 implication)
SAP: Real-Time Inventory Availability (Near-Real-Time + Nightly Backstop)
- Middleware calls SAP OData stock API on a 15-minute schedule during business hours, updating
Inventory_Location__crecords per SKU per storage location (Req 4) - A staleness monitor checks
Last_Synced__c; if the last successful sync is more than 2 hours old, a process setsIs_Stale__c = trueon all inventory records and a banner appears in the portal and in Salesforce (Req 17) - Nightly full inventory snapshot runs at 11 PM CT as a backstop; reconciles any drift from the real-time feed (Req 17)
SAP: Order Submission (Synchronous with Async Fallback)
- Dealer or rep submits an order in Salesforce; an Apex callout via Named Credential posts synchronously to middleware, which relays the order to SAP via OData, all within the 30-second SLA (Req 15). Platform Events are asynchronous and cannot guarantee sub-30-second end-to-end delivery; the primary submission path must be synchronous.
- On success: SAP returns an order number, Salesforce
Order.SAP_Order_ID__cis set, status is “Confirmed” - On failure (SAP unreachable): the Apex callout catches the exception, sets
Submission_Status__c = Queued, and fires a Platform Event to middleware as an async fallback. Middleware schedules retry at T+5 and T+15 minutes; dealer/rep sees a notification that submission is pending (Req 15) - All attempts logged to
Integration_Error_Log__cwith payload and retry count (Req 19)
SAP: Order Status Updates (Outbound Poll)
- SAP must not initiate calls to Salesforce (Req 16); middleware polls SAP every 30 minutes for order status changes
- States synced: Confirmed, In Production, Shipped, Delivered, Invoiced
- On each poll, middleware compares current SAP state against Salesforce; if changed, updates
Order.Status__cvia REST API - Status in Salesforce reflects SAP within 30 minutes (Req 16)
FreightBridge: Shipment Tracking (Outbound Poll)
- Middleware job polls FreightBridge REST API every 60 minutes for open shipments (Req 18)
- Updates
Shipment_Tracking__c.Carrier_Status__candEDD__c - If status changes to “Out for Delivery” or “Delivered”, a process triggers an email or Experience Cloud notification to the dealer contact on the order (Req 18)
- Tracking numbers arrive from SAP via the order status sync; middleware writes them to
Shipment_Tracking__cwhen the SAP status moves to Shipped
Security and Sharing Model
Dealer Data Isolation
- Each dealer is a separate Account in Salesforce. Community users are created under that Account.
- OWD for Order and Case: Private. Sharing is granted through the Experience Cloud account hierarchy role (Req 21).
- Parent dealer users hold a community role that is parent to all child-location roles. Salesforce sharing cascades down via the role hierarchy, giving parent users visibility into all child orders, cases, and invoices (Req 21).
- Branch users hold the leaf role for their specific location and see only records owned by users in that role (Req 20, 21).
- No dealer can see another dealer’s records. Cross-account sharing rules are not created.
Tier-Based Pricing Isolation
- Three pricebooks (Tier 1, Tier 2, Tier 3) are separate
Pricebook2records in Salesforce. Each dealer account hasDealer_Tier__cset to their tier. - In the Experience Cloud portal, the Apex controller queries only the
Pricebook2assigned to the authenticated dealer’s tier. It does not expose a pricebook selector to the user (Req 22). Tier isolation is enforced through separate pricebook records, not through FLS onPricebookEntry.PricebookEntryhas a singleUnitPricefield per entry; FLS cannot be used to hide one tier’s price from another because each tier’s prices live in entirely separate pricebook records, not separate fields. - Internal sales reps can see all tiers for comparison purposes by querying all three pricebooks, but all
PricebookEntryfields are read-only for all Salesforce users. No rep can edit a price (Req 3).
Internal Sales Team Visibility
- Standard role hierarchy provides geographic/team scoping for internal reps
- Plant Manager users have a custom report type scoped to orders where
Plant_Source__cmatches their plant, enforced via row-level record visibility through sharing rules on the Order object (Req 31) - Integration error logs are restricted to the System Admin profile and the integration monitoring user; general sales users have no access
Migration Strategy
Phase 1: Deduplication (Weeks 1-4)
Before migrating any records, resolve the ~340 suspected duplicates in the legacy CRM (Req 7). The process:
- Extract all 1,400 accounts from Microsoft Dynamics as a flat CSV
- Run a deduplication tool (Cloudingo, DemandTools, or similar) against the extract using fuzzy matching rules: exact
AccountNamematch, phonetic match, abbreviation normalization (“Pgh” = “Pittsburgh”, ”&” = “and”), city/state suffix stripping - Tool outputs a candidate merge list. The Dealer Relations Manager reviews and approves or rejects each proposed merge before any action is taken (Req 8)
- Confirmed merges are executed in the staging environment. Surviving records carry the legacy IDs of both merged records in a multi-select or junction object for audit (Req 12)
- After deduplication, 1,400 accounts reduce to an estimated 1,060-1,100 clean records
Phase 2: Contact Audit (Weeks 3-5, parallel with account dedup)
- Flag contacts where both
EmailandPhoneare null, or whereLastActivityDateis more than 4 years prior to go-live date (Req 9) - Flagged contacts are delivered to inside sales for human review, not auto-migrated
- Clean contacts proceed to the migration load queue
Phase 3: Data Load (Weeks 6-8)
Migration sequencing matters. Load in dependency order:
- Accounts (deduplicated, clean) with
Source_System__c = "Legacy CRM"andLegacy_CRM_ID__cpopulated (Req 12) - Contacts, linked to migrated accounts
- Six years of Opportunity history, linked to the correct merged account records (Req 10)
- Post-load: run duplicate rules in Salesforce to catch any duplicates the tool missed; report to Dealer Relations Manager
Phase 4: Legacy CRM Transition (Go-Live + 90 Days)
- Legacy CRM is locked to read-only immediately at go-live (Req 11)
- Internal users who need historical reference access the legacy CRM directly in read-only mode for 90 days
- At 90 days post go-live, the legacy system is decommissioned from active use
- Full decommission (hardware retirement) by month 6 post go-live (Req 11)
Reporting Approach
All five dashboards are built natively in Salesforce using CRM Analytics or standard Reports and Dashboards. No external BI tool is in scope.
| Report | Audience | Refresh | Key Objects |
|---|---|---|---|
| VP of Sales Dashboard | Linda Reyes | Daily | Order, Account, Opportunity |
| Inside Sales Order Pipeline | Inside sales | Real-time / on-demand | Order, Integration_Error_Log__c |
| CIO Integration Health | David Okonkwo | Weekly | Integration_Error_Log__c, Inventory_Location__c |
| Plant Manager View | Per plant manager | Daily | Order filtered by Plant_Source__c |
| Executive Monthly Summary | Executives | Monthly, scheduled PDF | Order, Product_Family__c, Account |
The VP dashboard (Req 28) needs 90-day rolling revenue by dealer and tier. This requires a custom report type joining Order, OrderItem, and Account with Dealer_Tier__c. Order frequency trends require a summary formula on a grouped report.
The integration health dashboard (Req 30) reads directly from Integration_Error_Log__c. Unresolved errors older than 24 hours are surfaced via a filter on Resolution_Status__c != Resolved AND Error_Time__c < NOW() - 1 day.
The executive monthly PDF (Req 32) is delivered via scheduled report subscription; Salesforce emails the PDF on the first business day of each month.
Requirements Addressed
| Req | Requirement | Solution |
|---|---|---|
| 1 | 3-level hierarchy: Family > Line > SKU | Product_Family__c > Product_Line__c > Product2 custom object chain |
| 2 | Per-line attribute sets, no 200-field table | Separate child attribute objects per product line (Structural_Attributes__c, etc.) |
| 3 | Pricing read-only; SAP is write authority | FLS on PricebookEntry fields; all price fields read-only for all Salesforce users |
| 4 | Inventory per location within 15 min | 15-minute middleware poll writes to Inventory_Location__c; staleness flag at 2 hours |
| 5 | SKU supersession: old part number surfaces new | Superseded_By__c self-lookup on Product2; search includes superseded records and redirects |
| 6 | Lifecycle states; EOL SKUs hidden from portal | Lifecycle_Status__c picklist; portal catalog query filters Status != End-of-Life |
| 7 | Migrate all 1,400 accounts; dedup ~340 first | Fuzzy dedup tool + human review + staged load; see Migration Strategy |
| 8 | Dedup handles naming variations; human review before merge | Fuzzy/phonetic matching rules; candidate list sent to Dealer Relations Manager for approval |
| 9 | Flag incomplete/stale contacts for review | Pre-migration audit flags contacts missing email+phone or inactive 4+ years |
| 10 | Migrate 6 years of opportunity history | Load after accounts; relate to merged account records using legacy-to-new ID map |
| 11 | Legacy CRM read-only 90 days; decommission by month 6 | Cutover plan: read-only lock at go-live; decommission checkpoint at day 90 and month 6 |
| 12 | Source-system field and legacy ID on all migrated records | Source_System__c and Legacy_CRM_ID__c fields on Account, Contact, Opportunity |
| 13 | New SKUs within 24 hours; price changes within 4 hours | Scheduled batch every 4 hours; 24-hour window covers one full business day |
| 14 | Orders created in SAP; Salesforce holds reference only | Order submission via middleware to SAP OData; Salesforce stores SAP_Order_ID__c |
| 15 | Order submission <30 seconds; queue if SAP unreachable | Synchronous REST via middleware; async fallback with Submission_Status__c = Queued and retry |
| 16 | SAP status synced within 30 minutes; SAP does not call Salesforce | Outbound poll by middleware every 30 minutes; no inbound listener required |
| 17 | Nightly inventory backstop; staleness warning after 2 hours | Nightly full snapshot + staleness monitor on Last_Synced__c; Is_Stale__c drives UI banner |
| 18 | FreightBridge poll every 60 minutes; notify on key status changes | Scheduled polling; process triggers notification on “Out for Delivery” and “Delivered” |
| 19 | Log all integration errors with payload, timestamp, retry count | Integration_Error_Log__c object; middleware writes all events; daily health report |
| 20 | 200 dealers get Experience Cloud portal access | Customer Community Plus; dealer principal manages their own portal users |
| 21 | Parent users see child-account orders/invoices; branch users see own | Experience Cloud account role hierarchy mirrors Account parent-child |
| 22 | Dealers see their tier pricing only; other tiers invisible | Query scoped to dealer’s assigned Pricebook2; Apex controller never queries other-tier pricebooks |
| 23 | Dealers place orders: line items, shipping address, PO number; validate before submit | Custom portal order form; validates SKU status and availability before submitting to middleware |
| 24 | CSV order upload for high-volume dealers (25 accounts, 5+ orders/week) | File upload component; server-side validation; line-level error preview; confirmation before submit |
| 25 | Dealers view orders with SAP status, tracking, and PDF invoice | Order detail page pulls Order.Status__c, Shipment_Tracking__c, and invoice PDF from SAP/files |
| 26 | Dealers submit Cases; 4-hour acknowledgment SLA, 2-day resolution | Case object with SLA entitlements; dealer support queue; SLA_Acknowledge_By__c and SLA_Resolve_By__c |
| 27 | English only Phase 1; no Phase 2 blocker | Experience Cloud Language settings left flexible; Translations Workbench not activated but not blocked |
| 28 | VP Sales dashboard: 90-day rolling, revenue by dealer/tier, frequency, opportunities | Custom report types on Order + Account + Opportunity; daily scheduled refresh |
| 29 | Inside sales order pipeline with 5-business-day aging flags | Report with Status grouping and formula for business-day age; conditional highlighting |
| 30 | CIO integration health: sync success rates, latency, unresolved errors | Dashboard reading Integration_Error_Log__c; middleware writes latency metrics |
| 31 | Plant manager view scoped to their plant | Report filtered on Order.Plant_Source__c; sharing rule scopes record access |
| 32 | Executive monthly summary with PDF email delivery | Scheduled report subscription; summary report joining Product_Family__c and Account tier |
Risk Assessment
Risk 1: SAP Order Window Conflict The morning peak window (7-9 AM CT) is when dealers are most active placing orders. Batch sync jobs are blocked during this window, but real-time order submissions continue. Risk: a spike of 280 orders on a peak day stresses the middleware-to-SAP OData path. Mitigation: load test at 1.5x peak (420 orders per day compressed into 2 hours) before go-live; configure middleware thread pools and SAP OData rate limits accordingly. Have a queue-and-retry fallback for the window if SAP cannot keep pace.
Risk 2: Deduplication Timeline 340 suspected duplicates requiring human review is a significant workload for a sales team also preparing for a new CRM launch. If the Dealer Relations Manager takes longer than 4 weeks, the migration sequence slips. Mitigation: start dedup in week 1 of the program; run in parallel with design sprints; set a day-28 hard cutoff where unresolved candidates are migrated separately as distinct accounts and flagged for post-go-live cleanup.
Risk 3: Tier-Pricing Leakage If a permission set misconfiguration exposes a Tier 1 dealer to Tier 2 pricing fields, the business consequences are significant. This is a penetration test scenario. Mitigation: test pricing isolation for each tier profile in a sandbox using dedicated dealer test users before UAT begins; add a regression test to the deployment checklist.
Risk 4: Experience Cloud Role Hierarchy Retrofitting With 200 dealers and a parent-child structure, the community role hierarchy must be established before any community user is provisioned. If the hierarchy is designed incorrectly and needs revision after accounts are live, all sharing must be rebuilt. Mitigation: design the complete role hierarchy in a scratch org in sprint 1, validated against the actual dealer account list before creating any portal users.
Domain Scoring Notes
Data Domain Judge Probes
A Data judge will probe the attribute model. Expect: “How do you handle a new product line with a different attribute set? Do you change your schema?” The correct answer is: create a new attribute child object and a new portal component for that line; the core Product2 schema does not change. Also expect: “How do you ensure a rep cannot quote a discontinued SKU?” The answer is through Lifecycle_Status__c validation rules on OrderItem and portal-side SKU validation before submit.
A judge may also probe the dedup strategy: “What happens if the automated tool proposes a merge that is wrong and the admin confirms it?” You must have a rollback procedure. Migrated records carry both legacy IDs, so a support ticket can restore the original record state from the legacy CRM during the 90-day read-only window.
Integration Domain Judge Probes
Expect: “Your order submission is synchronous. What is your exact failure path at 8:05 AM when SAP is under peak load?” Walk through the full path: the Apex callout via Named Credential posts synchronously to middleware; middleware makes a REST call to SAP that times out at 25 seconds (leaving a 5-second buffer within the 30-second SLA); middleware returns an error response to Salesforce; Apex catches the exception, sets Submission_Status__c = Queued, and fires a Platform Event as an async fallback trigger; middleware schedules retry at T+5 and T+15; a notification goes to the dealer and the inside sales rep. If both retries fail, the error is escalated to the integration log and a manual intervention flag appears on the Order record.
Also expect: “You’re polling SAP every 30 minutes for order status. What if SAP is down for 3 hours? How does that manifest in Salesforce?” Answer: Integration_Error_Log__c accumulates failed poll attempts, the CIO dashboard shows the gap, and inventory staleness logic triggers after 2 hours. Order statuses freeze at their last known value. When SAP comes back online, the next poll catches all status changes. You do not replay history. SAP sends current state, not a delta, so the next successful poll is a full reconciliation.
What Would Fail
Anti-Pattern 1: Writing price fields back to Salesforce from a trigger A common trap: build a trigger or flow that writes negotiated prices to a currency field on the Opportunity Product or Order Item so reps can “see the price.” This breaks SAP as the pricing authority (Req 3), creates drift when SAP prices change, and opens the door to reps quoting stale prices. The correct pattern: prices are read at display time from the pricebook, which is populated by the middleware sync. No price data lives outside PricebookEntry.
Anti-Pattern 2: Giving all Community users read access to all Orders Setting OWD for Order to Public Read, or creating a sharing rule that gives all portal users read access to all orders for simplicity, would expose one dealer’s order history to another. The scenario states this explicitly as a failure mode (Rick Huang: “A dealer in Portland must never see another dealer’s negotiated pricing”). OWD must be Private; sharing must be controlled exclusively through the account role hierarchy.
Anti-Pattern 3: Skipping the dedup phase and migrating directly A time-pressured team might argue: migrate all 1,400 accounts and clean up duplicates post go-live using Salesforce’s built-in duplicate rules. This fails because: the duplicate rules will block merges of records with linked Opportunities (data loss risk), the legacy 6-year opportunity history links to the wrong account post-merge, and sales reps will encounter duplicates on day one and lose confidence in the new system. The dedup must happen before migration, not after.
Scoring Rubric
| Criterion | Weight | What Earns Full Marks |
|---|---|---|
| Data Model | 25% | 3-level hierarchy modeled correctly; per-line attribute child objects (not flat table or EAV); supersession self-lookup present; lifecycle states with EOL exclusion explained |
| Integration Architecture | 25% | Middleware layer present and justified; correct pattern per integration (sync REST for orders, batch for catalog, poll for status and tracking); SAP-initiates-no-calls respected; failure path for order submission described |
| Dealer Portal and Security | 20% | Experience Cloud portal role hierarchy for parent-child visibility; tier pricing isolation via separate Pricebook2 records scoped by Apex controller; dealer cannot see another dealer’s data; CSV upload handled |
| Migration Strategy | 15% | Dedup before migration, not after; human review gate; contact flagging; legacy ID preserved; sequencing in dependency order; 90-day transition and decommission plan |
| Reporting and Completeness | 15% | All 5 dashboards addressed; correct objects identified; integration health tied to the error log object; no requirements missed |
Self-Assessment Checklist
- Does my data model show all three hierarchy levels as distinct objects, not a flat Product2 with three lookup fields to itself?
- Are per-line attributes in separate child objects (not as fields on Product2 and not as a key-value EAV)?
- Is there a middleware layer between Salesforce and SAP? Did I explain why direct callouts are insufficient?
- Did I explicitly address the “SAP must not call Salesforce” constraint and show how middleware polls instead?
- Does my dealer portal security model prevent cross-dealer data visibility, including for parent users who can only see their own hierarchy?
- Is deduplication sequenced before migration, with a human review step before any merge is committed?
- Did I address the staleness warning for inventory (2-hour threshold) and the nightly backstop?
- Are all 32 requirements traceable to a specific architecture decision or design element?
Q&A Prep
Q: Why did you choose middleware over direct Salesforce-to-SAP callouts? A: Three reasons. First, the internal IT team is two admins with no development background, so they cannot troubleshoot custom Apex callout chains. Second, the CIO’s daily health dashboard requires centralized error logging with payload and retry counts; that is only manageable from a dedicated integration layer. Third, the morning order window and the poll-based status sync require scheduling logic that belongs outside Salesforce.
Q: Your order submission is synchronous. What happens at 8 AM when SAP is under load?
A: Salesforce makes a synchronous Apex callout via Named Credential to middleware. Middleware relays the order to SAP OData with a 25-second timeout (leaving a 5-second buffer within the 30-second SLA). If SAP does not respond in time, middleware returns an error to Salesforce; Apex catches the exception, sets Submission_Status__c = Queued, and fires a Platform Event as an async fallback. Middleware picks up the event, schedules a retry at T+5 and T+15, and sends the dealer a notification that submission is pending. If both retries fail, the order is escalated in the error log and an alert appears on the Order record for inside sales. The dealer’s order is not lost.
Q: How do you stop a Tier 2 dealer from seeing Tier 1 pricing? A: Isolation is enforced through separate Pricebook2 records, one per tier. The Apex controller for the portal catalog page queries only the Pricebook2 assigned to the authenticated dealer’s tier; the query never references other-tier pricebooks. Because PricebookEntry has a single UnitPrice field per entry and tier prices live in entirely separate pricebook records (not separate fields), FLS is not applicable as a tier-isolation mechanism. The isolation guarantee lives in the Apex query logic and the portal configuration that maps each dealer account’s Dealer_Tier__c to its assigned Pricebook2.
Q: How does inventory from three SAP locations appear in Salesforce without direct SAP access?
A: Middleware polls the SAP OData stock API every 15 minutes and writes results to Inventory_Location__c records, one per SKU per storage location. Portal and Lightning pages query this object, not SAP. If the last sync is more than 2 hours old, Is_Stale__c is set to true and a banner warns the user the data may be outdated.
Q: You have 340 duplicate accounts. What’s your dedup approach? A: A dedicated dedup tool runs against the legacy CRM extract before any data touches Salesforce. It applies fuzzy matching, abbreviation normalization, and phonetic matching to produce a candidate merge list. The Dealer Relations Manager reviews and approves each proposed merge. No automated merging. Confirmed merges happen in the staging environment. Every surviving record carries the legacy IDs of all merged predecessors.
Q: What happens to opportunity history when two accounts are merged?
A: The merge retains all linked opportunities under the surviving account. The legacy-to-new account ID map is preserved in Legacy_CRM_ID__c so any post-go-live disputes can be traced. The 6-year opportunity history is loaded after accounts, using the map to assign records to the correct merged account.
Q: How does the parent dealer see orders from all their locations? A: Experience Cloud uses the Account role hierarchy. The parent dealer’s community user holds a role that is hierarchically above all child-location roles. Salesforce’s standard role-based sharing makes all records owned by subordinate roles visible to the parent role. No custom sharing rules are needed. The hierarchy handles it.
Q: How do you prevent dealers from ordering end-of-life SKUs?
A: Two mechanisms. The portal catalog query filters out records where Lifecycle_Status__c = End-of-Life; EOL SKUs never appear in search results (Req 6). As a backstop, the order submission validation checks the current SKU status before sending to middleware; if a SKU changed to EOL between page load and submit, the order is rejected with an inline error.
Q: How does FreightBridge tracking connect to the right dealer order?
A: When SAP moves an order to “Shipped” status, it includes a tracking number in the payload. The order status poll captures this and creates or updates the Shipment_Tracking__c record with the tracking number and a lookup to the Salesforce Order. The 60-minute FreightBridge poll queries all open Shipment_Tracking__c records, calls the FreightBridge API per tracking number, and writes the result back.
Q: The legacy CRM is 11 years old with no mobile access. What risk does that represent during the 90-day overlap? A: The main risk is that sales reps create new records in Salesforce but try to update the legacy system out of habit, creating inconsistency. The mitigation is training and a clear cutover communication: Salesforce is the system of record from go-live. The legacy CRM is locked to read-only and cannot accept writes, so there is no technical path for reps to create a divergence in the legacy system.
Q: How do you handle the CSV order upload for high-volume dealers? A: A file upload component in the portal accepts the dealer’s CSV. An Apex controller parses the file, validates each line against SKU status and availability, and returns a preview grid with line-level errors highlighted. The dealer reviews the preview and explicitly confirms before the order is submitted. No partial auto-submission happens. The dealer must correct errors and resubmit or exclude failed lines.
Q: How does the integration health dashboard get its data?
A: All integration events (successes and failures) are written to Integration_Error_Log__c by middleware. The dashboard reads this object directly. Success rate is calculated as a summary formula; unresolved errors older than 24 hours use a filter on Resolution_Status__c and Error_Time__c. Middleware also writes latency metrics so the CIO can see order submission response times over time.
Q: What is your multi-language strategy for Phase 2, given Phase 1 is English only? A: The portal is built without hard-coded English strings in Apex or components. All labels are defined in Custom Labels or Translation Workbench entries. The Experience Cloud language settings are configured to allow multiple languages but only English is activated in Phase 1. Adding a language in Phase 2 means activating it in Translation Workbench and providing translated label files. No structural changes to the portal architecture.
Presentation Notes
Open with the system landscape diagram. It frames the four systems and the integration boundaries clearly before you discuss any detail. Name each integration line and its pattern (synchronous REST, scheduled batch, outbound poll) before the board asks.
For the data model, lead with the account hierarchy and dealer portal visibility model because that is what differentiates this scenario from a generic CRM. The product hierarchy is complex but follows a predictable pattern. Cover it second.
The integration section is where Data and Integration judges will focus most of their probes. Be ready to walk the failure path for order submission without being prompted. The board wants to see that you have thought through failure modes, not just happy paths.
The migration sequence matters. If you cannot articulate “dedup before load” with a human review gate, the Data judge will press hard. Know your sequencing cold.
Presentation Time Budget (30-minute presentation block)
The scenario format allocates 30 minutes for the presentation and a separate 30 minutes for Q&A. Q&A does not count against the presentation block.
| Segment | Time |
|---|---|
| System landscape and architecture decisions recap | 4 minutes |
| Data model (account hierarchy, product catalog, inventory) | 7 minutes |
| Integration architecture (all four SAP channels + FreightBridge) | 10 minutes |
| Security and sharing (dealer isolation, tier pricing) | 4 minutes |
| Migration strategy and cutover plan | 3 minutes |
| Reporting approach | 1 minute |
| Assumptions recap and handoff to Q&A | 1 minute |
Leave exactly 30 minutes for Q&A. Do not eat into the Q&A block by running long on the presentation; boards penalize candidates who cannot hit the presentation time limit.
Q&A Preparation (separate 30-minute block)
Expect the Integration and Data judges to consume most of the Q&A minutes. Rehearse the order-submission failure path, SAP poll cadence, and product attribute model answers so they take under 90 seconds each. Hold back secondary details (migration cutover window, dealer hierarchy retrofit risk) for follow-up questions rather than front-loading them into the presentation.
Always verify against official Salesforce documentation
This content is study material for CTA exam preparation. Content compiled and presented with AI assistance. Not affiliated with Salesforce.
Personal study notes for the Salesforce CTA exam. Content compiled from VJ's study notes, official Salesforce documentation, community sources, and online publicly available content, then organized and presented with AI assistance. Not affiliated with Salesforce. © 2025–2026 VJ Srivastava.