修改蜂鸟配送

This commit is contained in:
邹宗楠
2022-03-25 09:36:45 +08:00
parent f1d6c0cff5
commit f8c576d750
9 changed files with 267 additions and 158 deletions

View File

@@ -1,32 +1,72 @@
package fn
import (
"strings"
"git.rosy.net.cn/baseapi/platformapi/fnpsapi"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/jx-callback/business/model"
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/business/partner"
"git.rosy.net.cn/jx-callback/globals/api"
)
func (c *DeliveryHandler) CreateStore(ctx *jxcontext.Context, storeDetail *dao.StoreDetail2) (vendorStoreID string, status int, err error) {
err = api.FnAPI.CreateStore(&fnpsapi.CreateStoreParam{
ChainStoreCode: utils.Int2Str(storeDetail.ID),
ChainStoreName: globals.StoreName + "-" + storeDetail.Name,
ContactPhone: storeDetail.Tel1,
Address: storeDetail.Address,
PositionSource: 3,
Longitude: utils.Float64ToStr(jxutils.IntCoordinate2Standard(storeDetail.Lng)),
Latitude: utils.Float64ToStr(jxutils.IntCoordinate2Standard(storeDetail.Lat)),
})
if err == nil {
vendorStoreID = utils.Int2Str(storeDetail.ID)
var (
auditStatusMap = map[int]int{
// 创建
fnpsapi.ShopCreateStatusAuditRejected: model.StoreAuditStatusCreated,
fnpsapi.ShopCreateStatusAuditPassed: model.StoreAuditStatusRejected,
fnpsapi.ShopCreateStatusAuditCreated: model.StoreAuditStatusCreated,
fnpsapi.ShopCreateStatusAuditOnline: model.StoreAuditStatusOnline,
fnpsapi.ShopCreateStatusAuditUpdateRejected: model.StoreAuditStatusOnline,
// 修改
fnpsapi.ShopUpdateStatusAuditRejected: model.StoreAuditStatusCreated,
}
return vendorStoreID, status, err
)
func getAuditStatus(vendorAuditStatus int) int {
if auditStatus, ok := auditStatusMap[vendorAuditStatus]; ok {
return auditStatus
}
return model.StoreAuditStatusCreated
}
func (c *DeliveryHandler) CreateStore(ctx *jxcontext.Context, storeDetail *dao.StoreDetail2) (vendorStoreID string, status int, err error) {
// 获取品牌名称
brandInfo, err := dao.GetBrands(dao.GetDB(), "", storeDetail.BrandID, "", false, "")
if err != nil {
return "", 0, err
}
createStore := &fnpsapi.CreateStoreBaseInfo{
ContactPhone: storeDetail.Tel1,
Address: storeDetail.Address,
Longitude: utils.Int2Float64(storeDetail.Lng) / 1000000,
Latitude: utils.Int2Float64(storeDetail.Lat) / 1000000,
PositionSource: 3,
OutShopCode: utils.Int2Str(storeDetail.ID),
CategoryID: "51",
OwnerName: storeDetail.IDName,
OwnerIDNum: storeDetail.IDCode,
HandheldLicencePicHash: "暂不需要(手持身份证、营业执照图片)",
OwnerIDPicFrontHash: "暂不需要(省份证正)",
OwnerIDPicBackHash: "暂不需要(身份证反)",
CreditCode: storeDetail.LicenceCode,
BusinessLicencePicHash: storeDetail.Licence,
}
if len(brandInfo) >= 0 {
createStore.HeadShopName = brandInfo[0].Name + "-" + storeDetail.Name
} else {
createStore.HeadShopName = storeDetail.Name
}
fnShopId, err := api.FnAPI.CreateStore(createStore)
if err != nil {
return "", 0, err
}
return fnShopId, status, err
}
func shopStatus2JX(status int) (jxStatus int) {
@@ -65,20 +105,68 @@ func (c *DeliveryHandler) IsErrStoreNotExist(err error) bool {
}
func (c *DeliveryHandler) UpdateStore(ctx *jxcontext.Context, storeDetail *dao.StoreDetail2) (err error) {
params := &fnpsapi.CreateStoreParam{
ChainStoreCode: utils.Int2Str(storeDetail.ID),
// ChainStoreName: globals.StoreName + "-" + storeDetail.Name,
ContactPhone: storeDetail.Tel1,
Address: storeDetail.Address,
PositionSource: 3,
Longitude: utils.Float64ToStr(jxutils.IntCoordinate2Standard(storeDetail.Lng)),
Latitude: utils.Float64ToStr(jxutils.IntCoordinate2Standard(storeDetail.Lat)),
// 获取品牌名称
brandInfo, err := dao.GetBrands(dao.GetDB(), "", storeDetail.BrandID, "", false, "")
if err != nil {
return err
}
if !strings.Contains(storeDetail.Name, globals.StoreName+"-") {
params.ChainStoreName = globals.StoreName + "-" + storeDetail.Name
updateStore := &fnpsapi.UpdateStoreParam{
ChainStoreID: "",
HeadShopName: brandInfo[0].Name + "-" + storeDetail.Name,
ContactPhone: storeDetail.Tel1,
Address: storeDetail.Address,
Longitude: utils.Int2Float64(storeDetail.Lng) / 1000000,
Latitude: utils.Int2Float64(storeDetail.Lat) / 1000000,
PositionSource: 3,
OutShopCode: utils.Int2Str(storeDetail.ID),
CategoryID: "51",
OwnerName: storeDetail.IDName,
OwnerIDNum: storeDetail.IDCode,
HandheldLicencePicHash: "暂不需要(手持身份证、营业执照图片)",
OwnerIDPicFrontHash: "暂不需要(省份证正)",
OwnerIDPicBackHash: "暂不需要(身份证反)",
CreditCode: storeDetail.LicenceCode,
BusinessLicencePicHash: storeDetail.Licence,
}
if len(brandInfo) >= 0 {
updateStore.HeadShopName = brandInfo[0].Name + "-" + storeDetail.Name
} else {
params.ChainStoreName = storeDetail.Name
updateStore.HeadShopName = storeDetail.Name
}
err = api.FnAPI.UpdateStore(params)
return err
return api.FnAPI.UpdateStore(updateStore)
}
// 蜂鸟门店状态改变
func OnStoreStatus(msg map[string]interface{}) (retVal *fnpsapi.CallbackResponse) {
return curDeliveryHandler.OnStoreStatus(msg)
}
// 修改本地门店审核状态
func (c *DeliveryHandler) OnStoreStatus(msg map[string]interface{}) (retVal *fnpsapi.CallbackResponse) {
var status int = 0
if storeStatus, ok := msg["status"]; ok && storeStatus != 0 {
status = int(utils.ForceInterface2Int64(storeStatus))
} else {
status = int(utils.ForceInterface2Int64(msg["modify_status"]))
}
err := partner.CurStoreManager.OnCourierStoreStatusChanged(
jxcontext.AdminCtx,
utils.Interface2String(msg["out_shop_code"]),
model.VendorIDFengNiao,
getAuditStatus(status),
utils.Interface2String(msg["remark"]),
)
retVal = fnpsapi.Err2CallbackResponse(err, "mtps OnStoreStatus")
return retVal
}
type ChainstoreParam struct {
MerchantId string `json:"merchant_id"` // 商户id
ChainStoreId string `json:"chain_store_id"` // 蜂鸟门店id
OutShopCode string `json:"out_shop_code"` // 外部门店编码
Status string `json:"status"` // 门店认证状态
ModifyStatus string `json:"modify_status"` // 门店修改状态
Remark string `json:"remark "` // 门店认证、修改等驳回时返回原因
}

View File

@@ -2,12 +2,11 @@ package fn
import (
"fmt"
"strings"
"time"
"git.rosy.net.cn/baseapi/utils"
"github.com/astaxie/beego/client/orm"
beego "github.com/astaxie/beego/server/web"
"strconv"
"strings"
"git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/jx-callback/business/partner/delivery"
@@ -65,17 +64,18 @@ func (c *DeliveryHandler) GetVendorID() int {
}
func (c *DeliveryHandler) CancelWaybill(bill *model.Waybill, cancelReasonID int, cancelReason string) (err error) {
err = api.FnAPI.CancelOrder(&fnpsapi.CancelOrderParam{
PartnerOrderCode: bill.VendorOrderID,
OrderCancelReasonCode: 1, //用户取消
OrderCancelCode: fnpsapi.OrderCancelReson9,
OrderCancelTime: time.Now().UnixNano() / 1e6,
})
if err != nil {
parameter := &fnpsapi.CancelOrderReq{
OrderCancelCode: fnpsapi.OrderCancelReson9,
OrderCancelRole: 2,
}
parameter.PartnerOrderCode = bill.VendorOrderID
if err = api.FnAPI.CancelOrder(parameter); err != nil {
if strings.Contains(err.Error(), "运单暂未生成") {
err = nil
}
}
bill.Status = model.WaybillStatusCanceled
bill.Remark = cancelReason
partner.CurOrderManager.OnWaybillStatusChanged(bill)
@@ -90,7 +90,6 @@ func (c *DeliveryHandler) ComplaintRider(bill *model.Waybill, resonID int, reson
// 创建蜂鸟配送订单
func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, maxDeliveryFee int64) (bill *model.Waybill, err error) {
db := dao.GetDB()
// 检查配送平台是否被禁用
vendorOrgCode, err := dao.GetVendorOrgCode(db, model.VendorIDFengNiao, "", model.VendorOrgTypeDelivery)
if err != nil {
@@ -100,84 +99,56 @@ func (c *DeliveryHandler) CreateWaybill(order *model.GoodsOrder, maxDeliveryFee
return nil, fmt.Errorf("此平台配送已被系统关闭,暂不发配送 [%v]", vendorOrgCode[0].Comment)
}
// 购物平台信息
storeDetail, err := dao.GetStoreDetail(db, order.StoreID, order.VendorID, order.VendorOrgCode)
// 自定义配送费
deliveryFee, _, err := delivery.CalculateOrderDeliveryFee(order, time.Now(), db)
if err != nil {
return nil, err
}
if err = delivery.CallCreateWaybillPolicy(deliveryFee, maxDeliveryFee, order, model.VendorIDFengNiao); err != nil {
return nil, err
// 蜂鸟入参结构体
parameter := &fnpsapi.CreateOrderReqParam{
PartnerOrderCode: order.VendorOrderID,
OrderType: 1,
PositionSource: 3,
ReceiverAddress: order.ConsigneeAddress,
ReceiverLongitude: utils.Int2Float64(order.ConsigneeLng) / 1000000,
ReceiverLatitude: utils.Int2Float64(order.ConsigneeLat) / 1000000,
GoodsTotalAmountCent: order.SalePrice,
GoodsActualAmountCent: order.ActualPayPrice,
GoodsWeight: utils.Int2Float64(order.Weight) / 1000,
GoodsCount: order.GoodsCount,
GoodsItemList: nil,
ReceiverName: order.ConsigneeName,
ReceiverPrimaryPhone: order.ConsigneeName,
OutShopCode: utils.Int2Str(order.StoreID),
ChainStoreId: "",
}
// 蜂鸟入参结构体
params := &fnpsapi.CreateOrderParam{
PartnerOrderCode: order.VendorOrderID,
NotifyURL: globals.FnNotifyURL,
ChainStoreCode: utils.Int2Str(jxutils.GetSaleStoreIDFromOrder(order)),
OrderType: 1, //即时达
TransportInfo: &fnpsapi.TransportInfo{
TransportName: order.StoreName,
TransportAddress: storeDetail.Address,
TransportLongitude: jxutils.IntCoordinate2Standard(storeDetail.Lng),
TransportLatitude: jxutils.IntCoordinate2Standard(storeDetail.Lat),
PositionSource: 3,
TransportTel: storeDetail.Tel1,
},
OrderAddTime: order.OrderCreatedAt.UnixNano() / 1e6,
OrderTotalAmount: jxutils.IntPrice2Standard(order.SalePrice),
OrderActualAmount: jxutils.IntPrice2Standard(order.ActualPayPrice),
OrderWeight: float64(jxutils.IntWeight2Float(order.Weight)),
OrderRemark: utils.FilterMb4("客户电话:" + order.ConsigneeMobile + "," + order.BuyerComment + "取货失败或配送遇到问题请联系18048531223禁止未配送直接完成定单"),
IsInvoiced: 0,
OrderPaymentStatus: 1,
OrderPaymentMethod: 1,
IsAgentPayment: 0,
GoodsCount: order.GoodsCount,
ReceiverInfo: &fnpsapi.ReceiverInfo{
ReceiverName: order.ConsigneeName,
ReceiverAddress: order.ConsigneeAddress,
ReceiverLongitude: jxutils.IntCoordinate2Standard(order.ConsigneeLng),
ReceiverLatitude: jxutils.IntCoordinate2Standard(order.ConsigneeLat),
ReceiverPrimaryPhone: order.ConsigneeMobile,
ReceiverSecondPhone: order.ConsigneeMobile2,
PositionSource: 3,
},
SerialNumber: model.VendorNames[order.VendorID] + " #" + utils.Int2Str(order.OrderSeq),
}
var skuInfo []*fnpsapi.ItemsJSON
var goodsList []*fnpsapi.GoodsItemsList
for _, v := range order.Skus {
skuInfo = append(skuInfo, &fnpsapi.ItemsJSON{
ItemID: utils.Int2Str(v.SkuID),
ItemName: v.SkuName,
ItemQuantity: v.Count,
ItemPrice: jxutils.IntPrice2Standard(v.SalePrice),
ItemActualPrice: jxutils.IntPrice2Standard(v.SalePrice),
goodsList = append(goodsList, &fnpsapi.GoodsItemsList{
ItemName: v.SkuName,
ItemQuantity: v.Count,
ItemAmountCent: v.SalePrice,
ItemActualAmountCent: v.SalePrice,
ItemId: utils.Int2Str(v.SkuID),
})
}
params.ItemsJSON = skuInfo
parameter.GoodsItemList = goodsList
//要求饿百的订单要传来源
if order.VendorID == model.VendorIDEBAI {
params.OrderSource = "109"
params.ChannelOrderCode = order.VendorOrderID
parameter.OrderSource = "109"
}
// 创建蜂鸟订单
err = api.FnAPI.CreateOrder(params)
if err != nil {
globals.SugarLogger.Debugf("CreateWaybill failed, orderID:%s, billParams:%v, error:%v", order.VendorOrderID, params, err)
if err = api.FnAPI.CreateOrder(parameter); err != nil {
globals.SugarLogger.Debugf("CreateWaybill failed, orderID:%s, billParams:%v, error:%v", order.VendorOrderID, parameter, err)
return nil, err
}
// 查询订单获取配送费
bill = &model.Waybill{
VendorOrderID: order.VendorOrderID,
OrderVendorID: order.VendorID,
VendorWaybillID: "",
VendorWaybillID2: "",
WaybillVendorID: model.VendorIDFengNiao,
DesiredFee: deliveryFee,
DesiredFee: GetDesiredFee(order.VendorOrderID),
}
delivery.OnWaybillCreated(bill)
return bill, err
@@ -199,55 +170,90 @@ func (c *DeliveryHandler) getMTPSShopID(order *model.GoodsOrder, db *dao.DaoDB)
return retVal, nil
}
// 预下单获取配送费
func (c *DeliveryHandler) GetWaybillFee(order *model.GoodsOrder) (deliveryFeeInfo *partner.WaybillFeeInfo, err error) {
db := dao.GetDB()
deliveryFeeInfo = &partner.WaybillFeeInfo{}
deliveryFeeInfo.RefDeliveryFee, deliveryFeeInfo.RefAddFee, err = delivery.CalculateOrderDeliveryFee(order, time.Now(), db)
if err == nil {
if _, err = c.getMTPSShopID(order, db); err == nil {
deliveryFeeInfo.DeliveryFee = deliveryFeeInfo.RefDeliveryFee
}
preCreateOrder := &fnpsapi.PreCreateOrder{
PartnerOrderCode: order.VendorOrderID,
OrderType: 1,
PositionSource: 3,
ReceiverAddress: order.ConsigneeAddress,
ReceiverLongitude: utils.Int2Float64(order.ConsigneeLng) / 1000000,
ReceiverLatitude: utils.Int2Float64(order.ConsigneeLat) / 1000000,
GoodsTotalAmountCent: order.SalePrice,
GoodsActualAmountCent: order.ActualPayPrice,
GoodsWeight: utils.Int2Float64(order.Weight) / 1000,
GoodsCount: order.GoodsCount,
GoodsItemList: nil,
OutShopCode: utils.Int2Str(order.StoreID),
}
var goodsList []*fnpsapi.GoodsItemsList
for _, v := range order.Skus {
goodsList = append(goodsList, &fnpsapi.GoodsItemsList{
ItemName: v.SkuName,
ItemQuantity: v.Count,
ItemAmountCent: v.SalePrice,
ItemActualAmountCent: v.SalePrice,
ItemId: utils.Int2Str(v.SkuID),
})
}
preCreateOrder.GoodsItemList = goodsList
deliveryFeeInfo.RefDeliveryFee, deliveryFeeInfo.RefAddFee, err = api.FnAPI.PreCreateByShopFn(preCreateOrder)
return deliveryFeeInfo, err
}
func OnWaybillMsg(msg *fnpsapi.WayBillInfo) {
func OnWaybillMsg(msg map[string]interface{}) (resp *fnpsapi.CallbackResponse) {
order := &model.Waybill{
VendorWaybillID: utils.Int64ToStr(msg.OpenOrderCode),
VendorWaybillID2: msg.PartnerOrderCode,
VendorWaybillID: utils.Interface2String(msg["open_order_code"]),
VendorWaybillID2: utils.Interface2String(msg["partner_order_code"]),
WaybillVendorID: model.VendorIDFengNiao,
CourierName: msg.CarrierDriverName,
CourierMobile: msg.CarrierDriverPhone,
VendorStatus: utils.Int2Str(msg.OrderStatus),
StatusTime: utils.Timestamp2Time(msg.PushTime),
Remark: msg.Description,
CourierName: utils.Interface2String(msg["carrier_driver_name"]),
CourierMobile: utils.Interface2String(msg["carrier_driver_phone"]),
VendorStatus: utils.Interface2String(msg["order_status"]),
StatusTime: utils.Timestamp2Time(utils.MustInterface2Int64(msg["push_time"])),
Remark: utils.Interface2String(msg["description"]),
}
order.VendorOrderID, order.OrderVendorID = jxutils.SplitUniversalOrderID(msg.PartnerOrderCode)
switch msg.OrderStatus {
case fnpsapi.OrderStatusAccept:
order.Status = model.WaybillStatusNew
case fnpsapi.OrderStatusAssigned:
order.VendorOrderID, order.OrderVendorID = jxutils.SplitUniversalOrderID(order.VendorWaybillID2)
orderStatus, err := strconv.Atoi(order.VendorStatus)
if err != nil {
globals.SugarLogger.Debugf("FNPS strconv.Atoi fail :[%s]", err)
return fnpsapi.Err2CallbackResponse(err, "")
}
switch orderStatus {
case fnpsapi.OrderStatusAcceptCreate: // 0 创建订单
order.DesiredFee = GetDesiredFee(order.VendorOrderID)
order.Status = model.WaybillStatusAccepted
order.Status = model.WaybillStatusNew //5 带调度
case fnpsapi.OrderStatusAccept: // 1 新运单
order.DesiredFee = GetDesiredFee(order.VendorOrderID)
order.Status = model.WaybillStatusNew //5 带调度
case fnpsapi.OrderStatusAssigned: //20分配骑手
order.DesiredFee = GetDesiredFee(order.VendorOrderID)
order.Status = model.WaybillStatusAccepted //10
order.Remark = order.CourierName + "" + order.CourierMobile
case fnpsapi.OrderStatusArrived:
case fnpsapi.OrderStatusArrived: // 80 到店
order.DesiredFee = GetDesiredFee(order.VendorOrderID)
order.Status = model.WaybillStatusCourierArrived
case fnpsapi.OrderStatusDelivering:
case fnpsapi.OrderStatusDelivering: // 2 配送中
order.Status = model.WaybillStatusDelivering
case fnpsapi.OrderStatusDelivered:
case fnpsapi.OrderStatusDelivered: // 3 已经送达
order.Status = model.WaybillStatusDelivered
case fnpsapi.OrderStatusException:
order.Status = model.WaybillStatusDeliverFailed
case fnpsapi.OrderStatusAcceptCacle: // 4取消订单
order.Status = model.WaybillStatusAcceptCanceled
case fnpsapi.OrderStatusException: // 5 异常
order.Status = model.WaybillStatusDeliverFailed // 22
default:
globals.SugarLogger.Warnf("onWaybillMsg unknown msg:%v", msg)
}
partner.CurOrderManager.OnWaybillStatusChanged(order)
if err := partner.CurOrderManager.OnWaybillStatusChanged(order); err != nil {
globals.SugarLogger.Debugf("FNPS partner.CurOrderManager.OnWaybillStatusChanged fail :[%s]", err)
return fnpsapi.Err2CallbackResponse(err, "")
}
return fnpsapi.Err2CallbackResponse(nil, "")
}
// 查询订单配送费
func GetDesiredFee(vendorOrderID string) (desiredFee int64) {
if result, err := api.FnAPI.QueryOrder(vendorOrderID); err == nil {
return jxutils.StandardPrice2Int(result.OrderTotalDeliveryCost)
return result.OrderActualAmountCent
}
return desiredFee
}

View File

@@ -91,7 +91,6 @@ func (c *DeliveryHandler) onWaybillMsg(msg *mtpsapi.CallbackOrderMsg) (retVal *m
if err != nil {
return mtpsapi.Err2CallbackResponse(err, fmt.Sprintf("%s", "获取订单状态错误"))
}
//order.DesiredFee, _ = delivery.CalculateBillDeliveryFee(order) // 美团外卖可能会丢失新运单事件,这里补一下
order.DesiredFee = utils.Float64TwoInt64(utils.MustInterface2Float64(data["delivery_fee"]) * 100)
order.Status = model.WaybillStatusNew
case mtpsapi.OrderStatusAccepted:
@@ -100,7 +99,6 @@ func (c *DeliveryHandler) onWaybillMsg(msg *mtpsapi.CallbackOrderMsg) (retVal *m
return mtpsapi.Err2CallbackResponse(err, fmt.Sprintf("%s", "获取订单状态错误"))
}
order.DesiredFee = utils.Float64TwoInt64(utils.MustInterface2Float64(data["delivery_fee"]) * 100)
//order.DesiredFee, _ = delivery.CalculateBillDeliveryFee(order) // 美团外卖可能会丢失新运单事件,这里补一下
order.Status = model.WaybillStatusAccepted
order.Remark = order.CourierName + "" + order.CourierMobile
case mtpsapi.OrderStatusPickedUp: