using KJD_Web.Entitys; using KJD_Web.Model.WxModel; using MySqlX.XDevAPI; using System; using System.Collections.Generic; using System.Data.Common; using System.Diagnostics; using System.Linq; using System.Text; using System.Web; using static FreeSql.Internal.GlobalFilter; namespace KJD_Web.Services.Users { /// /// 消费 /// public partial class UserService { /// /// 店铺续费手续费 15 /// private const int ShopRenewFee = 15; /// /// 结算OEM流水 /// public OEMEntity SettleOemFlows(string userName, DbTransaction tarn = null) { throw new Exception("结算失败"); var oem = GetOEMByUserName(userName); if (oem == null) { throw new Exception("错误的账号"); } using var work = tarn != null ? _freeSql.CreateUnitOfWork(tarn) : _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() .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(); oem = GetOEMByUserName(userName, false); return oem; } /// /// 结算用户流水 /// /// public long SettleUserFlows(string userName, DbTransaction tarn = null) { var user = GetUserAndSubUser(userName); if (user == null) { throw new Exception("错误的账号"); } using var work = tarn != null ? _freeSql.CreateUnitOfWork(tarn) : _freeSql.CreateUnitOfWork(); var trFreeSql = work.Orm; var userNames = user.Select(a => a.UserName).ToList(); /* * 普通用户没有OEM创建时间限制。 * * 所以这里传null。 */ long totalAmount = SettleFlowsInternal(trFreeSql, userNames, null); /* * 普通用户没有余额, * 所以不做任何金额更新。 */ Debug.WriteLine($"用户流水结算:{totalAmount}"); work.Commit(); return totalAmount; } /// /// 1. 查询支付流水 /// 2. 计算OEM结算金额 /// 3. 查询续费流水 /// 4. 标记流水为已结算 /// /// 当前事务ORM /// 需要结算的用户 /// private long SettleFlowsInternal(IFreeSql tr_freeSql, ICollection 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 UserPaymentTypeFiltert = [16, 20, 23, 26, 31, 34]; var paymentQuery = tr_freeSql.Select() .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); } paymentQuery.OrderBy(a => a.Id); var userPayments = paymentQuery.ToList(); if (userPayments.Count > 0) { Debug.WriteLine(userPayments.Where(a => a.Type == 20).Sum(a => a.OemAmount)); ///原始流水ID。 List ids = userPayments.Select(a => a.Id).ToList(); var userPaymentUnique = userPayments.GroupBy(a => //去重 new { a.Type, a.OrderId }).Select(a => a.First()).ToList(); //经过计算过滤后的列表 List userPaymentCalculated = new List(); foreach (var item in userPaymentUnique) { if (item.Type == 20) { //item.OemAmount = item.Amount - 2.2m; item.OemAmount = item.OemAmount; } else if (item.Type == 26) { //item.OemAmount = item.Amount - 2.5m; item.OemAmount = item.OemAmount; } if (item.Type == 23) { var temp = userPaymentCalculated.FirstOrDefault(a => a.Type == 20 && a.OrderId == item.OrderId); if (temp != null) { userPaymentCalculated.Remove(temp);//23 移除 20 } continue; } else if (item.Type == 34) { item.OemAmount = item.OemAmount * -1; } userPaymentCalculated.Add(item); } decimal userPaymentAmount = userPaymentCalculated.Sum(x => x.OemAmount ?? 0);//累计返利 //StringBuilder sb = new StringBuilder(); //sb.AppendLine("id,order_id,type,amount,oem_amount,time"); //foreach (var item in userPayments) //{ // sb.AppendLine($"{item.Id},{item.OrderId},{item.Type},{item.Amount},{item.OemAmount},{item.CreateTime}"); //} total_amount += userPaymentAmount; rebate_amount += userPaymentAmount; Debug.WriteLine($"运费流水返利:{userPaymentAmount}"); var settlementCount = tr_freeSql.Update() .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() .Where(a => userNames.Contains(a.UserName)) .Where(a => a.OptionType == "续费") .Where(a => a.Settlement == false) .ToList(); if (userPoints.Count > 0) { List ids = userPoints.Select(a => a.Id).ToList(); decimal userPointsAmount = userPoints.Sum(x => { return x.DeltaPoints * 1 - ShopRenewFee; //比例1:1 减去固定收取费用 });//累计返利 total_amount += userPointsAmount; rebate_amount += userPointsAmount; Debug.WriteLine($"商铺月费返利:{userPointsAmount}"); var settlementCount = tr_freeSql.Update() .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; } /// /// 获取用户金额统计 /// /// public UserAmountSummary GetUserAmountSummary(string userName) { UserAmountSummary summary = new UserAmountSummary(); var user = GetUserByUserName(userName); if (user == null) throw new Exception("错误的用户"); summary.RechargeTotal = (long)Math.Round((user.RechargeAmountTotal ?? 0) * 100m); summary.Balance = (long)Math.Round((user.Balance ?? 0) * 100m); List types = new List { 16, 20, 23, 24, 26, 31 }; var data = _freeSql.Select() .Where(a => types.Contains(a.Type)) .Where(a => a.UserName == userName) .ToList(); decimal sum = data.Sum(r => r.Type == 23 ? -(r.Amount ?? 0) : r.Amount ?? 0); summary.ConsumeTotal = (long)Math.Round(sum * 100m); return summary; } } public class UserAmountSummary { /// /// 充值总额 /// public long RechargeTotal { get; set; } /// /// 消费总额 /// public long ConsumeTotal { get; set; } /// /// 剩余余额 /// public long Balance { get; set; } } }