diff --git a/CoreCms.Net.IServices/Order/ICoreCmsOrderServices.cs b/CoreCms.Net.IServices/Order/ICoreCmsOrderServices.cs index 5c7cec56..b4f65f82 100644 --- a/CoreCms.Net.IServices/Order/ICoreCmsOrderServices.cs +++ b/CoreCms.Net.IServices/Order/ICoreCmsOrderServices.cs @@ -163,6 +163,13 @@ namespace CoreCms.Net.IServices /// Task CancelOrder(string[] ids, int userId = 0); + /// + /// 取消订单并退款 + /// + /// + /// + Task CancelOrderAndRefund(string orderId); + /// /// 后端根据订单状态生成不同的操作按钮 diff --git a/CoreCms.Net.Services/Order/CoreCmsOrderServices.cs b/CoreCms.Net.Services/Order/CoreCmsOrderServices.cs index 9a63a887..269959a1 100644 --- a/CoreCms.Net.Services/Order/CoreCmsOrderServices.cs +++ b/CoreCms.Net.Services/Order/CoreCmsOrderServices.cs @@ -31,13 +31,17 @@ using CoreCms.Net.Model.ViewModels.UI; using CoreCms.Net.Utility.Extensions; using CoreCms.Net.Utility.Helper; using CoreCms.Net.WeChat.Service.HttpClients; +using EnumsNET; using Microsoft.AspNetCore.Http; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using Org.BouncyCastle.Crypto; using SKIT.FlurlHttpClient.Wechat.Api; using SKIT.FlurlHttpClient.Wechat.Api.Models; using SqlSugar; using Yitter.IdGenerator; +using static CoreCms.Net.Configuration.GlobalEnumVars; +using static SKIT.FlurlHttpClient.Wechat.Api.Models.ChannelsECAftersaleGetAftersaleOrderResponse.Types.AftersaleOrder.Types; namespace CoreCms.Net.Services @@ -62,6 +66,7 @@ namespace CoreCms.Net.Services private readonly ICoreCmsLogisticsServices _logisticsServices; private readonly ICoreCmsInvoiceServices _invoiceServices; private readonly ICoreCmsBillAftersalesServices _billAftersalesServices; + private readonly ICoreCmsBillAftersalesItemServices _billAftersalesItemServices; private readonly ICoreCmsOrderItemServices _orderItemServices; private readonly ICoreCmsInvoiceRecordServices _invoiceRecordServices; private readonly ICoreCmsOrderLogServices _orderLogServices; @@ -107,7 +112,7 @@ namespace CoreCms.Net.Services , ICoreCmsPaymentsServices paymentsServices , ICoreCmsBillRefundServices billRefundServices , ICoreCmsBillLadingServices billLadingServices - , ICoreCmsBillReshipServices billReshipServices, ICoreCmsMessageCenterServices messageCenterServices, ICoreCmsGoodsCommentServices goodsCommentServices, ISysTaskLogServices taskLogServices, ICoreCmsPromotionRecordServices promotionRecordServices, IRedisOperationRepository redisOperationRepository, ICoreCmsUserWeChatInfoServices userWeChatInfoServices, IWeChatApiHttpClientFactory weChatApiHttpClientFactory, IUnitOfWork unitOfWork) + , ICoreCmsBillReshipServices billReshipServices, ICoreCmsMessageCenterServices messageCenterServices, ICoreCmsGoodsCommentServices goodsCommentServices, ISysTaskLogServices taskLogServices, ICoreCmsPromotionRecordServices promotionRecordServices, IRedisOperationRepository redisOperationRepository, ICoreCmsUserWeChatInfoServices userWeChatInfoServices, IWeChatApiHttpClientFactory weChatApiHttpClientFactory, IUnitOfWork unitOfWork, ICoreCmsBillAftersalesItemServices billAftersalesItemServices) { this._dal = dal; base.BaseDal = dal; @@ -144,6 +149,7 @@ namespace CoreCms.Net.Services _userWeChatInfoServices = userWeChatInfoServices; _weChatApiHttpClientFactory = weChatApiHttpClientFactory; _unitOfWork = unitOfWork; + _billAftersalesItemServices = billAftersalesItemServices; } #region 查询团购秒杀下单数量(获取货品的秒杀团购数据) @@ -1638,6 +1644,150 @@ namespace CoreCms.Net.Services } #endregion + /// + /// 取消订单并退款 + /// + /// + /// + public async Task CancelOrderAndRefund(string orderId) + { + var jm = new WebApiCallBack(); + //获取订单并确认是否属于已支付并未发货的订单 + var where = PredicateBuilder.True(); + where = where.And(p => p.orderId == orderId); + where = where.And(p => p.payStatus == (int)GlobalEnumVars.OrderPayStatus.Yes); + where = where.And(p => p.status == (int)GlobalEnumVars.OrderStatus.Normal); + where = where.And(p => p.shipStatus == (int)GlobalEnumVars.OrderShipStatus.No); + + var orderInfo = await _dal.QueryByClauseAsync(where); + if (orderInfo == null) + { + jm.status = false; + jm.msg = "不满足条件,必须是已支付未发货订单。"; + return jm; + } + + //判断是否存在售后单据。 + var haveAs = await _billAftersalesServices.ExistsAsync(p => p.orderId == orderId && p.userId == orderInfo.userId); + if (haveAs) + { + jm.msg = "存在售后单,暂不支持直接取消。"; + jm.status = false; + return jm; + } + + orderInfo.items = await _orderItemServices.QueryListByClauseAsync(p => p.orderId == orderInfo.orderId); + AfterSalesVal(orderInfo, 0); + + if (orderInfo.addAftersalesStatus == false) + { + jm.msg = GlobalErrorCodeVars.Code13200; + jm.code = 13200; + return jm; + } + + //构建售后单 + //生成售后单号 + var afterSalesId = CommonHelper.GetSerialNumberType((int)GlobalEnumVars.SerialNumberType.售后单编号); + + var billAftersales = new CoreCmsBillAftersales(); + billAftersales.aftersalesId = afterSalesId; + billAftersales.orderId = orderId; + billAftersales.userId = orderInfo.userId; + billAftersales.type = 1; + billAftersales.refundAmount = orderInfo.payedAmount; + billAftersales.reason = "后台主动发起取消订单,并走售后流程生成退款单。"; + billAftersales.status = (int)GlobalEnumVars.BillAftersalesStatus.Success; + billAftersales.createTime = DateTime.Now; + //保存主表数据 + await _billAftersalesServices.InsertAsync(billAftersales); + //保存子项目 + var aftersalesItemData = orderInfo.items.Select(orderItem => new CoreCmsBillAftersalesItem + { + aftersalesId = afterSalesId, + orderItemsId = orderItem.id, + goodsId = orderItem.goodsId, + productId = orderItem.productId, + sn = orderItem.sn, + bn = orderItem.bn, + name = orderItem.name, + imageUrl = orderItem.imageUrl, + nums = orderItem.nums, + addon = orderItem.addon, + createTime = DateTime.Now + }) + .ToList(); + await _billAftersalesItemServices.InsertAsync(aftersalesItemData); + //构建退款单 + if (billAftersales.refundAmount > 0) + { + var billRefund = new CoreCmsBillRefund(); + billRefund.refundId = CommonHelper.GetSerialNumberType((int)GlobalEnumVars.SerialNumberType.退款单编号); + billRefund.aftersalesId = afterSalesId; + billRefund.money = billAftersales.refundAmount; + billRefund.userId = billAftersales.userId; + billRefund.sourceId = billAftersales.orderId; + billRefund.type = orderInfo.orderType; + + //取支付成功的支付单号 + var paymentsInfo = await _billPaymentsServices.QueryByClauseAsync(p => p.sourceId == billRefund.sourceId && p.type == orderInfo.orderType && p.status == (int)GlobalEnumVars.BillPaymentsStatus.Payed); + if (paymentsInfo != null) + { + billRefund.paymentCode = paymentsInfo.paymentCode; + billRefund.tradeNo = paymentsInfo.tradeNo; + } + billRefund.status = (int)GlobalEnumVars.BillRefundStatus.STATUS_NOREFUND; + billRefund.createTime = DateTime.Now; + + await _billRefundServices.InsertAsync(billRefund); + } + + //构建订单记录 + //订单记录 + var orderLog = new CoreCmsOrderLog + { + orderId = orderInfo.orderId, + userId = orderInfo.userId, + type = (int)GlobalEnumVars.OrderLogTypes.LOG_TYPE_CANCEL, + msg = "后端操作取消订单并退款", + data = JsonConvert.SerializeObject(orderInfo), + createTime = DateTime.Now + }; + await _orderLogServices.InsertAsync(orderLog); + + //如果有积分消费退还 + if (orderInfo.point > 0) + { + await _userPointLogServices.SetPoint(orderInfo.userId, orderInfo.point, (int)GlobalEnumVars.UserPointSourceTypes.PointCanCelOrder, "后端取消订单:" + orderInfo.orderId + "返还积分"); + } + + //优惠券返还 + if (!string.IsNullOrEmpty(orderInfo.coupon)) + { + await _couponServices.CancelReturnCoupon(orderInfo.coupon); + } + + //状态修改 + await _dal.UpdateAsync( + p => new CoreCmsOrder() + { + payStatus = (int)GlobalEnumVars.OrderPayStatus.Refunded, + status = (int)GlobalEnumVars.OrderStatus.Cancel, + updateTime = DateTime.Now + }, p => p.orderId == orderId); + + var orderItems = await _orderItemServices.QueryListByClauseAsync(p => p.orderId == orderId); + //更改库存 + foreach (var item in orderItems) + { + _goodsServices.ChangeStock(item.productId, GlobalEnumVars.OrderChangeStockType.cancel.ToString(), item.nums); + } + + jm.msg = "订单取消成功请前往退款单退款。"; + return jm; + } + + #region 后端根据订单状态生成不同的操作按钮 /// @@ -1669,7 +1819,10 @@ namespace CoreCms.Net.Services { html.Append("编辑
"); html.Append("发货
"); - + if (shipStatus == (int)GlobalEnumVars.OrderShipStatus.No) + { + html.Append("取消并退款
"); + } if (receiptType == (int)GlobalEnumVars.OrderReceiptType.IntraCityService || receiptType == (int)GlobalEnumVars.OrderReceiptType.SelfDelivery) { html.Append("秒发
"); diff --git a/CoreCms.Net.Services/Pay/BalancePayServices.cs b/CoreCms.Net.Services/Pay/BalancePayServices.cs index 6f90f556..4477a750 100644 --- a/CoreCms.Net.Services/Pay/BalancePayServices.cs +++ b/CoreCms.Net.Services/Pay/BalancePayServices.cs @@ -108,7 +108,12 @@ namespace CoreCms.Net.Services var res = await _userBalanceServices.Change(paymentInfo.userId, (int)GlobalEnumVars.UserBalanceSourceTypes.Refund, refundInfo.money, paymentInfo.paymentId); - if (res.status == false) return jm; + if (res.status == false) + { + jm.msg = res.msg; + jm.status = false; + return jm; + } jm.status = true; jm.data = res; jm.msg = "退款成功"; diff --git a/CoreCms.Net.Web.Admin/wwwroot/views/order/orders/index.html b/CoreCms.Net.Web.Admin/wwwroot/views/order/orders/index.html index 7a9b8251..df9a7543 100644 --- a/CoreCms.Net.Web.Admin/wwwroot/views/order/orders/index.html +++ b/CoreCms.Net.Web.Admin/wwwroot/views/order/orders/index.html @@ -525,6 +525,11 @@ var id = $(this).attr('data-deliveryId'); refreshDelivery(id); }, + //取消订单并退款 + cancelOrderAndRefund: function () { + var id = $(this).attr('data-id'); + doCancelOrderAndRefund(id); + }, }); //头工具栏事件 @@ -1212,6 +1217,21 @@ }); } + //取消订单并退款 + function doCancelOrderAndRefund(id) { + layer.confirm('确认取消订单号:' + id + ' 的订单吗?', { + title: '提示', btn: ['确认', '取消'] //按钮 + }, function () { + coreHelper.Post("Api/CoreCmsOrder/CancelOrderAndRefund", { id: id }, function (e) { + layer.msg(e.msg, { time: 1300 }, function () { + layui.table.reloadData('LAY-app-CoreCmsOrder-tableBox'); //重载表格 + doreLoadOrderCount(); + }); + }); + }); + return false; + } + //完成订单 function doCompleteOrder(id) { coreHelper.Post("Api/CoreCmsOrder/GetDoHaveAfterSale", { id: id }, function (e) {