using System; using System.Linq; using System.Threading.Tasks; using CoreCms.Net.Configuration; using CoreCms.Net.IServices; using CoreCms.Net.Loging; using CoreCms.Net.Model.Entities; using CoreCms.Net.Utility.Extensions; using CoreCms.Net.Utility.Helper; using InitQ.Abstractions; using InitQ.Attributes; using Microsoft.Extensions.DependencyInjection; using SqlSugar; namespace CoreCms.Net.RedisMQ { /// /// 售后审核通过后对积分的返还处理 /// public class AfterSalesReviewForPointSubscribe : IRedisSubscribe { private readonly IServiceProvider _serviceProvider; public AfterSalesReviewForPointSubscribe(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } /// /// 售后审核通过后对积分的返还处理 /// /// /// [Subscribe(RedisMessageQueueKey.AfterSalesReviewForPoint)] private async Task AfterSalesReviewForPointSubscribeCommand(string msg) { try { if (string.IsNullOrEmpty(msg)) { NLogUtil.WriteAll(NLog.LogLevel.Error, LogType.RedisMessageQueue, "售后审核通过后积分处理", "审核单编号获取失败"); return; } //使用服务驱动器取服务,防止autofac出现循环注入 using var container = _serviceProvider.CreateScope(); var _aftersalesServices = container.ServiceProvider.GetService(); var _orderServices = container.ServiceProvider.GetService(); var _orderItemServices = container.ServiceProvider.GetService(); var _aftersalesItemServices = container.ServiceProvider.GetService(); var _productsServices = container.ServiceProvider.GetService(); var _settingServices = container.ServiceProvider.GetService(); var _userServices = container.ServiceProvider.GetService(); var _userPointLogServices = container.ServiceProvider.GetService(); var info = await _aftersalesServices.QueryByClauseAsync(p => p.aftersalesId == msg, true); if (info != null) { var order = await _orderServices.QueryByClauseAsync(p => p.orderId == info.orderId, true); if (order == null) { NLogUtil.WriteAll(NLog.LogLevel.Error, LogType.RedisMessageQueue, "售后审核通过后积分处理", "订单数据获取失败"); return; } if (order.point == 0) { NLogUtil.WriteAll(NLog.LogLevel.Info, LogType.RedisMessageQueue, "售后审核通过后积分处理", "未使用积分无需处理"); return; } var userModel = await _userServices.QueryByClauseAsync(p => p.id == order.userId, true); if (userModel == null) { NLogUtil.WriteAll(NLog.LogLevel.Info, LogType.RedisMessageQueue, "售后审核通过后积分处理", "用户信息获取失败"); return; } //获取售后明细 var aftersalesItems = await _aftersalesItemServices.QueryListByClauseAsync(p => p.aftersalesId == info.aftersalesId, p => p.id, OrderByType.Asc, true); if (aftersalesItems == null) { NLogUtil.WriteAll(NLog.LogLevel.Info, LogType.RedisMessageQueue, "售后审核通过后积分处理", "售后明细获取失败"); return; } //获取售后货品信息 var productIds = aftersalesItems.Select(p => p.productId).ToList(); var orderItem = await _orderItemServices.QueryListByClauseAsync(p => p.orderId == order.orderId, p => p.id, OrderByType.Asc, true); var products = await _productsServices.QueryListByClauseAsync(p => productIds.Contains(p.id), p => p.id, OrderByType.Asc, true); var allConfigs = await _settingServices.GetConfigDictionaries(); var pointExchangeModel = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.PointExchangeModel).ObjectToInt(); //积分模式 1全局2单品 var pointDiscountedProportion = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.PointDiscountedProportion).ObjectToInt(); //多少积分等于1元钱。 //var pointDiscounted = Math.Round(pointDiscountedProportion / 100, 4); //var ordersPointProportion = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.OrdersPointProportion).ObjectToInt(); //积分使用比例 全局模式下一个订单最多可以使用多少比例的积分 decimal point = 0; foreach (var p in aftersalesItems) { var orderProduct = orderItem.Find(x => x.productId == p.productId); if (orderProduct == null) { continue; }; var product = products.Find(x => x.id == p.productId); if (product == null) { continue; }; //如果是全局模式(根据比例来退还积分) if (pointExchangeModel == 1) { //可能存在就是根本不是全积分抵扣,而是订单实际在不够积分的情况下,抵扣了多少金额。那么统一就根据订单的比例来计算,更加精准,(这里的总金额是实际支付金额,去掉了优惠) //如果订单实际支付金额是0的话,那就是全积分。 var practicalProportion = order.orderAmount <= 0 ? 1 : Math.Round(order.pointMoney / order.goodsAmount, 4); //未发货的商品库存调整,如果订单未发货或者部分发货,并且用户未收到商品的情况下 if (order.shipStatus is (int)GlobalEnumVars.OrderShipStatus.No or (int)GlobalEnumVars.OrderShipStatus.PartialYes && info.type == (int)GlobalEnumVars.BillAftersalesIsReceive.Refund && p.nums == 0) { point += orderProduct.price * practicalProportion * orderProduct.nums * pointDiscountedProportion; } else { //获取货品金额*积分使用比例*数量*积分折现比例=积分抵扣的金额应该可以兑换的积分。 point += orderProduct.price * practicalProportion * p.nums * pointDiscountedProportion; } } //如果是单品模式 else if (pointExchangeModel == 2) { //未发货的商品库存调整,如果订单未发货或者部分发货,并且用户未收到商品的情况下 if (order.shipStatus is (int)GlobalEnumVars.OrderShipStatus.No or (int)GlobalEnumVars.OrderShipStatus.PartialYes && info.type == (int)GlobalEnumVars.BillAftersalesIsReceive.Refund && p.nums == 0) { point += product.pointsDeduction * orderProduct.nums * pointDiscountedProportion; } else { //单品模式只能是全积分抵扣或者全金额支付。所以直接按照扣掉的金额还原积分即可。 point += product.pointsDeduction * p.nums * pointDiscountedProportion; } } } //为了计算比例情况下,增加精度,全局模式下用了4位小数。这里四色五入积分差异控制小点。 var practicalPoint = Convert.ToInt32(point); var newPoint = practicalPoint + userModel.point; var pointLog = new CoreCmsUserPointLog { userId = userModel.id, type = (int)GlobalEnumVars.UserPointSourceTypes.PointRefundReturn, num = practicalPoint, balance = newPoint, remarks = "售后单:" + info.aftersalesId + "退还积分", createTime = DateTime.Now }; var id = await _userPointLogServices.InsertAsync(pointLog); if (id > 0) { await _userServices.UpdateAsync(p => new CoreCmsUser() { point = p.point + practicalPoint }, p => p.id == userModel.id); } NLogUtil.WriteAll(NLog.LogLevel.Info, LogType.RedisMessageQueue, "售后审核通过后积分处理", msg); } else { NLogUtil.WriteAll(NLog.LogLevel.Info, LogType.RedisMessageQueue, "售后审核通过后积分处理", "售后单查询失败"); } } catch (Exception ex) { NLogUtil.WriteAll(NLog.LogLevel.Error, LogType.RedisMessageQueue, "售后审核通过后积分处理", msg, ex); throw; } await Task.CompletedTask; } } }