shan
This commit is contained in:
@@ -1,74 +0,0 @@
|
|||||||
package orderman
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
|
||||||
"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/netprinter"
|
|
||||||
"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/business/partner/purchase/jd"
|
|
||||||
"git.rosy.net.cn/jx-callback/globals"
|
|
||||||
"git.rosy.net.cn/jx-callback/globals/api"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *OrderManager) OnNewFakeJdOrder(vendorOrderID string) (err error) {
|
|
||||||
utils.CallFuncAsync(func() {
|
|
||||||
orderInfo, err := api.FakeJdAPI.FakeQuerySingleOrderRaw(vendorOrderID)
|
|
||||||
if err == nil {
|
|
||||||
order := jd.Map2Order(orderInfo)
|
|
||||||
jxutils.RefreshOrderSkuRelated(order)
|
|
||||||
err = c.notifyNewFakeJdOrder(order)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
globals.SugarLogger.Warnf("OnNewFakeJdOrder failed with err:%v", err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *OrderManager) notifyNewFakeJdOrder(order *model.GoodsOrder) (err error) {
|
|
||||||
db := dao.GetDB()
|
|
||||||
storeDetail, err := dao.GetStoreDetailByVendorStoreID(db, order.VendorStoreID, model.VendorIDJD)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
realStoreID := storeDetail.ID
|
|
||||||
if storeDetail.LinkStoreID != 0 {
|
|
||||||
realStoreID = storeDetail.LinkStoreID
|
|
||||||
}
|
|
||||||
notifyWxNewFakeJdOrder(order, realStoreID)
|
|
||||||
netprinter.PrintOrderByOrder4Store(jxcontext.AdminCtx, order, realStoreID)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func notifyWxNewFakeJdOrder(order *model.GoodsOrder, storeID int) (err error) {
|
|
||||||
globals.SugarLogger.Debugf("notifyWxNewFakeJdOrder orderID:%s", order.VendorOrderID)
|
|
||||||
|
|
||||||
sb := new(strings.Builder)
|
|
||||||
sb.WriteString("老板,你有新订单了\n")
|
|
||||||
sb.WriteString(fmt.Sprintf("订单号:%s\n", order.VendorOrderID))
|
|
||||||
sb.WriteString("送达时间:")
|
|
||||||
if order.BusinessType == model.BusinessTypeDingshida {
|
|
||||||
sb.WriteString(utils.Time2Str(order.ExpectedDeliveredTime))
|
|
||||||
} else {
|
|
||||||
sb.WriteString("立即达")
|
|
||||||
}
|
|
||||||
sb.WriteString("\n")
|
|
||||||
sb.WriteString(fmt.Sprintf("买家:%s\n", order.ConsigneeName))
|
|
||||||
sb.WriteString(fmt.Sprintf("电话:%s\n", order.ConsigneeMobile))
|
|
||||||
sb.WriteString(fmt.Sprintf("收货地址:%s\n", order.ConsigneeAddress))
|
|
||||||
sb.WriteString("商品详情:\n")
|
|
||||||
for _, sku := range order.Skus {
|
|
||||||
sb.WriteString(fmt.Sprintf("\t%s*%d\n", sku.SkuName, sku.Count))
|
|
||||||
}
|
|
||||||
title := fmt.Sprintf("你有到家菜市新订单%d", order.OrderSeq)
|
|
||||||
content := sb.String()
|
|
||||||
// globals.SugarLogger.Debugf("notifyWxNewFakeJdOrder, orderID:%s, content:%s", order.VendorOrderID, content)
|
|
||||||
_, err = weixinmsg.SendStoreMessage(jxcontext.AdminCtx, title, content, []int{storeID}, true, true)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package orderman
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestOnNewFakeJdOrder(t *testing.T) {
|
|
||||||
err := FixedOrderManager.OnNewFakeJdOrder("2002984074001021")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
time.Sleep(3 * time.Second)
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,209 +0,0 @@
|
|||||||
package act
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
|
||||||
"git.rosy.net.cn/jx-callback/globals"
|
|
||||||
"git.rosy.net.cn/jx-callback/globals/testinit"
|
|
||||||
|
|
||||||
"git.rosy.net.cn/jx-callback/business/model"
|
|
||||||
|
|
||||||
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/ebai"
|
|
||||||
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/jd"
|
|
||||||
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/mtwm"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
testinit.Init()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInitDb(t *testing.T) {
|
|
||||||
dao.ExecuteSQL(dao.GetDB(), `
|
|
||||||
DROP TABLE IF EXISTS act, act_map, act_order_rule, act_store_sku, act_store_sku_map;
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCreateActOnAlpha(t *testing.T) {
|
|
||||||
actStoreSkuList := []*ActStoreSkuParam{
|
|
||||||
&ActStoreSkuParam{
|
|
||||||
ActStoreSku: model.ActStoreSku{
|
|
||||||
StoreID: 2,
|
|
||||||
SkuID: 2142,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
&ActStoreSkuParam{
|
|
||||||
ActStoreSku: model.ActStoreSku{
|
|
||||||
StoreID: 2,
|
|
||||||
SkuID: 1162,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
&ActStoreSkuParam{
|
|
||||||
ActStoreSku: model.ActStoreSku{
|
|
||||||
StoreID: 2,
|
|
||||||
SkuID: 1167,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
&ActStoreSkuParam{
|
|
||||||
ActStoreSku: model.ActStoreSku{
|
|
||||||
StoreID: 2,
|
|
||||||
SkuID: 1172,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
t.Log(utils.Format4Output(actStoreSkuList, true))
|
|
||||||
// actID, err := CreateAct(jxcontext.AdminCtx, &model.Act{
|
|
||||||
// Name: "测试活动",
|
|
||||||
// PricePercentage: 80,
|
|
||||||
// Type: model.ActSkuDirectDown,
|
|
||||||
// }, []int{model.VendorIDJD, model.VendorIDMTWM, model.VendorIDEBAI}, nil, actStoreSkuList, false)
|
|
||||||
// if err != nil {
|
|
||||||
// t.Fatal(err)
|
|
||||||
// }
|
|
||||||
// globals.SugarLogger.Debug(actID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCreateActOnDev(t *testing.T) {
|
|
||||||
actStoreSkuList := []*ActStoreSkuParam{
|
|
||||||
&ActStoreSkuParam{
|
|
||||||
ActStoreSku: model.ActStoreSku{
|
|
||||||
StoreID: 100884,
|
|
||||||
SkuID: 22716,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
&ActStoreSkuParam{
|
|
||||||
ActStoreSku: model.ActStoreSku{
|
|
||||||
StoreID: 100884,
|
|
||||||
SkuID: 22717,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
&ActStoreSkuParam{
|
|
||||||
ActStoreSku: model.ActStoreSku{
|
|
||||||
StoreID: 100920,
|
|
||||||
SkuID: 22714,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
&ActStoreSkuParam{
|
|
||||||
ActStoreSku: model.ActStoreSku{
|
|
||||||
StoreID: 100920,
|
|
||||||
SkuID: 22715,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// &ActStoreSkuParam{
|
|
||||||
// ActStoreSku: model.ActStoreSku{
|
|
||||||
// StoreID: 100119,
|
|
||||||
// SkuID: 26595,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
}
|
|
||||||
// t.Log(utils.Format4Output(actStoreSkuList, true))
|
|
||||||
actID, err := CreateAct(jxcontext.AdminCtx, &model.Act{
|
|
||||||
Name: "测试活动",
|
|
||||||
PricePercentage: 80,
|
|
||||||
Type: model.ActSkuDirectDown,
|
|
||||||
BeginAt: time.Now().Add(-24 * time.Hour),
|
|
||||||
EndAt: time.Now().Add(10 * 24 * time.Hour),
|
|
||||||
}, []int{model.VendorIDJD, model.VendorIDMTWM /*, model.VendorIDEBAI*/}, nil, actStoreSkuList, false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
globals.SugarLogger.Debug(actID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCancelAct(t *testing.T) {
|
|
||||||
err := CancelAct(jxcontext.AdminCtx, 1)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDeleteActStoreBind(t *testing.T) {
|
|
||||||
_, err := DeleteActStoreSkuBind(jxcontext.AdminCtx, dao.GetDB(), 1, []*ActStoreSkuParam{
|
|
||||||
// &ActStoreSkuParam{
|
|
||||||
// ActStoreSku: model.ActStoreSku{
|
|
||||||
// StoreID: 100119,
|
|
||||||
// SkuID: 30828,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// &ActStoreSkuParam{
|
|
||||||
// ActStoreSku: model.ActStoreSku{
|
|
||||||
// StoreID: 100119,
|
|
||||||
// SkuID: 30827,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
&ActStoreSkuParam{
|
|
||||||
ActStoreSku: model.ActStoreSku{
|
|
||||||
StoreID: 100884,
|
|
||||||
SkuID: 22716,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
&ActStoreSkuParam{
|
|
||||||
ActStoreSku: model.ActStoreSku{
|
|
||||||
StoreID: 100884,
|
|
||||||
SkuID: 22717,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddActStoreBind(t *testing.T) {
|
|
||||||
err := AddActStoreSkuBind(jxcontext.AdminCtx, dao.GetDB(), 1, []*ActStoreSkuParam{
|
|
||||||
// &ActStoreSkuParam{
|
|
||||||
// ActStoreSku: model.ActStoreSku{
|
|
||||||
// StoreID: 100119,
|
|
||||||
// SkuID: 30828,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// &ActStoreSkuParam{
|
|
||||||
// ActStoreSku: model.ActStoreSku{
|
|
||||||
// StoreID: 100119,
|
|
||||||
// SkuID: 30827,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
&ActStoreSkuParam{
|
|
||||||
ActStoreSku: model.ActStoreSku{
|
|
||||||
StoreID: 100884,
|
|
||||||
SkuID: 22716,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
&ActStoreSkuParam{
|
|
||||||
ActStoreSku: model.ActStoreSku{
|
|
||||||
StoreID: 100884,
|
|
||||||
SkuID: 22717,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSyncAct(t *testing.T) {
|
|
||||||
_, err := SyncAct(jxcontext.AdminCtx, nil, 1, nil, false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestForceUpdateVendorPrice(t *testing.T) {
|
|
||||||
hint, err := ForceUpdateVendorPrice(jxcontext.AdminCtx, model.VendorIDJD, model.ActSkuDirectDown, []*ActStoreSkuParam{
|
|
||||||
&ActStoreSkuParam{
|
|
||||||
ActStoreSku: model.ActStoreSku{
|
|
||||||
StoreID: 100118,
|
|
||||||
SkuID: 22509,
|
|
||||||
ActPrice: 9900,
|
|
||||||
},
|
|
||||||
VendorPrice: 19900,
|
|
||||||
},
|
|
||||||
}, false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
t.Log(hint)
|
|
||||||
}
|
|
||||||
@@ -1,531 +1,27 @@
|
|||||||
package misc
|
package misc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.rosy.net.cn/jx-callback/business/partner/purchase/jdshop"
|
|
||||||
|
|
||||||
"git.rosy.net.cn/baseapi/platformapi/jdapi"
|
|
||||||
|
|
||||||
"git.rosy.net.cn/jx-callback/business/partner/purchase/jx/localjx"
|
|
||||||
"git.rosy.net.cn/jx-callback/globals/api"
|
|
||||||
|
|
||||||
"git.rosy.net.cn/jx-callback/business/jxstore/event"
|
|
||||||
|
|
||||||
"git.rosy.net.cn/jx-callback/business/jxstore/report"
|
|
||||||
|
|
||||||
"git.rosy.net.cn/baseapi/utils"
|
"git.rosy.net.cn/baseapi/utils"
|
||||||
"git.rosy.net.cn/baseapi/utils/errlist"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/jxcallback/orderman"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/jxcallback/scheduler/defsch"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/jxstore/act"
|
|
||||||
"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"
|
||||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/jxutils/netprinter"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/model"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/netspider"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/partner"
|
|
||||||
"git.rosy.net.cn/jx-callback/globals"
|
"git.rosy.net.cn/jx-callback/globals"
|
||||||
"github.com/astaxie/beego"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
SpecialTaskID = "Running"
|
|
||||||
TaskNameSyncStoreSku = "SyncStoreSku"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
dailyHeartbeat = []string{
|
|
||||||
"09:00:00",
|
|
||||||
}
|
|
||||||
dailyWorkTimeList = []string{
|
dailyWorkTimeList = []string{
|
||||||
"20:30:00",
|
"20:30:00",
|
||||||
}
|
}
|
||||||
dailyWorkTimeList2 = []string{
|
|
||||||
"02:00:00",
|
|
||||||
}
|
|
||||||
priceReferTimeList = []string{
|
|
||||||
"03:00:00",
|
|
||||||
}
|
|
||||||
checkCookieList = []string{
|
|
||||||
"08:00:00",
|
|
||||||
"12:00:00",
|
|
||||||
"18:00:00",
|
|
||||||
}
|
|
||||||
createStorePriceTimeList = []string{
|
|
||||||
"04:00:00",
|
|
||||||
}
|
|
||||||
refreshPageActTimeList = []string{
|
|
||||||
"7:00:00",
|
|
||||||
"8:00:00",
|
|
||||||
"9:00:00",
|
|
||||||
"10:00:00",
|
|
||||||
"11:00:00",
|
|
||||||
"12:00:00",
|
|
||||||
"13:00:00",
|
|
||||||
"14:00:00",
|
|
||||||
"15:00:00",
|
|
||||||
"16:00:00",
|
|
||||||
"17:00:00",
|
|
||||||
"18:00:00",
|
|
||||||
"19:00:00",
|
|
||||||
"22:00:00",
|
|
||||||
}
|
|
||||||
ChangeStoreSkuSaleStatusList = []string{
|
|
||||||
"7:00:00",
|
|
||||||
"8:00:00",
|
|
||||||
"9:00:00",
|
|
||||||
"10:00:00",
|
|
||||||
"11:00:00",
|
|
||||||
"12:00:00",
|
|
||||||
"13:00:00",
|
|
||||||
"14:00:00",
|
|
||||||
"15:00:00",
|
|
||||||
"16:00:00",
|
|
||||||
"17:00:00",
|
|
||||||
"18:00:00",
|
|
||||||
"19:00:00",
|
|
||||||
"20:00:00",
|
|
||||||
}
|
|
||||||
openRemoteStoreTimeList = []string{
|
|
||||||
"04:30:00",
|
|
||||||
"23:30:00",
|
|
||||||
}
|
|
||||||
updateActStatusTimeList = []string{
|
|
||||||
"00:01:00",
|
|
||||||
}
|
|
||||||
sendSecKillWarnList = []string{
|
|
||||||
"9:00:00",
|
|
||||||
}
|
|
||||||
autoPayForPopluarManList = []string{
|
|
||||||
"10:30:00",
|
|
||||||
}
|
|
||||||
|
|
||||||
autoSaleStoreSkuTimeList = []string{
|
|
||||||
cms.AutoSaleAtStr,
|
|
||||||
}
|
|
||||||
|
|
||||||
backUpStoreSkuBindList = []string{
|
|
||||||
"23:30:00",
|
|
||||||
}
|
|
||||||
|
|
||||||
exSyncList = []string{
|
|
||||||
"11:30:00",
|
|
||||||
}
|
|
||||||
|
|
||||||
importantTaskMap = &sync.Map{}
|
|
||||||
|
|
||||||
cancelPayTimeOutOrderList = localjx.GetHalfHoursList()
|
|
||||||
discountActJxList = localjx.GetDiscountActHoursList()
|
|
||||||
|
|
||||||
ebaiStorePageCookieExdTOKEN string
|
|
||||||
ebaiStorePageCookieWMUSS2 string
|
|
||||||
ebaiStorePageCookieWMSTOKEN2 string
|
|
||||||
ebaiStorePageCookieWMUSS string
|
|
||||||
ebaiStorePageCookieWMSTOKEN string
|
|
||||||
mtwmCookieStr string
|
|
||||||
mtpsStoreToken string
|
|
||||||
jd2StorePageCookie string
|
|
||||||
JdStorePageCookie string
|
|
||||||
yinbaoCookie string
|
|
||||||
feiePageCookie string
|
|
||||||
jdStorePageEarning string
|
|
||||||
jdsCookie string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetImportantTaskID(taskName string) string {
|
|
||||||
if value, ok := importantTaskMap.Load(taskName); ok {
|
|
||||||
return value.(string)
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func SaveImportantTaskID(taskName, taskID string) {
|
|
||||||
importantTaskMap.Store(taskName, taskID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsImportantTaskRunning(taskName string) bool {
|
|
||||||
taskID := GetImportantTaskID(taskName)
|
|
||||||
if taskID == "" {
|
|
||||||
return false
|
|
||||||
} else if taskID == SpecialTaskID {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return tasksch.IsTaskRunning(taskID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Init() {
|
func Init() {
|
||||||
if globals.IsProductEnv() {
|
if globals.IsProductEnv() {
|
||||||
ScheduleTimerFunc("doDailyWork", doDailyWork, dailyWorkTimeList)
|
ScheduleTimerFunc("doDailyWork", doDailyWork, dailyWorkTimeList)
|
||||||
|
|
||||||
ScheduleTimerFunc("doDailyWork2", doDailyWork2, dailyWorkTimeList2)
|
|
||||||
|
|
||||||
// ScheduleTimerFuncByInterval(func() {
|
|
||||||
// orderman.SaveJdsOrders(jxcontext.AdminCtx, time.Now().Add(-20*time.Minute), time.Now())
|
|
||||||
// }, 10*time.Second, 10*time.Minute)
|
|
||||||
|
|
||||||
//京东的订单信息解密密钥获取
|
|
||||||
ScheduleTimerFuncByInterval(func() {
|
|
||||||
jdshop.InitKey()
|
|
||||||
}, 10*time.Second, 8*time.Hour)
|
|
||||||
|
|
||||||
ScheduleTimerFuncByInterval(func() {
|
|
||||||
RefreshRealMobile(jxcontext.AdminCtx, model.VendorIDEBAI, time.Now().Add(-24*time.Hour), utils.DefaultTimeValue, false, true)
|
|
||||||
}, 5*time.Second, 1*time.Hour)
|
|
||||||
|
|
||||||
ScheduleTimerFuncByInterval(func() {
|
|
||||||
defsch.FixedScheduler.ConfirmSelfTakeOrders(jxcontext.AdminCtx, []int{model.VendorIDJD}, time.Now().Add(-48*time.Hour), time.Now().Add(-30*time.Minute), true, true)
|
|
||||||
}, 5*time.Second, 10*time.Minute)
|
|
||||||
|
|
||||||
ScheduleTimerFunc("auto enable remote store", func() {
|
|
||||||
cms.EnableHaveRestStores(jxcontext.AdminCtx, false, true)
|
|
||||||
cms.OpenRemoteStoreByJxStatus(jxcontext.AdminCtx, nil, nil, false, false, true)
|
|
||||||
}, openRemoteStoreTimeList)
|
|
||||||
|
|
||||||
ScheduleTimerFunc("SaveAndSendAlarmVendorSnapshot", func() {
|
|
||||||
cms.SaveAndSendAlarmVendorSnapshot(jxcontext.AdminCtx, nil, nil, false)
|
|
||||||
}, cms.WatchVendorStoreTimeList)
|
|
||||||
|
|
||||||
ScheduleTimerFunc("RefreshPageActs", func() {
|
|
||||||
act.RefreshPageActs(jxcontext.AdminCtx, []int{model.VendorIDEBAI}, time.Now().Add(-30*24*time.Hour), false)
|
|
||||||
}, refreshPageActTimeList)
|
|
||||||
ScheduleTimerFunc("UpdateActStatusByTime", func() {
|
|
||||||
dao.UpdateActStatusByTime(dao.GetDB(), time.Now())
|
|
||||||
}, updateActStatusTimeList)
|
|
||||||
ScheduleScoreStore()
|
|
||||||
ScheduleCheckStoreAlert()
|
|
||||||
ScheduleTimerFunc("ChangeStoreSkuSaleStatus", func() {
|
|
||||||
cms.CurVendorSync.ChangeStoreSkuSaleStatus(jxcontext.AdminCtx, 0, true, true)
|
|
||||||
}, ChangeStoreSkuSaleStatusList)
|
|
||||||
ScheduleTimerFunc("BeginSavePriceRefer", func() {
|
|
||||||
report.BeginSavePriceRefer(jxcontext.AdminCtx, nil, nil, true, true)
|
|
||||||
}, priceReferTimeList)
|
|
||||||
ScheduleTimerFunc("CreateStorePriceScore", func() {
|
|
||||||
cms.CreateStorePriceScore(jxcontext.AdminCtx)
|
|
||||||
}, createStorePriceTimeList)
|
|
||||||
ScheduleTimerFunc("AutoFocusStoreSkusForTopSkus", func() {
|
|
||||||
cms.AutoFocusStoreSkusForTopSkus(jxcontext.AdminCtx, true, true)
|
|
||||||
}, createStorePriceTimeList)
|
|
||||||
ScheduleTimerFunc("GetCheckVendorCookie", func() {
|
|
||||||
event.GetCheckVendorCookie(jxcontext.AdminCtx, []int{model.VendorIDEBAI, model.VendorIDJD, model.VendorIDMTWM, model.VendorIDMTPS, model.VendorIDJDShop}, true)
|
|
||||||
}, checkCookieList)
|
|
||||||
ScheduleTimerFunc("SendSeckillSkusCountMsg", func() {
|
|
||||||
cms.SendSeckillSkusCountMsg(jxcontext.AdminCtx, []int{model.VendorIDEBAI, model.VendorIDJD, model.VendorIDMTWM}, false, true)
|
|
||||||
}, sendSecKillWarnList)
|
|
||||||
ScheduleTimerFunc("每日报警心跳", func() {
|
|
||||||
globals.SugarLogger.Warnf("每日报警心跳,这不是报警。启动时间:%s", cms.GetServiceInfo(jxcontext.AdminCtx)["startupTime"])
|
|
||||||
}, dailyHeartbeat)
|
|
||||||
ScheduleTimerFunc("AutoPayForPopluarMan", func() {
|
|
||||||
localjx.AutoPayForPopluarMan(jxcontext.AdminCtx)
|
|
||||||
}, autoPayForPopluarManList)
|
|
||||||
ScheduleTimerFunc("CancelPayTimeOutOrder", func() {
|
|
||||||
localjx.CancelPayTimeOutOrder(jxcontext.AdminCtx)
|
|
||||||
}, cancelPayTimeOutOrderList)
|
|
||||||
ScheduleTimerFunc("BackUpStoreSkuBind", func() {
|
|
||||||
cms.BackUpStoreSkuBind(jxcontext.AdminCtx, true, true)
|
|
||||||
}, backUpStoreSkuBindList)
|
|
||||||
ScheduleTimerFunc("SendNoCatSkusToOperater", func() {
|
|
||||||
cms.SendNoCatSkusToOperater(jxcontext.AdminCtx)
|
|
||||||
}, autoPayForPopluarManList)
|
|
||||||
ScheduleTimerFunc("CleanStoreIsBoughtMatter", func() {
|
|
||||||
cms.CleanStoreIsBoughtMatter(jxcontext.AdminCtx)
|
|
||||||
}, priceReferTimeList)
|
|
||||||
ScheduleTimerFunc("CleanUserOrderSMSMark", func() {
|
|
||||||
cms.CleanUserOrderSMSMark(jxcontext.AdminCtx)
|
|
||||||
}, priceReferTimeList)
|
|
||||||
ScheduleTimerFunc("exSync", func() {
|
|
||||||
var (
|
|
||||||
db = dao.GetDB()
|
|
||||||
storeList []int
|
|
||||||
exSyncStoreIDList string
|
|
||||||
syncFlag = 0
|
|
||||||
)
|
|
||||||
syncFlag = model.SyncFlagPriceMask
|
|
||||||
if (time.Now().Unix()/24*3600)%10 == 0 {
|
|
||||||
syncFlag |= model.SyncFlagSaleMask
|
|
||||||
}
|
|
||||||
if configs, err := dao.QueryConfigs(dao.GetDB(), "exSyncStoreIDList", model.ConfigTypeSys, ""); err == nil {
|
|
||||||
exSyncStoreIDList = configs[0].Value
|
|
||||||
}
|
|
||||||
storeIDList := strings.Split(exSyncStoreIDList, ",")
|
|
||||||
for _, v := range storeIDList {
|
|
||||||
storeList = append(storeList, int(utils.Str2Int64(v)))
|
|
||||||
}
|
|
||||||
cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, partner.GetMultiStoreVendorIDs(), storeList, false, nil, []int{27379}, syncFlag, true, true)
|
|
||||||
}, exSyncList)
|
|
||||||
ScheduleTimerFunc("CreateOrderByPriceDefend", func() {
|
|
||||||
localjx.CreateOrderByPriceDefend(jxcontext.AdminCtx)
|
|
||||||
}, []string{
|
|
||||||
"22:00:00",
|
|
||||||
})
|
|
||||||
ScheduleTimerFunc("ChangeJxPriceByDiscountAct", func() {
|
|
||||||
act.ChangeJxPriceByDiscountAct(jxcontext.AdminCtx)
|
|
||||||
}, discountActJxList)
|
|
||||||
ScheduleTimerFunc("RefreshUserMemberStatus", func() {
|
|
||||||
cms.RefreshUserMemberStatus(jxcontext.AdminCtx)
|
|
||||||
}, updateActStatusTimeList)
|
|
||||||
}
|
}
|
||||||
ScheduleTimerFunc("AutoSaleStoreSku", func() {
|
|
||||||
cms.AutoSaleStoreSku(jxcontext.AdminCtx, nil, false)
|
|
||||||
}, autoSaleStoreSkuTimeList)
|
|
||||||
|
|
||||||
if beego.BConfig.RunMode == "jxgy" {
|
|
||||||
ScheduleTimerFunc("SyncMatterC4ToGy", func() {
|
|
||||||
cms.SyncMatterC4ToGy(jxcontext.AdminCtx, true, true)
|
|
||||||
}, dailyWorkTimeList)
|
|
||||||
}
|
|
||||||
if beego.BConfig.RunMode == "beta" {
|
|
||||||
ScheduleTimerFunc("CancelPayTimeOutOrder", func() {
|
|
||||||
localjx.CancelPayTimeOutOrder(jxcontext.AdminCtx)
|
|
||||||
}, cancelPayTimeOutOrderList)
|
|
||||||
ScheduleTimerFunc("GetAndStoreCitiesShops", func() {
|
|
||||||
netspider.GetAndStoreCitiesShops(jxcontext.AdminCtx, nil, nil, 0, 0, false, false)
|
|
||||||
}, []string{
|
|
||||||
"04:05:06",
|
|
||||||
})
|
|
||||||
//京东的订单信息解密密钥获取
|
|
||||||
ScheduleTimerFuncByInterval(func() {
|
|
||||||
jdshop.InitKey()
|
|
||||||
}, 10*time.Second, 8*time.Hour)
|
|
||||||
ScheduleTimerFunc("ChangeJxPriceByDiscountAct", func() {
|
|
||||||
act.ChangeJxPriceByDiscountAct(jxcontext.AdminCtx)
|
|
||||||
}, discountActJxList)
|
|
||||||
ScheduleTimerFunc("CreateOrderByPriceDefend", func() {
|
|
||||||
localjx.CreateOrderByPriceDefend(jxcontext.AdminCtx)
|
|
||||||
}, []string{
|
|
||||||
"22:00:00",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if configs, err := dao.QueryConfigs(dao.GetDB(), "ebaiStorePageCookieExdTOKEN", model.ConfigTypeCookie, ""); err == nil {
|
|
||||||
ebaiStorePageCookieExdTOKEN = configs[0].Value
|
|
||||||
}
|
|
||||||
if configs, err := dao.QueryConfigs(dao.GetDB(), "ebaiStorePageCookieWMUSS2", model.ConfigTypeCookie, ""); err == nil {
|
|
||||||
ebaiStorePageCookieWMUSS2 = configs[0].Value
|
|
||||||
}
|
|
||||||
if configs, err := dao.QueryConfigs(dao.GetDB(), "ebaiStorePageCookieWMSTOKEN2", model.ConfigTypeCookie, ""); err == nil {
|
|
||||||
ebaiStorePageCookieWMSTOKEN2 = configs[0].Value
|
|
||||||
}
|
|
||||||
if configs, err := dao.QueryConfigs(dao.GetDB(), "ebaiStorePageCookieWMUSS", model.ConfigTypeCookie, ""); err == nil {
|
|
||||||
ebaiStorePageCookieWMUSS = configs[0].Value
|
|
||||||
}
|
|
||||||
if configs, err := dao.QueryConfigs(dao.GetDB(), "ebaiStorePageCookieWMSTOKEN", model.ConfigTypeCookie, ""); err == nil {
|
|
||||||
ebaiStorePageCookieWMSTOKEN = configs[0].Value
|
|
||||||
}
|
|
||||||
if configs, err := dao.QueryConfigs(dao.GetDB(), "mtwmCookieStr", model.ConfigTypeCookie, ""); err == nil {
|
|
||||||
mtwmCookieStr = configs[0].Value
|
|
||||||
}
|
|
||||||
if configs, err := dao.QueryConfigs(dao.GetDB(), "mtpsStoreToken", model.ConfigTypeCookie, ""); err == nil {
|
|
||||||
mtpsStoreToken = configs[0].Value
|
|
||||||
}
|
|
||||||
if configs, err := dao.QueryConfigs(dao.GetDB(), "jdStorePageCookie", model.ConfigTypeCookie, ""); err == nil {
|
|
||||||
JdStorePageCookie = configs[0].Value
|
|
||||||
}
|
|
||||||
if configs, err := dao.QueryConfigs(dao.GetDB(), "jdStorePageEarning", model.ConfigTypeCookie, ""); err == nil {
|
|
||||||
jdStorePageEarning = configs[0].Value
|
|
||||||
}
|
|
||||||
if configs, err := dao.QueryConfigs(dao.GetDB(), "jd2StorePageCookie", model.ConfigTypeCookie, ""); err == nil {
|
|
||||||
jd2StorePageCookie = configs[0].Value
|
|
||||||
}
|
|
||||||
if configs, err := dao.QueryConfigs(dao.GetDB(), "feiePageCookie", model.ConfigTypeCookie, ""); err == nil {
|
|
||||||
feiePageCookie = configs[0].Value
|
|
||||||
}
|
|
||||||
if configs, err := dao.QueryConfigs(dao.GetDB(), "jdsCookie", model.ConfigTypeCookie, ""); err == nil {
|
|
||||||
jdsCookie = configs[0].Value
|
|
||||||
api.JdShopAPI.SetCookieWithStr(jdsCookie)
|
|
||||||
}
|
|
||||||
if configs, err := dao.QueryConfigs(dao.GetDB(), "yinbaoCookie", model.ConfigTypeCookie, ""); err == nil {
|
|
||||||
yinbaoCookie := configs[0].Value
|
|
||||||
api.YinBaoAPI.SetCookie(".POSPALAUTH30220", yinbaoCookie)
|
|
||||||
}
|
|
||||||
if globals.Jd2OrgCode != "" {
|
|
||||||
api.Jd2API.SetJdCookie(jd2StorePageCookie)
|
|
||||||
}
|
|
||||||
api.EbaiAPI.SetCookie("PASSPORT_DELIMONT_TOKEN", ebaiStorePageCookieExdTOKEN)
|
|
||||||
api.EbaiAPI.SetCookie("WMUSS", ebaiStorePageCookieWMUSS)
|
|
||||||
api.EbaiAPI.SetCookie("WMSTOKEN", ebaiStorePageCookieWMSTOKEN)
|
|
||||||
api.Ebai2API.SetCookie("PASSPORT_DELIMONT_TOKEN", ebaiStorePageCookieExdTOKEN)
|
|
||||||
api.Ebai2API.SetCookie("WMUSS", ebaiStorePageCookieWMUSS2)
|
|
||||||
api.Ebai2API.SetCookie("WMSTOKEN", ebaiStorePageCookieWMSTOKEN2)
|
|
||||||
api.MtwmAPI.SetCookieWithStr(mtwmCookieStr)
|
|
||||||
api.MtpsAPI.SetCookie("token", mtpsStoreToken)
|
|
||||||
api.JdAPI.SetJdCookie(JdStorePageCookie)
|
|
||||||
api.JdAPI.SetCookie("user", jdStorePageEarning)
|
|
||||||
api.JdPageAPI.SetCookie(jdapi.AccessStorePageCookieName, JdStorePageCookie)
|
|
||||||
api.JdPageAPI.SetCookie(jdapi.AccessStorePageCookieName2, JdStorePageCookie)
|
|
||||||
api.FeieAPI.SetCookieWithStr(feiePageCookie)
|
|
||||||
}
|
|
||||||
|
|
||||||
func syncStoreSku() {
|
|
||||||
syncFlag := 0
|
|
||||||
// syncFlag := model.SyncFlagPriceMask
|
|
||||||
// if (time.Now().Unix()/24*3600)%10 == 0 {
|
|
||||||
// syncFlag |= model.SyncFlagSaleMask
|
|
||||||
// }
|
|
||||||
task := tasksch.NewParallelTask("同步京西与平台数据", nil, jxcontext.AdminCtx,
|
|
||||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
|
||||||
step := batchItemList[0].(int)
|
|
||||||
errList := errlist.New()
|
|
||||||
db := dao.GetDB()
|
|
||||||
switch step {
|
|
||||||
case 0:
|
|
||||||
errList.AddErr(cms.DeleteSkuNameExPrefixOverdue(db))
|
|
||||||
errList.AddErr(cms.SetMultiStoreSkuSyncModifyStatus(db, partner.GetMultiStoreVendorIDs()))
|
|
||||||
|
|
||||||
_, err = cms.CurVendorSync.LoopMultiStoresVendors(jxcontext.AdminCtx, db, "同步多门店平台商品库", false, true,
|
|
||||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
|
||||||
vendorInfo := batchItemList[0].(*cms.MultiStoreVendorInfo)
|
|
||||||
_, err = cms.FullSyncVendorStuff(jxcontext.AdminCtx, task, vendorInfo.VendorID, vendorInfo.OrgCode, false, true)
|
|
||||||
return retVal, err
|
|
||||||
})
|
|
||||||
errList.AddErr(err)
|
|
||||||
|
|
||||||
_, err = cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, []int{0}, nil, false, nil, []int{27379}, syncFlag, true, true)
|
|
||||||
// _, err = cms.CurVendorSync.FullSyncStoresSkus(jxcontext.AdminCtx, db, partner.GetMultiStoreVendorIDs(), nil, false, []int{27379}, true, true)
|
|
||||||
errList.AddErr(err)
|
|
||||||
case 1:
|
|
||||||
//TODO 暂时不同步银豹(可能要从银豹到京西),2020-04-27
|
|
||||||
errList.AddErr(cms.SetSingleStoreSkuSyncModifyStatus(db, []int{1, 3}))
|
|
||||||
|
|
||||||
// errList.AddErr(cms.SetSingleStoreSkuSyncModifyStatus(db, partner.GetSingleStoreVendorIDs()))
|
|
||||||
// _, err = cms.CurVendorSync.AmendAndPruneStoreStuff(jxcontext.AdminCtx, []int{1, 3}, nil, false, true, cms.AmendPruneAll, false)
|
|
||||||
|
|
||||||
// _, err = cms.CurVendorSync.AmendAndPruneStoreStuff(jxcontext.AdminCtx, partner.GetSingleStoreVendorIDs(), nil, false, true, cms.AmendPruneAll, false)
|
|
||||||
errList.AddErr(err)
|
|
||||||
|
|
||||||
SaveImportantTaskID(TaskNameSyncStoreSku, SpecialTaskID)
|
|
||||||
taskID, err2 := cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, []int{1, 3, 5}, nil, false, nil, nil, syncFlag, true, true)
|
|
||||||
// taskID, err2 := cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, partner.GetSingleStoreVendorIDs(), nil, false, nil, nil, syncFlag, true, true)
|
|
||||||
|
|
||||||
errList.AddErr(err2)
|
|
||||||
SaveImportantTaskID(TaskNameSyncStoreSku, taskID)
|
|
||||||
}
|
|
||||||
err = errList.GetErrListAsOne()
|
|
||||||
return retVal, err
|
|
||||||
}, []int{0, 1})
|
|
||||||
tasksch.HandleTask(task, nil, true).Run()
|
|
||||||
}
|
|
||||||
|
|
||||||
func doDailyWork2() {
|
|
||||||
globals.SugarLogger.Debug("doDailyWork2")
|
|
||||||
|
|
||||||
//同步京东商城门店的商品
|
|
||||||
cms.CurVendorSync.SyncJdsStoresSkus(jxcontext.AdminCtx, nil, true, true)
|
|
||||||
//刷新京东商城的门店库存
|
|
||||||
cms.SyncJdsStoreStock(jxcontext.AdminCtx, true, true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func doDailyWork() {
|
func doDailyWork() {
|
||||||
globals.SugarLogger.Debug("doDailyWork")
|
globals.SugarLogger.Debug("doDailyWork")
|
||||||
|
|
||||||
//同步商品额外前缀和水印图(打标记)
|
|
||||||
cms.SyncSkuExperfixAndWatermark(jxcontext.AdminCtx)
|
|
||||||
|
|
||||||
dao.SetStoresMapSyncStatus(dao.GetDB(), nil, nil, model.SyncFlagStoreStatus)
|
|
||||||
cms.CurVendorSync.SyncStore2(jxcontext.AdminCtx, dao.GetDB(), nil, nil, true, true)
|
|
||||||
|
|
||||||
syncStoreSku()
|
|
||||||
InitEx()
|
|
||||||
cms.SyncStoresCourierInfo(jxcontext.AdminCtx, nil, false, true)
|
|
||||||
netprinter.RebindAllPrinters(jxcontext.AdminCtx, false, true)
|
|
||||||
|
|
||||||
// 每天补全前一天与当天的订单
|
|
||||||
curDate := utils.Time2Date(time.Now())
|
|
||||||
orderman.FixedOrderManager.AmendMissingOrders(jxcontext.AdminCtx, nil, 0, curDate.Add(-72*time.Hour), curDate, true, true)
|
|
||||||
//订单门店归属补漏
|
|
||||||
//fromDate, toDate都不传默认刷新当前天5天以前的订单,只传fromDate默认刷新fromDate到当天的订单
|
|
||||||
//只传toDate默认刷新toDate到5天以前的订单
|
|
||||||
orderman.RefreshOrdersWithoutJxStoreID(jxcontext.AdminCtx, "", "", true, true)
|
|
||||||
//刷新京东门店的等级
|
|
||||||
cms.RefreshJdLevel(jxcontext.AdminCtx)
|
|
||||||
//删除操作日志
|
|
||||||
// event.DeleteOperateEventAndDetail(jxcontext.AdminCtx, time.Now().AddDate(0, -3, 0))
|
|
||||||
//禁用没有绑定的门店
|
|
||||||
cms.DisabledStoreWithoutVendor(jxcontext.AdminCtx, true, true)
|
|
||||||
//刷新物料订单状态
|
|
||||||
localjx.RefreshAllMatterOrderStatus(jxcontext.AdminCtx)
|
|
||||||
//同步银豹到京西
|
|
||||||
// cms.CurVendorSync.SyncStoreSkusFromYb(jxcontext.AdminCtx, nil, true, true)
|
|
||||||
//刷新京东商城订单结算价
|
|
||||||
orderman.RefreshJdShopOrdersEarningPrice(jxcontext.AdminCtx, time.Now().AddDate(0, 0, -2).Format("20060102"), time.Now().Format("20060102"))
|
|
||||||
//同步上架京东商城待售商品
|
|
||||||
cms.RefreshJdsSkusStatus(jxcontext.AdminCtx)
|
|
||||||
//同步美团配送与否状态及美团门店是否存在
|
|
||||||
cms.SetMTPSStatus(jxcontext.AdminCtx, 0, 0)
|
|
||||||
//售后单如果超过12小时没有审核,就自动通过
|
|
||||||
RefreshAfsOrderStatusAccess(jxcontext.AdminCtx)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RefreshAfsOrderStatusAccess(ctx *jxcontext.Context) {
|
|
||||||
var (
|
|
||||||
offset = 0
|
|
||||||
pageSize = 9999
|
|
||||||
db = dao.GetDB()
|
|
||||||
)
|
|
||||||
afsOrderList, _, err := dao.GetAfsOrdersByPage(db, "", "", "", time.Now().AddDate(0, 0, -7), time.Now(), offset, pageSize)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, v := range afsOrderList {
|
|
||||||
if v.Status == model.AfsOrderStatusWait4Approve && time.Now().Sub(v.AfsCreatedAt).Hours() > 12 {
|
|
||||||
defsch.FixedScheduler.AgreeOrRefuseRefund(ctx, v.AfsOrderID, v.VendorID, model.AfsTypePartRefund, "超时系统同意")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func RefreshRealMobile(ctx *jxcontext.Context, vendorID int, fromTime, toTime time.Time, isAsync, isContinueWhenError bool) (hint string, err error) {
|
|
||||||
globals.SugarLogger.Debug("RefreshRealMobile")
|
|
||||||
|
|
||||||
handler := partner.GetPurchasePlatformFromVendorID(vendorID)
|
|
||||||
if handler == nil {
|
|
||||||
return "", fmt.Errorf("不合法的vendorID:%d", vendorID)
|
|
||||||
}
|
|
||||||
sql := `
|
|
||||||
SELECT *
|
|
||||||
FROM goods_order
|
|
||||||
WHERE vendor_id = ? AND consignee_mobile2 = ''
|
|
||||||
`
|
|
||||||
sqlParams := []interface{}{
|
|
||||||
vendorID,
|
|
||||||
}
|
|
||||||
if !utils.IsTimeZero(fromTime) {
|
|
||||||
sql += " AND order_created_at >= ?"
|
|
||||||
sqlParams = append(sqlParams, fromTime)
|
|
||||||
}
|
|
||||||
if !utils.IsTimeZero(toTime) {
|
|
||||||
sql += " AND order_created_at <= ?"
|
|
||||||
sqlParams = append(sqlParams, toTime)
|
|
||||||
}
|
|
||||||
var orderList []*model.GoodsOrder
|
|
||||||
db := dao.GetDB()
|
|
||||||
if err = dao.GetRows(db, &orderList, sql, sqlParams...); err == nil && len(orderList) > 0 {
|
|
||||||
task := tasksch.NewParallelTask("misc RefreshRealMobile", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
|
|
||||||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
|
||||||
order := batchItemList[0].(*model.GoodsOrder)
|
|
||||||
mobile, err2 := handler.GetOrderRealMobile(ctx, order)
|
|
||||||
if err = err2; err == nil {
|
|
||||||
mobile = jxutils.FormalizeMobile(mobile)
|
|
||||||
if jxutils.IsStringLikeMobile(mobile) && strings.Index(order.ConsigneeMobile, mobile) == -1 {
|
|
||||||
order.ConsigneeMobile2 = mobile
|
|
||||||
_, err = dao.UpdateEntity(db, order, "ConsigneeMobile2")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
globals.SugarLogger.Infof("RefreshRealMobile orderID:%s failed with error:%v", order.VendorOrderID, err)
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}, orderList)
|
|
||||||
tasksch.HandleTask(task, nil, true).Run()
|
|
||||||
hint = task.ID
|
|
||||||
if !isAsync {
|
|
||||||
_, err = task.GetResult(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hint, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 按时间序列循环
|
// 按时间序列循环
|
||||||
|
|||||||
@@ -1,396 +0,0 @@
|
|||||||
package misc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"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/tasksch"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/model"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/partner"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/partner/putils"
|
|
||||||
"git.rosy.net.cn/jx-callback/globals"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
enableScheduleRefreshStore = true
|
|
||||||
taskParallelCount = 4
|
|
||||||
specialSkuNameKeyWord = "温馨提示"
|
|
||||||
startOpStoreStockNumber = 0
|
|
||||||
endOpStoreStockNumber = model.MaxStoreSkuStockQty
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
isDaemonRunning = false
|
|
||||||
vendorList = map[int]bool{
|
|
||||||
model.VendorIDMTWM: true,
|
|
||||||
model.VendorIDEBAI: true,
|
|
||||||
}
|
|
||||||
storeListQueueData = map[bool]*StoreListQueueData{
|
|
||||||
true: &StoreListQueueData{},
|
|
||||||
false: &StoreListQueueData{},
|
|
||||||
}
|
|
||||||
// vendorStoreRefreshTimeList = map[int][]string {
|
|
||||||
// model.VendorIDMTWM: []string {
|
|
||||||
// //start and end time for JXGY
|
|
||||||
// "22:00:00",
|
|
||||||
// "00:00:00",
|
|
||||||
// //start and end time for JXCS
|
|
||||||
// "22:10:00",
|
|
||||||
// "00:10:00",
|
|
||||||
// },
|
|
||||||
// model.VendorIDEBAI: []string {
|
|
||||||
// "22:20:00",
|
|
||||||
// "06:00:00",
|
|
||||||
|
|
||||||
// "22:30:00",
|
|
||||||
// "06:10:00",
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
|
|
||||||
// vendorStartEndStoreTime = map[int][]int16 {
|
|
||||||
// model.VendorIDMTWM: []int16 {
|
|
||||||
// int16(2200),//start time
|
|
||||||
// int16(2355),//end time
|
|
||||||
// },
|
|
||||||
// model.VendorIDEBAI: []int16 {
|
|
||||||
// int16(5),
|
|
||||||
// int16(2355),
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
)
|
|
||||||
|
|
||||||
type StoreListQueueData struct {
|
|
||||||
waitQueue []*cms.StoreExt
|
|
||||||
processQueue []*cms.StoreExt
|
|
||||||
locker sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StoreListQueueData) GetProcessQueue() (outQueue []*cms.StoreExt) {
|
|
||||||
s.locker.RLock()
|
|
||||||
defer s.locker.RUnlock()
|
|
||||||
outQueue = append(outQueue, s.processQueue...)
|
|
||||||
return outQueue
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StoreListQueueData) InsertToWaitQueue(storeInfo *cms.StoreExt) {
|
|
||||||
s.locker.Lock()
|
|
||||||
defer s.locker.Unlock()
|
|
||||||
s.waitQueue = append(s.waitQueue, storeInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StoreListQueueData) ClearProcessQueue() {
|
|
||||||
s.locker.Lock()
|
|
||||||
defer s.locker.Unlock()
|
|
||||||
if len(s.processQueue) > 0 {
|
|
||||||
s.processQueue = []*cms.StoreExt{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StoreListQueueData) TransferWaitQueueToProcessQueue() {
|
|
||||||
s.locker.Lock()
|
|
||||||
defer s.locker.Unlock()
|
|
||||||
if len(s.processQueue) == 0 && len(s.waitQueue) > 0 {
|
|
||||||
for _, value := range s.waitQueue {
|
|
||||||
s.processQueue = append(s.processQueue, value)
|
|
||||||
}
|
|
||||||
s.waitQueue = []*cms.StoreExt{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddOrDelExtraStoreOptime(ctx *jxcontext.Context, vendorID int, vendorOrgCode string, storeID int, vendorStoreID string, storeInfo *model.Store, startOpStoreTime, endOpStoreTime int16, needAddTime bool) bool {
|
|
||||||
opTimeList := storeInfo.GetOpTimeList()
|
|
||||||
if needAddTime {
|
|
||||||
opTimeList = []int16{startOpStoreTime, endOpStoreTime}
|
|
||||||
}
|
|
||||||
handler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.IStoreHandler)
|
|
||||||
return handler.UpdateStoreOpTime(ctx, vendorOrgCode, storeID, vendorStoreID, opTimeList) == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetStockValue(isStart bool) int {
|
|
||||||
if isStart {
|
|
||||||
return startOpStoreStockNumber
|
|
||||||
} else {
|
|
||||||
return endOpStoreStockNumber
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// func GetOpStoreTime(vendorID int) (startTime, endTime int16) {
|
|
||||||
// startTime = vendorStartEndStoreTime[vendorID][0]
|
|
||||||
// endTime = vendorStartEndStoreTime[vendorID][1]
|
|
||||||
// return startTime, endTime
|
|
||||||
// }
|
|
||||||
|
|
||||||
func IsSpecialSku(name string) bool {
|
|
||||||
return strings.Contains(name, specialSkuNameKeyWord)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetSkuStock(isStart bool, storeSkuNameList []*partner.SkuNameInfo) {
|
|
||||||
for _, skuNameInfo := range storeSkuNameList {
|
|
||||||
for _, skuInfo := range skuNameInfo.SkuList {
|
|
||||||
if IsSpecialSku(skuNameInfo.Name) || IsSpecialSku(skuInfo.SkuName) {
|
|
||||||
skuInfo.Stock = endOpStoreStockNumber
|
|
||||||
} else {
|
|
||||||
skuInfo.Stock = GetStockValue(isStart)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetSpecialSkuStatus(ctx *jxcontext.Context, vendorID int, vendorOrgCode string, storeID int, vendorStoreID string, storeSkuNameList []*partner.SkuNameInfo) {
|
|
||||||
singleStoreHandler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.ISingleStoreStoreSkuHandler)
|
|
||||||
for _, skuNameInfo := range storeSkuNameList {
|
|
||||||
for _, skuInfo := range skuNameInfo.SkuList {
|
|
||||||
if IsSpecialSku(skuNameInfo.Name) || IsSpecialSku(skuInfo.SkuName) {
|
|
||||||
storeSkuList := []*partner.StoreSkuInfo{&skuInfo.StoreSkuInfo}
|
|
||||||
singleStoreHandler.UpdateStoreSkusStatus(ctx, vendorOrgCode, storeID, vendorStoreID, storeSkuList, model.SkuStatusNormal)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetFilterStoreSkuList(storeSkuList []*partner.StoreSkuInfo) (storeSkuListOut []*partner.StoreSkuInfo) {
|
|
||||||
for _, value := range storeSkuList {
|
|
||||||
if value.SkuID != 0 {
|
|
||||||
storeSkuListOut = append(storeSkuListOut, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return storeSkuListOut
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetStoreList(ctx *jxcontext.Context) (storeList []*cms.StoreExt, err error) {
|
|
||||||
storeInfo, err := cms.GetStores(ctx, "", map[string]interface{}{}, 0, -1, utils.DefaultTimeValue, utils.DefaultTimeValue, 0, 0)
|
|
||||||
storeList = storeInfo.Stores
|
|
||||||
return storeList, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetFilterStoreList(storeList []*cms.StoreExt, vendorMap, storeIDMap map[int]bool) (outStoreList []*cms.StoreExt) {
|
|
||||||
for _, storeInfo := range storeList {
|
|
||||||
storeID := storeInfo.ID
|
|
||||||
//filter for storeID
|
|
||||||
if len(storeIDMap) > 0 {
|
|
||||||
if _, ok := storeIDMap[storeID]; !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, vendorStoreInfo := range storeInfo.StoreMaps {
|
|
||||||
vendorID := vendorStoreInfo.VendorID
|
|
||||||
//filter for vendorID
|
|
||||||
if len(vendorMap) > 0 {
|
|
||||||
if _, ok := vendorMap[vendorID]; !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if _, ok := vendorList[vendorID]; !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
temp := *storeInfo
|
|
||||||
newStoreInfo := &temp
|
|
||||||
newStoreInfo.StoreMaps = []*model.StoreMap{vendorStoreInfo}
|
|
||||||
outStoreList = append(outStoreList, newStoreInfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return outStoreList
|
|
||||||
}
|
|
||||||
|
|
||||||
func StartOrEndOpStore(ctx *jxcontext.Context, isStart bool, vendorIDList []int, storeIDList []int, startTime, endTime int16, isAsync, isContinueWhenError bool) (retVal interface{}, err error) {
|
|
||||||
storeList, err := GetStoreList(ctx)
|
|
||||||
vendorMap := make(map[int]bool)
|
|
||||||
for _, vendorID := range vendorIDList {
|
|
||||||
vendorMap[vendorID] = true
|
|
||||||
}
|
|
||||||
storeIDMap := make(map[int]bool)
|
|
||||||
for _, storeID := range storeIDList {
|
|
||||||
storeIDMap[storeID] = true
|
|
||||||
}
|
|
||||||
storeList = GetFilterStoreList(storeList, vendorMap, storeIDMap)
|
|
||||||
return StartOrEndOpStoreEx(ctx, isStart, startTime, endTime, isAsync, isContinueWhenError, storeList)
|
|
||||||
}
|
|
||||||
|
|
||||||
func StartOrEndOpStoreEx(ctx *jxcontext.Context, isStart bool, startTime, endTime int16, isAsync, isContinueWhenError bool, storeList []*cms.StoreExt) (retVal interface{}, err error) {
|
|
||||||
startProcessTime := time.Now().Unix()
|
|
||||||
baseapi.SugarLogger.Debugf("StartOrEndOpStore start time: %v", time.Now())
|
|
||||||
|
|
||||||
if len(storeList) > 0 {
|
|
||||||
taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
|
||||||
storeListValue := batchItemList[0].(*cms.StoreExt)
|
|
||||||
storeID := storeListValue.ID
|
|
||||||
for _, vendorListValue := range storeListValue.StoreMaps {
|
|
||||||
vendorID := vendorListValue.VendorID
|
|
||||||
startOpStoreTime := vendorListValue.FakeOpenStart
|
|
||||||
endOpStoreTime := vendorListValue.FakeOpenStop
|
|
||||||
//startOpStoreTime, endOpStoreTime := GetOpStoreTime(vendorID)
|
|
||||||
if startTime != 0 && endTime != 0 {
|
|
||||||
startOpStoreTime = startTime
|
|
||||||
endOpStoreTime = endTime
|
|
||||||
baseapi.SugarLogger.Debugf("StartOrEndOpStore SetStoreOptime:%d do:%d", startTime, endTime)
|
|
||||||
}
|
|
||||||
if isStart && (startOpStoreTime == 0 || endOpStoreTime == 0) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
vendorStoreID := vendorListValue.VendorStoreID
|
|
||||||
baseapi.SugarLogger.Debugf("StartOrEndOpStore storeID:%d vendorID:%d vendorStoreID:%s", storeID, vendorID, vendorStoreID)
|
|
||||||
singleStoreHandler := partner.GetPurchasePlatformFromVendorID(vendorID).(partner.ISingleStoreStoreSkuHandler)
|
|
||||||
storeSkuNameList, err := singleStoreHandler.GetStoreSkusFullInfo(ctx, task, storeID, vendorStoreID, nil)
|
|
||||||
if err != nil {
|
|
||||||
baseapi.SugarLogger.Errorf("StartOrEndOpStore GetStoreSkusFullInfo error:%v storeID:%d vendorID:%d vendorStoreID:%s", err, storeID, vendorID, vendorStoreID)
|
|
||||||
} else {
|
|
||||||
SetSkuStock(isStart, storeSkuNameList)
|
|
||||||
SetSpecialSkuStatus(ctx, vendorID, vendorListValue.VendorOrgCode, storeID, vendorStoreID, storeSkuNameList)
|
|
||||||
storeSkuList := putils.StoreSkuFullList2Bare(storeSkuNameList)
|
|
||||||
if vendorID == model.VendorIDMTWM {
|
|
||||||
storeSkuList = GetFilterStoreSkuList(storeSkuList)
|
|
||||||
}
|
|
||||||
if len(storeSkuList) > 0 {
|
|
||||||
if !isStart {
|
|
||||||
AddOrDelExtraStoreOptime(ctx, vendorID, vendorListValue.VendorOrgCode, storeID, vendorStoreID, &storeListValue.Store, startOpStoreTime, endOpStoreTime, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = putils.FreeBatchStoreSkuInfo("更新门店商品库存", func(task tasksch.ITask, batchedStoreSkuList []*partner.StoreSkuInfo) (result interface{}, successCount int, err error) {
|
|
||||||
_, err = singleStoreHandler.UpdateStoreSkusStock(ctx, vendorListValue.VendorOrgCode, storeID, vendorStoreID, batchedStoreSkuList)
|
|
||||||
return nil, 0, err
|
|
||||||
}, ctx, task, storeSkuList, singleStoreHandler.GetStoreSkusBatchSize(partner.FuncUpdateStoreSkusStock), true)
|
|
||||||
|
|
||||||
if isStart {
|
|
||||||
AddOrDelExtraStoreOptime(ctx, vendorID, vendorListValue.VendorOrgCode, storeID, vendorStoreID, &storeListValue.Store, startOpStoreTime, endOpStoreTime, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return retVal, err
|
|
||||||
}
|
|
||||||
taskName := ""
|
|
||||||
if isStart {
|
|
||||||
taskName = "开启平台商店的额外营业时间"
|
|
||||||
} else {
|
|
||||||
taskName = "结束平台商店的额外营业时间"
|
|
||||||
}
|
|
||||||
task := tasksch.NewParallelTask(taskName, tasksch.NewParallelConfig().SetParallelCount(taskParallelCount), ctx, taskFunc, storeList)
|
|
||||||
tasksch.HandleTask(task, nil, true).Run()
|
|
||||||
if isAsync {
|
|
||||||
retVal = task.ID
|
|
||||||
} else {
|
|
||||||
_, err = task.GetResult(0)
|
|
||||||
if err != nil {
|
|
||||||
baseapi.SugarLogger.Debugf("StartOrEndOpStore tasksch error:%v", err)
|
|
||||||
}
|
|
||||||
retVal = "1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
endProcessTime := time.Now().Unix()
|
|
||||||
diff := endProcessTime - startProcessTime
|
|
||||||
baseapi.SugarLogger.Debugf("StartOrEndOpStore end time: %v", time.Now())
|
|
||||||
baseapi.SugarLogger.Debugf("StartOrEndOpStore cost time: %d sec", diff)
|
|
||||||
|
|
||||||
return retVal, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsJXCS() bool {
|
|
||||||
return globals.IsMainProductEnv()
|
|
||||||
}
|
|
||||||
|
|
||||||
// func GetVendorStoreRefreshTime(vendorID int) (startTimeList, stopTimeList []string) {
|
|
||||||
// isJXCS := globals.IsMainProductEnv()
|
|
||||||
// refreshTimeList := vendorStoreRefreshTimeList[vendorID]
|
|
||||||
// if isJXCS {
|
|
||||||
// startTimeList = []string{refreshTimeList[2]}
|
|
||||||
// stopTimeList = []string{refreshTimeList[3]}
|
|
||||||
// } else {
|
|
||||||
// startTimeList = []string{refreshTimeList[0]}
|
|
||||||
// stopTimeList = []string{refreshTimeList[1]}
|
|
||||||
// }
|
|
||||||
// return startTimeList, stopTimeList
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func RefreshStore(vendorID int) {
|
|
||||||
// ctx := jxcontext.AdminCtx
|
|
||||||
// startTimeList, stopTimeList := GetVendorStoreRefreshTime(vendorID)
|
|
||||||
// vendorIDList := []int{vendorID}
|
|
||||||
// storeIDList := []int{}
|
|
||||||
// ScheduleTimerFunc("StartOpStore", func() {
|
|
||||||
// if !IsImportantTaskRunning(TaskNameSyncStoreSku) {
|
|
||||||
// StartOrEndOpStore(ctx, true, vendorIDList, storeIDList, 0, 0, false, true)
|
|
||||||
// }
|
|
||||||
// }, startTimeList)
|
|
||||||
// ScheduleTimerFunc("EndOpStore", func() {
|
|
||||||
// if !IsImportantTaskRunning(TaskNameSyncStoreSku) {
|
|
||||||
// StartOrEndOpStore(ctx, false, vendorIDList, storeIDList, 0, 0, false, true)
|
|
||||||
// }
|
|
||||||
// }, stopTimeList)
|
|
||||||
// }
|
|
||||||
|
|
||||||
func InitEx() {
|
|
||||||
// for index, value := range vendorList {
|
|
||||||
// if value {
|
|
||||||
// RefreshStore(index)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
if enableScheduleRefreshStore && IsJXCS() {
|
|
||||||
ctx := jxcontext.AdminCtx
|
|
||||||
storeList, err := GetStoreList(ctx)
|
|
||||||
storeList = GetFilterStoreList(storeList, map[int]bool{}, map[int]bool{})
|
|
||||||
if err == nil {
|
|
||||||
for _, storeInfo := range storeList {
|
|
||||||
for _, vendorStoreInfo := range storeInfo.StoreMaps {
|
|
||||||
startOpStoreTime := vendorStoreInfo.FakeOpenStart
|
|
||||||
endOpStoreTime := vendorStoreInfo.FakeOpenStop
|
|
||||||
if startOpStoreTime == 0 || endOpStoreTime == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
startTime := jxutils.OperationTime2StrWithSecond(startOpStoreTime)
|
|
||||||
ScheduleTimerFuncOnce("StartOpStore", func(param interface{}) {
|
|
||||||
if !IsImportantTaskRunning(TaskNameSyncStoreSku) {
|
|
||||||
storeInfo := param.(*cms.StoreExt)
|
|
||||||
storeListQueueData[true].InsertToWaitQueue(storeInfo)
|
|
||||||
}
|
|
||||||
}, startTime, storeInfo)
|
|
||||||
|
|
||||||
stopTime := jxutils.OperationTime2StrWithSecond(endOpStoreTime)
|
|
||||||
ScheduleTimerFuncOnce("EndOpStore", func(param interface{}) {
|
|
||||||
storeInfo := param.(*cms.StoreExt)
|
|
||||||
storeListQueueData[false].InsertToWaitQueue(storeInfo)
|
|
||||||
}, stopTime, storeInfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !isDaemonRunning {
|
|
||||||
isDaemonRunning = true
|
|
||||||
taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
|
|
||||||
switch step {
|
|
||||||
case 0:
|
|
||||||
periodlyFunc := func() {
|
|
||||||
for isStart, value := range storeListQueueData {
|
|
||||||
storeList := value.GetProcessQueue()
|
|
||||||
if len(storeList) > 0 {
|
|
||||||
StartOrEndOpStoreEx(ctx, isStart, 0, 0, false, true, storeList)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, value := range storeListQueueData {
|
|
||||||
value.ClearProcessQueue()
|
|
||||||
value.TransferWaitQueueToProcessQueue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PeriodlyCall(60*time.Second, periodlyFunc)
|
|
||||||
}
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
taskSeq := tasksch.NewSeqTask("启动监听-定时刷新平台商店的额外营业时间", ctx, taskSeqFunc, 1)
|
|
||||||
tasksch.HandleTask(taskSeq, nil, true).Run()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func PeriodlyCall(d time.Duration, handler func()) {
|
|
||||||
ticker := time.NewTicker(d)
|
|
||||||
for _ = range ticker.C {
|
|
||||||
handler()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package misc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestStartOrEndOpStore(t *testing.T) {
|
|
||||||
StartOrEndOpStore(jxcontext.AdminCtx, true, nil, nil, 0, 0, false, true)
|
|
||||||
}
|
|
||||||
@@ -1,509 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
@@ -1,882 +0,0 @@
|
|||||||
package misc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
"sync"
|
|
||||||
"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/tasksch"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/model"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
|
||||||
"git.rosy.net.cn/jx-callback/globals"
|
|
||||||
"git.rosy.net.cn/jx-callback/globals/refutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
EnableScheduleScoreStore = true
|
|
||||||
ParallelCount = 1
|
|
||||||
|
|
||||||
GoldMedalScore = 90
|
|
||||||
SilverMedalScore = 80
|
|
||||||
BronzeMedalScore = 70
|
|
||||||
GoldMedalLevel = 1
|
|
||||||
SilverMedalLevel = 2
|
|
||||||
BronzeMedalLevel = 3
|
|
||||||
|
|
||||||
ItemTotalScore = 10
|
|
||||||
|
|
||||||
StoreOpenTimeNormalTime = 12.0 //小时
|
|
||||||
SaleSkuNormalCount = 1000 //数量
|
|
||||||
SaleSkuScorePerUnit = float64(ItemTotalScore) / SaleSkuNormalCount //分数
|
|
||||||
PromotionSkuNormalCount = 20 //数量
|
|
||||||
AveragePickupTimeNormalTime = 10.0 //分钟
|
|
||||||
BadCommentOrderNormalRatio = 0.2 //百分比
|
|
||||||
UnfinishOrderNormalRatio = 1.0 //百分比
|
|
||||||
AbsentGoodsOrderNormalRatio = 1.0 //百分比
|
|
||||||
StoreRangeGoodRadius = 2.0 //千米
|
|
||||||
StoreRangeBadRadius = 1.0 //千米
|
|
||||||
SaleSkuPriceRatio = 90 //千米
|
|
||||||
SaleSkuCheckRange = 5.0 //千米
|
|
||||||
|
|
||||||
WeekNum = 5 //得到门店近期周的数量
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
scoreStoreTimeList = []string{
|
|
||||||
"23:00:00",
|
|
||||||
}
|
|
||||||
scoreStoreCheckTimeEnd = "23:30:00"
|
|
||||||
fullVendorList = map[int]bool{
|
|
||||||
model.VendorIDJD: true,
|
|
||||||
model.VendorIDMTWM: true,
|
|
||||||
model.VendorIDEBAI: true,
|
|
||||||
}
|
|
||||||
storeScoreFieldName = []string{
|
|
||||||
model.FieldStoreOpenTime,
|
|
||||||
model.FieldSaleSkuCount,
|
|
||||||
model.FieldAveragePickupTime,
|
|
||||||
model.FieldBadCommentOrder,
|
|
||||||
model.FieldUnfinishOrder,
|
|
||||||
model.FieldAbsentGoodsOrder,
|
|
||||||
model.FieldPromotionSku,
|
|
||||||
model.FieldFullVendor,
|
|
||||||
model.FieldStoreRange,
|
|
||||||
model.FieldSaleSkuPrice,
|
|
||||||
}
|
|
||||||
|
|
||||||
storeScoreDataWrapper StoreScoreDataWrapper
|
|
||||||
allStoreSkusWrapper AllStoreSkusWrapper
|
|
||||||
scoreDate time.Time
|
|
||||||
isScoring bool
|
|
||||||
)
|
|
||||||
|
|
||||||
type AllStoreSkusWrapper struct {
|
|
||||||
allStoreSkus map[int]map[int]int
|
|
||||||
locker sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *AllStoreSkusWrapper) InitData() {
|
|
||||||
a.allStoreSkus = make(map[int]map[int]int)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *AllStoreSkusWrapper) ClearData() {
|
|
||||||
a.allStoreSkus = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *AllStoreSkusWrapper) SetData(storeID int, skuMapData map[int]int) {
|
|
||||||
a.locker.Lock()
|
|
||||||
defer a.locker.Unlock()
|
|
||||||
a.allStoreSkus[storeID] = skuMapData
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *AllStoreSkusWrapper) GetData(storeID int) map[int]int {
|
|
||||||
a.locker.RLock()
|
|
||||||
defer a.locker.RUnlock()
|
|
||||||
return a.allStoreSkus[storeID]
|
|
||||||
}
|
|
||||||
|
|
||||||
type StoreScoreDataWrapper struct {
|
|
||||||
storeScoreData map[int]*model.StoreScore
|
|
||||||
dailyBadCommentOrderCount map[int]int
|
|
||||||
dailyUnFinishOrderCount map[int]int
|
|
||||||
dailyFinishOrderCount map[int]int
|
|
||||||
dailyAbsentGoodsOrderCount map[int]int
|
|
||||||
locker sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StoreScoreDataWrapper) InitData() {
|
|
||||||
s.storeScoreData = make(map[int]*model.StoreScore)
|
|
||||||
s.dailyBadCommentOrderCount = make(map[int]int)
|
|
||||||
s.dailyUnFinishOrderCount = make(map[int]int)
|
|
||||||
s.dailyFinishOrderCount = make(map[int]int)
|
|
||||||
s.dailyAbsentGoodsOrderCount = make(map[int]int)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StoreScoreDataWrapper) ClearData() {
|
|
||||||
s.storeScoreData = nil
|
|
||||||
s.dailyBadCommentOrderCount = nil
|
|
||||||
s.dailyUnFinishOrderCount = nil
|
|
||||||
s.dailyFinishOrderCount = nil
|
|
||||||
s.dailyAbsentGoodsOrderCount = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StoreScoreDataWrapper) SetData(storeID int, valueName string, value int) {
|
|
||||||
s.locker.Lock()
|
|
||||||
defer s.locker.Unlock()
|
|
||||||
data := s.storeScoreData[storeID]
|
|
||||||
if data == nil {
|
|
||||||
data = &model.StoreScore{}
|
|
||||||
data.StoreID = storeID
|
|
||||||
data.ScoreDate = scoreDate
|
|
||||||
s.storeScoreData[storeID] = data
|
|
||||||
}
|
|
||||||
valueInfo := reflect.ValueOf(data).Elem()
|
|
||||||
valueInfo.FieldByName(valueName).SetInt(int64(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StoreScoreDataWrapper) SetDailyBadCommentOrderCount(storeCountList []*model.StoreCount) {
|
|
||||||
s.locker.Lock()
|
|
||||||
defer s.locker.Unlock()
|
|
||||||
for _, value := range storeCountList {
|
|
||||||
s.dailyBadCommentOrderCount[value.StoreID] = value.Count
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StoreScoreDataWrapper) GetDailyBadCommentOrderCount(storeID int) int {
|
|
||||||
s.locker.RLock()
|
|
||||||
defer s.locker.RUnlock()
|
|
||||||
if count, ok := s.dailyBadCommentOrderCount[storeID]; ok {
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StoreScoreDataWrapper) SetDailyUnFinishOrderCount(storeCountList []*model.StoreCount) {
|
|
||||||
for _, value := range storeCountList {
|
|
||||||
s.dailyUnFinishOrderCount[value.StoreID] = value.Count
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StoreScoreDataWrapper) GetDailyUnFinishOrderCount(storeID int) int {
|
|
||||||
s.locker.RLock()
|
|
||||||
defer s.locker.RUnlock()
|
|
||||||
if count, ok := s.dailyUnFinishOrderCount[storeID]; ok {
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StoreScoreDataWrapper) SetDailyFinishOrderCount(storeCountList []*model.StoreCount) {
|
|
||||||
for _, value := range storeCountList {
|
|
||||||
s.dailyFinishOrderCount[value.StoreID] = value.Count
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StoreScoreDataWrapper) GetDailyFinishOrderCount(storeID int) int {
|
|
||||||
s.locker.RLock()
|
|
||||||
defer s.locker.RUnlock()
|
|
||||||
if count, ok := s.dailyFinishOrderCount[storeID]; ok {
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StoreScoreDataWrapper) SetDailyAbsentGoodsOrderCount(storeCountList []*model.StoreCount) {
|
|
||||||
for _, value := range storeCountList {
|
|
||||||
s.dailyAbsentGoodsOrderCount[value.StoreID] = value.Count
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StoreScoreDataWrapper) GetDailyAbsentGoodsOrderCount(storeID int) int {
|
|
||||||
s.locker.RLock()
|
|
||||||
defer s.locker.RUnlock()
|
|
||||||
if count, ok := s.dailyAbsentGoodsOrderCount[storeID]; ok {
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StoreScoreDataWrapper) InsertStoreScore() {
|
|
||||||
for _, value := range s.storeScoreData {
|
|
||||||
dao.InsertStoreScore(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//得到所有门店的可售商品(优化内存,只存商品的价格)
|
|
||||||
func GetAllStoreSkus(ctx *jxcontext.Context, parentTask tasksch.ITask, storeList []*cms.StoreExt) {
|
|
||||||
allStoreSkusWrapper.InitData()
|
|
||||||
taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
|
||||||
storeInfo := batchItemList[0].(*cms.StoreExt)
|
|
||||||
storeID := storeInfo.ID
|
|
||||||
if jxSkuInfoData, err2 := cms.GetStoreSkus(ctx, storeID, []int{}, true, "", true, false, map[string]interface{}{}, 0, -1); jxSkuInfoData != nil {
|
|
||||||
jxSkuPriceMapData := make(map[int]int)
|
|
||||||
for _, value := range jxSkuInfoData.SkuNames {
|
|
||||||
for _, skuInfo := range value.Skus {
|
|
||||||
saleStatus := jxutils.MergeSkuStatus(skuInfo.SkuStatus, skuInfo.StoreSkuStatus)
|
|
||||||
if saleStatus == model.SkuStatusNormal {
|
|
||||||
jxSkuPriceMapData[skuInfo.SkuID] = skuInfo.BindPrice
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
allStoreSkusWrapper.SetData(storeID, jxSkuPriceMapData)
|
|
||||||
} else {
|
|
||||||
globals.SugarLogger.Warnf("store_score.GetAllStoreSkus %d return empty, err:%v", storeID, err2)
|
|
||||||
}
|
|
||||||
return retVal, err
|
|
||||||
}
|
|
||||||
taskParallel := tasksch.NewParallelTask("得到所有门店商品", tasksch.NewParallelConfig().SetParallelCount(ParallelCount), ctx, taskFunc, storeList)
|
|
||||||
tasksch.HandleTask(taskParallel, parentTask, true).Run()
|
|
||||||
taskParallel.GetResult(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetOpenTime(opTimeList []int16) (opTime float64) {
|
|
||||||
opTime = 0
|
|
||||||
for index, _ := range opTimeList {
|
|
||||||
if index%2 == 1 {
|
|
||||||
endTime := opTimeList[index]
|
|
||||||
startTime := opTimeList[index-1]
|
|
||||||
diffHour := float64(endTime/100 - startTime/100)
|
|
||||||
diffMin := float64(endTime%100-startTime%100) / 60
|
|
||||||
opTime += diffHour + diffMin
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return opTime
|
|
||||||
}
|
|
||||||
|
|
||||||
//营业时间12小时及以上满分,总分10分,每少一个小时扣1分
|
|
||||||
func ScoreStoreOpenTime(storeInfo *cms.StoreExt) {
|
|
||||||
storeID := storeInfo.ID
|
|
||||||
storeStatus := storeInfo.Status
|
|
||||||
isStoreOpen := storeStatus == model.StoreStatusOpened
|
|
||||||
finalScore := 0
|
|
||||||
if isStoreOpen {
|
|
||||||
for _, storeMap := range storeInfo.StoreMaps {
|
|
||||||
isSyncStoreSku := storeMap.IsSync
|
|
||||||
vendorStoreStatus := storeMap.Status
|
|
||||||
isVendorStoreOpen := vendorStoreStatus == model.StoreStatusOpened
|
|
||||||
opTimeList := storeInfo.GetOpTimeList()
|
|
||||||
if len(opTimeList) > 0 && isStoreOpen && isVendorStoreOpen && isSyncStoreSku != 0 {
|
|
||||||
opTime := GetOpenTime(opTimeList)
|
|
||||||
if opTime >= StoreOpenTimeNormalTime {
|
|
||||||
finalScore = ItemTotalScore
|
|
||||||
} else {
|
|
||||||
decScore := int(math.Round(StoreOpenTimeNormalTime - opTime))
|
|
||||||
finalScore = ItemTotalScore - decScore
|
|
||||||
if finalScore < 0 {
|
|
||||||
finalScore = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
storeScoreDataWrapper.SetData(storeID, model.FieldStoreOpenTime, finalScore)
|
|
||||||
}
|
|
||||||
|
|
||||||
//可售商品数量大于1000,总分10分,按比例扣
|
|
||||||
func ScoreSaleSkuCount(storeInfo *cms.StoreExt) {
|
|
||||||
storeID := storeInfo.ID
|
|
||||||
skusMapData := allStoreSkusWrapper.GetData(storeID)
|
|
||||||
finalScore := 0
|
|
||||||
if len(skusMapData) > 0 {
|
|
||||||
saleSkuCount := len(skusMapData)
|
|
||||||
finalScore = int(math.Round(float64(saleSkuCount) * SaleSkuScorePerUnit))
|
|
||||||
if finalScore > ItemTotalScore {
|
|
||||||
finalScore = ItemTotalScore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
storeScoreDataWrapper.SetData(storeID, model.FieldSaleSkuCount, finalScore)
|
|
||||||
}
|
|
||||||
|
|
||||||
//平均捡货时间小于等于拣货截止时间为10分满分,每超出1分钟,减1分
|
|
||||||
func ScoreAveragePickupTime(storeInfo *cms.StoreExt) {
|
|
||||||
storeID := storeInfo.ID
|
|
||||||
db := dao.GetDB()
|
|
||||||
orderList, err := dao.GetDailyFinishOrderList(db, storeID, scoreDate)
|
|
||||||
orderListCount := len(orderList)
|
|
||||||
finalScore := 0
|
|
||||||
if err == nil && orderListCount > 0 {
|
|
||||||
totalScore := 0
|
|
||||||
for _, value := range orderList {
|
|
||||||
statusTime := value.StatusTime.Unix()
|
|
||||||
pickDeadline := value.PickDeadline.Unix()
|
|
||||||
if statusTime <= pickDeadline {
|
|
||||||
totalScore += ItemTotalScore
|
|
||||||
} else {
|
|
||||||
decScore := int(math.Round(float64(statusTime-pickDeadline) / 60))
|
|
||||||
tempScore := ItemTotalScore - decScore
|
|
||||||
if tempScore < 0 {
|
|
||||||
tempScore = 0
|
|
||||||
}
|
|
||||||
totalScore += tempScore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finalScore = totalScore / orderListCount
|
|
||||||
}
|
|
||||||
storeScoreDataWrapper.SetData(storeID, model.FieldAveragePickupTime, finalScore)
|
|
||||||
}
|
|
||||||
|
|
||||||
//差评订单和完成订单比例小于0.2%,得满分10分,每增加0.1%减1分
|
|
||||||
func ScoreBadCommentOrder(storeInfo *cms.StoreExt) {
|
|
||||||
storeID := storeInfo.ID
|
|
||||||
badCommentOrderCount := storeScoreDataWrapper.GetDailyBadCommentOrderCount(storeID)
|
|
||||||
finishOrderCount := storeScoreDataWrapper.GetDailyFinishOrderCount(storeID)
|
|
||||||
finalScore := 0
|
|
||||||
if finishOrderCount > 0 {
|
|
||||||
badCommentOrderRatio := float64(badCommentOrderCount) * 100 / float64(finishOrderCount)
|
|
||||||
if badCommentOrderRatio <= BadCommentOrderNormalRatio {
|
|
||||||
finalScore = ItemTotalScore
|
|
||||||
} else {
|
|
||||||
decScore := int(math.Round((badCommentOrderRatio - BadCommentOrderNormalRatio) / 0.1))
|
|
||||||
finalScore = ItemTotalScore - decScore
|
|
||||||
if finalScore < 0 {
|
|
||||||
finalScore = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
storeScoreDataWrapper.SetData(storeID, model.FieldBadCommentOrder, finalScore)
|
|
||||||
}
|
|
||||||
|
|
||||||
//未完成订单和完成订单比小于1%,得满分10分,比例每增加5%,分数减1
|
|
||||||
func ScoreUnfinishOrder(storeInfo *cms.StoreExt) {
|
|
||||||
storeID := storeInfo.ID
|
|
||||||
unFinishOrderCount := storeScoreDataWrapper.GetDailyUnFinishOrderCount(storeID)
|
|
||||||
finishOrderCount := storeScoreDataWrapper.GetDailyFinishOrderCount(storeID)
|
|
||||||
finalScore := 0
|
|
||||||
if finishOrderCount > 0 {
|
|
||||||
unfinishOrderRatio := float64(unFinishOrderCount) * 100 / float64(finishOrderCount)
|
|
||||||
if unfinishOrderRatio <= UnfinishOrderNormalRatio {
|
|
||||||
finalScore = ItemTotalScore
|
|
||||||
} else {
|
|
||||||
decScore := int(math.Round((unfinishOrderRatio - UnfinishOrderNormalRatio) / 5))
|
|
||||||
finalScore = ItemTotalScore - decScore
|
|
||||||
if finalScore < 0 {
|
|
||||||
finalScore = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
storeScoreDataWrapper.SetData(storeID, model.FieldUnfinishOrder, finalScore)
|
|
||||||
}
|
|
||||||
|
|
||||||
//缺货订单和完成订单比小于1%得10分,比例每增加0.1%减1分
|
|
||||||
func ScoreAbsentGoodsOrder(storeInfo *cms.StoreExt) {
|
|
||||||
storeID := storeInfo.ID
|
|
||||||
absentGoodsOrderCount := storeScoreDataWrapper.GetDailyAbsentGoodsOrderCount(storeID)
|
|
||||||
finishOrderCount := storeScoreDataWrapper.GetDailyFinishOrderCount(storeID)
|
|
||||||
finalScore := 0
|
|
||||||
if finishOrderCount > 0 {
|
|
||||||
absentGoodsOrderRatio := float64(absentGoodsOrderCount) * 100 / float64(finishOrderCount)
|
|
||||||
if absentGoodsOrderRatio <= AbsentGoodsOrderNormalRatio {
|
|
||||||
finalScore = ItemTotalScore
|
|
||||||
} else {
|
|
||||||
decScore := int(math.Round((absentGoodsOrderRatio - AbsentGoodsOrderNormalRatio) / 0.1))
|
|
||||||
finalScore = ItemTotalScore - decScore
|
|
||||||
if finalScore < 0 {
|
|
||||||
finalScore = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
storeScoreDataWrapper.SetData(storeID, model.FieldAbsentGoodsOrder, finalScore)
|
|
||||||
}
|
|
||||||
|
|
||||||
//促销品数量20个以上为满分10分,每少2个扣1分
|
|
||||||
func ScorePromotionSku(storeInfo *cms.StoreExt) {
|
|
||||||
storeID := storeInfo.ID
|
|
||||||
db := dao.GetDB()
|
|
||||||
beginTime := time.Now()
|
|
||||||
endTime := time.Now()
|
|
||||||
actStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, -1, nil, model.ActTypeAll, []int{storeID}, nil, beginTime, endTime)
|
|
||||||
finalScore := 0
|
|
||||||
if err == nil && len(actStoreSkuList) > 0 {
|
|
||||||
actStoreSkuMap := make(map[int]int)
|
|
||||||
for _, value := range actStoreSkuList {
|
|
||||||
if value.Type != model.ActSkuFake {
|
|
||||||
actStoreSkuMap[value.SkuID] = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
promotionSkuCount := len(actStoreSkuMap)
|
|
||||||
if promotionSkuCount >= PromotionSkuNormalCount {
|
|
||||||
finalScore = ItemTotalScore
|
|
||||||
} else {
|
|
||||||
decScore := (PromotionSkuNormalCount - promotionSkuCount) / 2
|
|
||||||
finalScore = ItemTotalScore - decScore
|
|
||||||
if finalScore < 0 {
|
|
||||||
finalScore = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
storeScoreDataWrapper.SetData(storeID, model.FieldPromotionSku, finalScore)
|
|
||||||
}
|
|
||||||
|
|
||||||
//经营全平台满分10分,每少一个平台扣2分(一个平台没有得0分)
|
|
||||||
func ScoreFullVendor(storeInfo *cms.StoreExt) {
|
|
||||||
fullVendorCount := len(fullVendorList)
|
|
||||||
finalScore := 0
|
|
||||||
storeID := storeInfo.ID
|
|
||||||
storeStatus := storeInfo.Status
|
|
||||||
isStoreOpen := storeStatus == model.StoreStatusOpened
|
|
||||||
count := 0
|
|
||||||
for _, storeMap := range storeInfo.StoreMaps {
|
|
||||||
isSyncStoreSku := storeMap.IsSync
|
|
||||||
vendorStoreStatus := storeMap.Status
|
|
||||||
isVendorStoreOpen := vendorStoreStatus == model.StoreStatusOpened
|
|
||||||
opTimeList := storeInfo.GetOpTimeList()
|
|
||||||
if len(opTimeList) > 0 && isStoreOpen && isVendorStoreOpen && isSyncStoreSku != 0 {
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if count > 0 {
|
|
||||||
if count == fullVendorCount {
|
|
||||||
finalScore = ItemTotalScore
|
|
||||||
} else {
|
|
||||||
decScore := (fullVendorCount - count) * 2
|
|
||||||
finalScore = ItemTotalScore - decScore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
storeScoreDataWrapper.SetData(storeID, model.FieldFullVendor, finalScore)
|
|
||||||
}
|
|
||||||
|
|
||||||
//经营范围面积大于半径2km的圆得满分10分,低于1km得分0
|
|
||||||
func ScoreStoreRange(storeInfo *cms.StoreExt) {
|
|
||||||
finalScore := 0
|
|
||||||
storeID := storeInfo.ID
|
|
||||||
if storeInfo.DeliveryRangeType == model.DeliveryRangeTypePolygon {
|
|
||||||
if storeInfo.DeliveryRange != "" {
|
|
||||||
points := jxutils.CoordinateStr2Points(storeInfo.DeliveryRange)
|
|
||||||
area := jxutils.CalcPolygonAreaAutonavi(points)
|
|
||||||
goodArea := math.Pi * StoreRangeGoodRadius * StoreRangeGoodRadius
|
|
||||||
badArea := math.Pi * StoreRangeBadRadius * StoreRangeBadRadius
|
|
||||||
if area >= goodArea {
|
|
||||||
finalScore = ItemTotalScore
|
|
||||||
} else if area <= badArea {
|
|
||||||
finalScore = 0
|
|
||||||
} else {
|
|
||||||
diff := goodArea - area
|
|
||||||
ratio := float64(ItemTotalScore) / (goodArea - badArea)
|
|
||||||
finalScore = ItemTotalScore - int(math.Round(diff*ratio))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if storeInfo.DeliveryRangeType == model.DeliveryRangeTypeRadius {
|
|
||||||
deliveryRadius := utils.Str2Float64WithDefault(storeInfo.DeliveryRange, 0) / 1000
|
|
||||||
if deliveryRadius >= StoreRangeGoodRadius {
|
|
||||||
finalScore = ItemTotalScore
|
|
||||||
} else if deliveryRadius <= StoreRangeBadRadius {
|
|
||||||
finalScore = 0
|
|
||||||
} else {
|
|
||||||
diff := StoreRangeGoodRadius - deliveryRadius
|
|
||||||
ratio := float64(ItemTotalScore) / (StoreRangeGoodRadius - StoreRangeBadRadius)
|
|
||||||
finalScore = ItemTotalScore - int(math.Round(diff*ratio))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if finalScore < 0 {
|
|
||||||
globals.SugarLogger.Infof("ScoreStoreRange abnormal finalScore:%d, storeInfo:%s", finalScore, utils.Format4Output(storeInfo, true))
|
|
||||||
finalScore = 0
|
|
||||||
} else if finalScore > ItemTotalScore {
|
|
||||||
globals.SugarLogger.Infof("ScoreStoreRange abnormal finalScore:%d, storeInfo:%s", finalScore, utils.Format4Output(storeInfo, true))
|
|
||||||
finalScore = ItemTotalScore
|
|
||||||
}
|
|
||||||
storeScoreDataWrapper.SetData(storeID, model.FieldStoreRange, finalScore)
|
|
||||||
}
|
|
||||||
|
|
||||||
//得到距离某个门店多少KM内的所有门店信息
|
|
||||||
func GetRangeStoreList(storeID int, lng, lat, checkRange float64, storeList []*cms.StoreExt) (outStoreList []*cms.StoreExt) {
|
|
||||||
for _, storeInfo := range storeList {
|
|
||||||
if storeInfo.ID == storeID {
|
|
||||||
outStoreList = append(outStoreList, storeInfo)
|
|
||||||
} else {
|
|
||||||
distance := jxutils.EarthDistance(lng, lat, storeInfo.FloatLng, storeInfo.FloatLat)
|
|
||||||
if distance <= checkRange {
|
|
||||||
outStoreList = append(outStoreList, storeInfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return outStoreList
|
|
||||||
}
|
|
||||||
|
|
||||||
//得到给定门店列表里的同一SkuID商品的平均价格
|
|
||||||
func GetStoreSkusAveragePrice(storeList []*cms.StoreExt) map[int]int {
|
|
||||||
skusTotalPrice := make(map[int]int)
|
|
||||||
skusCount := make(map[int]int)
|
|
||||||
skusAveragePrice := make(map[int]int)
|
|
||||||
for _, storeInfo := range storeList {
|
|
||||||
storeID := storeInfo.ID
|
|
||||||
storeSkuMapData := allStoreSkusWrapper.GetData(storeID)
|
|
||||||
for skuID, skuPrice := range storeSkuMapData {
|
|
||||||
skusTotalPrice[skuID] += skuPrice
|
|
||||||
skusCount[skuID]++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for id, totalPrice := range skusTotalPrice {
|
|
||||||
skusAveragePrice[id] = int(math.Round(float64(totalPrice) / float64(skusCount[id])))
|
|
||||||
}
|
|
||||||
return skusAveragePrice
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetSkusCountLessEqualAvgPrice(storeID int, skusAveragePrice map[int]int) (count int) {
|
|
||||||
storeSkuMapData := allStoreSkusWrapper.GetData(storeID)
|
|
||||||
for skuID, skuPrice := range storeSkuMapData {
|
|
||||||
skuAvgPrice := skusAveragePrice[skuID]
|
|
||||||
if skuPrice <= skuAvgPrice {
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
//可售商品价格在附近5km内门店比较,价格低于等于平均值的商品数占90%以上满分10分,比例每降低10%减1分,100%超标得0分
|
|
||||||
func ScoreSaleSkuPrice(storeInfo *cms.StoreExt, storeList []*cms.StoreExt) {
|
|
||||||
finalScore := 0
|
|
||||||
storeID := storeInfo.ID
|
|
||||||
totalCount := len(allStoreSkusWrapper.GetData(storeID))
|
|
||||||
if totalCount > 0 {
|
|
||||||
rangeStoreList := GetRangeStoreList(storeID, storeInfo.FloatLng, storeInfo.FloatLat, SaleSkuCheckRange, storeList)
|
|
||||||
skusAveragePrice := GetStoreSkusAveragePrice(rangeStoreList)
|
|
||||||
count := GetSkusCountLessEqualAvgPrice(storeID, skusAveragePrice)
|
|
||||||
if count > 0 {
|
|
||||||
ratio := int(math.Round(float64(count) * 100 / float64(totalCount)))
|
|
||||||
if ratio >= SaleSkuPriceRatio {
|
|
||||||
finalScore = ItemTotalScore
|
|
||||||
} else {
|
|
||||||
decScore := (SaleSkuPriceRatio - ratio) / 10
|
|
||||||
finalScore = ItemTotalScore - decScore
|
|
||||||
if finalScore < 0 {
|
|
||||||
finalScore = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
storeScoreDataWrapper.SetData(storeID, model.FieldSaleSkuPrice, finalScore)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetFilterStoreListEx(storeList []*cms.StoreExt, storeIDMap map[int]int) (outStoreList []*cms.StoreExt) {
|
|
||||||
for _, storeInfo := range storeList {
|
|
||||||
storeID := storeInfo.ID
|
|
||||||
if len(storeIDMap) > 0 {
|
|
||||||
if _, ok := storeIDMap[storeID]; !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var tempStoreMaps []*model.StoreMap
|
|
||||||
for _, vendorStoreInfo := range storeInfo.StoreMaps {
|
|
||||||
vendorID := vendorStoreInfo.VendorID
|
|
||||||
if _, ok := fullVendorList[vendorID]; !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
tempStoreMaps = append(tempStoreMaps, vendorStoreInfo)
|
|
||||||
}
|
|
||||||
if len(tempStoreMaps) > 0 {
|
|
||||||
storeInfo.StoreMaps = tempStoreMaps
|
|
||||||
outStoreList = append(outStoreList, storeInfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return outStoreList
|
|
||||||
}
|
|
||||||
|
|
||||||
func ScoreStore(ctx *jxcontext.Context, storeIDList []int) (retVal interface{}, err error) {
|
|
||||||
isScoring = true
|
|
||||||
scoreDate = utils.GetCurDate()
|
|
||||||
var storeList []*cms.StoreExt
|
|
||||||
taskCount := 5
|
|
||||||
taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
|
|
||||||
switch step {
|
|
||||||
case 0:
|
|
||||||
baseapi.SugarLogger.Debugf("ScoreStore step0 begin")
|
|
||||||
storeScoreDataWrapper.InitData()
|
|
||||||
storeList, err = GetStoreList(ctx)
|
|
||||||
storeIDMap := jxutils.IntList2Map(storeIDList)
|
|
||||||
storeList = GetFilterStoreListEx(storeList, storeIDMap)
|
|
||||||
baseapi.SugarLogger.Debugf("ScoreStore step0 end")
|
|
||||||
case 1:
|
|
||||||
baseapi.SugarLogger.Debugf("ScoreStore step1 begin")
|
|
||||||
GetAllStoreSkus(ctx, task, storeList)
|
|
||||||
baseapi.SugarLogger.Debugf("ScoreStore step1 end")
|
|
||||||
case 2:
|
|
||||||
baseapi.SugarLogger.Debugf("ScoreStore step2 begin")
|
|
||||||
db := dao.GetDB()
|
|
||||||
storeCountList, err := dao.GetDailyBadCommentOrderCount(db, scoreDate)
|
|
||||||
if err == nil {
|
|
||||||
storeScoreDataWrapper.SetDailyBadCommentOrderCount(storeCountList)
|
|
||||||
} else {
|
|
||||||
baseapi.SugarLogger.Debugf("ScoreStore GetDailyBadCommentOrderCount %v", err)
|
|
||||||
}
|
|
||||||
storeCountList, err = dao.GetDailyUnFinishOrderCount(db, scoreDate)
|
|
||||||
if err == nil {
|
|
||||||
storeScoreDataWrapper.SetDailyUnFinishOrderCount(storeCountList)
|
|
||||||
} else {
|
|
||||||
baseapi.SugarLogger.Debugf("ScoreStore GetDailyUnFinishOrderCount %v", err)
|
|
||||||
}
|
|
||||||
storeCountList, err = dao.GetDailyFinishOrderCount(db, scoreDate)
|
|
||||||
if err == nil {
|
|
||||||
storeScoreDataWrapper.SetDailyFinishOrderCount(storeCountList)
|
|
||||||
} else {
|
|
||||||
baseapi.SugarLogger.Debugf("ScoreStore GetDailyFinishOrderCount %v", err)
|
|
||||||
}
|
|
||||||
storeCountList, err = dao.GetDailyAbsentGoodsOrderCount(db, scoreDate)
|
|
||||||
if err == nil {
|
|
||||||
storeScoreDataWrapper.SetDailyAbsentGoodsOrderCount(storeCountList)
|
|
||||||
} else {
|
|
||||||
baseapi.SugarLogger.Debugf("ScoreStore GetDailyAbsentGoodsOrderCount %v", err)
|
|
||||||
}
|
|
||||||
baseapi.SugarLogger.Debugf("ScoreStore step2 end")
|
|
||||||
case 3:
|
|
||||||
baseapi.SugarLogger.Debugf("ScoreStore step3 begin")
|
|
||||||
taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
|
||||||
storeInfo := batchItemList[0].(*cms.StoreExt)
|
|
||||||
storeID := storeInfo.ID
|
|
||||||
baseapi.SugarLogger.Debugf("Begin store id:%d", storeID)
|
|
||||||
ScoreStoreOpenTime(storeInfo)
|
|
||||||
ScoreSaleSkuCount(storeInfo)
|
|
||||||
ScoreAveragePickupTime(storeInfo)
|
|
||||||
ScoreBadCommentOrder(storeInfo)
|
|
||||||
ScoreUnfinishOrder(storeInfo)
|
|
||||||
ScoreAbsentGoodsOrder(storeInfo)
|
|
||||||
ScorePromotionSku(storeInfo)
|
|
||||||
ScoreFullVendor(storeInfo)
|
|
||||||
ScoreStoreRange(storeInfo)
|
|
||||||
ScoreSaleSkuPrice(storeInfo, storeList)
|
|
||||||
baseapi.SugarLogger.Debugf("End store id:%d", storeID)
|
|
||||||
return retVal, err
|
|
||||||
}
|
|
||||||
taskParallel := tasksch.NewParallelTask("计算门店得分", tasksch.NewParallelConfig().SetParallelCount(ParallelCount), ctx, taskFunc, storeList)
|
|
||||||
tasksch.HandleTask(taskParallel, task, true).Run()
|
|
||||||
taskParallel.GetResult(0)
|
|
||||||
_, err = taskParallel.GetResult(0)
|
|
||||||
if err != nil {
|
|
||||||
baseapi.SugarLogger.Debugf("ScoreStore taskParallel error:%v", err)
|
|
||||||
}
|
|
||||||
baseapi.SugarLogger.Debugf("ScoreStore step3 end")
|
|
||||||
case 4:
|
|
||||||
baseapi.SugarLogger.Debugf("ScoreStore step4 begin")
|
|
||||||
storeScoreDataWrapper.InsertStoreScore()
|
|
||||||
storeScoreDataWrapper.ClearData()
|
|
||||||
allStoreSkusWrapper.ClearData()
|
|
||||||
baseapi.SugarLogger.Debugf("ScoreStore step4 end")
|
|
||||||
isScoring = false
|
|
||||||
}
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
taskSeq := tasksch.NewSeqTask("门店评分-序列任务", ctx, taskSeqFunc, taskCount)
|
|
||||||
tasksch.HandleTask(taskSeq, nil, true).Run()
|
|
||||||
|
|
||||||
return retVal, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func ScheduleScoreStore() {
|
|
||||||
if EnableScheduleScoreStore {
|
|
||||||
ScheduleTimerFunc("ScheduleScoreStore", func() {
|
|
||||||
if !isScoring {
|
|
||||||
ScoreStore(jxcontext.AdminCtx, nil)
|
|
||||||
}
|
|
||||||
}, scoreStoreTimeList)
|
|
||||||
CheckScoreStore()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func CheckScoreStore() {
|
|
||||||
if !isScoring {
|
|
||||||
curTime := time.Now()
|
|
||||||
checkTimeStr1 := fmt.Sprintf("%s %s", utils.Time2DateStr(curTime), scoreStoreTimeList[0])
|
|
||||||
checkTime1 := utils.Str2Time(checkTimeStr1)
|
|
||||||
checkTimeStr2 := fmt.Sprintf("%s %s", utils.Time2DateStr(curTime), scoreStoreCheckTimeEnd)
|
|
||||||
checkTime2 := utils.Str2Time(checkTimeStr2)
|
|
||||||
if curTime.Unix() >= checkTime1.Unix() && curTime.Unix() <= checkTime2.Unix() {
|
|
||||||
db := dao.GetDB()
|
|
||||||
hasStoreScoreData, err := dao.CheckHasStoreScoreData(db, curTime)
|
|
||||||
if err == nil && !hasStoreScoreData {
|
|
||||||
ScoreStore(jxcontext.AdminCtx, nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Time2Week(t time.Time) int {
|
|
||||||
yearDay := t.YearDay()
|
|
||||||
yearFirstDay := t.AddDate(0, 0, -yearDay+1)
|
|
||||||
firstDayInWeek := int(yearFirstDay.Weekday())
|
|
||||||
|
|
||||||
firstWeekDays := 1
|
|
||||||
if firstDayInWeek != 0 {
|
|
||||||
firstWeekDays = 7 - firstDayInWeek + 1
|
|
||||||
}
|
|
||||||
var week int
|
|
||||||
if yearDay <= firstWeekDays {
|
|
||||||
week = 1
|
|
||||||
} else {
|
|
||||||
tempWeek := (float64(yearDay) - float64(firstWeekDays)) / float64(7)
|
|
||||||
week = int(math.Ceil(tempWeek)) + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return week
|
|
||||||
}
|
|
||||||
|
|
||||||
func SplitToSingleWeekDataList(storeScoreList []*model.StoreScoreEx) (weekDataList [][]*model.StoreScoreEx) {
|
|
||||||
singleWeekData := []*model.StoreScoreEx{}
|
|
||||||
weekIndex := 0
|
|
||||||
for _, value := range storeScoreList {
|
|
||||||
if weekIndex == 0 {
|
|
||||||
weekIndex = Time2Week(value.ScoreDate)
|
|
||||||
}
|
|
||||||
if weekIndex == Time2Week(value.ScoreDate) {
|
|
||||||
singleWeekData = append(singleWeekData, value)
|
|
||||||
} else {
|
|
||||||
weekDataList = append(weekDataList, singleWeekData)
|
|
||||||
singleWeekData = []*model.StoreScoreEx{}
|
|
||||||
weekIndex = 0
|
|
||||||
singleWeekData = append(singleWeekData, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(singleWeekData) > 0 {
|
|
||||||
weekDataList = append(weekDataList, singleWeekData)
|
|
||||||
}
|
|
||||||
|
|
||||||
return weekDataList
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetStoreScoreLevel(score int) int {
|
|
||||||
level := 0
|
|
||||||
if score >= GoldMedalScore {
|
|
||||||
level = GoldMedalLevel
|
|
||||||
} else if score >= SilverMedalScore {
|
|
||||||
level = SilverMedalLevel
|
|
||||||
} else if score >= BronzeMedalScore {
|
|
||||||
level = BronzeMedalLevel
|
|
||||||
}
|
|
||||||
|
|
||||||
return level
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetWeeklyStoreScore(storeID, weekIndexParam int) (outWeeklyStoreScoreDataList []*model.WeeklyStoreScore, err error) {
|
|
||||||
db := dao.GetDB()
|
|
||||||
storeScoreList, err := dao.GetWeeklyStoreScoreList(db, storeID, WeekNum)
|
|
||||||
if err == nil && len(storeScoreList) > 0 {
|
|
||||||
weeklyStoreScoreDataList := []*model.WeeklyStoreScore{}
|
|
||||||
weekDataList := SplitToSingleWeekDataList(storeScoreList)
|
|
||||||
for weekIndex, weekData := range weekDataList {
|
|
||||||
weeklyData := &model.WeeklyStoreScore{}
|
|
||||||
weeklyData.ID = weekIndex
|
|
||||||
weeklyData.ItemTotalScore = ItemTotalScore
|
|
||||||
weeklyData.StoreID = storeID
|
|
||||||
weeklyStoreScoreDataList = append(weeklyStoreScoreDataList, weeklyData)
|
|
||||||
weekDataCount := len(weekData)
|
|
||||||
for dayIndex, dayData := range weekData {
|
|
||||||
for _, fieldName := range storeScoreFieldName {
|
|
||||||
srcFieldValue := refutil.GetObjFieldByName(dayData, fieldName).(int)
|
|
||||||
destFieldValue := refutil.GetObjFieldByName(weeklyData, fieldName).(int)
|
|
||||||
refutil.SetObjFieldByName(weeklyData, fieldName, destFieldValue+srcFieldValue)
|
|
||||||
}
|
|
||||||
if weekDataCount == 1 {
|
|
||||||
weeklyData.BeginTime = dayData.ScoreDate
|
|
||||||
weeklyData.EndTime = dayData.ScoreDate
|
|
||||||
} else {
|
|
||||||
if dayIndex == 0 {
|
|
||||||
weeklyData.EndTime = dayData.ScoreDate
|
|
||||||
} else if dayIndex == weekDataCount-1 {
|
|
||||||
weeklyData.BeginTime = dayData.ScoreDate
|
|
||||||
}
|
|
||||||
}
|
|
||||||
weeklyData.StoreName = dayData.StoreName
|
|
||||||
}
|
|
||||||
for _, fieldName := range storeScoreFieldName {
|
|
||||||
destFieldValue := refutil.GetObjFieldByName(weeklyData, fieldName).(int)
|
|
||||||
refutil.SetObjFieldByName(weeklyData, fieldName, int(math.Round(float64(destFieldValue)/float64(weekDataCount))))
|
|
||||||
}
|
|
||||||
for _, fieldName := range storeScoreFieldName {
|
|
||||||
srcFieldValue := refutil.GetObjFieldByName(weeklyData, fieldName).(int)
|
|
||||||
destFieldValue := refutil.GetObjFieldByName(weeklyData, model.FieldTotalScore).(int)
|
|
||||||
refutil.SetObjFieldByName(weeklyData, model.FieldTotalScore, destFieldValue+srcFieldValue)
|
|
||||||
}
|
|
||||||
weeklyData.Level = GetStoreScoreLevel(weeklyData.TotalScore)
|
|
||||||
}
|
|
||||||
if weekIndexParam == -1 {
|
|
||||||
outWeeklyStoreScoreDataList = weeklyStoreScoreDataList
|
|
||||||
} else {
|
|
||||||
fmt.Println("testss", utils.Format4Output(weeklyStoreScoreDataList, false))
|
|
||||||
outWeeklyStoreScoreDataList = []*model.WeeklyStoreScore{weeklyStoreScoreDataList[weekIndexParam]}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return outWeeklyStoreScoreDataList, err
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
storeID := value.StoreID
|
|
||||||
if storeTotalScoreMapData[storeID] == nil {
|
|
||||||
storeTotalScore := &model.StoreTotalScore{}
|
|
||||||
storeTotalScore.StoreID = value.StoreID
|
|
||||||
storeTotalScore.StoreName = value.StoreName
|
|
||||||
storeTotalScore.CityName = value.CityName
|
|
||||||
storeTotalScoreMapData[storeID] = storeTotalScore
|
|
||||||
}
|
|
||||||
storeTotalScore := storeTotalScoreMapData[storeID]
|
|
||||||
storeTotalScore.StoreScore += value.StoreScore
|
|
||||||
countDayNum[storeID]++
|
|
||||||
}
|
|
||||||
for storeID, value := range storeTotalScoreMapData {
|
|
||||||
value.StoreScore = int(math.Round(float64(value.StoreScore) / float64(countDayNum[storeID])))
|
|
||||||
needAdd := true
|
|
||||||
if checkScoreLow > 0 && value.StoreScore < checkScoreLow {
|
|
||||||
needAdd = false
|
|
||||||
}
|
|
||||||
if checkScoreHigh > 0 && value.StoreScore > checkScoreHigh {
|
|
||||||
needAdd = false
|
|
||||||
}
|
|
||||||
if needAdd {
|
|
||||||
filterStoreTotalScoreList = append(filterStoreTotalScoreList, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if isDesc {
|
|
||||||
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 {
|
|
||||||
return data1.StoreScore > data2.StoreScore
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
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 {
|
|
||||||
return data1.StoreScore < data2.StoreScore
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package misc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
|
|
||||||
"git.rosy.net.cn/jx-callback/globals/api2"
|
|
||||||
"git.rosy.net.cn/jx-callback/globals/testinit"
|
|
||||||
|
|
||||||
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/ebai"
|
|
||||||
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/elm"
|
|
||||||
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/jd"
|
|
||||||
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/mtwm"
|
|
||||||
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/weimob/wsc"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
testinit.Init()
|
|
||||||
api2.Init()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestScoreStore(t *testing.T) {
|
|
||||||
ScoreStore(jxcontext.AdminCtx, []int{})
|
|
||||||
}
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
package misc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"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/tasksch"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/model"
|
|
||||||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
DayNum = 30 //请求天数
|
|
||||||
LimitNum = 100 //最大数据限制
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetStoreSkuSalesInfo(ctx *jxcontext.Context, storeID int) (outStoreSkuSales []*model.StoreSkuSales, err error) {
|
|
||||||
db := dao.GetDB()
|
|
||||||
//得到所有门店
|
|
||||||
storeList, err := GetStoreList(ctx)
|
|
||||||
if err == nil {
|
|
||||||
storeList = GetFilterStoreListEx(storeList, nil)
|
|
||||||
} else {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
storeMapData := make(map[int]*cms.StoreExt)
|
|
||||||
for _, value := range storeList {
|
|
||||||
storeMapData[value.ID] = value
|
|
||||||
}
|
|
||||||
curStoreInfo := storeMapData[storeID]
|
|
||||||
if curStoreInfo == nil {
|
|
||||||
return nil, errors.New(fmt.Sprintf("未找到商店:[%d]", storeID))
|
|
||||||
}
|
|
||||||
cityCode := curStoreInfo.CityCode
|
|
||||||
|
|
||||||
//获取本市商品总销量
|
|
||||||
citySkuSalesCntMap := make(map[int]int)
|
|
||||||
citySkuSalesCntList, err := dao.GetSkuSalesCntList(db, -1, cityCode, DayNum, LimitNum, nil)
|
|
||||||
citySkuIDs := []int{}
|
|
||||||
if err == nil {
|
|
||||||
for _, value := range citySkuSalesCntList {
|
|
||||||
citySkuSalesCntMap[value.SkuID] = value.Count
|
|
||||||
citySkuIDs = append(citySkuIDs, value.SkuID)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
//获取本店商品总销量
|
|
||||||
storeSkuSalesCntMap := make(map[int]int)
|
|
||||||
storeSkuSalesCntList, err := dao.GetSkuSalesCntList(db, storeID, cityCode, DayNum, -1, citySkuIDs)
|
|
||||||
if err == nil {
|
|
||||||
for _, value := range storeSkuSalesCntList {
|
|
||||||
storeSkuSalesCntMap[value.SkuID] = value.Count
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
//获取本店商品差评数量
|
|
||||||
storeSkuBadCommentCntMap := make(map[int]int)
|
|
||||||
storeSkuBadCommentCntList, err := dao.GetSkuBadCommentCntList(db, storeID, DayNum)
|
|
||||||
if err == nil {
|
|
||||||
for _, value := range storeSkuBadCommentCntList {
|
|
||||||
storeSkuBadCommentCntMap[value.SkuID] = value.Count
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
//得到当前门店商品数据
|
|
||||||
storeSkuMapData := make(map[int]*dao.StoreSkuNameExt)
|
|
||||||
storeSkuData, err := cms.GetStoreSkus(ctx, storeID, citySkuIDs, true, "", true, false, map[string]interface{}{}, 0, -1)
|
|
||||||
if err == nil {
|
|
||||||
for _, value := range storeSkuData.SkuNames {
|
|
||||||
for _, skuInfo := range value.Skus {
|
|
||||||
storeSkuMapData[skuInfo.SkuID] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
//得到5KM内的所有门店
|
|
||||||
rangeStoreList := GetRangeStoreList(storeID, curStoreInfo.FloatLng, curStoreInfo.FloatLat, SaleSkuCheckRange, storeList)
|
|
||||||
|
|
||||||
//得到5KM内的所有门店的商品的价格
|
|
||||||
allStoreSkus := make(map[int]map[int]int)
|
|
||||||
var locker sync.RWMutex
|
|
||||||
taskFunc := func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
|
||||||
storeInfo := batchItemList[0].(*cms.StoreExt)
|
|
||||||
storeID := storeInfo.ID
|
|
||||||
jxSkuInfoData, err := cms.GetStoreSkus(ctx, storeID, citySkuIDs, true, "", true, false, map[string]interface{}{}, 0, -1)
|
|
||||||
jxSkuPriceMapData := make(map[int]int)
|
|
||||||
for _, value := range jxSkuInfoData.SkuNames {
|
|
||||||
for _, skuInfo := range value.Skus {
|
|
||||||
jxSkuPriceMapData[skuInfo.SkuID] = skuInfo.BindPrice
|
|
||||||
}
|
|
||||||
}
|
|
||||||
locker.Lock()
|
|
||||||
defer locker.Unlock()
|
|
||||||
allStoreSkus[storeID] = jxSkuPriceMapData
|
|
||||||
return retVal, err
|
|
||||||
}
|
|
||||||
taskParallel := tasksch.NewParallelTask("得到所有门店商品", nil, ctx, taskFunc, rangeStoreList)
|
|
||||||
taskParallel.Run()
|
|
||||||
_, err = taskParallel.GetResult(0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
//计算商品的平均价格
|
|
||||||
skusTotalPrice := make(map[int]int)
|
|
||||||
skusCount := make(map[int]int)
|
|
||||||
skusAveragePrice := make(map[int]int)
|
|
||||||
for _, storeInfo := range rangeStoreList {
|
|
||||||
storeID := storeInfo.ID
|
|
||||||
storeSkuMapData := allStoreSkus[storeID]
|
|
||||||
for skuID, skuPrice := range storeSkuMapData {
|
|
||||||
skusTotalPrice[skuID] += skuPrice
|
|
||||||
skusCount[skuID]++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for id, totalPrice := range skusTotalPrice {
|
|
||||||
skusAveragePrice[id] = int(math.Round(float64(totalPrice) / float64(skusCount[id])))
|
|
||||||
}
|
|
||||||
|
|
||||||
//输出商品销量统计结果
|
|
||||||
skuAndNameMapData := make(map[int]*model.SkuAndName)
|
|
||||||
if len(storeSkuMapData) < len(citySkuIDs) {
|
|
||||||
skuAndNameList, err := dao.GetSkus(db, citySkuIDs, nil, nil, nil, nil)
|
|
||||||
if err == nil {
|
|
||||||
for _, value := range skuAndNameList {
|
|
||||||
skuAndNameMapData[value.ID] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, value := range citySkuSalesCntList {
|
|
||||||
skuID := value.SkuID
|
|
||||||
storeSkuSales := &model.StoreSkuSales{}
|
|
||||||
storeSkuSales.SkuID = skuID
|
|
||||||
storeSkuInfo := storeSkuMapData[skuID]
|
|
||||||
skuAndNameInfo := skuAndNameMapData[skuID]
|
|
||||||
if storeSkuInfo != nil {
|
|
||||||
skuName := storeSkuInfo.SkuName
|
|
||||||
skuInfo := storeSkuInfo.Skus[0]
|
|
||||||
storeSkuSales.SkuName = jxutils.ComposeSkuName(skuName.Prefix, skuName.Name, skuInfo.Comment, skuName.Unit, skuInfo.SkuSpecQuality, skuInfo.SkuSpecUnit, 0, skuName.ExPrefix, skuName.ExPrefixBegin, skuName.ExPrefixEnd)
|
|
||||||
storeSkuSales.SkuImage = storeSkuInfo.Img
|
|
||||||
storeSkuSales.SkuPrice = jxutils.IntPrice2StandardCurrencyString(int64(storeSkuInfo.Skus[0].BindPrice))
|
|
||||||
} else if skuAndNameInfo != nil {
|
|
||||||
skuNameList, err := dao.GetSkuNames(db, []int{skuAndNameInfo.NameID}, nil, "", false)
|
|
||||||
prefix := ""
|
|
||||||
if err == nil && len(skuNameList) > 0 {
|
|
||||||
storeSkuSales.SkuImage = skuNameList[0].Img
|
|
||||||
prefix = skuNameList[0].Prefix
|
|
||||||
}
|
|
||||||
storeSkuSales.SkuName = jxutils.ComposeSkuName(prefix, skuAndNameInfo.Name, skuAndNameInfo.Comment, skuAndNameInfo.Unit, skuAndNameInfo.SpecQuality, skuAndNameInfo.SpecUnit, 0, skuAndNameInfo.ExPrefix, skuAndNameInfo.ExPrefixBegin, skuAndNameInfo.ExPrefixEnd)
|
|
||||||
storeSkuSales.SkuPrice = "N/A"
|
|
||||||
} else {
|
|
||||||
storeSkuSales.SkuName = "N/A"
|
|
||||||
storeSkuSales.SkuPrice = "N/A"
|
|
||||||
}
|
|
||||||
storeSkuSales.SkuAvgPrice = jxutils.IntPrice2StandardCurrencyString(int64(skusAveragePrice[skuID]))
|
|
||||||
storeSkuSales.BadCommentCnt = storeSkuBadCommentCntMap[skuID]
|
|
||||||
storeSkuSales.StoreSkuSalesCnt = storeSkuSalesCntMap[skuID]
|
|
||||||
storeSkuSales.CitySkuSalesCnt = citySkuSalesCntMap[skuID]
|
|
||||||
outStoreSkuSales = append(outStoreSkuSales, storeSkuSales)
|
|
||||||
}
|
|
||||||
|
|
||||||
return outStoreSkuSales, err
|
|
||||||
}
|
|
||||||
@@ -1,285 +0,0 @@
|
|||||||
package report
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
"sort"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"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 []int, fromDate string, toDate string) (statisticsReportForOrdersList []*dao.StatisticsReportForOrdersList, err error) {
|
|
||||||
db := dao.GetDB()
|
|
||||||
fromDateParm := utils.Str2Time(fromDate)
|
|
||||||
toDateParm := utils.Str2Time(toDate)
|
|
||||||
//若时间间隔大于3个月则不允许查询
|
|
||||||
if math.Ceil(toDateParm.Sub(fromDateParm).Hours()/24) > 92 {
|
|
||||||
return nil, errors.New(fmt.Sprintf("查询间隔时间不允许大于3个月!: 时间范围:[%v] 至 [%v]", fromDate, toDate))
|
|
||||||
}
|
|
||||||
statisticsReportForOrdersList, err = dao.GetStatisticsReportForOrders(db, storeIDs, fromDateParm, toDateParm)
|
|
||||||
return statisticsReportForOrdersList, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetStatisticsReportForAfsOrders(ctx *jxcontext.Context, storeIDs []int, fromDate string, toDate string) (statisticsReportForOrdersList []*dao.StatisticsReportForOrdersList, err error) {
|
|
||||||
db := dao.GetDB()
|
|
||||||
fromDateParm := utils.Str2Time(fromDate)
|
|
||||||
toDateParm := utils.Str2Time(toDate)
|
|
||||||
//若时间间隔大于3个月则不允许查询
|
|
||||||
if math.Ceil(toDateParm.Sub(fromDateParm).Hours()/24) > 92 {
|
|
||||||
return nil, errors.New(fmt.Sprintf("查询间隔时间不允许大于3个月!: 时间范围:[%v] 至 [%v]", fromDate, toDate))
|
|
||||||
}
|
|
||||||
statisticsReportForOrdersList, err = dao.GetGetStatisticsReportForAfsOrders(db, storeIDs, fromDateParm, toDateParm)
|
|
||||||
return statisticsReportForOrdersList, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func StatisticsReportForStoreSkusPrice(ctx *jxcontext.Context, cityCodes, skuIDs []int, snapDate string, offset, pageSize int) (pagedInfo *model.PagedInfo, err error) {
|
|
||||||
var snapDateParam time.Time
|
|
||||||
db := dao.GetDB()
|
|
||||||
if snapDate != "" {
|
|
||||||
snapDateParam = utils.Str2Time(snapDate)
|
|
||||||
}
|
|
||||||
priceReferSnapshot, totalCount, err := dao.GetPriceReferSnapshot(db, cityCodes, skuIDs, 0, snapDateParam, offset, pageSize)
|
|
||||||
pagedInfo = &model.PagedInfo{
|
|
||||||
Data: priceReferSnapshot,
|
|
||||||
TotalCount: totalCount,
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func BeginSavePriceRefer(ctx *jxcontext.Context, cityCodes, skuIDs []int, isAsync, isContinueWhenError bool) (hint string, err error) {
|
|
||||||
var priceReferSnapshotList []*model.PriceReferSnapshot
|
|
||||||
db := dao.GetDB()
|
|
||||||
snapshotAt := utils.Time2Date(time.Now().AddDate(0, 0, -1))
|
|
||||||
dao.DeletePriceReferHistory(db, utils.Time2Date(snapshotAt.AddDate(0, 0, -7)))
|
|
||||||
priceReferSnapshotDelete := &model.PriceReferSnapshot{SnapshotAt: snapshotAt}
|
|
||||||
dao.DeleteEntity(db, priceReferSnapshotDelete, "SnapshotAt")
|
|
||||||
taskSeqFunc := func(task *tasksch.SeqTask, step int, params ...interface{}) (result interface{}, err error) {
|
|
||||||
switch step {
|
|
||||||
case 0:
|
|
||||||
priceReferSnapshot, err := dao.GetStatisticsReportForStoreSkusPrice(db, cityCodes, skuIDs)
|
|
||||||
if len(priceReferSnapshot) > 0 {
|
|
||||||
dao.Begin(db)
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil || err != nil {
|
|
||||||
dao.Rollback(db)
|
|
||||||
if r != nil {
|
|
||||||
panic(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
for _, v := range priceReferSnapshot {
|
|
||||||
dao.WrapAddIDCULDEntity(v, ctx.GetUserName())
|
|
||||||
v.SnapshotAt = snapshotAt
|
|
||||||
}
|
|
||||||
dao.CreateMultiEntities(db, priceReferSnapshot)
|
|
||||||
dao.Commit(db)
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
priceReferSnapshotList, err = dao.GetPriceReferSnapshotNoPage(db, nil, nil, nil, snapshotAt)
|
|
||||||
var (
|
|
||||||
citySkuMap = make(map[int]map[int][]int)
|
|
||||||
countryMap = make(map[int][]int)
|
|
||||||
resultMap = make(map[int]map[int]*model.PriceReferSnapshot)
|
|
||||||
resultCountryMap = make(map[int]*model.PriceReferSnapshot)
|
|
||||||
)
|
|
||||||
storeList, err := dao.GetStoreList(db, nil, nil, nil, nil, "")
|
|
||||||
if err != nil {
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
for _, v := range storeList {
|
|
||||||
if v.PayPercentage < 50 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var tList []*tStoreSkuBindAndSkuName
|
|
||||||
sql := `
|
|
||||||
SELECT DISTINCT b.city_code, a.store_id, Round(a.unit_price * IF(b.pay_percentage < 50 , 70, b.pay_percentage) / 100) AS unit_price, c.name_id
|
|
||||||
FROM store_sku_bind a
|
|
||||||
JOIN store b ON b.id = a.store_id AND b.deleted_at = ? AND b.status != ?
|
|
||||||
JOIN sku c ON c.id = a.sku_id
|
|
||||||
WHERE a.store_id = ?
|
|
||||||
AND c.name_id NOT IN(
|
|
||||||
SELECT b.name_id
|
|
||||||
FROM store_sku_bind a
|
|
||||||
JOIN sku b ON a.sku_id = b.id AND b.deleted_at = ?
|
|
||||||
WHERE a.deleted_at = ?
|
|
||||||
AND a.store_id = ?
|
|
||||||
AND b.name_id NOT IN(SELECT DISTINCT b.name_id
|
|
||||||
FROM store_sku_bind a
|
|
||||||
JOIN sku b ON a.sku_id = b.id AND b.deleted_at = ?
|
|
||||||
WHERE a.deleted_at = ?
|
|
||||||
AND a.store_id = ?
|
|
||||||
AND a.status = ?)
|
|
||||||
)
|
|
||||||
AND a.deleted_at = ?
|
|
||||||
`
|
|
||||||
sqlParams := []interface{}{
|
|
||||||
utils.DefaultTimeValue,
|
|
||||||
model.StoreStatusDisabled,
|
|
||||||
v.ID,
|
|
||||||
utils.DefaultTimeValue,
|
|
||||||
utils.DefaultTimeValue,
|
|
||||||
v.ID,
|
|
||||||
utils.DefaultTimeValue,
|
|
||||||
utils.DefaultTimeValue,
|
|
||||||
v.ID,
|
|
||||||
model.StoreSkuBindStatusNormal,
|
|
||||||
utils.DefaultTimeValue,
|
|
||||||
}
|
|
||||||
dao.GetRows(db, &tList, sql, sqlParams...)
|
|
||||||
skuNameMap := make(map[int][]int)
|
|
||||||
if len(tList) > 0 {
|
|
||||||
for _, vv := range tList {
|
|
||||||
skuNameMap[vv.NameID] = append(skuNameMap[vv.NameID], vv.UnitPrice)
|
|
||||||
countryMap[vv.NameID] = append(countryMap[vv.NameID], vv.UnitPrice)
|
|
||||||
}
|
|
||||||
if citySkuMap[v.CityCode] != nil {
|
|
||||||
for nameID, unitPriceList := range skuNameMap {
|
|
||||||
if citySkuMap[v.CityCode][nameID] != nil {
|
|
||||||
citySkuMap[v.CityCode][nameID] = append(citySkuMap[v.CityCode][nameID], unitPriceList...)
|
|
||||||
} else {
|
|
||||||
citySkuMap[v.CityCode][nameID] = unitPriceList
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
citySkuMap[v.CityCode] = skuNameMap
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for k, v := range countryMap {
|
|
||||||
var midUnitPrice int
|
|
||||||
var avgUnitPrice int
|
|
||||||
sort.Ints(v)
|
|
||||||
if len(v)%2 == 0 {
|
|
||||||
midUnitPrice = v[len(v)/2-1]
|
|
||||||
} else {
|
|
||||||
midUnitPrice = v[len(v)/2]
|
|
||||||
}
|
|
||||||
for _, vv := range v {
|
|
||||||
avgUnitPrice += vv
|
|
||||||
}
|
|
||||||
priceRefer := &model.PriceReferSnapshot{
|
|
||||||
MidUnitPrice: midUnitPrice,
|
|
||||||
MaxUnitPrice: v[len(v)-1],
|
|
||||||
MinUnitPrice: v[0],
|
|
||||||
AvgUnitPrice: avgUnitPrice / len(v),
|
|
||||||
}
|
|
||||||
resultCountryMap[k] = priceRefer
|
|
||||||
}
|
|
||||||
for k1, v := range citySkuMap {
|
|
||||||
skuNameMap := make(map[int]*model.PriceReferSnapshot)
|
|
||||||
for k2, _ := range v {
|
|
||||||
var midUnitPrice int
|
|
||||||
var avgUnitPrice int
|
|
||||||
sort.Ints(v[k2])
|
|
||||||
if len(v[k2])%2 == 0 {
|
|
||||||
midUnitPrice = v[k2][len(v[k2])/2-1]
|
|
||||||
} else {
|
|
||||||
midUnitPrice = v[k2][len(v[k2])/2]
|
|
||||||
}
|
|
||||||
for _, vv := range v[k2] {
|
|
||||||
avgUnitPrice += vv
|
|
||||||
}
|
|
||||||
skuNameMap[k2] = &model.PriceReferSnapshot{
|
|
||||||
MidUnitPrice: midUnitPrice,
|
|
||||||
MaxUnitPrice: v[k2][len(v[k2])-1],
|
|
||||||
MinUnitPrice: v[k2][0],
|
|
||||||
AvgUnitPrice: avgUnitPrice / len(v[k2]),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resultMap[k1] = skuNameMap
|
|
||||||
}
|
|
||||||
dao.Begin(db)
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil || err != nil {
|
|
||||||
dao.Rollback(db)
|
|
||||||
if r != nil {
|
|
||||||
panic(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
if len(priceReferSnapshotList) > 0 {
|
|
||||||
for _, v := range priceReferSnapshotList {
|
|
||||||
if v.CityCode == 0 {
|
|
||||||
if resultCountryMap[v.NameID] != nil {
|
|
||||||
v.MidUnitPrice = resultCountryMap[v.NameID].MidUnitPrice
|
|
||||||
v.MaxUnitPrice = resultCountryMap[v.NameID].MaxUnitPrice
|
|
||||||
v.AvgUnitPrice = resultCountryMap[v.NameID].AvgUnitPrice
|
|
||||||
v.MinUnitPrice = resultCountryMap[v.NameID].MinUnitPrice
|
|
||||||
dao.UpdateEntity(db, v, "MidUnitPrice", "MaxUnitPrice", "MinUnitPrice", "AvgUnitPrice")
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if resultMap[v.CityCode][v.NameID] != nil {
|
|
||||||
v.MidUnitPrice = resultMap[v.CityCode][v.NameID].MidUnitPrice
|
|
||||||
v.MaxUnitPrice = resultMap[v.CityCode][v.NameID].MaxUnitPrice
|
|
||||||
v.AvgUnitPrice = resultMap[v.CityCode][v.NameID].AvgUnitPrice
|
|
||||||
v.MinUnitPrice = resultMap[v.CityCode][v.NameID].MinUnitPrice
|
|
||||||
dao.UpdateEntity(db, v, "MidUnitPrice", "MaxUnitPrice", "MinUnitPrice", "AvgUnitPrice")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dao.Commit(db)
|
|
||||||
case 2:
|
|
||||||
dao.Begin(db)
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil || err != nil {
|
|
||||||
dao.Rollback(db)
|
|
||||||
if r != nil {
|
|
||||||
panic(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
if len(priceReferSnapshotList) > 0 {
|
|
||||||
for _, v := range priceReferSnapshotList {
|
|
||||||
result, _ := dao.GetPriceReferPrice(db, v.CityCode, v.SkuID, snapshotAt)
|
|
||||||
v.MaxPrice = result.MaxPrice
|
|
||||||
v.MinPrice = result.MinPrice
|
|
||||||
v.AvgPrice = result.AvgPrice
|
|
||||||
v.MidPrice = result.MidPrice
|
|
||||||
dao.UpdateEntity(db, v, "MidPrice", "MaxPrice", "MinPrice", "AvgPrice")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dao.Commit(db)
|
|
||||||
//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
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,44 +0,0 @@
|
|||||||
package tempop
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"git.rosy.net.cn/jx-callback/globals/api2"
|
|
||||||
"git.rosy.net.cn/jx-callback/globals/testinit"
|
|
||||||
|
|
||||||
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/ebai"
|
|
||||||
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/elm"
|
|
||||||
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/jd"
|
|
||||||
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/mtwm"
|
|
||||||
_ "git.rosy.net.cn/jx-callback/business/partner/purchase/weimob/wsc"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
testinit.Init()
|
|
||||||
api2.Init()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestJdStoreInfo1125(t *testing.T) {
|
|
||||||
_, err := JdStoreInfo1125()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Testaa(t *testing.T) {
|
|
||||||
request, _ := http.NewRequest(http.MethodGet, "https://stores.shop.jd.com/stores/updateStoreStatus?storeId=24332466&storeStatus=1", nil)
|
|
||||||
c := &http.Cookie{
|
|
||||||
Name: "thor",
|
|
||||||
Value: "80FAF09E9A09B6E618A68057BDFCFCB8C86E8252DC9F7D3B34572625904FBA0AB6BF053A5325612EC0407791BB05F5301356E71E8B282C40C06D0B5DF3439DEECB102A78FAFF7AC0FC4E2D1FA8DD8BBAE1A011E50B5C74F1870AD982D7BF453F470F31F2241B73AC4C25485025C2ABEBC8A538AF7257824D2FAEE300A1435175B0B451FB5C19B78D729FC83152CA3BAF",
|
|
||||||
}
|
|
||||||
request.AddCookie(c)
|
|
||||||
client := &http.Client{}
|
|
||||||
fmt.Println("test1", request.URL)
|
|
||||||
response, _ := client.Do(request)
|
|
||||||
defer response.Body.Close()
|
|
||||||
bodyData, _ := ioutil.ReadAll(response.Body)
|
|
||||||
fmt.Println("test1", string(bodyData))
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
2
main.go
2
main.go
@@ -34,8 +34,6 @@ import (
|
|||||||
_ "git.rosy.net.cn/jx-callback/business/auth2/authprovider/password"
|
_ "git.rosy.net.cn/jx-callback/business/auth2/authprovider/password"
|
||||||
_ "git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin"
|
_ "git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin"
|
||||||
|
|
||||||
_ "git.rosy.net.cn/jx-callback/business/jxstore/act"
|
|
||||||
|
|
||||||
_ "git.rosy.net.cn/jx-callback/routers"
|
_ "git.rosy.net.cn/jx-callback/routers"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user