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), } 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 { err = partner.CurOrderManager.OnAfsOrderStatusChanged(orderStatus) } 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: 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 } return orderStatus } func (c *PurchaseHandler) GetAfsStatusFromVendorStatus(resType int, notifyType string) int { 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 }