142 lines
5.6 KiB
Go
142 lines
5.6 KiB
Go
package delivery
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
"math"
|
||
"time"
|
||
|
||
"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"
|
||
"github.com/astaxie/beego/orm"
|
||
)
|
||
|
||
const (
|
||
warningDistance = 10 // 公里
|
||
warningWeight = 50 * 1000 // 克
|
||
maxDiffFee2Mtps = 150 // 与美团配送最多差价
|
||
maxAddFee = 300 // 最大增加费用,单位为分,超过不发三方配送了
|
||
)
|
||
|
||
func NullCreateWaybillPolicy(refDeliveryFee, refAddFee, deliveryFee int64) (errStr string) {
|
||
return ""
|
||
}
|
||
|
||
func DefCreateWaybillPolicy(refDeliveryFee, refAddFee, deliveryFee int64) (errStr string) {
|
||
if refDeliveryFee-deliveryFee > maxDiffFee2Mtps {
|
||
errStr = fmt.Sprintf("超参考价太多, 费用:%d,参考价:%d, 最高超价:%d", deliveryFee, refDeliveryFee, maxDiffFee2Mtps)
|
||
} else if refAddFee > maxAddFee {
|
||
errStr = fmt.Sprintf("超基础价太多, 当前加价:%d, 最高加价:%d", refAddFee, maxAddFee)
|
||
}
|
||
return errStr
|
||
}
|
||
|
||
func AddPolicy(prevPolicy, newPolicy partner.CreateWaybillPolicy) (outPolicy partner.CreateWaybillPolicy) {
|
||
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.CreateWaybillPolicy, refDeliveryFee, deliveryFee, addFee int64, order *model.GoodsOrder, waybillVendorID int) (err error) {
|
||
if policy == nil {
|
||
policy = NullCreateWaybillPolicy
|
||
}
|
||
if errStr := policy(deliveryFee, deliveryFee, addFee); errStr != "" {
|
||
waybillVendorName := jxutils.GetVendorName(waybillVendorID)
|
||
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
|
||
}
|
||
|
||
func CalculateOrderDeliveryFee(order *model.GoodsOrder, billTime time.Time, db orm.Ormer) (deliveryFee, addFee int64, err error) {
|
||
globals.SugarLogger.Debugf("CalculateOrderDeliveryFee orderID:%s", order.VendorOrderID)
|
||
if db == nil {
|
||
db = orm.NewOrm()
|
||
}
|
||
jxStoreID := jxutils.GetSaleStoreIDFromOrder(order)
|
||
var lng, lat float64
|
||
priceInfo := &struct {
|
||
Price int
|
||
Lng int
|
||
Lat int
|
||
}{}
|
||
db2 := dao.WrapDB(db)
|
||
if err = dao.GetRow(db2, priceInfo, `
|
||
SELECT t2.mtps_price price, t1.lng, t1.lat
|
||
FROM store t1
|
||
JOIN place t2 ON t1.city_code = t2.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 == 0 {
|
||
globals.SugarLogger.Warnf("CalculateOrderDeliveryFee 查不到美团配送价格 orderID:%s", order.VendorOrderID)
|
||
deliveryFee = 650
|
||
}
|
||
if lng == 0 || lat == 0 {
|
||
globals.SugarLogger.Warnf("calculateDeliveryFee 门店没有坐标信息 orderID:%s", order.VendorOrderID)
|
||
return 0, 0, fmt.Errorf("找不到门店:%d的坐标", jxutils.GetSaleStoreIDFromOrder(order))
|
||
}
|
||
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("[运营]CalculateOrderDeliveryFee orderID:%s distance is %.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("[运营]CalculateOrderDeliveryFee orderID:%s weight is %d", order.VendorOrderID, order.Weight)
|
||
}
|
||
}
|
||
|
||
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(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
|
||
}
|
||
|
||
func CalculateBillDeliveryFee(bill *model.Waybill) (deliveryFee, addFee int64) {
|
||
order, err := partner.CurOrderManager.LoadOrder(bill.VendorOrderID, bill.OrderVendorID)
|
||
if err != nil {
|
||
return 0, 0
|
||
}
|
||
deliveryFee, addFee, _ = CalculateOrderDeliveryFee(order, bill.StatusTime, nil)
|
||
return deliveryFee, addFee
|
||
}
|