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 }