๐ฌ Order Tracker โ Deep Dive (GraphQL ยท Salesforce Apex ยท ROAM)
Companion to
ORDER_TRACKER_END_TO_END.md. That doc covers the whole pipeline; this one drills into the three areas you asked about:
- The GraphQL read path โ what GraphQL serves vs. what REST serves
- The Salesforce Apex publisher โ how/when the event is created (the producer)
- ROAM mobile
Grounded in real code. Where a fact came from a sub-agent's file read rather than a line I personally re-opened, it's still file-cited so you can verify.
#1. ๐ The GraphQL Read Path
#1.1 The headline (important!)
cart-service runs a GraphQL API (Netflix DGS), but the order tracker โ the progress bar โ does NOT use it. The tracker timestamps are served only by REST (GET cart/v1/orders). GraphQL serves the cart / commerce side of an order: the vehicle, the cost breakdown (cash/finance/lease), trade-ins, taxes, incentives โ plus a few small "hints."
Verified two ways:
- A
grepacross every*.graphqlsschema file finds noprogressState,trackerPhase, or per-milestone timestamp field. - The web tracker (
useOrderSteps.ts) readsOrderProgressStatefromuseCartOrderQuery.ts, which is a plain RESTGET cart/v1/ordersโ not a GraphQL query.
๐ Rule of thumb: "Where am I in the delivery?" โ REST. "What did I buy, for how much, with which trade-in/taxes/finance terms?" โ GraphQL.
#1.2 The query surface (what GraphQL actually exposes)
cart-service uses Netflix DGS (@DgsComponent / @DgsQuery / @DgsData). The schema is split across several files under cart-service/routes/src/main/resources/schema/ (queries.graphqls, mutations.graphqls, enums.graphqls, outputTypes/payloads.graphqls, outputTypes/cart/*.graphqls, outputTypes/orderDetails/*.graphqls).
There is one order-relevant root query (schema/queries.graphqls):
type Query {getCurrentCart: CurrentCartPayload # the customer's current ACTIVE/SUBMITTED/CLOSED cart# โฆplus dealership/lookup queriesโฆ}
# outputTypes/payloads.graphqlsinterface CartPayload { cart: Cart! orderDetails: OrderDetails hints: CartHints }type CurrentCartPayload implements CartPayload {cart: Cart!orderDetails: OrderDetailshints: CartHints}# outputTypes/orderDetails/orderDetails.graphqls โ a UNION by payment type (cost breakdown)union OrderDetails =CashOrderDetails | FinanceOrderDetails | LeaseOrderDetails | InterestedInLeaseOrderDetails# e.g. FinanceOrderDetails { billboard, vehicleCost, incentives, tradeIn,# careAndProtectionPlans, shippingAndTaxes,# estimatedFinancedAmountInCents, โฆ }# outputTypes/cart/hints.graphqltype CartHints {statusHint: StatusHint!sourceAction: SourceAction!orderHints: OrderHints # โ the ONLY order-domain data in GraphQLpaymentOptions: [PaymentOptionHint!]!# โฆtradeInOptions, incentiveOptions, financeHints, preQualificationHint, localDealerHintsโฆ}type OrderHints { orderNumber: String! } # just the order number โ NOT the tracker steps
Relevant enums (schema/enums.graphqls / hints.graphql):
enum StatusHint { CART_STAGED CART_ACTIVE CART_UNFINANCEABLE_ERROR CART_INTERESTED_IN_LEASECART_CUSTOMER_DECLINED_FINANCE_ERROR CART_EXPIRED CART_CANCELEDORDER_PLACED ORDER_CANCELED }enum SourceAction{ CART_STARTED SELECTED_HOME_AND_DELIVERY SELECTED_PAYMENT_OPTIONS SELECTED_TRADE_INSELECTED_INCENTIVES SELECTED_CARE_AND_PROTECTION SELECTED_FINANCE_TERMSSUBMITTED_FINANCE_APPLICATION FINANCE_USER_ACCEPTED SUBMITTED_ORDERCART_LIFETIME_TIMEOUT CART_MANUAL_CANCEL โฆ }
โ ๏ธ Note:
OrderHintsis just{ orderNumber }. GraphQL does not exposecanCancel,showTracker,estimatedDeliveryDate, or any progress timestamps โ those live only in the REST/orderspayload.
#1.3 Query โ fetcher โ service โ converter (the map)
The whole thing resolves off one cart lookup, then each field has its own fetcher (graphql/query/CartQueries.kt, graphql/fetchers/*):
@DgsComponentclass CartQueries(private val authHelper, private val currentCartLookupOrchestrator) {@DgsQuery @Securedfun getCurrentCart(dfe): DataFetcherResult<CurrentCartPayload> {val userId = authHelper.getAndValidateUserId() // Auth0 JWT โ userIdval cart = currentCartLookupOrchestrator.lookupCurrentCartForUser(userId)return DataFetcherResult.newResult<CurrentCartPayload>().data(CurrentCartPayload()).localContext(CartContext(resultCart = cart)) // passed to all fetchers.build()}}
| GraphQL field | Fetcher | Service / converter | Returns | Reads OrderProgressState? |
|---|---|---|---|---|
cart | CartFetcher | CartDomainConverter.convertCartDomainToGql | Cart (vehicle, delivery, paymentSelection) | โ |
orderDetails | OrderDetailsFetcher | OrderDetailsConverter.buildOrderDetailsFor(cart) | OrderDetails union (cost breakdown) | โ |
hints.statusHint | StatusHintFetcher | CartStatusDomainConverter.getStatusHintFromCart | StatusHint (cart lifecycle) | โ (cart status) |
hints.sourceAction | SourceActionFetcher | maps cart.sourceAction enum | SourceAction (last change) | โ |
hints.orderHints | OrderHintsFetcher | GetOrderOrchestrator.getOrderForCart โ order.toOrderHints() | OrderHints { orderNumber } | โ ๏ธ reads the Order, but only surfaces orderNumber |
// OrderHintsFetcher โ the only fetcher that touches the Order domain@DgsData(parentType = "CartHints", field = "orderHints")fun getOrderHints(dfe): OrderHints? =when (val r = getOrderOrchestrator.getOrderForCart(dfe.getLocalContext<CartContext>().resultCart)) {is Success -> r.order.toOrderHints() // โ OrderHints(orderNumber = order.orderNumber)NotFound -> null}
// StatusHintFetcher โ cart lifecycle, NOT fulfillment stagefun getStatusHintFromCart(cart): StatusHint = when (cart.status) {Staged -> CART_STAGEDActive -> CART_ACTIVEis Submitted -> when (reason) { ORDER_PLACED -> ORDER_PLACED; UNFINANCEABLE -> CART_UNFINANCEABLE_ERROR; โฆ }is Closed -> when (reason) { EXPIRED -> CART_EXPIRED; CANCELED -> CART_CANCELED }}
#1.4 Auth & a security note
Same Auth0 JWT model as REST; each fetcher pulls userId/cart from CartContext. One thing worth flagging: in SecurityConfiguration.kt, the REST routes are explicitly .authenticated() (GET /orders, GET /cart-disposition) but the GraphQL POST endpoint currently falls under .anyRequest().permitAll() with a // TODO to lock it down. The @Secured annotation on getCurrentCart + authHelper.getAndValidateUserId() still require a valid token at the resolver level, but the HTTP filter chain itself isn't gating /graphql yet. Worth confirming before prod.
#1.5 Web consumers (which hook hits which API)
UI hook (UI/src/apis/cartServices/graphQueries/) | Backend call | Used for |
|---|---|---|
useCartOrderQuery.ts | REST GET cart/v1/orders | the tracker bar (OrderProgressState) |
useCurrentCart.ts | GraphQL getCurrentCart | cart + orderDetails (cost) |
useCartStatusQuery.ts | GraphQL statusHint | cart lifecycle badge |
useSourceActionQuery.ts | GraphQL sourceAction | "what just happened" step |
๐ Takeaway: two read paths by design. The tracker needs raw timestamps (flat REST). The commerce screens need a rich selectable graph (GraphQL). The bridge is
orderNumber/statusHint/sourceActionโ lightweight GraphQL fields, no progress data duplicated.
#2. โ๏ธ The Salesforce Apex Publisher (the producer side)
In the first doc I said the Apex publisher "isn't checked out." That was wrong โ it is here. (I also previously guessed a TrackerPhaseResolver class and a โฆDynamicVehicle class โ those don't exist; the real design uses trigger handlers with static status maps.) Here's the verified producer.
#2.1 Three publishers, one event
Every publisher ends in EventBus.publish(new Order_Tracker_Event__e(...)). They differ by what triggers them:
#2.2 Publisher A โ CaseTriggerHandler (Case/Deal status โ phase)
(file: Salesforce-FreewayCRM/.../classes/CaseTriggerHandler.cls, method dealStatusPlatformEventHandlerShop, invoked from CaseTrigger after-update) โ fires only when newCase.Status != oldCase.Status and the Case Type is Shop/Shop w/Trade. A static map decides the phase:
static final Map<String,String> statusToTrackerPhaseMapCases = new Map<String,String>{'Received by DCS' => 'ORDER_CONFIRMED','Received by DDS IV' => 'ORDER_CONFIRMED','DMV Queue' => 'E_SIGNATURE','Deal Funded' => 'CONTRACTS_COMPLETE','Wet Docs Sent' => 'TITLE_REG_SENT_WET_DOCS','Paperwork Received' => 'TITLE_REG_RECEIVED_WET_DOCS','DMV Review' => 'TITLE_REG_SENT_DMV','DMV Completed' => 'TITLE_REG_PROCESSED_DMV','Pickup Complete' => 'VEHICLE_PICKED_UP'};// Special case (regression): Status == 'Option Selected' AND Send_Back_Date__c changed โ 'RETURN_TO_MANAGER'
#2.3 Publisher B โ VehicleTriggerHandler (Vehicle status โ phase)
(file: .../classes/VehicleTriggerHandler.cls, method dealTrackerEventHandlerShop, from VehicleTrigger after-update) โ fires when Vehicle__c.Status__c changes:
static final Map<String,String> statusToTrackerPhaseMapVehicles = new Map<String,String>{'At FF: Delivery Scheduled' => 'DELIVERY_SCHEDULED','In Transit' => 'VEHICLE_IN_TRANSIT','Delivery Completed' => 'VEHICLE_DELIVERED'};
#2.4 Publisher C โ DealStatusController.emitOrderCancelledEvent (cancellation)
This one I read in full (file: .../classes/DealStatusController.cls). It publishes only ORDER_CANCELLED, and is reached two ways:
DealStatusInvocableAction_Dynamic.dealStatus()โ an@InvocableMethodcalled from a Flow (e.g.Close_Case_Screen_Flow) withstatus == 'CANCELLED'.DealStatusController.publishCancelEvent()โ@AuraEnabled, called from a Lightning/LWC "cancel" button.
public static String emitOrderCancelledEvent(String caseId) {Case record = [SELECT Account.User_Id__c, Type, Purchased_Vehicle__r.Inventory__r.VIN__c, โฆ FROM Case WHERE Id = :caseId];if (record.Type?.equalsIgnoreCase('Sell')) return 'error'; // SELL not handledif (String.isBlank(record.Account?.User_Id__c)) return 'error_no_user';String mappedCaseType = mapCaseType(record.Type); // ShopโSHOP, Shop w/TradeโSHOP_W_TRADE, SellโSELLif (String.isBlank(mappedCaseType)) return 'error_no_case_type';VehicleData vehicle = resolveVehicle(record); // 3-priority: Purchased โ Active Intent โ Order-Submitted Intentif (vehicle == null) return 'error_no_vin';Order_Tracker_Event__e event = new Order_Tracker_Event__e(userId__c = record.Account.User_Id__c, eventDateTime__c = DateTime.now(),objectType__c = 'CASE', trackerPhase__c = 'ORDER_CANCELLED',caseType__c = mappedCaseType, vin__c = vehicle.vin, vehicleId__c = vehicle.vehicleId);Database.SaveResult result = EventBus.publish(event); // โ the publishreturn result.isSuccess() ? 'success' : 'error_publish_failed';}
๐ Two things the cancel invocable also does (verified in
DealStatusInvocableAction_Dynamic.cls): after a successful publish it stamps the Case (Driveway_Deal_Status__c='Canceled',DW_Status_Update_Conf__c='CANCELLED'), and it treats the legacyORDER_COMPLETED/OUT_FOR_DELIVERYstatuses as no-ops โ the comment says "ORDER_COMPLETED and OUT_FOR_DELIVERY callouts removed." So completion/in-transit now come only from the Vehicle trigger, not this action.
#2.5 How the event fields are populated
| Field | Source |
|---|---|
userId__c | Case.Account.User_Id__c (Auth0-style id) |
eventDateTime__c | DateTime.now() at publish |
trackerPhase__c | from the status map (or hard-coded ORDER_CANCELLED) |
caseType__c | mapCaseType / DrivewayUtility.caseTypeToTrackerType: ShopโSHOP, Shop w/TradeโSHOP_W_TRADE, SellโSELL |
objectType__c | 'CASE' (Case handler & cancel) or 'VEHICLE' (Vehicle handler) |
vin__c, vehicleId__c | trigger handlers: from Vehicle__c.Inventory__r (VIN__c, Inventory_ID__c); cancel path: 3-priority resolveVehicle() |
fulfillmentMethod__c | trigger handlers derive it from the Case RecordType DeveloperName โ contains PICK_UP โ IN_STORE_PICKUP, else DELIVERY (per CaseTriggerHandler / VehicleTriggerHandler). The cancel path omits it. |
Guards: the cancel path returns typed error codes (error_no_user / error_no_case_type / error_no_vin / error_publish_failed) and publishes nothing on failure; SELL cases short-circuit. Test coverage confirms this (e.g. DealStatusInvocableAction_DynamicTest.cancelled_noVehicleData_expectError asserts error_no_vin and that the Case is not updated).
#2.6 โ ๏ธ Producer โ full enum (real gaps worth knowing)
The cart-service TrackerPhase enum has 15 values, but the Salesforce producer in this repo only emits a subset. From the maps above, these phases have no producer mapping here:
VEHICLE_PREPAREDโ not in either status map.DELIVERY_DATE_UPDATEโ no Apex setstargetDate__cor this phase anywhere (grepforDELIVERY_DATE_UPDATE/targetDatein classes returns nothing). So even though cart-service + the consumer fully handle ETA updates, the SF side here doesn't appear to send them yet.
So cart-service is built to handle more phases than Salesforce currently produces โ those paths are either future work, emitted by a different org/automation, or sent via a Flow not in this checkout. Flag for the team, not an assumption to rely on.
#2.7 Full producer โ phase map (current reality)
| Salesforce status | Object | trackerPhase published |
|---|---|---|
| Received by DCS / Received by DDS IV | Case | ORDER_CONFIRMED |
| DMV Queue | Case | E_SIGNATURE |
| Deal Funded | Case | CONTRACTS_COMPLETE |
| Wet Docs Sent | Case | TITLE_REG_SENT_WET_DOCS |
| Paperwork Received | Case | TITLE_REG_RECEIVED_WET_DOCS |
| DMV Review | Case | TITLE_REG_SENT_DMV |
| DMV Completed | Case | TITLE_REG_PROCESSED_DMV |
| Option Selected (+ Send_Back_Date__c changed) | Case | RETURN_TO_MANAGER |
| Pickup Complete | Case | VEHICLE_PICKED_UP |
| At FF: Delivery Scheduled | Vehicle | DELIVERY_SCHEDULED |
| In Transit | Vehicle | VEHICLE_IN_TRANSIT |
| Delivery Completed | Vehicle | VEHICLE_DELIVERED |
| Flow/LWC cancel | Case | ORDER_CANCELLED |
| (no producer) | โ | VEHICLE_PREPARED, DELIVERY_DATE_UPDATE |
#3. ๐ฑ ROAM Mobile
#3.1 Not on this machine โ confirmed
I searched broadly: find across /Users/cristianscript (depth 5), Spotlight (mdfind), and mobile markers (AndroidManifest.xml, *.xcodeproj, Podfile). No ROAM/mobile project exists locally. The only "Roam" hit is Products-Api/integration tests/Roam_API_Tests.postman_collection.json โ a Postman collection for the Products API, unrelated to a mobile app. So ROAM is a remote repo not checked out; the following is the integration contract it must satisfy (inferred from the server side, not from ROAM's own source).
#3.2 How ROAM must enter the tracker flow
ROAM is a client of cart-service, exactly like the web app:
To show a tracker, ROAM must:
- Auth with Auth0 and send
Authorization: Bearer <JWT>(cart-service derivesuserIdfrom the token; the read path has no userId in the URL). - Call
GET cart/v1/orders(the REST read door,OrderController.getUserOrders). It returns a list; the web app picks the most-recent byorderedOn, and ROAM would do the same. - Render from
progressStateโ the same flat timestamp bag the webuseOrderStepsconsumes:orderConfirmedAt,eSignatureAt,contractsCompleteAt,vehiclePreparedAt,deliveryScheduledAt,vehicleInTransitAt,vehicleDeliveredAt/vehiclePickedUpAt, plusestimatedDeliveryDateandfulfillmentMethod(to choose delivery vs pickup steps).
#3.3 What ROAM does not do
- It does not talk to Salesforce, the Pub/Sub bus, or the
order-tracker-consumerโ all server-side. - It does not receive push for tracker changes in this design; the model is pull (re-fetch
cart/v1/orders; the web caches ~1h via React Query). Near-real-time would need polling or a separate push channel. - It does not need GraphQL for the bar; richer "my purchase" screens could use the same DGS surface (
getCurrentCart) as web.
๐ To verify ROAM's real implementation, clone it under
~/programming(or point me at the repo) and I'll trace its actual network layer โ Retrofit/Apollo/URLSession base URLs and exact endpoints โ and replace this contract-based section with verified citations.
#4. ๐ End-to-End Status Map (Salesforce status โ UI bar step)
This is the single table that ties everything together: a Lithia employee changes a status in Salesforce โ an Apex publisher emits a trackerPhase โ cart-service stamps a field โ the web UI lights up a step. Ordered by the customer's journey.
| # | Salesforce status (object) | Publisher | trackerPhase | cart-service effect (field / status) | UI label (variant) |
|---|---|---|---|---|---|
| 1 | Received by DCS / Received by DDS IV (Case) | CaseTriggerHandler | ORDER_CONFIRMED | orderConfirmedAt | Order Confirmed (stage) |
| 2 | DMV Queue (Case) | CaseTriggerHandler | E_SIGNATURE | eSignatureAt (clears later title steps) | E-signatures complete (substep) |
| 3 | Deal Funded (Case) | CaseTriggerHandler | CONTRACTS_COMPLETE | contractsCompleteAt (+back-fill orderConfirmedAt) | Contracts Complete (stage) |
| 4 | Wet Docs Sent (Case) | CaseTriggerHandler | TITLE_REG_SENT_WET_DOCS | titleAndRegistrationSentAt | Title & registration paperwork sent (substep) |
| 5 | Paperwork Received (Case) | CaseTriggerHandler | TITLE_REG_RECEIVED_WET_DOCS | titleAndRegistrationReceivedAt | Title & registration paperwork received (substep) |
| 6 | DMV Review (Case) | CaseTriggerHandler | TITLE_REG_SENT_DMV | titleSentForProcessingAt | Title & registration sent for processing (substep) |
| 7 | DMV Completed (Case) | CaseTriggerHandler | TITLE_REG_PROCESSED_DMV | titleAndRegistrationProcessedAt | Title & registration processed (substep) |
| 8 | At FF: Delivery Scheduled (Vehicle) | VehicleTriggerHandler | DELIVERY_SCHEDULED | deliveryScheduledAt | Delivery scheduled (substep) |
| 9 | In Transit (Vehicle) | VehicleTriggerHandler | VEHICLE_IN_TRANSIT | vehicleInTransitAt + deliveryStatus=IN_TRANSIT (clears deliveryScheduledAt) | Vehicle in transit (substep) |
| 10 | Delivery Completed (Vehicle) | VehicleTriggerHandler | VEHICLE_DELIVERED | vehicleDeliveredAt + orderStatus=COMPLETED + deliveryStatus=DELIVERED (+back-fill prepared/contracts/confirmed) | Vehicle Delivered (stage) |
| 11 | Pickup Complete (Case) | CaseTriggerHandler | VEHICLE_PICKED_UP | vehiclePickedUpAt + orderStatus=COMPLETED + deliveryStatus=DELIVERED (+back-fill) | Vehicle Picked Up (stage) |
| 12 | Option Selected + Send_Back_Date__c changed (Case) | CaseTriggerHandler | RETURN_TO_MANAGER | clears confirmedโtitle timestamps (regression) | bar steps back |
| 13 | Cancel โ Flow (Close_Case_Screen_Flow) or LWC button (Case) | DealStatusController | ORDER_CANCELLED | orderStatus=CANCELLED | Order canceled state |
| โ | (no producer in this repo) | โ | VEHICLE_PREPARED | vehiclePreparedAt | Vehicle Prepared (stage) โ see ยง5 |
| โ | (no producer in this repo) | โ | DELIVERY_DATE_UPDATE | estimatedDeliveryDate | ETA label |
Two UI stages are deliberately not driven by Salesforce status changes:
Order Placedโ the UI synthesizes this first stage from the order'sorderedOntimestamp (always shown complete; seeuseOrderSteps.ts, the"Order Placed"row), not from any event.- The substeps
Identity verified,Documents uploaded,Trade-in vehicle condition verified,Deposit paid,Down payment paidcome from the other cart-service callbacks (identity-verification, document-upload, payment /finalize-down-payment) โ not fromOrder_Tracker_Event__e. The UI shows them between the main stages, anduseOrderStepsfilters them out when they don't apply (no trade-in โ droptradeInVerifiedAt; non-finance deal โ dropdownPaymentPaidAt; pickup โ drop the whole delivery/title cluster).
#5. ๐ Trace: what populates VEHICLE_PREPARED?
Short answer: nothing in Salesforce emits it โ yet the "Vehicle Prepared" stage still completes, via back-fill at delivery/pickup.
#5.1 The evidence
VEHICLE_PREPARED exists at every layer except the producer:
| Layer | Supports VEHICLE_PREPARED? | Where |
|---|---|---|
| Salesforce producer | โ No | Not in statusToTrackerPhaseMapCases (9 entries) nor statusToTrackerPhaseMapVehicles (3 entries: Delivery Completed / In Transit / At FF: Delivery Scheduled). No Apex sets it. |
| Consumer | โ | OrderTrackerEvent.TrackerPhase.VEHICLE_PREPARED enum value |
| cart-service router | โ | OrderProgressOrchestratorRouter โ applyVehiclePrepared(...) |
| cart-service orchestrator/calculator | โ | OrderProgressUpdateOrchestrator.applyVehiclePrepared โ OrderProgressCalculator.calculateVehiclePreparedAt |
| UI | โ | useOrderSteps.ts step vehiclePreparedAt โ label "Vehicle Prepared" (a stage) |
So the direct path (applyVehiclePrepared โ set vehiclePreparedAt) is wired end-to-end but is effectively dead code today โ the router branch never fires because no event with trackerPhase=VEHICLE_PREPARED is ever produced.
#5.2 โฆbut the stage still lights up โ here's the trick
OrderProgressCalculator back-fills vehiclePreparedAt when the vehicle is delivered or picked up (verified in OrderProgressCalculator.kt):
fun calculateDeliveredAt(orderProgress, vehicleDeliveredAt, fulfillmentMethod): OrderProgressState {val init = initOrderProgress(orderProgress, fulfillmentMethod)return init.copy(vehicleDeliveredAt = vehicleDeliveredAt,vehiclePreparedAt = init.vehiclePreparedAt ?: vehicleDeliveredAt, // โ back-fillcontractsCompleteAt = init.contractsCompleteAt ?: vehicleDeliveredAt, // โ back-fillorderConfirmedAt = init.orderConfirmedAt ?: vehicleDeliveredAt, // โ back-fill)}// calculatePickedUpAt does the identical back-fill of vehiclePreparedAt.
So in practice vehiclePreparedAt only ever gets a value at the VEHICLE_DELIVERED / VEHICLE_PICKED_UP moment, timestamped at the delivery/pickup time (not at an actual "vehicle prepared" moment).
#5.3 What this means for the customer's bar
- Before delivery: the "Vehicle Prepared" stage shows as the current/upcoming step (its timestamp is null), even though the car may genuinely be prepared.
- At delivery/pickup: "Vehicle Prepared" and "Vehicle Delivered/Picked Up" both flip to complete together, sharing the delivery timestamp.
#5.4 How to make it light up at the right time (the fix)
The pipeline is already built for it โ only the producer is missing. To drive VEHICLE_PREPARED properly, Salesforce needs a status that maps to it, e.g. add to VehicleTriggerHandler.statusToTrackerPhaseMapVehicles:
'Ready for Delivery' => 'VEHICLE_PREPARED', // or whatever the real Vehicle status name is
Once a Vehicle status change emits VEHICLE_PREPARED, the existing chain (applyVehiclePrepared โ calculateVehiclePreparedAt โ UI) lights the stage at the correct moment, and the back-fill simply stops being the only source. Same applies to DELIVERY_DATE_UPDATE (needs an Apex path that sets targetDate__c).
๐ Takeaway: "Vehicle Prepared" is a downstream-ready, producer-pending stage. It's not broken โ back-fill guarantees the bar is never left with a gap โ but today it can only ever complete retroactively at delivery, not in real time. That's the gap to close on the Salesforce side.
#6. โ Deep-dive TL;DR
GraphQL: cart-service is a Netflix-DGS server, but the tracker bar is REST-only (
GET cart/v1/ordersโ fullOrderProgressState). The one GraphQL query,getCurrentCart, returnsCart+OrderDetails(a Cash/Finance/Lease/InterestedInLease union of cost data) +CartHints. The only order-domain field GraphQL surfaces isOrderHints.orderNumber;statusHint(cart lifecycle) andsourceAction(last change) round out the hints. No progress timestamps in GraphQL. (Security note:/ordersis.authenticated(), but the/graphqlHTTP route is stillpermitAllwith a TODO โ resolver-level@Secured+ JWT still apply.)Salesforce producer: three publishers, all ending in
EventBus.publish(Order_Tracker_Event__e)โCaseTriggerHandler(Case status โ phase viastatusToTrackerPhaseMapCases, incl.RETURN_TO_MANAGER),VehicleTriggerHandler(Vehicle status โDELIVERY_SCHEDULED/VEHICLE_IN_TRANSIT/VEHICLE_DELIVERED), andDealStatusController.emitOrderCancelledEvent(ORDER_CANCELLED, from a Flow invocable or an LWC button). Fields:userIdfromAccount.User_Id__c,caseTypemapped ShopโSHOP etc.,fulfillmentMethodfrom the Case RecordType (PICK_UPโ IN_STORE_PICKUP). NoTrackerPhaseResolverclass exists (earlier guess was wrong). The producer emits a subset of the 15 phases โVEHICLE_PREPAREDandDELIVERY_DATE_UPDATEhave no producer mapping in this repo, andORDER_COMPLETED/OUT_FOR_DELIVERYare explicitly removed no-ops.ROAM: not present locally (only an unrelated Products-API Postman file mentions "Roam"). By contract it's a pull-based cart-service client โ Auth0 JWT โ
GET cart/v1/ordersโ render the bar fromprogressState. Share the repo and I'll verify its real network layer.
Sources: cart-service (schema/*.graphqls, graphql/query/CartQueries.kt, graphql/fetchers/{OrderDetails,OrderHints,StatusHint,SourceAction,Cart}Fetcher.kt, graphql/conversions/*, config/SecurityConfiguration.kt), Salesforce-FreewayCRM (classes/CaseTriggerHandler.cls, VehicleTriggerHandler.cls, DealStatusController.cls, DealStatusInvocableAction_Dynamic.cls + tests), UI (apis/cartServices/graphQueries/*). ROAM described from integration contract โ no local source found.