266 lines
8.8 KiB
Go
266 lines
8.8 KiB
Go
package orderman
|
||
|
||
import (
|
||
"fmt"
|
||
"time"
|
||
|
||
"git.rosy.net.cn/jx-callback/business/partner"
|
||
|
||
"git.rosy.net.cn/baseapi/platformapi/dadaapi"
|
||
|
||
"git.rosy.net.cn/baseapi/utils"
|
||
"git.rosy.net.cn/jx-callback/business/jxcallback/scheduler"
|
||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||
"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"
|
||
"git.rosy.net.cn/jx-callback/globals"
|
||
"github.com/astaxie/beego/adapter/orm"
|
||
)
|
||
|
||
var (
|
||
waybillOrderStatusMap = map[int]int{
|
||
model.WaybillStatusApplyFailedGetGoods: model.OrderStatusApplyFailedGetGoods,
|
||
model.WaybillStatusAgreeFailedGetGoods: model.OrderStatusAgreeFailedGetGoods,
|
||
model.WaybillStatusRefuseFailedGetGoods: model.OrderStatusRefuseFailedGetGoods,
|
||
model.WaybillStatusDeliverFailed: model.OrderStatusDeliverFailed,
|
||
}
|
||
complaintReasonsMap = map[int]string{
|
||
1: "骑手态度恶劣",
|
||
2: "骑手接单后未取货",
|
||
3: "骑手取货太慢",
|
||
4: "骑手送货太慢",
|
||
5: "货品未送达",
|
||
6: "货品有损坏",
|
||
7: "骑手违规收取顾客其他费用",
|
||
69: "骑手恶意取消订单",
|
||
71: "骑手提前点击取货/送达",
|
||
}
|
||
)
|
||
|
||
func (w *OrderManager) LoadPendingWaybills() []*model.Waybill {
|
||
db := orm.NewOrm()
|
||
var bills []*model.Waybill
|
||
tillTime := time.Now().Add(-pendingOrderGapMax)
|
||
_, err := db.Raw(`
|
||
SELECT t1.*
|
||
FROM waybill t1
|
||
JOIN goods_order t2 ON t2.vendor_order_id = t1.vendor_order_id
|
||
AND t2.vendor_id = t1.order_vendor_id
|
||
AND t2.order_created_at >= ?
|
||
AND t2.status < ?
|
||
WHERE t1.waybill_created_at >= ?
|
||
AND t1.status < ?
|
||
`, tillTime, model.OrderStatusEndBegin, tillTime, model.WaybillStatusEndBegin).QueryRows(&bills)
|
||
if err != nil {
|
||
globals.SugarLogger.Warnf("LoadPendingWaybills load pending waybills error:%v", err)
|
||
return nil
|
||
}
|
||
return bills
|
||
}
|
||
|
||
func (w *OrderManager) onWaybillNew(bill2 *model.Waybill, db *dao.DaoDB) (isDuplicated bool, err error) {
|
||
globals.SugarLogger.Debugf("onWaybillNew bill:%v", bill2)
|
||
isDuplicated, err = addOrderOrWaybillStatus(model.Waybill2Status(bill2), db)
|
||
if err == nil && !isDuplicated {
|
||
bill2.ID = 0
|
||
bill2.WaybillCreatedAt = bill2.StatusTime
|
||
bill2.WaybillFinishedAt = utils.DefaultTimeValue
|
||
billCopied := *bill2
|
||
bill := &billCopied
|
||
created, _, err2 := db.Db.ReadOrCreate(bill, "VendorWaybillID", "WaybillVendorID")
|
||
if err = err2; err == nil {
|
||
if !created {
|
||
bill.DuplicatedCount++
|
||
if bill2.VendorOrderID == bill2.VendorWaybillID { // 购物平台(比如京东)重新建的运单,单号始终是与订单相同的
|
||
globals.SugarLogger.Infof("onWaybillNew duplicated1, DuplicatedCount:%d, bill:%v msg received", bill2.DuplicatedCount, bill2)
|
||
bill2.ID = bill.ID
|
||
bill2.CreatedAt = bill.CreatedAt
|
||
bill2.DuplicatedCount = bill.DuplicatedCount
|
||
err = utils.CallFuncLogError(func() error {
|
||
_, err = db.Db.Update(bill2) //更新所有字段
|
||
return err
|
||
}, "onWaybillNew Update1")
|
||
} else {
|
||
globals.SugarLogger.Infof("onWaybillNew duplicated2 DuplicatedCount:%d, bill:%v msg received", bill.DuplicatedCount, bill2)
|
||
isDuplicated = true
|
||
err = utils.CallFuncLogError(func() error {
|
||
_, err = db.Db.Update(bill, "DuplicatedCount")
|
||
return err
|
||
}, "onWaybillNew Update2")
|
||
}
|
||
} else {
|
||
*bill2 = *bill
|
||
globals.SugarLogger.Debugf("onWaybillNew created bill:%v", bill2)
|
||
}
|
||
} else {
|
||
globals.SugarLogger.Warnf("onWaybillNew create bill:%v, error:%v", bill2, err)
|
||
}
|
||
}
|
||
return isDuplicated, err
|
||
}
|
||
|
||
func (w *OrderManager) OnWaybillStatusChanged(bill *model.Waybill) (err error) {
|
||
var isDuplicated bool
|
||
if bill.ActualFee == 0 {
|
||
bill.ActualFee = bill.DesiredFee + bill.TipFee
|
||
}
|
||
bill.CourierMobile = jxutils.FormalizeMobile(bill.CourierMobile)
|
||
db := dao.GetDB()
|
||
dao.Begin(db)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
dao.Rollback(db)
|
||
panic(r)
|
||
}
|
||
}()
|
||
duplicatedCount := 0
|
||
if bill.Status == model.WaybillStatusNew {
|
||
isDuplicated, err = w.onWaybillNew(bill, db)
|
||
if isDuplicated {
|
||
duplicatedCount = 1
|
||
}
|
||
} else {
|
||
existingBill, err2 := w.LoadWaybill(bill.VendorWaybillID, bill.WaybillVendorID)
|
||
// todo
|
||
if err2 == nil {
|
||
bill.DeliveryFlag = existingBill.DeliveryFlag
|
||
}
|
||
if bill.Status == model.WaybillStatusAccepted { // 处理美团配送丢失新运单消息的情况
|
||
if err2 != nil {
|
||
if dao.IsNoRowsError(err2) || err2 == ErrCanNotFindWaybill {
|
||
existingBill = bill
|
||
billCopy := *bill
|
||
billCopy.Status = model.WaybillStatusNew
|
||
if isDuplicated, err = w.onWaybillNew(&billCopy, db); err != nil {
|
||
dao.Rollback(db)
|
||
return err
|
||
}
|
||
dao.Commit(db)
|
||
// 进运单调度器OnWaybillStatusChanged之前要确保事务是提交了的,否则会导致死锁
|
||
scheduler.CurrentScheduler.OnWaybillStatusChanged(&billCopy, false)
|
||
dao.Begin(db)
|
||
} else {
|
||
dao.Rollback(db)
|
||
return err2
|
||
}
|
||
}
|
||
// 运单消息错序,之前已经结束了,直接返回
|
||
if existingBill.Status >= model.WaybillStatusEndBegin {
|
||
dao.Commit(db)
|
||
return nil
|
||
}
|
||
}
|
||
addParams := orm.Params{}
|
||
if bill.Status >= model.WaybillStatusAccepted {
|
||
if bill.Status == model.WaybillStatusAccepted {
|
||
if bill.DesiredFee > 0 {
|
||
addParams["desired_fee"] = bill.DesiredFee
|
||
}
|
||
if bill.ActualFee > 0 {
|
||
addParams["actual_fee"] = bill.ActualFee
|
||
}
|
||
}
|
||
if bill.CourierMobile != "" {
|
||
addParams["courier_name"] = bill.CourierName
|
||
addParams["courier_mobile"] = bill.CourierMobile
|
||
}
|
||
if bill.Status >= model.WaybillStatusEndBegin {
|
||
addParams["waybill_finished_at"] = bill.StatusTime
|
||
}
|
||
}
|
||
duplicatedCount, err = w.addWaybillStatus(bill, db, addParams)
|
||
if err != nil {
|
||
dao.Rollback(db)
|
||
return err
|
||
}
|
||
}
|
||
if err == nil {
|
||
dao.Commit(db)
|
||
if duplicatedCount == 0 {
|
||
scheduler.CurrentScheduler.OnWaybillStatusChanged(bill, false)
|
||
}
|
||
} else {
|
||
dao.Rollback(db)
|
||
}
|
||
if bill.VendorOrderID == bill.VendorWaybillID {
|
||
if status, ok := waybillOrderStatusMap[bill.Status]; ok {
|
||
fakeOrderStatus := &model.OrderStatus{
|
||
VendorOrderID: bill.VendorOrderID,
|
||
VendorID: bill.OrderVendorID,
|
||
OrderType: model.OrderTypeOrder,
|
||
RefVendorOrderID: bill.VendorOrderID,
|
||
RefVendorID: bill.OrderVendorID,
|
||
Status: status,
|
||
VendorStatus: bill.VendorStatus,
|
||
StatusTime: bill.StatusTime,
|
||
Remark: bill.Remark,
|
||
}
|
||
w.OnOrderStatusChanged(bill.VendorOrgCode, fakeOrderStatus)
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func (w *OrderManager) addWaybillStatus(bill *model.Waybill, db *dao.DaoDB, addParams orm.Params) (duplicatedCount int, err error) {
|
||
waybillStatus := model.Waybill2Status(bill)
|
||
isDuplicated, err := addOrderOrWaybillStatus(waybillStatus, db)
|
||
if err == nil && !isDuplicated {
|
||
if waybillStatus.Status > model.WaybillStatusUnknown { // todo 这里应该和addOrderStatus一样的改法,状态不能回绕
|
||
params := utils.MergeMaps(orm.Params{
|
||
"status": bill.Status,
|
||
"vendor_status": bill.VendorStatus,
|
||
"status_time": bill.StatusTime,
|
||
}, addParams)
|
||
utils.CallFuncLogError(func() error {
|
||
_, err = db.Db.QueryTable("waybill").Filter("vendor_waybill_id", bill.VendorWaybillID).Filter("waybill_vendor_id", bill.WaybillVendorID).Filter("status__lte", bill.Status).Update(params)
|
||
return err
|
||
}, "addWaybillStatus update waybill status, bill:%v", bill)
|
||
} else {
|
||
duplicatedCount = -1
|
||
}
|
||
} else {
|
||
duplicatedCount = 1
|
||
}
|
||
return duplicatedCount, err
|
||
}
|
||
|
||
func (c *OrderManager) LoadWaybill(vendorWaybillID string, waybillVendorID int) (bill *model.Waybill, err error) {
|
||
db := orm.NewOrm()
|
||
bill = &model.Waybill{
|
||
VendorWaybillID: vendorWaybillID,
|
||
WaybillVendorID: waybillVendorID,
|
||
}
|
||
if err = db.Read(bill, "VendorWaybillID", "WaybillVendorID"); err != nil {
|
||
bill = nil
|
||
if err == orm.ErrNoRows {
|
||
err = ErrCanNotFindWaybill
|
||
}
|
||
globals.SugarLogger.Infof("LoadWaybill vendorWaybillID:%s failed with error:%v", vendorWaybillID, err)
|
||
}
|
||
return bill, err
|
||
}
|
||
|
||
func GetComplaintReasons() (complaintReasonList []*dadaapi.ComplaintReason) {
|
||
for k, v := range complaintReasonsMap {
|
||
complaintReason := &dadaapi.ComplaintReason{
|
||
ID: k,
|
||
Reason: v,
|
||
}
|
||
complaintReasonList = append(complaintReasonList, complaintReason)
|
||
}
|
||
return complaintReasonList
|
||
}
|
||
|
||
func ComplaintRider(ctx *jxcontext.Context, vendorOrderID string, vendorID, waybillVendorID, complaintID int) (err error) {
|
||
db := dao.GetDB()
|
||
p := partner.GetDeliveryPlatformFromVendorID(waybillVendorID).Handler
|
||
wayBillList, err := dao.GetWayBillByOrderID(db, 0, vendorID, waybillVendorID, vendorOrderID)
|
||
if err == nil && len(wayBillList) > 0 {
|
||
err = p.ComplaintRider(wayBillList[0], complaintID, complaintReasonsMap[complaintID])
|
||
} else {
|
||
return fmt.Errorf("未查询到到相关订单!订单号:[%v] ,厂商:[%v],运送厂商:[%v]", vendorOrderID, vendorID, waybillVendorID)
|
||
}
|
||
return err
|
||
}
|