Files
jx-callback/business/controller/mtps/waybill.go
gazebo 479ce46200 - fixed a bug in defsch.init, replace LoadOrder with GetOrder.
- dynamic table name for legacy order related table.
2018-07-23 17:30:22 +08:00

231 lines
8.7 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/legacyorder"
"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
}
// todo 生成mtps deliveryid为了兼容现在取jxorder中的id
func (c *WaybillController) getDeliveryID(order *model.GoodsOrder, db orm.Ormer) (retVal int64, err error) {
jxorder := &legacyorder.Jxorder2{
OrderId: utils.Str2Int64(order.VendorOrderID),
}
err = utils.CallFuncLogError(func() error {
err2 := db.Read(jxorder, "OrderId")
return err2
}, "getDeliveryID, orderID:%s", order.VendorOrderID)
return int64(jxorder.Id), err
}
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.Errorf("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
}