Skip to main content
Version: 2.0.0

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:

FieldSource
Billing / shipping addressSaved from checkout form to quote, copied at conversion
Shipping methodshipping_method_id + shipping_amount on the quote
Payment methodpayment_method_id + payment_amount on the quote
Customer notenote column on the quote
Discount / couponcoupon_code + discount_amount on the quote
Grand totalgrand_total on the quote (recalculated at each change)

Cart → Quote flow

  1. Customer adds a product: QuoteService::addItem() registers an empty quote (by cart_id) if one does not already exist, then calls updateItem().
  2. updateItem() resolves pricing (tier price, attribute price, gift card value), tax, and weight, then upserts a QuoteItemRecord.
  3. Each save triggers EVENT_AFTER_QUOTE_ITEM_UPDATE.
  4. 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.
  5. At order placement, the quote's is_order flag is set to 1, order_id and increment_id are written, and the quote is locked.

Item types

TypeDescription
simpleStandard physical product
variantA specific product variant (colour, size, etc.)
configurableBundle with child items; price is the sum of children
digitalNo 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 currency
  • price_incl_tax / price_excl_tax — derived from the applicable tax category
  • row_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())

MethodDescription
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

KeyTypeDescription
variantIdintTarget a specific product variant
configurationarrayChild SKU+qty pairs for configurable products
customDataarrayArbitrary JSON data stored on the item
minQtyintOverride minimum purchase quantity
entryIdintContext entry ID (for remote entry-bound products)
attributeMatrixarrayAttribute matrix coordinates
giftCardValuemixedCustom 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:

MethodDescription
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.