Accept Merge Request #6: (don -> mark)

Merge Request: 城市商品销量统计
Created By: @zhudan
Accepted By: @xujianhua
URL: https://rosydev.coding.net/p/jx-callback/d/jx-callback/git/merge/6
This commit is contained in:
xujianhua
2019-09-20 15:25:39 +08:00
parent 92cdb1d975
commit c5df4f5f5e
5 changed files with 290 additions and 0 deletions

View File

@@ -0,0 +1,171 @@
package misc
import (
"math"
"sync"
"git.rosy.net.cn/jx-callback/business/jxstore/cms"
"git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
)
const (
DayNum = 30 //请求天数
LimitNum = 100 //最大数据限制
)
func GetStoreSkuSalesInfo(ctx *jxcontext.Context, storeID int) (outStoreSkuSales []*model.StoreSkuSales, err error) {
db := dao.GetDB()
//得到所有门店
storeList, err := GetStoreList(ctx)
if err == nil {
storeList = GetFilterStoreListEx(storeList, nil)
} else {
return nil, err
}
storeMapData := make(map[int]*cms.StoreExt)
for _, value := range storeList {
storeMapData[value.ID] = value
}
curStoreInfo := storeMapData[storeID]
cityCode := curStoreInfo.CityCode
//获取本市商品总销量
citySkuSalesCntMap := make(map[int]int)
citySkuSalesCntList, err := dao.GetSkuSalesCntList(db, -1, cityCode, DayNum, LimitNum, nil)
citySkuIDs := []int{}
if err == nil {
for _, value := range citySkuSalesCntList {
citySkuSalesCntMap[value.SkuID] = value.Count
citySkuIDs = append(citySkuIDs, value.SkuID)
}
} else {
return nil, err
}
//获取本店商品总销量
storeSkuSalesCntMap := make(map[int]int)
storeSkuSalesCntList, err := dao.GetSkuSalesCntList(db, storeID, cityCode, DayNum, -1, citySkuIDs)
if err == nil {
for _, value := range storeSkuSalesCntList {
storeSkuSalesCntMap[value.SkuID] = value.Count
}
} else {
return nil, err
}
//获取本店商品差评数量
storeSkuBadCommentCntMap := make(map[int]int)
storeSkuBadCommentCntList, err := dao.GetSkuBadCommentCntList(db, storeID, DayNum)
if err == nil {
for _, value := range storeSkuBadCommentCntList {
storeSkuBadCommentCntMap[value.SkuID] = value.Count
}
} else {
return nil, err
}
//得到当前门店商品数据
storeSkuMapData := make(map[int]*cms.StoreSkuNameExt)
storeSkuData, err := cms.GetStoreSkus(ctx, storeID, citySkuIDs, true, "", true, map[string]interface{}{}, 0, -1)
if err == nil {
for _, value := range storeSkuData.SkuNames {
for _, skuInfo := range value.Skus2 {
storeSkuMapData[skuInfo.SkuID] = value
}
}
} else {
return nil, err
}
//得到5KM内的所有门店
rangeStoreList := GetRangeStoreList(storeID, curStoreInfo.FloatLng, curStoreInfo.FloatLat, SaleSkuCheckRange, storeList)
//得到5KM内的所有门店的商品的价格
allStoreSkus := make(map[int]map[int]int)
var locker sync.RWMutex
taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
storeInfo := batchItemList[0].(*cms.StoreExt)
storeID := storeInfo.ID
jxSkuInfoData, err := cms.GetStoreSkus(ctx, storeID, citySkuIDs, true, "", true, map[string]interface{}{}, 0, -1)
jxSkuPriceMapData := make(map[int]int)
for _, value := range jxSkuInfoData.SkuNames {
for _, skuInfo := range value.Skus2 {
jxSkuPriceMapData[skuInfo.SkuID] = skuInfo.BindPrice
}
}
locker.Lock()
defer locker.Unlock()
allStoreSkus[storeID] = jxSkuPriceMapData
return retVal, err
}
taskParallel := tasksch.NewParallelTask("得到所有门店商品", nil, ctx, taskFunc, rangeStoreList)
taskParallel.Run()
_, err = taskParallel.GetResult(0)
if err != nil {
return nil, err
}
//计算商品的平均价格
skusTotalPrice := make(map[int]int)
skusCount := make(map[int]int)
skusAveragePrice := make(map[int]int)
for _, storeInfo := range rangeStoreList {
storeID := storeInfo.ID
storeSkuMapData := allStoreSkus[storeID]
for skuID, skuPrice := range storeSkuMapData {
skusTotalPrice[skuID] += skuPrice
skusCount[skuID]++
}
}
for id, totalPrice := range skusTotalPrice {
skusAveragePrice[id] = int(math.Round(float64(totalPrice) / float64(skusCount[id])))
}
//输出商品销量统计结果
skuAndNameMapData := make(map[int]*model.SkuAndName)
if len(storeSkuMapData) < len(citySkuIDs) {
skuAndNameList, err := dao.GetSkus(db, citySkuIDs, nil, nil, nil)
if err == nil {
for _, value := range skuAndNameList {
skuAndNameMapData[value.ID] = value
}
}
}
for _, value := range citySkuSalesCntList {
skuID := value.SkuID
storeSkuSales := &model.StoreSkuSales{}
storeSkuSales.SkuID = skuID
storeSkuInfo := storeSkuMapData[skuID]
skuAndNameInfo := skuAndNameMapData[skuID]
if storeSkuInfo != nil {
skuName := storeSkuInfo.SkuName
skuInfo := storeSkuInfo.Skus2[0]
storeSkuSales.SkuName = jxutils.ComposeSkuName(skuName.Prefix, skuName.Name, skuInfo.Comment, skuName.Unit, skuInfo.SkuSpecQuality, skuInfo.SkuSpecUnit, 0)
storeSkuSales.SkuImage = storeSkuInfo.Img
storeSkuSales.SkuPrice = jxutils.IntPrice2StandardCurrencyString(int64(storeSkuInfo.Skus2[0].BindPrice))
} else if skuAndNameInfo != nil {
skuNameList, err := dao.GetSkuNames(db, []int{skuAndNameInfo.NameID})
prefix := ""
if err == nil && len(skuNameList) > 0 {
storeSkuSales.SkuImage = skuNameList[0].Img
prefix = skuNameList[0].Prefix
}
storeSkuSales.SkuName = jxutils.ComposeSkuName(prefix, skuAndNameInfo.Name, skuAndNameInfo.Comment, skuAndNameInfo.Unit, skuAndNameInfo.SpecQuality, skuAndNameInfo.SpecUnit, 0)
storeSkuSales.SkuPrice = "N/A"
} else {
storeSkuSales.SkuName = "N/A"
storeSkuSales.SkuPrice = "N/A"
}
storeSkuSales.SkuAvgPrice = jxutils.IntPrice2StandardCurrencyString(int64(skusAveragePrice[skuID]))
storeSkuSales.BadCommentCnt = storeSkuBadCommentCntMap[skuID]
storeSkuSales.StoreSkuSalesCnt = storeSkuSalesCntMap[skuID]
storeSkuSales.CitySkuSalesCnt = citySkuSalesCntMap[skuID]
outStoreSkuSales = append(outStoreSkuSales, storeSkuSales)
}
return outStoreSkuSales, err
}

