package report import ( "errors" "fmt" "math" "sort" "time" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" "git.rosy.net.cn/jx-callback/business/partner/purchase/jd" "git.rosy.net.cn/jx-callback/globals/api/apimanager" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/jxutils/jxcontext" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" ) type tStoreSkuBindAndSkuName struct { CityCode int StoreID int `orm:"column(store_id)"` NameID int `orm:"column(name_id)"` UnitPrice int UnitPriceList []int } func GetStatisticsReportForOrders(ctx *jxcontext.Context, storeIDs []int, fromDate string, toDate string) (statisticsReportForOrdersList []*dao.StatisticsReportForOrdersList, err error) { db := dao.GetDB() fromDateParm := utils.Str2Time(fromDate) toDateParm := utils.Str2Time(toDate) //若时间间隔大于3个月则不允许查询 if math.Ceil(toDateParm.Sub(fromDateParm).Hours()/24) > 92 { return nil, errors.New(fmt.Sprintf("查询间隔时间不允许大于3个月!: 时间范围:[%v] 至 [%v]", fromDate, toDate)) } statisticsReportForOrdersList, err = dao.GetStatisticsReportForOrders(db, storeIDs, fromDateParm, toDateParm) return statisticsReportForOrdersList, err } func GetStatisticsReportForAfsOrders(ctx *jxcontext.Context, storeIDs []int, fromDate string, toDate string) (statisticsReportForOrdersList []*dao.StatisticsReportForOrdersList, err error) { db := dao.GetDB() fromDateParm := utils.Str2Time(fromDate) toDateParm := utils.Str2Time(toDate) //若时间间隔大于3个月则不允许查询 if math.Ceil(toDateParm.Sub(fromDateParm).Hours()/24) > 92 { return nil, errors.New(fmt.Sprintf("查询间隔时间不允许大于3个月!: 时间范围:[%v] 至 [%v]", fromDate, toDate)) } statisticsReportForOrdersList, err = dao.GetGetStatisticsReportForAfsOrders(db, storeIDs, fromDateParm, toDateParm) return statisticsReportForOrdersList, err } func StatisticsReportForStoreSkusPrice(ctx *jxcontext.Context, cityCodes, skuIDs []int, snapDate string, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) { var snapDateParam time.Time db := dao.GetDB() if snapDate != "" { snapDateParam = utils.Str2Time(snapDate) } priceReferSnapshot, totalCount, err := dao.GetPriceReferSnapshot(db, cityCodes, skuIDs, 0, snapDateParam, offset, pageSize) pagedInfo = &model.PagedInfo{ Data: priceReferSnapshot, TotalCount: totalCount, } return } func BeginSavePriceRefer(ctx *jxcontext.Context, cityCodes, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) { var priceReferSnapshotList []*model.PriceReferSnapshot db := dao.GetDB() snapshotAt := utils.Time2Date(time.Now().AddDate(0, 0, -1)) dao.DeletePriceReferHistory(db, utils.Time2Date(snapshotAt.AddDate(0, 0, -7))) priceReferSnapshotDelete := &model.PriceReferSnapshot{SnapshotAt: snapshotAt} dao.DeleteEntity(db, priceReferSnapshotDelete, "SnapshotAt") taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) { switch step { case 0: priceReferSnapshot, err := dao.GetStatisticsReportForStoreSkusPrice(db, cityCodes, skuIDs) if len(priceReferSnapshot) > 0 { dao.Begin(db) defer func() { if r := recover(); r != nil || err != nil { dao.Rollback(db) if r != nil { panic(r) } } }() for _, v := range priceReferSnapshot { dao.WrapAddIDCULDEntity(v, ctx.GetUserName()) v.SnapshotAt = snapshotAt } dao.CreateMultiEntities(db, priceReferSnapshot) dao.Commit(db) } case 1: priceReferSnapshotList, err = dao.GetPriceReferSnapshotNoPage(db, nil, nil, nil, snapshotAt) var ( citySkuMap = make(map[int]map[int][]int) countryMap = make(map[int][]int) resultMap = make(map[int]map[int]*model.PriceReferSnapshot) resultCountryMap = make(map[int]*model.PriceReferSnapshot) ) storeList, err := dao.GetStoreList(db, nil, nil, nil, nil, "") if err != nil { return result, err } for _, v := range storeList { if v.PayPercentage < 50 { continue } var tList []*tStoreSkuBindAndSkuName sql := ` SELECT DISTINCT b.city_code, a.store_id, Round(a.unit_price * IF(b.pay_percentage < 50 , 70, b.pay_percentage) / 100) AS unit_price, c.name_id FROM store_sku_bind a JOIN store b ON b.id = a.store_id AND b.deleted_at = ? AND b.status != ? JOIN sku c ON c.id = a.sku_id WHERE a.store_id = ? AND c.name_id NOT IN( SELECT 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 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 = ?) ) AND a.deleted_at = ? ` sqlParams := []interface{}{ utils.DefaultTimeValue, model.StoreStatusDisabled, v.ID, utils.DefaultTimeValue, utils.DefaultTimeValue, v.ID, utils.DefaultTimeValue, utils.DefaultTimeValue, v.ID, model.StoreSkuBindStatusNormal, utils.DefaultTimeValue, } dao.GetRows(db, &tList, sql, sqlParams...) skuNameMap := make(map[int][]int) if len(tList) > 0 { for _, vv := range tList { skuNameMap[vv.NameID] = append(skuNameMap[vv.NameID], vv.UnitPrice) countryMap[vv.NameID] = append(countryMap[vv.NameID], vv.UnitPrice) } if citySkuMap[v.CityCode] != nil { for nameID, unitPriceList := range skuNameMap { if citySkuMap[v.CityCode][nameID] != nil { citySkuMap[v.CityCode][nameID] = append(citySkuMap[v.CityCode][nameID], unitPriceList...) } else { citySkuMap[v.CityCode][nameID] = unitPriceList } } } else { citySkuMap[v.CityCode] = skuNameMap } } } for k, v := range countryMap { var midUnitPrice int var avgUnitPrice int sort.Ints(v) if len(v)%2 == 0 { midUnitPrice = v[len(v)/2-1] } else { midUnitPrice = v[len(v)/2] } for _, vv := range v { avgUnitPrice += vv } priceRefer := &model.PriceReferSnapshot{ MidUnitPrice: midUnitPrice, MaxUnitPrice: v[len(v)-1], MinUnitPrice: v[0], AvgUnitPrice: avgUnitPrice / len(v), } resultCountryMap[k] = priceRefer } for k1, v := range citySkuMap { skuNameMap := make(map[int]*model.PriceReferSnapshot) for k2, _ := range v { var midUnitPrice int var avgUnitPrice int sort.Ints(v[k2]) if len(v[k2])%2 == 0 { midUnitPrice = v[k2][len(v[k2])/2-1] } else { midUnitPrice = v[k2][len(v[k2])/2] } for _, vv := range v[k2] { avgUnitPrice += vv } skuNameMap[k2] = &model.PriceReferSnapshot{ MidUnitPrice: midUnitPrice, MaxUnitPrice: v[k2][len(v[k2])-1], MinUnitPrice: v[k2][0], AvgUnitPrice: avgUnitPrice / len(v[k2]), } } resultMap[k1] = skuNameMap } dao.Begin(db) defer func() { if r := recover(); r != nil || err != nil { dao.Rollback(db) if r != nil { panic(r) } } }() if len(priceReferSnapshotList) > 0 { for _, v := range priceReferSnapshotList { if v.CityCode == 0 { if resultCountryMap[v.NameID] != nil { v.MidUnitPrice = resultCountryMap[v.NameID].MidUnitPrice v.MaxUnitPrice = resultCountryMap[v.NameID].MaxUnitPrice v.AvgUnitPrice = resultCountryMap[v.NameID].AvgUnitPrice v.MinUnitPrice = resultCountryMap[v.NameID].MinUnitPrice dao.UpdateEntity(db, v, "MidUnitPrice", "MaxUnitPrice", "MinUnitPrice", "AvgUnitPrice") } continue } if resultMap[v.CityCode][v.NameID] != nil { v.MidUnitPrice = resultMap[v.CityCode][v.NameID].MidUnitPrice v.MaxUnitPrice = resultMap[v.CityCode][v.NameID].MaxUnitPrice v.AvgUnitPrice = resultMap[v.CityCode][v.NameID].AvgUnitPrice v.MinUnitPrice = resultMap[v.CityCode][v.NameID].MinUnitPrice dao.UpdateEntity(db, v, "MidUnitPrice", "MaxUnitPrice", "MinUnitPrice", "AvgUnitPrice") } } } dao.Commit(db) case 2: dao.Begin(db) defer func() { if r := recover(); r != nil || err != nil { dao.Rollback(db) if r != nil { panic(r) } } }() if len(priceReferSnapshotList) > 0 { for _, v := range priceReferSnapshotList { result, _ := dao.GetPriceReferPrice(db, v.CityCode, v.SkuID, snapshotAt) v.MaxPrice = result.MaxPrice v.MinPrice = result.MinPrice v.AvgPrice = result.AvgPrice v.MidPrice = result.MidPrice dao.UpdateEntity(db, v, "MidPrice", "MaxPrice", "MinPrice", "AvgPrice") } } dao.Commit(db) case 3: priceReferSnapshotList, err = dao.GetPriceReferSnapshotNoPage(db, []int{0}, nil, nil, snapshotAt) taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { v := batchItemList[0].(*model.PriceReferSnapshot) for _, appOrg := range apimanager.CurAPIManager.GetAppOrgCodeList(model.VendorIDJD) { directPrice, _ := jd.GetAPI(appOrg).GetJdSkuDirectPrice(v.SkuID) v.JdDirectPrice = int(directPrice) dao.UpdateEntity(db, v, "JdDirectPrice") } return retVal, err } taskParallel := tasksch.NewParallelTask("获取并更新京东指导价格", tasksch.NewParallelConfig(), ctx, taskFunc, priceReferSnapshotList) tasksch.HandleTask(taskParallel, task, true).Run() _, err = taskParallel.GetResult(0) } return result, err } taskSeq := tasksch.NewSeqTask2("生成每日价格统计", ctx, isContinueWhenError, taskSeqFunc, 4) tasksch.HandleTask(taskSeq, nil, true).Run() if !isAsync { _, err = taskSeq.GetResult(0) hint = "1" } else { hint = taskSeq.GetID() } return hint, err }