Files
jx-callback/business/jxstore/cms/job.go
苏尹岚 ebc4f888a8 imgs
2020-11-04 16:59:31 +08:00

821 lines
27 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package cms
import (
"encoding/json"
"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 = DayTimeBegin.AddDate(0, 0, 1)
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, jobExt *model.JobExt) (errCode string, err error) {
var (
db = dao.GetDB()
job = &model.Job{}
finishedAt time.Time
)
//需根据任务类型做一些参数判断,比如门店商品链接,地址
// switch job.JobCategoryID {
// case 1:
// }
if data, err := json.Marshal(jobExt); err == nil {
json.Unmarshal(data, &job)
}
finishedAt = utils.Str2Time(jobExt.FinishedAtStr)
job.FinishedAt = &finishedAt
if job.UserID == "" {
return errCode, fmt.Errorf("参数有误!")
}
if ctx.GetUserID() != job.UserID {
return errCode, fmt.Errorf("用户信息已过期,请重新登录!")
}
if job.FinishedAt.Sub(time.Now()) <= 0 {
return errCode, fmt.Errorf("任务截止日期必须大于今天!")
}
// authBinds, err := dao.GetUserBindAuthInfo(dao.GetDB(), job.UserID, model.AuthBindTypeAuth, []string{"weixinapp"}, "", "", "wx70d0943e61e0d15c")
// if err != nil {
// return errCode, err
// }
// if len(authBinds) == 0 {
// return errCode, fmt.Errorf("请绑定微信认证方式!")
// }
//发布任务要扣除任务总额的保证金,不够扣就要进行充值
userBill, err := dao.GetUserBill(db, job.UserID, "")
if userBill == nil {
return errCode, fmt.Errorf("未查询到该用户的账单!")
}
job.TotalPrice = job.Count * job.AvgPrice
if userBill.AccountBalance < job.TotalPrice {
return model.ErrCodeAccountBalanceNotEnough, fmt.Errorf("用户余额不足!")
}
if job.Count <= 0 {
return errCode, fmt.Errorf("任务数量不能为0")
}
job.SurplusCount = job.Count
if job.UserID == "" {
return errCode, fmt.Errorf("任务发起人不能为空!")
}
jobs, err := dao.GetJobsNoPage(db, []string{job.UserID}, nil, nil, nil, DayTimeBegin, DayTimeEnd, false)
if len(jobs) > 0 {
members, err := dao.GetUserMember(db, job.UserID, model.MemberTypeNormal)
if err != nil {
return errCode, err
}
if len(members) <= 0 {
return errCode, fmt.Errorf("非会员一天只能发布一起任务,请确认!")
}
}
if job.Address != "" && (job.Lng == 0 || job.Lat == 0) {
lng, lat, err := api.AutonaviAPI.GetCoordinateFromAddressByPage(job.Address)
if err != nil {
return errCode, err
}
job.Lng = jxutils.StandardCoordinate2Int(lng)
job.Lat = jxutils.StandardCoordinate2Int(lat)
}
dao.WrapAddIDCULDEntity(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.WrapAddIDCULDEntity(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 errCode, 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, lng, lat float64, sortType, pageSize, offset int) (pagedInfo *model.PagedInfo, err error) {
return dao.GetJobs(dao.GetDB(), userIDs, categoryIDs, statuss, vendorIDs, []int{model.JobTypeNormal}, includeStep, utils.Str2Time(fromTime), utils.Str2Time(toTime), lng, lat, sortType, pageSize, offset)
}
func GetJobDetail(ctx *jxcontext.Context, jobID int, lng, lat float64) (job *dao.GetJobsResult, err error) {
var (
db = dao.GetDB()
)
job, err = dao.GetJobDetail(db, jobID)
if job.Lng != 0 && job.Lat != 0 {
job.Distance = jxutils.EarthDistance(lng, lat, jxutils.IntCoordinate2Standard(job.Lng), jxutils.IntCoordinate2Standard(job.Lat))
}
return job, err
}
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 job.Type == model.JobTypeMtMember {
// jobOrder.Status = model.JobOrderStatusSpec
// } else {
jobOrder.Status = model.JobOrderStatusAccept
// }
dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db)
panic(r)
}
}()
dao.WrapAddIDCULEntity(jobOrder, ctx.GetUserName())
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 job.Type == model.JobTypeMtMember {
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.Imgs = jobOrder.Imgs
jobOrder2.Content = jobOrder.Content
jobOrder2.SubmitAuditAt = time.Now()
jobOrder2.Status = model.JobOrderStatusWaitAudit
if _, err = dao.UpdateEntity(db, jobOrder2, "Imgs", "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}, nil, 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, err := dao.GetJob(db, nil, nil, nil, []int{model.JobTypeMtMember}, utils.ZeroTimeValue, utils.ZeroTimeValue, false)
if job != nil && err == 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()
)
job, err := dao.GetJob(db, nil, nil, nil, []int{model.JobTypeMtMember}, utils.ZeroTimeValue, utils.ZeroTimeValue, false)
errCode, err = AcceptJob(ctx, job.ID)
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()
)
job, err := dao.GetJob(db, nil, nil, nil, []int{model.JobTypeJdDelivery}, utils.ZeroTimeValue, utils.ZeroTimeValue, false)
errCode, err = AcceptJob(ctx, job.ID)
if errCode != "" {
return errCode, err
}
if err != nil {
return errCode, err
}
if dOrder.Weight == 0 {
return errCode, fmt.Errorf("重量必须填写!")
}
if dOrder.PayPrice == 0 {
if dOrder.Weight <= 3 {
dOrder.PayPrice = 500
} else {
dOrder.PayPrice = 500 + int(float64(200)*math.Ceil(dOrder.Weight-3))
}
}
sendDeliveryList, _, err := dao.QueryUserDeliveryAddress(db, int64(dOrder.DeliverySendID), nil, 0, 0, 0)
receiveDeliveryList, _, err := dao.QueryUserDeliveryAddress(db, int64(dOrder.DeliveryReceiveID), nil, 0, 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("未找到取件人地址!")
}
//内蒙古海南统一35
//新疆西藏统一45
if receiveDeliveryList[0].ParentCode == 150000 || receiveDeliveryList[0].ParentCode == 460000 {
dOrder.PayPrice = 3500
}
if receiveDeliveryList[0].ParentCode == 650000 || receiveDeliveryList[0].ParentCode == 540000 {
dOrder.PayPrice = 4500
}
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 {
deliveryOrder.IsWeight = 1
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
}
deliveryOrder.IsWeight = 2
}
}
dao.UpdateEntity(db, deliveryOrder, "IsWeight")
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()
}