Files
jx-callback/business/controller/mtps/waybill.go
gazebo ca9bf8f0a3 没有显示处理model.WaybillStatusCourierArrived事件,导致TIMER没有停掉,又执行了在第3方门店创建运单操作。(改为只要收到了大于NEW的运单事件,都将TIMER停掉,状态需要添加TIMER的,再自行添加)
然后createWaybillOn3rdProviders又没有判断状态,导致又重新创建运单(添加状态判断,另外将所有TIMER事件中的逻辑都添加状态判断,合适后才真正执行)
2018-07-24 15:50:24 +08:00

224 lines
8.4 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 mtps
import (
"errors"
"math"
"git.rosy.net.cn/baseapi/platformapi/mtpsapi"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/controller"
"git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/scheduler"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api"
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
)
var (
ErrCanNotFindMTPSStore = errors.New("不能找到美团配送站点配置")
)
type WaybillController struct {
}
func init() {
scheduler.CurrentScheduler.RegisterDeliveryPlatform(model.VendorIDMTPS, new(WaybillController))
}
func (c *WaybillController) OnWaybillMsg(msg *mtpsapi.CallbackOrderMsg) (retVal *mtpsapi.CallbackResponse) {
jxutils.CallMsgHandler(func() {
retVal = c.onWaybillMsg(msg)
}, msg.OrderID)
return retVal
}
func (c *WaybillController) OnWaybillExcept(msg *mtpsapi.CallbackOrderExceptionMsg) (retVal *mtpsapi.CallbackResponse) {
jxutils.CallMsgHandler(func() {
order := &model.Waybill{
VendorWaybillID: msg.MtPeisongID,
VendorWaybillID2: utils.Int64ToStr(msg.DeliveryID),
WaybillVendorID: model.VendorIDMTPS,
CourierName: msg.CourierName,
CourierMobile: msg.CourierPhone,
Status: model.WaybillStatusFailed, // todo 这里要再确定一下是否只要收到订单异常消息就视为订单失败
VendorStatus: utils.Int2Str(msg.ExceptionCode),
StatusTime: utils.Timestamp2Time(msg.Timestamp),
}
order.VendorOrderID, order.OrderVendorID = jxutils.SplitUniversalOrderID(msg.OrderID)
retVal = mtpsapi.Err2CallbackResponse(controller.WaybillManager.OnWaybillStatusChanged(order), "mtps OnWaybillExcept")
}, msg.OrderID)
return retVal
}
func (c *WaybillController) onWaybillMsg(msg *mtpsapi.CallbackOrderMsg) (retVal *mtpsapi.CallbackResponse) {
order := c.callbackMsg2Waybill(msg)
switch msg.Status {
case mtpsapi.OrderStatusWaitingForSchedule:
order.Status = model.WaybillStatusNew
case mtpsapi.OrderStatusAccepted:
order.DesiredFee = c.calculateDeliveryFee(order)
order.Status = model.WaybillStatusAccepted
case mtpsapi.OrderStatusPickedUp:
order.Status = model.WaybillStatusDelivering
case mtpsapi.OrderStatusDeliverred:
order.Status = model.WaybillStatusDelivered
case mtpsapi.OrderStatusCanceled:
order.Status = model.WaybillStatusCanceled
default:
globals.SugarLogger.Warnf("onWaybillMsg unknown msg:%v", msg)
return mtpsapi.SuccessResponse
}
return mtpsapi.Err2CallbackResponse(controller.WaybillManager.OnWaybillStatusChanged(order), order.VendorStatus)
}
func (c *WaybillController) callbackMsg2Waybill(msg *mtpsapi.CallbackOrderMsg) (retVal *model.Waybill) {
retVal = &model.Waybill{
VendorWaybillID: msg.MtPeisongID,
VendorWaybillID2: utils.Int64ToStr(msg.DeliveryID),
WaybillVendorID: model.VendorIDMTPS,
CourierName: msg.CourierName,
CourierMobile: msg.CourierPhone,
VendorStatus: utils.Int2Str(msg.Status),
StatusTime: utils.Timestamp2Time(msg.Timestamp),
}
retVal.VendorOrderID, retVal.OrderVendorID = jxutils.SplitUniversalOrderID(msg.OrderID)
return retVal
}
func (c *WaybillController) calculateDeliveryFee(bill *model.Waybill) (retVal int64) {
order, err := controller.OrderManager.LoadOrder(bill.VendorOrderID, bill.OrderVendorID)
if err != nil {
return 0
}
var lists []orm.ParamsList
db := orm.NewOrm()
JxStoreID := jxutils.GetJxStoreIDFromOrder(order)
num, err := db.Raw(`
SELECT t2.price, t1.lng, t1.lat
FROM jxstore t1
JOIN mtpsdeliveryprice t2 ON t2.citycode = t1.area
WHERE t1.storeid = ?
`, JxStoreID).ValuesList(&lists)
var delieveryFee int64
if err == nil && num == 1 {
delieveryFee = utils.Str2Int64(lists[0][0].(string))
} else {
globals.SugarLogger.Warnf("calculateDeliveryFee can not calculate delivery fee for orderID:%s, num:%d, error:%v", order.VendorOrderID, num, err)
return 0
}
lng := utils.Str2Float64(lists[0][1].(string))
lat := utils.Str2Float64(lists[0][2].(string))
lng2, lat2, _ := jxutils.IntCoordinate2MarsStandard(order.ConsigneeLng, order.ConsigneeLat, order.CoordinateType)
distance := jxutils.EarthDistance(lat, lng, lat2, lng2) * 1.4
if distance < 3 {
} else if distance < 5 {
delieveryFee += jxutils.StandardPrice2Int(math.Ceil(distance - 3))
} else {
delieveryFee += jxutils.StandardPrice2Int(2 + 2*math.Ceil(distance-5))
}
if order.Weight < 5*1000 {
} else if order.Weight < 10*1000 {
delieveryFee += jxutils.StandardPrice2Int(0.5 * float64(order.Weight/1000-5))
} else if order.Weight < 20*1000 {
delieveryFee += jxutils.StandardPrice2Int(2.5 + 1*float64(order.Weight/1000-10))
} else {
delieveryFee += jxutils.StandardPrice2Int(2.5 + 10 + 2*float64(order.Weight/1000-20))
}
hour, min, sec := bill.StatusTime.Clock()
totalSeconds := hour*3600 + min*60 + sec
if totalSeconds >= 11*3600+30*60 && totalSeconds <= 13*3600 { // 11:30 -- 13:00
delieveryFee += jxutils.StandardPrice2Int(3)
} else if totalSeconds >= 21*3600 || totalSeconds <= 6*3600 { // 21:00 -- 06:00
delieveryFee += jxutils.StandardPrice2Int(3)
}
return delieveryFee
}
// DeliveryPlatformHandler
func (c *WaybillController) CreateWaybill(order *model.GoodsOrder) (err error) {
db := orm.NewOrm()
// 忽略坐标转换错误,即使是转换出错,也只能当成转换成功来处理,底层会有错误日志输出
lngFloat, latFloat, _ := jxutils.IntCoordinate2MarsStandard(order.ConsigneeLng, order.ConsigneeLat, order.CoordinateType)
billParams := &mtpsapi.CreateOrderByShopParam{
OrderID: jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID),
DeliveryServiceCode: mtpsapi.DeliveryServiceCodeRapid,
ReceiverName: order.ConsigneeName,
ReceiverAddress: order.ConsigneeAddress,
ReceiverPhone: order.ConsigneeMobile,
CoordinateType: model.CoordinateTypeMars,
ReceiverLng: jxutils.StandardCoordinate2Int(lngFloat),
ReceiverLat: jxutils.StandardCoordinate2Int(latFloat),
GoodsValue: jxutils.IntPrice2Standard(order.SalePrice), // todo 超价处理
GoodsWeight: float64(order.Weight) / 1000,
ExpectedDeliveryTime: order.ExpectedDeliveredTime.Unix(),
OrderType: mtpsapi.OrderTypeASAP,
}
if billParams.DeliveryID, err = c.getDeliveryID(order, db); err == nil {
if billParams.ShopID, err = c.getMTPSShopID(order, db); err == nil {
globals.SugarLogger.Debug(billParams.ShopID)
goods := &mtpsapi.GoodsDetail{
Goods: []*mtpsapi.GoodsItem{},
}
for _, sku := range order.Skus {
goodItem := &mtpsapi.GoodsItem{
GoodCount: sku.Count,
GoodPrice: jxutils.IntPrice2Standard(sku.SalePrice),
}
goodItem.GoodName, goodItem.GoodUnit = jxutils.SplitSkuName(sku.SkuName)
goods.Goods = append(goods.Goods, goodItem)
}
addParams := utils.Params2Map("note", order.BuyerComment, "goods_detail", string(utils.MustMarshal(goods)))
_, err = api.MtpsAPI.CreateOrderByShop(billParams, addParams)
}
}
return err
}
func (c *WaybillController) CancelWaybill(bill *model.Waybill) (err error) {
reasonID := mtpsapi.CancelReasonMerchantOther
reasonMsg := "other reason"
if bill.Status < model.WaybillStatusAccepted {
} else if bill.Status < model.WaybillStatusCourierArrived {
reasonID = mtpsapi.CancelReasonRideerGetGoodNotIntime
reasonMsg = "CancelReasonRideerGetGoodNotIntime"
} else {
reasonID = mtpsapi.CancelReasonRidderSendNotIntime
reasonMsg = "CancelReasonRidderSendNotIntime"
}
_, err = api.MtpsAPI.CancelOrder(utils.Str2Int64(bill.VendorWaybillID2), bill.VendorWaybillID, reasonID, reasonMsg)
return nil
}
func (c *WaybillController) getDeliveryID(order *model.GoodsOrder, db orm.Ormer) (retVal int64, err error) {
// jxorder表当前已经有50多万条记录了加100万避免冲突
// 508505
return order.ID + 1000000, nil
}
func (c *WaybillController) getMTPSShopID(order *model.GoodsOrder, db orm.Ormer) (retVal string, err error) {
sql := "SELECT zs_store_id FROM jx_to_zs_store_map WHERE jx_store_id = ?"
var lists []orm.ParamsList
JxStoreID := jxutils.GetJxStoreIDFromOrder(order)
num, err := db.Raw(sql, JxStoreID).ValuesList(&lists)
if err == nil && num == 1 {
retVal = lists[0][0].(string)
if beego.BConfig.RunMode == "dev" {
retVal = "test_0001"
}
} else {
globals.SugarLogger.Infof("getMTPSShopID can not find mtps store info for orderID:%s, store:%d, num:%d, error:%v", order.VendorOrderID, JxStoreID, num, err)
if err == nil {
err = ErrCanNotFindMTPSStore
}
}
return retVal, err
}