Cart item schema with price snapshot for consistency.
When a product is added to the cart, we snapshot the current price and product details. This ensures that:
- Price changes after adding don't affect the cart total unexpectedly
- If the product is deleted, we still have the title and other info
- We can show users when prices have changed since they added items
Fields
cart_uuid- Reference to the cart (required)product_uuid- Reference to the product (nullable, ON DELETE SET NULL)product_title- Product title snapshot (required)product_slug- Product slug snapshotproduct_sku- Product SKU snapshotproduct_image- Product image URL snapshotunit_price- Price per unit at time of adding (required), frozen in the CART's own currency (§4.3.1, §4.4, §12.1)compare_at_price- Original price for showing discounts, frozen the same way and at the same rate asunit_price(§4.3.1) — never a raw base amount alongside an already-convertedunit_price, or the displayed discount misstates itselfquantity- Number of items (required, > 0)line_total- Calculated: unit_price * quantityweight_grams- Weight for shipping calculationtaxable- Whether item is taxableselected_specs- JSON object for specification-based pricing (e.g., {"material": "PETG", "color": "Gold"})
Summary
Functions
Changeset for cart item creation and updates.
Returns discount percentage for sale items.
Creates changeset attributes from a product.
Returns true if this item is on sale (has compare_at_price > unit_price).
Returns the price difference if the product price has changed. Positive = price increased, Negative = price decreased.
Returns true if product data has changed since the item was added. Useful for showing price change warnings.
Returns true if the product has been deleted (product_uuid is nil
after ON DELETE SET NULL).
Functions
Changeset for cart item creation and updates.
Returns discount percentage for sale items.
Creates changeset attributes from a product.
Parameters
product- The Product structquantity- Number of items (default: 1)language- Language code for localized fields (default: system default)
Examples
iex> from_product(product, 2)
%{
product_uuid: "01234567-...",
product_title: "Widget",
product_slug: "widget",
unit_price: Decimal.new("19.99"),
quantity: 2,
...
}
iex> from_product(product, 1, "ru")
%{product_title: "Виджет", product_slug: "vidzhet", ...}
Returns true if this item is on sale (has compare_at_price > unit_price).
Returns the price difference if the product price has changed. Positive = price increased, Negative = price decreased.
Returns true if product data has changed since the item was added. Useful for showing price change warnings.
Returns true if the product has been deleted (product_uuid is nil
after ON DELETE SET NULL).
Catalogue-backed lines never store product_uuid — their identity is
metadata["catalogue_item_uuid"] — so a nil uuid is not a deletion
signal for those.