Files
jx-callback/business/partner/delivery/delivery.go
2019-03-30 18:32:13 +08:00

142 lines
5.6 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 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
}