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 }