diff --git a/business/jxstore/cms/store_sku.go b/business/jxstore/cms/store_sku.go index 3e69bd1dc..6d137da56 100644 --- a/business/jxstore/cms/store_sku.go +++ b/business/jxstore/cms/store_sku.go @@ -2182,6 +2182,82 @@ func GetTopSkusByStoreIDs(ctx *jxcontext.Context, storeIDs []int) (storeSkuNameE return storeSkuNameExt, err } +func GetTopSkusByCityCode(ctx *jxcontext.Context, cityCode, storeID int) (skuNameAndPlaceList []*dao.SkuNameAndPlace, err error) { + db := dao.GetDB() + orderCreate := time.Now().AddDate(0, -1, 0) + skuNameAndPlace, err := dao.GetTopSkusByCityCode(db, cityCode, orderCreate) + if storeID > 0 { + var skuNameList []*model.SkuName + //未关注,不可售的商品nameID列表 + sql := ` + SELECT DISTINCT b.name_id id,1 brand_id + FROM store_sku_bind a + JOIN sku b ON a.sku_id = b.id AND b.deleted_at = ? + WHERE a.deleted_at = ? + AND a.store_id = ? + AND a.status <> ? + AND b.name_id NOT IN(SELECT DISTINCT b.name_id + FROM store_sku_bind a + JOIN sku b ON a.sku_id = b.id AND b.deleted_at = ? + WHERE a.deleted_at = ? + AND a.store_id = ? + AND a.status = ?) + UNION + SELECT DISTINCT a.name_id id,0 brand_id + FROM sku a + LEFT JOIN (SELECT DISTINCT b.name_id + FROM store_sku_bind a + JOIN sku b ON a.sku_id = b.id + WHERE a.deleted_at = ? + AND store_id = ?)b ON a.name_id = b.name_id + WHERE a.status = ? + AND a.deleted_at = ? + AND b.name_id IS NULL + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, + utils.DefaultTimeValue, + storeID, + model.StoreSkuBindStatusNormal, + utils.DefaultTimeValue, + utils.DefaultTimeValue, + storeID, + model.StoreSkuBindStatusNormal, + utils.DefaultTimeValue, + storeID, + model.StoreSkuBindStatusNormal, + utils.DefaultTimeValue, + } + err = dao.GetRows(db, &skuNameList, sql, sqlParams...) + var skuNameMap = make(map[int]*model.SkuName) + for _, v := range skuNameList { + skuNameMap[v.ID] = v + } + for _, v := range skuNameAndPlace { + if skuNameMap[v.ID] != nil { + midPrice, err := dao.GetMidPriceByNameID(db, cityCode, v.ID, utils.Time2Date(time.Now().AddDate(0, 0, -1))) + if err == nil { + v.Price = midPrice + } + v.Type = skuNameMap[v.ID].BrandID + skuNameAndPlaceList = append(skuNameAndPlaceList, v) + } + } + } else { + skuNameAndPlaceList = append(skuNameAndPlaceList, skuNameAndPlace...) + } + i := 1 + for _, v := range skuNameAndPlaceList { + v.Sequence = i + i++ + } + if len(skuNameAndPlaceList) <= 100 { + return skuNameAndPlaceList, err + } else { + return skuNameAndPlaceList[0:100], err + } +} + func GetTopCategoriesByStoreIDs(ctx *jxcontext.Context, storeIDs []int) (skuCategory []*model.SkuCategory, err error) { var ( skuCategory2 []*model.SkuCategory @@ -2662,3 +2738,88 @@ func WriteToExcelNormal(task *tasksch.SeqTask, fileName string, excelParam []Exc } return err } + +func FocusStoreSkusByExcel(ctx *jxcontext.Context, files []*multipart.FileHeader, isAsync, isContinueWhenError bool) (hint string, err error) { + if len(files) == 0 { + return "", errors.New("没有文件上传!") + } + fileHeader := files[0] + file, err := fileHeader.Open() + hint, err = FocusStoreSkusByExcelBin(ctx, file, isAsync, isContinueWhenError) + file.Close() + return hint, err +} + +func FocusStoreSkusByExcelBin(ctx *jxcontext.Context, reader io.Reader, isAsync, isContinueWhenError bool) (hint string, err error) { + var ( + skuMap = make(map[int]int) + skuNameMap = make(map[int]int) + skuBindInfos []*StoreSkuBindInfo + db = dao.GetDB() + storeIDs []int + skuIDs []int + price int + ) + sheetParam := &SheetParam{ + OutSkuIDCol: 1, + SkuPriceCol: 3, + SkuRow: 1, + } + xlsx, err := excelize.OpenReader(reader) + if err != nil { + return "", err + } + rows, _ := xlsx.GetRows(xlsx.GetSheetName(1)) + for rowNum, row := range rows { + if rowNum < sheetParam.SkuRow { + continue + } + GetCellForFocusStoreSkus(db, rowNum, row, sheetParam, skuMap) + } + for k, _ := range skuMap { + skuIDs = append(skuIDs, k) + } + skuList, err := dao.GetSkus(db, skuIDs, nil, nil, nil) + if err != nil && len(skuList) == 0 { + return + } + for _, v := range skuList { + if v.Unit == model.SpecialUnit { + price = model.SpecialSpecQuality / int(utils.Float64TwoInt64(float64(v.SpecQuality))) * skuMap[v.ID] + } + if skuNameMap[v.NameID] < price { + skuNameMap[v.NameID] = price + } + } + for k, v := range skuNameMap { + skuBindInfo := &StoreSkuBindInfo{ + NameID: k, + UnitPrice: v, + IsFocus: 1, + IsSale: 1, + } + skuBindInfos = append(skuBindInfos, skuBindInfo) + } + storeList, err := dao.GetStoreList(db, nil, nil, "") + for _, v := range storeList { + storeIDs = append(storeIDs, v.ID) + } + hint, err = UpdateStoresSkus(ctx, storeIDs, skuBindInfos, false, isAsync, isContinueWhenError) + return hint, err +} + +func GetCellForFocusStoreSkus(db *dao.DaoDB, rowNum int, row []string, sheetParam *SheetParam, skuMap map[int]int) { + var ( + skuID int + price int + ) + for k, cell := range row { + if k == sheetParam.OutSkuIDCol { + skuID = int(utils.Str2Int64(cell)) + } + if k == sheetParam.SkuPriceCol { + price = int(utils.Float64TwoInt64(utils.Str2Float64(cell) * 100)) + } + } + skuMap[skuID] = price +} diff --git a/business/model/dao/store_sku.go b/business/model/dao/store_sku.go index bd832e69a..89c43e16d 100644 --- a/business/model/dao/store_sku.go +++ b/business/model/dao/store_sku.go @@ -18,6 +18,7 @@ var ( model.VendorIDMTWM: "mtwm_url", model.VendorIDEBAI: "ebai_url", } + salePriceLimit = 100 ) type SkuStoreCatInfo struct { @@ -195,6 +196,15 @@ type StoreSkuExt struct { Times int `json:"times"` } +type SkuNameAndPlace struct { + model.SkuName + CityCode int `json:"cityCode"` + CityName string `json:"cityName"` + Sequence int `json:"sequence"` + Count int `json:"count"` + Type int `json:"type"` +} + // todo 应该通过需要同步的skuid来驱动同步分类,而不是当前这种分开的逻辑 // 单门店模式厂商适用 // 从store_sku_bind中,得到所有依赖的商家分类信息 @@ -1027,7 +1037,7 @@ func GetTopSkusByStoreIDs(db *DaoDB, storeIDs []int) (storeSkuNameExt []*StoreSk ORDER BY t1.count DESC LIMIT ? ` - sqlParams = append(sqlParams, 100, 30) + sqlParams = append(sqlParams, salePriceLimit, 30) err = GetRows(db, &storeSkuNameExt, sql, sqlParams...) var skuNamesInfo = &StoreSkuNamesInfo{ SkuNames: storeSkuNameExt, @@ -1063,6 +1073,32 @@ func GetTopSkusByStoreIDs(db *DaoDB, storeIDs []int) (storeSkuNameExt []*StoreSk return storeSkuNameExt, err } +func GetTopSkusByCityCode(db *DaoDB, cityCode int, orderCreate time.Time) (skuNameAndPlace []*SkuNameAndPlace, err error) { + sql := ` + SELECT SUM(b.count) count, e.name city_name, d.city_code, f.* + FROM goods_order a + JOIN order_sku b ON a.vendor_order_id = b.vendor_order_id AND a.vendor_id = b.vendor_id + JOIN sku c ON b.sku_id = c.id AND c.deleted_at = ? + JOIN sku_name f ON f.id = c.name_id + JOIN store d ON d.id = IF(a.jx_store_id = 0,a.store_id,a.jx_store_id) AND d.deleted_at = ? AND d.city_code = ? + JOIN place e ON e.code = d.city_code + WHERE 1=1 + AND b.sale_price > ? + AND a.created_at BETWEEN ? and NOW() + GROUP BY 2,3,4 + ORDER BY count DESC + ` + sqlParams := []interface{}{ + utils.DefaultTimeValue, + utils.DefaultTimeValue, + cityCode, + salePriceLimit, + orderCreate, + } + err = GetRows(db, &skuNameAndPlace, sql, sqlParams...) + return skuNameAndPlace, err +} + func GetTopCategoriesByStoreIDs(db *DaoDB, storeIDs []int, limit int) (skuCategory []*model.SkuCategory, err error) { sql := ` SELECT DISTINCT t5.* FROM( @@ -1102,7 +1138,7 @@ func GetTopCategoriesByStoreIDs(db *DaoDB, storeIDs []int, limit int) (skuCatego Order by t4.count DESC)t5 LIMIT ? ` - sqlParams = append(sqlParams, time.Now().AddDate(0, -1, 0), 100, 2, utils.DefaultTimeValue, 1, limit) + sqlParams = append(sqlParams, time.Now().AddDate(0, -1, 0), salePriceLimit, 2, utils.DefaultTimeValue, 1, limit) err = GetRows(db, &skuCategory, sql, sqlParams...) return skuCategory, err } @@ -1308,3 +1344,36 @@ func GetDeletedStoreSkuBind(db *DaoDB, storeID, skuID int) (storeSkuBind *model. } return storeSkuBind } + +func GetMidPriceByNameID(db *DaoDB, cityCode, skuNameID int, snapDate time.Time) (midPrice int, err error) { + var ( + storeSkuExt []*StoreSkuExt + price int + skuMap = make(map[int]int) + ) + sql := ` + SELECT a.mid_price bind_price,a.sku_id,b.spec_quality + FROM price_refer_snapshot a + JOIN sku b ON a.sku_id = b.id + JOIN sku_name c ON c.id = b.name_id + WHERE c.id = ? + AND a.snapshot_at = ? + AND a.city_code = ? + ` + sqlParams := []interface{}{ + skuNameID, + snapDate, + cityCode, + } + err = GetRows(db, &storeSkuExt, sql, sqlParams...) + if err != nil { + return 0, err + } + for _, v := range storeSkuExt { + price = model.SpecialSpecQuality / int(utils.Float64TwoInt64(float64(v.SkuSpecQuality))) * v.BindPrice + if skuMap[skuNameID] < price { + skuMap[skuNameID] = price + } + } + return skuMap[skuNameID], err +} diff --git a/controllers/cms_store_sku.go b/controllers/cms_store_sku.go index f99bdacd7..a99af647f 100644 --- a/controllers/cms_store_sku.go +++ b/controllers/cms_store_sku.go @@ -450,7 +450,7 @@ func (c *StoreSkuController) GetMissingStoreSkuFromOrder() { // @Title 根据门店信息查找推荐商品(按销量) // @Description 根据门店信息查找推荐商品(按销量) -// @Param token header string false "认证token" +// @Param token header string true "认证token" // @Param storeIDs query string true "门店列表" // @Success 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult @@ -465,9 +465,24 @@ func (c *StoreSkuController) GetTopSkusByStoreIDs() { }) } +// @Title 根据城市信息查找推荐商品(按销量) +// @Description 根据城市信息查找推荐商品(按销量) +// @Param token header string true "认证token" +// @Param cityCode query int true "城市id" +// @Param storeID query int false "门店id" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetTopSkusByCityCode [get] +func (c *StoreSkuController) GetTopSkusByCityCode() { + c.callGetTopSkusByCityCode(func(params *tStoreSkuGetTopSkusByCityCodeParams) (retVal interface{}, errCode string, err error) { + retVal, err = cms.GetTopSkusByCityCode(params.Ctx, params.CityCode, params.StoreID) + return retVal, "", err + }) +} + // @Title 根据门店信息查找推荐分类(按商品销量) // @Description 根据门店信息查找推荐分类(按商品销量) -// @Param token header string false "认证token" +// @Param token header string true "认证token" // @Param storeIDs query string true "门店列表" // @Success 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult @@ -520,6 +535,23 @@ func (c *StoreSkuController) RefreshJxPriceByExcel() { }) } +// @Title 根据Excel中SkuID批量关注商品 +// @Description 根据Excel中SkuID批量关注商品 +// @Param token header string true "认证token" +// @Param isAsync formData bool true "是否异步,缺省是同步" +// @Param isContinueWhenError formData bool true "单个同步失败是否继续,缺省false" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /FocusStoreSkusByExcel [post] +func (c *StoreSkuController) FocusStoreSkusByExcel() { + c.callFocusStoreSkusByExcel(func(params *tStoreSkuFocusStoreSkusByExcelParams) (retVal interface{}, errCode string, err error) { + r := c.Ctx.Request + files := r.MultipartForm.File["userfiles"] + retVal, err = cms.FocusStoreSkusByExcel(params.Ctx, files, params.IsAsync, params.IsContinueWhenError) + return retVal, "", err + }) +} + // @Title 得到门店的分类列表 // @Description 得到门店的分类列表(按商品销量) // @Param token header string false "认证token" diff --git a/routers/commentsRouter_controllers.go b/routers/commentsRouter_controllers.go index 2b51ceb30..c6d91884e 100644 --- a/routers/commentsRouter_controllers.go +++ b/routers/commentsRouter_controllers.go @@ -1611,6 +1611,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], + beego.ControllerComments{ + Method: "FocusStoreSkusByExcel", + Router: `/FocusStoreSkusByExcel`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], beego.ControllerComments{ Method: "GetMissingStoreSkuFromOrder", @@ -1674,6 +1683,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], + beego.ControllerComments{ + Method: "GetTopSkusByCityCode", + Router: `/GetTopSkusByCityCode`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreSkuController"], beego.ControllerComments{ Method: "GetTopSkusByStoreIDs",