Files
jx-callback/business/jd/controller/order.go
2018-06-12 16:36:44 +08:00

246 lines
6.8 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/platform/jdapi"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/freshfood"
"git.rosy.net.cn/jx-callback/business/jd/models"
"git.rosy.net.cn/jx-callback/compat/corm"
"github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql" // import your used driver
)
const (
MsgNotHandledCode = "9527"
)
var (
errChecker corm.DBErrorChecker
orderMsgChan chan *jdapi.JDOrderMsg
// freshFoodServerURL = "http://portal.jingxicaishi.com"
freshFoodServerURL = "http://test.jxc4.com"
freshFoodAPI *freshfood.FreshFoodAPI
)
type OrderControler struct {
}
func initOrder() {
errChecker = new(corm.MysqlErrorChecker)
freshFoodAPI = freshfood.NewFreshFoodAPI(freshFoodServerURL, sugarLogger.Desugar())
orderMsgChan = make(chan *jdapi.JDOrderMsg, 128)
go orderMsgHandlerRoutinue()
// 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 {
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 orderMsgHandlerRoutinue() {
for {
msg := <-orderMsgChan
sugarLogger.Debugf("OrderMsgHandlerRoutinue:%v", msg)
go handleOrderMsg(msg)
}
}
func addOrderMsg(orderMsg *jdapi.JDOrderMsg) {
sugarLogger.Debugf("addOrderMsg:%v", orderMsg)
orderMsgChan <- orderMsg
}
func handleOrderMsg(orderMsg *jdapi.JDOrderMsg) {
sugarLogger.Debugf("handleOrderMsg:%v", orderMsg)
switch orderMsg.StatusId {
case jdapi.JdOrderStatusNew:
newOrder(orderMsg)
case jdapi.JdOrderStatusAdjust:
adjustOrder(orderMsg)
default:
normalOrderStatus(orderMsg)
}
}
// --------------
func (c *OrderControler) OrderStatus(order *jdapi.JDOrderMsg) *jdapi.JDOrderMsgResponse {
if order.StatusId != jdapi.JdOrderStatusNew && order.StatusId != jdapi.JdOrderStatusAdjust {
err := normalOrderStatus(order)
if err != nil {
sugarLogger.Warnf("error in OrderStatus, error:%v", err)
return &jdapi.JDOrderMsgResponse{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 {
isStatusSame := order.StatusId == jdapi.JdOrderStatusNew
if !isStatusSame {
order.StatusId = jdapi.JdOrderStatusNew
sugarLogger.Warnf("order:%s get %s before create", order.BillId, order.StatusId)
}
addOrderMsg(order)
if !isStatusSame {
order.StatusId = utils.Int2Str(status)
}
}
if rec.OrderStatus != status {
rec.OrderStatus = status
rec.OrderStatusTime = order.Timestamp
rec.Code = MsgNotHandledCode
db.Update(rec, "OrderStatus", "OrderStatusTime", "Code")
addOrderMsg(order)
} else {
sugarLogger.Warnf("duplicated jd orderid:%s", order.BillId)
sugarLogger.Debug(rec)
}
} else {
sugarLogger.Errorf("error when calling ReadOrCreate:%v", err)
return &jdapi.JDOrderMsgResponse{jdapi.JDerrorCodeAccessFailed, err.Error(), ""}
}
}
return jdSuccessResponse
}
func (c *OrderControler) OrderDeliveryStatus(jdOrderDeliveryStatusMsg *jdapi.JDDeliveryStatusMsg) *jdapi.JDOrderMsgResponse {
err := freshFoodAPI.JDOrderDeliveryStatus(jdOrderDeliveryStatusMsg, "0")
if err != nil {
sugarLogger.Errorf("Error when calling JDOrderDeliveryStatus, error:%v", err)
return &jdapi.JDOrderMsgResponse{jdapi.JDerrorCodeAccessFailed, err.Error(), ""}
}
return jdSuccessResponse
}
//-----------
func acceptOrder(order *jdapi.JDOrderMsg) {
gJdapi.OrderAcceptOperate(order.BillId, true)
}
func newOrder(order *jdapi.JDOrderMsg) error {
sugarLogger.Debug("NewOrder2")
result, err := gJdapi.LegacyQuerySingleOrder(order.BillId)
acceptOrder(order)
if err != nil {
sugarLogger.Warnf("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, _ := json.Marshal(data)
rec.Data = string(resultByteArr)
err = freshFoodAPI.NewJDOrder(rec)
if err == nil {
db := orm.NewOrm()
_, err = db.Update(rec, "Data", "Code", "Msg", "Success", "CityName", "OrderStatus", "OrderStatusTime")
if err != nil {
sugarLogger.Errorf("update order error:%v", err)
}
} else {
sugarLogger.Errorf("Error when calling NewJDOrder error:%v", err)
}
} else {
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 {
sugarLogger.Warnf("error when accessing db:%v", err)
return err
}
if rec.OrderStatus == utils.Str2Int(order.StatusId) {
sugarLogger.Infof("Duplicate message order:%v", order)
return nil
}
rec.OrderStatus = utils.Str2Int(order.StatusId)
rec.OrderStatusTime = order.Timestamp
err = freshFoodAPI.JDOrderStatus(rec, "0")
if err != nil {
// todo 这里应该要加一个重试机制
sugarLogger.Warnf("access freshfood failed, error:%v", err)
return err
}
rec.Code = "0"
_, err = db.Update(rec, "OrderStatus", "OrderStatusTime", "Code")
if err != nil {
sugarLogger.Warnf("error when accessing db:%v", err)
}
return err
}