favorites
This commit is contained in:
@@ -90,7 +90,13 @@ func (h *ProductsHandler) ListProducts(c fiber.Ctx) error {
|
|||||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
|
||||||
}
|
}
|
||||||
|
|
||||||
list, err := h.productService.Find(id_lang, paging, filters)
|
userID, ok := localeExtractor.GetUserID(c)
|
||||||
|
if !ok {
|
||||||
|
return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).
|
||||||
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody)))
|
||||||
|
}
|
||||||
|
|
||||||
|
list, err := h.productService.Find(id_lang, userID, paging, filters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(responseErrors.GetErrorStatus(err)).
|
return c.Status(responseErrors.GetErrorStatus(err)).
|
||||||
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ type ProductInList struct {
|
|||||||
Reference string `gorm:"column:reference" json:"reference"`
|
Reference string `gorm:"column:reference" json:"reference"`
|
||||||
VariantsNumber uint `gorm:"column:variants_number" json:"variants_number"`
|
VariantsNumber uint `gorm:"column:variants_number" json:"variants_number"`
|
||||||
Quantity int64 `gorm:"column:quantity" json:"quantity"`
|
Quantity int64 `gorm:"column:quantity" json:"quantity"`
|
||||||
|
IsFavorite bool `gorm:"column:is_favorite" json:"is_favorite"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProductFilters struct {
|
type ProductFilters struct {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
|
|
||||||
type UIProductsRepo interface {
|
type UIProductsRepo interface {
|
||||||
GetJSON(p_id_product, p_id_shop, p_id_lang, p_id_customer, b2b_id_country, p_quantity int) (*json.RawMessage, error)
|
GetJSON(p_id_product, p_id_shop, p_id_lang, p_id_customer, b2b_id_country, p_quantity int) (*json.RawMessage, error)
|
||||||
Find(id_lang uint, p find.Paging, filt *filters.FiltersList) (find.Found[model.ProductInList], error)
|
Find(id_lang, userID uint, p find.Paging, filt *filters.FiltersList) (find.Found[model.ProductInList], error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProductsRepo struct{}
|
type ProductsRepo struct{}
|
||||||
@@ -37,7 +37,6 @@ func (repo *ProductsRepo) GetJSON(p_id_product, p_id_shop, p_id_lang, p_id_custo
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optional: validate it's valid JSON
|
|
||||||
if !json.Valid([]byte(productStr)) {
|
if !json.Valid([]byte(productStr)) {
|
||||||
return nil, fmt.Errorf("invalid json returned from stored procedure")
|
return nil, fmt.Errorf("invalid json returned from stored procedure")
|
||||||
}
|
}
|
||||||
@@ -46,7 +45,7 @@ func (repo *ProductsRepo) GetJSON(p_id_product, p_id_shop, p_id_lang, p_id_custo
|
|||||||
return &raw, nil
|
return &raw, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *ProductsRepo) Find(id_lang uint, p find.Paging, filt *filters.FiltersList) (find.Found[model.ProductInList], error) {
|
func (repo *ProductsRepo) Find(id_lang, userID uint, p find.Paging, filt *filters.FiltersList) (find.Found[model.ProductInList], error) {
|
||||||
var list []model.ProductInList
|
var list []model.ProductInList
|
||||||
var total int64
|
var total int64
|
||||||
|
|
||||||
@@ -60,7 +59,8 @@ func (repo *ProductsRepo) Find(id_lang uint, p find.Paging, filt *filters.Filter
|
|||||||
cl.name AS category_name,
|
cl.name AS category_name,
|
||||||
p.reference AS reference,
|
p.reference AS reference,
|
||||||
COALESCE(v.variants_number, 0) AS variants_number,
|
COALESCE(v.variants_number, 0) AS variants_number,
|
||||||
sa.quantity AS quantity
|
sa.quantity AS quantity,
|
||||||
|
COALESCE(f.is_favorite, 0) AS is_favorite
|
||||||
`, config.Get().Image.ImagePrefix).
|
`, config.Get().Image.ImagePrefix).
|
||||||
Joins("JOIN "+dbmodel.PsProductCols.IDProduct.Tab()+" p ON p.id_product = ps.id_product").
|
Joins("JOIN "+dbmodel.PsProductCols.IDProduct.Tab()+" p ON p.id_product = ps.id_product").
|
||||||
Joins("JOIN ps_product_lang pl ON pl.id_product = ps.id_product AND pl.id_lang = ?", id_lang).
|
Joins("JOIN ps_product_lang pl ON pl.id_product = ps.id_product AND pl.id_lang = ?", id_lang).
|
||||||
@@ -68,15 +68,37 @@ func (repo *ProductsRepo) Find(id_lang uint, p find.Paging, filt *filters.Filter
|
|||||||
Joins("JOIN ps_category_lang cl ON cl.id_category = ps.id_category_default AND cl.id_lang = ?", id_lang).
|
Joins("JOIN ps_category_lang cl ON cl.id_category = ps.id_category_default AND cl.id_lang = ?", id_lang).
|
||||||
Joins("JOIN ps_category_product cp ON cp.id_product = ps.id_product").
|
Joins("JOIN ps_category_product cp ON cp.id_product = ps.id_product").
|
||||||
Joins("LEFT JOIN variants v ON v.id_product = ps.id_product").
|
Joins("LEFT JOIN variants v ON v.id_product = ps.id_product").
|
||||||
|
Joins("LEFT JOIN favorites f ON f.id_product = ps.id_product").
|
||||||
Joins("LEFT JOIN ps_stock_available sa ON sa.id_product = ps.id_product AND sa.id_product_attribute = 0").
|
Joins("LEFT JOIN ps_stock_available sa ON sa.id_product = ps.id_product AND sa.id_product_attribute = 0").
|
||||||
Where("ps.active = ?", 1).
|
Where("ps.active = ?", 1).
|
||||||
Group("ps.id_product").
|
Group("ps.id_product").
|
||||||
Clauses(exclause.With{CTEs: []exclause.CTE{
|
Clauses(exclause.With{
|
||||||
|
CTEs: []exclause.CTE{
|
||||||
{
|
{
|
||||||
Name: "variants",
|
Name: "variants",
|
||||||
Subquery: exclause.Subquery{DB: db.Get().Model(&dbmodel.PsProductAttributeShop{}).Select("id_product", "COUNT(*) AS variants_number").Group("id_product")},
|
Subquery: exclause.Subquery{
|
||||||
|
DB: db.Get().
|
||||||
|
Model(&dbmodel.PsProductAttributeShop{}).
|
||||||
|
Select("id_product", "COUNT(*) AS variants_number").
|
||||||
|
Group("id_product"),
|
||||||
},
|
},
|
||||||
}}).
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
Name: "favorites",
|
||||||
|
Subquery: exclause.Subquery{
|
||||||
|
DB: db.Get().
|
||||||
|
Table("b2b_favorites").
|
||||||
|
Select(`
|
||||||
|
product_id AS id_product,
|
||||||
|
COUNT(*) > 0 AS is_favorite
|
||||||
|
`).
|
||||||
|
Where("user_id = ?", userID).
|
||||||
|
Group("product_id"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}).
|
||||||
Order("ps.id_product DESC")
|
Order("ps.id_product DESC")
|
||||||
|
|
||||||
// Apply all filters
|
// Apply all filters
|
||||||
|
|||||||
@@ -29,6 +29,6 @@ func (s *ProductService) GetJSON(p_id_product, p_id_lang, p_id_customer, b2b_id_
|
|||||||
return products, nil
|
return products, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ProductService) Find(id_lang uint, p find.Paging, filters *filters.FiltersList) (find.Found[model.ProductInList], error) {
|
func (s *ProductService) Find(id_lang, userID uint, p find.Paging, filters *filters.FiltersList) (find.Found[model.ProductInList], error) {
|
||||||
return s.productsRepo.Find(id_lang, p, filters)
|
return s.productsRepo.Find(id_lang, userID, p, filters)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,6 +151,16 @@ CREATE TABLE IF NOT EXISTS b2b_carts_products (
|
|||||||
CREATE INDEX IF NOT EXISTS idx_carts_products_cart_id ON b2b_carts_products (cart_id);
|
CREATE INDEX IF NOT EXISTS idx_carts_products_cart_id ON b2b_carts_products (cart_id);
|
||||||
|
|
||||||
|
|
||||||
|
-- favorites
|
||||||
|
CREATE TABLE IF NOT EXISTS b2b_favorites (
|
||||||
|
user_id BIGINT UNSIGNED NOT NULL,
|
||||||
|
product_id INT UNSIGNED NOT NULL,
|
||||||
|
PRIMARY KEY (user_id, product_id),
|
||||||
|
CONSTRAINT fk_favorites_customer FOREIGN KEY (user_id) REFERENCES b2b_customers(id) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT fk_favorites_product FOREIGN KEY (product_id) REFERENCES ps_product(id_product) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
|
||||||
|
|
||||||
|
|
||||||
-- refresh_tokens
|
-- refresh_tokens
|
||||||
CREATE TABLE IF NOT EXISTS b2b_refresh_tokens (
|
CREATE TABLE IF NOT EXISTS b2b_refresh_tokens (
|
||||||
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
|||||||
@@ -132,6 +132,12 @@ JSON_OBJECT(
|
|||||||
m.name,
|
m.name,
|
||||||
'category',
|
'category',
|
||||||
cl.name,
|
cl.name,
|
||||||
|
/* ================= FAVORITE ================= */
|
||||||
|
'is_favorite',
|
||||||
|
EXISTS(
|
||||||
|
SELECT 1 FROM b2b_favorites f
|
||||||
|
WHERE f.user_id = p_id_customer AND f.product_id = p_id_product
|
||||||
|
),
|
||||||
/* ================= IMAGE ================= */
|
/* ================= IMAGE ================= */
|
||||||
'cover_image',
|
'cover_image',
|
||||||
JSON_OBJECT(
|
JSON_OBJECT(
|
||||||
|
|||||||
Reference in New Issue
Block a user