门店触犯红线通知

This commit is contained in:
Rosy-zhudan
2019-09-27 16:30:18 +08:00
parent a7b2dc3abd
commit 6f579e7f1b
3 changed files with 199 additions and 125 deletions

View File

@@ -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() {

View File

@@ -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)"`
}

View File

@@ -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)
}