Files
jx-callback/legacy/jd/controller/order.go

234 lines
7.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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()
// todo 这样操作在有多个进程时,会有问题
// 另外当前这个模式可能会出现同一个订单的消息虽然远程推送过来顺序是对的但经过处理后推送到freshfood时乱序因为每个消息的处理时间是不确定的
handlePendingOrderMsg()
}
func handlePendingOrderMsg() {
var ordersInfo []models.Jdorder
db := orm.NewOrm()
_, err := db.Raw("SELECT * FROM jdorder WHERE orderstatustime >= DATE_ADD(NOW(), interval -2 day) 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)
// 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.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 {
globals.SugarLogger.Warnf("error when accessing db err:%v, rec:%v", err, rec)
if err == orm.ErrNoRows {
err = nil // 如果没有查到,不当成错误
}
} 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
}