284 lines
8.3 KiB
Go
284 lines
8.3 KiB
Go
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, p_id_customer 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, p_id_customer 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, p_id_customer).
|
|
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.DB.
|
|
Table("base_products AS bp").
|
|
Clauses(exclause.With{
|
|
CTEs: []exclause.CTE{
|
|
{
|
|
Name: "favorites",
|
|
Subquery: exclause.Subquery{
|
|
DB: db.DB.
|
|
Table("b2b_favorites").
|
|
Select(`
|
|
product_id AS product_id,
|
|
COUNT(*) > 0 AS is_favorite
|
|
`).
|
|
Where("user_id = ?", userID).
|
|
Group("product_id"),
|
|
},
|
|
},
|
|
{
|
|
Name: "new_product_days",
|
|
Subquery: exclause.Subquery{
|
|
DB: db.DB.
|
|
Table("ps_configuration").
|
|
Select("CAST(value AS SIGNED) AS days").
|
|
Where("name = ?", "PS_NB_DAYS_NEW_PRODUCT"),
|
|
},
|
|
},
|
|
{
|
|
Name: "variants",
|
|
Subquery: exclause.Subquery{
|
|
DB: db.DB.
|
|
Table("ps_product_attribute_shop").
|
|
Select("id_product, COUNT(*) AS variants_number").
|
|
Group("id_product"),
|
|
},
|
|
},
|
|
{
|
|
Name: "base_products",
|
|
Subquery: exclause.Subquery{
|
|
DB: db.DB.
|
|
Table(gormcol.Field.Tab(dbmodel.PsProductShopCols.Active)+" AS ps").
|
|
Select(`
|
|
ps.id_product AS product_id,
|
|
pl.name AS name,
|
|
ps.id_category_default AS category_id,
|
|
p.reference AS reference,
|
|
sa.quantity AS quantity,
|
|
COALESCE(f.is_favorite, 0) AS is_favorite,
|
|
CASE
|
|
WHEN ps.date_add >= DATE_SUB(
|
|
NOW(),
|
|
INTERVAL COALESCE(npd.days, 20) DAY
|
|
) AND ps.active = 1
|
|
THEN 1
|
|
ELSE 0
|
|
END AS is_new
|
|
`).
|
|
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("LEFT JOIN favorites f ON f.product_id = 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 new_product_days npd ON 1 = 1").
|
|
Where("ps.active = ?", 1).
|
|
Group("ps.id_product"),
|
|
},
|
|
},
|
|
},
|
|
}).
|
|
Select(`
|
|
bp.product_id AS product_id,
|
|
bp.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,
|
|
bp.reference AS reference,
|
|
COALESCE(v.variants_number, 0) AS variants_number,
|
|
bp.quantity AS quantity,
|
|
bp.is_favorite AS is_favorite,
|
|
bp.is_new AS is_new
|
|
`, config.Get().Image.ImagePrefix).
|
|
Joins("JOIN ps_product_lang pl ON pl.id_product = bp.product_id AND pl.id_lang = ?", langID).
|
|
Joins("JOIN ps_image_shop ims ON ims.id_product = bp.product_id AND ims.cover = 1").
|
|
Joins("JOIN ps_category_lang cl ON cl.id_category = bp.category_id AND cl.id_lang = ?", langID).
|
|
Joins("LEFT JOIN variants v ON v.id_product = bp.product_id").
|
|
Order("bp.product_id 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
|
|
}
|