Files
jx-callback/business/partner/delivery/dada/waybill.go
2018-10-28 14:19:00 +08:00

230 lines
7.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 dada
import (
"errors"
"fmt"
"git.rosy.net.cn/baseapi/platformapi/dadaapi"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/business/partner"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api"
"github.com/astaxie/beego/orm"
)
const (
maxCargoPrice = 63.99 // 单位为元,达达最大价格,超过这个价格配送费会增加
)
var (
ErrCanNotFindDadaCityCode = errors.New("不能找到美团配送站点配置")
)
var (
curDeliveryHandler *DeliveryHandler
)
type DeliveryHandler struct {
}
func init() {
curDeliveryHandler = new(DeliveryHandler)
partner.RegisterDeliveryPlatform(curDeliveryHandler, true)
}
func OnWaybillMsg(msg *dadaapi.CallbackMsg) (retVal *dadaapi.CallbackResponse) {
return curDeliveryHandler.OnWaybillMsg(msg)
}
func (c *DeliveryHandler) GetVendorID() int {
return model.VendorIDDada
}
func (c *DeliveryHandler) OnWaybillMsg(msg *dadaapi.CallbackMsg) (retVal *dadaapi.CallbackResponse) {
jxutils.CallMsgHandler(func() {
retVal = c.onWaybillMsg(msg)
}, msg.OrderID)
return retVal
}
func (c *DeliveryHandler) onWaybillMsg(msg *dadaapi.CallbackMsg) (retVal *dadaapi.CallbackResponse) {
order := c.callbackMsg2Waybill(msg)
switch msg.OrderStatus {
case dadaapi.OrderStatusWaitingForAccept:
order.Status = model.WaybillStatusNew
case dadaapi.OrderStatusAccepted:
if result, err := api.DadaAPI.QueryOrderInfo(msg.OrderID); err == nil {
order.DesiredFee = jxutils.StandardPrice2Int(utils.Interface2FloatWithDefault(result["deliveryFee"], 0.0))
}
order.Status = model.WaybillStatusAccepted
case dadaapi.OrderStatusDelivering:
order.Status = model.WaybillStatusDelivering
case dadaapi.OrderStatusFinished:
order.Status = model.WaybillStatusDelivered
case dadaapi.OrderStatusCanceled:
order.Status = model.WaybillStatusCanceled
case dadaapi.OrderStatusExpired, dadaapi.OrderStatusAddOrderFailed:
order.Status = model.WaybillStatusFailed
default:
order.Status = model.WaybillStatusUnknown
}
return dadaapi.Err2CallbackResponse(partner.CurOrderManager.OnWaybillStatusChanged(order), utils.Int2Str(order.Status))
}
func (c *DeliveryHandler) callbackMsg2Waybill(msg *dadaapi.CallbackMsg) (retVal *model.Waybill) {
retVal = &model.Waybill{
VendorWaybillID: msg.ClientID,
WaybillVendorID: model.VendorIDDada,
CourierName: msg.DmName,
CourierMobile: msg.DmMobile,
VendorStatus: utils.Int2Str(msg.OrderStatus),
Remark: msg.CancelReason,
// StatusTime: utils.Timestamp2Time(int64(msg.UpdateTime)),
}
// dada太扯了不同消息过来的时间格式不一样
updateTime := int64(msg.UpdateTime)
if updateTime > 2511789475 {
updateTime = updateTime / 1000
}
retVal.StatusTime = utils.Timestamp2Time(updateTime)
retVal.VendorOrderID, retVal.OrderVendorID = jxutils.SplitUniversalOrderID(msg.OrderID)
return retVal
}
// IDeliveryPlatformHandler
func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, policy func(deliveryFee, addFee int64) error) (bill *model.Waybill, err error) {
billParams := &dadaapi.OperateOrderRequiredParams{
ShopNo: utils.Int2Str(order.StoreID), // 当前达达的门店号与京西是一样的
OriginID: jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID),
CargoPrice: jxutils.IntPrice2Standard(order.ActualPayPrice),
IsPrepay: 0,
ReceiverName: order.ConsigneeName,
ReceiverAddress: order.ConsigneeAddress,
ReceiverPhone: order.ConsigneeMobile,
}
if billParams.CargoPrice > maxCargoPrice {
billParams.CargoPrice = maxCargoPrice
}
db := orm.NewOrm()
if billParams.CityCode, err = c.getDataCityCodeFromOrder(order, db); err == nil {
billParams.ReceiverLng, billParams.ReceiverLat, _ = jxutils.IntCoordinate2MarsStandard(order.ConsigneeLng, order.ConsigneeLat, order.CoordinateType)
addParams := map[string]interface{}{
"info": order.BuyerComment,
// "origin_mark": model.VendorNames[order.VendorID],
"origin_mark_no": fmt.Sprintf("%d", order.OrderSeq),
"cargo_type": 13,
"cargo_weight": jxutils.IntWeight2Float(order.Weight),
"cargo_num": order.GoodsCount,
}
// 达达要求第二次创建运单,调用函数不同。所以查找两天内有无相同订单号的运单
var lists []orm.ParamsList
num, err2 := db.Raw(`
SELECT vendor_waybill_id
FROM waybill
WHERE waybill_created_at > DATE_ADD(NOW(), interval -2 day)
AND vendor_order_id = ?
AND waybill_vendor_id = ?
`, jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID), model.VendorIDDada).ValuesList(&lists)
var result *dadaapi.CreateOrderResponse
if err2 == nil && num > 0 {
globals.SugarLogger.Debugf("CreateWaybill orderID:%s num=%d use ReaddOrder", order.VendorOrderID, num)
result, err = api.DadaAPI.ReaddOrder(billParams, addParams)
} else {
if err2 != nil {
globals.SugarLogger.Warnf("CreateWaybill orderID:%s error:%v", order.VendorOrderID, err2)
}
result, err = api.DadaAPI.AddOrder(billParams, addParams)
}
if err == nil && result != nil {
bill = &model.Waybill{
VendorOrderID: order.VendorOrderID,
OrderVendorID: order.VendorID,
WaybillVendorID: model.VendorIDDada,
DesiredFee: jxutils.StandardPrice2Int(result.DeliverFee),
ActualFee: jxutils.StandardPrice2Int(result.Fee),
}
}
}
return bill, err
}
func (c *DeliveryHandler) CancelWaybill(bill *model.Waybill, cancelReasonID int, cancelReason string) (err error) {
switch cancelReasonID {
case partner.CancelWaybillReasonNotAcceptIntime:
cancelReasonID = dadaapi.ReasonIDNobodyAccept
case partner.CancelWaybillReasonSwitch2SelfFailed:
cancelReasonID = dadaapi.ReasonIDClientDontWantItAnymore
default:
cancelReasonID = dadaapi.ReasonIDOther
}
_, err = api.DadaAPI.CancelOrder(bill.VendorOrderID, cancelReasonID, cancelReason)
return err
}
func (c *DeliveryHandler) getDataCityCodeFromOrder(order *model.GoodsOrder, db orm.Ormer) (retVal string, err error) {
var sql string
if globals.OrderUseNewTable || jxutils.GetJxStoreIDFromOrder(order) == globals.DebugStoreID {
jxStoreID := jxutils.GetJxStoreIDFromOrder(order)
sql = `
SELECT t2.tel_code
FROM store t1
JOIN place t2 on t1.city_code = t2.code
WHERE t1.id = ?
`
db2 := dao.WrapDB(db)
codeInfo := &struct {
TelCode string
}{}
if err = dao.GetRow(db2, codeInfo, sql, jxStoreID); err != nil {
globals.SugarLogger.Errorf("GetDataCityCodeFromOrder can not find store info for vendorID:%d, store:%s, error:%v", order.VendorID, order.VendorStoreID, err)
if err == nil {
err = ErrCanNotFindDadaCityCode
}
return "", err
}
return codeInfo.TelCode, nil
}
storeID := utils.Str2Int64(order.VendorStoreID)
if order.VendorID == model.VendorIDJD {
sql = `
SELECT t2.tel_code
FROM jxstoremap t0
JOIN jxstore t1 ON t0.jxstoreid = t1.storeid
JOIN city t2 ON t1.area = t2.citycode
WHERE t0.jdstoreid = ?
`
} else if order.VendorID == model.VendorIDELM {
sql = `
SELECT t2.tel_code
FROM jx_to_elm_store_map t0
JOIN jxstore t1 ON t0.jx_store_id = t1.storeid
JOIN city t2 ON t1.area = t2.citycode
WHERE t0.elm_store_id = ?
`
} else { // todo 为什么不统一用jxstoreid来找
storeID = int64(jxutils.GetJxStoreIDFromOrder(order))
sql = `
SELECT t2.tel_code
FROM jxstore t1
JOIN city t2 ON t1.area = t2.citycode
WHERE t1.storeid = ?
`
}
var lists []orm.ParamsList
num, err := db.Raw(sql, storeID).ValuesList(&lists)
if err == nil && num == 1 {
retVal = lists[0][0].(string)
} else {
globals.SugarLogger.Errorf("GetDataCityCodeFromOrder can not find store info for vendorID:%d, store:%s, num:%d, error:%v", order.VendorID, order.VendorStoreID, num, err)
if err == nil {
err = ErrCanNotFindDadaCityCode
}
}
return retVal, err
}