Files
jx-callback/business/partner/purchase/mtwm/order_afs.go
2023-09-26 11:14:12 +08:00

275 lines
12 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 mtwm
import (
"errors"
"fmt"
"git.rosy.net.cn/jx-callback/globals/api"
"net/url"
"strings"
"git.rosy.net.cn/baseapi/platformapi/mtwmapi"
"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/business/partner"
"git.rosy.net.cn/jx-callback/globals"
)
var (
// AfsVendorStatus2StatusMap = map[int]int{
// mtwmapi.ResTypePending: model.AfsOrderStatusWait4Approve,
// mtwmapi.ResTypeMerchantRefused: model.AfsOrderStatusFailed,
// mtwmapi.ResTypeMerchantAgreed: model.AfsOrderStatusFinished,
// mtwmapi.ResTypeCSRefused: model.AfsOrderStatusFailed,
// mtwmapi.ResTypeCSAgreed: model.AfsOrderStatusFinished,
// mtwmapi.ResTypeTimeoutAutoAgreed: model.AfsOrderStatusFinished,
// mtwmapi.ResTypeAutoAgreed: model.AfsOrderStatusFinished,
// mtwmapi.ResTypeUserCancelApply: model.AfsOrderStatusFailed,
// mtwmapi.ResTypeUserCancelComplain: model.AfsOrderStatusFailed,
// }
AfsVendorStatus2StatusMap = map[string]int{
mtwmapi.NotifyTypeApply: model.AfsOrderStatusWait4Approve,
mtwmapi.NotifyTypePartyApply: model.AfsOrderStatusWait4Approve,
mtwmapi.NotifyTypeSuccess: model.AfsOrderStatusFinished,
mtwmapi.NotifyTypeReject: model.AfsOrderStatusFailed,
mtwmapi.NotifyTypeCancelRefund: model.AfsOrderStatusFailed,
mtwmapi.NotifyTypeCancelRefundComplaint: model.AfsOrderStatusFailed,
}
)
func (c *PurchaseHandler) isAfsMsg(msg *mtwmapi.CallbackMsg) bool {
if msg.Cmd == mtwmapi.MsgTypeOrderRefund || msg.Cmd == mtwmapi.MsgTypeOrderPartialRefund {
// refundData := msg.Data.(*mtwmapi.CallbackRefundInfo)
orderID := utils.Str2Int64(GetOrderIDFromMsg(msg))
order, _ := partner.CurOrderManager.LoadOrder(utils.Int64ToStr(orderID), model.VendorIDMTWM)
if order != nil {
//status, err := getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromOrder(order), order.VendorStoreID).OrderViewStatus(orderID)
//if err == nil {
//return utils.Int2Str(status) == mtwmapi.OrderStatusFinished
return true //TODO 有的美团订单售前退款,也当做售后处理试试
//}
}
}
return false
}
func (c *PurchaseHandler) OnAfsOrderMsg(msg *mtwmapi.CallbackMsg) (retVal *mtwmapi.CallbackResponse) {
jxutils.CallMsgHandlerAsync(func() {
retVal = c.onAfsOrderMsg(msg)
}, jxutils.ComposeUniversalOrderID(GetOrderIDFromMsg(msg), model.VendorIDMTWM))
return retVal
}
// todo 对于退款与部分退款order.go与这个文件中对于状态的处理不一致
func (c *PurchaseHandler) onAfsOrderMsg(msg *mtwmapi.CallbackMsg) (retVal *mtwmapi.CallbackResponse) {
var err error
orderStatus := c.callbackAfsMsg2Status(msg)
needCallNew := orderStatus.Status == model.AfsOrderStatusWait4Approve || orderStatus.Status == model.AfsOrderStatusNew
if !needCallNew {
_, err := partner.CurOrderManager.LoadAfsOrder(orderStatus.VendorOrderID, orderStatus.VendorID)
if err != nil {
if dao.IsNoRowsError(err) {
needCallNew = true
} else {
return mtwmapi.Err2CallbackResponse(err, "")
}
}
}
if needCallNew {
var afsOrder *model.AfsOrder
refundData := msg.Data.(*mtwmapi.CallbackRefundInfo)
if msg.Cmd == mtwmapi.MsgTypeOrderPartialRefund {
afsOrder = &model.AfsOrder{
VendorID: model.VendorIDMTWM,
AfsOrderID: orderStatus.VendorOrderID,
VendorOrderID: orderStatus.RefVendorOrderID,
VendorStoreID: "",
StoreID: 0,
AfsCreatedAt: utils.Timestamp2Time(refundData.Timestamp),
VendorAppealType: "",
AppealType: model.AfsAppealTypeRefund,
VendorReasonType: "",
ReasonType: model.AfsReasonNotOthers,
ReasonDesc: utils.LimitUTF8StringLen(refundData.Reason, 1024),
ReasonImgList: utils.LimitUTF8StringLen(strings.Join(refundData.PictureList, ","), 1024),
RefundType: model.AfsTypePartRefund,
VendorOrgCode: msg.AppID,
// FreightUserMoney: afsInfo.OrderFreightMoney,
// AfsFreightMoney: afsInfo.AfsFreight,
// BoxMoney: afsInfo.PackagingMoney,
// TongchengFreightMoney: afsInfo.TongchengFreightMoney,
// SkuBoxMoney: afsInfo.MealBoxMoney,
}
for _, sku := range refundData.FoodList {
orderSku := &model.OrderSkuFinancial{
// VendorID: model.VendorIDMTWM,
AfsOrderID: afsOrder.AfsOrderID,
// VendorOrderID: afsOrder.VendorOrderID,
// VendorStoreID: afsOrder.VendorStoreID,
// StoreID: afsOrder.StoreID,
IsAfsOrder: 1,
Count: sku.Count,
// ConfirmTime: afsOrder.AfsCreateAt,
VendorSkuID: sku.SkuID,
SkuID: int(utils.Str2Int64WithDefault(sku.SkuID, 0)),
Name: sku.FoodName,
UserMoney: jxutils.StandardPrice2Int(sku.RefundPrice)*int64(sku.Count) + jxutils.StandardPrice2Int(sku.BoxPrice)*int64(sku.BoxNum),
}
if orderSku.VendorSkuID == "" || orderSku.VendorSkuID == "0" {
orderSku.VendorSkuID = sku.AppFoodCode
}
afsOrder.SkuUserMoney += orderSku.UserMoney
afsOrder.Skus = append(afsOrder.Skus, orderSku)
}
//afsOrder.PmSubsidyMoney += afsOrder.RefundMoney - afsOrder.SkuUserMoney
} else {
if afsOrder = c.createAfsOrder(msg.FormData); afsOrder != nil {
// if orderFinancial, err2 := partner.CurOrderManager.LoadOrderFinancial(orderStatus.RefVendorOrderID, model.VendorIDMTWM); err2 == nil {
// afsOrder = c.OrderFinancialDetail2Refund(orderFinancial, msg.FormData)
afsOrder.AfsOrderID = orderStatus.VendorOrderID
afsOrder.RefundType = model.AfsTypeFullRefund
afsOrder.AppealType = model.AfsAppealTypeRefund
afsOrder.VendorReasonType = ""
afsOrder.ReasonType = model.AfsReasonNotOthers
afsOrder.ReasonDesc = utils.LimitUTF8StringLen(refundData.Reason, 1024)
afsOrder.ReasonImgList = utils.LimitUTF8StringLen(strings.Join(refundData.PictureList, ","), 1024)
}
}
if afsOrder != nil {
//直接就来一个新的售后单,并且还是售后完成的
if orderStatus.Status == model.AfsOrderStatusFinished {
afsOrder.AfsFinishedAt = afsOrder.AfsCreatedAt
}
err = partner.CurOrderManager.OnAfsOrderNew(afsOrder, orderStatus)
}
} else {
if err := partner.CurOrderManager.OnAfsOrderStatusChanged(orderStatus); err == nil {
// 订单回调全额退款接口时,将订单状态修改为取消
refundData := msg.Data.(*mtwmapi.CallbackRefundInfo)
if refundData.NotifyType == mtwmapi.MsgTypeOrderAgree && msg.Cmd == mtwmapi.MsgTypeOrderRefund {
order, _ := partner.CurOrderManager.LoadOrder(orderStatus.RefVendorOrderID, model.VendorIDMTWM)
order.Status = model.OrderStatusCanceled
dao.UpdateEntity(dao.GetDB(), order, "Status")
}
// 新订单平台自动同意退单,某一些情况下产生的运单没退!这个处理一下!
if refundData.NotifyType == mtwmapi.MsgTypeOrderAgree && (msg.Cmd == mtwmapi.MsgTypeOrderRefund || msg.Cmd == mtwmapi.MsgTypeOrderAgree) {
wayBill, _ := dao.GetWaybills(dao.GetDB(), orderStatus.RefVendorOrderID, nil)
for _, v := range wayBill {
handlerInfo := partner.GetDeliveryPlatformFromVendorID(v.WaybillVendorID)
if handlerInfo != nil {
handlerInfo.Handler.CancelWaybill(v, 0, "订单转移被取消")
}
}
}
}
}
return mtwmapi.Err2CallbackResponse(err, "")
}
func (p *PurchaseHandler) createAfsOrder(orderData url.Values) (afsOrder *model.AfsOrder) {
afsOrder, err := partner.CurOrderManager.CreateAfsOrderFromOrder(orderData.Get("order_id"), model.VendorIDMTWM)
if err == nil {
afsOrder.AfsOrderID = orderData.Get("refund_id")
afsOrder.AfsCreatedAt = utils.Timestamp2Time(utils.Str2Int64(orderData.Get("timestamp")))
if afsOrder.AfsOrderID == "" {
afsOrder.AfsOrderID = afsOrder.VendorOrderID
}
} else {
afsOrder = nil
}
return afsOrder
}
func (c *PurchaseHandler) callbackAfsMsg2Status(msg *mtwmapi.CallbackMsg) (orderStatus *model.OrderStatus) {
refundData := msg.Data.(*mtwmapi.CallbackRefundInfo)
orderStatus = &model.OrderStatus{
VendorID: model.VendorIDMTWM,
OrderType: model.OrderTypeAfsOrder,
RefVendorOrderID: utils.Int64ToStr(refundData.OrderID),
RefVendorID: model.VendorIDMTWM,
VendorStatus: refundData.Status, // fmt.Sprintf("%s:%d", refundData.NotifyType, refundData.ResType),
Status: c.GetAfsStatusFromVendorStatus(refundData.ResType, refundData.NotifyType),
StatusTime: utils.Timestamp2Time(refundData.Timestamp),
Remark: refundData.Reason,
}
if refundData.RefundID > 0 {
orderStatus.VendorOrderID = utils.Int64ToStr(refundData.RefundID)
} else {
orderStatus.VendorOrderID = orderStatus.RefVendorOrderID
}
if refundData.NotifyType == "" && refundData.ResType == model.NO {
orderStatus.VendorStatus = "用户申请退货且退款"
}
// 1-已申请 10-初审已同意 11-初审已驳回 16-初审已申诉 17-初审申诉已同意 18-初审申诉已驳回 20-终审已发起(用户已发货) 21-终审已同意 22-终审已驳回 26-终审已申诉 27-终审申诉已同意 28-终审申诉已驳回 30-已取消
if refundData.Status == "21" {
orderStatus.Status = model.AfsOrderStatusFinished
orderStatus.VendorStatus += "," + refundData.Status
}
return orderStatus
}
func (c *PurchaseHandler) GetAfsStatusFromVendorStatus(resType int, notifyType string) int {
// 当resType为0且notifyType为空的时候,是退货退款,之前是未处理这个,现在退货退款默认成退款未处理
if notifyType == "" {
notifyType = mtwmapi.NotifyTypeApply
}
status := AfsVendorStatus2StatusMap[notifyType]
if status == model.AfsOrderStatusWait4Approve && resType != mtwmapi.ResTypePending {
status = model.AfsOrderStatusNew
}
return status
}
// 审核售后单申请
func (c *PurchaseHandler) AgreeOrRefuseRefund(ctx *jxcontext.Context, order *model.AfsOrder, approveType int, reason string) (err error) {
if globals.EnableMtwmStoreWrite {
if approveType == partner.AfsApproveTypeRefused {
err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromAfsOrder(order), order.VendorStoreID).OrderRefundReject(utils.Str2Int64(order.VendorOrderID), reason)
} else if approveType == partner.AfsApproveTypeRefusedToRefundMoney {
return errors.New("此平台暂时不支持")
} else {
err = getAPI(order.VendorOrgCode, jxutils.GetSaleStoreIDFromAfsOrder(order), order.VendorStoreID).OrderRefundAgree(utils.Str2Int64(order.VendorOrderID), reason)
}
}
return err
}
// 确认收到退货
func (c *PurchaseHandler) ConfirmReceivedReturnGoods(ctx *jxcontext.Context, order *model.AfsOrder) (err error) {
err = fmt.Errorf("内部错误,美团外卖平台不支持确认收到退货操作")
return err
}
// 发起全款退款
func (c *PurchaseHandler) RefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, reason string) (err error) {
return fmt.Errorf("%s不支持售后全额退款请让买家发起退款", model.VendorChineseNames[model.VendorIDMTWM])
}
// 发起部分退款
func (c *PurchaseHandler) PartRefundOrder(ctx *jxcontext.Context, order *model.GoodsOrder, refundSkuList []*model.OrderSku, reason string) (err error) {
return c.AdjustOrder(ctx, order, refundSkuList, reason)
}
func (c *PurchaseHandler) GetOrderAfsInfo(ctx *jxcontext.Context, vendorOrderID, afsOrderID string) (orderAfsInfo *partner.OrderAfsInfo, err error) {
orderAfsInfo = &partner.OrderAfsInfo{}
var afsTotalShopMoney int64
if list, err := api.MtwmAPI.GetOrderRefundDetail(utils.Str2Int64(vendorOrderID), 0); err == nil {
for _, v := range list {
if v.RefundPartialEstimateCharge.SettleAmount != "" {
afsTotalShopMoney += jxutils.StandardPrice2Int(utils.Str2Float64(v.RefundPartialEstimateCharge.SettleAmount))
}
}
}
if order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, model.VendorIDMTWM); err == nil {
orderAfsInfo.AfsTotalShopMoney = order.TotalShopMoney + afsTotalShopMoney
}
return orderAfsInfo, err
}