239 lines
6.8 KiB
Go
239 lines
6.8 KiB
Go
package controller
|
||
|
||
import (
|
||
"encoding/json"
|
||
|
||
"git.rosy.net.cn/baseapi/platform/jdapi"
|
||
"git.rosy.net.cn/baseapi/utils"
|
||
"git.rosy.net.cn/jx-callback/business/jd/models"
|
||
"git.rosy.net.cn/jx-callback/compat/corm"
|
||
"git.rosy.net.cn/jx-callback/globals"
|
||
"github.com/astaxie/beego/orm"
|
||
)
|
||
|
||
const (
|
||
MsgNotHandledCode = "9527"
|
||
)
|
||
|
||
var (
|
||
errChecker corm.DBErrorChecker
|
||
orderMsgChan chan jdapi.JDOrderMsg
|
||
)
|
||
|
||
type OrderController struct {
|
||
}
|
||
|
||
func InitOrder() {
|
||
errChecker = new(corm.MysqlErrorChecker)
|
||
|
||
orderMsgChan = make(chan jdapi.JDOrderMsg, 128)
|
||
go orderMsgHandlerRoutine()
|
||
|
||
// todo 这样操作在有多个进程时,会有问题
|
||
// 另外当前这个模式可能会出现同一个定单的消息,虽然远程推送过来顺序是对的,但经过处理后推送到freshfood时乱序(因为每个消息的处理时间是不确定的)
|
||
handlePendingOrderMsg()
|
||
}
|
||
|
||
func handlePendingOrderMsg() {
|
||
var ordersInfo []models.Jdorder
|
||
db := orm.NewOrm()
|
||
_, err := db.Raw("SELECT * FROM jdorder WHERE 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.JDOrderMsg{
|
||
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(orderMsg *jdapi.JDOrderMsg) {
|
||
globals.SugarLogger.Debugf("addOrderMsg:%v", orderMsg)
|
||
orderMsgChan <- *orderMsg
|
||
}
|
||
|
||
func handleOrderMsg(orderMsg *jdapi.JDOrderMsg) {
|
||
globals.SugarLogger.Debugf("handleOrderMsg:%v", orderMsg)
|
||
switch orderMsg.StatusId {
|
||
case jdapi.JdOrderStatusNew:
|
||
newOrder(orderMsg)
|
||
case jdapi.JdOrderStatusAdjust:
|
||
adjustOrder(orderMsg)
|
||
default:
|
||
normalOrderStatus(orderMsg)
|
||
}
|
||
}
|
||
|
||
// --------------
|
||
func (c *OrderController) OrderStatus(order *jdapi.JDOrderMsg) *jdapi.JDCallbackResponse {
|
||
if order.StatusId != jdapi.JdOrderStatusNew && order.StatusId != jdapi.JdOrderStatusAdjust {
|
||
err := normalOrderStatus(order)
|
||
if err != nil {
|
||
return &jdapi.JDCallbackResponse{jdapi.JDerrorCodeAccessFailed, err.Error(), ""}
|
||
}
|
||
} else {
|
||
db := orm.NewOrm()
|
||
jdorderid := utils.Str2Int64(order.BillId)
|
||
status := utils.Str2Int(order.StatusId)
|
||
rec := &models.Jdorder{
|
||
Code: MsgNotHandledCode,
|
||
JdOrderId: jdorderid,
|
||
OrderStatus: status,
|
||
OrderStatusTime: order.Timestamp,
|
||
}
|
||
|
||
if created, _, err := db.ReadOrCreate(rec, "Jdorderid"); err == nil {
|
||
order.Id = rec.Id
|
||
if created {
|
||
if order.StatusId != jdapi.JdOrderStatusNew && order.StatusId != jdapi.JdOrderStatusAdjust {
|
||
globals.SugarLogger.Warnf("order:%v get before create", order)
|
||
oldStatusId := order.StatusId
|
||
order.StatusId = jdapi.JdOrderStatusNew
|
||
addOrderMsg(order)
|
||
order.StatusId = oldStatusId
|
||
}
|
||
addOrderMsg(order)
|
||
} else {
|
||
if rec.OrderStatus != status {
|
||
if order.StatusId == jdapi.JdOrderStatusNew {
|
||
globals.SugarLogger.Warnf("order:%v get after some other message:%d", order, rec.OrderStatus)
|
||
} else {
|
||
rec.OrderStatus = status
|
||
rec.OrderStatusTime = order.Timestamp
|
||
rec.Code = MsgNotHandledCode
|
||
utils.CallFuncLogError(func() error {
|
||
_, err := db.Update(rec, "OrderStatus", "OrderStatusTime", "Code")
|
||
return err
|
||
}, globals.ErrStrAccessDB)
|
||
addOrderMsg(order)
|
||
}
|
||
} else {
|
||
globals.SugarLogger.Warnf("duplicated jd order msg %v", order)
|
||
}
|
||
}
|
||
} else {
|
||
globals.SugarLogger.Errorf("error when calling ReadOrCreate:%v", err)
|
||
return &jdapi.JDCallbackResponse{jdapi.JDerrorCodeAccessFailed, err.Error(), ""}
|
||
}
|
||
}
|
||
return jdapi.SuccessResponse
|
||
}
|
||
|
||
func (c *OrderController) OrderDeliveryStatus(jdOrderDeliveryStatusMsg *jdapi.JDDeliveryStatusMsg) *jdapi.JDCallbackResponse {
|
||
err := globals.FreshFoodAPI.JDOrderDeliveryStatus(jdOrderDeliveryStatusMsg)
|
||
|
||
if err != nil {
|
||
globals.SugarLogger.Errorf("Error when calling JDOrderDeliveryStatus, error:%v", err)
|
||
return &jdapi.JDCallbackResponse{jdapi.JDerrorCodeAccessFailed, err.Error(), ""}
|
||
}
|
||
|
||
return jdapi.SuccessResponse
|
||
}
|
||
|
||
//-----------
|
||
func acceptOrder(order *jdapi.JDOrderMsg) {
|
||
globals.Jdapi.OrderAcceptOperate(order.BillId, true)
|
||
}
|
||
|
||
func newOrder(order *jdapi.JDOrderMsg) error {
|
||
result, err := globals.Jdapi.LegacyQuerySingleOrder(order.BillId)
|
||
acceptOrder(order)
|
||
if err != nil {
|
||
globals.SugarLogger.Errorf("error when query jd order:%s, error:%v", order.BillId, err)
|
||
} else {
|
||
rec := &models.Jdorder{
|
||
Id: order.Id,
|
||
}
|
||
|
||
rec.Code, _ = result["code"].(string)
|
||
rec.Msg, _ = result["msg"].(string)
|
||
success, _ := result["success"].(bool)
|
||
if success {
|
||
rec.Success = 1
|
||
} else {
|
||
rec.Success = 0
|
||
}
|
||
|
||
// todo
|
||
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.OrderStatus = int(orderStatus)
|
||
rec.OrderStatusTime = resultList0["orderStatusTime"].(string)
|
||
|
||
resultByteArr := utils.MustMarshal(data)
|
||
rec.Data = string(resultByteArr)
|
||
err = globals.FreshFoodAPI.NewJDOrder(rec)
|
||
if err == nil {
|
||
db := orm.NewOrm()
|
||
utils.CallFuncLogError(func() error {
|
||
_, err := db.Update(rec, "Data", "Code", "Msg", "Success", "CityName", "OrderStatus", "OrderStatusTime")
|
||
return err
|
||
}, globals.ErrStrAccessDB)
|
||
} else {
|
||
globals.SugarLogger.Errorf("Error when calling NewJDOrder error:%v", err)
|
||
}
|
||
} else {
|
||
globals.SugarLogger.Warnf("can not get jdorder info:%v", order.BillId)
|
||
}
|
||
}
|
||
return err
|
||
}
|
||
|
||
func adjustOrder(order *jdapi.JDOrderMsg) error {
|
||
return newOrder(order)
|
||
}
|
||
|
||
func normalOrderStatus(order *jdapi.JDOrderMsg) error {
|
||
db := orm.NewOrm()
|
||
rec := &models.Jdorder{
|
||
JdOrderId: utils.Str2Int64(order.BillId),
|
||
}
|
||
|
||
err := db.Read(rec, "JdOrderId")
|
||
if err != nil {
|
||
globals.SugarLogger.Warnf("error when accessing db:%v", err)
|
||
return err
|
||
}
|
||
|
||
if rec.OrderStatus == utils.Str2Int(order.StatusId) {
|
||
globals.SugarLogger.Infof("Duplicate message order:%v", order)
|
||
return nil
|
||
}
|
||
|
||
rec.OrderStatus = utils.Str2Int(order.StatusId)
|
||
rec.OrderStatusTime = order.Timestamp
|
||
err = globals.FreshFoodAPI.JDOrderStatus(rec)
|
||
if err != nil {
|
||
globals.SugarLogger.Warnf("access freshfood failed, error:%v", err)
|
||
return err
|
||
}
|
||
|
||
rec.Code = "0"
|
||
utils.CallFuncLogError(func() error {
|
||
_, err := db.Update(rec, "OrderStatus", "OrderStatusTime", "Code")
|
||
return err
|
||
}, globals.ErrStrAccessDB)
|
||
return err
|
||
}
|