01 · Business Context
#The customer-facing problem
When a customer puts a vehicle in their cart on driveway.com, the price they were looking at gets locked. Later changes to the live price don't affect them — they pay what they agreed to.
But the SRP (Search Results Page) sort wasn't aware of this. If a customer:
- Saw a Honda Civic at $28,000 and added it to their cart
- The dealer dropped the live price to $24,000 the next day
- The customer came back and sorted by "Lowest Price"
…the card would correctly show their locked $28k — but the sort position would put the vehicle in the $24k slot. Cards and sort positions disagreed → confusing UX → customer trust hit.
#Where the "locked price" comes from
When the customer adds the vehicle to their cart, the cart-service publishes
a CartStatusUpdateNotificationMessage to the Azure Service Bus topic
cart-status-update-topic. The message carries the price the customer saw:
data class CartStatusUpdateNotificationMessage(val vin: String,val orderSubmitted: Boolean,val purchasePending: Boolean,@Deprecated("Replaced by purchasePriceWithFeesInCents")val purchasePriceInCents: Int? = null,val purchasePriceWithFeesInCents: Int? = null // ← the locked price (with fees))
Odyssey's availability service consumes the message and writes the values
into MongoDB:
// MongoVehicleDaoImpl.upsertAvailabilityFlags(...)mongoCollection.updateOne(Vehicle::vin eq vin,combine(...availability flags...,setValue(Vehicle::frozenPriceInCents, frozenPriceInCents),setValue(Vehicle::frozenPriceWithFeesInCents, frozenPriceWithFeesInCents)))
After this, the vehicleV3 document for that VIN has the locked price
stored on it.
#The Feature AC
From the parent feature ticket:
SRP, VDP, Favorites, Cart, and Order Tracker receive the correct pricing value based on vehicle state: If vehicle is Sale Pending for the customer's in-progress transaction, the locked Sale Pending price is returned.
This story is the SRP-sort piece of that AC. The other consumers (VDP,
Favorites, Cart, Order Tracker) are already covered by separate work that
made frozenPriceWithFeesInCents available in GraphQL responses.
#The "with fees" piece — important context
The original ticket talks about frozenPriceInCents, but the actual current
field is frozenPriceWithFeesInCents. Same data, different unit:
frozenPriceInCents(deprecated): just the raw locked pricefrozenPriceWithFeesInCents(current): locked price + document fees, matching the all-in price the customer saw on the card
The reason for the rename is the same one that made inStatePriceWithFees
and outStatePriceWithFees replace price: Driveway shows customers the
total they'll pay, not a raw sticker. Every field that participates in the
displayed price has a *WithFees* variant.
#Why this is a config-only story
No Kotlin code changes are needed. The data flow already exists end-to-end (cart-service → ASB → availability service → Mongo). Only two config artifacts need updating:
- The Atlas Search index mapping (declared in Terraform) — to make
frozenPriceWithFeesInCentsindexable. - The 4
searchScoreWeightsMongo documents that drive the four price-sort options — to add a new "frozen price wins" branch.
Both are reversible without a deploy.
#Out of scope for this ticket
- Audi/BMW MSRP behavior stays exactly as it is today. Audi/BMW new vehicles contractually must sort by MSRP, regardless of frozen price.
SHIPPING_FEE_LOWESTandRECOMMENDED's shipping placeholder still referencedealer.stateShippingMap.<USER_STATE>. ThestateShippingMapfield is not deprecated, so this is a separate concern for whoever owns shipping-cost sorting.- The availability gate (
+10,000bonus when all 4 availability flags are false) is not modified. A side effect: a vehicle the customer has in their own cart haspurchasePending=true→ fails the gate → loses the bonus → sinks below available vehicles even with the frozen-price fix. This is a known issue worth flagging to product but is outside this ticket's scope.