From 16a3261bd1b374e33815fd881eef95f68cfdccd8 Mon Sep 17 00:00:00 2001 From: gazebo Date: Thu, 24 Jan 2019 14:34:49 +0800 Subject: [PATCH] - refactor CalculateOrderDeliveryFee - use QueryDeliverFee and AddOrderAfterQuery for dada --- business/partner/delivery/dada/waybill.go | 33 ++++- business/partner/delivery/delivery.go | 104 ++++++++++++++++ business/partner/delivery/mtps/waybill.go | 140 +++------------------- 3 files changed, 147 insertions(+), 130 deletions(-) create mode 100644 business/partner/delivery/delivery.go diff --git a/business/partner/delivery/dada/waybill.go b/business/partner/delivery/dada/waybill.go index e2efc97d0..8b62b54f2 100644 --- a/business/partner/delivery/dada/waybill.go +++ b/business/partner/delivery/dada/waybill.go @@ -3,6 +3,7 @@ package dada import ( "errors" "fmt" + "time" "git.rosy.net.cn/baseapi/platformapi/dadaapi" "git.rosy.net.cn/baseapi/utils" @@ -10,6 +11,7 @@ import ( "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/business/partner/delivery" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" "github.com/astaxie/beego" @@ -17,12 +19,14 @@ import ( ) const ( - maxOrderPrice = 6399 // 单位为分,达达最大价格,超过这个价格配送费会增加 - maxOrderWeight = 5000 // 5公斤 + maxOrderPrice = 6399 // 单位为分,达达最大价格,超过这个价格配送费会增加 + maxOrderWeight = 5000 // 5公斤 + maxDiffFee2Mtps = 100 // 与美团配送最多差价 ) var ( ErrCanNotFindDadaCityCode = errors.New("不能找到美团配送站点配置") + ErrExceedMaxDiffFee2Mtps = errors.New("与美团配送超价太多") ) var ( @@ -59,6 +63,7 @@ func (c *DeliveryHandler) onWaybillMsg(msg *dadaapi.CallbackMsg) (retVal *dadaap order.Status = model.WaybillStatusNew case dadaapi.OrderStatusAccepted: if result, err := api.DadaAPI.QueryOrderInfo(msg.OrderID); err == nil { + order.ActualFee = jxutils.StandardPrice2Int(utils.Interface2FloatWithDefault(result["actualFee"], 0.0)) order.DesiredFee = jxutils.StandardPrice2Int(utils.Interface2FloatWithDefault(result["deliveryFee"], 0.0)) } order.Status = model.WaybillStatusAccepted @@ -98,6 +103,16 @@ func (c *DeliveryHandler) callbackMsg2Waybill(msg *dadaapi.CallbackMsg) (retVal // IDeliveryPlatformHandler func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, policy func(deliveryFee, addFee int64) error) (bill *model.Waybill, err error) { + db := orm.NewOrm() + deliveryFee, addFee, err := delivery.CalculateOrderDeliveryFee(order, time.Now(), db) + if err != nil { + return nil, err + } + if policy != nil { + if err = policy(deliveryFee, addFee); err != nil { + return nil, err + } + } billParams := &dadaapi.OperateOrderRequiredParams{ // ShopNo: utils.Int2Str(order.StoreID), // 当前达达的门店号与京西是一样的 OriginID: jxutils.ComposeUniversalOrderID(order.VendorOrderID, order.VendorID), @@ -107,7 +122,6 @@ func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, policy func(del ReceiverAddress: utils.FilterMb4(order.ConsigneeAddress), ReceiverPhone: order.ConsigneeMobile, } - db := orm.NewOrm() if billParams.ShopNo, err = c.getDadaShopID(order, db); err == nil { if billParams.CityCode, err = c.getDataCityCodeFromOrder(order, db); err == nil { billParams.ReceiverLng, billParams.ReceiverLat, _ = jxutils.IntCoordinate2MarsStandard(order.ConsigneeLng, order.ConsigneeLat, order.CoordinateType) @@ -137,7 +151,18 @@ func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, policy func(del if err2 != nil { globals.SugarLogger.Warnf("CreateWaybill orderID:%s error:%v", order.VendorOrderID, err2) } - result, err = api.DadaAPI.AddOrder(billParams, addParams) + if false { + result, err = api.DadaAPI.AddOrder(billParams, addParams) + } else { + if result, err = api.DadaAPI.QueryDeliverFee(billParams, addParams); err != nil { + return nil, err + } + if jxutils.StandardPrice2Int(result.Fee)-deliveryFee > maxDiffFee2Mtps { + globals.SugarLogger.Infof("CreateWaybill orderID:%s 达达与美团配送超价太多,达达:%d,美团配送:%d", order.VendorOrderID, result.Fee, deliveryFee) + return nil, ErrExceedMaxDiffFee2Mtps + } + err = api.DadaAPI.AddOrderAfterQuery(result.DeliveryNo) + } } if err == nil && result != nil { bill = &model.Waybill{ diff --git a/business/partner/delivery/delivery.go b/business/partner/delivery/delivery.go new file mode 100644 index 000000000..4a96d4258 --- /dev/null +++ b/business/partner/delivery/delivery.go @@ -0,0 +1,104 @@ +package delivery + +import ( + "errors" + "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 // 克 +) + +var ( + ErrStoreNoCoordinate = errors.New("找不到门店的坐标信息") +) + +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 lng == 0 || lat == 0 { + globals.SugarLogger.Warnf("calculateDeliveryFee can not calculate delivery fee for orderID:%s, because no coordinate info", order.VendorOrderID) + return 0, 0, ErrStoreNoCoordinate + } + lng2, lat2, _ := jxutils.IntCoordinate2MarsStandard(order.ConsigneeLng, order.ConsigneeLat, order.CoordinateType) + + var distanceAddFee, weightAddFee, timeAddFee int64 + distance := jxutils.EarthDistance(lat, lng, lat2, lng2) * 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.Warnf("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.Warnf("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:%d timeAddFee:%d", order.VendorOrderID, deliveryFee, addFee, distance, distanceAddFee, order.Weight, weightAddFee, totalSeconds, 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 +} diff --git a/business/partner/delivery/mtps/waybill.go b/business/partner/delivery/mtps/waybill.go index e57f1e093..6c942ed79 100644 --- a/business/partner/delivery/mtps/waybill.go +++ b/business/partner/delivery/mtps/waybill.go @@ -3,7 +3,6 @@ package mtps import ( "errors" "fmt" - "math" "time" "git.rosy.net.cn/baseapi/platformapi/mtpsapi" @@ -13,6 +12,7 @@ import ( "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/business/model/legacymodel" "git.rosy.net.cn/jx-callback/business/partner" + "git.rosy.net.cn/jx-callback/business/partner/delivery" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" "github.com/astaxie/beego" @@ -27,7 +27,6 @@ const ( var ( ErrCanNotFindMTPSStore = errors.New("不能找到美团配送站点配置") ErrStoreNoPriceInfo = errors.New("找不到门店的美团配送价格信息") - ErrStoreNoCoordinate = errors.New("找不到门店的坐标信息") ) var ( @@ -85,7 +84,7 @@ func (c *DeliveryHandler) onWaybillMsg(msg *mtpsapi.CallbackOrderMsg) (retVal *m case mtpsapi.OrderStatusWaitingForSchedule: order.Status = model.WaybillStatusNew case mtpsapi.OrderStatusAccepted: - order.DesiredFee, _ = c.calculateBillDeliveryFee(order) + order.DesiredFee, _ = delivery.CalculateBillDeliveryFee(order) order.Status = model.WaybillStatusAccepted case mtpsapi.OrderStatusPickedUp: order.Status = model.WaybillStatusDelivering @@ -115,97 +114,10 @@ func (c *DeliveryHandler) callbackMsg2Waybill(msg *mtpsapi.CallbackOrderMsg) (re return retVal } -func (c *DeliveryHandler) calculateOrderDeliveryFee(order *model.GoodsOrder, billTime time.Time, db orm.Ormer) (deliveryFee, addFee int64, err error) { - if db == nil { - db = orm.NewOrm() - } - jxStoreID := jxutils.GetSaleStoreIDFromOrder(order) - var lng, lat float64 - if globals.OrderUseNewTable || jxStoreID == globals.DebugStoreID { - 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) - } else { - var lists []orm.ParamsList - num, err := db.Raw(` - SELECT t2.price, t1.lng, t1.lat - FROM jxstore t1 - JOIN mtpsdeliveryprice t2 ON t2.citycode = t1.area - WHERE t1.storeid = ? - `, jxStoreID).ValuesList(&lists) - if err != nil || num == 0 { - globals.SugarLogger.Warnf("calculateDeliveryFee can not calculate delivery fee for orderID:%s, num:%d, error:%v", order.VendorOrderID, num, err) - if err != nil { - return 0, 0, err - } - return 0, 0, ErrStoreNoPriceInfo - } - lng = utils.Str2Float64(utils.Interface2String(lists[0][1])) - lat = utils.Str2Float64(utils.Interface2String(lists[0][2])) - deliveryFee = utils.Str2Int64(lists[0][0].(string)) - } - - if lng == 0 || lat == 0 { - globals.SugarLogger.Warnf("calculateDeliveryFee can not calculate delivery fee for orderID:%s, because no coordinate info", order.VendorOrderID) - return 0, 0, ErrStoreNoCoordinate - } - lng2, lat2, _ := jxutils.IntCoordinate2MarsStandard(order.ConsigneeLng, order.ConsigneeLat, order.CoordinateType) - - distance := jxutils.EarthDistance(lat, lng, lat2, lng2) * 1.4 - if distance < 3 { - } else if distance < 5 { - addFee += jxutils.StandardPrice2Int(math.Ceil(distance - 3)) - } else { - addFee += jxutils.StandardPrice2Int(2 + 2*math.Ceil(distance-5)) - } - - if order.Weight < 5*1000 { - } else if order.Weight < 10*1000 { - addFee += jxutils.StandardPrice2Int(0.5 * float64(jxutils.IntWeight2Float(order.Weight)-5)) - } else if order.Weight < 20*1000 { - addFee += jxutils.StandardPrice2Int(2.5 + 1*float64(jxutils.IntWeight2Float(order.Weight)-10)) - } else { - addFee += jxutils.StandardPrice2Int(2.5 + 10 + 2*float64(jxutils.IntWeight2Float(order.Weight)-20)) - } - - hour, min, sec := billTime.Clock() - totalSeconds := hour*3600 + min*60 + sec - if totalSeconds >= 11*3600 && totalSeconds <= 14*3600 { // 11:00 -- 14:00 - addFee += jxutils.StandardPrice2Int(3) - } - // else if totalSeconds >= 21*3600 || totalSeconds <= 6*3600 { // 21:00 -- 06:00 - // addFee += jxutils.StandardPrice2Int(3) - // } - return deliveryFee + addFee, addFee, nil -} - -func (c *DeliveryHandler) calculateBillDeliveryFee(bill *model.Waybill) (deliveryFee, addFee int64) { - order, err := partner.CurOrderManager.LoadOrder(bill.VendorOrderID, bill.OrderVendorID) - if err != nil { - return 0, 0 - } - deliveryFee, addFee, _ = c.calculateOrderDeliveryFee(order, bill.StatusTime, nil) - return deliveryFee, addFee -} - // IDeliveryPlatformHandler func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, policy func(deliveryFee, addFee int64) error) (bill *model.Waybill, err error) { db := orm.NewOrm() - deliveryFee, addFee, err := c.calculateOrderDeliveryFee(order, time.Now(), db) + deliveryFee, addFee, err := delivery.CalculateOrderDeliveryFee(order, time.Now(), db) if err == nil { if policy != nil { err = policy(deliveryFee, addFee) @@ -300,43 +212,19 @@ func (c *DeliveryHandler) getDeliveryID(order *model.GoodsOrder, db orm.Ormer) ( func (c *DeliveryHandler) getMTPSShopID(order *model.GoodsOrder, db orm.Ormer) (retVal string, err error) { saleStoreID := jxutils.GetSaleStoreIDFromOrder(order) - if globals.OrderUseNewTable || saleStoreID == globals.DebugStoreID { - db2 := dao.WrapDB(db) - storeCourierList, err2 := dao.GetOpenedStoreCouriersByStoreID(db2, saleStoreID, model.VendorIDMTPS) - if err = err2; err != nil && err != orm.ErrNoRows { - return "", err - } - if len(storeCourierList) == 0 { - return "", partner.ErrStoreHaveNoCourier - } - retVal = storeCourierList[0].VendorStoreID - if beego.BConfig.RunMode == "dev" { - retVal = "test_0001" - } - return retVal, nil + db2 := dao.WrapDB(db) + storeCourierList, err2 := dao.GetOpenedStoreCouriersByStoreID(db2, saleStoreID, model.VendorIDMTPS) + if err = err2; err != nil && err != orm.ErrNoRows { + return "", err } - sql := "SELECT zs_store_id FROM jx_to_zs_store_map WHERE jx_store_id = ?" - var lists []orm.ParamsList - num, err := db.Raw(sql, saleStoreID).ValuesList(&lists) - if err == nil && num == 1 { - retVal = lists[0][0].(string) - if beego.BConfig.RunMode == "dev" { - retVal = "test_0001" - } - } else { - globals.SugarLogger.Infof("getMTPSShopID can not find mtps store info for orderID:%s, store:%d, num:%d, error:%v", order.VendorOrderID, saleStoreID, num, err) - if err == nil { - err = ErrCanNotFindMTPSStore - } - - tmpLog := &legacymodel.TempLog{ - VendorOrderID: order.VendorOrderID, - RefVendorOrderID: order.VendorOrderID, - Msg: fmt.Sprintf("getMTPSShopID can not find mtps store info for orderID:%s, store:%d, num:%d, error:%v", order.VendorOrderID, saleStoreID, num, err), - } - db.Insert(tmpLog) + if len(storeCourierList) == 0 { + return "", partner.ErrStoreHaveNoCourier } - return retVal, err + retVal = storeCourierList[0].VendorStoreID + if beego.BConfig.RunMode == "dev" { + retVal = "test_0001" + } + return retVal, nil } func limitOrderWeight(weight int) int {