增加用户结算

This commit is contained in:
chfei committed 2026-09-19 17:44:06 +08:00
1 parent 4dbcd6542e
commit 69bfe9ff05
6 files changed
+273 -47

No files matched your search

+50 -45
View File
@@ -641,54 +641,59 @@ namespace KJD_Web.BLL.WXXD
if (flowDt != null && flowDt.Rows.Count > 0)
{
HashSet<string> deductedOrderSet = new HashSet<string>(); // type=23 已扣减的订单
HashSet<string> giftsOrderSet = new HashSet<string>(); // type=34 礼物已扣减的订单
List<long> settleIdLst = new List<long>(); // 参与结算的流水id
List<user_payment_record_info> flowList = new List<user_payment_record_info>();//流水记录
foreach (DataRow row in flowDt.Rows)
{
int type = row["type"].ParseToInt();
decimal amount = row["amount"].ParseToDecimal();
decimal oem_amount = row["oem_amount"].ParseToDecimal();
long flowId = row["id"].ParseToLong();
settleIdLst.Add(flowId);
decimal itemAmount = 0m;
if (type == 20)
itemAmount = amount - 2.2m;
else if (type == 26)
itemAmount = amount - 2.5m;
else if (type == 16)
itemAmount = oem_amount;
else if (type == 31)
itemAmount = oem_amount;
else if (type == 23)
var item = new user_payment_record_info
{
// 同一个订单只能减少一次
string orderId = row["order_id"].ParseToString();
if (orderId.IsNullOrEmpty() || deductedOrderSet.Contains(orderId))
continue;
deductedOrderSet.Add(orderId);
itemAmount = -(amount - 2.2m);
}
else if (type == 34)
{
// 同一个订单只能减少一次
string orderId = row["order_id"].ParseToString();
if (orderId.IsNullOrEmpty() || giftsOrderSet.Contains(orderId))
continue;
giftsOrderSet.Add(orderId);
itemAmount = -oem_amount;
}
else
{
continue; // 其他类型不计入
}
total_amount += itemAmount;
rebate_amount += itemAmount;
id = row["id"].ParseToLong(),
type = row["type"].ParseToInt(),
amount = row["amount"].ParseToDecimal(),
oem_amount = row["oem_amount"].ParseToDecimal(),
};
flowList.Add(item);
settleIdLst.Add(item.id);
}
var flowUniqueList = flowList
.GroupBy(x => new
{
x.type,
x.order_id
})
.Select(x => x.First())
.ToList(); // 去重后的流水记录
List<user_payment_record_info> flowFilterList = new List<user_payment_record_info>();//去除后的流水记录 23-20 34-16
foreach (var item in flowUniqueList)//去除退款返回
{
if (item.type == 20)
{
item.oem_amount = item.amount - 2.2m;
}
else if (item.type == 26)
{
item.oem_amount = item.amount - 2.5m;
}
if (item.type == 23)
{
var temp = flowFilterList.FirstOrDefault(a => a.type == 20 && a.order_id == item.order_id);
if (temp != null)
flowFilterList.Remove(temp);//23 移除 20
}
else if (item.type == 34)
{
item.oem_amount = -item.oem_amount;
}
flowFilterList.Add(item);
}
decimal paymentAmount = flowFilterList.Sum(x => x.oem_amount);
total_amount += paymentAmount;
rebate_amount += paymentAmount;
if (settleIdLst.Count == 0)
return 0;
@@ -698,13 +703,13 @@ namespace KJD_Web.BLL.WXXD
var flowRst = mySql.ExecuteAffectedRows(sql);
if (!string.IsNullOrEmpty(mySql.Message) || flowRst <= 0)
throw new Exception("标记流水结算失败");
}
//读取用户店铺续费
sql = "SELECT id,delta_points FROM `wxxd`.`user_points_record` WHERE user_name IN ('" + string.Join("','", userLst) + "') AND option_type ='续费' AND settlement=0 ORDER BY id ASC";
var userPointsDt = mySql.ExecuteDataTable(sql);
@@ -14,7 +14,7 @@ namespace KJD_Web.Entitys
/// 主键(自增)
/// </summary>
[Column(Name = "id", IsPrimary = true, IsIdentity = true)]
public int Id { get; set; }
public long Id { get; set; }
/// <summary>
/// 用户名(NOT NULL)
+1
View File
@@ -272,6 +272,7 @@
<Compile Include="Repository\UserPointsRecordRepository.cs" />
<Compile Include="Requests\Users\ShopRenewRequest.cs" />
<Compile Include="Services\ImageCacheService.cs" />
<Compile Include="Services\Users\UserService.FeeRecord.cs" />
<Compile Include="Services\Users\UserService.OEM.cs" />
<Compile Include="Services\Users\UserService.cs" />
<Compile Include="SignValidateFilterAttribute.cs" />
@@ -0,0 +1,221 @@
using KJD_Web.Entitys;
using KJD_Web.Model.WxModel;
using MySqlX.XDevAPI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace KJD_Web.Services.Users
{
/// <summary>
/// 消费
/// </summary>
public partial class UserService
{
/// <summary>
/// 店铺续费手续费 15
/// </summary>
private const int ShopRenewFee = 15;
/// <summary>
/// 结算OEM流水
/// </summary>
public OEMEntity SettleOemFlows(string userName)
{
var oem = GetOEMByUserName(userName);
if (oem == null)
{
throw new Exception("错误的账号");
}
using var work = _freeSql.CreateUnitOfWork();
var trFreeSql = work.Orm;
// 获取OEM下面的所有用户
var users = GetOEMUsers(oem.OemId, true);
var userNames = users
.Select(a => a.UserName)
.Where(a => !string.IsNullOrEmpty(a))
.Distinct()
.ToList();
if (userNames.Count == 0)
{//todo
throw new Exception("没有用户");
}
/*
* OEM结算规则:
*
* 只结算OEM创建之后产生的流水。
*
* CreateTime > oem.AddTime
*/
long totalFen = SettleFlowsInternal(
trFreeSql,
userNames,
oem.AddTime);
long rebateFen = totalFen;
if (totalFen != 0 || rebateFen != 0)
{
var affrows = trFreeSql
.Update<OEMEntity>()
.Set(a => new
{
AvailableBalance =
a.AvailableBalance + totalFen,
TotalRebateAmount =
a.TotalRebateAmount + rebateFen
})
.Where(a => a.OemId == oem.OemId)
.ExecuteAffrows();
if (affrows != 1)
{
throw new Exception("OEM余额更新失败");
}
}
work.Commit();
return oem;
}
/// <summary>
/// 结算用户流水
/// </summary>
/// <param name="userName"></param>
public void SettleUserFlows(string userName)
{
var user = GetUserByUserName(userName); if (user == null) { throw new Exception("错误的账号"); }
using var work = _freeSql.CreateUnitOfWork();
var trFreeSql = work.Orm;
var userNames = new List<string> { user.UserName };
/* * 普通用户没有OEM创建时间限制。 * * 所以这里传null。 */
long totalAmount = SettleFlowsInternal(trFreeSql, userNames, null);
/* * 普通用户没有余额, * 所以不做任何金额更新。 */
work.Commit();
}
/// <summary>
/// 1. 查询支付流水
/// 2. 计算OEM结算金额
/// 3. 查询续费流水
/// 4. 标记流水为已结算
/// </summary>
/// <param name="orm">当前事务ORM</param>
/// <param name="userNames">需要结算的用户</param>
/// <param name="oemAddTime">
private long SettleFlowsInternal(IFreeSql tr_freeSql, ICollection<string> userNames, DateTime? oemAddTime)
{
if (userNames == null || userNames.Count == 0) { throw new Exception("没有用户"); }
decimal total_amount = 0m; // 总金额(元)
decimal rebate_amount = 0m; // 正数部分(累计返利)
DateTime now = DateTime.Now;
List<int> UserPaymentTypeFiltert = [20, 23, 26, 16, 31, 34];
var paymentQuery = tr_freeSql.Select<UserPaymentRecordEntity>()
.Where(a => userNames.Contains(a.UserName))
.Where(a => UserPaymentTypeFiltert.Contains(a.Type))
.Where(a => a.Settlement == 0)
.Where(a => a.IsDeleted == 0);
//只有OEM结算才限制OEM创建时间。
if (oemAddTime.HasValue) { paymentQuery = paymentQuery.Where(a => a.CreateTime > oemAddTime.Value); }
var userPayments = paymentQuery.ToList();
if (userPayments.Count > 0)
{
///原始流水ID。
List<long> ids = userPayments.Select(a => a.Id).ToList();
var userPaymentUnique = userPayments.GroupBy(a => //去重
new
{
a.Type,
a.OrderId
}).Select(a => a.First());
//经过计算过滤后的列表
List<UserPaymentRecordEntity> userPaymentCalculated = new List<UserPaymentRecordEntity>();
foreach (var item in userPaymentUnique)
{
if (item.Type == 20)
{
item.OemAmount = item.Amount - 2.2m;
}
else if (item.Type == 26)
{
item.OemAmount = item.Amount - 2.5m;
}
if (item.Type == 23)
{
var temp = userPaymentCalculated.FirstOrDefault(a => a.Type == 20 && a.OrderId == item.OrderId);
if (temp != null)
userPaymentCalculated.Remove(temp);//23 移除 20
}
else if (item.Type == 34)
{
item.OemAmount = -item.OemAmount;
}
userPaymentCalculated.Add(item);
}
decimal userPaymentAmount = userPaymentCalculated.Sum(x => x.OemAmount ?? 0);//累计返利
total_amount += userPaymentAmount;
rebate_amount += userPaymentAmount;
var settlementCount = tr_freeSql.Update<UserPaymentRecordEntity>()
.Set(a => a.Settlement, (byte)1)
.Set(a => a.SettlementTime, now)
.Where(a => ids.Contains(a.Id))
.ExecuteAffrows();
if (settlementCount != ids.Count)
throw new Exception("运费流水结算失败");
}
var userPoints = tr_freeSql.Select<UserPointsRecordEntity>()
.Where(a => userNames.Contains(a.UserName))
.Where(a => a.OptionType == "续费")
.Where(a => a.Settlement == false)
.ToList();
if (userPoints.Count > 0)
{
List<long> ids = userPoints.Select(a => a.Id).ToList();
decimal userPointsAmount = userPoints.Sum(x =>
{
return x.DeltaPoints * 1 - ShopRenewFee; //比例1:1 减去固定收取费用
});//累计返利
userPointsAmount *= 1;//比例1:1
total_amount += userPointsAmount;
rebate_amount += userPointsAmount;
var settlementCount = tr_freeSql.Update<UserPointsRecordEntity>()
.Set(a => a.Settlement, true)
.Set(a => a.SettlementTime, now)
.Where(a => ids.Contains(a.Id))
.ExecuteAffrows();
if (settlementCount != ids.Count)
throw new Exception("积分流水结算失败");
}
long total_fen = (long)Math.Round(total_amount * 100m);
//long rebate_fen = (long)Math.Round(rebate_amount * 100m);
return total_fen;
}
}
}
-1
View File
@@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
BIN
View File
Binary file not shown.