768 lines
25 KiB
Go
768 lines
25 KiB
Go
package cms
|
||
|
||
import (
|
||
"fmt"
|
||
"math"
|
||
"strings"
|
||
"time"
|
||
|
||
"git.rosy.net.cn/baseapi/platformapi/jdeclpapi"
|
||
|
||
"git.rosy.net.cn/jx-callback/globals"
|
||
|
||
"git.rosy.net.cn/jx-callback/business/jxstore/financial"
|
||
|
||
"git.rosy.net.cn/baseapi/utils"
|
||
|
||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||
|
||
"git.rosy.net.cn/jx-callback/globals/api"
|
||
|
||
"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 (
|
||
AcceptMaxCount = 2
|
||
CancelMaxCount = 5
|
||
|
||
waybillKgPrice = 200
|
||
)
|
||
|
||
var (
|
||
DayTimeBegin time.Time
|
||
DayTimeEnd time.Time
|
||
WeekTimeBegin time.Time
|
||
WeekTimeEnd time.Time
|
||
|
||
JobTimerMap map[int64]*time.Timer
|
||
JobAuditTimerMap map[int64]*time.Timer
|
||
)
|
||
|
||
func init() {
|
||
DayTimeBegin = utils.Str2Time(utils.Time2Str(utils.Time2Date(time.Now())) + " 00:00:00")
|
||
DayTimeEnd = utils.Str2Time(utils.Time2Str(utils.Time2Date(time.Now())) + " 23:59:59")
|
||
WeekTimeBegin, WeekTimeEnd = getWeekTime()
|
||
|
||
JobTimerMap = make(map[int64]*time.Timer)
|
||
JobAuditTimerMap = make(map[int64]*time.Timer)
|
||
}
|
||
|
||
func getWeekTime() (weekTimeBegin, weekTimeEnd time.Time) {
|
||
offset := int(time.Now().Weekday() - 1)
|
||
if offset == -1 {
|
||
offset = -6
|
||
}
|
||
weekTimeBegin = time.Now().AddDate(0, 0, offset)
|
||
weekTimeEnd = weekTimeBegin.AddDate(0, 0, 7)
|
||
return weekTimeBegin, weekTimeEnd
|
||
}
|
||
|
||
func PublishJob(ctx *jxcontext.Context, job *model.Job) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
//需根据任务类型做一些参数判断,比如门店商品链接,地址
|
||
// switch job.JobCategoryID {
|
||
// case 1:
|
||
// }
|
||
if ctx.GetUserID() != job.UserID {
|
||
return fmt.Errorf("用户信息已过期,请重新登录!")
|
||
}
|
||
//发布任务要扣除任务总额的保证金,不够扣就要进行充值
|
||
userBill, err := dao.GetUserBill(db, job.UserID, "")
|
||
if userBill == nil {
|
||
return fmt.Errorf("未查询到该用户的账单!")
|
||
}
|
||
job.TotalPrice = job.Count * job.AvgPrice
|
||
if userBill.AccountBalance < job.TotalPrice {
|
||
job.Status = model.JobStatusFailed
|
||
} else {
|
||
job.Status = model.JobStatusDoing
|
||
}
|
||
if job.Count <= 0 {
|
||
return fmt.Errorf("任务数量不能为0!")
|
||
}
|
||
if job.UserID == "" {
|
||
return fmt.Errorf("任务发起人不能为空!")
|
||
}
|
||
jobs, err := dao.GetJobsNoPage(db, []string{job.UserID}, nil, nil, DayTimeBegin, DayTimeEnd, false)
|
||
if len(jobs) > 0 {
|
||
members, err := dao.GetUserMember(db, job.UserID, model.MemberTypeNormal)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if len(members) <= 0 {
|
||
return fmt.Errorf("非会员一天只能发布一起任务,请确认!")
|
||
}
|
||
}
|
||
if job.Address != "" && (job.Lng == 0 || job.Lat == 0) {
|
||
lng, lat, err := api.AutonaviAPI.GetCoordinateFromAddressByPage(job.Address)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
job.Lng = jxutils.StandardCoordinate2Int(lng)
|
||
job.Lat = jxutils.StandardCoordinate2Int(lat)
|
||
}
|
||
dao.WrapAddIDCULEntity(job, ctx.GetUserName())
|
||
dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db)
|
||
panic(r)
|
||
}
|
||
}()
|
||
err = dao.CreateEntity(db, job)
|
||
for _, v := range job.JobSteps {
|
||
dao.WrapAddIDCULEntity(v, ctx.GetUserName())
|
||
v.JobID = job.ID
|
||
err = dao.CreateEntity(db, v)
|
||
}
|
||
for _, v := range job.JobImgs {
|
||
dao.WrapAddIDCULEntity(v, ctx.GetUserName())
|
||
v.JobID = job.ID
|
||
err = dao.CreateEntity(db, v)
|
||
}
|
||
if err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
//发布任务要扣除任务总额的保证金,不够扣就要进行充值
|
||
if err == nil && job.Status != model.JobStatusFailed {
|
||
if err = financial.AddExpendUpdateAccount(db, userBill, model.BillTypeDeposit, job.TotalPrice); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
}
|
||
dao.Commit(db)
|
||
return err
|
||
}
|
||
|
||
func CancelPublishJob(ctx *jxcontext.Context, jobID int) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
job := &model.Job{}
|
||
job.ID = jobID
|
||
err = dao.GetEntity(db, job)
|
||
if job.UserID == "" || job.Status == model.JobStatusFailed || job.Status == model.JobStatusOverdue || job.FinishedAt.Sub(time.Now()) <= 0 || job.SurplusCount <= 0 || job.LimitCountType <= 0 {
|
||
return fmt.Errorf("未找到该任务或该任务状态不正常,无法取消!")
|
||
}
|
||
//取消已发布的任务
|
||
userBill, err := dao.GetUserBill(db, job.UserID, "")
|
||
if userBill == nil {
|
||
return fmt.Errorf("未查询到该用户的账单!")
|
||
}
|
||
dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db)
|
||
panic(r)
|
||
}
|
||
}()
|
||
if err = financial.AddIncomeUpdateAccount(db, userBill, model.BillTypeJobCancelOverdue, job.SurplusCount*job.AvgPrice); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
//3、任务状态被取消
|
||
job.Status = model.JobStatusFailed
|
||
if _, err = dao.UpdateEntity(db, job, "Status"); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
dao.Commit(db)
|
||
return err
|
||
}
|
||
|
||
func GetJobs(ctx *jxcontext.Context, userIDs []string, categoryIDs, statuss, vendorIDs []int, includeStep bool, fromTime, toTime string, pageSize, offset int) (pagedInfo *model.PagedInfo, err error) {
|
||
return dao.GetJobs(dao.GetDB(), userIDs, categoryIDs, statuss, vendorIDs, includeStep, utils.Str2Time(fromTime), utils.Str2Time(toTime), pageSize, offset)
|
||
}
|
||
|
||
func AcceptJob(ctx *jxcontext.Context, jobID int) (errCode string, err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
userID = ctx.GetUserID()
|
||
num int
|
||
)
|
||
job := &model.Job{}
|
||
job.ID = jobID
|
||
err = dao.GetEntity(db, job)
|
||
if job.UserID == "" || job.Status == model.JobStatusFailed || job.Status == model.JobStatusOverdue || job.FinishedAt.Sub(time.Now()) <= 0 || job.SurplusCount <= 0 || job.LimitCountType <= 0 {
|
||
return errCode, fmt.Errorf("未找到该任务或该任务状态不正常,无法接单!")
|
||
}
|
||
num, err = checkJobOrders(db, 0, "<= "+utils.Int2Str(model.JobOrderStatusAccept), userID, utils.ZeroTimeValue, utils.ZeroTimeValue)
|
||
if num >= AcceptMaxCount {
|
||
return errCode, fmt.Errorf("每人最多接取" + utils.Int2Str(AcceptMaxCount) + "个任务,请核实!")
|
||
}
|
||
num, err = checkJobOrders(db, jobID, "<= "+utils.Int2Str(model.JobOrderStatusWaitAudit), userID, utils.ZeroTimeValue, utils.ZeroTimeValue)
|
||
if num > 0 {
|
||
return errCode, fmt.Errorf("您还有此任务未完成,请完成后再接取!")
|
||
}
|
||
// num, err = checkJobOrders(db, "= "+utils.Int2Str(model.JobOrderStatusAuditUnPass), userID, utils.ZeroTimeValue, utils.ZeroTimeValue)
|
||
// if num > 0 {
|
||
// return fmt.Errorf("您还有此任务未审核通过记录,可直接在未审核中重新提交!")
|
||
// }
|
||
switch job.LimitCountType {
|
||
case model.JobLimitCountTypePO:
|
||
num, err = checkJobOrders(db, jobID, "<> "+utils.Int2Str(model.JobOrderStatusCancel), userID, utils.ZeroTimeValue, utils.ZeroTimeValue)
|
||
if num > 0 {
|
||
return errCode, fmt.Errorf("此任务只支持每人做一次!")
|
||
}
|
||
case model.JobLimitCountTypePDO:
|
||
num, err = checkJobOrders(db, jobID, "<> "+utils.Int2Str(model.JobOrderStatusCancel), userID, DayTimeBegin, DayTimeEnd)
|
||
if num > 0 {
|
||
return errCode, fmt.Errorf("此任务只支持每人每天做一次!")
|
||
}
|
||
case model.JobLimitCountTypePWO:
|
||
num, err = checkJobOrders(db, jobID, "<> "+utils.Int2Str(model.JobOrderStatusCancel), userID, WeekTimeBegin, WeekTimeEnd)
|
||
if num > 0 {
|
||
return errCode, fmt.Errorf("此任务只支持每人每周做一次!")
|
||
}
|
||
case model.JobLimitCountTypeNoLimit:
|
||
default:
|
||
return errCode, fmt.Errorf("不支持的任务限次类型!%v", job.LimitCountType)
|
||
}
|
||
jobOrder := &model.JobOrder{
|
||
JobID: jobID,
|
||
JobOrderID: jxutils.GenJobOrderNo(),
|
||
UserID: ctx.GetUserID(),
|
||
// Status: model.JobOrderStatusAccept,
|
||
}
|
||
//美团会员任务
|
||
if jobID == model.JobIDMtMembers {
|
||
jobOrder.Status = model.JobOrderStatusSpec
|
||
} else {
|
||
jobOrder.Status = model.JobOrderStatusAccept
|
||
}
|
||
dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db)
|
||
panic(r)
|
||
}
|
||
}()
|
||
if err = dao.CreateEntity(db, jobOrder); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
//用户接受任务,任务剩余次数-1
|
||
job.SurplusCount -= 1
|
||
if _, err = dao.UpdateEntity(db, job, "SurplusCount"); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
dao.Commit(db)
|
||
//任务限时完成
|
||
defer func() {
|
||
timer := checkLimitJobOrders(db, job, jobOrder, model.JobTimerTypeAccept)
|
||
JobTimerMap[jobOrder.JobOrderID] = timer
|
||
}()
|
||
//特殊任务,如美团会员,是直接要支付
|
||
if jobID == model.JobIDMtMembers {
|
||
userBill, err := dao.GetUserBill(db, ctx.GetUserID(), "")
|
||
if err != nil {
|
||
return errCode, err
|
||
}
|
||
if userBill.AccountBalance < job.AvgPrice {
|
||
return model.ErrCodeAccountBalanceNotEnough, fmt.Errorf("用户余额不足,请充值!")
|
||
}
|
||
dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db)
|
||
panic(r)
|
||
}
|
||
}()
|
||
//账户支出
|
||
if err = financial.AddExpendUpdateAccount(db, userBill, model.BillTypeSpJob, job.AvgPrice); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
dao.Commit(db)
|
||
}
|
||
return errCode, err
|
||
}
|
||
|
||
func CancelAcceptJob(ctx *jxcontext.Context, jobID int, jobOrderID int64) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
jobOrder := &model.JobOrder{}
|
||
jobOrder.JobOrderID = jobOrderID
|
||
err = dao.GetEntity(db, jobOrder, "JobOrderID")
|
||
job := &model.Job{}
|
||
job.ID = jobID
|
||
err = dao.GetEntity(db, job)
|
||
dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db)
|
||
panic(r)
|
||
}
|
||
}()
|
||
//如果当前任务状态正常,剩余数量就加1
|
||
if job.Status > 0 {
|
||
job.SurplusCount += 1
|
||
if _, err = dao.UpdateEntity(db, job, "SurplusCount"); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
} else {
|
||
userBill, err := dao.GetUserBill(db, job.UserID, "")
|
||
if userBill == nil {
|
||
return fmt.Errorf("未查询到该用户的账单!")
|
||
}
|
||
//如果状态不正常(取消或者过期)就要把这一笔退回去
|
||
//2、账户收入
|
||
if err = financial.AddIncomeUpdateAccount(db, userBill, model.BillTypeJobCancelOverdue, job.AvgPrice); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
//3、任务订单状态被取消
|
||
jobOrder.Status = model.JobOrderStatusCancel
|
||
if _, err = dao.UpdateEntity(db, jobOrder, "Status"); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
}
|
||
dao.Commit(db)
|
||
return err
|
||
}
|
||
|
||
func checkJobOrders(db *dao.DaoDB, jobID int, statusCompareStr, userID string, fromTime, toTime time.Time) (num int, err error) {
|
||
jobOrders, err := dao.GetJobOrdersNoPage(db, jobID, 0, userID, statusCompareStr, fromTime, toTime, nil)
|
||
return len(jobOrders), err
|
||
}
|
||
|
||
func checkLimitJobOrders(db *dao.DaoDB, job *model.Job, jobOrder *model.JobOrder, jobTimerType int) (timer *time.Timer) {
|
||
//插到定时任务表里,主要是重启项目后的重启定时器用
|
||
jobTimer := &model.JobTimer{
|
||
JobID: job.ID,
|
||
JobOrderID: jobOrder.JobOrderID,
|
||
Type: jobTimerType,
|
||
Status: model.JobTimerStatusWait,
|
||
StartAt: jobOrder.CreatedAt,
|
||
LimitAt: job.JobLimitAt,
|
||
}
|
||
dao.WrapAddIDCULEntity(jobTimer, jxcontext.AdminCtx.GetUserName())
|
||
dao.CreateEntity(db, jobTimer)
|
||
switch jobTimerType {
|
||
case model.JobTimerTypeAccept:
|
||
timer = time.NewTimer(time.Hour * time.Duration(job.JobLimitAt))
|
||
case model.JobTimerTypeSubmit:
|
||
timer = time.NewTimer(time.Hour * time.Duration(job.AuditLimitAt))
|
||
}
|
||
utils.CallFuncAsync(func() {
|
||
select {
|
||
case <-timer.C:
|
||
switch jobTimerType {
|
||
case model.JobTimerTypeAccept:
|
||
UpdateLimitJobOrders(db, timer, job.ID, jobOrder, jobTimer)
|
||
case model.JobTimerTypeSubmit:
|
||
UpdateLimitAuditJobOrders(db, timer, job.ID, jobOrder, jobTimer)
|
||
}
|
||
}
|
||
})
|
||
return timer
|
||
}
|
||
|
||
func UpdateLimitJobOrders(db *dao.DaoDB, timer *time.Timer, jobID int, jobOrder *model.JobOrder, jobTimer *model.JobTimer) {
|
||
globals.SugarLogger.Debugf("updateLimitJobOrders jobID: %v, jobOrderID: %v", jobID, jobOrder.JobOrderID)
|
||
defer timer.Stop()
|
||
if jobOrder.Status > model.JobOrderStatusAccept {
|
||
return
|
||
}
|
||
jobOrder.Status = model.JobOrderStatusCancel
|
||
if _, err := dao.UpdateEntity(db, jobOrder, "Status"); err == nil {
|
||
jobTimer.Status = model.JobTimerStatusFinish
|
||
dao.UpdateEntity(db, jobTimer, "Status")
|
||
}
|
||
}
|
||
|
||
func UpdateLimitAuditJobOrders(db *dao.DaoDB, timer *time.Timer, jobID int, jobOrder *model.JobOrder, jobTimer *model.JobTimer) {
|
||
globals.SugarLogger.Debugf("checkLimitAuditJobOrders jobID: %v, jobOrderID: %v", jobID, jobOrder.JobOrderID)
|
||
defer timer.Stop()
|
||
if jobOrder.Status == model.JobOrderStatusWaitAudit {
|
||
err := AuditJob(jxcontext.AdminCtx, int(jobOrder.JobOrderID), model.JobOrderStatusAuditPass, "超时系统通过")
|
||
if err != nil {
|
||
globals.SugarLogger.Debugf("checkLimitAuditJobOrders err: %v jobID: %v, jobOrderID: %v", err, jobID, jobOrder.JobOrderID)
|
||
} else {
|
||
jobTimer.Status = model.JobTimerStatusFinish
|
||
dao.UpdateEntity(db, jobTimer, "Status")
|
||
}
|
||
}
|
||
}
|
||
|
||
func SubmitJob(ctx *jxcontext.Context, jobOrder *model.JobOrder) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
if jobOrder.JobID == 0 || jobOrder.JobOrderID == 0 {
|
||
return fmt.Errorf("传入数据有误!")
|
||
}
|
||
job := &model.Job{}
|
||
job.ID = jobOrder.JobID
|
||
err = dao.GetEntity(db, job)
|
||
jobOrder2 := &model.JobOrder{}
|
||
jobOrder2.JobOrderID = jobOrder.JobOrderID
|
||
err = dao.GetEntity(db, jobOrder2, "JobOrderID")
|
||
if jobOrder2.JobID == 0 {
|
||
return fmt.Errorf("未查询到相应的任务!")
|
||
}
|
||
if jobOrder2.Status >= model.JobOrderStatusWaitAudit {
|
||
return fmt.Errorf("任务订单状态有误!")
|
||
}
|
||
if ctx.GetUserID() != jobOrder2.UserID {
|
||
return fmt.Errorf("任务订单接收人有误!")
|
||
}
|
||
jobOrder2.Img = jobOrder.Img
|
||
jobOrder2.Content = jobOrder.Content
|
||
jobOrder2.SubmitAuditAt = time.Now()
|
||
jobOrder2.Status = model.JobOrderStatusWaitAudit
|
||
if _, err = dao.UpdateEntity(db, jobOrder2, "Img", "Content", "SubmitAuditAt", "Status"); err == nil {
|
||
//任务定时器停止
|
||
JobTimerMap[jobOrder2.JobOrderID].Stop()
|
||
//任务定时表状态完成
|
||
jobTimer := &model.JobTimer{
|
||
JobID: job.ID,
|
||
JobOrderID: jobOrder2.JobOrderID,
|
||
Type: model.JobTimerTypeAccept,
|
||
}
|
||
if err = dao.GetEntity(db, jobTimer, "JobID", "JobOrderID", "Type"); err == nil {
|
||
jobTimer.Status = model.JobTimerStatusFinish
|
||
dao.UpdateEntity(db, jobTimer, "Status")
|
||
}
|
||
//审核定时开启
|
||
timer := checkLimitJobOrders(db, job, jobOrder2, model.JobTimerTypeSubmit)
|
||
JobAuditTimerMap[jobOrder2.JobOrderID] = timer
|
||
}
|
||
return err
|
||
}
|
||
|
||
func AuditJob(ctx *jxcontext.Context, jobOrderID, status int, comment string) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
jobOrder := &model.JobOrder{}
|
||
jobOrder.JobOrderID = int64(jobOrderID)
|
||
err = dao.GetEntity(db, jobOrder, "JobOrderID")
|
||
job := &model.Job{}
|
||
job.ID = jobOrder.JobID
|
||
err = dao.GetEntity(db, job)
|
||
if ctx.GetUserID() != job.UserID {
|
||
return fmt.Errorf("任务发起人才能审核!")
|
||
}
|
||
//审核时,若此任务已过期或者已取消,不通过则应将此任务保证金退还给发起人,通过则应将单次任务保证金给接受人
|
||
//若此任务未过期,不通过则此任务剩余数量将+1,通过则应将单次任务保证金给接受人
|
||
jobOrder.Status = status
|
||
jobOrder.Comment = comment
|
||
jobOrder.AuditAt = time.Now()
|
||
jobOrder.LastOperator = ctx.GetUserName()
|
||
dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db)
|
||
panic(r)
|
||
}
|
||
}()
|
||
if _, err = dao.UpdateEntity(db, jobOrder, "Status", "Comment", "AuditAt", "LastOperator"); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
if status == model.JobOrderStatusAuditPass {
|
||
//接收人账户收入
|
||
userBillJobOrder, err := dao.GetUserBill(db, jobOrder.UserID, "")
|
||
if err = financial.AddIncomeUpdateAccount(db, userBillJobOrder, model.BillTypeJob, job.AvgPrice); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
} else {
|
||
if job.Status < 0 {
|
||
userBill, err := dao.GetUserBill(db, job.UserID, "")
|
||
if err = financial.AddIncomeUpdateAccount(db, userBill, model.BillTypeJobAuditUnPassWithCancelOverdue, job.AvgPrice); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
} else {
|
||
job.SurplusCount += 1
|
||
if _, err = dao.UpdateEntity(db, job, "SurplusCount"); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
}
|
||
}
|
||
dao.Commit(db)
|
||
//任务定时器停止
|
||
JobAuditTimerMap[int64(jobOrderID)].Stop()
|
||
//任务定时表状态完成
|
||
jobTimer := &model.JobTimer{
|
||
JobID: job.ID,
|
||
JobOrderID: jobOrder.JobOrderID,
|
||
Type: model.JobTimerTypeSubmit,
|
||
}
|
||
if err = dao.GetEntity(db, jobTimer, "JobID", "JobOrderID", "Type"); err == nil {
|
||
jobTimer.Status = model.JobTimerStatusFinish
|
||
dao.UpdateEntity(db, jobTimer, "Status")
|
||
}
|
||
return err
|
||
}
|
||
|
||
func RefreshJobStatus(ctx *jxcontext.Context) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
globals.SugarLogger.Debugf("RefreshJobStatus begin...")
|
||
jobs, err := dao.GetJobsNoPage(db, nil, nil, []int{model.JobStatusDoing}, utils.ZeroTimeValue, utils.ZeroTimeValue, false)
|
||
if err != nil {
|
||
globals.SugarLogger.Debugf("RefreshJobStatus err :%v", err)
|
||
return
|
||
}
|
||
for _, job := range jobs {
|
||
if time.Now().Sub(job.FinishedAt) >= 0 {
|
||
job.Status = model.JobStatusOverdue
|
||
dao.UpdateEntity(db, job, "Status")
|
||
}
|
||
}
|
||
globals.SugarLogger.Debugf("RefreshJobStatus end...")
|
||
return err
|
||
}
|
||
|
||
func ImprotMtMembers(ctx *jxcontext.Context, mtMembers []*model.MtMember) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
for _, v := range mtMembers {
|
||
v.ShortLink = v.URL[strings.LastIndex(v.URL, "/")+1 : len(v.URL)]
|
||
dao.WrapAddIDCULDEntity(v, ctx.GetUserName())
|
||
}
|
||
if err = dao.CreateMultiEntities(db, mtMembers); err == nil {
|
||
job := &model.Job{}
|
||
job.ID = model.JobIDMtMembers
|
||
dao.GetEntity(db, job)
|
||
if job != nil {
|
||
job.Count += len(mtMembers)
|
||
dao.UpdateEntity(db, job, "Count")
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func RechargeMtMembers(ctx *jxcontext.Context, phone int) (errCode string, err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
errCode, err = AcceptJob(ctx, model.JobIDMtMembers)
|
||
if errCode != "" {
|
||
return errCode, err
|
||
}
|
||
if err != nil {
|
||
return errCode, err
|
||
}
|
||
mtMember, err := dao.GetMtMember(db)
|
||
if mtMember == nil {
|
||
return errCode, fmt.Errorf("美团会员数量不足,请等待补充!")
|
||
}
|
||
if err != nil {
|
||
return errCode, err
|
||
}
|
||
if err = api.MtMemberAPI.RechargeExchange(phone, mtMember.ShortLink); err == nil {
|
||
mtMember.DeletedAt = time.Now()
|
||
dao.UpdateEntity(db, mtMember, "DeletedAt")
|
||
}
|
||
return errCode, err
|
||
}
|
||
|
||
func SendJdDelivery(ctx *jxcontext.Context, dOrder *model.DeliveryOrder) (errCode string, err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
errCode, err = AcceptJob(ctx, model.JobIDJdDelivery)
|
||
if errCode != "" {
|
||
return errCode, err
|
||
}
|
||
if err != nil {
|
||
return errCode, err
|
||
}
|
||
sendDeliveryList, _, err := dao.QueryUserDeliveryAddress(db, int64(dOrder.DeliverySendID), nil, 0, 0)
|
||
receiveDeliveryList, _, err := dao.QueryUserDeliveryAddress(db, int64(dOrder.DeliveryReceiveID), nil, 0, 0)
|
||
userBill, err := dao.GetUserBill(db, ctx.GetUserID(), "")
|
||
if err != nil {
|
||
return errCode, err
|
||
}
|
||
if userBill.AccountBalance < dOrder.PayPrice {
|
||
return model.ErrCodeAccountBalanceNotEnough, fmt.Errorf("用户余额不足,请充值!")
|
||
}
|
||
if len(sendDeliveryList) == 0 {
|
||
return errCode, fmt.Errorf("未找到寄件人地址!")
|
||
}
|
||
if len(receiveDeliveryList) == 0 {
|
||
return errCode, fmt.Errorf("未找到取件人地址!")
|
||
}
|
||
dao.WrapAddIDCULEntity(dOrder, ctx.GetUserName())
|
||
if vendorWaybillID, err := api.JdEclpAPI.WaybillReceive(&jdeclpapi.WaybillReceiveParam{
|
||
SalePlat: jdeclpapi.SalePlatSourceDelivery,
|
||
CustomerCode: jdeclpapi.CustomerCode,
|
||
OrderID: utils.Int64ToStr(jxutils.GenOrderNo()),
|
||
SenderName: sendDeliveryList[0].ConsigneeName,
|
||
SenderAddress: sendDeliveryList[0].Address + sendDeliveryList[0].DetailAddress,
|
||
SenderTel: sendDeliveryList[0].ConsigneeMobile,
|
||
ReceiveName: receiveDeliveryList[0].ConsigneeName,
|
||
ReceiveAddress: receiveDeliveryList[0].Address + receiveDeliveryList[0].DetailAddress,
|
||
ReceiveTel: receiveDeliveryList[0].ConsigneeMobile,
|
||
Weight: dOrder.Weight,
|
||
Vloumn: dOrder.Vloumn,
|
||
PackageCount: dOrder.PackageCount,
|
||
Description: dOrder.Description,
|
||
Aging: 5,
|
||
PromiseTimeType: 1, //特惠送
|
||
}); err == nil {
|
||
dOrder.VendorWaybillID = vendorWaybillID
|
||
} else {
|
||
return errCode, err
|
||
}
|
||
dOrder.Status = model.OrderStatusNew
|
||
dOrder.UserID = ctx.GetUserID()
|
||
dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db)
|
||
panic(r)
|
||
}
|
||
}()
|
||
if err = dao.CreateEntity(db, dOrder); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
//账户支出明细
|
||
if err = financial.AddExpendUpdateAccount(db, userBill, model.BillTypeSpJob, dOrder.PayPrice); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
dao.Commit(db)
|
||
return errCode, err
|
||
}
|
||
|
||
func CancelJdDelivery(ctx *jxcontext.Context, vendorWaybillID, reason string) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
dOrder = &model.DeliveryOrder{
|
||
VendorWaybillID: vendorWaybillID,
|
||
}
|
||
)
|
||
err = dao.GetEntity(db, dOrder, "VendorWaybillID")
|
||
userBill, err := dao.GetUserBill(db, ctx.GetUserID(), "")
|
||
dOrders, err := dao.GetDeliveryOrdersNoPage(db, []string{ctx.GetUserID()}, []int{model.OrderStatusCanceled}, DayTimeBegin, DayTimeEnd, nil)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if len(dOrders) > 0 {
|
||
return fmt.Errorf("抱歉,您已经在今天取消过京东物流订单!")
|
||
}
|
||
if dOrder.ID == 0 {
|
||
return fmt.Errorf("未找到该运单!")
|
||
}
|
||
if err = api.JdEclpAPI.CancelWayBill(&jdeclpapi.CancelWayBillParam{
|
||
WaybillCode: vendorWaybillID,
|
||
CustomerCode: jdeclpapi.CustomerCode,
|
||
Source: "JOS",
|
||
CancelReason: reason,
|
||
OperatorName: ctx.GetUserName(),
|
||
}); err != nil {
|
||
return err
|
||
}
|
||
dOrder.Status = model.OrderStatusCanceled
|
||
dOrder.OrderFinishedAt = time.Now()
|
||
dOrder.Comment = reason
|
||
dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db)
|
||
panic(r)
|
||
}
|
||
}()
|
||
if _, err = dao.UpdateEntity(db, dOrder, "Status", "OrderFinishedAt", "Comment"); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
if err = financial.AddIncomeUpdateAccount(db, userBill, model.BillTypeSpJob, dOrder.PayPrice); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
dao.Commit(db)
|
||
return err
|
||
}
|
||
|
||
func GetJdDelivery(ctx *jxcontext.Context, status int, fromTime, toTime string, pageSize, offset int) (pagedInfo *model.PagedInfo, err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
return dao.GetDeliveryOrders(db, []string{ctx.GetUserID()}, []int{status}, utils.Str2Time(fromTime), utils.Str2Time(toTime), pageSize, offset)
|
||
}
|
||
|
||
func GetJdDeliveryDetail(ctx *jxcontext.Context, vendorWaybillID string) (queryDynamicTraceInfo []*jdeclpapi.QueryDynamicTraceInfoResult, err error) {
|
||
return api.JdEclpAPI.QueryDynamicTraceInfo(vendorWaybillID)
|
||
}
|
||
|
||
func CheckJdDeliveryWeight(ctx *jxcontext.Context) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
userBill, err := dao.GetUserBill(db, ctx.GetUserID(), "")
|
||
if userBill.AccountBalance < 0 {
|
||
return fmt.Errorf("您有京东物流订单实际超重,请支付欠款!")
|
||
}
|
||
deliveryOrders, err := dao.GetDeliveryOrdersNoPage(db, []string{ctx.GetUserID()}, nil, utils.ZeroTimeValue, utils.ZeroTimeValue, []int{0})
|
||
if err != nil {
|
||
return err
|
||
}
|
||
task := tasksch.NewParallelTask("CheckJdDeliveryWeight", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(true), ctx,
|
||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||
deliveryOrder := batchItemList[0].(*model.DeliveryOrder)
|
||
waybill, err := api.JdEclpAPI.WaybillQuery(deliveryOrder.VendorWaybillID)
|
||
if err == nil {
|
||
return retVal, err
|
||
}
|
||
if waybill.DeliveryID == "" {
|
||
return retVal, err
|
||
}
|
||
if waybill.DeliveryID == deliveryOrder.VendorWaybillID {
|
||
if waybill.Weight > 3 && math.Floor(deliveryOrder.Weight) < math.Floor(waybill.Weight) {
|
||
diffPrice := (math.Floor(waybill.Weight) - math.Floor(deliveryOrder.Weight)) * waybillKgPrice
|
||
if err != nil {
|
||
return retVal, err
|
||
}
|
||
if err = financial.AddExpendUpdateAccount(db, userBill, model.BillTypeJdWaybillOverWeight, utils.Float64TwoInt(diffPrice)); err != nil {
|
||
return retVal, err
|
||
}
|
||
}
|
||
}
|
||
return retVal, err
|
||
}, deliveryOrders)
|
||
tasksch.HandleTask(task, nil, true).Run()
|
||
task.GetID()
|
||
return err
|
||
}
|
||
|
||
func ResetJobTimers() {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
jobTimers, err := dao.GetJobTimers(db, model.JobTimerStatusWait)
|
||
if err != nil {
|
||
return
|
||
}
|
||
task := tasksch.NewParallelTask("ResetJobTimers", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(true), jxcontext.AdminCtx,
|
||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||
jobTimer := batchItemList[0].(*model.JobTimer)
|
||
switch jobTimer.Type {
|
||
case model.JobTimerTypeAccept:
|
||
timer := time.NewTimer(jobTimer.StartAt.Add(time.Duration(jobTimer.LimitAt) * time.Hour).Sub(time.Now()))
|
||
jobOrders, err := dao.GetJobOrdersNoPage(db, jobTimer.JobID, jobTimer.JobOrderID, "", "", utils.ZeroTimeValue, utils.ZeroTimeValue, nil)
|
||
if err != nil {
|
||
return retVal, err
|
||
}
|
||
utils.CallFuncAsync(func() {
|
||
select {
|
||
case <-timer.C:
|
||
switch jobTimer.Type {
|
||
case model.JobTimerTypeAccept:
|
||
UpdateLimitJobOrders(db, timer, jobTimer.JobID, jobOrders[0], jobTimer)
|
||
case model.JobTimerTypeSubmit:
|
||
UpdateLimitAuditJobOrders(db, timer, jobTimer.JobID, jobOrders[0], jobTimer)
|
||
}
|
||
}
|
||
})
|
||
case model.JobTimerTypeSubmit:
|
||
default:
|
||
return retVal, err
|
||
}
|
||
return retVal, err
|
||
}, jobTimers)
|
||
tasksch.HandleTask(task, nil, true).Run()
|
||
task.GetID()
|
||
}
|