diff --git a/business/jxstore/misc/Store_Alert_Inform.go b/business/jxstore/misc/Store_Alert_Inform.go index 68135d9e8..24d242448 100644 --- a/business/jxstore/misc/Store_Alert_Inform.go +++ b/business/jxstore/misc/Store_Alert_Inform.go @@ -11,23 +11,25 @@ import ( ) const ( + IncludeToday = true CheckStoreAlertOneMonthDayNum = 30 CheckStoreAlertOneDayNum = 1 CheckStoreAlertOneWeekDayNum = 7 MonthCheckOnWeekDay = 1 - AlertTypePickTimeOrderDaDa = 0 - AlertTypeBadCommentOrder = 1 - AlertTypeAbsentGoodsOrder = 2 - AlertTypePickTimeOrderSelfDelivery = 3 - AlertTypePickUpTimeOrderDaDa = 4 + AlertTypePickTimeOrderDaDa = 0 + AlertTypeBadCommentOrder = 1 + AlertTypeAbsentGoodsOrder = 2 + AlertTypeStandardFinishTimeOrderSelfDelivery = 3 + AlertTypeStandardPickUpTimeOrderDaDa = 4 - OneDayName = "单日" - OneWeekDayName = "七日" - OneMonthDayName = "三十日" - YellowAlertInfo = "您的店铺京西菜市-%s,由于%s%s>=%d%%,可能会被系统下线,请及时补救。" - RedAlertInfo = "您的店铺京西菜市-%s,由于%s%s>=%d%%,会被系统下线,需要马上补救。" - NoOrderAlertInfo = "您的店铺京西菜市-%s,由于近%s无订单,会被系统下线,需要马上补救。" + OneDayName = "单日" + OneWeekDayName = "七日" + OneMonthDayName = "三十日" + YellowAlertInfo = "您的店铺京西菜市-%s,由于%s%s>=%d%%,可能会被系统下线,请及时补救。" + RedAlertInfo = "您的店铺京西菜市-%s,由于%s%s>=%d%%,会被系统下线,需要马上补救。" + NoOrderAlertInfo = "您的店铺京西菜市-%s,由于近%s无订单,会被系统下线,需要马上补救。" + RiskOrderAlertInfo = "系统检测到您的店铺可能有虚假定单,定单号为:%s,可能会被罚款,请及时与运营联系!" ) var ( @@ -36,11 +38,11 @@ var ( } AlertTypeNameMap = map[int]string{ - AlertTypePickTimeOrderDaDa: "拣货履约率(达达)", - AlertTypeBadCommentOrder: "差评率", - AlertTypeAbsentGoodsOrder: "缺货率", - AlertTypePickTimeOrderSelfDelivery: "按时履约率(商家自送)", - AlertTypePickUpTimeOrderDaDa: "10分钟取货完成率(达达)", + AlertTypePickTimeOrderDaDa: "拣货履约率(达达)", + AlertTypeBadCommentOrder: "差评率", + AlertTypeAbsentGoodsOrder: "缺货率", + AlertTypeStandardFinishTimeOrderSelfDelivery: "按时履约率(商家自送)", + AlertTypeStandardPickUpTimeOrderDaDa: "10分钟取货完成率(达达)", } ) @@ -53,7 +55,20 @@ func ConvertListToMap(listData []*model.StoreCount) (mapData map[int]int) { return mapData } -func GetAlertInfo(dayNum int, isRedAlert bool, storeName string, alertType int, ratio int) (info string) { +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{} + } + vendorOrderIDList := mapData[value.StoreID] + vendorOrderIDList = append(vendorOrderIDList, value.VendorOrderID) + } + + return mapData +} + +func GetAlertInfo(dayNum int, isRedAlert bool, storeName string, alertType int, ratio float64) (info string) { if dayNum == CheckStoreAlertOneDayNum { if isRedAlert { info = fmt.Sprintf(RedAlertInfo, storeName, OneDayName, AlertTypeNameMap[alertType], ratio) @@ -73,162 +88,199 @@ func GetAlertInfo(dayNum int, isRedAlert bool, storeName string, alertType int, return info } -func GetAlertRatio(alertType int, dayNum int) (yellowRatio, redRatio float64) { +func CheckAlert(alertType int, dayNum int, ratio float64, count int) (isYellowAlert, isRedAlert bool) { + yellowRatio := float64(-1) + redRatio := float64(-1) + extraCount := -1 + conditionLessEqual := false + switch alertType { case AlertTypePickTimeOrderDaDa: if dayNum == CheckStoreAlertOneDayNum { - yellowRatio = -1 redRatio = 0 - } else { + } else if dayNum == CheckStoreAlertOneWeekDayNum { yellowRatio = 70 redRatio = 50 + extraCount = 5 } + conditionLessEqual = false case AlertTypeBadCommentOrder: if dayNum == CheckStoreAlertOneDayNum { - yellowRatio = -1 redRatio = 100 - } else { + } else if dayNum == CheckStoreAlertOneWeekDayNum { yellowRatio = 1 redRatio = 3 + extraCount = 5 } + conditionLessEqual = true case AlertTypeAbsentGoodsOrder: if dayNum == CheckStoreAlertOneDayNum { - yellowRatio = -1 redRatio = 100 - } else { + } else if dayNum == CheckStoreAlertOneWeekDayNum { yellowRatio = 3 redRatio = 5 + extraCount = 5 } - case AlertTypePickTimeOrderSelfDelivery: + conditionLessEqual = true + case AlertTypeStandardFinishTimeOrderSelfDelivery: yellowRatio = 85 redRatio = 70 - case AlertTypePickUpTimeOrderDaDa: + conditionLessEqual = false + case AlertTypeStandardPickUpTimeOrderDaDa: yellowRatio = 85 redRatio = 70 - default: - yellowRatio = -1 - redRatio = -1 + conditionLessEqual = false } - return float64(yellowRatio), float64(redRatio) + if conditionLessEqual { + if extraCount != -1 && count >= extraCount { + isRedAlert = true + } else if redRatio != -1 && ratio <= redRatio { + isRedAlert = true + } else if yellowRatio != -1 && ratio <= yellowRatio { + isYellowAlert = true + } + } else { + if extraCount != -1 && count >= extraCount { + isRedAlert = true + } else if redRatio != -1 && ratio >= redRatio { + isRedAlert = true + } else if yellowRatio != -1 && ratio >= yellowRatio { + isYellowAlert = true + } + } + + return isYellowAlert, isRedAlert } -func CheckStoreDayAlert(storeMapData map[int]*cms.StoreExt, dayNum int) (retVal interface{}, err error) { +func SendAlertInfo(storeID int, alertInfo string) { + fmt.Printf("SendAlertInfo:%d %s\n", storeID, alertInfo) +} + +func SendAlertInfoWrapper(storeID int, storeName string, dayNum, alertType, count, totalCount int) { + if totalCount > 0 { + ratio := float64(count) * 100 / float64(totalCount) + yellowAlert, redAlert := CheckAlert(alertType, dayNum, ratio, count) + isAlert := false + isRedAlert := redAlert + isAlert = yellowAlert || redAlert + if isAlert { + alertInfo := GetAlertInfo(dayNum, isRedAlert, storeName, alertType, ratio) + SendAlertInfo(storeID, alertInfo) + } + } +} + +func CheckStoreDayAlert(storeMapData map[int]*cms.StoreExt, dayNum int) { db := dao.GetDB() - //拣货履约率(达达) - pickTimeOrderCountDaDa, err := dao.GetStandardPickTimeOrderCountByDaDa(db, dayNum, true) - pickTimeOrderCountDaDaMapData := ConvertListToMap(pickTimeOrderCountDaDa) + //拣货履约订单(达达) + pickTimeOrderCountDaDaList, _ := dao.GetStandardPickTimeOrderCountByDaDa(db, dayNum, IncludeToday) + pickTimeOrderCountDaDaMapData := ConvertListToMap(pickTimeOrderCountDaDaList) + //完成订单(达达) - finishOrderCountDaDa, err := dao.GetFinishOrderCountByDaDa(db, dayNum, true) - finishOrderCountDaDaMapData := ConvertListToMap(finishOrderCountDaDa) + finishOrderCountDaDaList, _ := dao.GetFinishOrderCountByDaDa(db, dayNum, IncludeToday) + finishOrderCountDaDaMapData := ConvertListToMap(finishOrderCountDaDaList) + //差评订单 - badCommentOrderCount, err := dao.GetBadCommentOrderCountByDayNum(db, dayNum, true) - badCommentOrderCountMapData := ConvertListToMap(badCommentOrderCount) + badCommentOrderCountList, _ := dao.GetBadCommentOrderCountByDayNum(db, dayNum, IncludeToday) + badCommentOrderCountMapData := ConvertListToMap(badCommentOrderCountList) + //缺货订单 - absentGoodsOrderCount, err := dao.GetAbsentGoodsOrderCountByDayNum(db, dayNum, true) - absentGoodsOrderCountMapData := ConvertListToMap(absentGoodsOrderCount) + absentGoodsOrderCountList, _ := dao.GetAbsentGoodsOrderCountByDayNum(db, dayNum, IncludeToday) + absentGoodsOrderCountMapData := ConvertListToMap(absentGoodsOrderCountList) + //完成订单 - finishOrderCount, err := dao.GetFinishOrderCountByDayNum(db, dayNum, true) - finishOrderCountMapData := ConvertListToMap(finishOrderCount) - //按时履约订单(商家自送) - standardFinishTimeOrderCountSelfDelivery, err := dao.GetStandardFinishTimeOrderCountBySelfDelivery(db, dayNum, true) - standardFinishTimeOrderCountSelfDeliveryMapData := ConvertListToMap(standardFinishTimeOrderCountSelfDelivery) - //完成订单(商家自送) - finishOrderCountSelfDelivery, err := dao.GetFinishOrderCountBySelfDelivery(db, dayNum, true) - finishOrderCountSelfDeliveryMapData := ConvertListToMap(finishOrderCountSelfDelivery) - //10分钟取货完成订单量(达达) - standardPickUpTimeOrderCountSelfDelivery, err := dao.GetStandardPickUpTimeOrderCountBySelfDelivery(db, dayNum, true) - standardPickUpTimeOrderCountSelfDeliveryMapData := ConvertListToMap(standardPickUpTimeOrderCountSelfDelivery) + finishOrderCountList, _ := dao.GetFinishOrderCountByDayNum(db, dayNum, IncludeToday) + finishOrderCountMapData := ConvertListToMap(finishOrderCountList) - pickTimeOrderDaDaStoreIDListRed := []int{} - badCommentOrderStoreIDListRed := []int{} - absentGoodsOrderStoreIDListRed := []int{} + 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) + } - pickTimeOrderDaDaStoreIDListYellow := []int{} - badCommentOrderStoreIDListYellow := []int{} - absentGoodsOrderStoreIDListYellow := []int{} for _, storeInfo := range storeMapData { storeID := storeInfo.ID - pickTimeOrderCountDaDa := pickTimeOrderCountDaDaMapData[storeID] - finishOrderCountDaDa := finishOrderCountDaDaMapData[storeID] - if finishOrderCountDaDa > 0 { - pickTimeOrderDaDaRatio := float64(pickTimeOrderCountDaDa) * 100 / float64(finishOrderCountDaDa) - yellowRatio, redRatio := GetAlertRatio(AlertTypePickTimeOrderDaDa, dayNum) - if redRatio != -1 && pickTimeOrderDaDaRatio <= redRatio { - pickTimeOrderDaDaStoreIDListRed = append(pickTimeOrderDaDaStoreIDListRed, storeID) - } else if yellowRatio != -1 && pickTimeOrderDaDaRatio <= yellowRatio { - pickTimeOrderDaDaStoreIDListYellow = append(pickTimeOrderDaDaStoreIDListYellow, storeID) - } - } + storeName := storeInfo.Name + count := pickTimeOrderCountDaDaMapData[storeID] + totalCount := finishOrderCountDaDaMapData[storeID] + SendAlertInfoWrapper(storeID, storeName, dayNum, AlertTypePickTimeOrderDaDa, count, totalCount) - badCommentOrderCount := badCommentOrderCountMapData[storeID] - absentGoodsOrderCount := absentGoodsOrderCountMapData[storeID] - finishOrderCount := finishOrderCountMapData[storeID] - if finishOrderCount > 0 { - badCommentOrderRatio := float64(badCommentOrderCount) * 100 / float64(finishOrderCount) - yellowRatio, redRatio := GetAlertRatio(AlertTypeBadCommentOrder, dayNum) - if redRatio != -1 && badCommentOrderRatio >= redRatio { - badCommentOrderStoreIDListRed = append(badCommentOrderStoreIDListRed, storeID) - } else if yellowRatio != -1 && badCommentOrderRatio >= yellowRatio { - badCommentOrderStoreIDListYellow = append(badCommentOrderStoreIDListYellow, storeID) - } + count = badCommentOrderCountMapData[storeID] + totalCount = finishOrderCountMapData[storeID] + SendAlertInfoWrapper(storeID, storeName, dayNum, AlertTypeBadCommentOrder, count, totalCount) + count = absentGoodsOrderCountMapData[storeID] + SendAlertInfoWrapper(storeID, storeName, dayNum, AlertTypeAbsentGoodsOrder, count, totalCount) - absentGoodsOrderRatio := float64(absentGoodsOrderCount) * 100 / float64(finishOrderCount) - yellowRatio, redRatio = GetAlertRatio(AlertTypeAbsentGoodsOrder, dayNum) - if redRatio != -1 && absentGoodsOrderRatio >= redRatio { - absentGoodsOrderStoreIDListRed = append(absentGoodsOrderStoreIDListRed, storeID) - } else if yellowRatio != -1 && absentGoodsOrderRatio >= yellowRatio { - absentGoodsOrderStoreIDListYellow = append(absentGoodsOrderStoreIDListYellow, storeID) - } - } + if isOneWeekDay { + count = standardFinishTimeOrderCountSelfDeliveryMapData[storeID] + totalCount = finishOrderCountSelfDeliveryMapData[storeID] + SendAlertInfoWrapper(storeID, storeName, dayNum, AlertTypeStandardFinishTimeOrderSelfDelivery, count, totalCount) - if dayNum == CheckStoreAlertOneWeekDayNum { - standardFinishTimeOrderCountSelfDelivery := standardFinishTimeOrderCountSelfDeliveryMapData[storeID] - finishOrderCountSelfDelivery := finishOrderCountSelfDeliveryMapData[storeID] - if finishOrderCountSelfDelivery > 0 { - standardFinishTimeOrderSelfDeliveryRatio := float64(standardFinishTimeOrderCountSelfDelivery) * 100 / float64(finishOrderCountSelfDelivery) - yellowRatio, redRatio := GetAlertRatio(AlertTypePickTimeOrderSelfDelivery, dayNum) - if redRatio != -1 && standardFinishTimeOrderSelfDeliveryRatio <= redRatio { - - } else if yellowRatio != -1 && standardFinishTimeOrderSelfDeliveryRatio <= yellowRatio { - - } - } - - standardPickUpTimeOrderCountSelfDelivery := standardPickUpTimeOrderCountSelfDeliveryMapData[storeID] - finishOrderCountDaDa := finishOrderCountDaDaMapData[storeID] - if finishOrderCountSelfDelivery > 0 { - standardPickUpTimeOrderSelfDeliveryRatio := float64(standardPickUpTimeOrderCountSelfDelivery) * 100 / float64(finishOrderCountDaDa) - yellowRatio, redRatio := GetAlertRatio(AlertTypePickUpTimeOrderDaDa, dayNum) - if redRatio != -1 && standardPickUpTimeOrderSelfDeliveryRatio <= redRatio { - - } else if yellowRatio != -1 && standardPickUpTimeOrderSelfDeliveryRatio <= yellowRatio { - - } - } + count = standardPickUpTimeOrderCountDaDaMapData[storeID] + totalCount = finishOrderCountDaDaMapData[storeID] + SendAlertInfoWrapper(storeID, storeName, dayNum, AlertTypeStandardPickUpTimeOrderDaDa, count, totalCount) } } - - return retVal, err } -func CheckStoreMonthAlert(storeMapData map[int]*cms.StoreExt) (retVal interface{}, err error) { +func CheckStoreMonthAlert(storeMapData map[int]*cms.StoreExt) { db := dao.GetDB() - storeCountList, err := dao.GetFinishOrderCountByDayNum(db, CheckStoreAlertOneMonthDayNum, true) + storeCountList, _ := dao.GetFinishOrderCountByDayNum(db, CheckStoreAlertOneMonthDayNum, IncludeToday) storeCountMapData := make(map[int]int) for _, value := range storeCountList { storeCountMapData[value.StoreID] = value.Count } - alertStoreIDList := []int{} for _, storeInfo := range storeMapData { storeID := storeInfo.ID + storeName := storeInfo.Name if _, ok := storeCountMapData[storeID]; !ok { - alertStoreIDList = append(alertStoreIDList, storeID) + alertInfo := GetAlertInfo(CheckStoreAlertOneMonthDayNum, true, storeName, -1, -1) + SendAlertInfo(storeID, alertInfo) } } +} - return retVal, err +func CheckStoreRiskOrderAlert(storeMapData map[int]*cms.StoreExt, dayNum int) { + db := dao.GetDB() + storeOrderList, _ := dao.GetRiskOrderCount(db, dayNum, IncludeToday) + storeOrderMapData := ConvertListToMapEx(storeOrderList) + for _, storeInfo := range storeMapData { + storeID := storeInfo.ID + vendorOrderIDList := storeOrderMapData[storeID] + if vendorOrderIDList != nil { + vendorOrderIDStr := "" + for index, vendorOrderID := range vendorOrderIDList { + if index == 0 { + vendorOrderIDStr += vendorOrderID + } else { + vendorOrderIDStr += "," + vendorOrderID + } + } + alertInfo := fmt.Sprintf(RiskOrderAlertInfo, vendorOrderIDStr) + SendAlertInfo(storeID, alertInfo) + } + } +} + +func GetWeekDay() int { + return int(time.Now().Weekday()) } func CheckStoreAlert(ctx *jxcontext.Context) { @@ -242,10 +294,7 @@ func CheckStoreAlert(ctx *jxcontext.Context) { } CheckStoreDayAlert(storeMapData, CheckStoreAlertOneDayNum) CheckStoreDayAlert(storeMapData, CheckStoreAlertOneWeekDayNum) -} - -func GetWeekDay() int { - return int(time.Now().Weekday()) + CheckStoreRiskOrderAlert(storeMapData, CheckStoreAlertOneDayNum) } func ScheduleCheckStoreAlert() { diff --git a/business/model/Store_Alert_Inform.go b/business/model/Store_Alert_Inform.go index 6b799489c..fec0c7089 100644 --- a/business/model/Store_Alert_Inform.go +++ b/business/model/Store_Alert_Inform.go @@ -14,3 +14,8 @@ type StoreOrderStatus struct { 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)"` +} \ No newline at end of file diff --git a/business/model/dao/dao_order.go b/business/model/dao/dao_order.go index 4c771ea07..163e33a81 100644 --- a/business/model/dao/dao_order.go +++ b/business/model/dao/dao_order.go @@ -435,7 +435,7 @@ func GetFinishOrderCountByWayBillVendorID(db *DaoDB, wayBillVendorID, dayNum int //拣货履约订单量, 仅统计达达专送 func GetStandardPickTimeOrderCountByDaDa(db *DaoDB, dayNum int, includeToday bool) (storeCountList []*model.StoreCount, err error) { sql := ` - SELECT jx_store_id store_id, COUNT(*) count + SELECT t1.jx_store_id store_id, COUNT(*) count FROM goods_order t1 JOIN order_status t2 ON t2.vendor_order_id = t1.vendor_order_id where t1.order_finished_at >= ? AND t1.order_finished_at <= ? @@ -444,7 +444,7 @@ func GetStandardPickTimeOrderCountByDaDa(db *DaoDB, dayNum int, includeToday boo AND t2.order_type = ? AND t2.status = ? AND t2.status_time <= t1.pick_deadline - GROUP BY jx_store_id + GROUP BY t1.jx_store_id ` beginTime, endTime := utils.GetTimeRange(utils.GetCurDate(), dayNum, includeToday) sqlParams := []interface{}{ @@ -495,7 +495,7 @@ func GetStandardFinishTimeOrderCountBySelfDelivery(db *DaoDB, dayNum int, includ } //10分钟取货完成订单量, 仅统计达达专送 -func GetStandardPickUpTimeOrderCountBySelfDelivery(db *DaoDB, dayNum int, includeToday bool) (storeCountList []*model.StoreCount, err error) { +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 @@ -562,3 +562,23 @@ func GetStandardPickUpTimeOrderCountBySelfDelivery(db *DaoDB, dayNum int, includ 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) +}