mirror of
http://git.coreshop.cn/jianweie/coreshoppro.git
synced 2025-12-06 20:13:26 +08:00
【新增】增加售后审核通过后,积分返还机制的队列实现,取消原有积分统一返还机制。
This commit is contained in:
@@ -380,6 +380,11 @@ namespace CoreCms.Net.Configuration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public const string AfterSalesReview = "AfterSalesReview";
|
public const string AfterSalesReview = "AfterSalesReview";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 售后审核通过后积分处理
|
||||||
|
/// </summary>
|
||||||
|
public const string AfterSalesReviewForPoint = "AfterSalesReviewForPoint";
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 日志队列
|
/// 日志队列
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ namespace CoreCms.Net.Core.Config
|
|||||||
m.ConnectionString = AppSettingsConstVars.RedisConfigConnectionString;
|
m.ConnectionString = AppSettingsConstVars.RedisConfigConnectionString;
|
||||||
//对应的订阅者类,需要new一个实例对象,当然你也可以传参,比如日志对象
|
//对应的订阅者类,需要new一个实例对象,当然你也可以传参,比如日志对象
|
||||||
m.ListSubscribe = new List<Type>() {
|
m.ListSubscribe = new List<Type>() {
|
||||||
typeof(DemoSubscribe),
|
|
||||||
typeof(OrderAgentOrDistributionSubscribe),
|
typeof(OrderAgentOrDistributionSubscribe),
|
||||||
typeof(OrderAutomaticDeliverySubscribe),
|
typeof(OrderAutomaticDeliverySubscribe),
|
||||||
typeof(OrderFinishCommandSubscribe),
|
typeof(OrderFinishCommandSubscribe),
|
||||||
@@ -45,6 +44,7 @@ namespace CoreCms.Net.Core.Config
|
|||||||
typeof(WeChatPayNoticeSubscribe),
|
typeof(WeChatPayNoticeSubscribe),
|
||||||
typeof(SendWxTemplateMessageSubscribe),
|
typeof(SendWxTemplateMessageSubscribe),
|
||||||
typeof(AfterSalesReviewSubscribe),
|
typeof(AfterSalesReviewSubscribe),
|
||||||
|
typeof(AfterSalesReviewForPointSubscribe),
|
||||||
};
|
};
|
||||||
//显示日志
|
//显示日志
|
||||||
m.ShowLog = false;
|
m.ShowLog = false;
|
||||||
|
|||||||
@@ -0,0 +1,153 @@
|
|||||||
|
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.Subscribe
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 售后审核通过后对积分的返还处理
|
||||||
|
/// </summary>
|
||||||
|
public class AfterSalesReviewForPointSubscribe : IRedisSubscribe
|
||||||
|
{
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
|
||||||
|
public AfterSalesReviewForPointSubscribe(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 售后审核通过后对积分的返还处理
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="msg"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[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<ICoreCmsBillAftersalesServices>();
|
||||||
|
var _orderServices = container.ServiceProvider.GetService<ICoreCmsOrderServices>();
|
||||||
|
var _aftersalesItemServices = container.ServiceProvider.GetService<ICoreCmsBillAftersalesItemServices>();
|
||||||
|
var _productsServices = container.ServiceProvider.GetService<ICoreCmsProductsServices>();
|
||||||
|
var _settingServices = container.ServiceProvider.GetService<ICoreCmsSettingServices>();
|
||||||
|
var _userServices = container.ServiceProvider.GetService<ICoreCmsUserServices>();
|
||||||
|
var _userPointLogServices = container.ServiceProvider.GetService<ICoreCmsUserPointLogServices>();
|
||||||
|
|
||||||
|
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 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 ordersPointProportion = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.OrdersPointProportion).ObjectToInt(); //积分使用比例 全局模式下一个订单最多可以使用多少比例的积分
|
||||||
|
decimal point = 0;
|
||||||
|
foreach (var p in aftersalesItems)
|
||||||
|
{
|
||||||
|
var aftersalesProduct = products.Find(x => x.id == p.productId);
|
||||||
|
if (aftersalesProduct == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
//如果是全局模式(根据比例来退还积分)
|
||||||
|
if (pointExchangeModel == 1)
|
||||||
|
{
|
||||||
|
//可能存在就是根本不是全积分抵扣,而是订单实际在不够积分的情况下,抵扣了多少金额。那么统一就根据订单的比例来计算,更加精准,(这里的总金额是实际支付金额,去掉了优惠)
|
||||||
|
var practicalProportion = Math.Round(order.pointMoney / order.orderAmount, 4);
|
||||||
|
|
||||||
|
//获取货品金额*积分使用比例*数量*积分折现比例=积分抵扣的金额应该可以兑换的积分。
|
||||||
|
point += aftersalesProduct.price * practicalProportion * p.nums * pointDiscountedProportion;
|
||||||
|
}
|
||||||
|
//如果是单品模式
|
||||||
|
else if (pointDiscountedProportion == 2)
|
||||||
|
{
|
||||||
|
//单品模式只能是全积分抵扣或者全金额支付。所以直接按照扣掉的金额还原积分即可。
|
||||||
|
point += aftersalesProduct.pointsDeduction * p.nums * pointDiscountedProportion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//为了计算比例情况下,增加精度,全局模式下用了4位小数。这里四色五入积分差异控制小点。
|
||||||
|
var practicalPoint = Convert.ToInt32(point);
|
||||||
|
|
||||||
|
var newPoint = practicalPoint + userModel.point;
|
||||||
|
|
||||||
|
var pointLog = new CoreCmsUserPointLog();
|
||||||
|
pointLog.userId = userModel.id;
|
||||||
|
pointLog.type = (int)GlobalEnumVars.UserPointSourceTypes.PointRefundReturn;
|
||||||
|
pointLog.num = practicalPoint;
|
||||||
|
pointLog.balance = newPoint;
|
||||||
|
pointLog.remarks = "售后单:" + info.aftersalesId + "退还积分";
|
||||||
|
pointLog.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -144,6 +144,7 @@ namespace CoreCms.Net.Services
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 统计用户的售后数量============================================
|
#region 统计用户的售后数量============================================
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 统计用户的售后数量
|
/// 统计用户的售后数量
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -376,10 +377,19 @@ namespace CoreCms.Net.Services
|
|||||||
{
|
{
|
||||||
if (type == (int)GlobalEnumVars.BillAftersalesIsReceive.Refund)
|
if (type == (int)GlobalEnumVars.BillAftersalesIsReceive.Refund)
|
||||||
{
|
{
|
||||||
var n = orderItem.nums - orderItem.sendNums - (orderItem.reshipNums - orderItem.reshipedNums);
|
//售后中未退换的数量(申请售后退还的,已经收到退还的,差额就是客户还需要退还的)
|
||||||
if (n < nums)
|
var reshipNum = orderItem.reshipNums - orderItem.reshipedNums;
|
||||||
|
|
||||||
|
//如果未发货,但申请售后大于0
|
||||||
|
if (orderItem.sendNums == 0 && nums > 0)
|
||||||
{
|
{
|
||||||
jm.msg = orderItem.name + orderItem.addon + ",未发货商品,最多能退" + n + "个";
|
jm.msg = orderItem.name + orderItem.addon + ",未发货商品,退货数量只能为0个";
|
||||||
|
return jm;
|
||||||
|
}
|
||||||
|
//如果当前售后数量+未寄送的售后数量 > 已经发货数量
|
||||||
|
if (reshipNum + nums > orderItem.sendNums)
|
||||||
|
{
|
||||||
|
jm.msg = orderItem.name + orderItem.addon + ",售后申请超过数量,最多能退" + (orderItem.sendNums - reshipNum - nums) + "个";
|
||||||
return jm;
|
return jm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -625,17 +635,16 @@ namespace CoreCms.Net.Services
|
|||||||
orderInfo.payStatus = (int)GlobalEnumVars.OrderPayStatus.Refunded;
|
orderInfo.payStatus = (int)GlobalEnumVars.OrderPayStatus.Refunded;
|
||||||
orderInfo.status = (int)GlobalEnumVars.OrderStatus.Complete;
|
orderInfo.status = (int)GlobalEnumVars.OrderStatus.Complete;
|
||||||
|
|
||||||
//返还积分
|
//返还积分(此模式会导致多次售后刷积分情况)
|
||||||
if (orderInfo.point > 0)
|
//if (orderInfo.point > 0)
|
||||||
{
|
//{
|
||||||
await _userPointLogServices.SetPoint(orderInfo.userId, orderInfo.point, (int)GlobalEnumVars.UserPointSourceTypes.PointRefundReturn, "售后退款:" + orderInfo.orderId + "返还积分");
|
// await _userPointLogServices.SetPoint(orderInfo.userId, orderInfo.point, (int)GlobalEnumVars.UserPointSourceTypes.PointRefundReturn, "售后退款:" + orderInfo.orderId + "返还积分");
|
||||||
}
|
//}
|
||||||
//返还优惠券
|
//返还优惠券
|
||||||
if (!string.IsNullOrEmpty(orderInfo.coupon))
|
if (!string.IsNullOrEmpty(orderInfo.coupon))
|
||||||
{
|
{
|
||||||
await couponServices.CancelReturnCoupon(orderInfo.coupon);
|
await couponServices.CancelReturnCoupon(orderInfo.coupon);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -731,6 +740,8 @@ namespace CoreCms.Net.Services
|
|||||||
{
|
{
|
||||||
//售后审核通过后处理
|
//售后审核通过后处理
|
||||||
await _redisOperationRepository.ListLeftPushAsync(RedisMessageQueueKey.AfterSalesReview, aftersalesId);
|
await _redisOperationRepository.ListLeftPushAsync(RedisMessageQueueKey.AfterSalesReview, aftersalesId);
|
||||||
|
//售后审核通过后积分退还机制
|
||||||
|
await _redisOperationRepository.ListLeftPushAsync(RedisMessageQueueKey.AfterSalesReviewForPoint, aftersalesId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
"AppConfig": {
|
"AppConfig": {
|
||||||
"AppUrl": "https://admin.demo.coreshop.cn/", //后端管理地址
|
"AppUrl": "https://admin.demo.coreshop.cn/", //后端管理地址
|
||||||
"AppInterFaceUrl": "https://api.demo.coreshop.cn/", //接口请求地址
|
"AppInterFaceUrl": "https://api.demo.coreshop.cn/", //接口请求地址
|
||||||
"AppVersion": "CoreShopProfessional v0.5.4"
|
"AppVersion": "CoreShopProfessional v0.5.5"
|
||||||
},
|
},
|
||||||
//redis为必须启动项,请保持redis为正常可用
|
//redis为必须启动项,请保持redis为正常可用
|
||||||
"RedisConfig": {
|
"RedisConfig": {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ layui.define(['laytpl', 'layer', 'element', 'util'], function (exports) {
|
|||||||
, pageTabs: false //是否开启页面选项卡功能。单页版不推荐开启
|
, pageTabs: false //是否开启页面选项卡功能。单页版不推荐开启
|
||||||
|
|
||||||
, name: '核心商城系统'
|
, name: '核心商城系统'
|
||||||
, version: 'CoreShopProfessional v0.5.4'
|
, version: 'CoreShopProfessional v0.5.5'
|
||||||
, tableName: 'CoreCms' //本地存储表名
|
, tableName: 'CoreCms' //本地存储表名
|
||||||
, MOD_NAME: 'admin' //模块事件名
|
, MOD_NAME: 'admin' //模块事件名
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
"AppConfig": {
|
"AppConfig": {
|
||||||
"AppUrl": "https://admin.demo.coreshop.cn/", //后端管理地址
|
"AppUrl": "https://admin.demo.coreshop.cn/", //后端管理地址
|
||||||
"AppInterFaceUrl": "https://api.demo.coreshop.cn/", //接口请求地址
|
"AppInterFaceUrl": "https://api.demo.coreshop.cn/", //接口请求地址
|
||||||
"AppVersion": "CoreShopProfessional v0.5.4"
|
"AppVersion": "CoreShopProfessional v0.5.5"
|
||||||
},
|
},
|
||||||
//redis为必须启动项,请保持redis为正常可用
|
//redis为必须启动项,请保持redis为正常可用
|
||||||
"RedisConfig": {
|
"RedisConfig": {
|
||||||
|
|||||||
Reference in New Issue
Block a user