229 lines
6.9 KiB
Go
229 lines
6.9 KiB
Go
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 = 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)
|
||
} else {
|
||
if rec.OrderStatus == int(utils.Str2Int64(msg.StatusID)) {
|
||
globals.SugarLogger.Infof("Duplicate message msg:%v", msg)
|
||
} else {
|
||
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
|
||
}
|