Products, Combinations and Stock in PrestaShop: how they really connect
The request sounds simple: “Give me every product with SKU and stock.”
Then you open the database or Webservice and discover that a product may have combinations, the real SKU can live at variant level and stock belongs to another entity.
1. Simple product
ps_product
↓
ps_stock_availableFor a simple product:
id_product_attribute = 02. Product with combinations
ps_product
↓
ps_product_attribute
↓
ps_stock_available3. Where do attributes live?
ps_product_attribute
↓
ps_product_attribute_combination
↓
ps_attribute
↓
ps_attribute_lang4. Example catalogue
PRODUCT
Basic T-Shirt
id_product: 42
reference: TSHIRT-BASIC
COMBINATIONS
101 → TSHIRT-BLK-S
102 → TSHIRT-BLK-M
103 → TSHIRT-BLK-L5. Where is stock actually stored?
Simple product:
id_product = 42
id_product_attribute = 0
quantity = 19Combination:
id_product = 42
id_product_attribute = 103
quantity = 76. Simple products and stock
SELECT
p.id_product,
p.reference,
pl.name,
sa.quantity
FROM ps_product p
INNER JOIN ps_product_lang pl
ON pl.id_product = p.id_product
AND pl.id_lang = 1
AND pl.id_shop = 1
LEFT JOIN ps_stock_available sa
ON sa.id_product = p.id_product
AND sa.id_product_attribute = 0
WHERE p.active = 1;7. Combination stock
SELECT
p.id_product,
pl.name AS product_name,
pa.id_product_attribute,
pa.reference AS combination_reference,
sa.quantity
FROM ps_product p
INNER JOIN ps_product_lang pl
ON pl.id_product = p.id_product
AND pl.id_lang = 1
AND pl.id_shop = 1
INNER JOIN ps_product_attribute pa
ON pa.id_product = p.id_product
LEFT JOIN ps_stock_available sa
ON sa.id_product = pa.id_product
AND sa.id_product_attribute = pa.id_product_attribute
WHERE p.active = 1
ORDER BY p.id_product, pa.id_product_attribute;8. Why product-only exports can be wrong
One parent row:
Basic T-Shirt | TSHIRT-BASIC | 19.90may need to become:
Basic T-Shirt / Black / S | TSHIRT-BLK-S | 19.90 | 4
Basic T-Shirt / Black / M | TSHIRT-BLK-M | 19.90 | 8
Basic T-Shirt / Black / L | TSHIRT-BLK-L | 19.90 | 79. Product-level or combination-level identifier?
Decide whether the dataset is one row per product or one row per combination before writing the export.
10. EAN / UPC / MPN
Combinations can have their own identification fields. Do not assume parent-level identifiers represent every variant.
11. Webservice mental model
/api/products
↓
/api/combinations
↓
/api/stock_availables
↓
usable stock dataset12. Multistore
Stock also has shop context in multistore setups.
13. Write the dataset specification first
ONE ROW PER:
Combination
FIELDS:
Product ID
Combination ID
Product name
Combination reference
EAN
Price
Stock
LANGUAGE:
English
SHOP:
Shop 1Official references
- https://devdocs.prestashop-project.org/9/faq/stock/
- https://devdocs.prestashop-project.org/9/webservice/resources/products/
- https://devdocs.prestashop-project.org/9/webservice/resources/combinations/
- https://devdocs.prestashop-project.org/9/webservice/resources/stock_availables/
Where to go from here
Use this relationship model to build catalogue reports with explicit SQL joins. For API writes, carry the same product/combination distinction into the safe Webservice update workflow.