Skip to main content

Cart Field System

The cart field system is the foundation of EverShop's checkout logic. Every piece of data on a cart — from the subtotal and tax amount to the shipping address and coupon code — is defined as a field with its own calculation logic. Extensions can add new fields to inject custom data or business logic into the cart.

How Cart Fields Work

Each cart field is an object with three properties:

{
key: string; // Field name (e.g., 'sub_total', 'tax_amount')
resolvers: Function[]; // Array of functions that calculate the field's value
dependencies?: string[]; // Other fields this field depends on
}

When the cart is loaded or updated, EverShop:

  1. Sorts fields by their dependencies (topological sort).
  2. For each field, runs its resolvers in order.
  3. The final resolver's return value becomes the field's value.

Field Resolvers

Resolvers are functions that calculate a field's value. Inside a resolver, this gives you access to the cart (or cart item) data:

{
key: 'sub_total',
resolvers: [
async function resolver() {
// Access cart data via 'this'
const items = this.getItems();
let subTotal = 0;
for (const item of items) {
subTotal += item.getData('final_price') * item.getData('qty');
}
return subTotal;
}
],
dependencies: ['items'] // Depends on items being calculated first
}

Context Methods Available in Resolvers

Inside a cart field resolver, this provides:

MethodDescription
this.getData(key)Get a field's current value
this.setData(key, value)Set a field's value
this.getItems()Get all cart items
this.setError(field, message)Set a validation error on a field
this.getTriggeredField()Get which field triggered the recalculation

Inside a cart item field resolver, this provides:

MethodDescription
this.getData(key)Get the item field's current value
this.setData(key, value)Set an item field's value
this.setError(field, message)Set a validation error
this.getProduct()Get the product data for this item

Adding Custom Cart Fields

Register custom cart fields in your extension's bootstrap.ts using the cartFields processor:

extensions/my-ext/src/bootstrap.ts
import { addProcessor } from '@evershop/evershop/lib/util/registry';

export default () => {
addProcessor('cartFields', (fields) => {
return fields.concat([
{
key: 'gift_message',
resolvers: [
async function resolver() {
// Return existing value or empty string
return this.getData('gift_message') || '';
}
]
},
{
key: 'gift_wrap_fee',
resolvers: [
async function resolver() {
const hasGiftWrap = this.getData('gift_wrap');
return hasGiftWrap ? 5.00 : 0;
}
],
dependencies: ['sub_total'] // Calculate after subtotal
}
]);
});
};

Adding Custom Cart Item Fields

Similarly, use the cartItemFields processor:

extensions/my-ext/src/bootstrap.ts
import { addProcessor } from '@evershop/evershop/lib/util/registry';

export default () => {
addProcessor('cartItemFields', (fields) => {
return fields.concat([
{
key: 'personalization_text',
resolvers: [
async function resolver() {
return this.getData('personalization_text') || '';
}
]
}
]);
});
};

Field Dependencies

The dependencies array ensures fields are calculated in the correct order. If field B depends on field A, field A is always calculated first:

// Calculated first
{ key: 'sub_total', resolvers: [...] }

// Calculated second (depends on sub_total)
{ key: 'discount_amount', resolvers: [...], dependencies: ['sub_total'] }

// Calculated third (depends on both)
{ key: 'grand_total', resolvers: [...], dependencies: ['sub_total', 'discount_amount'] }
warning

Circular dependencies (A depends on B, B depends on A) will cause an error during cart calculation.

Built-in Cart Fields

EverShop registers these cart fields by default:

FieldDescription
cart_idDatabase ID
uuidUnique cart identifier
currencyCart currency from config
customer_emailCustomer email address
sub_totalSum of all item prices
sub_total_incl_taxSubtotal including tax
tax_amountCalculated tax
discount_amountApplied discount
grand_totalFinal total
shipping_fee_excl_taxShipping cost before tax
shipping_fee_incl_taxShipping cost after tax
shipping_methodSelected shipping method code
payment_methodSelected payment method code
couponApplied coupon code
total_qtyTotal quantity of items
total_weightTotal weight of items

Built-in Cart Item Fields

FieldDescription
cart_item_idDatabase ID
uuidUnique item identifier
product_idProduct reference
product_skuProduct SKU
product_nameProduct display name
qtyQuantity (validated against stock)
product_priceUnit price
final_pricePrice after discounts
tax_percentTax percentage
tax_amountItem tax amount
discount_amountItem discount
totalLine total (qty * final_price)

Stock Validation

Cart item fields automatically validate quantities against product inventory:

  • If manage_stock is enabled and qty exceeds available stock, an error is set on the item.
  • If the product is out of stock, an error is set immediately.
  • These errors are tracked per-item and can be queried.

See Also



Support us


EverShop is an open-source project that relies on community support. If you find our project useful, please consider sponsoring us.