View File

@@ -0,0 +1,78 @@
package dao
import (
"time"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/model"
)
func GetSkuSalesCntList(db *DaoDB, storeID, cityCode, dayNum, limit int, skuIDs []int) (skuCountList []*model.SkuCount, err error) {
sql := `
SELECT t2.jx_sku_id sku_id, SUM(t2.count) count
FROM goods_order t1
JOIN order_sku t2 on t1.vendor_order_id = t2.vendor_order_id and t1.vendor_id = t2.vendor_id
JOIN store t3 on t1.jx_store_id = t3.id
WHERE t1.order_finished_at >= ? AND t1.order_finished_at < ?
AND t1.status = ?
AND t2.jx_sku_id <> 0
AND t3.city_code = ?
`
if dayNum < 0 {
dayNum = 30
}
beginTime := utils.GetCurDate().Add(-time.Hour * 24 * time.Duration(dayNum))
endTime := utils.GetCurDate()
sqlParams := []interface{}{
beginTime,
endTime,
model.OrderStatusFinished,
cityCode,
}
if storeID > 0 {
sql += `
AND t1.jx_store_id = ?
`
sqlParams = append(sqlParams, storeID)
}
if len(skuIDs) > 0 {
sql += `
AND t2.jx_sku_id IN (` + GenQuestionMarks(len(skuIDs)) + `)`
sqlParams = append(sqlParams, skuIDs)
}
sql += `
GROUP BY jx_sku_id
ORDER BY count DESC
`
if limit > 0 {
sql += `
LIMIT ?
`
sqlParams = append(sqlParams, limit)
}
err = GetRows(db, &skuCountList, sql, sqlParams)
return skuCountList, err
}
func GetSkuBadCommentCntList(db *DaoDB, storeID, dayNum int) (skuCountList []*model.SkuCount, err error) {
sql := `
SELECT t2.jx_sku_id sku_id, COUNT(*) count
FROM jx_bad_comments t1
JOIN order_sku t2 ON t1.order_id = t2.vendor_order_id
WHERE t1.createtime >= ? AND t1.createtime < ?
AND t1.jxstoreid = ?
GROUP BY t2.jx_sku_id
`
if dayNum < 0 {
dayNum = 30
}
beginTime := utils.GetCurDate().Add(-time.Hour * 24 * time.Duration(dayNum))
endTime := utils.GetCurDate()
sqlParams := []interface{}{
beginTime,
endTime,
storeID,
}
err = GetRows(db, &skuCountList, sql, sqlParams)
return skuCountList, err
}

