2082 lines
75 KiB
Go
2082 lines
75 KiB
Go
package cms
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"git.rosy.net.cn/baseapi/platformapi/tbunionapi"
|
||
"math"
|
||
"strings"
|
||
"sync"
|
||
"time"
|
||
|
||
"git.rosy.net.cn/jx-callback/business/jxstore/event"
|
||
"git.rosy.net.cn/jx-callback/business/jxstore/partner"
|
||
|
||
"git.rosy.net.cn/baseapi/platformapi/txcloudapi"
|
||
|
||
"git.rosy.net.cn/jx-callback/business/jxutils/ddmsg"
|
||
|
||
"git.rosy.net.cn/baseapi/platformapi/dingdingapi"
|
||
"git.rosy.net.cn/baseapi/platformapi/jdeclpapi"
|
||
|
||
"git.rosy.net.cn/jx-callback/globals"
|
||
|
||
"git.rosy.net.cn/jx-callback/business/auth2"
|
||
"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
|
||
|
||
mtwmMemberPrice = 1100
|
||
)
|
||
|
||
type JobTimer struct {
|
||
JobTimerMap map[int64]*time.Timer
|
||
JobAuditTimerMap map[int64]*time.Timer
|
||
s *sync.RWMutex
|
||
}
|
||
|
||
var (
|
||
JobTimers = &JobTimer{}
|
||
)
|
||
|
||
func init() {
|
||
JobTimerMap := make(map[int64]*time.Timer)
|
||
JobAuditTimerMap := make(map[int64]*time.Timer)
|
||
JobTimers.JobTimerMap = JobTimerMap
|
||
JobTimers.JobAuditTimerMap = JobAuditTimerMap
|
||
JobTimers.s = new(sync.RWMutex)
|
||
}
|
||
|
||
func PublishJob(ctx *jxcontext.Context, jobExt *model.JobExt) (errCode string, err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
job = &model.Job{}
|
||
finishedAt time.Time
|
||
DayTimeBegin, DayTimeEnd = jxutils.GetDayTime()
|
||
)
|
||
if data, err := json.Marshal(jobExt); err == nil {
|
||
json.Unmarshal(data, &job)
|
||
}
|
||
finishedAt = utils.Str2Time(jobExt.FinishedAtStr)
|
||
job.FinishedAt = &finishedAt
|
||
// 需根据任务类型做一些参数判断,比如门店商品链接,地址
|
||
if job.JobCategoryID != model.JobCategoryIDUnion {
|
||
if job.AvgPrice == 0 {
|
||
return errCode, fmt.Errorf("请输入单个任务奖励(保证)金额!")
|
||
}
|
||
}
|
||
switch job.JobCategoryID {
|
||
case model.JobCategoryIDwmtg:
|
||
if job.Address == "" {
|
||
return errCode, fmt.Errorf("外卖推广任务请输入门店地址!")
|
||
}
|
||
case model.JobCategoryIDOther:
|
||
case model.JobCategoryIDDropShipping:
|
||
if job.DropShippingAt == 0 {
|
||
return errCode, fmt.Errorf("一件代发任务请输入承诺x天内发货!")
|
||
}
|
||
if job.DropShippingSkuPrice == 0 {
|
||
return errCode, fmt.Errorf("一件代发任务请输入商品价格!")
|
||
}
|
||
job.CashbackType = model.JobCashbackPrice
|
||
job.LimitCountType = model.JobLimitCountTypeNoLimit
|
||
job.JobLimitAt = 0
|
||
job.AuditLimitAt = 0
|
||
case model.JobCategoryIDUnion:
|
||
if job.UnionImg == "" || job.UnionQrcodePosition == "" {
|
||
return errCode, fmt.Errorf("联盟任务发布请输入分享的背景图和二维码图方位!")
|
||
}
|
||
default:
|
||
return errCode, fmt.Errorf("暂不支持的任务类型! %v", job.JobCategoryID)
|
||
}
|
||
// 需根据返现类型做一些参数判断
|
||
switch job.CashbackType {
|
||
case model.JobCashbackPercentage:
|
||
if job.Percentage <= 0 || job.Percentage > 100 {
|
||
return errCode, fmt.Errorf("返现比例请输入1-100之间的比例!")
|
||
}
|
||
case model.JobCashbackPrice:
|
||
default:
|
||
return errCode, fmt.Errorf("暂不支持的返现类型! %v", job.CashbackType)
|
||
}
|
||
if job.Count <= 0 {
|
||
return errCode, fmt.Errorf("任务数量不能为0!")
|
||
}
|
||
job.SurplusCount = job.Count
|
||
if job.UserID == "" {
|
||
return errCode, fmt.Errorf("任务发起人不能为空!")
|
||
}
|
||
var (
|
||
userBill *model.UserBill
|
||
)
|
||
|
||
if ctx.GetToken() != jxcontext.RsmDefultToken {
|
||
if ctx.GetUserID() != job.UserID {
|
||
return errCode, fmt.Errorf("用户信息已过期,请重新登录!")
|
||
}
|
||
//验证微信绑定
|
||
if err = auth2.CheckWeixinminiAuthBind(ctx.GetUserID()); err != nil {
|
||
return "", err
|
||
}
|
||
//发布任务要扣除任务总额的保证金,不够扣就要进行充值
|
||
userBill, _ = 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("用户余额不足!")
|
||
}
|
||
jobs, _ := dao.GetJobsNoPage(db, []string{job.UserID}, nil, nil, nil, DayTimeBegin, DayTimeEnd, 0, 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, _ := api.AutonaviAPI.GetCoordinateFromAddressByPage(job.Address, job.JobCityCode)
|
||
if lng == 0 || lat == 0 {
|
||
return errCode, fmt.Errorf("请填写完整且正确的门店地址!")
|
||
}
|
||
job.Lng = jxutils.StandardCoordinate2Int(lng)
|
||
job.Lat = jxutils.StandardCoordinate2Int(lat)
|
||
}
|
||
}
|
||
if job.FinishedAt.Sub(time.Now()) <= 0 {
|
||
return errCode, fmt.Errorf("任务截止日期必须大于今天!")
|
||
}
|
||
if job2, _ := dao.GetJobWithTitle(db, job.Title); job2 != nil {
|
||
return errCode, fmt.Errorf("任务标题重复,请重新输入!")
|
||
}
|
||
if job.JobCityCode != model.JobCountrywideCode {
|
||
_, _, job.JobCityCode, err = getAddressInfoFromCoord(db, job.JobLng, job.JobLat)
|
||
}
|
||
|
||
dao.WrapAddIDCULDEntity(job, ctx.GetUserName())
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
if err = dao.CreateEntityTx(txDB, job); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
for _, v := range jobExt.JobSteps {
|
||
dao.WrapAddIDCULDEntity(v, ctx.GetUserName())
|
||
v.JobID = job.ID
|
||
err = dao.CreateEntityTx(txDB, v)
|
||
}
|
||
for _, v := range jobExt.JobImgs {
|
||
dao.WrapAddIDCULEntity(v, ctx.GetUserName())
|
||
v.JobID = job.ID
|
||
err = dao.CreateEntityTx(txDB, v)
|
||
}
|
||
if err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
//发布任务要扣除任务总额的保证金,不够扣就要进行充值
|
||
if err == nil && job.Status != model.JobStatusFailed && ctx.GetToken() != jxcontext.RsmDefultToken {
|
||
if err = financial.AddExpendUpdateAccount(txDB, userBill, model.BillTypeDeposit, job.TotalPrice, job.ID); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
}
|
||
dao.Commit(db, txDB)
|
||
if ctx.GetToken() != jxcontext.RsmDefultToken {
|
||
content := new(strings.Builder)
|
||
content.WriteString("您的任务:")
|
||
content.WriteString(job.Title)
|
||
content.WriteString("。已发布成功,已扣除您的余额:")
|
||
content.WriteString(utils.Float64ToStr(jxutils.IntPrice2Standard(int64(job.TotalPrice))))
|
||
content.WriteString("元")
|
||
event.SendSysMessageSimple(content.String(), job.UserID)
|
||
}
|
||
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("未查询到该用户的账单!")
|
||
}
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
//如果是固定返现,退给任务发起人剩余数量*单价
|
||
//如果是比例返现,推给任务发起人任务总价-接取这个任务的用户实际返现的价格之和
|
||
var price int
|
||
if job.CashbackType == model.JobCashbackPrice {
|
||
price = job.SurplusCount * job.AvgPrice
|
||
} else {
|
||
if billIncomes, err := dao.GetBillIncome(db, jobID, 0); err == nil {
|
||
for _, v := range billIncomes {
|
||
price += v.IncomePrice
|
||
}
|
||
}
|
||
price = job.TotalPrice - price
|
||
}
|
||
if err = financial.AddIncomeUpdateAccount(txDB, userBill, model.BillTypeJobCancelOverdue, price, jobID); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
//3、任务状态被取消
|
||
job.Status = model.JobStatusFailed
|
||
// job.DeletedAt = time.Now()
|
||
if _, err = dao.UpdateEntityTx(txDB, job, "Status"); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
dao.Commit(db, txDB)
|
||
content := new(strings.Builder)
|
||
content.WriteString("您的任务:")
|
||
content.WriteString(job.Title)
|
||
content.WriteString("。已过期或被取消,")
|
||
content.WriteString(utils.Float64ToStr(jxutils.IntPrice2Standard(int64(price))))
|
||
content.WriteString("元已返回您的余额中!")
|
||
event.SendSysMessageSimple(content.String(), job.UserID)
|
||
return err
|
||
}
|
||
|
||
func GetJobs(ctx *jxcontext.Context, userIDs []string, categoryIDs, statuss, vendorIDs, cityCodes []int, includeStep bool, fromTime, toTime string, lng, lat float64, span int, keyword string, sortType, pageSize, offset int) (pagedInfo *model.PagedInfo, err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
userID = ctx.GetUserID()
|
||
_, _, cityCode, _ = getAddressInfoFromCoord(db, lng, lat)
|
||
)
|
||
if toTime != "" {
|
||
toTime = toTime + " 23:59:59"
|
||
}
|
||
pagedInfo, err = dao.GetJobs(db, userIDs, categoryIDs, statuss, vendorIDs, []int{model.JobTypeNormal}, cityCodes, includeStep, utils.Str2Time(fromTime), utils.Str2Time(toTime), lng, lat, cityCode, span, keyword, sortType, pageSize, offset)
|
||
//插入用户搜索关键词
|
||
if keyword != "" && ctx.GetToken() != jxcontext.RsmDefultToken {
|
||
if userSearchs, _ := dao.GetUserSearch(db, userID, keyword); len(userSearchs) > 0 {
|
||
userSearchs[0].Count++
|
||
userSearchs[0].UpdatedAt = time.Now()
|
||
dao.UpdateEntity(db, userSearchs[0], "Count", "UpdatedAt")
|
||
} else {
|
||
userSearch := &model.UserSearch{
|
||
UserID: userID,
|
||
Keyword: keyword,
|
||
}
|
||
dao.WrapAddIDCULEntity(userSearch, ctx.GetUserName())
|
||
dao.CreateEntity(db, userSearch)
|
||
}
|
||
}
|
||
return pagedInfo, err
|
||
}
|
||
|
||
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))
|
||
}
|
||
utils.CallFuncAsync(func() {
|
||
job2 := &model.Job{}
|
||
job2.ID = job.ID
|
||
dao.GetEntity(db, job2)
|
||
job2.BrowseCount++
|
||
dao.UpdateEntity(db, job2, "BrowseCount")
|
||
})
|
||
return job, err
|
||
}
|
||
|
||
func AcceptJob(ctx *jxcontext.Context, jobID, dropShippingDeliveryID, dropShippingCount int) (jobOrderID int64, errCode string, err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
userID = ctx.GetUserID()
|
||
num int
|
||
DayTimeBegin, DayTimeEnd = jxutils.GetDayTime()
|
||
WeekTimeBegin, WeekTimeEnd = jxutils.GetWeekTime()
|
||
)
|
||
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 {
|
||
if job.JobCategoryID == model.JobCategoryIDUnion {
|
||
return 0, errCode, fmt.Errorf("活动已结束,请等待下批次活动!")
|
||
} else {
|
||
return 0, errCode, fmt.Errorf("未找到该任务或该任务状态不正常,无法接单!")
|
||
}
|
||
}
|
||
// num, err = checkJobOrders(db, 0, "<= "+utils.Int2Str(model.JobOrderStatusAccept), userID, utils.ZeroTimeValue, utils.ZeroTimeValue)
|
||
// if num >= AcceptMaxCount {
|
||
// return 0, errCode, fmt.Errorf("每人最多接取" + utils.Int2Str(AcceptMaxCount) + "个任务,请核实!")
|
||
// }
|
||
//非快递任务
|
||
if jobID != 2 && job.JobCategoryID != model.JobCategoryIDUnion {
|
||
num, err = checkJobOrders(db, jobID, "<= "+utils.Int2Str(model.JobOrderStatusWaitAudit), userID, utils.ZeroTimeValue, utils.ZeroTimeValue)
|
||
if num > 0 {
|
||
return 0, errCode, fmt.Errorf("您还有此任务未完成,请完成后再接取!")
|
||
}
|
||
num, err = checkJobOrders(db, jobID, "= "+utils.Int2Str(model.JobOrderStatusAuditUnPass), userID, utils.ZeroTimeValue, utils.ZeroTimeValue)
|
||
if num > 0 {
|
||
return 0, errCode, 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 0, errCode, fmt.Errorf("此任务只支持每人做一次!")
|
||
}
|
||
case model.JobLimitCountTypePDO:
|
||
num, err = checkJobOrders(db, jobID, "<> "+utils.Int2Str(model.JobOrderStatusCancel), userID, DayTimeBegin, DayTimeEnd)
|
||
if num > 0 {
|
||
return 0, errCode, fmt.Errorf("此任务只支持每人每天做一次!")
|
||
}
|
||
case model.JobLimitCountTypePWO:
|
||
num, err = checkJobOrders(db, jobID, "<> "+utils.Int2Str(model.JobOrderStatusCancel), userID, WeekTimeBegin, WeekTimeEnd)
|
||
if num > 0 {
|
||
return 0, errCode, fmt.Errorf("此任务只支持每人每周做一次!")
|
||
}
|
||
case model.JobLimitCountTypeNoLimit:
|
||
default:
|
||
return 0, errCode, fmt.Errorf("不支持的任务限次类型!%v", job.LimitCountType)
|
||
}
|
||
jobOrder := &model.JobOrder{
|
||
JobID: jobID,
|
||
JobOrderID: jxutils.GenJobOrderNo(),
|
||
UserID: ctx.GetUserID(),
|
||
}
|
||
jobOrder.Status = model.JobOrderStatusAccept
|
||
//如果是一件代发任务,用户需要支付订单金额
|
||
var userBill *model.UserBill
|
||
if job.JobCategoryID == model.JobCategoryIDDropShipping {
|
||
if dropShippingCount == 0 || dropShippingDeliveryID == 0 {
|
||
return 0, errCode, fmt.Errorf("一件代发订单请输入商品数量和收件人地址!")
|
||
}
|
||
//验证微信绑定
|
||
if err = auth2.CheckWeixinminiAuthBind(ctx.GetUserID()); err != nil {
|
||
return 0, "", err
|
||
}
|
||
//发布任务要扣除任务总额的保证金,不够扣就要进行充值
|
||
userBill, err = dao.GetUserBill(db, ctx.GetUserID(), "")
|
||
if userBill == nil {
|
||
return 0, errCode, fmt.Errorf("未查询到该用户的账单!")
|
||
}
|
||
jobOrder.UserActualPrice = job.DropShippingSkuPrice * dropShippingCount
|
||
if userBill.AccountBalance < jobOrder.UserActualPrice {
|
||
return 0, model.ErrCodeAccountBalanceNotEnough, fmt.Errorf("用户余额不足!")
|
||
}
|
||
if deliveryList, _, err2 := dao.QueryUserDeliveryAddress(db, int64(dropShippingDeliveryID), nil, 0, 0, 0); err2 == nil {
|
||
delivery := deliveryList[0]
|
||
jobOrder.DropShippingCount = dropShippingCount
|
||
jobOrder.DropShippingDeliveryID = dropShippingDeliveryID
|
||
jobOrder.DropShippingName = delivery.ConsigneeName
|
||
jobOrder.DropShippingMobile = delivery.ConsigneeMobile
|
||
jobOrder.DropShippingAddress = delivery.Address
|
||
jobOrder.DropShippingDetailAddress = delivery.DetailAddress
|
||
jobOrder.DropShippingLng = delivery.Lng
|
||
jobOrder.DropShippingLat = delivery.Lat
|
||
jobOrder.DropShippingAutoAddress = delivery.AutoAddress
|
||
jobOrder.DropShippingCityCode = delivery.CityCode
|
||
jobOrder.DropShippingDistrictCode = delivery.DistrictCode
|
||
}
|
||
// jobOrder.Status = model.JobOrderStatusWaitAudit
|
||
} else if job.JobCategoryID == model.JobCategoryIDUnion {
|
||
jobOrder.Status = model.JobOrderStatusSpec
|
||
}
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
dao.WrapAddIDCULEntity(jobOrder, ctx.GetUserName())
|
||
if err = dao.CreateEntityTx(txDB, jobOrder); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
//用户接受任务,任务剩余次数-1
|
||
job.SurplusCount -= 1
|
||
if _, err = dao.UpdateEntityTx(txDB, job, "SurplusCount"); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
dao.Commit(db, txDB)
|
||
|
||
if job.JobCategoryID == model.JobCategoryIDDropShipping {
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
if err = financial.AddExpendUpdateAccount(txDB, userBill, model.BillTypeDropShipping, jobOrder.UserActualPrice, job.ID); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
//一件代发
|
||
if err = SubmitJob(ctx, jobOrder); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
dao.Commit(db, txDB)
|
||
} else if job.JobCategoryID != model.JobCategoryIDUnion {
|
||
//任务限时完成
|
||
timer := checkLimitJobOrders(db, job, jobOrder, model.JobTimerTypeAccept)
|
||
JobTimers.s.Lock()
|
||
JobTimers.JobTimerMap[jobOrder.JobOrderID] = timer
|
||
JobTimers.s.Unlock()
|
||
}
|
||
return jobOrder.JobOrderID, 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")
|
||
if jobOrder.ID != 0 && jobOrder.Status == model.JobOrderStatusCancel {
|
||
return fmt.Errorf("此任务已被取消了!")
|
||
}
|
||
job := &model.Job{}
|
||
job.ID = jobID
|
||
err = dao.GetEntity(db, job)
|
||
//系统消息
|
||
content := new(strings.Builder)
|
||
content.WriteString("您接取的任务:")
|
||
content.WriteString(job.Title)
|
||
if ctx.GetUserName() == "jxadmin" {
|
||
content.WriteString(",因超时未完成已被系统自动取消。")
|
||
} else {
|
||
content.WriteString(",已被取消。")
|
||
}
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
//如果当前任务状态正常,剩余数量就加1
|
||
if job.Status >= 0 {
|
||
job.SurplusCount += 1
|
||
if _, err = dao.UpdateEntityTx(txDB, job, "SurplusCount"); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
} else {
|
||
userBill, err := dao.GetUserBill(db, job.UserID, "")
|
||
if userBill == nil {
|
||
return fmt.Errorf("未查询到该用户的账单!")
|
||
}
|
||
//如果状态不正常(取消或者过期)就要把这一笔退回去
|
||
//2、账户收入
|
||
//是固定返现才会退一笔任务单价
|
||
if job.CashbackType == model.JobCashbackPrice {
|
||
if err = financial.AddIncomeUpdateAccount(txDB, userBill, model.BillTypeJobCancelOverdue, job.AvgPrice, jobID); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
//一件代发任务要退钱给用户
|
||
if job.JobCategoryID == model.JobCategoryIDDropShipping {
|
||
userBill, err := dao.GetUserBill(db, jobOrder.UserID, "")
|
||
if userBill == nil {
|
||
return fmt.Errorf("未查询到该用户的账单!")
|
||
}
|
||
if err = financial.AddIncomeUpdateAccount(txDB, userBill, model.BillTypeJobCancelOverdue, jobOrder.UserActualPrice, jobID); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return err
|
||
}
|
||
}
|
||
//3、任务订单状态被取消
|
||
jobOrder.Status = model.JobOrderStatusCancel
|
||
if _, err = dao.UpdateEntityTx(txDB, jobOrder, "Status"); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return err
|
||
}
|
||
dao.Commit(db, txDB)
|
||
event.SendSysMessageSimple(content.String(), jobOrder.UserID)
|
||
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) {
|
||
//插到定时任务表里,主要是重启项目后的重启定时器用
|
||
//main 里有重启的函数
|
||
jobTimer := &model.JobTimer{
|
||
JobID: job.ID,
|
||
JobOrderID: jobOrder.JobOrderID,
|
||
Type: jobTimerType,
|
||
Status: model.JobTimerStatusWait,
|
||
StartAt: jobOrder.CreatedAt,
|
||
// LimitAt: job.JobLimitAt,
|
||
}
|
||
switch jobTimerType {
|
||
case model.JobTimerTypeAccept:
|
||
timer = time.NewTimer(time.Hour * time.Duration(job.JobLimitAt))
|
||
jobTimer.LimitAt = job.JobLimitAt
|
||
case model.JobTimerTypeSubmit:
|
||
timer = time.NewTimer(time.Hour * time.Duration(job.AuditLimitAt))
|
||
jobTimer.LimitAt = job.AuditLimitAt
|
||
case model.JobTimerTypeDropShipping:
|
||
timer = time.NewTimer(time.Hour * time.Duration(job.DropShippingAt))
|
||
jobTimer.LimitAt = job.DropShippingAt
|
||
}
|
||
dao.WrapAddIDCULEntity(jobTimer, jxcontext.AdminCtx.GetUserName())
|
||
dao.CreateEntity(db, jobTimer)
|
||
utils.CallFuncAsync(func() {
|
||
select {
|
||
case <-timer.C:
|
||
switch jobTimerType {
|
||
case model.JobTimerTypeAccept:
|
||
UpdateLimitJobOrders(db, timer, job.ID, jobOrder.JobOrderID, jobTimer)
|
||
case model.JobTimerTypeSubmit:
|
||
UpdateLimitAuditJobOrders(db, timer, job.ID, jobOrder.JobOrderID, jobTimer)
|
||
case model.JobTimerTypeDropShipping:
|
||
UpdateDropShippingJobOrders(db, timer, job.ID, jobOrder.JobOrderID, jobTimer)
|
||
}
|
||
}
|
||
})
|
||
return timer
|
||
}
|
||
|
||
func UpdateLimitJobOrders(db *dao.DaoDB, timer *time.Timer, jobID int, jobOrderID int64, jobTimer *model.JobTimer) {
|
||
globals.SugarLogger.Debugf("updateLimitJobOrders jobID: %v, jobOrderID: %v", jobID, jobOrderID)
|
||
defer timer.Stop()
|
||
jobOrder := &model.JobOrder{JobOrderID: jobOrderID}
|
||
if err := dao.GetEntity(db, jobOrder, "JobOrderID"); err == nil {
|
||
if jobOrder.Status > model.JobOrderStatusAccept {
|
||
return
|
||
}
|
||
if err := CancelAcceptJob(jxcontext.AdminCtx, jobID, jobOrderID); err == nil {
|
||
jobTimer.Status = model.JobTimerStatusFinish
|
||
dao.UpdateEntity(db, jobTimer, "Status")
|
||
}
|
||
}
|
||
}
|
||
|
||
func UpdateLimitAuditJobOrders(db *dao.DaoDB, timer *time.Timer, jobID int, jobOrderID int64, jobTimer *model.JobTimer) {
|
||
globals.SugarLogger.Debugf("checkLimitAuditJobOrders jobID: %v, jobOrderID: %v", jobID, jobOrderID)
|
||
defer timer.Stop()
|
||
jobOrder := &model.JobOrder{JobOrderID: jobOrderID}
|
||
if err := dao.GetEntity(db, jobOrder, "JobOrderID"); err == nil {
|
||
if jobOrder.Status == model.JobOrderStatusWaitAudit {
|
||
err := AuditJob(jxcontext.AdminCtx, int(jobOrderID), model.JobOrderStatusAuditPass, "超时系统通过", "")
|
||
if err != nil {
|
||
globals.SugarLogger.Debugf("checkLimitAuditJobOrders err: %v jobID: %v, jobOrderID: %v", err, jobID, jobOrderID)
|
||
} else {
|
||
jobTimer.Status = model.JobTimerStatusFinish
|
||
dao.UpdateEntity(db, jobTimer, "Status")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func UpdateDropShippingJobOrders(db *dao.DaoDB, timer *time.Timer, jobID int, jobOrderID int64, jobTimer *model.JobTimer) {
|
||
globals.SugarLogger.Debugf("UpdateDropShippingJobOrders jobID: %v, jobOrderID: %v", jobID, jobOrderID)
|
||
defer timer.Stop()
|
||
jobOrder := &model.JobOrder{JobOrderID: jobOrderID}
|
||
job := &model.Job{}
|
||
job.ID = jobID
|
||
if err := dao.GetEntity(db, jobOrder, "JobOrderID"); err == nil {
|
||
if err := dao.GetEntity(db, job); err == nil {
|
||
//如果限时内还没发货
|
||
if jobOrder.Status < model.JobOrderStatusFinish {
|
||
userBill, err := dao.GetUserBill(db, jobOrder.UserID, "")
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
if err = financial.AddIncomeUpdateAccount(txDB, userBill, model.BillTypeDropShippingDeposit, job.AvgPrice, job.ID); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
dao.Commit(db, txDB)
|
||
}
|
||
}
|
||
}
|
||
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 job.CashbackType == model.JobCashbackPercentage {
|
||
if jobOrder.UserActualPrice == 0 {
|
||
return fmt.Errorf("比例返现任务请输入订单实际实付金额,用于任务发起人审核!")
|
||
}
|
||
}
|
||
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.UserActualPrice = jobOrder.UserActualPrice
|
||
jobOrder2.Status = model.JobOrderStatusWaitAudit
|
||
if _, err = dao.UpdateEntity(db, jobOrder2, "Imgs", "Content", "SubmitAuditAt", "Status", "UserActualPrice"); err == nil {
|
||
//任务定时器停止
|
||
JobTimers.s.RLock()
|
||
if JobTimers.JobTimerMap[jobOrder2.JobOrderID] != nil {
|
||
JobTimers.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")
|
||
}
|
||
}
|
||
JobTimers.s.RUnlock()
|
||
//一件代发
|
||
var timerType int
|
||
if job.JobCategoryID == model.JobCategoryIDDropShipping {
|
||
timerType = model.JobTimerTypeDropShipping
|
||
} else {
|
||
timerType = model.JobTimerTypeSubmit
|
||
}
|
||
//审核定时开启
|
||
timer := checkLimitJobOrders(db, job, jobOrder2, timerType)
|
||
JobTimers.s.Lock()
|
||
JobTimers.JobAuditTimerMap[jobOrder2.JobOrderID] = timer
|
||
JobTimers.s.Unlock()
|
||
}
|
||
content := new(strings.Builder)
|
||
content.WriteString("您的任务:")
|
||
content.WriteString(job.Title)
|
||
content.WriteString("。已有人提交了审核,请及时审核!")
|
||
event.SendSysMessageSimple(content.String(), job.UserID)
|
||
return err
|
||
}
|
||
|
||
func AuditJob(ctx *jxcontext.Context, jobOrderID, status int, comment, vendorWaybillID 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 && ctx.GetUserName() != "jxadmin" {
|
||
return fmt.Errorf("任务发起人才能审核!")
|
||
}
|
||
if job.JobCategoryID == model.JobCategoryIDDropShipping && vendorWaybillID == "" {
|
||
return fmt.Errorf("一件代发任务发货请输入运单号!")
|
||
}
|
||
if job.JobCategoryID == model.JobCategoryIDDropShipping && status != model.JobOrderStatusAuditPass {
|
||
return fmt.Errorf("一件代发任务发货参数有误!")
|
||
}
|
||
if jobOrder.Status != model.JobOrderStatusWaitAudit {
|
||
return fmt.Errorf("审核状态不正确!")
|
||
}
|
||
//固定返现
|
||
//1、审核时,若此任务已过期或者已取消,不通过则应将此任务保证金退还给发起人,通过则应将单次任务保证金给接受人
|
||
//2、若此任务未过期,不通过则此任务剩余数量将+1,通过则应将单次任务保证金给接受人
|
||
jobOrder.Status = status
|
||
jobOrder.Comment = comment
|
||
jobOrder.AuditAt = time.Now()
|
||
jobOrder.LastOperator = ctx.GetUserName()
|
||
userBillJobOrder, err := dao.GetUserBill(db, jobOrder.UserID, "")
|
||
//系统消息
|
||
content := new(strings.Builder)
|
||
content.WriteString("恭喜您完成了任务:")
|
||
content.WriteString(job.Title)
|
||
if ctx.GetUserName() == "jxadmin" {
|
||
content.WriteString(",因超时未审核已被系统自动审核")
|
||
} else {
|
||
content.WriteString(",商家已经审核")
|
||
}
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
if _, err = dao.UpdateEntityTx(txDB, jobOrder, "Status", "Comment", "AuditAt", "LastOperator"); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
if status == model.JobOrderStatusAuditPass {
|
||
content.WriteString("通过,")
|
||
if job.JobCategoryID != model.JobCategoryIDDropShipping {
|
||
var price int
|
||
if job.CashbackType == model.JobCashbackPrice {
|
||
price = job.AvgPrice
|
||
} else {
|
||
price = jobOrder.UserActualPrice * job.Percentage / 100
|
||
if price > job.AvgPrice {
|
||
price = job.AvgPrice
|
||
}
|
||
}
|
||
//若完成任务的人在某个群组中,则要向群主分成
|
||
if messageGroupMembers, err := dao.GetMessageGroupMembers(db, 0, model.GroupTypeMulit, jobOrder.UserID); err == nil {
|
||
if len(messageGroupMembers) > 1 {
|
||
return fmt.Errorf("审核异常,该任务提交人加入了多个群组!")
|
||
} else if len(messageGroupMembers) == 1 {
|
||
if messageGroupsResult, err := dao.GetMessageGroups(db, "", messageGroupMembers[0].GroupID, model.GroupTypeMulit, false, ""); err == nil {
|
||
if len(messageGroupsResult) == 1 {
|
||
if messageGroupsResult[0].DividePercentage != 0 {
|
||
if userBillGroupMaster, err := dao.GetUserBill(db, messageGroupsResult[0].UserID, ""); err == nil {
|
||
if err = financial.AddIncomeUpdateAccount(txDB, userBillGroupMaster, model.BillTypeDivide, price*messageGroupsResult[0].DividePercentage/100, job.ID); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return err
|
||
}
|
||
}
|
||
//接收人账户收入
|
||
if err = financial.AddIncomeUpdateAccount(txDB, userBillJobOrder, model.BillTypeJobDivide, price*(100-messageGroupsResult[0].DividePercentage)/100, job.ID); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return err
|
||
}
|
||
} else {
|
||
//接收人账户收入
|
||
if err = financial.AddIncomeUpdateAccount(txDB, userBillJobOrder, model.BillTypeJob, price, job.ID); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} else if len(messageGroupMembers) == 0 { //若没有在某个群组,则得到全部
|
||
//接收人账户收入
|
||
if err = financial.AddIncomeUpdateAccount(txDB, userBillJobOrder, model.BillTypeJob, price, job.ID); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
jobOrder.Status = model.JobOrderStatusFinish
|
||
if _, err = dao.UpdateEntityTx(txDB, jobOrder, "Status"); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return err
|
||
}
|
||
content.WriteString(utils.Float64ToStr(jxutils.IntPrice2Standard(int64(price))))
|
||
content.WriteString("元已存入您的余额中!")
|
||
} else {
|
||
//一件代发处理,审核相当于发货
|
||
jobOrder.VendorWaybillID = vendorWaybillID
|
||
jobOrder.Status = model.JobOrderStatusFinish
|
||
if _, err = dao.UpdateEntityTx(txDB, jobOrder, "Status", "VendorWaybillID"); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return err
|
||
}
|
||
userBill, err := dao.GetUserBill(db, job.UserID, "")
|
||
if err = financial.AddIncomeUpdateAccount(txDB, userBill, model.BillTypeDropShippingDeposit, job.AvgPrice, job.ID); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return err
|
||
}
|
||
}
|
||
event.SendSysMessageSimple(content.String(), jobOrder.UserID)
|
||
} else {
|
||
content2 := new(strings.Builder)
|
||
content2.WriteString("非常抱歉,您提交的任务: ")
|
||
content2.WriteString(job.Title)
|
||
content2.WriteString("未通过审核,请您修改后重新提交!")
|
||
if job.Status < 0 {
|
||
if job.CashbackType == model.JobCashbackPrice {
|
||
userBill, err := dao.GetUserBill(db, job.UserID, "")
|
||
if err = financial.AddIncomeUpdateAccount(txDB, userBill, model.BillTypeJobAuditUnPassWithCancelOverdue, job.AvgPrice, job.ID); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return err
|
||
}
|
||
}
|
||
} else {
|
||
//审核不通过的话,要重新变成待上传,再重新开个定时器
|
||
jobOrder.Status = model.JobOrderStatusAccept
|
||
if _, err = dao.UpdateEntityTx(txDB, jobOrder, "Status"); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
//之前的定时表删了?
|
||
jobTimer := &model.JobTimer{
|
||
JobID: job.ID,
|
||
JobOrderID: jobOrder.JobOrderID,
|
||
}
|
||
if _, err = dao.DeleteEntityTx(txDB, jobTimer, "JobID", "JobOrderID"); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
//任务限时完成
|
||
timer := checkLimitJobOrders(db, job, jobOrder, model.JobTimerTypeAccept)
|
||
JobTimers.s.Lock()
|
||
JobTimers.JobTimerMap[jobOrder.JobOrderID] = timer
|
||
JobTimers.s.Unlock()
|
||
}
|
||
event.SendSysMessageSimple(content2.String(), jobOrder.UserID)
|
||
}
|
||
dao.Commit(db, txDB)
|
||
//任务定时器停止
|
||
JobTimers.s.RLock()
|
||
if JobTimers.JobAuditTimerMap[int64(jobOrderID)] != nil {
|
||
JobTimers.JobAuditTimerMap[int64(jobOrderID)].Stop()
|
||
}
|
||
JobTimers.s.RUnlock()
|
||
//任务定时表状态完成
|
||
jobTimer := &model.JobTimer{
|
||
JobID: job.ID,
|
||
JobOrderID: jobOrder.JobOrderID,
|
||
// Type: model.JobTimerTypeSubmit,
|
||
}
|
||
if job.JobCategoryID != model.JobCategoryIDDropShipping {
|
||
jobTimer.Type = model.JobTimerTypeSubmit
|
||
} else {
|
||
jobTimer.Type = model.JobTimerTypeDropShipping
|
||
}
|
||
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, 0, false)
|
||
if err != nil {
|
||
globals.SugarLogger.Debugf("RefreshJobStatus err :%v", err)
|
||
return
|
||
}
|
||
for _, job := range jobs {
|
||
if time.Now().Sub(*job.FinishedAt) >= 0 {
|
||
//取消已发布的任务
|
||
userBill, err := dao.GetUserBill(db, job.UserID, "")
|
||
if userBill == nil {
|
||
return fmt.Errorf("未查询到该用户的账单!")
|
||
}
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
//如果是固定返现,退给任务发起人剩余数量*单价
|
||
//如果是比例返现,推给任务发起人任务总价-接取这个任务的用户实际返现的价格之和
|
||
var price int
|
||
if job.CashbackType == model.JobCashbackPrice {
|
||
price = job.SurplusCount * job.AvgPrice
|
||
} else {
|
||
if billIncomes, err := dao.GetBillIncome(db, job.ID, 0); err == nil {
|
||
for _, v := range billIncomes {
|
||
price += v.IncomePrice
|
||
}
|
||
}
|
||
price = job.TotalPrice - price
|
||
}
|
||
if err = financial.AddIncomeUpdateAccount(txDB, userBill, model.BillTypeJobCancelOverdue, price, job.ID); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return err
|
||
}
|
||
//3、任务状态被取消
|
||
job2 := &model.Job{}
|
||
job2.ID = job.ID
|
||
dao.GetEntity(db, job2)
|
||
if job2 != nil {
|
||
job2.Status = model.JobStatusOverdue
|
||
// job.DeletedAt = time.Now()
|
||
if _, err = dao.UpdateEntityTx(txDB, job2, "Status"); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return err
|
||
}
|
||
}
|
||
dao.Commit(db, txDB)
|
||
}
|
||
}
|
||
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)
|
||
job.SurplusCount += len(mtMembers)
|
||
dao.UpdateEntity(db, job, "Count", "SurplusCount")
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func RechargeMtMembers(ctx *jxcontext.Context, phone int) (errCode string, err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
db2 = dao.GetDB()
|
||
userID = ctx.GetUserID()
|
||
)
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
nums, err := dao.GetMtMembers(db)
|
||
if nums < 10 {
|
||
utils.CallFuncAsync(func() {
|
||
ddmsg.SendUserMessage(dingdingapi.MsgTyeText, "F4836F9238F611EB9101525400C36BDA", "美团会员券", "美团会员券仅剩"+utils.Int2Str(nums)+"张了!")
|
||
ddmsg.SendUserMessage(dingdingapi.MsgTyeText, "EFA9876238FC11EB9101525400C36BDA", "美团会员券", "美团会员券仅剩"+utils.Int2Str(nums)+"张了!")
|
||
})
|
||
}
|
||
if err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return errCode, err
|
||
}
|
||
//验证微信绑定
|
||
if err = auth2.CheckWeixinminiAuthBind(userID); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return "", err
|
||
}
|
||
//特殊任务,如美团会员,是直接要支付
|
||
userBill, err := dao.GetUserBill(db, userID, "")
|
||
if err != nil {
|
||
return errCode, err
|
||
}
|
||
if userBill.AccountBalance < mtwmMemberPrice {
|
||
return model.ErrCodeAccountBalanceNotEnough, fmt.Errorf("用户余额不足,请充值!")
|
||
}
|
||
//账户支出
|
||
if err = financial.AddExpendUpdateAccount(txDB, userBill, model.BillTypeSpJob, mtwmMemberPrice, 1); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return errCode, err
|
||
}
|
||
dao.Commit(db, txDB)
|
||
for {
|
||
txDB, _ := dao.Begin(db2)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db2, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
mtMember, err := dao.GetMtMember(db2)
|
||
if mtMember == nil {
|
||
return errCode, fmt.Errorf("补券中,请稍后再试!")
|
||
}
|
||
err = api.MtMemberAPI.RechargeExchange(phone, mtMember.ShortLink)
|
||
mtMember.DeletedAt = time.Now()
|
||
dao.UpdateEntity(db2, mtMember, "DeletedAt")
|
||
dao.Commit(db2, txDB)
|
||
if err == nil {
|
||
job, err := dao.GetJob(db2, nil, nil, nil, []int{model.JobTypeMtMember}, utils.ZeroTimeValue, utils.ZeroTimeValue, false)
|
||
_, errCode, err = AcceptJob(ctx, job.ID, 0, 0)
|
||
if errCode != "" {
|
||
return errCode, err
|
||
}
|
||
if err != nil {
|
||
return errCode, err
|
||
}
|
||
break
|
||
}
|
||
}
|
||
return errCode, err
|
||
}
|
||
|
||
func SendJdDelivery(ctx *jxcontext.Context, dOrder *model.DeliveryOrder) (errCode string, err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
if dOrder.Weight == 0 {
|
||
return errCode, fmt.Errorf("重量必须填写!")
|
||
}
|
||
if dOrder.PayPrice == 0 {
|
||
if dOrder.Weight <= 3 {
|
||
dOrder.PayPrice = 1000
|
||
} else {
|
||
dOrder.PayPrice = 1000 + int(float64(waybillKgPrice)*math.Ceil(dOrder.Weight-3))
|
||
}
|
||
}
|
||
var (
|
||
sendDelivery *dao.UserDeliveryAddressEx
|
||
receiveDelivery *dao.UserDeliveryAddressEx
|
||
)
|
||
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 err = auth2.CheckWeixinminiAuthBind(ctx.GetUserID()); err != nil {
|
||
return "", err
|
||
}
|
||
if userBill.AccountBalance < dOrder.PayPrice {
|
||
return model.ErrCodeAccountBalanceNotEnough, fmt.Errorf("用户余额不足,请充值!")
|
||
}
|
||
if len(sendDeliveryList) == 0 {
|
||
return errCode, fmt.Errorf("未找到寄件人地址!")
|
||
} else {
|
||
sendDelivery = sendDeliveryList[0]
|
||
}
|
||
if len(receiveDeliveryList) == 0 {
|
||
return errCode, fmt.Errorf("未找到取件人地址!")
|
||
} else {
|
||
receiveDelivery = receiveDeliveryList[0]
|
||
}
|
||
//内蒙古海南统一35
|
||
//新疆西藏统一45
|
||
if receiveDelivery.ParentCode == 150000 || receiveDelivery.ParentCode == 460000 ||
|
||
receiveDelivery.ParentCode == 650000 || receiveDelivery.ParentCode == 540000 ||
|
||
sendDelivery.ParentCode == 150000 || sendDelivery.ParentCode == 460000 ||
|
||
sendDelivery.ParentCode == 650000 || sendDelivery.ParentCode == 540000 {
|
||
return errCode, fmt.Errorf("暂不支持该地区的快递业务!")
|
||
}
|
||
sendProvinceName := ""
|
||
receiveProvinceName := ""
|
||
if place1, err := dao.GetPlaceByCode(db, sendDelivery.CityCode); err == nil {
|
||
if place2, err2 := dao.GetPlaceByCode(db, place1.ParentCode); err2 == nil {
|
||
sendProvinceName = place2.Name
|
||
}
|
||
}
|
||
if place1, err := dao.GetPlaceByCode(db, receiveDelivery.CityCode); err == nil {
|
||
if place2, err2 := dao.GetPlaceByCode(db, place1.ParentCode); err2 == nil {
|
||
receiveProvinceName = place2.Name
|
||
}
|
||
}
|
||
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: sendDelivery.ConsigneeName,
|
||
SenderAddress: sendProvinceName + sendDelivery.CityName + sendDelivery.DistrictName + sendDelivery.Address + sendDelivery.DetailAddress,
|
||
SenderTel: sendDelivery.ConsigneeMobile,
|
||
ReceiveName: receiveDelivery.ConsigneeName,
|
||
ReceiveAddress: receiveProvinceName + receiveDelivery.CityName + receiveDelivery.DistrictName + receiveDelivery.Address + receiveDelivery.DetailAddress,
|
||
ReceiveTel: receiveDelivery.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()
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
//账户支出明细
|
||
if err = financial.AddExpendUpdateAccount(txDB, userBill, model.BillTypeSpJob, dOrder.PayPrice, 2); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
dOrder.SendName = sendDelivery.ConsigneeName
|
||
dOrder.SendMobile = sendDelivery.ConsigneeMobile
|
||
dOrder.SendAddress = sendDelivery.Address
|
||
dOrder.SendAutoAddress = sendDelivery.AutoAddress
|
||
dOrder.SendCityCode = sendDelivery.CityCode
|
||
dOrder.SendDetailAddress = sendDelivery.DetailAddress
|
||
dOrder.SendLng = sendDelivery.Lng
|
||
dOrder.SendLat = sendDelivery.Lat
|
||
dOrder.ReceiveName = receiveDelivery.ConsigneeName
|
||
dOrder.ReceiveMobile = receiveDelivery.ConsigneeMobile
|
||
dOrder.ReceiveAddress = receiveDelivery.Address
|
||
dOrder.ReceiveAutoAddress = receiveDelivery.AutoAddress
|
||
dOrder.ReceiveCityCode = receiveDelivery.CityCode
|
||
dOrder.ReceiveDetailAddress = receiveDelivery.DetailAddress
|
||
dOrder.ReceiveLng = receiveDelivery.Lng
|
||
dOrder.ReceiveLat = receiveDelivery.Lat
|
||
if err = dao.CreateEntity(db, dOrder); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
dao.Commit(db, txDB)
|
||
utils.CallFuncAsync(func() {
|
||
job, _ := dao.GetJob(db, nil, nil, nil, []int{model.JobTypeJdDelivery}, utils.ZeroTimeValue, utils.ZeroTimeValue, false)
|
||
if jobOrderID, _, err := AcceptJob(ctx, job.ID, 0, 0); err == nil {
|
||
dOrder.JobOrderID = utils.Int64ToStr(jobOrderID)
|
||
dao.UpdateEntity(db, dOrder, "JobOrderID")
|
||
}
|
||
})
|
||
return errCode, err
|
||
}
|
||
|
||
func CancelJdDelivery(ctx *jxcontext.Context, vendorWaybillID, reason string) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
dOrder = &model.DeliveryOrder{
|
||
VendorWaybillID: vendorWaybillID,
|
||
}
|
||
// DayTimeBegin, DayTimeEnd = jxutils.GetDayTime()
|
||
)
|
||
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
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
if _, err = dao.UpdateEntity(db, dOrder, "Status", "OrderFinishedAt", "Comment"); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
if err = financial.AddIncomeUpdateAccount(txDB, userBill, model.BillTypeSpJob, dOrder.PayPrice, 2); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
if err = CancelAcceptJob(ctx, 2, utils.Str2Int64(dOrder.JobOrderID)); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
}
|
||
dao.Commit(db, txDB)
|
||
return err
|
||
}
|
||
|
||
func GetJdDelivery(ctx *jxcontext.Context, status int, fromTime, toTime string, pageSize, offset int) (pagedInfo *model.PagedInfo, err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
statuss []int
|
||
)
|
||
if status != 0 {
|
||
statuss = append(statuss, status)
|
||
}
|
||
RefreshJdDelivery(ctx)
|
||
return dao.GetDeliveryOrders(db, []string{ctx.GetUserID()}, statuss, utils.Str2Time(fromTime), utils.Str2Time(toTime), pageSize, offset)
|
||
}
|
||
|
||
func RefreshJdDelivery(ctx *jxcontext.Context) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
userID string
|
||
userIDs []string
|
||
)
|
||
if ctx.GetUserName() == "jxadmin" {
|
||
userID = ""
|
||
userIDs = nil
|
||
} else {
|
||
userID = ctx.GetUserID()
|
||
userIDs = append(userIDs, userID)
|
||
}
|
||
pages, _ := dao.GetDeliveryOrders(db, userIDs, []int{model.OrderStatusNew, model.OrderStatusDelivering}, utils.ZeroTimeValue, utils.ZeroTimeValue, 9999, 0)
|
||
list := pages.Data.([]*dao.GetDeliveryOrdersResult)
|
||
task := tasksch.NewParallelTask("RefreshJdDelivery", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(true), jxcontext.AdminCtx,
|
||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||
v := batchItemList[0].(*dao.GetDeliveryOrdersResult)
|
||
if v != nil && v.VendorWaybillID != "" {
|
||
var (
|
||
isDeliverying, isFinished, isCancel bool
|
||
)
|
||
if results, err := api.JdEclpAPI.QueryDynamicTraceInfo(v.VendorWaybillID); err == nil {
|
||
for _, result := range results {
|
||
if result.State == jdeclpapi.TraceInfoStateM640 {
|
||
isDeliverying = true
|
||
}
|
||
if result.State == jdeclpapi.TraceInfoStateM650 || result.State == jdeclpapi.TraceInfoStateM790 {
|
||
isCancel = true
|
||
break
|
||
}
|
||
if result.State == jdeclpapi.TraceInfoState150 {
|
||
isFinished = true
|
||
break
|
||
}
|
||
}
|
||
}
|
||
dOrder := &model.DeliveryOrder{}
|
||
dOrder.VendorWaybillID = v.VendorWaybillID
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
if err = dao.GetEntity(db, dOrder, "VendorWaybillID"); err == nil {
|
||
if isCancel {
|
||
//退钱给发快递的
|
||
dOrder.Status = model.OrderStatusCanceled
|
||
userBill, _ := dao.GetUserBill(db, v.UserID, "")
|
||
err = financial.AddIncomeUpdateAccount(txDB, userBill, model.BillTypeSpJob, v.PayPrice+v.DiffPrice, 2)
|
||
} else if isFinished {
|
||
//快递任务要完成
|
||
dOrder.Status = model.OrderStatusFinished
|
||
err = AuditJob(ctx, utils.Str2Int(dOrder.JobOrderID), model.JobOrderStatusAuditPass, "快递完成,自动审核通过", "")
|
||
} else if isDeliverying {
|
||
dOrder.Status = model.OrderStatusDelivering
|
||
} else {
|
||
return retVal, err
|
||
}
|
||
if err == nil {
|
||
dao.UpdateEntityTx(txDB, dOrder, "Status")
|
||
} else {
|
||
if strings.Contains(err.Error(), "审核状态不正确") {
|
||
dao.UpdateEntityTx(txDB, dOrder, "Status")
|
||
}
|
||
}
|
||
}
|
||
dao.Commit(db, txDB)
|
||
}
|
||
return retVal, err
|
||
}, list)
|
||
tasksch.HandleTask(task, nil, true).Run()
|
||
task.GetID()
|
||
return err
|
||
}
|
||
|
||
func GetDeliveryDetail(ctx *jxcontext.Context, vendorWaybillID string) (queryDynamicTraceInfo []*jdeclpapi.QueryDynamicTraceInfoResult, err error) {
|
||
return api.JdEclpAPI.QueryDynamicTraceInfo(vendorWaybillID)
|
||
}
|
||
|
||
func GetAllDeliveryDetail(ctx *jxcontext.Context, vendorWaybillID, comType string) (result *txcloudapi.GetWaybillDetailInfoResult, err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
getWaybillDetailInfoResult = &txcloudapi.GetWaybillDetailInfoResult{}
|
||
)
|
||
jobOrder := &model.JobOrder{
|
||
VendorWaybillID: vendorWaybillID,
|
||
}
|
||
err = dao.GetEntity(db, jobOrder, "VendorWaybillID")
|
||
if jobOrder == nil {
|
||
return result, fmt.Errorf("运单号有误,无法查询!")
|
||
}
|
||
if jobOrder.WaybillStatus >= model.OrderStatusFinished {
|
||
json.Unmarshal([]byte(jobOrder.WaybillInfo), &getWaybillDetailInfoResult)
|
||
return getWaybillDetailInfoResult, err
|
||
}
|
||
//距上次查询时间要大于12小时的,才去真正查
|
||
if jobOrder.WaybillQueryTime != utils.ZeroTimeValue {
|
||
if time.Now().Sub(jobOrder.WaybillQueryTime) <= time.Hour*12 {
|
||
json.Unmarshal([]byte(jobOrder.WaybillInfo), &getWaybillDetailInfoResult)
|
||
return getWaybillDetailInfoResult, err
|
||
}
|
||
}
|
||
if getWaybillDetailInfoResult, err = api.TxAPI.GetWaybillDetailInfo(vendorWaybillID, comType); err != nil {
|
||
return nil, err
|
||
}
|
||
jobOrder.WaybillQueryTime = time.Now()
|
||
if waybillInfo, err := json.Marshal(getWaybillDetailInfoResult); err == nil {
|
||
jobOrder.WaybillInfo = string(waybillInfo)
|
||
}
|
||
if getWaybillDetailInfoResult.State == utils.Int2Str(txcloudapi.StatusFinished) && jobOrder.WaybillStatus < model.OrderStatusFinished {
|
||
jobOrder.WaybillStatus = model.OrderStatusFinished
|
||
}
|
||
dao.UpdateEntity(db, jobOrder, "WaybillQueryTime", "WaybillInfo", "WaybillStatus")
|
||
return getWaybillDetailInfoResult, err
|
||
}
|
||
|
||
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), jxcontext.AdminCtx,
|
||
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
|
||
}
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
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(txDB, userBill, model.BillTypeJdWaybillOverWeight, utils.Float64TwoInt(diffPrice), 2); err != nil {
|
||
txDB.Rollback()
|
||
return retVal, err
|
||
}
|
||
deliveryOrder.IsWeight = 2 //超重
|
||
deliveryOrder.DiffPrice = utils.Float64TwoInt(diffPrice)
|
||
}
|
||
}
|
||
deliveryOrder.ActualWeight = waybill.Weight
|
||
dao.UpdateEntityTx(txDB, deliveryOrder, "IsWeight", "ActualWeight", "DiffPrice")
|
||
dao.Commit(db, txDB)
|
||
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)
|
||
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].JobOrderID, jobTimer)
|
||
case model.JobTimerTypeSubmit:
|
||
UpdateLimitAuditJobOrders(db, timer, jobTimer.JobID, jobOrders[0].JobOrderID, jobTimer)
|
||
case model.JobTimerTypeDropShipping:
|
||
UpdateDropShippingJobOrders(db, timer, jobTimer.JobID, jobOrders[0].JobOrderID, jobTimer)
|
||
}
|
||
}
|
||
})
|
||
return retVal, err
|
||
}, jobTimers)
|
||
tasksch.HandleTask(task, nil, true).Run()
|
||
task.GetID()
|
||
}
|
||
|
||
func CreateJobSpan(ctx *jxcontext.Context, jobIDs []int, endAt string, span int) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
maxSeq = 0
|
||
)
|
||
if span == model.JobSpanTop {
|
||
maxSeq, err = dao.GetMaxJobTopSeq(db)
|
||
} else {
|
||
maxSeq, err = dao.GetMaxJobRecmdSeq(db)
|
||
}
|
||
for k, jobID := range jobIDs {
|
||
endAt2 := utils.Str2Time(endAt)
|
||
jonSpan := &model.JobSpan{
|
||
JobID: jobID,
|
||
EndAt: &endAt2,
|
||
SpanType: span,
|
||
}
|
||
if err = dao.CreateEntity(db, jonSpan); err == nil {
|
||
job := &model.Job{}
|
||
job.ID = jobID
|
||
if err = dao.GetEntity(db, job); err == nil {
|
||
if span == model.JobSpanTop {
|
||
job.TopSeq = k + 1 + maxSeq
|
||
job.JobSpanTop = 1
|
||
dao.UpdateEntity(db, job, "TopSeq", "JobSpanTop")
|
||
} else {
|
||
job.RecmdSeq = k + 1 + maxSeq
|
||
job.JobSpanRecmd = 1
|
||
dao.UpdateEntity(db, job, "RecmdSeq", "JobSpanRecmd")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func RefreshJobSpan(ctx *jxcontext.Context) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
jobSpans, err := dao.GetJobSpans(db)
|
||
task := tasksch.NewParallelTask("RefreshJobSpan", tasksch.NewParallelConfig().SetIsContinueWhenError(true), jxcontext.AdminCtx,
|
||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||
jobSpan := batchItemList[0].(*model.JobSpan)
|
||
if time.Now().Sub(*jobSpan.EndAt) >= 0 {
|
||
job := &model.Job{}
|
||
job.ID = jobSpan.JobID
|
||
if err = dao.GetEntity(db, job); err == nil {
|
||
if jobSpan.SpanType == model.JobSpanTop {
|
||
job.TopSeq = 0
|
||
job.JobSpanTop = 0
|
||
dao.UpdateEntity(db, job, "TopSeq", "JobSpanTop")
|
||
} else {
|
||
job.RecmdSeq = 0
|
||
job.JobSpanRecmd = 0
|
||
dao.UpdateEntity(db, job, "RecmdSeq", "JobSpanRecmd")
|
||
}
|
||
}
|
||
jobSpan.DeletedAt = time.Now()
|
||
dao.UpdateEntity(db, jobSpan, "DeletedAt")
|
||
}
|
||
return retVal, err
|
||
}, jobSpans)
|
||
tasksch.HandleTask(task, nil, true).Run()
|
||
task.GetID()
|
||
return err
|
||
}
|
||
|
||
func ReloadJobSpan(ctx *jxcontext.Context, jobIDs []int, span int) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
for k, v := range jobIDs {
|
||
job := &model.Job{}
|
||
job.ID = v
|
||
if err = dao.GetEntity(db, job); err == nil {
|
||
if span == model.JobSpanTop {
|
||
if job.JobSpanTop == model.JobSpanTop {
|
||
job.TopSeq = k + 1
|
||
dao.UpdateEntity(db, job, "TopSeq")
|
||
} else {
|
||
continue
|
||
}
|
||
} else {
|
||
if job.JobSpanRecmd == 1 {
|
||
job.RecmdSeq = k + 1
|
||
dao.UpdateEntity(db, job, "RecmdSeq")
|
||
} else {
|
||
continue
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func ConfirmDropShippingJob(ctx *jxcontext.Context, jobOrderID int) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
)
|
||
jobOrder := &model.JobOrder{
|
||
JobOrderID: int64(jobOrderID),
|
||
}
|
||
if err = dao.GetEntity(db, jobOrder, "JobOrderID"); err != nil {
|
||
return err
|
||
}
|
||
job := &model.Job{}
|
||
job.ID = jobOrder.JobID
|
||
if err = dao.GetEntity(db, job); err != nil {
|
||
return err
|
||
}
|
||
if ctx.GetUserID() != jobOrder.UserID && ctx.GetUserName() != "jxadmin" {
|
||
return fmt.Errorf("只有任务接取人才能确认收货!")
|
||
}
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
//确认收货更新时间和收货人
|
||
jobOrder.DropShippingConfirmTime = time.Now()
|
||
jobOrder.DropShippingConfirmUser = ctx.GetUserName()
|
||
jobOrder.Status = model.OrderStatusConfirm
|
||
if _, err = dao.UpdateEntity(db, jobOrder, "DropShippingConfirmTime", "DropShippingConfirmUser", "Status"); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
userBill, err := dao.GetUserBill(db, job.UserID, "")
|
||
if err = financial.AddIncomeUpdateAccount(txDB, userBill, model.BillTypeDropShipping, jobOrder.UserActualPrice, job.ID); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return
|
||
}
|
||
dao.Commit(db, txDB)
|
||
return err
|
||
}
|
||
|
||
func RefreshDropShippingJob(ctx *jxcontext.Context) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
jobOrders []*model.JobOrder
|
||
)
|
||
if time.Now().Weekday() != 5 && time.Now().Weekday() != 1 {
|
||
return
|
||
}
|
||
//找出没有完成的,顺便刷成完成
|
||
sql := `
|
||
SELECT a.*
|
||
FROM job_order a
|
||
JOIN job b ON a.job_id = b.id AND b.job_category_id = ?
|
||
WHERE a.waybill_status <= ?
|
||
AND a.drop_shipping_confirm_user = ''
|
||
AND a.status = ?
|
||
AND a.vendor_waybill_id <> ''
|
||
`
|
||
sqlParams := []interface{}{
|
||
model.JobCategoryIDDropShipping,
|
||
model.OrderStatusFinished,
|
||
model.OrderStatusFinished,
|
||
}
|
||
err = dao.GetRows(db, &jobOrders, sql, sqlParams)
|
||
task := tasksch.NewParallelTask("RefreshDropShippingJob", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(true), ctx,
|
||
func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||
jobOrder := batchItemList[0].(*model.JobOrder)
|
||
result, err := GetAllDeliveryDetail(ctx, jobOrder.VendorWaybillID, "")
|
||
//完成了的,现在判断是如果收货时间已经过了3天了就自动确认收货
|
||
if result.State == utils.Int2Str(txcloudapi.StatusFinished) && time.Now().Sub(utils.Str2Time(result.UpdateTime)) > time.Hour*72 {
|
||
err = ConfirmDropShippingJob(ctx, int(jobOrder.JobOrderID))
|
||
}
|
||
return retVal, err
|
||
}, jobOrders)
|
||
tasksch.HandleTask(task, nil, true).Run()
|
||
task.GetID()
|
||
return err
|
||
}
|
||
|
||
func AddressDistinguish(ctx *jxcontext.Context, address string) (result *txcloudapi.AddressDistinguishResult, err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
addressDistinguish = &model.AddressDistinguish{Address: address}
|
||
)
|
||
if len(address) <= 11 {
|
||
return result, fmt.Errorf("地址长度过短,请确认后再进行识别!")
|
||
}
|
||
//建了个表,有查过的记录就存一下吧
|
||
if err = dao.GetEntity(db, addressDistinguish, "Address"); err == nil && addressDistinguish.ID != 0 {
|
||
if err = json.Unmarshal([]byte(addressDistinguish.Info), &result); err == nil {
|
||
return result, err
|
||
}
|
||
}
|
||
result, err = api.TxAPI.AddressDistinguish(address)
|
||
result.Lng, result.Lat, err = api.AutonaviAPI.GetCoordinateFromAddressByPage(result.AddressDetail, result.CityCode)
|
||
if data, err := json.Marshal(result); err == nil {
|
||
addressDistinguish.Info = string(data)
|
||
dao.CreateEntity(db, addressDistinguish)
|
||
}
|
||
return result, err
|
||
}
|
||
|
||
func UpdateJob(ctx *jxcontext.Context, payload map[string]interface{}) (err error) {
|
||
var (
|
||
db = dao.GetDB()
|
||
jobExt = &model.JobExt{}
|
||
job2 = &model.Job{}
|
||
)
|
||
utils.Map2StructByJson(payload, &jobExt, false)
|
||
job2.ID = int(utils.MustInterface2Int64(payload["id"]))
|
||
dao.GetEntity(db, job2)
|
||
valid := dao.StrictMakeMapByStructObject(payload, job2, ctx.GetUserName())
|
||
if len(valid) > 0 {
|
||
txDB, _ := dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db, txDB)
|
||
panic(r)
|
||
}
|
||
}()
|
||
if _, err = dao.UpdateEntityByKV(db, job2, valid, nil); err != nil {
|
||
dao.Rollback(db, txDB)
|
||
return err
|
||
}
|
||
if len(jobExt.JobSteps) > 0 {
|
||
steps, _ := dao.GetJobSteps(db, job2.ID)
|
||
for _, v := range steps {
|
||
v.DeletedAt = time.Now()
|
||
dao.UpdateEntity(db, v, "DeletedAt")
|
||
}
|
||
for _, v := range jobExt.JobSteps {
|
||
v.DeletedAt = utils.DefaultTimeValue
|
||
v.LastOperator = ctx.GetUserName()
|
||
v.JobID = job2.ID
|
||
dao.CreateEntity(db, v)
|
||
}
|
||
}
|
||
if len(jobExt.JobImgs) > 0 {
|
||
imgs, _ := dao.GetJobImgs(db, job2.ID)
|
||
for _, v := range imgs {
|
||
dao.DeleteEntity(db, v)
|
||
}
|
||
for _, v := range jobExt.JobImgs {
|
||
v.LastOperator = ctx.GetUserName()
|
||
v.JobID = job2.ID
|
||
dao.CreateEntity(db, v)
|
||
}
|
||
}
|
||
dao.Commit(db, txDB)
|
||
}
|
||
return err
|
||
}
|
||
|
||
type Store struct {
|
||
model.ModelIDCULD
|
||
|
||
OriginalName string `orm:"-" json:"originalName"`
|
||
Name string `orm:"size(255)" json:"name"`
|
||
CityCode int `orm:"default(0);null" json:"cityCode"` // todo ?
|
||
DistrictCode int `orm:"default(0);null" json:"districtCode"` // todo ?
|
||
Address string `orm:"size(255)" json:"address"`
|
||
Tel1 string `orm:"size(32);index" json:"tel1"`
|
||
Tel2 string `orm:"size(32);index" json:"tel2"`
|
||
OpenTime1 int16 `json:"openTime1" validate:"max=2359,min=1,ltfield=CloseTime1"` // 930就表示9点半,用两个的原因是为了支持中午休息,1与2的时间段不能交叉,为0表示没有
|
||
CloseTime1 int16 `json:"closeTime1" validate:"max=2359,min=1` // 格式同上
|
||
OpenTime2 int16 `json:"openTime2" validate:"max=2359,min=1,ltfield=CloseTime2"` // 格式同上
|
||
CloseTime2 int16 `json:"closeTime2" validate:"max=2359,min=1` // 格式同上
|
||
Lng int `json:"-"` // 乘了10的6次方
|
||
Lat int `json:"-"` // 乘了10的6次方
|
||
DeliveryRangeType int8 `json:"deliveryRangeType"` // 参见相关常量定义
|
||
DeliveryRange string `orm:"type(text)" json:"deliveryRange"` // 如果DeliveryRangeType为DeliveryRangeTypePolygon,则为逗号分隔坐标,分号分隔的坐标点(坐标与Lng和Lat一样,都是整数),比如 121361504,31189308;121420555,31150238。否则为半径,单位为米
|
||
Status int `json:"status"`
|
||
AutoEnableAt *time.Time `orm:"type(datetime);null" json:"autoEnableAt"` // 自动营业时间(临时休息用)
|
||
ChangePriceType int8 `json:"changePriceType"` // 修改价格类型,即是否需要审核
|
||
SMSNotify int8 `orm:"column(sms_notify);" json:"smsNotify"` // 是否通过短信接收订单消息(每天只推一条)
|
||
SMSNotifyMark int8 `orm:"column(sms_notify_mark);" json:"smsNotifyMark"` //今天是否已经推送过订单消息
|
||
AutoReplyType int8 `json:"autoReplyType"` // 订单评价自动回复类型
|
||
LinkStoreID int `orm:"column(link_store_id);default(0);index" json:"linkStoreID"` // 关联门店ID
|
||
StoreLevel string `orm:"default(C);size(32)" json:"storeLevel"` // 门店等级(筛选用,京西的)
|
||
Comment string `orm:"size(255)" json:"comment"` //门店备注
|
||
|
||
PrinterDisabled int8 `orm:"default(0)" json:"printerDisabled"` // 是否禁用网络打印机
|
||
PrinterFontSize int8 `orm:"default(0)" json:"printerFontSize"` // 打印字体-1:小,0:正常,1:大
|
||
PrinterVendorID int `orm:"column(printer_vendor_id);" json:"printerVendorID"`
|
||
PrinterSN string `orm:"size(32);column(printer_sn);index" json:"printerSN"`
|
||
PrinterKey string `orm:"size(64)" json:"printerKey"`
|
||
PrinterBindInfo string `orm:"size(1024)" json:"-"`
|
||
|
||
IDCardFront string `orm:"size(255);column(id_card_front)" json:"idCardFront"`
|
||
IDCardBack string `orm:"size(255);column(id_card_back)" json:"idCardBack"`
|
||
IDCardHand string `orm:"size(255);column(id_card_hand)" json:"idCardHand"`
|
||
Licence string `orm:"size(255)" json:"licence"` // 营业执照图片
|
||
LicenceCode string `orm:"size(32)" json:"licenceCode"`
|
||
|
||
LicenceType int8 `json:"licenceType"` // 营业执照类型,0:个人,1:公司
|
||
LicenceCorpName string `orm:"size(64)" json:"licenceCorpName"` // 营业执照公司名称
|
||
LicenceOwnerName string `orm:"size(8)" json:"licenceOwnerName"` // 法人姓名
|
||
LicenceAddress string `orm:"size(255)" json:"licenceAddress"` // 地址
|
||
LicenceValid string `orm:"size(32)" json:"licenceValid"` // 有效期开始
|
||
LicenceExpire string `orm:"size(32)" json:"licenceExpire"` // 有效期结束
|
||
|
||
IDName string `orm:"size(8);column(id_name)" json:"idName"` // 身份证姓名
|
||
IDCode string `orm:"size(32);column(id_code)" json:"idCode"` // 身份证号
|
||
IDValid string `orm:"column(id_valid);size(32)" json:"idValid"` // 有效期开始
|
||
IDExpire string `orm:"column(id_expire);size(32)" json:"idExpire"` // 有效期结束
|
||
|
||
Licence2Image string `orm:"size(255)" json:"licence2Image"` // 食品经营许可证
|
||
Licence2Code string `orm:"size(32)" json:"licence2Code"` // 食品经营许可证编号
|
||
Licence2Valid string `orm:"size(32)" json:"licence2Valid"` // 有效期开始
|
||
Licence2Expire string `orm:"size(32)" json:"licence2Expire"` // 有效期结束
|
||
|
||
// MarketManName string `orm:"size(8)" json:"marketManName"` // 市场负责人姓名
|
||
MarketManPhone string `orm:"size(16)" json:"marketManPhone"` // 市场负责人电话
|
||
MarketManRole string `orm:"size(32)" json:"marketManRole"` // 市场负责人组(角色,单人)
|
||
|
||
JxBrandFeeFactor int `json:"jxBrandFeeFactor"` // 京西品牌费因子
|
||
MarketAddFeeFactor int `json:"marketAddFeeFactor"` // 市场附加费因子
|
||
|
||
PayeeName string `orm:"size(8)" json:"payeeName"` // 收款人姓名
|
||
PayeeAccountNo string `orm:"size(255)" json:"payeeAccountNo"` // 收款账号
|
||
PayeeBankBranchName string `orm:"size(255)" json:"payeeBankBranchName"` // 开户支行
|
||
PayeeBankCode string `orm:"size(8)" json:"payeeBankCode"` // 开户行代码
|
||
PayPercentage int `json:"payPercentage"`
|
||
OldPayPercentage int `json:"oldPayPercentage"`
|
||
|
||
StoreFrontPic string `orm:"size(255)" json:"storeFrontPic"` //门面照
|
||
StoreInPic string `orm:"size(255)" json:"storeInPic"` //门店内照片
|
||
|
||
// OperatorName string `orm:"size(8)" json:"operatorName"` // 运营人姓名
|
||
OperatorPhone string `orm:"size(16)" json:"operatorPhone"` // 京东运营人电话
|
||
OperatorRole string `orm:"size(32)" json:"operatorRole"` // 京东运营人组(角色)
|
||
|
||
OperatorPhone2 string `orm:"size(16)" json:"operatorPhone2"` // 美团运营人电话
|
||
OperatorRole2 string `orm:"size(32)" json:"operatorRole2"` // 美团运营人组(角色)
|
||
|
||
OperatorPhone3 string `orm:"size(16)" json:"operatorPhone3"` // 饿百运营人电话
|
||
OperatorRole3 string `orm:"size(32)" json:"operatorRole3"` // 饿百运营人组(角色)
|
||
|
||
PromoteInfo string `orm:"size(255)" json:"promoteInfo"` //门店公告(所有平台统一的公告)
|
||
IsBoughtMatter int `json:"isBoughtMatter"` //这周是否申请过物料
|
||
SoundPercentage int `json:"soundPercentage"` //打印机声音大小比例
|
||
Banner string `orm:"size(9999)" json:"banner"` //门店商城bannar图
|
||
BrandID int `orm:"column(brand_id)" json:"brandID"` //品牌ID
|
||
VendorStoreID string `orm:"column(vendor_store_id)" json:"vendorStoreID"`
|
||
}
|
||
|
||
func TempJob() (err error) {
|
||
//var (
|
||
// db = dao.GetDB()
|
||
// ctx = jxcontext.AdminCtx
|
||
// storesJD []*Store
|
||
// storesMT []*Store
|
||
//)
|
||
//db.Db.Using("c4")
|
||
//sql := `
|
||
// SELECT a.*, b.vendor_store_id
|
||
// FROM store a
|
||
// JOIN store_map b ON a.id = b.store_id AND b.vendor_id = 0 AND b.deleted_at = ? AND b.vendor_store_id <> ''
|
||
// WHERE a.deleted_at = ?
|
||
// AND a.id <> 667281
|
||
// AND a.id <> 667278
|
||
// AND a.status IN (1,0)
|
||
//`
|
||
//sqlParams := []interface{}{utils.DefaultTimeValue, utils.DefaultTimeValue}
|
||
//if err = dao.GetRows(db, &storesJD, sql, sqlParams); err != nil {
|
||
// return err
|
||
//}
|
||
//sql2 := `
|
||
// SELECT a.*, b.vendor_store_id
|
||
// FROM store a
|
||
// JOIN store_map b ON a.id = b.store_id AND b.vendor_id = 1 AND b.deleted_at = ? AND b.vendor_store_id <> ''
|
||
// WHERE a.deleted_at = ?
|
||
// AND a.id <> 667281
|
||
// AND a.id <> 667278
|
||
// AND a.status IN (1,0)
|
||
//`
|
||
//sqlParams2 := []interface{}{utils.DefaultTimeValue, utils.DefaultTimeValue}
|
||
//if err = dao.GetRows(db, &storesMT, sql2, sqlParams2); err != nil {
|
||
// return err
|
||
//}
|
||
//db.Db.Using("default")
|
||
//task := tasksch.NewParallelTask("TempJob", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(true), ctx,
|
||
// func(task2 *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||
// step := batchItemList[0].(int)
|
||
// switch step {
|
||
// case 0:
|
||
// task := tasksch.NewParallelTask("TempJob1", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(true), ctx,
|
||
// func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||
// store := batchItemList[0].(*Store)
|
||
// job := &model.Job{
|
||
// UserID: "906380C7390E11EB8831525400C36BDA",
|
||
// JobCategoryID: 3,
|
||
// Title: "京东(" + store.Name + ")",
|
||
// Content: "领取任务后,需要尽快去完成,并提交截图。如超时未完成,任务会被取消",
|
||
// Count: 1000,
|
||
// AvgPrice: 300,
|
||
// TotalPrice: 300000,
|
||
// Status: 0,
|
||
// Address: store.Address,
|
||
// StoreURL: store.VendorStoreID,
|
||
// SurplusCount: 1000,
|
||
// JobLimitAt: 72,
|
||
// AuditLimitAt: 168,
|
||
// LimitCountType: 3,
|
||
// VendorID: 0,
|
||
// CashbackType: 1,
|
||
// JobLat: jxutils.IntCoordinate2Standard(store.Lat),
|
||
// JobLng: jxutils.IntCoordinate2Standard(store.Lng),
|
||
// Lng: store.Lng,
|
||
// Lat: store.Lat,
|
||
// JobCityCode: store.CityCode,
|
||
// }
|
||
// finishAt := utils.Str2Time("2021-12-31 00:00:00")
|
||
// job.FinishedAt = &finishAt
|
||
// dao.WrapAddIDCULDEntity(job, ctx.GetUserName())
|
||
// if err = dao.CreateEntity(db, job); err == nil {
|
||
// jobsteps, _ := dao.GetJobSteps(db, 171)
|
||
// for _, v := range jobsteps {
|
||
// jobStep := &model.JobStep{
|
||
// JobID: job.ID,
|
||
// StepCount: v.StepCount,
|
||
// Content: v.Content,
|
||
// Img: v.Img,
|
||
// Type: v.Type,
|
||
// }
|
||
// dao.WrapAddIDCULDEntity(jobStep, ctx.GetUserName())
|
||
// err = dao.CreateEntity(db, jobStep)
|
||
// }
|
||
// jobImgs, _ := dao.GetJobImgs(db, 171)
|
||
// for _, v := range jobImgs {
|
||
// jobImg := &model.JobImg{
|
||
// JobID: job.ID,
|
||
// Img: v.Img,
|
||
// }
|
||
// dao.WrapAddIDCULEntity(jobImg, ctx.GetUserName())
|
||
// err = dao.CreateEntity(db, jobImg)
|
||
// }
|
||
// }
|
||
// return retVal, err
|
||
// }, storesJD)
|
||
// tasksch.HandleTask(task, task2, true).Run()
|
||
// task.GetResult(0)
|
||
// case 1:
|
||
// task := tasksch.NewParallelTask("TempJob2", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(true), ctx,
|
||
// func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
|
||
// store := batchItemList[0].(*Store)
|
||
// job := &model.Job{
|
||
// UserID: "906380C7390E11EB8831525400C36BDA",
|
||
// JobCategoryID: 3,
|
||
// Title: "美团(" + store.Name + ")",
|
||
// Content: "领取任务后,需要尽快去完成,并提交截图。如超时未完成,任务会被取消",
|
||
// Count: 1000,
|
||
// AvgPrice: 300,
|
||
// TotalPrice: 300000,
|
||
// Status: 0,
|
||
// Address: store.Address,
|
||
// StoreURL: store.VendorStoreID,
|
||
// SurplusCount: 1000,
|
||
// JobLimitAt: 72,
|
||
// AuditLimitAt: 168,
|
||
// LimitCountType: 3,
|
||
// VendorID: 1,
|
||
// CashbackType: 1,
|
||
// JobLat: jxutils.IntCoordinate2Standard(store.Lat),
|
||
// JobLng: jxutils.IntCoordinate2Standard(store.Lng),
|
||
// Lng: store.Lng,
|
||
// Lat: store.Lat,
|
||
// JobCityCode: store.CityCode,
|
||
// }
|
||
// finishAt := utils.Str2Time("2021-12-31 00:00:00")
|
||
// job.FinishedAt = &finishAt
|
||
// dao.WrapAddIDCULDEntity(job, ctx.GetUserName())
|
||
// if err = dao.CreateEntity(db, job); err == nil {
|
||
// jobsteps, _ := dao.GetJobSteps(db, 173)
|
||
// for _, v := range jobsteps {
|
||
// jobStep := &model.JobStep{
|
||
// JobID: job.ID,
|
||
// StepCount: v.StepCount,
|
||
// Content: v.Content,
|
||
// Img: v.Img,
|
||
// Type: v.Type,
|
||
// }
|
||
// dao.WrapAddIDCULDEntity(jobStep, ctx.GetUserName())
|
||
// err = dao.CreateEntity(db, jobStep)
|
||
// }
|
||
// jobImgs, _ := dao.GetJobImgs(db, 173)
|
||
// for _, v := range jobImgs {
|
||
// jobImg := &model.JobImg{
|
||
// JobID: job.ID,
|
||
// Img: v.Img,
|
||
// }
|
||
// dao.WrapAddIDCULEntity(jobImg, ctx.GetUserName())
|
||
// err = dao.CreateEntity(db, jobImg)
|
||
// }
|
||
// }
|
||
// return retVal, err
|
||
// }, storesMT)
|
||
// tasksch.HandleTask(task, task2, true).Run()
|
||
// task.GetResult(0)
|
||
// }
|
||
// return retVal, err
|
||
// }, []int{0, 1})
|
||
//tasksch.HandleTask(task, nil, true).Run()
|
||
//task.GetID()
|
||
return err
|
||
}
|
||
|
||
func GetUnionActList(ctx *jxcontext.Context, vendorID, actType int) (actList []*partner.ActivityList, err error) {
|
||
if handler := partner.GetHandler(vendorID); handler != nil {
|
||
actList, err = handler.GetUnionActList(ctx, actType)
|
||
}
|
||
return actList, err
|
||
}
|
||
|
||
func ShareUnionLink(ctx *jxcontext.Context, jobID, shareType, linkType, resourceType int, goodsID string) (link string, err error) {
|
||
var (
|
||
job = &model.Job{}
|
||
db = dao.GetDB()
|
||
sid string //推广位ID,美团为userID,淘宝饿了么本地化暂时是固定的京西推广位ID,pdd为表中推广位ID
|
||
//userID = ctx.GetUserID()
|
||
mobile, userID = ctx.GetMobileAndUserID()
|
||
userBinds []*model.UserUnionBind
|
||
)
|
||
job.ID = jobID
|
||
if err = dao.GetEntity(db, job); err != nil {
|
||
return "", err
|
||
}
|
||
vendorID := job.VendorID
|
||
handler := partner.GetHandler(vendorID)
|
||
//1、建推广位(本地和平台)
|
||
if userBinds, err = dao.GetUserUnionBind(db, userID, vendorID); err != nil {
|
||
return "", err
|
||
}
|
||
//本地已有推广位
|
||
if len(userBinds) > 0 {
|
||
sid = userBinds[0].UnionID
|
||
} else {
|
||
userBind := &model.UserUnionBind{
|
||
UserID: userID,
|
||
VendorID: vendorID,
|
||
}
|
||
dao.WrapAddIDCULDEntity(userBind, ctx.GetUserName())
|
||
if handler != nil {
|
||
if sid, err = handler.CreateUnionPosition(ctx, mobile+utils.Int2Str(jobID)); err == nil {
|
||
if sid == "" {
|
||
sid = mobile + utils.Int2Str(jobID)
|
||
if vendorID == model.VendorIDTB {
|
||
sid = utils.Int2Str(tbunionapi.JxAdzoneID)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
userBind.UnionID = sid
|
||
dao.CreateEntity(db, userBind)
|
||
}
|
||
//2、分享链接
|
||
if handler != nil {
|
||
if link, err = handler.ShareUnionLink(ctx, linkType, job.UnionActID, sid, userID, resourceType, goodsID); err == nil {
|
||
if vendorID == model.VendorIDMTWM || vendorID == model.VendorIDTB {
|
||
if linkType == partner.LinkTypeWeiXinMini {
|
||
if resBinary, _, err := jxutils.DownloadFileByURL(link); err == nil {
|
||
if downloadURL, err := jxutils.UploadExportContent(resBinary, utils.Int64ToStr(time.Now().Unix())+link[strings.LastIndex(link, "/")+1:len(link)]); err == nil {
|
||
if err == nil {
|
||
link = jxutils.MixWatermarkImg(downloadURL+"?imageView2/1/w/120/h/120/q/75", job.UnionImg, job.UnionQrcodePosition)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return link, err
|
||
}
|
||
|
||
type GetUnionJobOrderInfoResult struct {
|
||
AcceptCouponCount int `json:"acceptCouponCount"` //领取优惠券数量
|
||
FinishedOrderCount int `json:"finishedOrderCount"` //完成订单量
|
||
IncomePrice int `json:"incomePrice"` //收入
|
||
}
|
||
|
||
func GetUnionJobOrderInfo(ctx *jxcontext.Context, jobOrderID int) (getUnionJobOrderInfoResult *GetUnionJobOrderInfoResult, err error) {
|
||
var (
|
||
jobOrder = &model.JobOrder{}
|
||
job = &model.Job{}
|
||
db = dao.GetDB()
|
||
)
|
||
jobOrder.ID = int64(jobOrderID)
|
||
if err = dao.GetEntity(db, jobOrder); err != nil {
|
||
return nil, err
|
||
}
|
||
job.ID = jobOrder.JobID
|
||
if err = dao.GetEntity(db, job); err != nil {
|
||
return nil, err
|
||
}
|
||
if job.JobCategoryID != model.JobCategoryIDUnion {
|
||
return nil, fmt.Errorf("只允许联盟任务才能查看!")
|
||
}
|
||
userBill, err := dao.GetUserBill(db, jobOrder.UserID, "")
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
incomes, err := dao.GetBillIncome(db, job.ID, userBill.BillID)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
incomeTotal := 0
|
||
for _, v := range incomes {
|
||
incomeTotal += v.IncomePrice
|
||
}
|
||
getUnionJobOrderInfoResult.IncomePrice = incomeTotal
|
||
return getUnionJobOrderInfoResult, err
|
||
}
|
||
|
||
func GetVendorMatters(ctx *jxcontext.Context, vendorID int, vendorCatID, keyword string, offset, pageSize, sortType int, listID string) (result *partner.MatterList, err error) {
|
||
handler := partner.GetHandler(vendorID)
|
||
return handler.GetUnionMatterList(ctx, vendorCatID, keyword, offset/pageSize+1, pageSize, sortType, listID)
|
||
}
|
||
|
||
func GetVendorMatterDetail(ctx *jxcontext.Context, vendorID int, goodsID string) (goodsDetail *partner.GoodsDetail, err error) {
|
||
handler := partner.GetHandler(vendorID)
|
||
return handler.GetUnionMatterDetail(ctx, goodsID)
|
||
}
|
||
|
||
func GetVendorMatterRcmmd(ctx *jxcontext.Context, vendorID int, goodsID string, rcmmdType, offset, pageSize int) (result *partner.MatterList, err error) {
|
||
handler := partner.GetHandler(vendorID)
|
||
return handler.GetUnionMatterListRcmmd(ctx, goodsID, rcmmdType, offset, pageSize)
|
||
}
|