package productDescriptionRepo import ( "fmt" "git.ma-al.com/goc_daniel/b2b/app/db" "git.ma-al.com/goc_daniel/b2b/app/model" constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data" ) type UIProductDescriptionRepo interface { GetProductDescription(productID uint, productLangID uint) (*model.ProductDescription, error) CreateIfDoesNotExist(productID uint, productLangID uint) error UpdateFields(productID uint, productLangID uint, updates map[string]string) error GetMeiliProducts(id_lang uint) ([]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, productLangID uint) (*model.ProductDescription, error) { var ProductDescription model.ProductDescription err := db.DB. Table("ps_product_lang"). Where("id_product = ? AND id_shop = ? AND id_lang = ?", productID, constdata.SHOP_ID, productLangID). First(&ProductDescription).Error if err != nil { return nil, fmt.Errorf("database error: %w", err) } return &ProductDescription, nil } // If it doesn't exist, returns an error. func (r *ProductDescriptionRepo) CreateIfDoesNotExist(productID uint, productLangID uint) error { record := model.ProductDescription{ ProductID: productID, ShopID: constdata.SHOP_ID, LangID: productLangID, } err := db.DB. Table("ps_product_lang"). Where("id_product = ? AND id_shop = ? AND id_lang = ?", productID, constdata.SHOP_ID, productLangID). FirstOrCreate(&record).Error if err != nil { return fmt.Errorf("database error: %w", err) } return nil } func (r *ProductDescriptionRepo) UpdateFields(productID uint, productLangID 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.DB. Table("ps_product_lang"). Where("id_product = ? AND id_shop = ? AND id_lang = ?", productID, constdata.SHOP_ID, productLangID). Updates(updatesIface).Error if err != nil { return fmt.Errorf("database error: %w", err) } return nil } // We assume that any user has access to all product descriptions func (r *ProductDescriptionRepo) GetMeiliProducts(id_lang uint) ([]model.MeiliSearchProduct, error) { var products []model.MeiliSearchProduct err := db.DB.Debug(). // Select(` // ps.id_product AS id_product, // pl.name AS name, // ps.price AS price, // pl.description AS description, // pl.description_short AS description_short, // pl.usage AS used_for, // p.ean13 AS ean13, // p.reference AS reference, // p.width AS width, // p.height AS height, // p.depth AS depth, // p.weight AS weight, // ps.id_category_default AS id_category, // cl.name AS category_name, // COUNT(DISTINCT pas.id_product_attribute) AS variations // `). // Table("ps_product_shop AS ps"). // Joins("LEFT JOIN ps_product_lang AS pl ON ps.id_product = pl.id_product AND pl.id_shop = ? AND pl.id_lang = ?", constdata.SHOP_ID, id_lang). // Joins("LEFT JOIN ps_product AS p ON p.id_product = ps.id_product"). // Joins("LEFT JOIN ps_category_lang AS 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 ps_product_attribute_shop AS pas ON pas.id_product = ps.id_product AND pas.id_shop = ?", constdata.SHOP_ID). // Where("ps.id_shop = ? AND ps.active = 1", constdata.SHOP_ID). // Group("ps.id_product"). Select(` ps.id_product AS id_product, pl.name AS name, pl.description AS description, pl.description_short AS description_short, pl.usage AS used_for, p.ean13 AS ean13, p.reference AS reference, ps.id_category_default AS id_category, cl.name AS category_name, cl.link_rewrite as link_rewrite, COUNT(DISTINCT pas.id_product_attribute) AS variations, pis.id_image AS id_image, GROUP_CONCAT(DISTINCT pcp.id_category) AS category_ids `). Table("ps_product_shop AS ps"). Joins("LEFT JOIN ps_product_lang AS pl ON ps.id_product = pl.id_product AND pl.id_shop = ? AND pl.id_lang = ?", constdata.SHOP_ID, id_lang). Joins("LEFT JOIN ps_product AS p ON p.id_product = ps.id_product"). Joins("LEFT JOIN ps_category_lang AS 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 ps_product_attribute_shop AS pas ON pas.id_product = ps.id_product AND pas.id_shop = ?", constdata.SHOP_ID). Joins("JOIN ps_image_shop AS pis ON pis.id_product = ps.id_product AND pis.cover = 1"). Joins("JOIN ps_category_product AS pcp ON pcp.id_product = ps.id_product"). Where("ps.id_shop = ? AND ps.active = 1", constdata.SHOP_ID). Group("pcp.id_product, ps.id_product"). Scan(&products).Error if err != nil { return products, fmt.Errorf("database error: %w", err) } // Get all category IDs for each product (including child categories) for i := range products { var categoryIDs []uint // Find all parent categories and their children using nested set err := db.DB. Table("ps_category AS c"). Select("c.id_category"). Joins("JOIN ps_category_product AS cp ON cp.id_category = c.id_category"). Joins("JOIN ps_category AS parent ON c.nleft >= parent.nleft AND c.nright <= parent.nright AND parent.id_category = ?", products[i].CategoryID). Where("cp.id_product = ?", products[i].ProductID). Group("c.id_category"). Pluck("c.id_category", &categoryIDs).Error if err != nil { continue // Skip if error, use default category } if len(categoryIDs) > 0 { products[i].CategoryIDs = categoryIDs } else { products[i].CategoryIDs = []uint{products[i].CategoryID} } // Get cover image for the product var imageID int err = db.DB. Table("ps_image AS i"). Select("i.id_image"). Joins("LEFT JOIN ps_image_shop AS iss ON iss.id_image = i.id_image AND iss.id_shop = ?", constdata.SHOP_ID). Where("i.id_product = ? AND (i.cover = 1 OR i.cover IS TRUE)", products[i].ProductID). Order("i.position ASC"). Limit(1). Pluck("i.id_image", &imageID).Error if err == nil && imageID > 0 { products[i].CoverImage = fmt.Sprintf("%d/%d.jpg", products[i].ProductID, imageID) } } return products, nil }