Files
jx-callback/business/partner/delivery/delivery.go

166 lines
7.2 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"
)
const (
warningDistance = 10 // 公里
warningWeight = 50 * 1000 // 克
maxDiffFee2Mtps = 200 // 与美团配送最多差价
maxAddFee = 200 // 最大增加费用,单位为分,超过不发三方配送了
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
}
if maxAddFee2 == 0 {
maxAddFee2 = maxAddFee
}
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
}
func CalculateOrderDeliveryFee(order *model.GoodsOrder, billTime time.Time, db *dao.DaoDB) (deliveryFee, addFee int64, err error) {
globals.SugarLogger.Debugf("CalculateOrderDeliveryFee orderID:%s", order.VendorOrderID)
if db == nil {
db = dao.GetDB()
}
jxStoreID := jxutils.GetSaleStoreIDFromOrder(order)
var lng, lat float64
priceInfo := &struct {
Price int
Lng int
Lat int
}{}
if err = dao.GetRow(db, 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.Infof("[运营]计算订单配送费orderID:%s,门店:%d没有坐标信息", order.VendorOrderID, jxutils.GetSaleStoreIDFromOrder(order))
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("[运营]计算订单配送费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)
}
}
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
}
func OnWaybillCreated(waybill *model.Waybill) {
deliveryFee := int64(math.Max(float64(waybill.DesiredFee), float64(waybill.ActualFee)))
if deliveryFee > alarmFee {
globals.SugarLogger.Infof("[运营]%s订单, orderID:%s, 成功创建%s运单:%s, 配送费:%s太高(大于%s),请知悉!", model.VendorChineseNames[waybill.OrderVendorID], waybill.VendorOrderID,
model.VendorChineseNames[waybill.WaybillVendorID], waybill.VendorWaybillID, jxutils.IntPrice2StandardCurrencyString(deliveryFee), jxutils.IntPrice2StandardCurrencyString(alarmFee))
}
}