Skip to main content
An offer is a store’s listing of one master product variant. The catalog product belongs to the marketplace, and the offer holds the store’s commercial terms on top of it: SKU, barcodes, condition, shipping profile, prices, and stock. You need this split in mind before you build anything that sells, because carts, orders, commissions, and payouts all follow the offer, not the product.

The offer record

The Offer data model (table offer, id prefix offer) is a thin row that points at catalog records by id. Prices and inventory aren’t columns on it: they attach through module links. The row carries these groups of fields:
  • Ownership: seller_id is the store, and created_by is the member who created the offer
  • Catalog pointers: variant_id and product_id, where product_id is read from the variant when the offer is created
  • Identity: sku, plus optional ean and upc barcodes copied from the variant when you leave them out
  • Selling terms: shipping_profile_id, manage_inventory (default true), allow_backorder (default false), and leadtime_to_ship
  • Condition: an optional condition_id that points at an OfferCondition
This query reads one offer with its store and master variant. seller resolves through the offer_seller link table, which createOffersWorkflow writes next to seller_id; product_variant resolves through a read-only link on variant_id.

Offers and master products

A master variant can back any number of offers. Each store that sells the variant holds its own offer, and the variant itself never changes when a store lists, prices, or stocks it. The same store can also list a variant more than once, for example a new and a refurbished copy. The module doesn’t limit offers per variant. The only uniqueness rule is the SKU.
A SKU is unique within a store: the index on (seller_id, sku) applies while deleted_at is null. Two stores can use the same SKU string, and a soft-deleted offer frees its SKU.

Offer conditions

An offer condition describes the physical state an offer is sold in. Operators manage conditions, and stores pick one when they create or update an offer. The OfferCondition model (id prefix ofcond) has a unique code, a display label, an is_active flag, and a rank that orders the list. The create and update workflows check every condition_id they receive:
  • Unknown id: the run fails with a not found error
  • Inactive condition: the run fails, so a deactivated condition can’t be assigned to new or edited offers
  • Condition in use: deleteOfferConditionsWorkflow refuses to delete a condition while any offer still uses it
Deactivating a condition leaves the offers already listed under it unchanged.

Grouping offers by store

A store’s offers on one product usually mirror that product’s variants. The service can collapse them into one row per product and store. When you pass group_by_seller: true to listOffers or listAndCountOffers, the service returns the newest offer of each (product_id, seller_id) group and sets two computed fields on it:
  • variant_count: how many offers the store has on that product
  • offer_ids: the ids of all offers in the group
Only product_id and seller_id filters apply in grouped mode.