@@ -476,7 +476,7 @@ func CentralKitchenForSchoolDataStatisticsExport(req md.CentralKitchenForSchoolD | |||
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) | |||
titleList = []string{"订单号", "学生姓名", "学校", "年级", "班级", "家长电话", "预定日期", "预定天数", "订单价格", "支付时间", "订单状态"} | |||
xlsx.SetSheetRow("Sheet1", "A2", &titleList) | |||
@@ -1438,7 +1438,7 @@ func CentralKitchenForSchoolDataStatisticsExport(req md.CentralKitchenForSchoolD | |||
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) | |||
titleList = []string{"学校名称", "预定总数"} | |||
xlsx.SetSheetRow("Sheet1", "A2", &titleList) | |||
@@ -1454,10 +1454,14 @@ func CentralKitchenForSchoolDataStatisticsExport(req md.CentralKitchenForSchoolD | |||
xlsx.SetColWidth("Sheet1", "A", "B", 40) | |||
j := 3 //表头前两行用了,只能从第三行开始 | |||
total := int64(0) | |||
for k, v := range list { | |||
xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{k, v}) | |||
total += v | |||
j++ | |||
} | |||
xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{ | |||
"合计", total}) | |||
//将文件保存至服务器 | |||
xlsx.SaveAs("./static" + downloadPath) | |||
break | |||
@@ -63,6 +63,20 @@ func CentralKitchenForSchoolOrderList(c *gin.Context) { | |||
"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{ | |||
{ | |||
"name": "按学期购买", | |||
@@ -94,6 +94,7 @@ func UserInfo(c *gin.Context) { | |||
e.OutErr(c, e.ERR, "当前学校暂未完成《一脸通行入驻》") | |||
return | |||
} | |||
info = &model.SelfSupportForUserFaceInfo{ | |||
EnterpriseId: v.UserIdentity.EnterpriseId, | |||
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 | |||
import ( | |||
"applet/app/admin/db/model" | |||
"applet/app/db" | |||
"applet/app/db/model" | |||
taskMd "applet/app/task/md" | |||
"fmt" | |||
"time" | |||
"applet/app/utils/logx" | |||
@@ -11,15 +13,13 @@ import ( | |||
) | |||
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() { | |||
@@ -28,7 +28,7 @@ func Init() { | |||
var err error | |||
timer = cron.New() | |||
// reload为初始化数据库方法 | |||
if baseEntryId, err = timer.AddFunc("@every 15m", reload); err != nil { | |||
if baseEntryId, err = timer.AddFunc("@every 30m", reload); err != nil { | |||
_ = logx.Fatal(err) | |||
} | |||
} | |||
@@ -40,9 +40,10 @@ func Run() { | |||
} | |||
func reload() { | |||
// 重新初始化数据库 | |||
if len(taskCfgList) > 0 { | |||
taskCfgList = db.MapCrontabCfg(db.Db) | |||
if len(*taskCfgList) > 0 { | |||
// 删除原有所有任务 | |||
if len(entryIds) > 0 { | |||
for _, v := range entryIds { | |||
@@ -57,27 +58,24 @@ func reload() { | |||
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() { | |||
begin := time.Now().Local() | |||
jobs[fnName](db.Db) | |||
end := time.Now().Local() | |||
logx.Infof( | |||
"[%s] AutoTask <%s> started at <%s>, ended at <%s> duration <%s>", | |||
dbName, | |||
fnName, | |||
begin.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() { | |||
jobs[taskMd.MallCronOrderCancel] = taskCancelOrder // 取消订单 | |||
jobs[taskMd.SyncCentralKitchenForSchoolPackageOrdState] = taskSyncCentralKitchenForSchoolPackageOrdState | |||
} |
@@ -1,5 +1,5 @@ | |||
package md | |||
const ( | |||
MallCronOrderCancel = "mall_cron_order_cancel" // 取消订单任务 | |||
SyncCentralKitchenForSchoolPackageOrdState = "cron_sync_central_kitchen_for_school_package_ord_state" //更新央厨订单支付状态 | |||
) |
@@ -1,64 +1,58 @@ | |||
package svc | |||
import ( | |||
"applet/app/db" | |||
"applet/app/db/model" | |||
"applet/app/enum" | |||
"applet/app/utils" | |||
"applet/app/utils/logx" | |||
"errors" | |||
"fmt" | |||
"time" | |||
"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() { | |||
if err := recover(); err != nil { | |||
_ = logx.Error(err) | |||
} | |||
}() | |||
timeStr, err := getCancelCfg(eg, dbName) | |||
if err != nil { | |||
fmt.Println(err.Error()) | |||
return | |||
} | |||
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, "") | |||
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 { | |||
if len(ch) > workerNum { | |||
time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000))) | |||
@@ -18,6 +18,6 @@ func taskCancelOrder(eg *xorm.Engine, dbName string) { | |||
} | |||
START: | |||
ch <- 1 | |||
svc.CancelOrder(eg, dbName) | |||
svc.SyncCentralKitchenForSchoolPackageOrdState(eg) | |||
<-ch | |||
} |