三方运单计价各管各,不在以美团为基准,创建运单只有一个限制条件,最高运费:maxDeliveryFee
优化美团运费计算,两点距离用高德API实际计算行走距离
This commit is contained in:
@@ -3,7 +3,6 @@ package dada
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/dadaapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
@@ -205,7 +204,6 @@ func (c *DeliveryHandler) IsErrStoreExist(err error) bool {
|
||||
func (c *DeliveryHandler) GetWaybillFee(order *model.GoodsOrder) (deliveryFeeInfo *partner.WaybillFeeInfo, err error) {
|
||||
db := dao.GetDB()
|
||||
deliveryFeeInfo = &partner.WaybillFeeInfo{}
|
||||
deliveryFeeInfo.RefDeliveryFee, deliveryFeeInfo.RefAddFee, err = delivery.CalculateOrderDeliveryFee(order, time.Now(), db)
|
||||
billParams, addParams, err := c.getBillParams(db, order)
|
||||
if err == nil {
|
||||
var result *dadaapi.CreateOrderResponse
|
||||
@@ -213,6 +211,7 @@ func (c *DeliveryHandler) GetWaybillFee(order *model.GoodsOrder) (deliveryFeeInf
|
||||
return nil, err
|
||||
}
|
||||
deliveryFeeInfo.DeliveryFee = jxutils.StandardPrice2Int(result.Fee)
|
||||
deliveryFeeInfo.RefDeliveryFee = deliveryFeeInfo.DeliveryFee
|
||||
}
|
||||
return deliveryFeeInfo, err
|
||||
}
|
||||
@@ -244,15 +243,8 @@ func (c *DeliveryHandler) getBillParams(db *dao.DaoDB, order *model.GoodsOrder)
|
||||
}
|
||||
|
||||
// IDeliveryPlatformHandler
|
||||
func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, policy partner.CreateWaybillPolicyFunc) (bill *model.Waybill, err error) {
|
||||
func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, maxDeliveryFee int64) (bill *model.Waybill, err error) {
|
||||
db := dao.GetDB()
|
||||
deliveryFee, addFee, err := delivery.CalculateOrderDeliveryFee(order, time.Now(), db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = delivery.CallCreateWaybillPolicy(policy, deliveryFee, addFee, deliveryFee, order, model.VendorIDDada); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
billParams, addParams, err := c.getBillParams(db, order)
|
||||
if err == nil {
|
||||
if globals.EnableStoreWrite {
|
||||
@@ -268,13 +260,14 @@ func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, policy partner.
|
||||
`, jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID), model.VendorIDDada)
|
||||
var result *dadaapi.CreateOrderResponse
|
||||
if err = err2; err == nil && len(waybillList) > 0 && waybillList[0].Status != model.WaybillStatusFailed {
|
||||
// 再次创建
|
||||
globals.SugarLogger.Debugf("CreateWaybill orderID:%s len(waybillList)=%d use ReaddOrder", order.VendorOrderID, len(waybillList))
|
||||
dadaFee := waybillList[0].ActualFee
|
||||
if err = delivery.CallCreateWaybillPolicy(policy, deliveryFee, addFee, dadaFee, order, model.VendorIDDada); err != nil {
|
||||
if err = delivery.CallCreateWaybillPolicy(waybillList[0].ActualFee, maxDeliveryFee, order, model.VendorIDDada); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, err = api.DadaAPI.ReaddOrder(billParams, addParams)
|
||||
} else {
|
||||
// 第一次创建
|
||||
if err != nil {
|
||||
globals.SugarLogger.Warnf("CreateWaybill orderID:%s error:%v", order.VendorOrderID, err)
|
||||
}
|
||||
@@ -284,8 +277,7 @@ func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, policy partner.
|
||||
if result, err = api.DadaAPI.QueryDeliverFee(billParams, addParams); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dadaFee := jxutils.StandardPrice2Int(result.Fee)
|
||||
if err = delivery.CallCreateWaybillPolicy(policy, deliveryFee, addFee, dadaFee, order, model.VendorIDDada); err != nil {
|
||||
if err = delivery.CallCreateWaybillPolicy(jxutils.StandardPrice2Int(result.Fee), maxDeliveryFee, order, model.VendorIDDada); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = api.DadaAPI.AddOrderAfterQuery(result.DeliveryNo)
|
||||
@@ -296,7 +288,7 @@ func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, policy partner.
|
||||
VendorOrderID: order.VendorOrderID,
|
||||
OrderVendorID: order.VendorID,
|
||||
WaybillVendorID: model.VendorIDDada,
|
||||
DesiredFee: deliveryFee,
|
||||
DesiredFee: jxutils.StandardPrice2Int(result.Fee),
|
||||
ActualFee: jxutils.StandardPrice2Int(result.Fee),
|
||||
}
|
||||
delivery.OnWaybillCreated(bill)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package delivery
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
@@ -17,61 +16,22 @@ import (
|
||||
const (
|
||||
warningDistance = 10 // 公里
|
||||
warningWeight = 50 * 1000 // 克
|
||||
maxDiffFee2Mtps = 200 // 与美团配送最多差价
|
||||
maxAddFee = 200 // 最大增加费用,单位为分,超过不发三方配送了
|
||||
|
||||
alarmFee = 1500 // 配送费报警阈值
|
||||
// maxDiffFee2Mtps = 200 // 与美团配送最多差价
|
||||
// maxAddFee = 200 // 最大增加费用,单位为分,超过不发三方配送了
|
||||
defMaxDeliveryFee = 10000 // 创建运单最高价
|
||||
alarmFee = 1500 // 配送费报警阈值
|
||||
)
|
||||
|
||||
var (
|
||||
DefCreateWaybillPolicy = CreateWaybillPolicy(maxDiffFee2Mtps, maxAddFee, 0)
|
||||
)
|
||||
|
||||
func NullCreateWaybillPolicy(refDeliveryFee, refAddFee, deliveryFee int64) (errStr string) {
|
||||
return ""
|
||||
}
|
||||
|
||||
func CreateWaybillPolicy(maxDiffFee2Mtps2, maxAddFee2, maxDeliveryFee2 int64) func(refDeliveryFee, refAddFee, deliveryFee int64) (errStr string) {
|
||||
if maxDiffFee2Mtps2 == 0 {
|
||||
maxDiffFee2Mtps2 = maxDiffFee2Mtps
|
||||
func CallCreateWaybillPolicy(deliveryFee, maxDeliveryFee int64, order *model.GoodsOrder, waybillVendorID int) (err error) {
|
||||
if maxDeliveryFee <= 0 || maxDeliveryFee > defMaxDeliveryFee {
|
||||
maxDeliveryFee = defMaxDeliveryFee
|
||||
}
|
||||
if maxAddFee2 == 0 {
|
||||
maxAddFee2 = maxAddFee
|
||||
if deliveryFee > maxDeliveryFee {
|
||||
errStr := fmt.Sprintf("超最高限价, 所需运费:%s, 最高限价:%s", jxutils.IntPrice2StandardCurrencyString(deliveryFee), jxutils.IntPrice2StandardCurrencyString(maxDeliveryFee))
|
||||
err = fmt.Errorf(errStr)
|
||||
globals.SugarLogger.Debugf("CallCreateWaybillPolicy orderID:%s, 平台:%s运单,创建出错:%s", order.VendorOrderID, model.VendorChineseNames[waybillVendorID], errStr)
|
||||
}
|
||||
return func(refDeliveryFee, refAddFee, deliveryFee int64) (errStr string) {
|
||||
if deliveryFee-refDeliveryFee > maxDiffFee2Mtps2 {
|
||||
errStr = fmt.Sprintf("超参考价太多, 费用:%s,参考价:%s, 最高超价:%s", jxutils.IntPrice2StandardCurrencyString(deliveryFee), jxutils.IntPrice2StandardCurrencyString(refDeliveryFee), jxutils.IntPrice2StandardCurrencyString(maxDiffFee2Mtps2))
|
||||
} else if refAddFee > maxAddFee2 {
|
||||
errStr = fmt.Sprintf("超基础价太多, 当前加价:%s, 最高加价:%s", jxutils.IntPrice2StandardCurrencyString(refAddFee), jxutils.IntPrice2StandardCurrencyString(maxAddFee2))
|
||||
} else if maxDeliveryFee2 > 0 && deliveryFee > maxDeliveryFee2 {
|
||||
errStr = fmt.Sprintf("超最高限价, 所需运费:%s, 最高限价:%s", jxutils.IntPrice2StandardCurrencyString(deliveryFee), jxutils.IntPrice2StandardCurrencyString(maxDeliveryFee2))
|
||||
}
|
||||
return errStr
|
||||
}
|
||||
}
|
||||
|
||||
func AddPolicy(prevPolicy, newPolicy partner.CreateWaybillPolicyFunc) (outPolicy partner.CreateWaybillPolicyFunc) {
|
||||
return func(refDeliveryFee, refAddFee, deliveryFee int64) (errStr string) {
|
||||
if errStr = prevPolicy(refDeliveryFee, refAddFee, deliveryFee); errStr == "" {
|
||||
errStr = newPolicy(refDeliveryFee, refAddFee, deliveryFee)
|
||||
}
|
||||
return errStr
|
||||
}
|
||||
}
|
||||
|
||||
func CallCreateWaybillPolicy(policy partner.CreateWaybillPolicyFunc, refDeliveryFee, refAddFee, deliveryFee int64, order *model.GoodsOrder, waybillVendorID int) (err error) {
|
||||
waybillVendorName := jxutils.GetVendorName(waybillVendorID)
|
||||
globals.SugarLogger.Debugf("CallCreateWaybillPolicy orderID:%s, refDeliveryFee:%d, refAddFee:%d, deliveryFee:%d, waybillVendor:%s",
|
||||
order.VendorOrderID, refDeliveryFee, refAddFee, deliveryFee, waybillVendorName)
|
||||
if policy == nil {
|
||||
policy = NullCreateWaybillPolicy
|
||||
}
|
||||
if errStr := policy(refDeliveryFee, refAddFee, deliveryFee); errStr != "" {
|
||||
errStr = fmt.Sprintf("oderID:%s创建运单出错:%s", order.VendorOrderID, errStr)
|
||||
globals.SugarLogger.Debugf("%s CallCreateWaybillPolicy failed with %s", waybillVendorName, errStr)
|
||||
return errors.New(errStr)
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
func CalculateOrderDeliveryFee(order *model.GoodsOrder, billTime time.Time, db *dao.DaoDB) (deliveryFee, addFee int64, err error) {
|
||||
@@ -82,21 +42,26 @@ func CalculateOrderDeliveryFee(order *model.GoodsOrder, billTime time.Time, db *
|
||||
jxStoreID := jxutils.GetSaleStoreIDFromOrder(order)
|
||||
var lng, lat float64
|
||||
priceInfo := &struct {
|
||||
Price int
|
||||
Lng int
|
||||
Lat int
|
||||
CityPrice int64
|
||||
DistrictPrice int64
|
||||
Lng int
|
||||
Lat int
|
||||
}{}
|
||||
if err = dao.GetRow(db, priceInfo, `
|
||||
SELECT t2.mtps_price price, t1.lng, t1.lat
|
||||
SELECT
|
||||
t2.mtps_price city_price, t2.mtps_price district_price, t1.lng, t1.lat
|
||||
FROM store t1
|
||||
JOIN place t2 ON t1.city_code = t2.code
|
||||
LEFT JOIN place t2 ON t2.level = 2 AND t2.code = t1.city_code
|
||||
LEFT JOIN place t3 ON t3.level = 3 AND t2.code = t1.district_code
|
||||
WHERE t1.id = ? AND t1.deleted_at = ?
|
||||
`, jxStoreID, utils.DefaultTimeValue); err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
lng = jxutils.IntCoordinate2Standard(priceInfo.Lng)
|
||||
lat = jxutils.IntCoordinate2Standard(priceInfo.Lat)
|
||||
deliveryFee = int64(priceInfo.Price)
|
||||
if deliveryFee = priceInfo.DistrictPrice; deliveryFee == 0 {
|
||||
deliveryFee = priceInfo.CityPrice
|
||||
}
|
||||
if deliveryFee == 0 {
|
||||
globals.SugarLogger.Warnf("CalculateOrderDeliveryFee 查不到美团配送价格 orderID:%s", order.VendorOrderID)
|
||||
deliveryFee = 650
|
||||
@@ -108,40 +73,55 @@ func CalculateOrderDeliveryFee(order *model.GoodsOrder, billTime time.Time, db *
|
||||
lng2, lat2, _ := jxutils.IntCoordinate2MarsStandard(order.ConsigneeLng, order.ConsigneeLat, order.CoordinateType)
|
||||
|
||||
var distanceAddFee, weightAddFee, timeAddFee int64
|
||||
distance := jxutils.EarthDistance(lng, lat, lng2, lat2) * 1.4
|
||||
if distance < 3 {
|
||||
} else if distance < 5 {
|
||||
distanceAddFee = jxutils.StandardPrice2Int(math.Ceil(distance - 3))
|
||||
} else {
|
||||
distanceAddFee = jxutils.StandardPrice2Int(2 + 2*math.Ceil(distance-5))
|
||||
if distance > warningDistance {
|
||||
globals.SugarLogger.Infof("[运营]计算订单配送费orderID:%s,距离%.3fkm太远,请检查门店坐标信息", order.VendorOrderID, distance)
|
||||
}
|
||||
}
|
||||
globals.SugarLogger.Debugf("CalculateOrderDeliveryFee orderID:%s", order.VendorOrderID)
|
||||
|
||||
if order.Weight < 5*1000 {
|
||||
} else if order.Weight < 10*1000 {
|
||||
weightAddFee = jxutils.StandardPrice2Int(0.5 * float64(jxutils.IntWeight2Float(order.Weight)-5))
|
||||
} else if order.Weight < 20*1000 {
|
||||
weightAddFee = jxutils.StandardPrice2Int(2.5 + 1*float64(jxutils.IntWeight2Float(order.Weight)-10))
|
||||
} else {
|
||||
weightAddFee = jxutils.StandardPrice2Int(2.5 + 10 + 2*float64(jxutils.IntWeight2Float(order.Weight)-20))
|
||||
if order.Weight > warningWeight {
|
||||
globals.SugarLogger.Infof("[运营]计算订单配送费orderID:%s,重量:%dg太重,请检查商品属性", order.VendorOrderID, order.Weight)
|
||||
}
|
||||
// 距离加价
|
||||
distance := jxutils.WalkingDistance(lng, lat, lng2, lat2)
|
||||
if distance > warningDistance {
|
||||
globals.SugarLogger.Infof("[运营]计算订单配送费orderID:%s,距离%.3fkm太远,请检查门店坐标信息", order.VendorOrderID, distance)
|
||||
}
|
||||
distanceAddFee = int64(jxutils.CalcStageValue([][]float64{
|
||||
[]float64{
|
||||
7,
|
||||
300,
|
||||
},
|
||||
[]float64{
|
||||
5,
|
||||
200,
|
||||
},
|
||||
[]float64{
|
||||
3,
|
||||
100,
|
||||
},
|
||||
}, distance))
|
||||
|
||||
// 重量加价
|
||||
if order.Weight > warningWeight {
|
||||
globals.SugarLogger.Infof("[运营]计算订单配送费orderID:%s,重量:%dg太重,请检查商品属性", order.VendorOrderID, order.Weight)
|
||||
}
|
||||
weightAddFee = int64(jxutils.CalcStageValue([][]float64{
|
||||
[]float64{
|
||||
20,
|
||||
200,
|
||||
},
|
||||
[]float64{
|
||||
10,
|
||||
100,
|
||||
},
|
||||
[]float64{
|
||||
5,
|
||||
50,
|
||||
},
|
||||
}, float64(order.Weight)/1000))
|
||||
|
||||
// 其它加价
|
||||
hour, min, sec := billTime.Clock()
|
||||
totalSeconds := hour*3600 + min*60 + sec
|
||||
// 午高峰加价
|
||||
if totalSeconds >= 11*3600 && totalSeconds <= 14*3600 { // 11:00 -- 14:00
|
||||
timeAddFee = jxutils.StandardPrice2Int(2)
|
||||
} else if totalSeconds >= 21*3600 || totalSeconds <= 6*3600 { // 21:00 -- 06:00 夜间加价
|
||||
timeAddFee = jxutils.StandardPrice2Int(3)
|
||||
}
|
||||
// 夜间加价
|
||||
// else if totalSeconds >= 21*3600 || totalSeconds <= 6*3600 { // 21:00 -- 06:00
|
||||
// timeAddFee = jxutils.StandardPrice2Int(3)
|
||||
// }
|
||||
addFee = distanceAddFee + weightAddFee + timeAddFee
|
||||
globals.SugarLogger.Debugf("CalculateOrderDeliveryFee orderID:%s, deliveryFee:%d addFee:%d, distance:%.3fkm distanceAddFee:%d, weight:%dg weightAddFee:%d, time:%s timeAddFee:%d", order.VendorOrderID, deliveryFee, addFee, distance, distanceAddFee, order.Weight, weightAddFee, utils.Time2TimeStr(billTime), timeAddFee)
|
||||
return deliveryFee + addFee, addFee, nil
|
||||
|
||||
@@ -127,11 +127,11 @@ func (c *DeliveryHandler) GetWaybillFee(order *model.GoodsOrder) (deliveryFeeInf
|
||||
}
|
||||
|
||||
// IDeliveryPlatformHandler
|
||||
func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, policy partner.CreateWaybillPolicyFunc) (bill *model.Waybill, err error) {
|
||||
func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, maxDeliveryFee int64) (bill *model.Waybill, err error) {
|
||||
db := dao.GetDB()
|
||||
deliveryFee, addFee, err := delivery.CalculateOrderDeliveryFee(order, time.Now(), db)
|
||||
deliveryFee, _, err := delivery.CalculateOrderDeliveryFee(order, time.Now(), db)
|
||||
if err == nil {
|
||||
if err = delivery.CallCreateWaybillPolicy(policy, deliveryFee, addFee, deliveryFee, order, model.VendorIDMTPS); err != nil {
|
||||
if err = delivery.CallCreateWaybillPolicy(deliveryFee, maxDeliveryFee, order, model.VendorIDMTPS); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 忽略坐标转换错误,即使是转换出错,也只能当成转换成功来处理,底层会有错误日志输出
|
||||
|
||||
@@ -18,8 +18,8 @@ const (
|
||||
type WaybillFeeInfo struct {
|
||||
ErrCode int `json:"errCode"`
|
||||
ErrStr string `json:"errStr"`
|
||||
RefDeliveryFee int64 `json:"refDeliveryFee"`
|
||||
RefAddFee int64 `json:"refAddFee"`
|
||||
RefDeliveryFee int64 `json:"refDeliveryFee"` // 无用,待删除
|
||||
RefAddFee int64 `json:"refAddFee"` // 无用,待删除
|
||||
DeliveryFee int64 `json:"deliveryFee"`
|
||||
TimeoutSecond int `json:"timeoutSecond"` // 系统会自动发运单的倒计时
|
||||
Waybill *model.Waybill `json:"waybill"`
|
||||
@@ -35,7 +35,7 @@ type IDeliveryPlatformHandler interface {
|
||||
IsErrStoreNotExist(err error) bool
|
||||
IsErrStoreExist(err error) bool
|
||||
|
||||
CreateWaybill(order *model.GoodsOrder, policy CreateWaybillPolicyFunc) (bill *model.Waybill, err error)
|
||||
CreateWaybill(order *model.GoodsOrder, maxDeliveryFee int64) (bill *model.Waybill, err error)
|
||||
CancelWaybill(bill *model.Waybill, cancelReasonID int, cancelReason string) (err error)
|
||||
GetWaybillFee(order *model.GoodsOrder) (deliveryFeeInfo *WaybillFeeInfo, err error)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import (
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"git.rosy.net.cn/jx-callback/business/partner/delivery"
|
||||
|
||||
"git.rosy.net.cn/baseapi/platformapi/weimobapi"
|
||||
"git.rosy.net.cn/baseapi/utils"
|
||||
"git.rosy.net.cn/jx-callback/business/jxutils"
|
||||
@@ -199,7 +197,7 @@ func (p *PurchaseHandler) AcceptOrRefuseOrder(order *model.GoodsOrder, isAcceptI
|
||||
func (p *PurchaseHandler) PickupGoods(order *model.GoodsOrder, isSelfDelivery bool, userName string) (err error) {
|
||||
globals.SugarLogger.Debugf("wsc PickupGoods orderID:%s, isSelfDelivery:%t", order.VendorOrderID, isSelfDelivery)
|
||||
if globals.EnableWscStoreWrite && !isSelfDelivery {
|
||||
_, err = dada.CurDeliveryHandler.CreateWaybill(order, delivery.DefCreateWaybillPolicy)
|
||||
_, err = dada.CurDeliveryHandler.CreateWaybill(order, 0)
|
||||
}
|
||||
// 微商城没有拣货完成,模拟
|
||||
p.postFakeMsg(utils.Str2Int64(order.VendorOrderID), FakeOrderStatusFinishedPickup)
|
||||
|
||||
Reference in New Issue
Block a user