package report import ( "errors" "fmt" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" "math" "sort" "strings" "time" "git.rosy.net.cn/baseapi/platformapi/mtwmapi" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/partner" "git.rosy.net.cn/jx-callback/business/jxstore/permission" "git.rosy.net.cn/jx-callback/business/jxutils/tasksch" "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, vendorIDs []int, fromDate, toDate, marketPhone, jdPhone, mtPhone, ebaiPhone 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, vendorIDs, fromDateParm, toDateParm, marketPhone, jdPhone, mtPhone, ebaiPhone) 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 { txDB, _ := dao.Begin(db) defer func() { if r := recover(); r != nil || err != nil { dao.Rollback(db, txDB) if r != nil { panic(r) } } }() for _, v := range priceReferSnapshot { dao.WrapAddIDCULDEntity(v, ctx.GetUserName()) v.SnapshotAt = snapshotAt } dao.CreateMultiEntities(db, priceReferSnapshot) dao.Commit(db, txDB) } 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, 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 } 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") } } } case 2: if len(priceReferSnapshotList) > 0 { for _, v := range priceReferSnapshotList { result, _ := dao.GetPriceReferPrice(db, v.CityCode, v.SkuID, snapshotAt) if result != nil { v.MaxPrice = result.MaxPrice v.MinPrice = result.MinPrice v.AvgPrice = result.AvgPrice v.MidPrice = result.MidPrice dao.UpdateEntity(db, v, "MidPrice", "MaxPrice", "MinPrice", "AvgPrice") } } } //TODO 京东查询接口报错,暂时屏蔽了 // 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, 3) tasksch.HandleTask(taskSeq, nil, true).Run() if !isAsync { _, err = taskSeq.GetResult(0) hint = "1" } else { hint = taskSeq.GetID() } return hint, err } type GetManageStateResult struct { OpenStoreCount int `json:"openStoreCount"` //营业店铺数 HaveRestStoreCount int `json:"haveRestStoreCount"` //临时休息店铺数 RestStoreCount int `json:"restStoreCount"` //休息店铺数 FinishOrderState *GetManageStateOrderInfo //完成订单情况 IngOrderState *GetManageStateOrderInfo //进行中订单情况 CancelOrderState *GetManageStateOrderInfo //取消订单情况 } type GetManageStateOrderInfo struct { ActualPayPrice int `json:"actualPayPrice"` //支付总额 TotalShopMoney int `json:"totalShopMoney"` //平台结算 DesiredFee int `json:"desiredFee"` //配送费 Yhld string `json:"yhld"` //优惠力度(支付总额-平台结算-配送支出)/支付总额*100% } func getStoreStatusCount(db *dao.DaoDB, cityCodes []int, vendorID, status int) (count int, err error) { countType := &struct{ Count int }{} sqlParams := []interface{}{} sql := ` SELECT COUNT(DISTINCT a.id) count FROM store a LEFT JOIN store_map b ON a.id = b.store_id AND b.deleted_at = ? WHERE a.deleted_at = ? ` sqlParams = append(sqlParams, utils.DefaultTimeValue, utils.DefaultTimeValue) if len(cityCodes) > 0 { sql += " AND a.city_code IN (" + dao.GenQuestionMarks(len(cityCodes)) + ")" sqlParams = append(sqlParams, cityCodes) } if vendorID != -1 { sql += " AND b.vendor_id = ? AND b.status = ?" sqlParams = append(sqlParams, vendorID, status) } else { sql += " AND a.status = ?" sqlParams = append(sqlParams, status) } err = dao.GetRow(db, &countType, sql, sqlParams) return countType.Count, err } func getOrderStateCount(db *dao.DaoDB, cityCodes []int, vendorID, status int) (getManageStateOrderInfo *GetManageStateOrderInfo, err error) { sqlParams := []interface{}{} getManageStateOrderInfo = &GetManageStateOrderInfo{} endTime := time.Now().AddDate(0, -3, 0) sql := ` SELECT SUM(b.actual_pay_price) actual_pay_price, SUM(b.total_shop_money) total_shop_money, SUM(IFNULL(c.desired_fee, 0)) desired_fee FROM store a LEFT JOIN goods_order b ON a.id = IF(b.jx_store_id = 0, b.store_id, b.jx_store_id) LEFT JOIN waybill c ON IF(b.waybill_vendor_id = -1,b.vendor_order_id,b.vendor_waybill_id) = c.vendor_waybill_id WHERE a.deleted_at = ? AND a.status <> ? AND b.order_created_at < ? AND b.order_created_at > ? ` sqlParams = append(sqlParams, utils.DefaultTimeValue, model.StoreStatusDisabled, time.Now(), endTime) if len(cityCodes) > 0 { sql += " AND a.city_code IN (" + dao.GenQuestionMarks(len(cityCodes)) + ")" sqlParams = append(sqlParams, cityCodes) } if vendorID != -1 { sql += " AND b.vendor_id = ?" sqlParams = append(sqlParams, vendorID) } if status != model.OrderStatusDelivering { sql += " AND b.status = ?" sqlParams = append(sqlParams, status) } else { sql += " AND b.status < ? AND b.status >= ?" sqlParams = append(sqlParams, model.OrderStatusEndBegin, model.OrderStatusWait4Pay) } err = dao.GetRow(db, &getManageStateOrderInfo, sql, sqlParams) getManageStateOrderInfo.Yhld = utils.Float64ToStr(math.Round((float64(getManageStateOrderInfo.ActualPayPrice-getManageStateOrderInfo.TotalShopMoney-getManageStateOrderInfo.DesiredFee) / float64(getManageStateOrderInfo.ActualPayPrice) * 100))) + "%" return getManageStateOrderInfo, err } func GetManageState(ctx *jxcontext.Context, cityCodes []int, vendorID int) (getManageStateResult *GetManageStateResult, err error) { var ( db = dao.GetDB() ) getManageStateResult = &GetManageStateResult{} if openCount, err := getStoreStatusCount(db, cityCodes, vendorID, model.StoreStatusOpened); err == nil { getManageStateResult.OpenStoreCount = openCount } if haveRestCount, err := getStoreStatusCount(db, cityCodes, vendorID, model.StoreStatusHaveRest); err == nil { getManageStateResult.HaveRestStoreCount = haveRestCount } if restCount, err := getStoreStatusCount(db, cityCodes, vendorID, model.StoreStatusClosed); err == nil { getManageStateResult.RestStoreCount = restCount } if finishCount, err := getOrderStateCount(db, cityCodes, vendorID, model.OrderStatusFinished); err == nil { getManageStateResult.FinishOrderState = finishCount } if ingCount, err := getOrderStateCount(db, cityCodes, vendorID, model.OrderStatusDelivering); err == nil { getManageStateResult.IngOrderState = ingCount } if cancelCount, err := getOrderStateCount(db, cityCodes, vendorID, model.OrderStatusCanceled); err == nil { getManageStateResult.CancelOrderState = cancelCount } return getManageStateResult, err } func RefreshStoreManageState(ctx *jxcontext.Context, storeIDs []int, vendorIDs []int) { var ( db = dao.GetDB() //vendorIDs = []int{model.VendorIDJD, model.VendorIDMTWM, model.VendorIDEBAI} messageFlag = time.Now().Hour() == 10 && time.Now().Minute() > 0 && time.Now().Minute() < 12 ) task := tasksch.NewParallelTask("RefreshStoreManageState", tasksch.NewParallelConfig().SetParallelCount(3).SetIsContinueWhenError(true), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { vendorID := batchItemList[0].(int) storeMaps, err := dao.GetStoresMapList(db, []int{vendorID}, storeIDs, []int{model.StoreStatusOpened, model.StoreStatusClosed, model.StoreStatusHaveRest}, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "") storeManageStates, err := dao.GetStoreManageStateSimple(db, storeIDs, nil, vendorID) var ( storeMapsMap = make(map[int]*model.StoreMap) storeManagesMap = make(map[int]*model.StoreManageState) deleteList []int createList, updateList []*model.StoreMap ) for _, v := range storeMaps { storeMapsMap[v.StoreID] = v } for _, v := range storeManageStates { storeManagesMap[v.StoreID] = v if storeMapsMap[v.StoreID] != nil { updateList = append(updateList, storeMapsMap[v.StoreID]) } else { deleteList = append(deleteList, v.StoreID) } } for _, v := range storeMapsMap { if storeManagesMap[v.StoreID] == nil { createList = append(createList, v) } } task2 := tasksch.NewParallelTask("deleteList", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { storeID := batchItemList[0].(int) storeManage := &model.StoreManageState{ StoreID: storeID, VendorID: vendorID, } dao.DeleteEntity(db, storeManage, "StoreID", "VendorID") return retVal, err }, deleteList) tasksch.HandleTask(task2, task, true).Run() task2.GetResult(0) task3 := tasksch.NewParallelTask("createList", tasksch.NewParallelConfig().SetParallelCount(20).SetIsContinueWhenError(true), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { storeMap := batchItemList[0].(*model.StoreMap) if storeMap.VendorOrgCode == "" || storeMap.VendorStoreID == "" { return retVal, err } storeDetail, _ := dao.GetStoreDetail(db, storeMap.StoreID, vendorID, storeMap.VendorOrgCode) if storeDetail == nil { return retVal, err } storeManage := buildStoreManageState(ctx, db, storeMap, storeDetail, messageFlag) if storeManage == nil { return retVal, err } dao.CreateEntity(db, storeManage) return retVal, err }, createList) tasksch.HandleTask(task3, task, true).Run() task3.GetResult(0) task4 := tasksch.NewParallelTask("updateList", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(true), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { storeMap := batchItemList[0].(*model.StoreMap) if storeMap.VendorOrgCode == "" || storeMap.VendorStoreID == "" { return retVal, err } storeDetail, _ := dao.GetStoreDetail(db, storeMap.StoreID, vendorID, storeMap.VendorOrgCode) if storeDetail == nil { return retVal, err } storeManage := buildStoreManageState(ctx, db, storeMap, storeDetail, messageFlag) if storeManage == nil { return retVal, err } if storeManageStates, err := dao.GetStoreManageStateSimple(db, []int{storeDetail.ID}, nil, vendorID); err == nil && len(storeManageStates) > 0 { storeManage.ID = storeManageStates[0].ID dao.UpdateEntity(db, storeManage) } return retVal, err }, updateList) tasksch.HandleTask(task4, task, true).Run() task4.GetResult(0) return retVal, err }, vendorIDs) tasksch.HandleTask(task, nil, true).Run() task.GetID() } func buildStoreManageState(ctx *jxcontext.Context, db *dao.DaoDB, storeMap *model.StoreMap, storeDetail *dao.StoreDetail, messageFlag bool) *model.StoreManageState { var ( dayTimeBegin, dayTimeEnd = utils.Str2Time(utils.Time2Str(utils.Time2Date(time.Now())) + "00:00:00"), utils.Str2Time(utils.Time2Str(utils.Time2Date(time.Now())) + "23:59:59") ) storeManage := &model.StoreManageState{ StoreID: storeMap.StoreID, VendorID: storeMap.VendorID, } dao.WrapAddIDCULEntity(storeManage, ctx.GetUserName()) handler := partner.GetPurchasePlatformFromVendorID(storeMap.VendorID) store, err := handler.ReadStore(ctx, storeDetail.VendorOrgCode, storeDetail.VendorStoreID, storeDetail.VendorStoreName) if err != nil || store == nil { return nil } // if coverAreaFlag { if storeMap.VendorID == model.VendorIDJD && store.DeliveryRangeType != model.DeliveryRangeTypePolygon { storeManage.CoverArea = utils.Str2Float64(fmt.Sprintf("%.2f", math.Pi*utils.Str2Float64WithDefault(store.DeliveryRange, 0)/float64(1000)*utils.Str2Float64WithDefault(store.DeliveryRange, 0)/float64(1000))) } else { storeManage.CoverArea = utils.Str2Float64(fmt.Sprintf("%.2f", CalculateCoverArea(strings.Split(store.DeliveryRange, ";"), storeMap.VendorID))) } // } //营业状态 storeManage.VendorStatus = store.Status //不一致发消息 //if messageFlag { // vendorStatus, status := -1, -1 // if store.Status == model.StoreStatusOpened { // vendorStatus = 1 // } // if storeDetail.Status == model.StoreStatusOpened { // status = 1 // } // //statusMap := map[int]string{ // // 1: "营业", // // -1: "休息", // //} // //if vendorStatus != status { // // content := "您的门店 [" + storeDetail.Name + "],ID:[" + utils.Int2Str(storeDetail.ID) + "],在[" + model.VendorChineseNames[storeMap.VendorID] + "] 平台上营业状态和京西不一致!平台状态:【" + statusMap[vendorStatus] + "】,京西状态:【" + statusMap[status] + "】" // // if user, err := dao.GetUserByID(db, "mobile", storeDetail.MarketManPhone); err == nil { // // ddmsg.SendUserMessage(dingdingapi.MsgTyeText, user.UserID, "平台门店状态变化", content) // // } // //} //} //营业时长 optime := jxutils.JxOperationTime2TimeByDate(storeDetail.CloseTime1, time.Now()).Sub(jxutils.JxOperationTime2TimeByDate(storeDetail.OpenTime1, time.Now())).Hours() if storeDetail.CloseTime2 != 0 && storeDetail.OpenTime2 != 0 { optime += jxutils.JxOperationTime2TimeByDate(storeDetail.CloseTime2, time.Now()).Sub(jxutils.JxOperationTime2TimeByDate(storeDetail.OpenTime2, time.Now())).Hours() } storeManage.OpenTime = utils.Str2Float64(fmt.Sprintf("%.2f", optime)) //商品数 highSkuCount := 0 storeSkus, _ := dao.GetStoresSkusForManageState(db, storeMap.StoreID, model.StoreSkuBindStatusNormal) for _, v := range storeSkus { if v.UnitPrice > v.MidUnitPrice { highSkuCount++ } } storeManage.SkuCount, storeManage.HighSkuCount = len(storeSkus), highSkuCount //活动丰富度 ample, _ := handler.GetActAmple(ctx, storeDetail.VendorStoreID, storeDetail.VendorStoreID) storeManage.ActAmple = ample //订单 refuseOrderCount := 0 orderList, _ := dao.QueryOrdersForManageState(db, storeMap.StoreID, storeMap.VendorID, model.OrderStatusCanceled, dayTimeBegin, dayTimeEnd) for _, v := range orderList { if v.BindID == 0 { refuseOrderCount++ } } storeManage.NullOrderCount, storeManage.RefuseOrderCount = len(orderList), refuseOrderCount //评分(美团) if storeMap.VendorID == model.VendorIDMTWM { mtapi := partner.CurAPIManager.GetAPI(model.VendorIDMTWM, storeDetail.VendorOrgCode).(*mtwmapi.API) if scoreResult, err := mtapi.CommentScore(storeDetail.VendorStoreID); err == nil { storeManage.StoreScore = scoreResult.AvgPoiScore } } return storeManage } func GetStoreManageState(ctx *jxcontext.Context, storeIDs, brandIDs []int, vendorID, sortType, offset, pageSize int) (pageInfo *model.PagedInfo, err error) { var ( db = dao.GetDB() ) //权限 if permission.IsRoled(ctx) { if storeIDsMap, err := permission.GetUserStoresResultMap(ctx.GetUserID()); err == nil { var storeIDs2 []int if len(storeIDs) > 0 { for _, v := range storeIDs { if storeIDsMap[v] != 0 { storeIDs2 = append(storeIDs2, v) } } if len(storeIDs2) == 0 { storeIDs2 = append(storeIDs2, -1) } } else { for k, _ := range storeIDsMap { storeIDs2 = append(storeIDs2, k) } } storeIDs = nil storeIDs = storeIDs2 } } return dao.GetStoreManageState(db, storeIDs, brandIDs, vendorID, sortType, offset, pageSize) } func CalculateCoverArea(coordinate []string, vendorID int) (area float64) { //我先把地理坐标转成了平面坐标(百度的方法) //然后按多个坐标求面积公式求的面积(百度的方法) if len(coordinate) == 0 { return 0 } var xyList [][2]float64 for _, v := range coordinate { cell := strings.Split(v, ",") if len(cell) == 0 || len(cell) == 1 { continue } var lat, lng float64 if vendorID == model.VendorIDJD || vendorID == model.VendorIDEBAI { lng = utils.Str2Float64WithDefault(cell[0], 0) lat = utils.Str2Float64WithDefault(cell[1], 0) } else { lat = utils.Str2Float64WithDefault(cell[0], 0) lng = utils.Str2Float64WithDefault(cell[1], 0) } xys := jxutils.MillierConvertion(lat, lng) xyList = append(xyList, xys) } var sum float64 = 0 if len(xyList) == 0 { return 0 } for i := 0; i < len(xyList)-1; i++ { // sum += (xyList[i+1][0] - xyList[i][0]) * (xyList[i+1][1] + xyList[i][1]) sum += (xyList[i][0]*xyList[i+1][1] - xyList[i+1][0]*xyList[i][1]) } // sum += (xyList[0][0] - xyList[len(xyList)-1][0]) * (xyList[0][1] + xyList[len(xyList)-1][1]) sum += (xyList[len(xyList)-1][0]*xyList[0][1] - xyList[0][0]*xyList[len(xyList)-1][1]) sum /= float64(2) sum = math.Abs(sum) sum = utils.Str2Float64(fmt.Sprintf("%.2f", sum)) return sum } func RefreshJDMembers(ctx *jxcontext.Context) (err error) { var ( db = dao.GetDB() pageSize = 50 page int pages []int memberMap = make(map[string]*model.UserMember) ) userMemebers, _ := dao.GetUserMemberWithoutDeleted(db, model.VendorIDJD) for _, v := range userMemebers { memberMap[v.Mobile] = v } pageResult, err := api.JdAPI.QueryMemberTransListByCondition("", "", page, pageSize) if err != nil { if strings.Contains(err.Error(), "cookie") { globals.SugarLogger.Warnf("京东cookie过期了!") } } if pageResult.Total%pageSize == 0 { page = pageResult.Total / pageSize } else { page = pageResult.Total/pageSize + 1 } for ; page > 0; page-- { pages = append(pages, page) } task := tasksch.NewParallelTask2("RefreshJDMembers", tasksch.NewParallelConfig().SetIsContinueWhenError(true), ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, successCount int, err error) { pageNo := batchItemList[0].(int) pageResult2, err := api.JdAPI.QueryMemberTransListByCondition("", "", pageNo, pageSize) if pageResult2 != nil { for _, v := range pageResult2.Rows { if utils.Str2Time(v.Endtimestr+" 23:59:59").Sub(time.Now()) >= 0 && v.Dealstatus == 0 { if memberMap[v.Merchantcardno] != nil { //库里有这个人的会员信息了 if utils.Time2Str(memberMap[v.Merchantcardno].EndAt) != v.Endtimestr+" 23:59:59" { //可能这个人续费了,续存了 memberMap[v.Merchantcardno].EndAt = utils.Str2Time(v.Endtimestr + " 23:59:59") memberMap[v.Merchantcardno].DeletedAt = utils.DefaultTimeValue dao.UpdateEntity(db, memberMap[v.Merchantcardno], "EndAt", "DeletedAt") } } else { userMember := &model.UserMember{ VendorOrderID: v.Orderid, VendorID: model.VendorIDJD, Mobile: v.Merchantcardno, MemberType: 1, EndAt: utils.Str2Time(v.Endtimestr + " 23:59:59"), IsPay: 1, } dao.WrapAddIDCULDEntity(userMember, "jxadmin") if v.Createtime != "" { userMember.CreatedAt = utils.Str2Time(v.Createtime) } else { userMember.CreatedAt = utils.Str2Time(v.Cardcreatetime) } if userMember.EndAt.Sub(time.Now()) <= 0 { userMember.DeletedAt = time.Now() } dao.CreateEntity(db, userMember) } } } } return retVal, successCount, err }, pages) tasksch.HandleTask(task, nil, true).Run() task.GetID() return err } func UserMemberReport(ctx *jxcontext.Context, vendorID int, keyword string, offset, pageSize int) (page *model.PagedInfo, err error) { var ( db = dao.GetDB() ) var list []*dao.UserMemberReportResult sql := ` SELECT SQL_CALC_FOUND_ROWS a.mobile, IF(a.vendor_id = ?, b.name, t1.consignee_name) name, IF(a.deleted_at = ?, ?, ?) status, a.vendor_id, t1.buy_count, t1.buy_price, t1.good_comment_count, t1.bad_comment_count, t2.finished_count, t2.finished_price FROM user_member a LEFT JOIN user b ON a.mobile = b.mobile LEFT JOIN ( SELECT a.mobile, MAX(b.consignee_name) consignee_name, COUNT(b.vendor_store_id) buy_count, SUM(b.actual_pay_price) buy_price, COUNT(c.score > 3) good_comment_count, COUNT(c.score < 3) bad_comment_count FROM user_member a LEFT JOIN goods_order b ON a.mobile = b.consignee_mobile2 AND a.vendor_id = b.vendor_id AND b.order_type = ? AND b.store_id <> ? LEFT JOIN jx_bad_comments c ON c.order_id = b.vendor_order_id GROUP BY 1 ) t1 ON t1.mobile = a.mobile LEFT JOIN ( SELECT a.mobile, COUNT(b.vendor_store_id) finished_count, SUM(b.actual_pay_price) finished_price FROM user_member a LEFT JOIN goods_order b ON a.mobile = b.consignee_mobile2 AND a.vendor_id = b.vendor_id AND b.order_type = ? AND status = ? AND b.store_id <> ? GROUP BY 1 )t2 ON t2.mobile = a.mobile WHERE 1 = 1 ` sqlParams := []interface{}{ model.VendorIDJX, utils.DefaultTimeValue, model.YES, model.NO, model.OrderTypeNormal, model.MatterStoreID, model.OrderTypeNormal, model.OrderStatusFinished, model.MatterStoreID, } if vendorID != -1 { sql += " AND a.vendor_id = ?" sqlParams = append(sqlParams, vendorID) } if keyword != "" { keywordLike := "%" + keyword + "%" sql += " AND (a.mobile LIKE ? OR name LIKE ?)" sqlParams = append(sqlParams, keywordLike, keywordLike) } sql += ` LIMIT ? OFFSET ? ` pageSize = jxutils.FormalizePageSize(pageSize) sqlParams = append(sqlParams, pageSize, offset) txDB, _ := dao.Begin(db) defer dao.Commit(db, txDB) if err = dao.GetRowsTx(txDB, &list, sql, sqlParams...); err == nil { page = &model.PagedInfo{ TotalCount: dao.GetLastTotalRowCount2(db, txDB), //Data: page, } task := tasksch.NewParallelTask("", tasksch.NewParallelConfig().SetIsContinueWhenError(true), jxcontext.AdminCtx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { v := batchItemList[0].(*dao.UserMemberReportResult) var good *model.GoodsOrder sql := ` SELECT * FROM goods_order WHERE consignee_mobile2 = ? AND vendor_id = ? AND order_type = ? AND store_id <> ? LIMIT 1 OFFSET 0 ` sqlParams := []interface{}{v.Mobile, v.VendorID, model.OrderTypeNormal, model.MatterStoreID} dao.GetRow(db, &good, sql, sqlParams) if good != nil { v.NewPrice = good.ActualPayPrice } var place *model.Place sql2 := ` SELECT a.* FROM place a,( SELECT b.city_code, COUNT(*) count FROM goods_order a LEFT JOIN store b ON b.id = IF(a.jx_store_id = 0, store_id, jx_store_id) WHERE consignee_mobile2 = ? AND vendor_id = ? GROUP BY 1 ORDER BY COUNT(*) LIMIT 1 OFFSET 0)b WHERE a.code = b.city_code ` dao.GetRow(db, &place, sql2, sqlParams) if place != nil { v.CityName = place.Name v.CityCode = place.Code } return retVal, err }, list) tasksch.HandleTask(task, nil, true).Run() task.GetResult(0) page.Data = list } return page, err } type OrderNotifyReportResult struct { StoreID int `orm:"column(store_id)" json:"storeID"` Name string `json:"name"` Count int `json:"count"` //总通知数 SmsCount int `json:"smsCount"` //短信通知数 VoiceCount int `json:"voiceCount"` //语音通知数 } func OrderNotifyReport(ctx *jxcontext.Context, storeIDs, brandIDs []int, vendorID, notifyType int, keyword string, isFinished bool, fromTime, toTime string, offset, pageSize int) (page *model.PagedInfo, err error) { var ( db = dao.GetDB() results []*OrderNotifyReportResult ) sql := ` SELECT SQL_CALC_FOUND_ROWS IF(a.store_id = 0, a.jx_store_id, a.store_id) store_id, b.name ,COUNT(*) count, COUNT(a.notify_type = 1 or NULL) sms_count, COUNT(a.notify_type = 2 or NULL) voice_count FROM goods_order a LEFT JOIN store b ON IF(a.store_id = 0 ,a.jx_store_id, a.store_id) = b.id LEFT JOIN user c ON c.mobile = b.market_man_phone LEFT JOIN user d ON d.mobile = b.operator_phone WHERE a.notify_type <> ? ` sqlParams := []interface{}{0} if len(storeIDs) > 0 { sql += ` AND IF(a.jx_store_id != 0, a.jx_store_id, a.store_id) IN(` + dao.GenQuestionMarks(len(storeIDs)) + `)` sqlParams = append(sqlParams, storeIDs) } if len(brandIDs) > 0 { sql += ` AND b.brand_id IN(` + dao.GenQuestionMarks(len(brandIDs)) + `)` sqlParams = append(sqlParams, brandIDs) } if vendorID != -1 { sql += " AND a.vendor_id = ?" sqlParams = append(sqlParams, vendorID) } if notifyType != -1 { sql += " AND a.notify_type = ?" sqlParams = append(sqlParams, notifyType) } if keyword != "" { sql += " AND (b.name LIKE ? OR c.name LIKE ? OR d.name LIKE ? OR b.id = ? OR a.vendor_order_id = ?)" sqlParams = append(sqlParams, "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%", keyword, keyword) } if !utils.IsTimeZero(utils.Str2Time(fromTime)) { if isFinished { sql += " AND a.order_finished_at > ?" } else { sql += " AND a.order_created_at > ?" } sqlParams = append(sqlParams, fromTime) } if !utils.IsTimeZero(utils.Str2Time(toTime)) { if isFinished { sql += " AND a.order_finished_at < ?" } else { sql += " AND a.order_created_at < ?" } sqlParams = append(sqlParams, toTime) } sql += ` GROUP BY 1, 2 ORDER BY count DESC LIMIT ? OFFSET ? ` pageSize = jxutils.FormalizePageSize(pageSize) sqlParams = append(sqlParams, pageSize, offset) txDB, _ := dao.Begin(db) defer dao.Commit(db, txDB) if err = dao.GetRowsTx(txDB, &results, sql, sqlParams...); err == nil { page = &model.PagedInfo{ TotalCount: dao.GetLastTotalRowCount2(db, txDB), Data: results, } } return page, err } type OrderDeliveryReportResult struct { model.GoodsOrder DesiredFee int `json:"desiredFee"` } func OrderDeliveryReport(ctx *jxcontext.Context, storeIDs, brandIDs []int, vendorID, deliveryVendorID int, keyword string, isFinished bool, fromTime, toTime string, offset, pageSize int) (page *model.PagedInfo, err error) { var ( db = dao.GetDB() results []*OrderDeliveryReportResult ) sql := ` SELECT SQL_CALC_FOUND_ROWS a.*, b.desired_fee FROM goods_order a LEFT JOIN waybill b ON a.vendor_order_id = b.vendor_order_id AND a.waybill_vendor_id = b.waybill_vendor_id LEFT JOIN store c ON c.id = IF(a.jx_store_id = 0, a.store_id, a.jx_store_id) WHERE b.status <> ? AND a.waybill_vendor_id IN (? , ? , ?) ` sqlParams := []interface{}{model.WaybillStatusCanceled, model.VendorIDMTPS, model.VendorIDDada, model.VendorIDFengNiao, model.VendorIDUUPT} if len(storeIDs) > 0 { sql += ` AND IF(a.jx_store_id != 0, a.jx_store_id, a.store_id) IN(` + dao.GenQuestionMarks(len(storeIDs)) + `)` sqlParams = append(sqlParams, storeIDs) } if len(brandIDs) > 0 { sql += ` AND c.brand_id IN(` + dao.GenQuestionMarks(len(brandIDs)) + `)` sqlParams = append(sqlParams, brandIDs) } if vendorID != -1 { sql += " AND a.vendor_id = ?" sqlParams = append(sqlParams, vendorID) } if deliveryVendorID != -1 { sql += " AND a.waybill_vendor_id = ?" sqlParams = append(sqlParams, deliveryVendorID) } if keyword != "" { sql += " AND (c.name LIKE ? OR c.id = ? OR a.vendor_order_id = ?)" sqlParams = append(sqlParams, "%"+keyword+"%", keyword, keyword) } if !utils.IsTimeZero(utils.Str2Time(fromTime)) { if isFinished { sql += " AND a.order_finished_at > ?" } else { sql += " AND a.order_created_at > ?" } sqlParams = append(sqlParams, fromTime) } if !utils.IsTimeZero(utils.Str2Time(toTime)) { if isFinished { sql += " AND a.order_finished_at < ?" } else { sql += " AND a.order_created_at < ?" } sqlParams = append(sqlParams, toTime) } sql += ` ORDER BY a.order_created_at DESC LIMIT ? OFFSET ? ` pageSize = jxutils.FormalizePageSize(pageSize) sqlParams = append(sqlParams, pageSize, offset) txDB, _ := dao.Begin(db) defer dao.Commit(db, txDB) if err = dao.GetRowsTx(txDB, &results, sql, sqlParams...); err == nil { page = &model.PagedInfo{ TotalCount: dao.GetLastTotalRowCount2(db, txDB), Data: results, } } return page, err }