447 lines
15 KiB
Go
447 lines
15 KiB
Go
package cms
|
||
|
||
import (
|
||
"fmt"
|
||
"time"
|
||
|
||
"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/model"
|
||
"git.rosy.net.cn/jx-callback/business/model/dao"
|
||
)
|
||
|
||
const (
|
||
AcceptMaxCount = 2
|
||
CancelMaxCount = 5
|
||
)
|
||
|
||
var (
|
||
DayTimeBegin time.Time
|
||
DayTimeEnd time.Time
|
||
WeekTimeBegin time.Time
|
||
WeekTimeEnd time.Time
|
||
)
|
||
|
||
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()
|
||
}
|
||
|
||
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()
|
||
timeNow = utils.Time2Date(time.Now())
|
||
fromTime = utils.Time2Str(timeNow) + "00:00:00"
|
||
toTime = utils.Time2Str(timeNow) + "23:59:59"
|
||
)
|
||
//需根据任务类型做一些参数判断,比如门店商品链接,地址
|
||
// 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, utils.Str2Time(fromTime), utils.Str2Time(toTime), false)
|
||
if len(jobs) > 0 {
|
||
members, err := dao.GetUserMember(db, job.UserID, 0, 0, true)
|
||
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)
|
||
}
|
||
if err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
//发布任务要扣除任务总额的保证金,不够扣就要进行充值
|
||
if err == nil && job.Status != model.JobStatusFailed {
|
||
//1、账户支出增加一条记录
|
||
if err = financial.AddBillExpend(db, userBill.BillID, model.BillTypeDeposit, job.TotalPrice); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
//2、账户表余额减少相应值
|
||
userBill.AccountBalance -= job.TotalPrice
|
||
if _, err = dao.UpdateEntity(db, userBill, "AccountBalance"); 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)
|
||
}
|
||
}()
|
||
//1、根据任务剩余数量退钱到账户余额中
|
||
userBill.AccountBalance += job.SurplusCount * job.AvgPrice
|
||
if _, err = dao.UpdateEntity(db, userBill, "AccountBalance"); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
//2、账户收入增加一条记录
|
||
if err = financial.AddBillIncome(db, userBill.BillID, 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) (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 fmt.Errorf("未找到该任务或该任务状态不正常,无法接单!")
|
||
}
|
||
num, err = checkJobOrders(db, 0, "<= "+utils.Int2Str(model.JobOrderStatusAccept), userID, utils.ZeroTimeValue, utils.ZeroTimeValue)
|
||
if num >= AcceptMaxCount {
|
||
return fmt.Errorf("每人最多接取" + utils.Int2Str(AcceptMaxCount) + "个任务,请核实!")
|
||
}
|
||
num, err = checkJobOrders(db, jobID, "<= "+utils.Int2Str(model.JobOrderStatusWaitAudit), userID, utils.ZeroTimeValue, utils.ZeroTimeValue)
|
||
if num > 0 {
|
||
return 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 fmt.Errorf("此任务只支持每人做一次!")
|
||
}
|
||
case model.JobLimitCountTypePDO:
|
||
num, err = checkJobOrders(db, jobID, "<> "+utils.Int2Str(model.JobOrderStatusCancel), userID, DayTimeBegin, DayTimeEnd)
|
||
if num > 0 {
|
||
return fmt.Errorf("此任务只支持每人每天做一次!")
|
||
}
|
||
case model.JobLimitCountTypePWO:
|
||
num, err = checkJobOrders(db, jobID, "<> "+utils.Int2Str(model.JobOrderStatusCancel), userID, WeekTimeBegin, WeekTimeEnd)
|
||
if num > 0 {
|
||
return fmt.Errorf("此任务只支持每人每周做一次!")
|
||
}
|
||
case model.JobLimitCountTypeNoLimit:
|
||
default:
|
||
return fmt.Errorf("不支持的任务限次类型!%v", job.LimitCountType)
|
||
}
|
||
jobOrder := &model.JobOrder{
|
||
JobID: jobID,
|
||
JobOrderID: jxutils.GenJobOrderNo(),
|
||
UserID: job.UserID,
|
||
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)
|
||
//任务限时完成
|
||
checkLimitJobOrders(db, job, jobOrder)
|
||
return 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("未查询到该用户的账单!")
|
||
}
|
||
//如果状态不正常(取消或者过期)就要把这一笔退回去
|
||
//1、根据任务剩余数量退钱到任务保证金余额中
|
||
userBill.AccountBalance += job.AvgPrice
|
||
if _, err = dao.UpdateEntity(db, userBill, "AccountBalance"); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
//2、账户收入增加一条记录
|
||
if err = financial.AddBillIncome(db, userBill.BillID, 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) {
|
||
utils.AfterFuncWithRecover(time.Hour*time.Duration(job.JobLimitAt), func() {
|
||
utils.CallFuncAsync(func() {
|
||
globals.SugarLogger.Debugf("checkLimitJobOrders jobID: %v, jobOrderID: %v", job.ID, jobOrder.JobOrderID)
|
||
jobOrders, _ := dao.GetJobOrdersNoPage(db, job.ID, jobOrder.JobOrderID, job.UserID, "", utils.ZeroTimeValue, utils.ZeroTimeValue, nil)
|
||
if len(jobOrders) == 0 {
|
||
return
|
||
}
|
||
jobOrder := jobOrders[0]
|
||
if jobOrder.Status == model.JobOrderStatusCancel {
|
||
return
|
||
}
|
||
jobOrder.Status = model.JobOrderStatusCancel
|
||
dao.UpdateEntity(db, jobOrder, "Status")
|
||
})
|
||
})
|
||
}
|
||
|
||
func checkLimitAuditJobOrders(db *dao.DaoDB, job *model.Job, jobOrder *model.JobOrder) {
|
||
utils.AfterFuncWithRecover(time.Hour*time.Duration(job.AuditLimitAt), func() {
|
||
utils.CallFuncAsync(func() {
|
||
globals.SugarLogger.Debugf("checkLimitAuditJobOrders jobID: %v, jobOrderID: %v", job.ID, jobOrder.JobOrderID)
|
||
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, job.ID, jobOrder.JobOrderID)
|
||
}
|
||
}
|
||
})
|
||
})
|
||
}
|
||
|
||
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 {
|
||
//审核定时
|
||
checkLimitAuditJobOrders(db, job, jobOrder2)
|
||
}
|
||
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, "")
|
||
userBillJobOrder.AccountBalance += job.AvgPrice
|
||
if _, err = dao.UpdateEntity(db, userBillJobOrder, "AccountBalance"); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
//接收人账户收入增加一条
|
||
if err = financial.AddBillIncome(db, userBillJobOrder.BillID, model.BillTypeJob, job.AvgPrice); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
} else {
|
||
if job.Status < 0 {
|
||
userBill, err := dao.GetUserBill(db, job.UserID, "")
|
||
//1、根据任务剩余数量退钱到任务保证金余额中
|
||
userBill.AccountBalance += job.AvgPrice
|
||
if _, err = dao.UpdateEntity(db, userBill, "AccountBalance"); err != nil {
|
||
dao.Rollback(db)
|
||
}
|
||
//2、账户收入增加一条记录
|
||
if err = financial.AddBillIncome(db, userBill.BillID, 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)
|
||
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
|
||
}
|