Quotes (Cart)
A quote is the internal representation of a shopping cart. Every time a customer adds a product to the cart, yStore creates or updates a quote record. When the customer completes checkout, the quote is converted into an order.
The lifecycle is: cart (quote, is_order = 0) → checkout → order (is_order = 1, order_id set).
Admin view
Admins do not have a dedicated "Quotes" list page. Active (not-yet-ordered) quotes are visible indirectly when editing orders that were recently placed. All order details are derived from the underlying quote at conversion time.
The key fields visible on a converted order that originate from the quote:
| Field | Source |
|---|---|
| Billing / shipping address | Saved from checkout form to quote, copied at conversion |
| Shipping method | shipping_method_id + shipping_amount on the quote |
| Payment method | payment_method_id + payment_amount on the quote |
| Customer note | note column on the quote |
| Discount / coupon | coupon_code + discount_amount on the quote |
| Grand total | grand_total on the quote (recalculated at each change) |
Cart → Quote flow
- Customer adds a product:
QuoteService::addItem()registers an empty quote (bycart_id) if one does not already exist, then callsupdateItem(). updateItem()resolves pricing (tier price, attribute price, gift card value), tax, and weight, then upserts aQuoteItemRecord.- Each save triggers
EVENT_AFTER_QUOTE_ITEM_UPDATE. - During checkout, the browser sends incremental field changes to
QuoteService::autoSave()which saves address, shipping, and payment data back to the quote and returns updated available methods. - At order placement, the quote's
is_orderflag is set to1,order_idandincrement_idare written, and the quote is locked.
Item types
| Type | Description |
|---|---|
simple | Standard physical product |
variant | A specific product variant (colour, size, etc.) |
configurable | Bundle with child items; price is the sum of children |
digital | No shipping weight; ships digitally |
Products with zero weight are automatically treated as digital unless they have a special type.
Pricing storage
All quote item prices are stored in the base currency (minor units, e.g. cents). Display currencies are converted at render time. This allows currency switching without data loss.
Each item stores:
price— unit price in minor units of the base currencyprice_incl_tax/price_excl_tax— derived from the applicable tax categoryrow_total/row_total_price_incl_tax/row_total_price_excl_tax— quantity × unit price
Discount calculation
Discounts (coupons and gift cards) are resolved by QuoteHelper::calculateDiscounts(). The result is persisted as QuoteCouponRecord snapshots and applied to quote.discount_amount during QuoteService::recalculate().
The QuoteCalculateDiscountsEvent fires at the end of every discount calculation so plugins can inject additional discounts or modify the resolved set.
Developer reference
Service
yui\craft\services\sales\QuoteService (access via Plugin::getInstance()->getQuote())
| Method | Description |
|---|---|
addItem($cartId, $product, $itemQty, $siteId, $options) | Add a product to the cart by cart ID |
updateItem($product, $quote, $itemQty, $options) | Upsert a quote item for the given product and quote |
updateQuoteItem($quoteItemId, $qty, $customData, $recalculate) | Change quantity (or set to 0 to remove) |
removeItem($item) | Remove a QuoteItemRecord |
recalculate($quote) | Recalculate totals on the given quote record |
recalculateItems($quoteId, $itemIds, $fromQuoteItem) | Recalculate specific items |
autoSave($cartId, $request) | Save checkout form data and return available methods |
getQuoteValue() | Return the current grand total |
Options accepted by addItem / updateItem
| Key | Type | Description |
|---|---|---|
variantId | int | Target a specific product variant |
configuration | array | Child SKU+qty pairs for configurable products |
customData | array | Arbitrary JSON data stored on the item |
minQty | int | Override minimum purchase quantity |
entryId | int | Context entry ID (for remote entry-bound products) |
attributeMatrix | array | Attribute matrix coordinates |
giftCardValue | mixed | Custom gift card face value |
Events
All events are triggered on QuoteService. Register listeners with EventManager::listen().
QuoteService::EVENT_AFTER_QUOTE_ITEM_UPDATE
Fires after any item is added, updated, or removed.
use yui\craft\support\EventManager;
use yui\craft\services\sales\QuoteService;
use yui\craft\events\QuoteItemUpdateEvent;
EventManager::listen(
QuoteService::class,
QuoteService::EVENT_AFTER_QUOTE_ITEM_UPDATE,
function (QuoteItemUpdateEvent $event) {
// $event->quote is the QuoteRecord that was modified
$quote = $event->quote;
}
);
QuoteService::EVENT_AFTER_QUOTE_METHOD_UPDATE
Fires after a shipping or payment method is changed on the quote.
use yui\craft\services\sales\QuoteService;
use yui\craft\events\QuoteMethodUpdateEvent;
EventManager::listen(
QuoteService::class,
QuoteService::EVENT_AFTER_QUOTE_METHOD_UPDATE,
function (QuoteMethodUpdateEvent $event) {
$quote = $event->quote;
}
);
QuoteCalculateDiscountsEvent
Fires at the end of QuoteHelper::calculateDiscounts(). Use it to inject additional discounts.
use yui\craft\services\CheckoutService;
use yui\craft\events\QuoteCalculateDiscountsEvent;
EventManager::listen(
CheckoutService::class,
CheckoutService::EVENT_QUOTE_CALCULATE_DISCOUNTS,
function (QuoteCalculateDiscountsEvent $event) {
// $event->quote — QuoteModel
// $event->quoteItems — array of QuoteItemModel
// $event->discounts — current discount array; modify to add/remove entries
$event->discounts[] = [
'amount' => ['value' => 5.00, 'type' => 'fixed', 'currency' => 'EUR'],
'label' => 'My custom discount',
'type' => 'custom',
'apply_to' => 'quote',
];
}
);
QuoteQuickSaveEvent
Fires during autoSave() (checkout form incremental save) when the quote is saved successfully. Use it to react to in-progress checkout data.
Helper
yui\craft\helpers\QuoteHelper provides static utilities:
| Method | Description |
|---|---|
registerEmptyQuote($cartId, $siteId) | Find or create a blank quote for a cart session |
getQuoteByCartId($cartId, $siteId) | Load a quote by cart session ID |
getQuoteByUserId($userId, $siteId) | Load the active (non-ordered) quote for a logged-in customer |
calculateDiscounts($quote, $quoteItems) | Resolve all applicable coupons and gift cards |
generateOrderIncrementIdFromQuote($siteId) | Atomically generate the next order number |
getCompanyDetailsFromQuote($quote) | Extract B2B company/ICO/DIC fields from the billing or shipping address |
Interface
yui\craft\contracts\QuoteServiceInterface — implement this interface if you need to substitute the default service.