381 lines
9.9 KiB
SQL
381 lines
9.9 KiB
SQL
-- +goose Up
|
|
DELIMITER //
|
|
DROP PROCEDURE IF EXISTS get_full_product
|
|
//
|
|
CREATE PROCEDURE get_full_product(
|
|
IN p_id_product INT UNSIGNED,
|
|
IN p_id_shop INT UNSIGNED,
|
|
IN p_id_lang INT UNSIGNED,
|
|
IN p_id_customer INT UNSIGNED,
|
|
IN b2b_id_country INT UNSIGNED,
|
|
IN p_quantity INT UNSIGNED
|
|
)
|
|
BEGIN
|
|
DECLARE v_tax_rate DECIMAL(10, 4) DEFAULT 0;
|
|
DECLARE p_id_currency DECIMAL(10, 4) DEFAULT 0;
|
|
SELECT
|
|
COALESCE(t.rate, 0.0000) INTO v_tax_rate
|
|
FROM
|
|
ps_tax_rule tr
|
|
INNER JOIN ps_tax t ON t.id_tax = tr.id_tax
|
|
LEFT JOIN b2b_countries ON b2b_countries.id = b2b_id_country
|
|
WHERE
|
|
tr.id_tax_rules_group = (
|
|
SELECT
|
|
ps.id_tax_rules_group
|
|
FROM
|
|
ps_product_shop ps
|
|
WHERE
|
|
ps.id_product = p_id_product
|
|
AND ps.id_shop = p_id_shop
|
|
LIMIT
|
|
1
|
|
)
|
|
AND tr.id_country = b2b_countries.ps_id_country
|
|
ORDER BY
|
|
tr.id_state DESC,
|
|
tr.zipcode_from != '' DESC,
|
|
tr.id_tax_rule DESC
|
|
LIMIT
|
|
1;
|
|
|
|
SELECT
|
|
b2b_currencies.ps_id_currency INTO p_id_currency
|
|
FROM
|
|
b2b_currencies
|
|
LEFT JOIN b2b_countries ON b2b_countries.b2b_id_currency = b2b_currencies.id
|
|
WHERE
|
|
b2b_countries.id = b2b_id_country
|
|
LIMIT 1;
|
|
|
|
/* FINAL JSON */
|
|
SELECT
|
|
JSON_OBJECT(
|
|
/* ================= PRODUCT ================= */
|
|
'id_product',
|
|
p.id_product,
|
|
'reference',
|
|
p.reference,
|
|
'name',
|
|
pl.name,
|
|
'description',
|
|
pl.description,
|
|
'short_description',
|
|
pl.description_short,
|
|
/* ================= PRICE ================= */
|
|
'price',
|
|
JSON_OBJECT(
|
|
'base',
|
|
COALESCE(ps.price * r.conversion_rate, p.price * r.conversion_rate),
|
|
|
|
'final_tax_excl',
|
|
(
|
|
CASE
|
|
WHEN bsp.id IS NOT NULL THEN
|
|
CASE
|
|
/* FIXED PRICE */
|
|
WHEN bsp.reduction_type = 'amount' THEN
|
|
(
|
|
CASE
|
|
WHEN bsp.b2b_id_currency IS NULL THEN bsp.price
|
|
ELSE bsp.price * br_bsp.conversion_rate
|
|
END
|
|
)
|
|
|
|
/* PERCENTAGE */
|
|
WHEN bsp.reduction_type = 'percentage' THEN
|
|
COALESCE(ps.price * r.conversion_rate, p.price * r.conversion_rate)
|
|
* (1 - bsp.percentage_reduction / 100)
|
|
|
|
ELSE
|
|
COALESCE(ps.price * r.conversion_rate, p.price * r.conversion_rate)
|
|
END
|
|
|
|
ELSE
|
|
COALESCE(ps.price * r.conversion_rate, p.price * r.conversion_rate)
|
|
END
|
|
),
|
|
|
|
'final_tax_incl',
|
|
(
|
|
(
|
|
CASE
|
|
WHEN bsp.id IS NOT NULL THEN
|
|
CASE
|
|
WHEN bsp.reduction_type = 'amount' THEN
|
|
(
|
|
CASE
|
|
WHEN bsp.b2b_id_currency IS NULL THEN bsp.price
|
|
ELSE bsp.price * br_bsp.conversion_rate
|
|
END
|
|
)
|
|
|
|
WHEN bsp.reduction_type = 'percentage' THEN
|
|
COALESCE(ps.price * r.conversion_rate, p.price * r.conversion_rate)
|
|
* (1 - bsp.percentage_reduction / 100)
|
|
|
|
ELSE
|
|
COALESCE(ps.price * r.conversion_rate, p.price * r.conversion_rate)
|
|
END
|
|
ELSE
|
|
COALESCE(ps.price * r.conversion_rate, p.price * r.conversion_rate)
|
|
END
|
|
) * (1 + v_tax_rate / 100)
|
|
)
|
|
),
|
|
/* ================= META ================= */
|
|
'active',
|
|
COALESCE(ps.active, p.active),
|
|
'visibility',
|
|
COALESCE(ps.visibility, p.visibility),
|
|
'manufacturer',
|
|
m.name,
|
|
'category',
|
|
cl.name,
|
|
/* ================= IMAGE ================= */
|
|
'cover_image',
|
|
JSON_OBJECT(
|
|
'id',
|
|
i.id_image,
|
|
'legend',
|
|
il.legend
|
|
),
|
|
/* ================= FEATURES ================= */
|
|
'features',
|
|
(
|
|
SELECT
|
|
JSON_ARRAYAGG(
|
|
JSON_OBJECT(
|
|
'name',
|
|
fl.name,
|
|
'value',
|
|
fvl.value
|
|
)
|
|
)
|
|
FROM
|
|
ps_feature_product fp
|
|
JOIN ps_feature_lang fl ON fl.id_feature = fp.id_feature
|
|
AND fl.id_lang = p_id_lang
|
|
JOIN ps_feature_value_lang fvl ON fvl.id_feature_value = fp.id_feature_value
|
|
AND fvl.id_lang = p_id_lang
|
|
WHERE
|
|
fp.id_product = p.id_product
|
|
),
|
|
/* ================= COMBINATIONS ================= */
|
|
'combinations',
|
|
(
|
|
SELECT
|
|
JSON_ARRAYAGG(
|
|
JSON_OBJECT(
|
|
'id_product_attribute',
|
|
pa.id_product_attribute,
|
|
'reference',
|
|
pa.reference,
|
|
'price',
|
|
JSON_OBJECT(
|
|
'impact',
|
|
COALESCE(pas.price, pa.price),
|
|
'final_tax_excl',
|
|
(
|
|
COALESCE(ps.price, p.price) + COALESCE(pas.price, pa.price)
|
|
),
|
|
'final_tax_incl',
|
|
(
|
|
(
|
|
COALESCE(ps.price, p.price) + COALESCE(pas.price, pa.price)
|
|
) * (1 + v_tax_rate / 100)
|
|
)
|
|
),
|
|
'stock',
|
|
IFNULL(sa.quantity, 0),
|
|
'default_on',
|
|
pas.default_on,
|
|
/* ATTRIBUTES JSON */
|
|
'attributes',
|
|
(
|
|
SELECT
|
|
JSON_ARRAYAGG(
|
|
JSON_OBJECT(
|
|
'group',
|
|
agl.name,
|
|
'attribute',
|
|
al.name
|
|
)
|
|
)
|
|
FROM
|
|
ps_product_attribute_combination pac
|
|
JOIN ps_attribute a ON a.id_attribute = pac.id_attribute
|
|
JOIN ps_attribute_lang al ON al.id_attribute = a.id_attribute
|
|
AND al.id_lang = p_id_lang
|
|
JOIN ps_attribute_group_lang agl ON agl.id_attribute_group = a.id_attribute_group
|
|
AND agl.id_lang = p_id_lang
|
|
WHERE
|
|
pac.id_product_attribute = pa.id_product_attribute
|
|
),
|
|
/* IMAGES */
|
|
'images',
|
|
(
|
|
SELECT
|
|
JSON_ARRAYAGG(img.id_image)
|
|
FROM
|
|
ps_product_attribute_image pai
|
|
JOIN ps_image img ON img.id_image = pai.id_image
|
|
WHERE
|
|
pai.id_product_attribute = pa.id_product_attribute
|
|
)
|
|
)
|
|
)
|
|
FROM
|
|
ps_product_attribute pa
|
|
JOIN ps_product_attribute_shop pas ON pas.id_product_attribute = pa.id_product_attribute
|
|
AND pas.id_shop = p_id_shop
|
|
LEFT JOIN ps_stock_available sa ON sa.id_product = pa.id_product
|
|
AND sa.id_product_attribute = pa.id_product_attribute
|
|
AND sa.id_shop = p_id_shop
|
|
WHERE
|
|
pa.id_product = p.id_product
|
|
)
|
|
) AS product_json
|
|
FROM
|
|
ps_product p
|
|
LEFT JOIN ps_product_shop ps ON ps.id_product = p.id_product
|
|
AND ps.id_shop = p_id_shop
|
|
LEFT JOIN ps_product_lang pl ON pl.id_product = p.id_product
|
|
AND pl.id_lang = p_id_lang
|
|
AND pl.id_shop = p_id_shop
|
|
LEFT JOIN ps_category_lang cl ON cl.id_category = COALESCE(ps.id_category_default, p.id_category_default)
|
|
AND cl.id_lang = p_id_lang
|
|
AND cl.id_shop = p_id_shop
|
|
LEFT JOIN ps_manufacturer m ON m.id_manufacturer = p.id_manufacturer
|
|
LEFT JOIN ps_image i ON i.id_product = p.id_product
|
|
AND i.cover = 1
|
|
LEFT JOIN ps_image_lang il ON il.id_image = i.id_image
|
|
AND il.id_lang = p_id_lang
|
|
/* SPECIFIC PRICE */
|
|
LEFT JOIN (
|
|
SELECT bsp.*
|
|
FROM b2b_specific_price bsp
|
|
|
|
/* RELATIONS */
|
|
LEFT JOIN b2b_specific_price_product bsp_p
|
|
ON bsp_p.b2b_specific_price_id = bsp.id
|
|
|
|
LEFT JOIN b2b_specific_price_category bsp_c
|
|
ON bsp_c.b2b_specific_price_id = bsp.id
|
|
|
|
WHERE bsp.is_active = TRUE
|
|
|
|
/* SCOPE MATCH */
|
|
AND (
|
|
/* PRODUCT */
|
|
(bsp.scope = 'product' AND bsp_p.id_product = p_id_product)
|
|
|
|
/* CATEGORY */
|
|
OR (
|
|
bsp.scope = 'category'
|
|
AND bsp_c.id_category IN (
|
|
SELECT cp.id_category
|
|
FROM ps_category_product cp
|
|
WHERE cp.id_product = p_id_product
|
|
)
|
|
)
|
|
|
|
/* SHOP (GLOBAL) */
|
|
OR (bsp.scope = 'shop')
|
|
)
|
|
|
|
/* CUSTOMER MATCH */
|
|
AND (
|
|
NOT EXISTS (
|
|
SELECT 1 FROM b2b_specific_price_customer c
|
|
WHERE c.b2b_specific_price_id = bsp.id
|
|
)
|
|
OR EXISTS (
|
|
SELECT 1 FROM b2b_specific_price_customer c
|
|
WHERE c.b2b_specific_price_id = bsp.id
|
|
AND c.b2b_id_customer = p_id_customer
|
|
)
|
|
)
|
|
|
|
/* COUNTRY MATCH */
|
|
AND (
|
|
NOT EXISTS (
|
|
SELECT 1 FROM b2b_specific_price_country ctry
|
|
WHERE ctry.b2b_specific_price_id = bsp.id
|
|
)
|
|
OR EXISTS (
|
|
SELECT 1 FROM b2b_specific_price_country ctry
|
|
WHERE ctry.b2b_specific_price_id = bsp.id
|
|
AND ctry.b2b_id_country = b2b_id_country
|
|
)
|
|
)
|
|
|
|
/* QUANTITY */
|
|
AND bsp.from_quantity <= p_quantity
|
|
|
|
/* DATE */
|
|
AND (
|
|
bsp.has_expiration_date = FALSE OR (
|
|
(bsp.valid_from IS NULL OR bsp.valid_from <= NOW())
|
|
AND (bsp.valid_till IS NULL OR bsp.valid_till >= NOW())
|
|
)
|
|
)
|
|
|
|
ORDER BY
|
|
/* 🔥 SCOPE PRIORITY */
|
|
bsp.scope = 'product' DESC,
|
|
bsp.scope = 'category' DESC,
|
|
bsp.scope = 'shop' DESC,
|
|
|
|
/* 🔥 CUSTOMER PRIORITY */
|
|
(
|
|
EXISTS (
|
|
SELECT 1 FROM b2b_specific_price_customer c
|
|
WHERE c.b2b_specific_price_id = bsp.id
|
|
AND c.b2b_id_customer = p_id_customer
|
|
)
|
|
) DESC,
|
|
|
|
/* 🔥 COUNTRY PRIORITY */
|
|
(
|
|
EXISTS (
|
|
SELECT 1 FROM b2b_specific_price_country ctry
|
|
WHERE ctry.b2b_specific_price_id = bsp.id
|
|
AND ctry.b2b_id_country = b2b_id_country
|
|
)
|
|
) DESC,
|
|
|
|
/* GLOBAL fallback (no restrictions) naturally goes last */
|
|
|
|
bsp.from_quantity DESC,
|
|
bsp.id DESC
|
|
|
|
LIMIT 1
|
|
) bsp ON 1=1
|
|
LEFT JOIN b2b_currency_rates br_bsp
|
|
ON br_bsp.b2b_id_currency = bsp.b2b_id_currency
|
|
AND br_bsp.created_at = (
|
|
SELECT MAX(created_at)
|
|
FROM b2b_currency_rates
|
|
WHERE b2b_id_currency = bsp.b2b_id_currency
|
|
)
|
|
LEFT JOIN b2b_countries ON b2b_countries.id = b2b_id_country
|
|
LEFT JOIN b2b_currencies ON b2b_currencies.id = p_id_currency
|
|
LEFT JOIN b2b_currency_rates r ON r.b2b_id_currency = b2b_currencies.id
|
|
AND r.created_at = (
|
|
SELECT
|
|
MAX(created_at)
|
|
FROM
|
|
b2b_currency_rates
|
|
WHERE
|
|
b2b_id_currency = b2b_currencies.id
|
|
)
|
|
WHERE
|
|
p.id_product = p_id_product
|
|
LIMIT
|
|
1;
|
|
END //
|
|
|
|
DELIMITER ;
|
|
-- +goose Down
|