diff --git a/business/jxstore/misc/Store_Alert_Inform.go b/business/jxstore/misc/Store_Alert_Inform.go new file mode 100644 index 000000000..524e6d178 --- /dev/null +++ b/business/jxstore/misc/Store_Alert_Inform.go @@ -0,0 +1,509 @@ +package misc + +import ( + "fmt" + "math" + "time" + + "git.rosy.net.cn/baseapi" + "git.rosy.net.cn/baseapi/utils" + "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/weixinmsg" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/model/dao" + "git.rosy.net.cn/jx-callback/globals/refutil" +) + +const ( + EnableCheckStoreAlert = true + EnableSendStoreAlert = true + + IncludeToday = true + CheckStoreAlertOneMonthDayNum = 30 + CheckStoreAlertOneDayNum = 1 + CheckStoreAlertOneWeekDayNum = 7 + MonthCheckOnWeekDay = 1 + + AlertTypePickTimeOrderDaDa = 0 + AlertTypeBadCommentOrder = 1 + AlertTypeAbsentGoodsOrder = 2 + AlertTypeStandardFinishTimeOrderSelfDelivery = 3 + AlertTypeStandardPickUpTimeOrderDaDa = 4 + + ColorRed = "red" + ColorYellow = "yellow" + ColorUnknown = "unknown" + + AlertLevelExtraRed = 1 + AlertLevelRed = 2 + AlertLevelYellow = 3 + + OneDayName = "单日" + OneWeekDayName = "七日" + OneMonthDayName = "三十日" + YellowAlertInfo = "您的店铺京西菜市-%s,由于%s%s%s%d%%,可能会被系统下线,请及时补救。" + RedAlertInfo = "您的店铺京西菜市-%s,由于%s%s%s%d%%,会被系统下线,需要马上补救。" + ExtraRedAlertInfo = "您的店铺京西菜市-%s,由于%s%s%s%d%%,会被系统下线,需要马上补救。" + NoOrderAlertInfo = "您的店铺京西菜市-%s,由于近%s无订单,会被系统下线,需要马上补救。" + RiskOrderAlertInfo = "您的店铺京西菜市-%s,可能有虚假定单,定单号为:%s,可能会被罚款,请及时与运营联系!" +) + +var ( + checkStoreAlertTimeList = []string{ + "18:30:00", + } + + AlertTypeNameMap = map[int]string{ + AlertTypePickTimeOrderDaDa: "拣货履约率(达达)", + AlertTypeBadCommentOrder: "差评率", + AlertTypeAbsentGoodsOrder: "缺货率", + AlertTypeStandardFinishTimeOrderSelfDelivery: "按时履约率(商家自送)", + AlertTypeStandardPickUpTimeOrderDaDa: "10分钟取货完成率(达达)", + } + + AlertTypeExtraNameMap = map[int]string{ + AlertTypePickTimeOrderDaDa: "拣货超时订单(达达)", + AlertTypeBadCommentOrder: "差评订单", + AlertTypeAbsentGoodsOrder: "缺货订单", + } + + storeAlertDataWrapper StoreAlertDataWrapper +) + +type StoreAlertDataWrapper struct { + storeAlertList map[int]*model.StoreAlert +} + +func (s *StoreAlertDataWrapper) InitData() { + s.storeAlertList = make(map[int]*model.StoreAlert) +} + +func (s *StoreAlertDataWrapper) ClearData() { + s.storeAlertList = nil +} + +func (s *StoreAlertDataWrapper) IsStatusField(valueName string) bool { + return valueName == model.FieldYellowStatus || valueName == model.FieldRedStatus || valueName == model.FieldExtraRedStatus +} + +func (s *StoreAlertDataWrapper) SetData(storeID int, valueName string, value int) { + data := s.storeAlertList[storeID] + if data == nil { + data = &model.StoreAlert{} + data.StoreID = storeID + data.AlertDate = utils.GetCurDate() + s.storeAlertList[storeID] = data + } + if s.IsStatusField(valueName) { + srcFieldValue := refutil.GetObjFieldByName(data, valueName).(int) + value |= srcFieldValue + } + refutil.SetObjFieldByName(data, valueName, value) +} + +func (s StoreAlertDataWrapper) InsertStoreAlertList() { + for _, value := range s.storeAlertList { + dao.InsertStoreAlert(value) + } +} + +func ConvertListToMap(listData []*model.StoreCount) (mapData map[int]int) { + mapData = make(map[int]int) + for _, value := range listData { + mapData[value.StoreID] = value.Count + } + + return mapData +} + +func ConvertListToMapEx(listData []*model.StoreOrder) (mapData map[int][]string) { + mapData = make(map[int][]string) + for _, value := range listData { + if mapData[value.StoreID] == nil { + mapData[value.StoreID] = []string{} + } + mapData[value.StoreID] = append(mapData[value.StoreID], value.VendorOrderID) + } + + return mapData +} + +func GetAlertInfo(dayNum, alertLevel int, storeName string, alertType int, logicCondition string, value int) (info string) { + if dayNum == CheckStoreAlertOneDayNum { + if alertLevel == AlertLevelExtraRed { + info = fmt.Sprintf(ExtraRedAlertInfo, storeName, OneDayName, AlertTypeExtraNameMap[alertType], logicCondition, value) + } else if alertLevel == AlertLevelRed { + info = fmt.Sprintf(RedAlertInfo, storeName, OneDayName, AlertTypeNameMap[alertType], logicCondition, value) + } else if alertLevel == AlertLevelYellow { + info = fmt.Sprintf(YellowAlertInfo, storeName, OneDayName, AlertTypeNameMap[alertType], logicCondition, value) + } + } else if dayNum == CheckStoreAlertOneWeekDayNum { + if alertLevel == AlertLevelExtraRed { + info = fmt.Sprintf(ExtraRedAlertInfo, storeName, OneWeekDayName, AlertTypeExtraNameMap[alertType], logicCondition, value) + } else if alertLevel == AlertLevelRed { + info = fmt.Sprintf(RedAlertInfo, storeName, OneWeekDayName, AlertTypeNameMap[alertType], logicCondition, value) + } else if alertLevel == AlertLevelYellow { + info = fmt.Sprintf(YellowAlertInfo, storeName, OneWeekDayName, AlertTypeNameMap[alertType], logicCondition, value) + } + } else if dayNum == CheckStoreAlertOneMonthDayNum { + info = fmt.Sprintf(NoOrderAlertInfo, storeName, OneMonthDayName) + } + + return info +} + +func CheckAlert(alertType int, dayNum int, ratio int, count int) (alertLevel int, logicCondtion string, outValue int) { + yellowRatio := -1 + redRatio := -1 + extraCount := -1 + conditionLessEqual := false + + switch alertType { + case AlertTypePickTimeOrderDaDa: + if dayNum == CheckStoreAlertOneDayNum { + redRatio = 0 + } else if dayNum == CheckStoreAlertOneWeekDayNum { + yellowRatio = 70 + redRatio = 50 + extraCount = 5 + } + conditionLessEqual = true + case AlertTypeBadCommentOrder: + if dayNum == CheckStoreAlertOneDayNum { + redRatio = 100 + } else if dayNum == CheckStoreAlertOneWeekDayNum { + yellowRatio = 1 + redRatio = 3 + extraCount = 5 + } + conditionLessEqual = false + case AlertTypeAbsentGoodsOrder: + if dayNum == CheckStoreAlertOneDayNum { + redRatio = 100 + } else if dayNum == CheckStoreAlertOneWeekDayNum { + yellowRatio = 3 + redRatio = 5 + extraCount = 5 + } + conditionLessEqual = false + case AlertTypeStandardFinishTimeOrderSelfDelivery: + yellowRatio = 85 + redRatio = 70 + conditionLessEqual = true + case AlertTypeStandardPickUpTimeOrderDaDa: + yellowRatio = 85 + redRatio = 70 + conditionLessEqual = true + } + + if conditionLessEqual { + logicCondtion = "<=" + if extraCount != -1 && count >= extraCount { + alertLevel = AlertLevelExtraRed + outValue = extraCount + } else if redRatio != -1 && ratio <= redRatio { + alertLevel = AlertLevelRed + outValue = redRatio + } else if yellowRatio != -1 && ratio <= yellowRatio { + alertLevel = AlertLevelYellow + outValue = yellowRatio + } + } else { + logicCondtion = ">=" + if extraCount != -1 && count >= extraCount { + alertLevel = AlertLevelExtraRed + outValue = extraCount + } else if redRatio != -1 && ratio >= redRatio { + alertLevel = AlertLevelRed + outValue = redRatio + } else if yellowRatio != -1 && ratio >= yellowRatio { + alertLevel = AlertLevelYellow + outValue = yellowRatio + } + } + + return alertLevel, logicCondtion, outValue +} + +func SendAlertInfo(storeID int, storeName, alertInfo string) { + if EnableSendStoreAlert { + baseapi.SugarLogger.Debugf("SendAlertInfo: %d, %s", storeID, alertInfo) + weixinmsg.NotifyStoreAlertMessage(storeID, storeName, "门店警告", alertInfo) + } +} + +func GetFieldNameByAlertType(alertType, dayNum int) (fieldName string, fieldFlag int) { + switch alertType { + case AlertTypePickTimeOrderDaDa: + if dayNum == CheckStoreAlertOneDayNum { + fieldName = model.FieldPickTimeDaDa + fieldFlag = model.FlagPickTimeDaDa + } else if dayNum == CheckStoreAlertOneWeekDayNum { + fieldName = model.FieldPickTimeDaDaOneWeek + fieldFlag = model.FlagPickTimeDaDaOneWeek + } + case AlertTypeBadCommentOrder: + if dayNum == CheckStoreAlertOneDayNum { + fieldName = model.FieldBadComment + fieldFlag = model.FlagBadComment + } else if dayNum == CheckStoreAlertOneWeekDayNum { + fieldName = model.FieldBadCommentOneWeek + fieldFlag = model.FlagBadCommentOneWeek + } + case AlertTypeAbsentGoodsOrder: + if dayNum == CheckStoreAlertOneDayNum { + fieldName = model.FieldAbsentGoods + fieldFlag = model.FlagAbsentGoods + } else if dayNum == CheckStoreAlertOneWeekDayNum { + fieldName = model.FieldAbsentGoodsOneWeek + fieldFlag = model.FlagAbsentGoodsOneWeek + } + case AlertTypeStandardFinishTimeOrderSelfDelivery: + fieldName = model.FieldStandardFinishTimeSelfDelivery + fieldFlag = model.FlagStandardFinishTimeSelfDelivery + case AlertTypeStandardPickUpTimeOrderDaDa: + fieldName = model.FieldStandardPickUpTimeDaDa + fieldFlag = model.FlagStandardPickUpTimeDaDa + } + + return fieldName, fieldFlag +} + +func SendAlertInfoWrapper(storeID int, storeName string, dayNum, alertType, count, totalCount int) { + if totalCount > 0 { + ratio := int(math.Round(float64(count) * 100 / float64(totalCount))) + alertLevel, logicCondtion, outValue := CheckAlert(alertType, dayNum, ratio, count) + if alertLevel != 0 { + alertInfo := GetAlertInfo(dayNum, alertLevel, storeName, alertType, logicCondtion, outValue) + SendAlertInfo(storeID, storeName, alertInfo) + fieldName, fieldFlag := GetFieldNameByAlertType(alertType, dayNum) + storeAlertDataWrapper.SetData(storeID, fieldName, ratio) + + if alertLevel == AlertLevelExtraRed { + storeAlertDataWrapper.SetData(storeID, model.FieldExtraRedStatus, fieldFlag) + } else if alertLevel == AlertLevelRed { + storeAlertDataWrapper.SetData(storeID, model.FieldRedStatus, fieldFlag) + } else if alertLevel == AlertLevelYellow { + storeAlertDataWrapper.SetData(storeID, model.FieldYellowStatus, fieldFlag) + } + } + } +} + +func CheckStoreDayAlert(storeList []*cms.StoreExt, dayNum int) { + db := dao.GetDB() + //拣货履约订单(达达) + pickTimeOrderCountDaDaList, _ := dao.GetStandardPickTimeOrderCountByDaDa(db, dayNum, IncludeToday) + pickTimeOrderCountDaDaMapData := ConvertListToMap(pickTimeOrderCountDaDaList) + + //完成订单(达达) + finishOrderCountDaDaList, _ := dao.GetFinishOrderCountByDaDa(db, dayNum, IncludeToday) + finishOrderCountDaDaMapData := ConvertListToMap(finishOrderCountDaDaList) + + //差评订单 + badCommentOrderCountList, _ := dao.GetBadCommentOrderCountByDayNum(db, dayNum, IncludeToday) + badCommentOrderCountMapData := ConvertListToMap(badCommentOrderCountList) + + //缺货订单 + absentGoodsOrderCountList, _ := dao.GetAbsentGoodsOrderCountByDayNum(db, dayNum, IncludeToday) + absentGoodsOrderCountMapData := ConvertListToMap(absentGoodsOrderCountList) + + //完成订单 + finishOrderCountList, _ := dao.GetFinishOrderCountByDayNum(db, dayNum, IncludeToday) + finishOrderCountMapData := ConvertListToMap(finishOrderCountList) + + var standardFinishTimeOrderCountSelfDeliveryList []*model.StoreCount + var standardFinishTimeOrderCountSelfDeliveryMapData map[int]int + var finishOrderCountSelfDeliveryList []*model.StoreCount + var finishOrderCountSelfDeliveryMapData map[int]int + var standardPickUpTimeOrderCountDaDaList []*model.StoreCount + var standardPickUpTimeOrderCountDaDaMapData map[int]int + isOneWeekDay := dayNum == CheckStoreAlertOneWeekDayNum + if isOneWeekDay { + //按时履约订单(商家自送) + standardFinishTimeOrderCountSelfDeliveryList, _ = dao.GetStandardFinishTimeOrderCountBySelfDelivery(db, dayNum, IncludeToday) + standardFinishTimeOrderCountSelfDeliveryMapData = ConvertListToMap(standardFinishTimeOrderCountSelfDeliveryList) + + //完成订单(商家自送) + finishOrderCountSelfDeliveryList, _ = dao.GetFinishOrderCountBySelfDelivery(db, dayNum, IncludeToday) + finishOrderCountSelfDeliveryMapData = ConvertListToMap(finishOrderCountSelfDeliveryList) + + //10分钟取货完成订单(达达) + standardPickUpTimeOrderCountDaDaList, _ = dao.GetStandardPickUpTimeOrderCountByDaDa(db, dayNum, IncludeToday) + standardPickUpTimeOrderCountDaDaMapData = ConvertListToMap(standardPickUpTimeOrderCountDaDaList) + } + + for _, storeInfo := range storeList { + storeID := storeInfo.ID + storeName := storeInfo.Name + count := pickTimeOrderCountDaDaMapData[storeID] + totalCount := finishOrderCountDaDaMapData[storeID] + SendAlertInfoWrapper(storeID, storeName, dayNum, AlertTypePickTimeOrderDaDa, count, totalCount) + + count = badCommentOrderCountMapData[storeID] + totalCount = finishOrderCountMapData[storeID] + SendAlertInfoWrapper(storeID, storeName, dayNum, AlertTypeBadCommentOrder, count, totalCount) + count = absentGoodsOrderCountMapData[storeID] + SendAlertInfoWrapper(storeID, storeName, dayNum, AlertTypeAbsentGoodsOrder, count, totalCount) + + if isOneWeekDay { + count = standardFinishTimeOrderCountSelfDeliveryMapData[storeID] + totalCount = finishOrderCountSelfDeliveryMapData[storeID] + SendAlertInfoWrapper(storeID, storeName, dayNum, AlertTypeStandardFinishTimeOrderSelfDelivery, count, totalCount) + + count = standardPickUpTimeOrderCountDaDaMapData[storeID] + totalCount = finishOrderCountDaDaMapData[storeID] + SendAlertInfoWrapper(storeID, storeName, dayNum, AlertTypeStandardPickUpTimeOrderDaDa, count, totalCount) + } + } +} + +func CheckStoreMonthAlert(storeList []*cms.StoreExt) { + db := dao.GetDB() + storeCountList, _ := dao.GetFinishOrderCountByDayNum(db, CheckStoreAlertOneMonthDayNum, IncludeToday) + storeCountMapData := make(map[int]int) + for _, value := range storeCountList { + storeCountMapData[value.StoreID] = value.Count + } + + for _, storeInfo := range storeList { + storeID := storeInfo.ID + storeName := storeInfo.Name + if _, ok := storeCountMapData[storeID]; !ok { + alertInfo := GetAlertInfo(CheckStoreAlertOneMonthDayNum, AlertLevelRed, storeName, -1, "", -1) + SendAlertInfo(storeID, storeName, alertInfo) + storeAlertDataWrapper.SetData(storeID, model.FieldNoOrderInMonth, 1) + storeAlertDataWrapper.SetData(storeID, model.FieldRedStatus, model.FlagNoOrderInMonth) + } + } +} + +func CheckStoreRiskOrderAlert(storeList []*cms.StoreExt, dayNum int) { + db := dao.GetDB() + storeOrderList, _ := dao.GetRiskOrderCount(db, dayNum, IncludeToday) + storeOrderMapData := ConvertListToMapEx(storeOrderList) + for _, storeInfo := range storeList { + storeID := storeInfo.ID + storeName := storeInfo.Name + vendorOrderIDList := storeOrderMapData[storeID] + if vendorOrderIDList != nil { + vendorOrderIDStr := "" + for index, vendorOrderID := range vendorOrderIDList { + if index == 0 { + vendorOrderIDStr += vendorOrderID + } else { + vendorOrderIDStr += "," + vendorOrderID + } + } + alertInfo := fmt.Sprintf(RiskOrderAlertInfo, storeName, vendorOrderIDStr) + SendAlertInfo(storeID, storeName, alertInfo) + storeAlertDataWrapper.SetData(storeID, model.FieldRiskOrderCount, len(vendorOrderIDList)) + storeAlertDataWrapper.SetData(storeID, model.FieldRedStatus, model.FlagRiskOrderCount) + } + } +} + +func GetWeekDay() int { + return int(time.Now().Weekday()) +} + +func CheckStoreAlert(ctx *jxcontext.Context, storeIDList []int) { + storeAlertDataWrapper.InitData() + storeList, _ := GetStoreList(ctx) + storeIDMap := jxutils.IntList2Map(storeIDList) + storeList = GetFilterStoreListEx(storeList, storeIDMap) + if GetWeekDay() == MonthCheckOnWeekDay { + CheckStoreMonthAlert(storeList) + } + CheckStoreDayAlert(storeList, CheckStoreAlertOneDayNum) + CheckStoreDayAlert(storeList, CheckStoreAlertOneWeekDayNum) + CheckStoreRiskOrderAlert(storeList, CheckStoreAlertOneDayNum) + storeAlertDataWrapper.InsertStoreAlertList() + storeAlertDataWrapper.ClearData() +} + +func ScheduleCheckStoreAlert() { + if EnableCheckStoreAlert { + ScheduleTimerFunc("ScheduleCheckStoreAlert", func() { + CheckStoreAlert(jxcontext.AdminCtx, nil) + }, checkStoreAlertTimeList) + } +} + +func GetValueColorByStatus(extraRedStatus, redStatus, yellowStatus, flag int) (color string) { + if (extraRedStatus&flag != 0) || (redStatus&flag != 0) { + color = ColorRed + } else if yellowStatus&flag != 0 { + color = ColorYellow + } else { + color = ColorUnknown + } + + return color +} + +func GetStoreAlertList(storeIDList []int, cityCode int, keyWord string, dateTime time.Time, offset, pageSize int) (storeAlertData model.StoreAlertData, err error) { + db := dao.GetDB() + storeAlertList, err := dao.GetStoreAlertList(db, storeIDList, cityCode, keyWord, dateTime) + if err == nil && len(storeAlertList) > 0 { + offset = jxutils.FormalizePageOffset(offset) + pageSize = jxutils.FormalizePageSize(pageSize) + var pagedStoreAlertList []*model.StoreAlertEx + for i := offset; i < offset+pageSize && i < len(storeAlertList); i++ { + pagedStoreAlertList = append(pagedStoreAlertList, storeAlertList[i]) + } + + var storeAlertAdvancedList []*model.StoreAlertAdvanced + for _, value := range pagedStoreAlertList { + storeAlertAdvanced := &model.StoreAlertAdvanced{} + storeAlertAdvanced.ID = value.ID + storeAlertAdvanced.CreatedTime = value.CreatedTime + storeAlertAdvanced.AlertDate = value.AlertDate + storeAlertAdvanced.StoreID = value.StoreID + storeAlertAdvanced.StoreName = value.StoreName + storeAlertAdvanced.CityName = value.CityName + + storeAlertAdvanced.PickTimeDaDa.Value = fmt.Sprintf("%d%%", value.PickTimeDaDa) + storeAlertAdvanced.PickTimeDaDa.Color = GetValueColorByStatus(value.ExtraRedStatus, value.RedStatus, value.YellowStatus, model.FlagPickTimeDaDa) + + storeAlertAdvanced.BadComment.Value = fmt.Sprintf("%d%%", value.BadComment) + storeAlertAdvanced.BadComment.Color = GetValueColorByStatus(value.ExtraRedStatus, value.RedStatus, value.YellowStatus, model.FlagBadComment) + + storeAlertAdvanced.AbsentGoods.Value = fmt.Sprintf("%d%%", value.AbsentGoods) + storeAlertAdvanced.AbsentGoods.Color = GetValueColorByStatus(value.ExtraRedStatus, value.RedStatus, value.YellowStatus, model.FlagAbsentGoods) + + storeAlertAdvanced.PickTimeDaDaOneWeek.Value = fmt.Sprintf("%d%%", value.PickTimeDaDaOneWeek) + storeAlertAdvanced.PickTimeDaDaOneWeek.Color = GetValueColorByStatus(value.ExtraRedStatus, value.RedStatus, value.YellowStatus, model.FlagPickTimeDaDaOneWeek) + + storeAlertAdvanced.BadCommentOneWeek.Value = fmt.Sprintf("%d%%", value.BadCommentOneWeek) + storeAlertAdvanced.BadCommentOneWeek.Color = GetValueColorByStatus(value.ExtraRedStatus, value.RedStatus, value.YellowStatus, model.FlagBadCommentOneWeek) + + storeAlertAdvanced.AbsentGoodsOneWeek.Value = fmt.Sprintf("%d%%", value.AbsentGoodsOneWeek) + storeAlertAdvanced.AbsentGoodsOneWeek.Color = GetValueColorByStatus(value.ExtraRedStatus, value.RedStatus, value.YellowStatus, model.FlagAbsentGoodsOneWeek) + + storeAlertAdvanced.StandardFinishTimeSelfDelivery.Value = fmt.Sprintf("%d%%", value.StandardFinishTimeSelfDelivery) + storeAlertAdvanced.StandardFinishTimeSelfDelivery.Color = GetValueColorByStatus(value.ExtraRedStatus, value.RedStatus, value.YellowStatus, model.FlagStandardFinishTimeSelfDelivery) + + storeAlertAdvanced.StandardPickUpTimeDaDa.Value = fmt.Sprintf("%d%%", value.StandardPickUpTimeDaDa) + storeAlertAdvanced.StandardPickUpTimeDaDa.Color = GetValueColorByStatus(value.ExtraRedStatus, value.RedStatus, value.YellowStatus, model.FlagStandardPickUpTimeDaDa) + + if value.NoOrderInMonth == 1 { + storeAlertAdvanced.NoOrderInMonth.Value = "是" + } else { + storeAlertAdvanced.NoOrderInMonth.Value = "否" + } + storeAlertAdvanced.NoOrderInMonth.Color = GetValueColorByStatus(value.ExtraRedStatus, value.RedStatus, value.YellowStatus, model.FlagNoOrderInMonth) + + storeAlertAdvanced.RiskOrderCount.Value = utils.Int2Str(value.RiskOrderCount) + storeAlertAdvanced.RiskOrderCount.Color = GetValueColorByStatus(value.ExtraRedStatus, value.RedStatus, value.YellowStatus, model.FlagRiskOrderCount) + + storeAlertAdvancedList = append(storeAlertAdvancedList, storeAlertAdvanced) + } + storeAlertData.TotalCount = len(storeAlertList) + storeAlertData.StoreAlertList = storeAlertAdvancedList + } + + return storeAlertData, err +} diff --git a/business/jxstore/misc/misc.go b/business/jxstore/misc/misc.go index 8ab5afdfd..0c73806cd 100644 --- a/business/jxstore/misc/misc.go +++ b/business/jxstore/misc/misc.go @@ -105,6 +105,7 @@ func Init() { dao.UpdateActStatusByTime(dao.GetDB(), time.Now().Add(-48*time.Hour)) }, updateActStatusTimeList) ScheduleScoreStore() + ScheduleCheckStoreAlert() } ScheduleTimerFunc("AutoSaleStoreSku", func() { cms.AutoSaleStoreSku(jxcontext.AdminCtx, nil, false) diff --git a/business/jxstore/misc/store_score.go b/business/jxstore/misc/store_score.go index c938395b8..5fd90ada7 100644 --- a/business/jxstore/misc/store_score.go +++ b/business/jxstore/misc/store_score.go @@ -808,10 +808,11 @@ func GetWeeklyStoreScore(storeID, weekIndexParam int) (outWeeklyStoreScoreDataLi return outWeeklyStoreScoreDataList, err } -func GetStoreTotalScoreList(storeIDList []int, cityCode int, keyWord string, beginTime, endTime time.Time, isDesc bool, checkScoreLow, checkScoreHigh int) (outStoreTotalScoreList []*model.StoreTotalScore, err error) { +func GetStoreTotalScoreList(storeIDList []int, cityCode int, keyWord string, beginTime, endTime time.Time, isDesc bool, checkScoreLow, checkScoreHigh, offset, pageSize int) (storeTotalScoreEx model.StoreTotalScoreEx, err error) { db := dao.GetDB() storeTotalScoreMapData := make(map[int]*model.StoreTotalScore) storeTotalScoreList, err := dao.GetStoreTotalScoreList(db, storeIDList, cityCode, keyWord, beginTime, endTime) + var filterStoreTotalScoreList []*model.StoreTotalScore if err == nil && len(storeTotalScoreList) > 0 { countDayNum := make(map[int]int) for _, value := range storeTotalScoreList { @@ -837,13 +838,13 @@ func GetStoreTotalScoreList(storeIDList []int, cityCode int, keyWord string, beg needAdd = false } if needAdd { - outStoreTotalScoreList = append(outStoreTotalScoreList, value) + filterStoreTotalScoreList = append(filterStoreTotalScoreList, value) } } if isDesc { - sort.Slice(outStoreTotalScoreList, func(i, j int) bool { - data1 := outStoreTotalScoreList[i] - data2 := outStoreTotalScoreList[j] + sort.Slice(filterStoreTotalScoreList, func(i, j int) bool { + data1 := filterStoreTotalScoreList[i] + data2 := filterStoreTotalScoreList[j] if data1.StoreScore == data2.StoreScore { return data1.StoreID < data2.StoreID } else { @@ -851,9 +852,9 @@ func GetStoreTotalScoreList(storeIDList []int, cityCode int, keyWord string, beg } }) } else { - sort.Slice(outStoreTotalScoreList, func(i, j int) bool { - data1 := outStoreTotalScoreList[i] - data2 := outStoreTotalScoreList[j] + sort.Slice(filterStoreTotalScoreList, func(i, j int) bool { + data1 := filterStoreTotalScoreList[i] + data2 := filterStoreTotalScoreList[j] if data1.StoreScore == data2.StoreScore { return data1.StoreID < data2.StoreID } else { @@ -863,5 +864,15 @@ func GetStoreTotalScoreList(storeIDList []int, cityCode int, keyWord string, beg } } - return outStoreTotalScoreList, err + offset = jxutils.FormalizePageOffset(offset) + pageSize = jxutils.FormalizePageSize(pageSize) + var pagedStoreTotalScoreList []*model.StoreTotalScore + for i := offset; i < offset+pageSize && i < len(filterStoreTotalScoreList); i++ { + pagedStoreTotalScoreList = append(pagedStoreTotalScoreList, filterStoreTotalScoreList[i]) + } + + storeTotalScoreEx.TotalCount = len(filterStoreTotalScoreList) + storeTotalScoreEx.StoreTotalScoreList = pagedStoreTotalScoreList + + return storeTotalScoreEx, err } diff --git a/business/jxutils/weixinmsg/weixinmsg.go b/business/jxutils/weixinmsg/weixinmsg.go index 41ab78cff..a47fd3d2d 100644 --- a/business/jxutils/weixinmsg/weixinmsg.go +++ b/business/jxutils/weixinmsg/weixinmsg.go @@ -64,6 +64,8 @@ const ( WX_AFS_ORDER_STATUS_CHANGED_TEMPLATE_ID = "99T33rrXX0VboO1hljs4x8dDoLiSj3QX_rOikPHIXkg" WS_NOTIFY_STORE_STATUS_CHHANGED_TEMPLATE_ID = "Fl0vOnBKTQqRFx3-shGKxdCnxMdQXNeODzgkuwd7oxw" + + WX_STORE_ALERT_TEMPLATE_ID = "0AjzVl1wPl6iO4nFOS4IEsJYSzBymlT37DciIvcCOxE" ) var ( @@ -83,6 +85,7 @@ var ( debugOpenIDMap = map[string]int{ "oYN_usk0AeGc_C6VEZfmFQP5VHMQ": 1, // 周小扬 "oYN_ust9hXKEvEv0X6Mq6nlAWs_E": 1, // me + "oYN_usqnpGVQ4xxlao_yybsbYJh4": 1, // 朱丹 } ) @@ -144,7 +147,7 @@ func GetWeixinOpenIDsFromStoreID(storeID int) (retVal []string) { func SendMsgToStore(storeID int, templateID, downloadURL, miniPageURL string, data interface{}) (err error) { globals.SugarLogger.Debugf("SendMsgToStore storeID:%d, templateID:%s, downloadURL:%s, miniPageURL:%s", storeID, templateID, downloadURL, miniPageURL) if storeID == 0 { // 测试,只发给我 - // SmartMessageTemplateSend("oYN_ust9hXKEvEv0X6Mq6nlAWs_E", templateID, downloadURL, miniPageURL, data) + //SmartMessageTemplateSend("oYN_usk0AeGc_C6VEZfmFQP5VHMQ", templateID, downloadURL, miniPageURL, data) } else { openIDs := GetWeixinOpenIDsFromStoreID(storeID) successCount := 0 @@ -637,3 +640,30 @@ func NotifyStoreStatusChanged(openUserID, title, content string) (err error) { }) return err } + +func NotifyStoreAlertMessage(storeID int, storeName, title, content string) (err error) { + globals.SugarLogger.Debugf("NotifyStoreAlertMessage storeID:%d, storeName:%d, title:%s, content:%s", storeID, storeName, title, content) + templateID := WX_STORE_ALERT_TEMPLATE_ID + data := map[string]interface{}{ + "first": map[string]interface{}{ + "value": "", + "color": "#333333", + }, + "keyword1": map[string]interface{}{ + "value": storeName, + "color": "#2E408E", + }, + "keyword2": map[string]interface{}{ + "value": utils.GetCurTimeStr(), + "color": "#2E408E", + }, + "keyword3": map[string]interface{}{ + "value": content, + "color": "#2E408E", + }, + "remark": map[string]interface{}{ + "value": "", + }, + } + return SendMsgToStore(storeID, templateID, "", "", data) +} diff --git a/business/model/Store_Alert_Inform.go b/business/model/Store_Alert_Inform.go new file mode 100644 index 000000000..bc9701edd --- /dev/null +++ b/business/model/Store_Alert_Inform.go @@ -0,0 +1,112 @@ +package model + +import "time" + +const ( + FieldPickTimeDaDa = "PickTimeDaDa" + FieldBadComment = "BadComment" + FieldAbsentGoods = "AbsentGoods" + FieldPickTimeDaDaOneWeek = "PickTimeDaDaOneWeek" + FieldBadCommentOneWeek = "BadCommentOneWeek" + FieldAbsentGoodsOneWeek = "AbsentGoodsOneWeek" + FieldStandardFinishTimeSelfDelivery = "StandardFinishTimeSelfDelivery" + FieldStandardPickUpTimeDaDa = "StandardPickUpTimeDaDa" + + FieldNoOrderInMonth = "NoOrderInMonth" + FieldRiskOrderCount = "RiskOrderCount" + + FieldYellowStatus = "YellowStatus" + FieldRedStatus = "RedStatus" + FieldExtraRedStatus = "ExtraRedStatus" +) + +const ( + FlagPickTimeDaDa = 1 + FlagBadComment = 2 + FlagAbsentGoods = 4 + FlagPickTimeDaDaOneWeek = 8 + FlagBadCommentOneWeek = 16 + FlagAbsentGoodsOneWeek = 32 + FlagStandardFinishTimeSelfDelivery = 64 + FlagStandardPickUpTimeDaDa = 128 + FlagNoOrderInMonth = 256 + FlagRiskOrderCount = 512 +) + +type StoreAlert struct { + ID int `orm:"column(id)" json:"id"` + CreatedTime time.Time `orm:"auto_now_add;type(datetime)" json:"createdTime"` + AlertDate time.Time `orm:"auto_now_add;type(datetime)" json:"alertDate"` + StoreID int `orm:"column(store_id)" json:"storeID"` + + PickTimeDaDa int `orm:"column(pick_time_order_dada)" json:"pickTimeDaDa"` + BadComment int `orm:"column(bad_comment)" json:"badComment"` + AbsentGoods int `orm:"column(absent_goods)" json:"absentGoods"` + PickTimeDaDaOneWeek int `orm:"column(pick_time_dada_oneweek)" json:"pickTimeDaDaOneWeek"` + BadCommentOneWeek int `orm:"column(bad_comment_oneweek)" json:"badCommentOneWeek"` + AbsentGoodsOneWeek int `orm:"column(absent_goods_oneweek)" json:"absentGoodsOneWeek"` + StandardFinishTimeSelfDelivery int `orm:"column(standard_finish_time_selfdelivery)" json:"standardFinishTimeSelfDelivery"` + StandardPickUpTimeDaDa int `orm:"column(standard_pickup_time_dada)" json:"standardPickUpTimeDaDa"` + + NoOrderInMonth int `json:"noOrderInMonth"` + RiskOrderCount int `json:"riskOrderCount"` + + YellowStatus int + RedStatus int + ExtraRedStatus int +} + +type StoreAlertEx struct { + StoreAlert + StoreName string `orm:"column(store_name)" json:"storeName"` + CityName string `orm:"column(city_name)" json:"cityName"` +} + +type StoreAlertProperty struct { + Value string `json:"value"` + Color string `json:"color"` +} + +type StoreAlertAdvanced struct { + ID int `json:"id"` + CreatedTime time.Time `json:"createdTime"` + AlertDate time.Time `json:"alertDate"` + StoreID int `json:"storeID"` + StoreName string `json:"storeName"` + CityName string `json:"cityName"` + + PickTimeDaDa StoreAlertProperty + BadComment StoreAlertProperty + AbsentGoods StoreAlertProperty + PickTimeDaDaOneWeek StoreAlertProperty + BadCommentOneWeek StoreAlertProperty + AbsentGoodsOneWeek StoreAlertProperty + StandardFinishTimeSelfDelivery StoreAlertProperty + StandardPickUpTimeDaDa StoreAlertProperty + + NoOrderInMonth StoreAlertProperty + RiskOrderCount StoreAlertProperty +} + +type StoreAlertData struct { + StoreAlertList []*StoreAlertAdvanced `json:"storeAlertList"` + TotalCount int `json:"totalCount"` +} + +type StoreOrderTime struct { + StoreID int `orm:"column(store_id)"` + OrderCreateTime time.Time `orm:"column(order_created_at)"` + OrderFinishedTime time.Time `orm:"column(order_finished_at)"` +} + +type StoreOrderStatus struct { + StoreID int `orm:"column(store_id)"` + VendorOrderID string `orm:"column(vendor_order_id)"` + StatusTime time.Time `orm:"column(status_time)"` + Status int `orm:"column(status)"` +} + +type StoreOrder struct { + StoreID int `orm:"column(store_id)"` + VendorOrderID string `orm:"column(vendor_order_id)"` +} diff --git a/business/model/dao/Store_Alert_Inform.go b/business/model/dao/Store_Alert_Inform.go new file mode 100644 index 000000000..690ccc464 --- /dev/null +++ b/business/model/dao/Store_Alert_Inform.go @@ -0,0 +1,51 @@ +package dao + +import ( + "fmt" + "time" + + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/model" +) + +func InsertStoreAlert(storeAlert *model.StoreAlert) error { + storeAlert.CreatedTime = time.Now() + return CreateEntity(nil, storeAlert) +} + +func GetStoreAlertList(db *DaoDB, storeIDList []int, cityCode int, keyWord string, dateTime time.Time) (storeAlertList []*model.StoreAlertEx, err error) { + sql := ` + SELECT t1.*, t2.name store_name, t3.name city_name + FROM store_alert t1 + JOIN store t2 ON t1.store_id = t2.id + JOIN place t3 ON t2.city_code = t3.code + WHERE t1.alert_date >= ? AND t1.alert_date <= ? + ` + beginTime, endTime := utils.GetTimeRange(dateTime, 1, true) + sqlParams := []interface{}{ + beginTime, + endTime, + } + if len(storeIDList) > 0 { + sql += ` + AND t2.id in (` + GenQuestionMarks(len(storeIDList)) + `)` + sqlParams = append(sqlParams, storeIDList) + } + if cityCode > 0 { + sql += ` + AND t3.code = ?` + sqlParams = append(sqlParams, cityCode) + } + if keyWord != "" { + sql += ` + AND (t2.id LIKE ? OR t2.name LIKE ? OR t3.name LIKE ?)` + keyWord = fmt.Sprintf("%%%s%%", keyWord) + sqlParams = append(sqlParams, keyWord, keyWord, keyWord) + } + sql += ` + ORDER BY t1.store_id + ` + err = GetRows(db, &storeAlertList, sql, sqlParams) + + return storeAlertList, err +} diff --git a/business/model/dao/dao_order.go b/business/model/dao/dao_order.go index 5585fcbc0..5933c8406 100644 --- a/business/model/dao/dao_order.go +++ b/business/model/dao/dao_order.go @@ -307,7 +307,7 @@ func GetDailyFinishOrderList(db *DaoDB, storeID int, dateTime time.Time) (orderL ` sqlParams := []interface{}{ storeID, - 1, + model.OrderTypeOrder, model.OrderStatusFinishedPickup, dateTime, } @@ -315,14 +315,25 @@ func GetDailyFinishOrderList(db *DaoDB, storeID int, dateTime time.Time) (orderL } func GetDailyBadCommentOrderCount(db *DaoDB, dateTime time.Time) (storeCountList []*model.StoreCount, err error) { + beginTime, endTime := utils.GetTimeRange(dateTime, 1, true) + return GetBadCommentOrderCount(db, beginTime, endTime) +} + +func GetBadCommentOrderCountByDayNum(db *DaoDB, dayNum int, includeToday bool) (storeCountList []*model.StoreCount, err error) { + beginTime, endTime := utils.GetTimeRange(utils.GetCurDate(), dayNum, includeToday) + return GetBadCommentOrderCount(db, beginTime, endTime) +} + +func GetBadCommentOrderCount(db *DaoDB, beginTime, endTime time.Time) (storeCountList []*model.StoreCount, err error) { sql := ` SELECT jxstoreid store_id, COUNT(*) count FROM jx_bad_comments - WHERE DATE(createtime) = DATE(?) + WHERE createtime >= ? AND createtime <= ? GROUP BY jxstoreid ` sqlParams := []interface{}{ - dateTime, + beginTime, + endTime, } err = GetRows(db, &storeCountList, sql, sqlParams) @@ -330,31 +341,64 @@ func GetDailyBadCommentOrderCount(db *DaoDB, dateTime time.Time) (storeCountList } func GetDailyUnFinishOrderCount(db *DaoDB, dateTime time.Time) (storeCountList []*model.StoreCount, err error) { - return GetDailyEndOrderCount(db, []int{model.OrderStatusCanceled}, false, dateTime) + beginTime, endTime := utils.GetTimeRange(dateTime, 1, true) + return GetUnFinishOrderCount(db, beginTime, endTime) } func GetDailyFinishOrderCount(db *DaoDB, dateTime time.Time) (storeCountList []*model.StoreCount, err error) { - return GetDailyEndOrderCount(db, []int{model.OrderStatusFinished}, false, dateTime) + beginTime, endTime := utils.GetTimeRange(dateTime, 1, true) + return GetFinishOrderCount(db, beginTime, endTime) } func GetDailyAbsentGoodsOrderCount(db *DaoDB, dateTime time.Time) (storeCountList []*model.StoreCount, err error) { - return GetDailyEndOrderCount(db, []int{model.OrderStatusFinished, model.OrderStatusCanceled}, true, dateTime) + beginTime, endTime := utils.GetTimeRange(dateTime, 1, true) + return GetAbsentGoodsOrderCount(db, beginTime, endTime) } -func GetDailyEndOrderCount(db *DaoDB, statusList []int, isAbsentOrder bool, dateTime time.Time) (storeCountList []*model.StoreCount, err error) { +func GetUnFinishOrderCount(db *DaoDB, beginTime, endTime time.Time) (storeCountList []*model.StoreCount, err error) { + return GetEndOrderCount(db, []int{model.OrderStatusCanceled}, false, beginTime, endTime) +} + +func GetFinishOrderCount(db *DaoDB, beginTime, endTime time.Time) (storeCountList []*model.StoreCount, err error) { + return GetEndOrderCount(db, []int{model.OrderStatusFinished}, false, beginTime, endTime) +} + +func GetAbsentGoodsOrderCount(db *DaoDB, beginTime, endTime time.Time) (storeCountList []*model.StoreCount, err error) { + return GetEndOrderCount(db, []int{model.OrderStatusFinished}, true, beginTime, endTime) +} + +func GetUnFinishOrderCountByDayNum(db *DaoDB, dayNum int, includeToday bool) (storeCountList []*model.StoreCount, err error) { + return GetEndOrderCountByDayNum(db, []int{model.OrderStatusCanceled}, false, dayNum, includeToday) +} + +func GetFinishOrderCountByDayNum(db *DaoDB, dayNum int, includeToday bool) (storeCountList []*model.StoreCount, err error) { + return GetEndOrderCountByDayNum(db, []int{model.OrderStatusFinished}, false, dayNum, includeToday) +} + +func GetAbsentGoodsOrderCountByDayNum(db *DaoDB, dayNum int, includeToday bool) (storeCountList []*model.StoreCount, err error) { + return GetEndOrderCountByDayNum(db, []int{model.OrderStatusFinished}, true, dayNum, includeToday) +} + +func GetEndOrderCountByDayNum(db *DaoDB, statusList []int, checkAbsentOrder bool, dayNum int, includeToday bool) (storeCountList []*model.StoreCount, err error) { + beginTime, endTime := utils.GetTimeRange(utils.GetCurDate(), dayNum, includeToday) + return GetEndOrderCount(db, statusList, checkAbsentOrder, beginTime, endTime) +} + +func GetEndOrderCount(db *DaoDB, statusList []int, checkAbsentOrder bool, beginTime, endTime time.Time) (storeCountList []*model.StoreCount, err error) { sql := ` SELECT jx_store_id store_id, COUNT(*) count FROM goods_order - WHERE DATE(order_finished_at) = DATE(?) + WHERE order_finished_at >= ? AND order_finished_at <= ? ` sqlParams := []interface{}{ - dateTime, + beginTime, + endTime, } if len(statusList) > 0 { sql += ` AND status IN (` + GenQuestionMarks(len(statusList)) + `)` sqlParams = append(sqlParams, statusList) } - if isAbsentOrder { + if checkAbsentOrder { sql += ` AND adjust_count > 0 ` @@ -365,3 +409,183 @@ func GetDailyEndOrderCount(db *DaoDB, statusList []int, isAbsentOrder bool, date return storeCountList, err } + +func GetFinishOrderCountByDaDa(db *DaoDB, dayNum int, includeToday bool) (storeCountList []*model.StoreCount, err error) { + return GetFinishOrderCountByWayBillVendorID(db, model.VendorIDDada, dayNum, includeToday) +} + +func GetFinishOrderCountBySelfDelivery(db *DaoDB, dayNum int, includeToday bool) (storeCountList []*model.StoreCount, err error) { + return GetFinishOrderCountByWayBillVendorID(db, model.VendorIDUnknown, dayNum, includeToday) +} + +//通过运单平台ID来统计完成的订单量 +func GetFinishOrderCountByWayBillVendorID(db *DaoDB, wayBillVendorID, dayNum int, includeToday bool) (storeCountList []*model.StoreCount, err error) { + sql := ` + SELECT jx_store_id store_id, COUNT(*) count + FROM goods_order + where order_finished_at >= ? AND order_finished_at <= ? + AND status = ? + AND waybill_vendor_id = ? + GROUP BY jx_store_id + ` + beginTime, endTime := utils.GetTimeRange(utils.GetCurDate(), dayNum, includeToday) + sqlParams := []interface{}{ + beginTime, + endTime, + model.OrderStatusFinished, + wayBillVendorID, + } + + return storeCountList, GetRows(db, &storeCountList, sql, sqlParams) +} + +//拣货履约订单量, 仅统计达达专送 +func GetStandardPickTimeOrderCountByDaDa(db *DaoDB, dayNum int, includeToday bool) (storeCountList []*model.StoreCount, err error) { + sql := ` + SELECT t1.jx_store_id store_id, COUNT(*) count + FROM goods_order t1 + JOIN order_status t2 ON t1.vendor_order_id = t2.vendor_order_id AND t1.vendor_id = t2.vendor_id + WHERE t1.order_finished_at >= ? AND t1.order_finished_at <= ? + AND t1.status = ? + AND t1.waybill_vendor_id = ? + AND t2.order_type = ? + AND t2.status = ? + AND t2.status_time <= t1.pick_deadline + GROUP BY t1.jx_store_id + ` + beginTime, endTime := utils.GetTimeRange(utils.GetCurDate(), dayNum, includeToday) + sqlParams := []interface{}{ + beginTime, + endTime, + model.OrderStatusFinished, + model.VendorIDDada, + model.OrderTypeOrder, + model.OrderStatusFinishedPickup, + } + + return storeCountList, GetRows(db, &storeCountList, sql, sqlParams) +} + +//按时履约订单量, 仅统计商家自送门店 +func GetStandardFinishTimeOrderCountBySelfDelivery(db *DaoDB, dayNum int, includeToday bool) (storeCountList []*model.StoreCount, err error) { + sql := ` + SELECT jx_store_id store_id, order_created_at, order_finished_at + FROM goods_order + WHERE order_finished_at >= ? AND order_finished_at <= ? + AND status = ? + AND waybill_vendor_id = ? + ` + beginTime, endTime := utils.GetTimeRange(utils.GetCurDate(), dayNum, includeToday) + sqlParams := []interface{}{ + beginTime, + endTime, + model.OrderStatusFinished, + model.VendorIDUnknown, + } + + standardTime := int64(3600) + var storeOrderTimeList []*model.StoreOrderTime + storeOrderTimeMapData := make(map[int]int) + err = GetRows(db, &storeOrderTimeList, sql, sqlParams) + if err == nil && len(storeOrderTimeList) > 0 { + for _, value := range storeOrderTimeList { + if value.OrderFinishedTime.Unix()-value.OrderCreateTime.Unix() <= standardTime { + storeOrderTimeMapData[value.StoreID]++ + } + } + for storeID, count := range storeOrderTimeMapData { + storeCountList = append(storeCountList, &model.StoreCount{storeID, count}) + } + } + + return storeCountList, err +} + +//10分钟取货完成订单量, 仅统计达达专送 +func GetStandardPickUpTimeOrderCountByDaDa(db *DaoDB, dayNum int, includeToday bool) (storeCountList []*model.StoreCount, err error) { + sql := ` + SELECT t1.jx_store_id store_id, t1.vendor_order_id, t2.status_time, t2.status + FROM goods_order t1 + JOIN order_status t2 ON t1.vendor_order_id = t2.vendor_order_id AND t1.vendor_id = t2.vendor_id + WHERE t1.order_finished_at >= ? AND t1.order_finished_at <= ? + AND t1.status = ? + AND t1.waybill_vendor_id = ? + AND t2.status in (?, ?) + ORDER BY t1.vendor_order_id, t2.status_time + ` + beginTime, endTime := utils.GetTimeRange(utils.GetCurDate(), dayNum, includeToday) + sqlParams := []interface{}{ + beginTime, + endTime, + model.OrderStatusFinished, + model.VendorIDDada, + model.OrderStatusFinishedPickup, + model.OrderStatusDelivering, + } + + standardTime := int64(600) + var storeOrderStatusList []*model.StoreOrderStatus + storeOrderTimeMapData := make(map[int][]*model.StoreOrderStatus) + err = GetRows(db, &storeOrderStatusList, sql, sqlParams) + if err == nil && len(storeOrderStatusList) > 0 { + for _, value := range storeOrderStatusList { + if storeOrderTimeMapData[value.StoreID] == nil { + storeOrderTimeMapData[value.StoreID] = []*model.StoreOrderStatus{} + } + storeOrderTimeMapData[value.StoreID] = append(storeOrderTimeMapData[value.StoreID], value) + } + for storeID, valueList := range storeOrderTimeMapData { + count := 0 + vendorOrderID := "" + statusBeginTime := int64(0) + statusEndTime := int64(0) + for _, value := range valueList { + if vendorOrderID != value.VendorOrderID { + if statusBeginTime != 0 && statusEndTime != 0 { + if statusEndTime-statusBeginTime <= standardTime { + count++ + } + } + vendorOrderID = value.VendorOrderID + statusBeginTime = int64(0) + statusEndTime = int64(0) + } + if value.Status == model.OrderStatusFinishedPickup { + statusBeginTime = value.StatusTime.Unix() + } else if value.Status == model.OrderStatusDelivering { + statusEndTime = value.StatusTime.Unix() + } + } + if statusBeginTime != 0 && statusEndTime != 0 { + if statusEndTime-statusBeginTime <= standardTime { + count++ + } + } + if count > 0 { + storeCountList = append(storeCountList, &model.StoreCount{storeID, count}) + } + } + } + + return storeCountList, err +} + +//风控定单(门店相关人员在自己的门店下单) +func GetRiskOrderCount(db *DaoDB, dayNum int, includeToday bool) (storeOrderList []*model.StoreOrder, err error) { + sql := ` + SELECT t1.jx_store_id store_id, t1.vendor_order_id + FROM goods_order t1 + JOIN store t2 ON t2.id = t1.jx_store_id + WHERE t1.order_finished_at >= ? AND t1.order_finished_at <= ? + AND t1.consignee_mobile2 <> "" + AND (t1.consignee_mobile2 = t2.tel1 or t1.consignee_mobile2 = t2.tel2) + GROUP BY t1.jx_store_id + ` + beginTime, endTime := utils.GetTimeRange(utils.GetCurDate(), dayNum, includeToday) + sqlParams := []interface{}{ + beginTime, + endTime, + } + + return storeOrderList, GetRows(db, &storeOrderList, sql, sqlParams) +} diff --git a/business/model/store_score.go b/business/model/store_score.go index fe2239216..b9e10857a 100644 --- a/business/model/store_score.go +++ b/business/model/store_score.go @@ -56,6 +56,11 @@ type StoreTotalScore struct { CityName string `orm:"column(city_name)" json:"cityName"` } +type StoreTotalScoreEx struct { + StoreTotalScoreList []*StoreTotalScore `json:"storeTotalScoreList"` + TotalCount int `json:"totalCount"` +} + type StoreCount struct { StoreID int `orm:"column(store_id)"` Count int diff --git a/controllers/cms_store.go b/controllers/cms_store.go index a1d44ee0d..a2213ca1e 100644 --- a/controllers/cms_store.go +++ b/controllers/cms_store.go @@ -462,12 +462,14 @@ func (c *StoreController) GetWeeklyStoreScore() { // @Param token header string true "认证token" // @Param storeIDs formData string false "京西门店ID列表" // @Param cityCode formData int false "城市编码" -// @Param keyWord formData string false "关键字" +// @Param keyword formData string false "关键字" // @Param beginTime formData string true "开始日期" // @Param endTime formData string true "结束日期" // @Param isDesc formData bool true "是否降序" // @Param checkScoreLow formData int false "在某个分数范围-低" // @Param checkScoreHigh formData int false "在某个分数范围-高" +// @Param offset formData int false "列表起始序号(以0开始,缺省为0)" +// @Param pageSize formData int false "列表页大小(缺省为50,-1表示全部)" // @Success 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult // @router /GetStoreTotalScoreList [post] @@ -477,7 +479,32 @@ func (c *StoreController) GetStoreTotalScoreList() { if err == nil { var storeIDList []int if err = jxutils.Strings2Objs(params.StoreIDs, &storeIDList); err == nil { - retVal, err = misc.GetStoreTotalScoreList(storeIDList, params.CityCode, params.KeyWord, timeList[0], timeList[1], params.IsDesc, params.CheckScoreLow, params.CheckScoreHigh) + retVal, err = misc.GetStoreTotalScoreList(storeIDList, params.CityCode, params.Keyword, timeList[0], timeList[1], params.IsDesc, params.CheckScoreLow, params.CheckScoreHigh, params.Offset, params.PageSize) + } + } + return retVal, "", err + }) +} + +// @Title 得到门店触犯红线/黄线数据 +// @Description 得到门店触犯红线/黄线数据 +// @Param token header string true "认证token" +// @Param storeIDs formData string false "京西门店ID列表" +// @Param cityCode formData int false "城市编码" +// @Param keyword formData string false "关键字" +// @Param dateTime formData string true "统计日期" +// @Param offset formData int false "列表起始序号(以0开始,缺省为0)" +// @Param pageSize formData int false "列表页大小(缺省为50,-1表示全部)" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /GetStoreAlertList [post] +func (c *StoreController) GetStoreAlertList() { + c.callGetStoreAlertList(func(params *tStoreGetStoreAlertListParams) (retVal interface{}, errCode string, err error) { + timeList, err := jxutils.BatchStr2Time(params.DateTime) + if err == nil { + var storeIDList []int + if err = jxutils.Strings2Objs(params.StoreIDs, &storeIDList); err == nil { + retVal, err = misc.GetStoreAlertList(storeIDList, params.CityCode, params.Keyword, timeList[0], params.Offset, params.PageSize) } } return retVal, "", err diff --git a/controllers/temp_op.go b/controllers/temp_op.go index 8a86a2a3e..f27734b67 100644 --- a/controllers/temp_op.go +++ b/controllers/temp_op.go @@ -316,3 +316,20 @@ func (c *TempOpController) CreateConsumerFromOrders() { return retVal, "", err }) } + +// @Title 触犯红线通知 +// @Description 触犯红线通知 +// @Param token header string true "认证token" +// @Param storeIDs formData string false "门店列表" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /CheckStoreAlert [post] +func (c *TempOpController) CheckStoreAlert() { + c.callCheckStoreAlert(func(params *tTempopCheckStoreAlertParams) (retVal interface{}, errCode string, err error) { + var storeIDs []int + if err = jxutils.Strings2Objs(params.StoreIDs, &storeIDs); err == nil { + misc.CheckStoreAlert(params.Ctx, storeIDs) + } + return retVal, "", err + }) +} diff --git a/globals/beegodb/beegodb.go b/globals/beegodb/beegodb.go index 2c0e11aca..eded1d8e9 100644 --- a/globals/beegodb/beegodb.go +++ b/globals/beegodb/beegodb.go @@ -55,6 +55,7 @@ func Init() { orm.RegisterModel(&model.CasbinRule{}) orm.RegisterModel(&model.SensitiveWord{}) orm.RegisterModel(&model.StoreScore{}) + orm.RegisterModel(&model.StoreAlert{}) orm.RegisterModel(&model.FoodRecipe{}, &model.FoodRecipeStep{}, &model.FoodRecipeItem{}, &model.FoodRecipeItemChoice{}, &model.FoodRecipeUser{}) orm.RegisterModel(&model.DataResource{}) diff --git a/routers/commentsRouter_controllers.go b/routers/commentsRouter_controllers.go index 8351784c6..3a7ba9778 100644 --- a/routers/commentsRouter_controllers.go +++ b/routers/commentsRouter_controllers.go @@ -1251,6 +1251,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], + beego.ControllerComments{ + Method: "GetStoreAlertList", + Router: `/GetStoreAlertList`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:StoreController"], beego.ControllerComments{ Method: "GetStoreCourierMaps", @@ -1656,6 +1665,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TempOpController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TempOpController"], + beego.ControllerComments{ + Method: "CheckStoreAlert", + Router: `/CheckStoreAlert`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TempOpController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:TempOpController"], beego.ControllerComments{ Method: "CreateConsumerFromOrders",