@@ -476,7 +476,7 @@ func CentralKitchenForSchoolDataStatisticsExport(req md.CentralKitchenForSchoolD | |||||
exportOutTradeNoList = append(exportOutTradeNoList, v.OutTradeNo) | exportOutTradeNoList = append(exportOutTradeNoList, v.OutTradeNo) | ||||
} | } | ||||
titleList = []string{startDate.Format("2006-01-02") + "~~" + endDate.Format("2006-01-02") + " 退款申请表"} | |||||
titleList = []string{startDate.Format("2006-01-02") + "~~" + endDate.Format("2006-01-02") + " 订单表"} | |||||
xlsx.SetSheetRow("Sheet1", "A1", &titleList) | xlsx.SetSheetRow("Sheet1", "A1", &titleList) | ||||
titleList = []string{"订单号", "学生姓名", "学校", "年级", "班级", "家长电话", "预定日期", "预定天数", "订单价格", "支付时间", "订单状态"} | titleList = []string{"订单号", "学生姓名", "学校", "年级", "班级", "家长电话", "预定日期", "预定天数", "订单价格", "支付时间", "订单状态"} | ||||
xlsx.SetSheetRow("Sheet1", "A2", &titleList) | xlsx.SetSheetRow("Sheet1", "A2", &titleList) | ||||
@@ -1438,7 +1438,7 @@ func CentralKitchenForSchoolDataStatisticsExport(req md.CentralKitchenForSchoolD | |||||
list[v.Enterprise.Name] += count | list[v.Enterprise.Name] += count | ||||
} | } | ||||
titleList = []string{startDate.Format("2006-01-02") + "~~" + endDate.Format("2006-01-02") + " 收款统计表"} | |||||
titleList = []string{startDate.Format("2006-01-02") + "~~" + endDate.Format("2006-01-02") + " 预定数量统计表"} | |||||
xlsx.SetSheetRow("Sheet1", "A1", &titleList) | xlsx.SetSheetRow("Sheet1", "A1", &titleList) | ||||
titleList = []string{"学校名称", "预定总数"} | titleList = []string{"学校名称", "预定总数"} | ||||
xlsx.SetSheetRow("Sheet1", "A2", &titleList) | xlsx.SetSheetRow("Sheet1", "A2", &titleList) | ||||
@@ -1454,10 +1454,14 @@ func CentralKitchenForSchoolDataStatisticsExport(req md.CentralKitchenForSchoolD | |||||
xlsx.SetColWidth("Sheet1", "A", "B", 40) | xlsx.SetColWidth("Sheet1", "A", "B", 40) | ||||
j := 3 //表头前两行用了,只能从第三行开始 | j := 3 //表头前两行用了,只能从第三行开始 | ||||
total := int64(0) | |||||
for k, v := range list { | for k, v := range list { | ||||
xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{k, v}) | xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{k, v}) | ||||
total += v | |||||
j++ | j++ | ||||
} | } | ||||
xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{ | |||||
"合计", total}) | |||||
//将文件保存至服务器 | //将文件保存至服务器 | ||||
xlsx.SaveAs("./static" + downloadPath) | xlsx.SaveAs("./static" + downloadPath) | ||||
break | break | ||||
@@ -63,6 +63,20 @@ func CentralKitchenForSchoolOrderList(c *gin.Context) { | |||||
"value": enum.CentralKitchenForSchoolPackageOrdOrdStateForComplete, | "value": enum.CentralKitchenForSchoolPackageOrdOrdStateForComplete, | ||||
}, | }, | ||||
}, | }, | ||||
"state_list": []map[string]interface{}{ | |||||
{ | |||||
"name": enum.CentralKitchenForSchoolPackageOrdState.String(enum.CentralKitchenForSchoolPackageOrdStateForWait), | |||||
"value": enum.CentralKitchenForSchoolPackageOrdStateForWait, | |||||
}, | |||||
{ | |||||
"name": enum.CentralKitchenForSchoolPackageOrdState.String(enum.CentralKitchenForSchoolPackageOrdStateForSuccess), | |||||
"value": enum.CentralKitchenForSchoolPackageOrdStateForSuccess, | |||||
}, | |||||
{ | |||||
"name": enum.CentralKitchenForSchoolPackageOrdState.String(enum.CentralKitchenForSchoolPackageOrdStateForFail), | |||||
"value": enum.CentralKitchenForSchoolPackageOrdStateForFail, | |||||
}, | |||||
}, | |||||
"kind_list": []map[string]string{ | "kind_list": []map[string]string{ | ||||
{ | { | ||||
"name": "按学期购买", | "name": "按学期购买", | ||||
@@ -94,6 +94,7 @@ func UserInfo(c *gin.Context) { | |||||
e.OutErr(c, e.ERR, "当前学校暂未完成《一脸通行入驻》") | e.OutErr(c, e.ERR, "当前学校暂未完成《一脸通行入驻》") | ||||
return | return | ||||
} | } | ||||
info = &model.SelfSupportForUserFaceInfo{ | info = &model.SelfSupportForUserFaceInfo{ | ||||
EnterpriseId: v.UserIdentity.EnterpriseId, | EnterpriseId: v.UserIdentity.EnterpriseId, | ||||
UserIdentityId: v.UserIdentity.Id, | UserIdentityId: v.UserIdentity.Id, | ||||
@@ -0,0 +1,19 @@ | |||||
package db | |||||
import ( | |||||
"applet/app/db/model" | |||||
"applet/app/utils/logx" | |||||
_ "github.com/go-sql-driver/mysql" | |||||
"xorm.io/xorm" | |||||
) | |||||
// 获取自动任务队列 | |||||
func MapCrontabCfg(eg *xorm.Engine) *[]model.CronTask { | |||||
var c []model.CronTask | |||||
// 数据库查询如果有下划线会认为是一个任意字符 | |||||
if err := eg.Where("`key` LIKE 'cron\\_%' AND val != ''").Cols("`key`,`val`").Find(&c); err != nil || len(c) == 0 { | |||||
logx.Warn(err) | |||||
return nil | |||||
} | |||||
return &c | |||||
} |
@@ -0,0 +1,7 @@ | |||||
package model | |||||
type CronTask struct { | |||||
Key string `json:"key" xorm:"not null pk comment('键') VARCHAR(64)"` | |||||
Val string `json:"val" xorm:"not null comment('值') TEXT"` | |||||
Memo string `json:"memo" xorm:"not null default '' comment('备注') VARCHAR(255)"` | |||||
} |
@@ -1,8 +1,10 @@ | |||||
package task | package task | ||||
import ( | import ( | ||||
"applet/app/admin/db/model" | |||||
"applet/app/db" | |||||
"applet/app/db/model" | |||||
taskMd "applet/app/task/md" | taskMd "applet/app/task/md" | ||||
"fmt" | |||||
"time" | "time" | ||||
"applet/app/utils/logx" | "applet/app/utils/logx" | ||||
@@ -11,15 +13,13 @@ import ( | |||||
) | ) | ||||
var ( | var ( | ||||
timer *cron.Cron | |||||
jobs = map[string]func(*xorm.Engine, string){} | |||||
baseEntryId cron.EntryID | |||||
entryIds []cron.EntryID | |||||
taskCfgList map[string]*[]model.SysCfg | |||||
ch = make(chan int, 30) | |||||
workerNum = 15 // 智盟跟单并发数量 | |||||
otherCh = make(chan int, 30) | |||||
otherWorkerNum = 18 // 淘宝, 苏宁, 考拉并发量 | |||||
timer *cron.Cron | |||||
jobs = map[string]func(*xorm.Engine){} | |||||
baseEntryId cron.EntryID | |||||
entryIds []cron.EntryID | |||||
taskCfgList *[]model.CronTask | |||||
ch = make(chan int, 30) | |||||
workerNum = 15 // 智盟跟单并发数量 | |||||
) | ) | ||||
func Init() { | func Init() { | ||||
@@ -28,7 +28,7 @@ func Init() { | |||||
var err error | var err error | ||||
timer = cron.New() | timer = cron.New() | ||||
// reload为初始化数据库方法 | // reload为初始化数据库方法 | ||||
if baseEntryId, err = timer.AddFunc("@every 15m", reload); err != nil { | |||||
if baseEntryId, err = timer.AddFunc("@every 30m", reload); err != nil { | |||||
_ = logx.Fatal(err) | _ = logx.Fatal(err) | ||||
} | } | ||||
} | } | ||||
@@ -40,9 +40,10 @@ func Run() { | |||||
} | } | ||||
func reload() { | func reload() { | ||||
// 重新初始化数据库 | |||||
if len(taskCfgList) > 0 { | |||||
taskCfgList = db.MapCrontabCfg(db.Db) | |||||
if len(*taskCfgList) > 0 { | |||||
// 删除原有所有任务 | // 删除原有所有任务 | ||||
if len(entryIds) > 0 { | if len(entryIds) > 0 { | ||||
for _, v := range entryIds { | for _, v := range entryIds { | ||||
@@ -57,27 +58,24 @@ func reload() { | |||||
err error | err error | ||||
) | ) | ||||
// 添加任务 | // 添加任务 | ||||
for dbName, v := range taskCfgList { | |||||
for _, vv := range *v { | |||||
if _, ok := jobs[vv.Key]; ok && vv.Val != "" { | |||||
// fmt.Println(vv.Val) | |||||
if entryId, err = timer.AddFunc(vv.Val, doTask(dbName, vv.Key)); err == nil { | |||||
entryIds = append(entryIds, entryId) | |||||
} | |||||
for _, v := range *taskCfgList { | |||||
if _, ok := jobs[v.Key]; ok && v.Val != "" { | |||||
fmt.Println(v.Val) | |||||
if entryId, err = timer.AddFunc(v.Val, doTask(v.Key)); err == nil { | |||||
entryIds = append(entryIds, entryId) | |||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
func doTask(dbName, fnName string) func() { | |||||
func doTask(fnName string) func() { | |||||
return func() { | return func() { | ||||
begin := time.Now().Local() | begin := time.Now().Local() | ||||
jobs[fnName](db.Db) | |||||
end := time.Now().Local() | end := time.Now().Local() | ||||
logx.Infof( | logx.Infof( | ||||
"[%s] AutoTask <%s> started at <%s>, ended at <%s> duration <%s>", | "[%s] AutoTask <%s> started at <%s>, ended at <%s> duration <%s>", | ||||
dbName, | |||||
fnName, | fnName, | ||||
begin.Format("2006-01-02 15:04:05.000"), | begin.Format("2006-01-02 15:04:05.000"), | ||||
end.Format("2006-01-02 15:04:05.000"), | end.Format("2006-01-02 15:04:05.000"), | ||||
@@ -88,5 +86,5 @@ func doTask(dbName, fnName string) func() { | |||||
// 增加自动任务队列 | // 增加自动任务队列 | ||||
func initTasks() { | func initTasks() { | ||||
jobs[taskMd.MallCronOrderCancel] = taskCancelOrder // 取消订单 | |||||
jobs[taskMd.SyncCentralKitchenForSchoolPackageOrdState] = taskSyncCentralKitchenForSchoolPackageOrdState | |||||
} | } |
@@ -1,5 +1,5 @@ | |||||
package md | package md | ||||
const ( | const ( | ||||
MallCronOrderCancel = "mall_cron_order_cancel" // 取消订单任务 | |||||
SyncCentralKitchenForSchoolPackageOrdState = "cron_sync_central_kitchen_for_school_package_ord_state" //更新央厨订单支付状态 | |||||
) | ) |
@@ -1,64 +1,58 @@ | |||||
package svc | package svc | ||||
import ( | import ( | ||||
"applet/app/db" | |||||
"applet/app/db/model" | |||||
"applet/app/enum" | |||||
"applet/app/utils" | "applet/app/utils" | ||||
"applet/app/utils/logx" | "applet/app/utils/logx" | ||||
"errors" | |||||
"fmt" | "fmt" | ||||
"time" | "time" | ||||
"xorm.io/xorm" | "xorm.io/xorm" | ||||
) | ) | ||||
func CancelOrder(eg *xorm.Engine, dbName string) { | |||||
fmt.Println("cancel order...") | |||||
func SyncCentralKitchenForSchoolPackageOrdState(eg *xorm.Engine) { | |||||
fmt.Println("sync central_kitchen_for_school_package_ord state...") | |||||
defer func() { | defer func() { | ||||
if err := recover(); err != nil { | if err := recover(); err != nil { | ||||
_ = logx.Error(err) | _ = logx.Error(err) | ||||
} | } | ||||
}() | }() | ||||
timeStr, err := getCancelCfg(eg, dbName) | |||||
if err != nil { | |||||
fmt.Println(err.Error()) | |||||
return | |||||
} | |||||
now := time.Now() | now := time.Now() | ||||
// x 分钟后取消订单 | |||||
expTime := now.Add(-time.Hour * time.Duration(utils.StrToInt64(timeStr))) | |||||
//TODO:: 20 分钟后 取消订单 | |||||
expTime := now.Add(-time.Minute * time.Duration(20)) | |||||
expTimeStr := utils.Time2String(expTime, "") | expTimeStr := utils.Time2String(expTime, "") | ||||
page := 1 | |||||
for { | |||||
isEmpty, err := handleOnePage(eg, dbName, expTimeStr) | |||||
if err != nil { | |||||
_ = logx.Error(err) | |||||
break | |||||
} | |||||
if isEmpty { | |||||
break | |||||
} | |||||
if page > 100 { | |||||
break | |||||
} | |||||
page += 1 | |||||
centralKitchenForSchoolPackageOrd := new(model.CentralKitchenForSchoolPackageOrd) | |||||
centralKitchenForSchoolPackageOrd.State = enum.CentralKitchenForSchoolPackageOrdStateForFail | |||||
affected, err := eg.Where("state =?", enum.CentralKitchenForSchoolPackageOrdStateForWait).And("create_at <= ?", expTimeStr). | |||||
Cols("state").Update(centralKitchenForSchoolPackageOrd) | |||||
if err != nil { | |||||
_ = logx.Error(err) | |||||
fmt.Println(">>>>>>>>SyncCentralKitchenForSchoolPackageOrdState_Err<<<<<<<<<<<<<<", err.Error()) | |||||
} | } | ||||
fmt.Println("SyncCentralKitchenForSchoolPackageOrdState_Affected>>>>>>>>>>>>>>>", affected) | |||||
return | |||||
//page := 1 | |||||
// | |||||
//for { | |||||
// isEmpty, err := handleOnePage(eg, expTimeStr) | |||||
// if err != nil { | |||||
// _ = logx.Error(err) | |||||
// break | |||||
// } | |||||
// if isEmpty { | |||||
// break | |||||
// } | |||||
// | |||||
// if page > 100 { | |||||
// break | |||||
// } | |||||
// | |||||
// page += 1 | |||||
//} | |||||
} | } | ||||
func handleOnePage(eg *xorm.Engine, dbName, expTimeStr string) (isEmpty bool, err error) { | |||||
return false, nil | |||||
} | |||||
func getCancelCfg(eg *xorm.Engine, masterId string) (string, error) { | |||||
cfg := db.SysCfgGetWithDb(eg, masterId, "order_expiration_time") | |||||
func handleOnePage(eg *xorm.Engine, expTimeStr string) (isEmpty bool, err error) { | |||||
if cfg == "" { | |||||
return "", errors.New("order_expiration_time no found") | |||||
} | |||||
return cfg, nil | |||||
return false, nil | |||||
} | } |
@@ -8,7 +8,7 @@ import ( | |||||
) | ) | ||||
// 取消订单 | // 取消订单 | ||||
func taskCancelOrder(eg *xorm.Engine, dbName string) { | |||||
func taskSyncCentralKitchenForSchoolPackageOrdState(eg *xorm.Engine) { | |||||
for { | for { | ||||
if len(ch) > workerNum { | if len(ch) > workerNum { | ||||
time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000))) | time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000))) | ||||
@@ -18,6 +18,6 @@ func taskCancelOrder(eg *xorm.Engine, dbName string) { | |||||
} | } | ||||
START: | START: | ||||
ch <- 1 | ch <- 1 | ||||
svc.CancelOrder(eg, dbName) | |||||
svc.SyncCentralKitchenForSchoolPackageOrdState(eg) | |||||
<-ch | <-ch | ||||
} | } |