View File

@@ -0,0 +1,17 @@
package model
type StoreSkuSales struct {
SkuID int `json:"skuID"`
SkuName string `json:"skuName"`
SkuImage string `json:"skuImage"`
SkuPrice string `json:"skuPrice"`
SkuAvgPrice string `json:"skuAvgPrice"`
BadCommentCnt int `json:"badCommentCnt"`
StoreSkuSalesCnt int `json:"storeSkuSalesCnt"`
CitySkuSalesCnt int `json:"citySkuSalesCnt"`
}
type SkuCount struct {
SkuID int `orm:"column(sku_id)"`
Count int
}

View File

@@ -3,6 +3,7 @@ package controllers
import (
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxstore/cms"
"git.rosy.net.cn/jx-callback/business/jxstore/misc"
"git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
@@ -359,3 +360,17 @@ func (c *SkuController) SortCategorySkus() {
return retVal, "", err
})
}
// @Title 按照当前城市近30天销量排序显示本店价格附近5公里平均价格差评数量本店销量情况本市总销量
// @Description 按照当前城市近30天销量排序显示本店价格附近5公里平均价格差评数量本店销量情况本市总销量
// @Param token header string true "认证token"
// @Param storeID query int true "京西门店ID"
// @Success 200 {object} controllers.CallResult
// @Failure 200 {object} controllers.CallResult
// @router /GetStoreSkuSalesInfo [get]
func (c *SkuController) GetStoreSkuSalesInfo() {
c.callGetStoreSkuSalesInfo(func(params *tSkuGetStoreSkuSalesInfoParams) (retVal interface{}, errCode string, err error) {
retVal, err = misc.GetStoreSkuSalesInfo(params.Ctx, params.StoreID)
return retVal, "", err
})
}

View File

@@ -1161,6 +1161,15 @@ func init() {
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"],
beego.ControllerComments{
Method: "GetStoreSkuSalesInfo",
Router: `/GetStoreSkuSalesInfo`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:SkuController"],
beego.ControllerComments{
Method: "GetVendorCategories",