204 lines
6.6 KiB
Go
204 lines
6.6 KiB
Go
package productDescriptionRepo
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"git.ma-al.com/goc_daniel/b2b/app/db"
|
|
"git.ma-al.com/goc_daniel/b2b/app/model"
|
|
"git.ma-al.com/goc_daniel/b2b/app/model/dbmodel"
|
|
constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data"
|
|
"github.com/WinterYukky/gorm-extra-clause-plugin/exclause"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type UIProductDescriptionRepo interface {
|
|
GetProductDescription(productID uint, productid_lang uint) (*model.ProductDescription, error)
|
|
CreateIfDoesNotExist(productID uint, productid_lang uint) error
|
|
UpdateFields(productID uint, productid_lang uint, updates map[string]string) error
|
|
GetMeiliProducts(id_lang uint, offset, limit int) ([]model.MeiliSearchProduct, error)
|
|
}
|
|
|
|
type ProductDescriptionRepo struct{}
|
|
|
|
func New() UIProductDescriptionRepo {
|
|
return &ProductDescriptionRepo{}
|
|
}
|
|
|
|
// We assume that any user has access to all product descriptions
|
|
func (r *ProductDescriptionRepo) GetProductDescription(productID uint, productid_lang uint) (*model.ProductDescription, error) {
|
|
var ProductDescription model.ProductDescription
|
|
|
|
err := db.Get().
|
|
Model(dbmodel.PsProductLang{}).
|
|
Where(&dbmodel.PsProductLang{
|
|
IDProduct: int32(productID),
|
|
IDShop: int32(constdata.SHOP_ID),
|
|
IDLang: int32(productid_lang),
|
|
}).
|
|
First(&ProductDescription).Error
|
|
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
// handle "not found" case only
|
|
ProductDescription.ExistsInDatabase = false
|
|
} else if err != nil {
|
|
return nil, fmt.Errorf("database error: %w", err)
|
|
} else {
|
|
ProductDescription.ExistsInDatabase = true
|
|
}
|
|
|
|
return &ProductDescription, nil
|
|
}
|
|
|
|
// If it doesn't exist, returns an error.
|
|
func (r *ProductDescriptionRepo) CreateIfDoesNotExist(productID uint, productid_lang uint) error {
|
|
record := dbmodel.PsProductLang{
|
|
IDProduct: int32(productID),
|
|
IDShop: int32(constdata.SHOP_ID),
|
|
IDLang: int32(productid_lang),
|
|
}
|
|
|
|
err := db.Get().
|
|
Model(dbmodel.PsProductLang{}).
|
|
Where(&dbmodel.PsProductLang{
|
|
IDProduct: int32(productID),
|
|
IDShop: int32(constdata.SHOP_ID),
|
|
IDLang: int32(productid_lang),
|
|
}).
|
|
FirstOrCreate(&record).Error
|
|
if err != nil {
|
|
return fmt.Errorf("database error: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *ProductDescriptionRepo) UpdateFields(productID uint, productid_lang uint, updates map[string]string) error {
|
|
if len(updates) == 0 {
|
|
return nil
|
|
}
|
|
updatesIface := make(map[string]interface{}, len(updates))
|
|
for k, v := range updates {
|
|
updatesIface[k] = v
|
|
}
|
|
|
|
err := db.Get().
|
|
Model(&dbmodel.PsProductLang{}).
|
|
Where(&dbmodel.PsProductLang{
|
|
IDProduct: int32(productID),
|
|
IDShop: int32(constdata.SHOP_ID),
|
|
IDLang: int32(productid_lang),
|
|
}).
|
|
Updates(updatesIface).Error
|
|
if err != nil {
|
|
return fmt.Errorf("database error: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetMeiliProductsBatchedScanned returns a batch of products with LIMIT/OFFSET pagination
|
|
// The scanning is done inside the repo to keep the service layer cleaner
|
|
func (r *ProductDescriptionRepo) GetMeiliProducts(id_lang uint, offset, limit int) ([]model.MeiliSearchProduct, error) {
|
|
|
|
var products []model.MeiliSearchProduct
|
|
|
|
err := db.Get().
|
|
Table("ps_product_shop ps").
|
|
Select(`
|
|
ps.id_product AS id_product,
|
|
pl.name AS name,
|
|
TRIM(REGEXP_REPLACE(REGEXP_REPLACE(pl.description_short, '<[^>]*>', ' '), '[[:space:]]+', ' ')) AS description,
|
|
p.ean13,
|
|
p.reference,
|
|
ps.price,
|
|
ps.id_category_default AS id_category,
|
|
cl.name AS cat_name,
|
|
cl.link_rewrite AS l_rew,
|
|
COALESCE(vary.attributes, JSON_OBJECT()) AS attr,
|
|
COALESCE(feat.features, JSON_OBJECT()) AS feat,
|
|
img.id_image,
|
|
cat.category_ids,
|
|
(SELECT COUNT(*) FROM ps_product_attribute_shop pas2 WHERE pas2.id_product = ps.id_product AND pas2.id_shop = ?) AS variations
|
|
`, constdata.SHOP_ID).
|
|
Joins("JOIN ps_product p ON p.id_product = ps.id_product").
|
|
Joins("JOIN ps_product_lang pl ON pl.id_product = ps.id_product AND pl.id_shop = ? AND pl.id_lang = ?", constdata.SHOP_ID, id_lang).
|
|
Joins("JOIN ps_category_lang cl ON cl.id_category = ps.id_category_default AND cl.id_shop = ? AND cl.id_lang = ?", constdata.SHOP_ID, id_lang).
|
|
Joins("LEFT JOIN variations vary ON vary.id_product = ps.id_product").
|
|
Joins("LEFT JOIN features feat ON feat.id_product = ps.id_product").
|
|
Joins("LEFT JOIN images img ON img.id_product = ps.id_product").
|
|
Joins("LEFT JOIN categories cat ON cat.id_product = ps.id_product").
|
|
Joins("JOIN products_page pp ON pp.id_product = ps.id_product").
|
|
Where("ps.active = ?", 1).
|
|
Order("ps.id_product").
|
|
Clauses(exclause.With{CTEs: []exclause.CTE{
|
|
{
|
|
Name: "products_page",
|
|
Subquery: exclause.Subquery{
|
|
DB: db.Get().
|
|
Model(&dbmodel.PsProductShop{}).
|
|
Select("id_product, price").
|
|
Where("id_shop = ? AND active = 1", constdata.SHOP_ID).
|
|
Order("id_product").
|
|
Limit(limit).
|
|
Offset(offset),
|
|
},
|
|
},
|
|
{
|
|
Name: "variation_attributes",
|
|
Subquery: exclause.Subquery{
|
|
DB: db.Get().
|
|
Table("ps_product_attribute_shop pas"). // <- explicit alias here
|
|
Select(`
|
|
pas.id_product,
|
|
pag.id_attribute_group AS attribute_name,
|
|
JSON_ARRAYAGG(DISTINCT pa.id_attribute) AS attribute_values
|
|
`).
|
|
Joins("JOIN ps_product_attribute_combination ppac ON ppac.id_product_attribute = pas.id_product_attribute").
|
|
Joins("JOIN ps_attribute pa ON pa.id_attribute = ppac.id_attribute").
|
|
Joins("JOIN ps_attribute_group pag ON pag.id_attribute_group = pa.id_attribute_group").
|
|
Where("pas.id_shop = ?", constdata.SHOP_ID).
|
|
Group("pas.id_product, pag.id_attribute_group"),
|
|
},
|
|
},
|
|
{
|
|
Name: "variations",
|
|
Subquery: exclause.Subquery{
|
|
DB: db.Get().
|
|
Table("variation_attributes").
|
|
Select("id_product, JSON_OBJECTAGG(attribute_name, attribute_values) AS attributes").
|
|
Group("id_product"),
|
|
},
|
|
},
|
|
{
|
|
Name: "features",
|
|
Subquery: exclause.Subquery{
|
|
DB: db.Get().
|
|
Table("ps_feature_product pfp"). // <- explicit alias
|
|
Select("pfp.id_product, JSON_OBJECTAGG(pfp.id_feature, pfp.id_feature_value) AS features").
|
|
Group("pfp.id_product"),
|
|
},
|
|
},
|
|
{
|
|
Name: "images",
|
|
Subquery: exclause.Subquery{
|
|
DB: db.Get().
|
|
Model(&dbmodel.PsImageShop{}).
|
|
Select("id_product, id_image").
|
|
Where("id_shop = ? AND cover = 1", constdata.SHOP_ID),
|
|
},
|
|
},
|
|
{
|
|
Name: "categories",
|
|
Subquery: exclause.Subquery{
|
|
DB: db.Get().
|
|
Model(&dbmodel.PsCategoryProduct{}).
|
|
Select("id_product, JSON_ARRAYAGG(id_category) AS category_ids").
|
|
Group("id_product"),
|
|
},
|
|
},
|
|
}}).Find(&products).Error
|
|
|
|
return products, err
|
|
}
|