package goods import ( "fmt" "recook/internal/back" "recook/internal/dbc" "recook/internal/model/goods" "recook/internal/v2/lib/es" ac2 "recook/internal/v2/model/jyy" "recook/internal/v2/model/keywords" goods2 "recook/internal/v2/model/recook/goods" "recook/internal/v2/model/recook/user" "recook/internal/v2/model/search_ali" "recook/tools" "strings" mysql2 "git.oa00.com/go/mysql" "github.com/gin-gonic/gin" "github.com/golangkit/formatime" "github.com/shopspring/decimal" gorm2 "gorm.io/gorm" "gorm.io/gorm/clause" ) type queryOrderGoodsListParam struct { SecondCategoryID uint `json:"secondCategoryID"` BrandID uint `json:"brandID"` Page uint `json:"page"` Order string `json:"order"` /*asc 升序 desc 降序*/ Keyword string `json:"keyword" form:"keyword"` /* 搜索的关键字 */ CountryId uint `json:"country_id"` UserId uint `json:"user_id"` Kind uint `json:"kind"` ActivityID uint `json:"activity_id"` // 批发活动商品 IsSale bool `json:"is_sale"` } type QueryCategoryGoodsListResp struct { ID uint `json:"id"` GoodsName string `json:"goodsName"` BrandImg string `json:"brandImg"` BrandName string `json:"brandName"` BrandId uint `json:"brandId"` Description string `json:"description"` Inventory uint `json:"inventory"` // 总库存 SalesVolume uint `json:"salesVolume"` // 总销量 MainPhotoURL string `json:"mainPhotoUrl"` // 主图链接 PromotionName string `json:"promotionName"` OriginalPrice decimal.Decimal `json:"originalPrice"` DiscountPrice decimal.Decimal `json:"discountPrice"` Commission decimal.Decimal `json:"commission"` Tags []string `json:"tags"` // 为产品打上标签,比如 "新人特惠" "限时特卖" Percent uint `json:"percent"` // 活动的%-1代表不是活动 StartTime formatime.Second `json:"startTime"` // 开始时间 EndTime formatime.Second `json:"endTime"` // 结束时间 Coupon decimal.Decimal `gorm:"coupon" json:"coupon"` IsImport int `json:"isImport"` //是否进口商品 Storehouse int `json:"storehouse"` //进口商品仓库 IsFerme int `json:"isFerme"` //是否包税 HasCoin bool `json:"hasCoin"` //是否支持瑞币抵扣 HasBalance bool `json:"hasBalance"` //是否支持余额支付 Living live `json:"living"` //直播中 GysId uint `json:"gys_id"` //供应商id SpecIcon []string `json:"spec_icon"` //特卖活动图标数组 CountryIcon string `json:"country_icon"` //进口国家图标 SecKill SecKillDetail `json:"sec_kill"` SalePrice decimal.Decimal `json:"sale_price"` } // QueryGoodsListByComprehension 综合排序 func QueryGoodsListByComprehension(c *gin.Context) { var p queryOrderGoodsListParam if err := tools.ParseParams(&p, c); err != nil { back.Fail(c, err.Error()) return } if p.SecondCategoryID == 0 && p.BrandID == 0 && len(p.Keyword) == 0 && p.ActivityID == 0 { back.Fail(c, "参数不全") return } //新增模块:存入用户的搜索记录 if p.UserId != 0 && p.Keyword != "" { //条件:用户id和关键词非空 var kw = keywords.RecookUserKeywordsModel{ UserId: p.UserId, Keywords: p.Keyword, CreatedTime: formatime.NewSecondNow(), } dbc.DB.Table(kw.TableName()).Create(&kw) } var goodsList []goods.Information status := 1 if p.IsSale { status = 0 } q3 := mysql2.Db.Table("recook_goods_info as a").Where("is_virtual = 0").Where(goods.Information{ BrandID: p.BrandID, SecondCategoryID: p.SecondCategoryID, PublishStatus: uint(status), }) if p.ActivityID != 0 { // 批发活动id sub := mysql2.Db.Table((&ac2.ActivityGoods{}).TableName()).Order("id desc").Select("goods_id").Where("activity_id = ?", p.ActivityID) ids := make([]uint, 0) sub.Pluck("goods_id", &ids) q3 = q3.Clauses(clause.OrderBy{ Expression: clause.Expr{SQL: "FIELD(id,?)", Vars: []interface{}{ids}, WithoutParentheses: true}}) q3 = q3.Where("id in (?) and sale_publish = 1 and is_sale = 1", ids) } filters := map[string]interface{}{} if p.SecondCategoryID > 0 { filters["brand_id"] = p.BrandID } if p.SecondCategoryID > 0 { filters["second_category_id"] = p.SecondCategoryID } findByKeyWord(q3, p.Keyword, filters, &goodsList, p.Page, p.IsSale, false) back.Suc(c, "", GetGoodsRespByInfoList(goodsList, p.UserId, p.IsSale)) } func findByKeyWord(q *gorm2.DB, str string, filters map[string]interface{}, data *[]goods.Information, page uint, isSale bool, isCondition bool) { if str != "" { gl, _, _ := search_ali.SearchByAliES(str, filters, isSale, 20, int(page)) q = q.Where("a.id in (?)", gl) if !isCondition { q = q.Clauses(clause.OrderBy{ Expression: clause.Expr{SQL: "FIELD(id,?)", Vars: []interface{}{gl}, WithoutParentheses: true}}) } q.Find(&data) } else { q.Limit(20).Offset(int(page * 20)).Find(&data) } } type DescVolGoodsList []goods.Information func (d DescVolGoodsList) Len() int { return len(d) } func (d DescVolGoodsList) Less(i, j int) bool { return d[i].SalesVolume > d[j].SalesVolume } func (d DescVolGoodsList) Swap(i, j int) { d[i], d[j] = d[j], d[i] } type AscVolGoodsList []goods.Information func (d AscVolGoodsList) Len() int { return len(d) } func (d AscVolGoodsList) Less(i, j int) bool { return d[i].SalesVolume < d[j].SalesVolume } func (d AscVolGoodsList) Swap(i, j int) { d[i], d[j] = d[j], d[i] } // QueryGoodsListBySalesVolume 新的按照销量排序 func QueryGoodsListBySalesVolume(c *gin.Context) { var p queryOrderGoodsListParam if err := tools.ParseParams(&p, c); err != nil { back.Fail(c, err.Error()) return } if p.SecondCategoryID == 0 && p.BrandID == 0 && len(p.Keyword) == 0 && p.ActivityID == 0 { back.Fail(c, "参数不全") return } status := 1 if p.IsSale { status = 0 } var goodsList []goods.Information order := fmt.Sprintf("vol %s, id desc", p.Order) q3 := mysql2.Db.Select("a.*, b.vol").Table("recook_goods_info as a").Where("is_virtual = 0").Joins("JOIN (SELECT goods_id, sum(sales_volume + sales_volume_inc ) as vol FROM recook_goods_sku GROUP BY goods_id) as b on a.id = b.goods_id ").Order(order).Where(goods.Information{ BrandID: p.BrandID, SecondCategoryID: p.SecondCategoryID, PublishStatus: uint(status), Country: p.CountryId, }) if p.ActivityID != 0 { // 批发活动id sub := mysql2.Db.Table((&ac2.ActivityGoods{}).TableName()).Select("goods_id").Where("activity_id = ?", p.ActivityID) q3 = q3.Where("id in (?) and sale_publish = 1 and is_sale = 1", sub) } filters := map[string]interface{}{} if p.SecondCategoryID > 0 { filters["brand_id"] = p.BrandID } if p.SecondCategoryID > 0 { filters["second_category_id"] = p.SecondCategoryID } findByKeyWord(q3, p.Keyword, filters, &goodsList, p.Page, p.IsSale, true) back.Suc(c, "", GetGoodsRespByInfoList(goodsList, p.UserId, p.IsSale)) } func QueryGoodsListByDiscountPrice(c *gin.Context) { var p queryOrderGoodsListParam if err := tools.ParseParams(&p, c); err != nil { back.Fail(c, err.Error()) return } if p.SecondCategoryID == 0 && p.BrandID == 0 && len(p.Keyword) == 0 && p.ActivityID == 0 { back.Fail(c, "参数不全") return } status := 1 orderStr := "discount_price" if p.IsSale { status = 0 orderStr = "sale_purchase_price" } var goodsList []goods.Information order := fmt.Sprintf("vol %s, id desc", p.Order) q3 := mysql2.Db.Select("a.*, b.vol").Table("recook_goods_info as a").Where("is_virtual = 0").Joins(fmt.Sprintf("JOIN (SELECT goods_id, MIN(%s) as vol FROM recook_goods_sku GROUP BY goods_id) as b on a.id = b.goods_id", orderStr)).Order(order).Where(goods.Information{ BrandID: p.BrandID, SecondCategoryID: p.SecondCategoryID, PublishStatus: uint(status), Country: p.CountryId, }) if p.ActivityID != 0 { // 批发活动id sub := mysql2.Db.Table((&ac2.ActivityGoods{}).TableName()).Select("goods_id").Where("activity_id = ?", p.ActivityID) q3 = q3.Where("id in (?) and sale_publish = 1 and is_sale= 1", sub) } filters := map[string]interface{}{} if p.SecondCategoryID > 0 { filters["brand_id"] = p.BrandID } if p.SecondCategoryID > 0 { filters["second_category_id"] = p.SecondCategoryID } findByKeyWord(q3, p.Keyword, filters, &goodsList, p.Page, p.IsSale, true) back.Suc(c, "", GetGoodsRespByInfoList(goodsList, p.UserId, p.IsSale)) } // GetGoodsRespByInfoList ============================================================== func GetGoodsRespByInfoList(goodsList []goods.Information, userID uint, isSale bool) []QueryCategoryGoodsListResp { ids := make([]uint, 0) bids := make([]uint, 0) for _, v := range goodsList { ids = append(ids, v.ID) bids = append(bids, v.BrandID) } list := make([]QueryCategoryGoodsListResp, 0) var u user.RecookUserInfoModel mysql2.Db.First(&u, "id = ?", userID) var sku []goods.Sku mysql2.Db.Select( "MIN(name), "+ "goods_id, "+ "SUM(inventory) AS inventory, "+ "SUM(sales_volume) AS sales_volume, "+ "SUM(sales_volume_inc) AS sales_volume_inc, "+ "SUM(sale_volume2) AS sale_volume2, "+ "SUM(sale_volume_inc2) AS sale_volume_inc2, "+ "MIN(purchase_price) AS purchase_price,"+ "MIN(original_price) AS original_price, "+ "MIN(discount_price) AS discount_price, "+ "MIN(commission) AS commission,"+ "MIN(coupon) AS coupon, "+ "MIN(sale_purchase_price) AS sale_purchase_price, "+ "MIN(extra_price) AS extra_price, "+ "MIN(sale_extra_price) AS sale_extra_price"). Group("goods_id"). Where("goods_id in (?)", ids). Find(&sku) skuMap := make(map[uint]goods.Sku) for _, v := range sku { skuMap[v.GoodsID] = v } var mainPhotoList []goods.MainPhoto mysql2.Db.Find(&mainPhotoList, "goods_id in (?) AND is_master = 1", ids) mpMap := make(map[uint]goods.MainPhoto) for _, v := range mainPhotoList { mpMap[v.GoodsID] = v } var brandList []goods.Brand mysql2.Db.Find(&brandList, "id in (?)", bids) brandMap := make(map[uint]goods.Brand) for _, v := range brandList { brandMap[v.ID] = v } //国家图标放入map结束 for _, v := range goodsList { if isSale && v.SalePublish != 1 { continue } if !isSale && v.PublishStatus == 0 { continue } ss := skuMap[v.ID] mp := mpMap[v.ID] brand := brandMap[v.BrandID] var startTime = formatime.Second{} var endTime = formatime.Second{} inventory := ss.Inventory salesVolume := ss.SalesVolume + ss.SalesVolumeInc if isSale { salesVolume = ss.SaleVolume2 + ss.SaleVolumeInc2 } commission := ss.GetSelfProfit(u.Level) tags := make([]string, 0) recookGoodsInfoModel := &goods2.RecookGoodsInfoModel{} space := " " list = append(list, QueryCategoryGoodsListResp{ ID: v.ID, GoodsName: strings.Join([]string{v.GoodsName, strings.Replace(ss.Name, "+", space, -1)}, space), BrandName: brand.Name + "品牌馆", BrandImg: brand.LogoURL, BrandId: brand.ID, Description: v.Description, Inventory: inventory, SalesVolume: salesVolume, MainPhotoURL: mp.URL, PromotionName: "", OriginalPrice: ss.OriginalPrice, DiscountPrice: ss.DiscountPrice, Commission: commission, Tags: tags, Percent: 0, //百分比,-1不显示 StartTime: startTime, EndTime: endTime, Coupon: ss.Coupon, IsImport: v.IsImport, Storehouse: v.Storehouse, IsFerme: v.IsFerme, HasCoin: recookGoodsInfoModel.HasCoin(v.Storehouse), HasBalance: recookGoodsInfoModel.HasBalance(v.Storehouse), GysId: v.VendorID, CountryIcon: "", SalePrice: ss.GetSalePrice(u.Level), }) } return list } type live struct { Status int `json:"status"` RoomId int `json:"room_id"` } //func GetGoodsRespBySkuList(skuList []goods.Sku, uid uint, isSale bool) []QueryCategoryGoodsListResp { // list := make([]QueryCategoryGoodsListResp, 0, 0) // var u user.RecookUserInfoModel // mysql2.Db.First(&u, "id = ?", uid) // // rate1 := decimal.Zero // rate2 := decimal.Zero // rate3 := decimal.Zero // if u.Level == 1 { // rate1 = decimal.NewFromFloat32(0.4) // rate2 = decimal.NewFromFloat32(0.1) // } // if u.Level == 2 { // rate1 = decimal.NewFromFloat32(0.4) // rate2 = decimal.NewFromFloat32(0.1) // rate3 = decimal.NewFromFloat32(0.2) // } // // for _, v := range skuList { // var mainPhoto goods.MainPhoto // dbc.DB.Select("url").First(&mainPhoto, "goods_id = ? AND is_master = 1", v.GoodsID) // // var goodsInfo goods.Information // dbc.DB.First(&goodsInfo, v.GoodsID) // if !isSale && goodsInfo.PublishStatus == 0 { // continue // } // if isSale && goodsInfo.SalePublish == 0 { // continue // } // gb := goods.Brand{} // dbc.DB.First(&gb, "id = ?", goodsInfo.BrandID) // // var inventory uint // //var percent uint // // var startTime = formatime.Second{} // var endTime = formatime.Second{} // // salesVolume := v.SalesVolume + v.SalesVolumeInc // discountPrice := v.DiscountPrice // commission := v.Commission // inventory = v.Inventory //sku库存 // // base := v.GetBase() // commission1 := base.Mul(rate1).Round(2) // commission2 := base.Mul(rate2).Round(2) // commission3 := base.Mul(rate3).Round(2) // fmt.Println(commission1, commission2, commission3, base, v.PurchasePrice, v.DiscountPrice) // commission = commission1.Add(commission2).Add(commission3) // // if u.Level == 10 { // commission = v.DiscountPrice.Sub(v.PurchasePrice.Mul(decimal.NewFromFloat(1.03))).Mul(decimal.NewFromFloat(define.Coefficient)).Round(2) // } // // recookGoodsInfoModel := &goods2.RecookGoodsInfoModel{} // list = append(list, QueryCategoryGoodsListResp{ // ID: v.GoodsID, // GoodsName: goodsInfo.GoodsName, // BrandImg: gb.LogoURL, // BrandName: gb.Name + "品牌馆", // BrandId: gb.ID, // Description: goodsInfo.Description, // Inventory: inventory, // SalesVolume: salesVolume, // MainPhotoURL: mainPhoto.URL, // PromotionName: "", // OriginalPrice: v.OriginalPrice, // DiscountPrice: discountPrice, // Commission: commission, // Percent: 0, //百分比,-1不显示 // StartTime: startTime, // EndTime: endTime, // Coupon: v.Coupon, // IsImport: goodsInfo.IsImport, // Storehouse: goodsInfo.Storehouse, // IsFerme: goodsInfo.IsFerme, // HasCoin: recookGoodsInfoModel.HasCoin(goodsInfo.Storehouse), // HasBalance: recookGoodsInfoModel.HasBalance(goodsInfo.Storehouse), // GysId: goodsInfo.VendorID, // CountryIcon: "", // SalePrice: v.GetSalePrice(u.Level), // }) // } // return list //} func GetListByLive(goodsList []goods.Information, userID uint, isSale bool) []QueryCategoryGoodsListResp { return GetGoodsRespByInfoList(goodsList, userID, isSale) } func KeyWordEs(c *gin.Context) { var p queryOrderGoodsListParam if err := tools.ParseParams(&p, c); err != nil { back.Fail(c, err.Error()) return } r := es.IKReq{ Text: p.Keyword, Tokenizer: "ik_smart", } res := es.GetIK(r) back.Suc(c, "", res.Tokens) }