package productsRepo import ( "encoding/json" "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, userID 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) GetBase(p_id_product, p_id_shop, p_id_lang uint) (view.Product, error) GetPrice(p_id_product uint, productAttributeID *uint, p_id_shop uint, p_id_customer uint, p_id_country uint, p_quantity uint) (view.Price, error) GetVariants(p_id_product, p_id_shop, p_id_lang, p_id_customer, p_id_country, p_quantity uint) ([]view.ProductAttribute, error) AddToFavorites(userID uint, productID uint) error RemoveFromFavorites(userID uint, productID uint) error ExistsInFavorites(userID uint, productID uint) (bool, error) ProductInDatabase(productID uint) (bool, error) } type ProductsRepo struct{} func New() UIProductsRepo { return &ProductsRepo{} } func (repo *ProductsRepo) GetBase(p_id_product, p_id_shop, p_id_lang uint) (view.Product, error) { var result view.Product err := db.DB.Raw(`CALL get_product_base(?,?,?)`, p_id_product, p_id_shop, p_id_lang). Scan(&result).Error return result, err } func (repo *ProductsRepo) GetPrice( p_id_product uint, productAttributeID *uint, p_id_shop uint, p_id_customer uint, p_id_country uint, p_quantity uint, ) (view.Price, error) { type row struct { Price json.RawMessage `gorm:"column:price"` } var r row err := db.DB.Raw(` SELECT fn_product_price(?,?,?,?,?,?) AS price`, p_id_product, p_id_shop, p_id_customer, p_id_country, p_quantity, productAttributeID). Scan(&r).Error if err != nil { return view.Price{}, err } var temp struct { Base json.Number `json:"base"` FinalTaxExcl json.Number `json:"final_tax_excl"` FinalTaxIncl json.Number `json:"final_tax_incl"` TaxRate json.Number `json:"tax_rate"` Priority json.Number `json:"priority"` } if err := json.Unmarshal(r.Price, &temp); err != nil { return view.Price{}, err } price := view.Price{ Base: mustParseFloat(temp.Base), FinalTaxExcl: mustParseFloat(temp.FinalTaxExcl), FinalTaxIncl: mustParseFloat(temp.FinalTaxIncl), TaxRate: mustParseFloat(temp.TaxRate), Priority: mustParseInt(temp.Priority), } return price, nil } func mustParseFloat(n json.Number) float64 { f, _ := n.Float64() return f } func mustParseInt(n json.Number) int { i, _ := n.Int64() return int(i) } func (repo *ProductsRepo) GetVariants(p_id_product, p_id_shop, p_id_lang, p_id_customer, p_id_country, p_quantity uint) ([]view.ProductAttribute, error) { var results []view.ProductAttribute err := db.DB.Raw(` CALL get_product_variants(?,?,?,?,?,?)`, p_id_product, p_id_shop, p_id_lang, p_id_customer, p_id_country, p_quantity). Scan(&results).Error return results, err } func (repo *ProductsRepo) Find(langID uint, userID 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, COALESCE(f.is_favorite, 0) AS is_favorite `, 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 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"). 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"), }, }, { 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") 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 } func (repo *ProductsRepo) AddToFavorites(userID uint, productID uint) error { fav := model.B2bFavorite{ UserID: userID, ProductID: productID, } return db.Get().Create(&fav).Error } func (repo *ProductsRepo) RemoveFromFavorites(userID uint, productID uint) error { return db.Get(). Where("user_id = ? AND product_id = ?", userID, productID). Delete(&model.B2bFavorite{}).Error } func (repo *ProductsRepo) ExistsInFavorites(userID uint, productID uint) (bool, error) { var count int64 err := db.Get(). Table("b2b_favorites"). Where("user_id = ? AND product_id = ?", userID, productID). Count(&count).Error return count >= 1, err } func (repo *ProductsRepo) ProductInDatabase(productID uint) (bool, error) { var count int64 err := db.Get(). Table(dbmodel.TableNamePsProduct). Where(dbmodel.PsProductCols.IDProduct.Col()+" = ?", productID). Count(&count).Error return count >= 1, err }