Skip to content
Back to Articles

Products, Combinations and Stock in PrestaShop: how they really connect

Product exports, ERP integrations & stock sync
SQL
SELECT
p.id_product,
p.reference,
sa.quantity
FROM ps_product p
JOIN ps_stock_available sa
ON sa.id_product = p.id_product
WHERE p.active = 1;
Data & Database
Intermediate
PrestaHacks 3 min read

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

TEXT
ps_product
    ↓
ps_stock_available

For a simple product:

TEXT
id_product_attribute = 0

2. Product with combinations

TEXT
ps_product
      ↓
ps_product_attribute
      ↓
ps_stock_available

3. Where do attributes live?

TEXT
ps_product_attribute
          ↓
ps_product_attribute_combination
          ↓
ps_attribute
          ↓
ps_attribute_lang

4. Example catalogue

TEXT
PRODUCT
Basic T-Shirt
id_product: 42
reference: TSHIRT-BASIC

COMBINATIONS
101 → TSHIRT-BLK-S
102 → TSHIRT-BLK-M
103 → TSHIRT-BLK-L

5. Where is stock actually stored?

Simple product:

TEXT
id_product = 42
id_product_attribute = 0
quantity = 19

Combination:

TEXT
id_product = 42
id_product_attribute = 103
quantity = 7

6. Simple products and stock

SQL
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

SQL
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:

TEXT
Basic T-Shirt | TSHIRT-BASIC | 19.90

may need to become:

TEXT
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 | 7

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

TEXT
/api/products
       ↓
/api/combinations
       ↓
/api/stock_availables
       ↓
usable stock dataset

12. Multistore

Stock also has shop context in multistore setups.

13. Write the dataset specification first

TEXT
ONE ROW PER:
Combination

FIELDS:
Product ID
Combination ID
Product name
Combination reference
EAN
Price
Stock

LANGUAGE:
English

SHOP:
Shop 1

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

STAY TUNED

Get practical PrestaShop hacks in your inbox.

INACTIVE