package controller import ( "encoding/json" "git.rosy.net.cn/baseapi/platformapi/jdapi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" "git.rosy.net.cn/jx-callback/legacy/controllers" "git.rosy.net.cn/jx-callback/legacy/freshfood" "git.rosy.net.cn/jx-callback/legacy/jd/models" "github.com/astaxie/beego/orm" ) const ( MsgNotHandledCode = "NH" ) var ( orderMsgChan chan jdapi.CallbackOrderMsg ) type OrderController struct { } func InitOrder() { orderMsgChan = make(chan jdapi.CallbackOrderMsg, 128) go orderMsgHandlerRoutine() // 另外当前这个模式可能会出现同一个订单的消息,虽然远程推送过来顺序是对的,但经过处理后推送到freshfood时乱序(因为每个消息的处理时间是不确定的) handlePendingOrderMsg() } func handlePendingOrderMsg() { var ordersInfo []models.Jdorder db := orm.NewOrm() _, err := db.Raw("SELECT * FROM jdorder WHERE orderstatustime >= DATE_FORMAT(DATE_ADD(NOW(), interval -1 day), '%Y-%m-%d %H:%i:%s') AND code = ?", MsgNotHandledCode).QueryRows(&ordersInfo) if err != nil { globals.SugarLogger.Errorf("can not get jdorder from db, error:%v", err) } else { for _, jdOrderInfo := range ordersInfo { orderMsg := &jdapi.CallbackOrderMsg{ ID: jdOrderInfo.ID, BillID: utils.Int64ToStr(jdOrderInfo.JdOrderID), StatusID: utils.Int2Str(jdOrderInfo.OrderStatus), Timestamp: jdOrderInfo.OrderStatusTime, } addOrderMsg(orderMsg) } } } func orderMsgHandlerRoutine() { for { msg := <-orderMsgChan globals.SugarLogger.Debugf("orderMsgHandlerRoutine:%v", msg) go handleOrderMsg(&msg) } } func addOrderMsg(msg *jdapi.CallbackOrderMsg) { globals.SugarLogger.Debugf("addOrderMsg:%v", msg) orderMsgChan <- *msg } func handleOrderMsg(msg *jdapi.CallbackOrderMsg) { globals.SugarLogger.Debugf("handleOrderMsg:%v", msg) switch msg.StatusID { case jdapi.OrderStatusNew: newOrder(msg) case jdapi.OrderStatusAdjust: adjustOrder(msg) default: normalOrderStatus(msg) } } // -------------- func (c *OrderController) OrderStatus(msg *jdapi.CallbackOrderMsg) *jdapi.CallbackResponse { if msg.StatusID != jdapi.OrderStatusNew && msg.StatusID != jdapi.OrderStatusAdjust { err := normalOrderStatus(msg) if err != nil { return jdapi.Err2CallbackResponse(err, "") } } else { db := orm.NewOrm() jdorderid := utils.Str2Int64(msg.BillID) status := int(utils.Str2Int64(msg.StatusID)) rec := &models.Jdorder{ Code: MsgNotHandledCode, JdOrderID: jdorderid, OrderStatus: status, OrderStatusTime: msg.Timestamp, } if created, _, err := db.ReadOrCreate(rec, "JdOrderID"); err == nil { msg.ID = rec.ID if created { if msg.StatusID != jdapi.OrderStatusNew && msg.StatusID != jdapi.OrderStatusAdjust { globals.SugarLogger.Warnf("order:%v get before create", msg) oldStatusID := msg.StatusID msg.StatusID = jdapi.OrderStatusNew addOrderMsg(msg) msg.StatusID = oldStatusID } addOrderMsg(msg) } else { if rec.OrderStatus != status { if msg.StatusID == jdapi.OrderStatusNew { globals.SugarLogger.Warnf("order:%v get after some other message:%d", msg, rec.OrderStatus) } else { rec.OrderStatus = status rec.OrderStatusTime = msg.Timestamp rec.Code = MsgNotHandledCode utils.CallFuncLogError(func() error { _, err := db.Update(rec, "OrderStatus", "OrderStatusTime", "Code") return err }, globals.ErrStrAccessDB) addOrderMsg(msg) } } else { globals.SugarLogger.Warnf("duplicated jd order msg:%v", msg) } } } else { globals.SugarLogger.Errorf("error when calling ReadOrCreate:%v", err) return jdapi.Err2CallbackResponse(err, "") } } return jdapi.SuccessResponse } func (c *OrderController) OrderDeliveryStatus(jdOrderDeliveryStatusMsg *jdapi.CallbackDeliveryStatusMsg) *jdapi.CallbackResponse { if err := freshfood.FreshFoodAPI.JDOrderDeliveryStatus(jdOrderDeliveryStatusMsg); err != nil { return jdapi.Err2CallbackResponse(err, "") } return jdapi.SuccessResponse } //----------- func OnNewOrder(msg *jdapi.CallbackOrderMsg, userMobile string, db orm.Ormer) { controllers.OnNewOrder(msg.BillID, controllers.JD_VENDORID, userMobile, 0, db, func(acceptIt bool) { globals.SugarLogger.Infof("OrderAcceptOperate billid:%v, acceptIt:%v", msg.BillID, acceptIt) api.JdAPI.OrderAcceptOperate(msg.BillID, acceptIt) }) } func newOrder(msg *jdapi.CallbackOrderMsg) error { result, err := api.JdAPI.LegacyQuerySingleOrder(msg.BillID) userMobile := "" var db orm.Ormer if err == nil { rec := &models.Jdorder{ ID: msg.ID, } rec.Code, _ = result["code"].(string) rec.Msg, _ = result["msg"].(string) rec.Success, _ = result["success"].(bool) rec.CityName = "all" data := result["data"].(map[string]interface{}) dataResult := data["result"].(map[string]interface{}) resultList, ok := dataResult["resultList"].([]interface{}) if ok && len(resultList) == 1 { resultList0 := resultList[0].(map[string]interface{}) orderStatus, _ := resultList0["orderStatus"].(json.Number).Int64() rec.JdOrderID = utils.Str2Int64(msg.BillID) rec.OrderStatus = int(orderStatus) rec.OrderStatusTime = resultList0["orderStatusTime"].(string) resultByteArr := utils.MustMarshal(data) rec.Data = utils.FilterMb4(string(resultByteArr)) rec.Data4Json = data userMobile = resultList0["buyerMobile"].(string) err = utils.CallFuncLogError(func() error { db = orm.NewOrm() _, err := db.Update(rec, "Data", "Code", "Msg", "Success", "CityName", "OrderStatus", "OrderStatusTime") return err }, globals.ErrStrAccessDB) freshfood.FreshFoodAPI.NewJDOrder(rec, msg.StatusID == jdapi.OrderStatusNew) } else { globals.SugarLogger.Errorf("can not get jdorder info:%v", msg.BillID) } } OnNewOrder(msg, userMobile, db) return err } func adjustOrder(msg *jdapi.CallbackOrderMsg) error { return newOrder(msg) } func normalOrderStatus(msg *jdapi.CallbackOrderMsg) (err error) { if msg.StatusID == jdapi.OrderStatusAddComment || msg.StatusID == jdapi.OrderStatusModifyComment { err = freshfood.FreshFoodAPI.JDOrderComment(msg) } else { db := orm.NewOrm() rec := &models.Jdorder{ JdOrderID: utils.Str2Int64(msg.BillID), } err = db.Read(rec, "JdOrderId") if err != nil { if err == orm.ErrNoRows { err = nil // 如果没有查到,不当成错误 } else { globals.SugarLogger.Warnf("error when accessing db err:%v, rec:%v", err, rec) } } else { if rec.OrderStatus == int(utils.Str2Int64(msg.StatusID)) { globals.SugarLogger.Infof("Duplicate message msg:%v", msg) } else { if msg.StatusID != jdapi.OrderStatusWaitOutStore { // 老系统没有处理OrderStatusWaitOutStore,不转发 if err = freshfood.FreshFoodAPI.JDOrderStatus(msg); err == nil { rec.OrderStatus = int(utils.Str2Int64(msg.StatusID)) rec.OrderStatusTime = msg.Timestamp rec.Code = "0" err = utils.CallFuncLogError(func() error { _, err := db.Update(rec, "OrderStatus", "OrderStatusTime", "Code") return err }, globals.ErrStrAccessDB) } } } } } return err }