package productsRepo import ( "encoding/json" "fmt" "git.ma-al.com/goc_daniel/b2b/app/config" "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" "git.ma-al.com/goc_daniel/b2b/app/utils/query/filters" "git.ma-al.com/goc_daniel/b2b/app/utils/query/find" "git.ma-al.com/goc_daniel/b2b/app/view" "git.ma-al.com/goc_marek/gormcol" "github.com/WinterYukky/gorm-extra-clause-plugin/exclause" ) 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) Find(id_lang uint, p find.Paging, filt *filters.FiltersList) (*find.Found[model.ProductInList], error) GetProductVariants(langID uint, productID uint, shopID uint, customerID uint, countryID uint, quantity uint) ([]view.ProductAttribute, error) } type ProductsRepo struct{} func New() UIProductsRepo { return &ProductsRepo{} } func (repo *ProductsRepo) GetJSON(p_id_product, p_id_shop, p_id_lang, p_id_customer, b2b_id_country, p_quantity int) (*json.RawMessage, error) { var productStr string // ← Scan as string first err := db.DB.Raw(`CALL get_full_product(?,?,?,?,?,?)`, p_id_product, p_id_shop, p_id_lang, p_id_customer, b2b_id_country, p_quantity). Scan(&productStr). Error if err != nil { return nil, err } // Optional: validate it's valid JSON if !json.Valid([]byte(productStr)) { return nil, fmt.Errorf("invalid json returned from stored procedure") } raw := json.RawMessage(productStr) return &raw, nil } func (repo *ProductsRepo) Find(langID uint, p find.Paging, filt *filters.FiltersList) (*find.Found[model.ProductInList], error) { query := db.Get(). Table(gormcol.Field.Tab(dbmodel.PsProductShopCols.Active)+" AS ps"). Select(` ps.id_product AS product_id, pl.name AS name, pl.link_rewrite AS link_rewrite, CONCAT(?, '/', ims.id_image, '-small_default/', pl.link_rewrite, '.webp') AS image_link, cl.name AS category_name, p.reference AS reference, COALESCE(v.variants_number, 0) AS variants_number, sa.quantity AS quantity `, config.Get().Image.ImagePrefix). 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 = ?", langID). Joins("JOIN ps_image_shop ims ON ims.id_product = ps.id_product AND ims.cover = 1"). Joins("JOIN ps_category_lang cl ON cl.id_category = ps.id_category_default AND cl.id_lang = ?", langID). 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 ps_stock_available sa ON sa.id_product = ps.id_product AND sa.id_product_attribute = 0"). Where("ps.active = ?", 1). Group("ps.id_product"). Clauses(exclause.With{CTEs: []exclause.CTE{ { Name: "variants", Subquery: exclause.Subquery{DB: db.Get().Model(&dbmodel.PsProductAttributeShop{}).Select("id_product", "COUNT(*) AS variants_number").Group("id_product")}, }, }}). Order("ps.id_product DESC") query = query.Scopes(filt.All()...) list, err := find.Paginate[model.ProductInList](langID, p, query) if err != nil { return nil, err } return &list, nil } func (repo *ProductsRepo) GetProductVariants(langID uint, productID uint, shopID uint, customerID uint, countryID uint, quantity uint) ([]view.ProductAttribute, error) { var result []view.ProductAttribute err := db.DB. Raw(` CALL get_product_attributes_with_price(?, ?, ?, ?, ?, ?) `, langID, productID, shopID, customerID, countryID, quantity, ). Scan(&result).Error if err != nil { return nil, err } return result, nil } func (repo *ProductsRepo) PopulateProductPrice(product *model.ProductInList, targetCustomer *model.Customer, quantity int, shopID uint) error { row := db.Get().Raw( "CALL get_product_price(?, ?, ?, ?, ?)", product.ProductID, shopID, targetCustomer.ID, targetCustomer.CountryID, quantity, ).Row() var ( id uint base float64 excl float64 incl float64 tax float64 ) err := row.Scan(&id, &base, &excl, &incl, &tax) if err != nil { return err } product.PriceTaxExcl = excl product.PriceTaxIncl = incl return nil }