This commit is contained in:
richboo111
2023-05-23 09:36:17 +08:00
parent d72d5dc75d
commit 0d41d6e46b
9 changed files with 466 additions and 21 deletions

View File

@@ -109,10 +109,10 @@ func GetOrderRiderInfoToPlatform(orderId string, wayBillStatus int) {
riderInfo := &mtpsapi.RiderInfo{}
if handlerInfo := partner.GetDeliveryPlatformFromVendorID(v.WaybillVendorID); handlerInfo != nil {
if v.WaybillVendorID == model.VendorIDDada || v.WaybillVendorID == model.VendorIDFengNiao || v.WaybillVendorID == model.VendorIDUUPT {
if v.WaybillVendorID == model.VendorIDDada || v.WaybillVendorID == model.VendorIDFengNiao || v.WaybillVendorID == model.VendorIDUUPT || v.WaybillVendorID == model.VendorIDSFPS {
riderInfo, err = handlerInfo.Handler.GetRiderInfo(v.VendorOrderID, 0, v.VendorWaybillID)
if err != nil {
globals.SugarLogger.Debug("Get Order waybill rider info err FN/DADA/DYPS :%v", err)
globals.SugarLogger.Debug("Get Order waybill rider info err FN/DADA/SFPS :%v", err)
}
} else if v.WaybillVendorID == model.VendorIDMTPS {
if v.VendorWaybillID != "" {

View File

@@ -0,0 +1,401 @@
package sfps
import (
"errors"
"fmt"
"time"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/business/partner/delivery"
"git.rosy.net.cn/jx-callback/business/jxutils"
"git.rosy.net.cn/baseapi/platformapi/mtpsapi"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/jx-callback/globals/api"
"git.rosy.net.cn/baseapi/utils"
"git.rosy.net.cn/jx-callback/business/model/dao"
"git.rosy.net.cn/jx-callback/business/partner"
"git.rosy.net.cn/baseapi/platformapi/sfps2"
"git.rosy.net.cn/jx-callback/business/model"
)
type DeliveryHandler struct {
}
var (
curDeliveryHandler *DeliveryHandler
)
func init() {
if api.SfPsAPI != nil {
curDeliveryHandler = new(DeliveryHandler)
partner.RegisterDeliveryPlatform(curDeliveryHandler, true)
}
}
func (d DeliveryHandler) GetVendorID() int {
return model.VendorIDSFPS
}
func (d DeliveryHandler) CreateStore(ctx *jxcontext.Context, storeDetail *dao.StoreDetail2) (vendorStoreID string, status int, err error) {
return "", 0, fmt.Errorf("顺丰派送暂不支持此操作")
}
func (d DeliveryHandler) GetStore(ctx *jxcontext.Context, storeID int, vendorStoreID string) (storeDetail *dao.StoreDetail2, err error) {
store, err := dao.GetStoreDetail(dao.GetDB(), utils.Str2Int(vendorStoreID), model.VendorIDSFPS, "")
if err == nil {
storeDetail = &dao.StoreDetail2{
Store: model.Store{
Name: store.Name,
Tel1: store.Tel1,
Address: store.Address,
Lat: store.Lat,
Lng: store.Lng,
},
VendorID: model.VendorIDSFPS,
VendorStoreID: utils.Int2Str(storeID),
CourierStatus: model.StoreStatusOpened,
}
}
return storeDetail, err
}
func (d DeliveryHandler) IsErrStoreNotExist(err error) bool {
return false
}
func (d DeliveryHandler) IsErrStoreExist(err error) bool {
return false
}
func (d DeliveryHandler) CreateWaybill(order *model.GoodsOrder, maxDeliveryFee int64) (bill *model.Waybill, err error) {
vendorOrgCode, err := dao.GetVendorOrgCode(dao.GetDB(), model.VendorIDSFPS, "", model.VendorOrgTypeDelivery)
if err != nil {
return nil, err
}
if len(vendorOrgCode) > 0 && vendorOrgCode[0].IsOpen == model.YES {
return nil, fmt.Errorf("此平台配送已被系统关闭,暂不发配送 [%v]", vendorOrgCode[0].Comment)
}
store, err := dao.GetStoreDetail(dao.GetDB(), getReallyStoreID(order.StoreID, order.JxStoreID), 0, "")
if err != nil {
return nil, err
}
var (
weight int
productDetail []*sfps2.ProductDetail
)
if order.Weight >= 49500 {
weight = 49500
} else {
weight = order.Weight
}
param := &sfps2.CreateOrderReq{
ShopId: sfps2.SFShopStoreID,
ShopOrderId: order.VendorOrderID,
OrderSource: GetVendorSource(order.VendorID),
OrderTime: order.CreatedAt.Unix(),
Receive: &sfps2.ReceiveAddress{
UserName: order.ConsigneeName,
UserPhone: order.ConsigneeMobile,
UserAddress: order.ConsigneeAddress,
UserLat: utils.Float64ToStr(jxutils.IntCoordinate2Standard(order.ConsigneeLat)),
UserLng: utils.Float64ToStr(jxutils.IntCoordinate2Standard(order.ConsigneeLng)),
},
Shop: &sfps2.SfShopInfo{
ShopName: order.StoreName,
ShopPhone: store.Tel1,
ShopAddress: store.Address,
ShopLat: utils.Float64ToStr(jxutils.IntCoordinate2Standard(store.Lat)),
ShopLng: utils.Float64ToStr(jxutils.IntCoordinate2Standard(store.Lng)),
},
OrderDetail: &sfps2.OrderDetail{
TotalPrice: order.ActualPayPrice,
ProductType: sfps2.ProductTypeFresh,
WeightGram: int64(weight),
ProductNum: int64(order.GoodsCount),
ProductTypeNum: int64(order.SkuCount),
},
}
for _, v := range order.Skus {
productDetail = append(productDetail, &sfps2.ProductDetail{
ProductName: v.SkuName,
ProductNum: int64(v.Count),
})
}
param.OrderDetail.ProductDetail = productDetail
sfOrderID, sfBillID, sfTotalPrice, err := api.SfPsAPI.CreateOrder(param)
if err != nil {
return nil, err
}
bill = &model.Waybill{
VendorOrderID: order.VendorOrderID,
OrderVendorID: order.VendorID,
VendorWaybillID: sfOrderID,
VendorWaybillID2: sfBillID,
WaybillVendorID: model.VendorIDFengNiao,
DesiredFee: int64(sfTotalPrice),
}
delivery.OnWaybillCreated(bill)
return bill, err
}
func (d DeliveryHandler) CancelWaybill(bill *model.Waybill, cancelReasonID int, cancelReason string) (err error) {
if err = api.SfPsAPI.CancelOrder(bill.VendorWaybillID); err != nil {
return err
}
bill.Status = model.WaybillStatusCanceled
bill.Remark = cancelReason
partner.CurOrderManager.OnWaybillStatusChanged(bill)
return nil
}
func (d DeliveryHandler) GetWaybillFee(order *model.GoodsOrder) (deliveryFeeInfo *partner.WaybillFeeInfo, err error) {
var (
weight int
//productDetail []*sfps2.ProductDetail
)
if order.Weight >= 49500 {
weight = 49500
} else {
weight = order.Weight
}
store, err := dao.GetStoreDetail(dao.GetDB(), getReallyStoreID(order.StoreID, order.JxStoreID), 0, "")
if err != nil {
return nil, err
}
param := &sfps2.PreCreateOrderReq{
ShopId: sfps2.SFShopStoreID,
UserLng: utils.Float64ToStr(jxutils.IntCoordinate2Standard(order.ConsigneeLng)),
UserLat: utils.Float64ToStr(jxutils.IntCoordinate2Standard(order.ConsigneeLat)),
UserAddress: order.ConsigneeAddress,
Weight: int64(weight),
ProductType: sfps2.ProductTypeFresh,
Shop: &sfps2.SfShopInfo{
ShopName: order.StoreName,
ShopPhone: store.Tel1,
ShopAddress: store.Address,
ShopLat: utils.Float64ToStr(jxutils.IntCoordinate2Standard(store.Lat)),
ShopLng: utils.Float64ToStr(jxutils.IntCoordinate2Standard(store.Lng)),
},
}
deliveryFeeInfo = &partner.WaybillFeeInfo{}
price, err := api.SfPsAPI.PreCreateOrder(param)
deliveryFeeInfo.DeliveryFee = jxutils.StandardPrice2Int(price)
return deliveryFeeInfo, err
}
func (d DeliveryHandler) ComplaintRider(bill *model.Waybill, resonID int, resonContent string) (err error) {
return nil
}
func (d DeliveryHandler) GetRiderInfo(orderId string, deliveryId int64, mtPeisongId string) (rider *mtpsapi.RiderInfo, err error) {
order, err := dao.GetWaybills(dao.GetDB(), orderId)
if len(order) == 0 || err != nil {
return nil, errors.New("顺丰 订单id无效请检查")
}
//获取顺丰运单详情
sfOrder, err := api.SfPsAPI.GetOrderStatus(order[0].VendorWaybillID)
//获取顺丰骑手实时位置
sfRider, err := api.SfPsAPI.GetRiderLatestPosition(sfOrder.OrderID)
result := &mtpsapi.RiderInfo{
OrderId: orderId,
ThirdCarrierOrderId: sfOrder.OrderID,
CourierName: sfOrder.RiderName,
CourierPhone: sfOrder.RiderPhone,
LogisticsProviderCode: mtpsapi.SFPSCode,
LogisticsStatus: utils.Float64TwoInt(sfOrder.OrderStatus), // 默认正在配送中
Latitude: sfRider.RiderLat,
Longitude: sfRider.RiderLng,
}
switch sfOrder.OrderStatus {
case sfps2.OrderStatusNewOrder:
result.LogisticsStatus = model.WaybillStatusNew
result.LogisticsContext = model.RiderWaitRider
case sfps2.OrderStatusTakeOrder:
result.LogisticsStatus = model.WaybillStatusCourierAssigned
result.LogisticsContext = model.RiderGetOrder
case sfps2.OrderStatusArrivedStore:
result.LogisticsStatus = model.WaybillStatusCourierArrived
result.LogisticsContext = model.RiderToStore
case sfps2.OrderStatusRiderArriving:
result.LogisticsStatus = model.WaybillStatusDelivering
result.LogisticsContext = model.RiderGetOrderDelivering
case sfps2.OrderStatusFinished:
result.LogisticsStatus = model.WaybillStatusDelivered
result.LogisticsContext = model.RiderGetOrderDelivered
case sfps2.OrderStatusOrderCancel:
result.LogisticsStatus = model.WaybillStatusCanceled
result.LogisticsContext = model.RiderGetOrderCanceled
case sfps2.OrderStatusError:
result.LogisticsStatus = model.WaybillStatusDeliverFailed
result.LogisticsContext = model.RiderGetOrderDeliverFailed
default:
result.LogisticsStatus = 0
result.LogisticsContext = model.RiderGetOrderDeliverOther
}
return result, nil
}
// OnWaybillMsg 配送状态更改回调
func OnWaybillMsg(msg *sfps2.RiderStatus) (resp *sfps2.CallbackResponse) {
order := &model.Waybill{
VendorWaybillID: msg.SFOrderID,
WaybillVendorID: model.VendorIDSFPS,
VendorOrderID: msg.ShopOrderID,
CourierName: msg.OperatorName,
CourierMobile: msg.OperatorPhone,
VendorStatus: utils.Int2Str(msg.OrderStatus),
StatusTime: utils.Timestamp2Time(int64(msg.PushTime)),
Remark: msg.StatusDesc,
}
if msg.PushTime == 0 {
order.StatusTime = time.Now()
}
//获取实时订单信息
sfOrder, err := api.SfPsAPI.GetOrderStatus(msg.SFOrderID)
if err != nil {
return sfps2.Err2CallbackResponse(err)
}
var good *model.GoodsOrder
sql := `SELECT * FROM goods_order WHERE vendor_order_id = ? ORDER BY order_created_at DESC LIMIT 1 OFFSET 0`
sqlParams := []interface{}{msg.ShopOrderID}
dao.GetRow(dao.GetDB(), &good, sql, sqlParams)
order.OrderVendorID = good.VendorID
orderStatus := utils.Str2Int64(order.VendorStatus)
switch orderStatus {
case sfps2.OrderStatusNewOrder: //1订单创建
order.DesiredFee = jxutils.StandardPrice2Int(sfOrder.TotalPrice)
order.Status = model.WaybillStatusNew //5 带调度
case sfps2.OrderStatusTakeOrder: //10配送员接单
order.DesiredFee = jxutils.StandardPrice2Int(sfOrder.TotalPrice)
order.Status = model.WaybillStatusCourierAssigned //12
order.Remark = order.CourierName + "" + order.CourierMobile
case sfps2.OrderStatusArrivedStore:
order.DesiredFee = jxutils.StandardPrice2Int(sfOrder.TotalPrice)
order.Status = model.WaybillStatusCourierArrived
case sfps2.OrderStatusRiderArriving:
order.DesiredFee = jxutils.StandardPrice2Int(sfOrder.TotalPrice)
order.Status = model.WaybillStatusDelivering
case sfps2.OrderStatusFinished:
order.DesiredFee = jxutils.StandardPrice2Int(sfOrder.TotalPrice)
order.Status = model.WaybillStatusDelivered
case sfps2.OrderStatusOrderCancel:
order.Status = model.WaybillStatusCanceled
case sfps2.OrderStatusError:
order.Status = model.WaybillStatusDeliverFailed // 22
default:
globals.SugarLogger.Warnf("onWaybillMsg unknown msg:%v", msg)
}
if err := partner.CurOrderManager.OnWaybillStatusChanged(order); err != nil {
return sfps2.Err2CallbackResponse(err)
}
if order.OrderVendorID == model.VendorIDDD {
result := &mtpsapi.RiderInfo{
OrderId: order.VendorOrderID,
ThirdCarrierOrderId: order.VendorOrderID,
CourierName: order.CourierName,
CourierPhone: order.CourierMobile,
LogisticsProviderCode: "10002",
LogisticsStatus: order.Status,
OpCode: "",
}
switch orderStatus {
case sfps2.OrderStatusNewOrder:
result.LogisticsStatus = model.WaybillStatusNew
result.LogisticsContext = model.RiderWaitRider
case sfps2.OrderStatusTakeOrder:
result.LogisticsStatus = model.WaybillStatusCourierAssigned // 分配骑手
result.LogisticsContext = model.RiderWaitGetGoods
case sfps2.OrderStatusRiderArriving:
result.LogisticsStatus = model.WaybillStatusDelivering
result.LogisticsContext = model.RiderGetOrderDelivering
case sfps2.OrderStatusFinished:
result.LogisticsStatus = model.WaybillStatusDelivered
result.LogisticsContext = model.RiderGetOrderDelivered
case sfps2.OrderStatusOrderCancel:
result.LogisticsStatus = model.WaybillStatusCanceled
result.LogisticsContext = model.RiderGetOrderCanceled
case sfps2.OrderStatusError:
result.LogisticsStatus = model.WaybillStatusDeliverFailed
result.LogisticsContext = model.RiderGetOrderDeliverFailed
case sfps2.OrderStatusArrivedStore:
result.LogisticsStatus = model.WaybillStatusCourierArrived
result.LogisticsContext = model.RiderToStore
default:
result.LogisticsStatus = 0
result.LogisticsContext = model.RiderGetOrderDeliverOther
}
delivery.PullTiktokRiderInfo(result)
}
defer delivery.GetOrderRiderInfoToPlatform(order.VendorOrderID, order.Status) // 骑手位置更新
return sfps2.Err2CallbackResponse(nil)
}
// OnWaybillExceptSF 异常报备
func OnWaybillExceptSF(msg *sfps2.RiderException) (retVal *sfps2.CallbackResponse) {
jxutils.CallMsgHandler(func() {
order := &model.Waybill{
VendorWaybillID: msg.SFOrderID,
VendorWaybillID2: utils.Int2Str(msg.ExID),
WaybillVendorID: model.VendorIDSFPS,
CourierName: msg.OperatorName,
CourierMobile: "",
Status: model.WaybillStatusUnknown, // todo 这里要再确定一下是否只要收到订单异常消息就只简单当成一个消息
VendorStatus: utils.Int2Str(msg.OrderStatus),
StatusTime: utils.Timestamp2Time(int64(msg.PushTime)),
}
order.VendorOrderID, order.OrderVendorID = jxutils.SplitUniversalOrderID(msg.ShopOrderID)
retVal = sfps2.Err2CallbackResponse(partner.CurOrderManager.OnWaybillStatusChanged(order))
}, jxutils.ComposeUniversalOrderID(msg.ShopOrderID, model.VendorIDSFPS))
return retVal
}
// GetVendorSource 辅助函数
//获取订单来源标识符
func GetVendorSource(vendorID int) (source string) {
switch vendorID {
case model.VendorIDMTWM:
source = sfps2.OrderSourceMt
case model.VendorIDELM:
source = sfps2.OrderSourceELM
case model.VendorIDEBAI:
source = sfps2.OrderSourceEBAI
case model.VendorIDDD:
source = "抖音"
case model.VendorIDJD:
source = "京东"
case model.VendorIDJX:
source = "京西"
default:
source = "其他"
}
return source
}
func getReallyStoreID(storeID, jxStoreID int) int {
if storeID == 0 && jxStoreID == 0 {
return 0
}
if storeID == 0 {
return jxStoreID
} else {
return storeID
}
}

View File

@@ -320,11 +320,8 @@ func OnWaybillMsg(req *uuptapi.WaybillCallbackParam) (resp *uuptapi.CallbackResp
case uuptapi.StateArrivedStore:
param.Status = model.WaybillStatusCourierArrived
param.DesiredFee = reallyPrice
case uuptapi.StatePickUp:
param.Status = model.WaybillStatusUuPickUp
param.DesiredFee = reallyPrice
case uuptapi.StateArrivedDestination:
param.Status = model.WaybillStatusUuArrivedDestination
case uuptapi.StatePickUp, uuptapi.StateArrivedDestination:
param.Status = model.WaybillStatusDelivering
param.DesiredFee = reallyPrice
case uuptapi.StateReceiverGetGoods:
param.Status = model.WaybillStatusDelivered
@@ -358,12 +355,9 @@ func OnWaybillMsg(req *uuptapi.WaybillCallbackParam) (resp *uuptapi.CallbackResp
case uuptapi.StateArrivedStore: //骑手到店
result.LogisticsStatus = model.WaybillStatusCourierArrived
result.LogisticsContext = model.RiderToStore
case uuptapi.StatePickUp: //已取件
result.LogisticsStatus = model.WaybillStatusUuPickUp
case uuptapi.StatePickUp, uuptapi.StateArrivedDestination: //已取件
result.LogisticsStatus = model.WaybillStatusDelivering
result.LogisticsContext = model.RiderPickUp
case uuptapi.StateArrivedDestination: //到达取件人地址处
result.LogisticsStatus = model.WaybillStatusUuArrivedDestination
result.LogisticsContext = model.RiderArrivedDestination
case uuptapi.StateReceiverGetGoods: //取件人收货
result.LogisticsStatus = model.WaybillStatusDelivered
result.LogisticsContext = model.RiderGetOrderDelivered