160 lines
4.9 KiB
Go
160 lines
4.9 KiB
Go
package controller
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"git.rosy.net.cn/baseapi/utils"
|
|
"git.rosy.net.cn/jx-callback/business/model"
|
|
"git.rosy.net.cn/jx-callback/globals"
|
|
"github.com/astaxie/beego/orm"
|
|
)
|
|
|
|
const (
|
|
WaybillStatusUnknown = 0
|
|
|
|
WaybillStatusNew = 5
|
|
WaybillStatusAcceptCanceled = 8
|
|
WaybillStatusAccepted = 10
|
|
WaybillStatusCourierArrived = 15 // 此状态是可选的,明确写出来是因为还是较重要的状态,但业务逻辑不应依赖此状态
|
|
WaybillStatusDelivering = 20
|
|
|
|
WaybillStatusDelivered = 105
|
|
WaybillStatusCanceled = 115
|
|
WaybillStatusFailed = 120
|
|
)
|
|
|
|
type DeliveryProvider interface {
|
|
}
|
|
|
|
type WaybillController struct {
|
|
WaybillMap SyncMapWithTimeout
|
|
deliveryProviders map[int]DeliveryProvider
|
|
}
|
|
|
|
func NewWaybillManager() *WaybillController {
|
|
return &WaybillController{
|
|
deliveryProviders: make(map[int]DeliveryProvider),
|
|
}
|
|
}
|
|
|
|
func (w *WaybillController) RegisterDeliveryProvider(vendorID int, handler DeliveryProvider) {
|
|
if !(vendorID >= VendorIDDeliveryBegin && vendorID <= VendorIDDeliveryEnd ||
|
|
vendorID >= VendorIDPurchaseBegin && vendorID <= VendorIDPurchaseEnd) {
|
|
panic(fmt.Sprintf("delivery provider vendor:%d is illegal", vendorID))
|
|
}
|
|
if _, ok := w.deliveryProviders[vendorID]; ok {
|
|
panic(fmt.Sprintf("delivery provider vendor:%d, already exists", vendorID))
|
|
}
|
|
w.deliveryProviders[vendorID] = handler
|
|
}
|
|
|
|
func (w *WaybillController) onWaybillNew(bill *model.Waybill) (err error) {
|
|
db := orm.NewOrm()
|
|
bill.Status = WaybillStatusNew
|
|
isDuplicated, err := addOrderOrWaybillStatus(w.waybill2Status(bill), db)
|
|
if !isDuplicated {
|
|
bill.Status = WaybillStatusNew
|
|
bill.WaybillFinishedAt = DefaultTimeValue
|
|
bill.ID = 0
|
|
created, _, err := db.ReadOrCreate(bill, "VendorWaybillID", "WaybillVendorID")
|
|
if err == nil {
|
|
w.WaybillMap.Store(ComposeUniversalOrderID(bill.VendorWaybillID, bill.WaybillVendorID), bill.ID)
|
|
if !created {
|
|
bill.DuplicatedCount++
|
|
db.Update(bill, "DuplicatedCount")
|
|
globals.SugarLogger.Infof("duplicated bill:%v vendorID:%d, msg received", bill.VendorWaybillID, bill.WaybillVendorID)
|
|
}
|
|
err = OrderManager.OnWaybillStatusChanged(bill, db)
|
|
} else {
|
|
globals.SugarLogger.Warnf("create bill:%v, error:%v", bill, err)
|
|
}
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (w *WaybillController) OnWaybillStatusChanged(bill *model.Waybill) (err error) {
|
|
if bill.Status == WaybillStatusNew {
|
|
err = w.onWaybillNew(bill)
|
|
} else if bill.Status == WaybillStatusAccepted {
|
|
err = w.onWaybillAccepted(bill)
|
|
} else {
|
|
db := orm.NewOrm()
|
|
isDuplicated, err2 := w.addWaybillStatus(bill, db)
|
|
if err2 == nil && !isDuplicated {
|
|
err2 = OrderManager.OnWaybillStatusChanged(bill, db)
|
|
}
|
|
err = err2
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (w *WaybillController) onWaybillAccepted(bill *model.Waybill) (err error) {
|
|
db := orm.NewOrm()
|
|
bill.Status = WaybillStatusAccepted
|
|
isDuplicated, err := w.addWaybillStatus(bill, db)
|
|
if !isDuplicated {
|
|
err = w.updateWaybillPKID(bill, db)
|
|
if err == nil {
|
|
utils.CallFuncLogError(func() error {
|
|
_, err = db.Update(bill, "CourierName", "CourierMobile")
|
|
return err
|
|
}, "update waybill info")
|
|
if err == nil {
|
|
err = OrderManager.OnWaybillStatusChanged(bill, db)
|
|
}
|
|
}
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (w *WaybillController) addWaybillStatus(bill *model.Waybill, db orm.Ormer) (isDuplicated bool, err error) {
|
|
if db == nil {
|
|
db = orm.NewOrm()
|
|
}
|
|
waybillStatus := w.waybill2Status(bill)
|
|
isDuplicated, err = addOrderOrWaybillStatus(waybillStatus, db)
|
|
if !isDuplicated && waybillStatus.Status > WaybillStatusUnknown {
|
|
if err = w.updateWaybillPKID(bill, db); err == nil {
|
|
bill.Status = waybillStatus.Status
|
|
bill.VendorStatus = waybillStatus.VendorStatus
|
|
utils.CallFuncLogError(func() error {
|
|
columns := []string{"Status", "VendorStatus"}
|
|
if waybillStatus.Status >= OrderStatusDelivered {
|
|
bill.WaybillFinishedAt = waybillStatus.StatusTime
|
|
columns = append(columns, "WaybillFinishedAt")
|
|
}
|
|
_, err := db.Update(bill, columns...)
|
|
return err
|
|
}, "update waybill")
|
|
}
|
|
}
|
|
return isDuplicated, err
|
|
}
|
|
|
|
func (w *WaybillController) waybill2Status(bill *model.Waybill) (retVal *model.OrderStatus) {
|
|
retVal = &model.OrderStatus{
|
|
VendorOrderID: bill.VendorWaybillID,
|
|
VendorID: bill.WaybillVendorID,
|
|
OrderType: OrderTypeWaybill,
|
|
Status: bill.Status,
|
|
VendorStatus: bill.VendorStatus,
|
|
StatusTime: bill.WaybillCreatedAt,
|
|
}
|
|
return retVal
|
|
}
|
|
|
|
func (w *WaybillController) updateWaybillPKID(bill *model.Waybill, db orm.Ormer) (err error) {
|
|
value, ok := w.WaybillMap.Load(ComposeUniversalOrderID(bill.VendorWaybillID, bill.WaybillVendorID))
|
|
if !ok {
|
|
err = db.Read(bill, "VendorWaybillID", "WaybillVendorID")
|
|
// todo 这里应该要报警,但测试阶段先去掉
|
|
// utils.CallFuncLogError(func() error {
|
|
// err = db.Read(bill, "VendorWaybillID", "WaybillVendorID")
|
|
// return err
|
|
// }, "can not get waybill info from db")
|
|
} else {
|
|
bill.ID = value.(int64)
|
|
}
|
|
return err
|
|
}
|