From 484be10fde7d03b0e7b53d084e00ae136d7fb2f9 Mon Sep 17 00:00:00 2001 From: liguoyang Date: Thu, 21 Nov 2024 10:27:08 +0800 Subject: [PATCH] =?UTF-8?q?fix=20=E6=B6=88=E8=B4=B9=E6=81=A2=E5=A4=8D?= =?UTF-8?q?=E4=B8=BA=E4=BD=99=E9=A2=9D=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Order/Repository/IBalanceRepository.cs | 16 +++- .../Implements/BalanceRepository.cs | 92 ++++++++++++++++--- .../Services/Implements/MiddleService.cs | 3 +- .../Order/Services/Implements/OrderService.cs | 16 +--- .../Services/Implements/WalletService.cs | 10 +- .../Canteen/Entities/UserBalanceEntity.cs | 27 ++++++ .../Canteen/Entities/WalletEntity.cs | 6 +- .../Jobs/MealSupplementHandlerJob.cs | 34 +++++++ 8 files changed, 168 insertions(+), 36 deletions(-) create mode 100644 Src/Dlhis.Entity/Canteen/Entities/UserBalanceEntity.cs diff --git a/Src/Dlhis.Canteen/Order/Repository/IBalanceRepository.cs b/Src/Dlhis.Canteen/Order/Repository/IBalanceRepository.cs index 0c1e321c..6e90a374 100644 --- a/Src/Dlhis.Canteen/Order/Repository/IBalanceRepository.cs +++ b/Src/Dlhis.Canteen/Order/Repository/IBalanceRepository.cs @@ -8,9 +8,8 @@ public interface IBalanceRepository : IScopeDependency /// 获取余额 /// /// - /// /// - Task GetBalanceAsync(string userCode, string factory); + Task GetBalanceAsync(string userCode); /// /// 获取消费明细 @@ -29,12 +28,19 @@ public interface IBalanceRepository : IScopeDependency /// Task> GetWalletFactoriesAsync(string factory); + /// - /// 检测余额是否足够 + /// 消费余额 /// /// - /// /// /// - Task CheckConsumableAsync(string userCode, string factory, decimal cost); + Task ConsumeBalanceAsync(string userCode, decimal cost); + + /// + /// 重算余额 + /// + /// + /// + Task CalculateBalanceAsync(string userCode); } \ No newline at end of file diff --git a/Src/Dlhis.Canteen/Order/Repository/Implements/BalanceRepository.cs b/Src/Dlhis.Canteen/Order/Repository/Implements/BalanceRepository.cs index f1d60d9e..0a687659 100644 --- a/Src/Dlhis.Canteen/Order/Repository/Implements/BalanceRepository.cs +++ b/Src/Dlhis.Canteen/Order/Repository/Implements/BalanceRepository.cs @@ -1,6 +1,8 @@ using Dlhis.Entity.Canteen.Entities; using Dlhis.Entity.Canteen.Enums; +using Kurisu.AspNetCore.DataAccess.SqlSugar.Extensions; using Kurisu.AspNetCore.DataAccess.SqlSugar.Services; +using Kurisu.AspNetCore.Utils; using Kurisu.AspNetCore.Utils.Extensions; namespace Dlhis.Canteen.Order.Repository.Implements; @@ -14,19 +16,21 @@ public class BalanceRepository : IBalanceRepository _dbContext = dbContext; } - public async Task GetBalanceAsync(string userCode, string factory) + public async Task GetBalanceAsync(string userCode) { - var queryable = _dbContext.Queryable() - .Where(x => x.UserCode == userCode && x.Status == BalanceRecordStatusEnumType.Valid) - .Where(x => x.Source != BalanceRecordSourceEnumType.EMealVoucher); + // var queryable = _dbContext.Queryable() + // .Where(x => x.UserCode == userCode && x.Status == BalanceRecordStatusEnumType.Valid) + // .Where(x => x.Source != BalanceRecordSourceEnumType.EMealVoucher); + // + // if (!factory.IsPresent()) + // { + // return await queryable.SumAsync(x => x.Amount); + // } + // + // var factories = await GetWalletFactoriesAsync(factory); + // return await queryable.Where(x => factories.Contains(x.TenantId)).SumAsync(x => x.Amount); - if (!factory.IsPresent()) - { - return await queryable.SumAsync(x => x.Amount); - } - - var factories = await GetWalletFactoriesAsync(factory); - return await queryable.Where(x => factories.Contains(x.TenantId)).SumAsync(x => x.Amount); + return await _dbContext.Queryable().Where(x => x.UserCode == userCode).Select(x => x.Balance).SingleAsync(); } public async Task> GetBalanceRecordsAsync(string userCode, string factory, DateTime startTime, DateTime endTime) @@ -51,10 +55,68 @@ public class BalanceRepository : IBalanceRepository } - public async Task CheckConsumableAsync(string userCode, string factory, decimal cost) + /// + public async Task ConsumeBalanceAsync(string userCode, decimal cost) { - var balance = await GetBalanceAsync(userCode, factory); - var isEnough = balance - Math.Abs(cost) >= 0; - isEnough.ThrowIfFalse($"钱包余额不足({balance}元)"); + await CommonHelper.RetryAsync(async () => + { + if (!await _dbContext.Queryable().Where(x => x.UserCode == userCode).AnyAsync()) + { + await CalculateBalanceAsync(userCode); + } + + var data = await _dbContext.Queryable() + .Where(x => x.UserCode == userCode) + .Select(x => new + { + x.Balance, x.Version + }) + .SingleAsync(); + + var currentBalance = data.Balance - Math.Abs(cost); + var isEnough = currentBalance >= 0; + isEnough.ThrowIfFalse($"钱包余额不足({data.Balance}元)"); + + await _dbContext.Updateable() + .SetColumns(x => x.Balance == currentBalance) + .SetColumns(x => x.Version == data.Version + 1) + .SetColumns(x => x.ModifiedTime == DateTime.Now) + .Where(x => x.UserCode == userCode && x.Version == data.Version) + .ExecuteCommandThrowVersionAsync(); + }); + } + + public async Task CalculateBalanceAsync(string userCode) + { + if (!await _dbContext.Queryable().Where(x => x.UserCode == userCode).AnyAsync()) + { + await _dbContext.InsertAsync(new UserBalanceEntity + { + UserCode = userCode, + Balance = 0, + Version = 0 + }); + } + + await CommonHelper.RetryAsync(async () => + { + var balance = await _dbContext.Queryable() + .Where(x => x.UserCode == userCode) + .Where(x => x.Status == BalanceRecordStatusEnumType.Valid) + .Where(x => x.Source != BalanceRecordSourceEnumType.EMealVoucher) + .SumAsync(x => x.Amount); + + var version = await _dbContext.Queryable() + .Where(x => x.UserCode == userCode) + .Select(x => x.Version) + .SingleAsync(); + + await _dbContext.Updateable() + .SetColumns(x => x.Balance == balance) + .SetColumns(x => x.Version == version + 1) + .SetColumns(x => x.ModifiedTime == DateTime.Now) + .Where(x => x.UserCode == userCode && x.Version == version) + .ExecuteCommandThrowVersionAsync(); + }, 5); } } \ No newline at end of file diff --git a/Src/Dlhis.Canteen/Order/Services/Implements/MiddleService.cs b/Src/Dlhis.Canteen/Order/Services/Implements/MiddleService.cs index f0a1bb2f..db53a72b 100644 --- a/Src/Dlhis.Canteen/Order/Services/Implements/MiddleService.cs +++ b/Src/Dlhis.Canteen/Order/Services/Implements/MiddleService.cs @@ -26,9 +26,10 @@ public class MiddleService : IMiddleService if (!await _dbContext.Queryable().AnyAsync(x => x.No == entity.No)) { await _dbContext.InsertAsync(entity); + await _balanceRepository.CalculateBalanceAsync(entity.UserCode); } - var balance = await _balanceRepository.GetBalanceAsync(entity.UserCode, string.Empty); + var balance = await _balanceRepository.GetBalanceAsync(entity.UserCode); //获取人员余额 return await _dbContext.Queryable() diff --git a/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs b/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs index 44978807..ec9917de 100644 --- a/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs +++ b/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs @@ -86,7 +86,7 @@ public class OrderService : IOrderService var jinkoCode = _currentUser.GetUserClaim("jinko-code") ?? string.Empty; if (jinkoCode.IsPresent()) { - gainfo = await _dbContext.Queryable().Where(x => x.Code == jinkoCode).FirstAsync(); + gainfo = await _dbContext.Queryable().Where(x => x.Code == jinkoCode).SingleAsync(); } var pageResult = await _dbContext.Queryable().Where(x => x.UserNo == gainfo.No) @@ -319,6 +319,7 @@ public class OrderService : IOrderService await _dbContext.InsertAsync(order); var balanceRecord = order.Adapt(); await _dbContext.InsertAsync(balanceRecord); + await _balanceRepository.CalculateBalanceAsync(balanceRecord.UserCode); } /// @@ -347,7 +348,7 @@ public class OrderService : IOrderService //校验 await Verify(order); - await _balanceRepository.CheckConsumableAsync(order.UserCode, order.TenantId, order.Amount); + await _balanceRepository.ConsumeBalanceAsync(order.UserCode, order.Amount); //写入记录 var balanceRecord = order.Adapt(); @@ -479,14 +480,7 @@ public class OrderService : IOrderService } } - //获取人员信息 - var currentFactory = await _dbContext.Queryable() - .Where(x => x.UniqueNo == request.DeviceUniqueNo) - .Select(x => x.TenantId) - .SingleAsync(); - - var balance = await _balanceRepository.GetBalanceAsync(gainfo.Code, currentFactory); - var totalBalance = await _balanceRepository.GetBalanceAsync(gainfo.Code, string.Empty); + var balance = await _balanceRepository.GetBalanceAsync(gainfo.Code); var data = await _dbContext.Queryable() .LeftJoin((x, department) => x.DepartmentNo == department.No) @@ -499,7 +493,7 @@ public class OrderService : IOrderService DepartmentName = department.Name, CurrentBalance = balance, - CurrentTotalBalance = totalBalance + CurrentTotalBalance = balance }) .SingleAsync(); diff --git a/Src/Dlhis.Canteen/Setting/Services/Implements/WalletService.cs b/Src/Dlhis.Canteen/Setting/Services/Implements/WalletService.cs index 1ef8e9c5..42f3a8fc 100644 --- a/Src/Dlhis.Canteen/Setting/Services/Implements/WalletService.cs +++ b/Src/Dlhis.Canteen/Setting/Services/Implements/WalletService.cs @@ -38,8 +38,12 @@ public class WalletService : IWalletService public async Task GetBalanceAsync(string walletCode) { var userCode = _currentUser.GetUserClaim("jinko-code"); - var factory = await _dbContext.Queryable().Where(x => x.Code == walletCode).Select(x => x.Factory).FirstAsync(); - - return await _balanceRepository.GetBalanceAsync(userCode, factory); + + if (!await _dbContext.Queryable().Where(x => x.UserCode == userCode).AnyAsync()) + { + await _balanceRepository.CalculateBalanceAsync(userCode); + } + + return await _balanceRepository.GetBalanceAsync(userCode); } } \ No newline at end of file diff --git a/Src/Dlhis.Entity/Canteen/Entities/UserBalanceEntity.cs b/Src/Dlhis.Entity/Canteen/Entities/UserBalanceEntity.cs new file mode 100644 index 00000000..fe4196ec --- /dev/null +++ b/Src/Dlhis.Entity/Canteen/Entities/UserBalanceEntity.cs @@ -0,0 +1,27 @@ +using Kurisu.AspNetCore.DataAccess.Entity; +using Kurisu.AspNetCore.DataAccess.SqlSugar; +using SqlSugar; + +namespace Dlhis.Entity.Canteen.Entities; + +/// +/// 用户余额表 +/// +[SugarTable(TableName = "UserBalances", TableDescription = "用户余额表")] +public class UserBalanceEntity : SugarBaseEntity, IVersion +{ + /// + /// 学工号 + /// + [SugarColumn(IsNullable = false, ColumnDescription = "学工号", UniqueGroupNameList = new[] { "idx_UserBalances_useCode" })] + public string UserCode { get; set; } + + /// + /// 余额 + /// + [SugarColumn(IsNullable = false, ColumnDescription = "余额")] + public decimal Balance { get; set; } + + /// + public int Version { get; set; } +} \ No newline at end of file diff --git a/Src/Dlhis.Entity/Canteen/Entities/WalletEntity.cs b/Src/Dlhis.Entity/Canteen/Entities/WalletEntity.cs index f396b88a..fd9dd3dc 100644 --- a/Src/Dlhis.Entity/Canteen/Entities/WalletEntity.cs +++ b/Src/Dlhis.Entity/Canteen/Entities/WalletEntity.cs @@ -1,3 +1,4 @@ +using Kurisu.AspNetCore.DataAccess.Entity; using Kurisu.AspNetCore.DataAccess.SqlSugar; using SqlSugar; @@ -7,7 +8,7 @@ namespace Dlhis.Entity.Canteen.Entities; /// 钱包 /// [SugarTable(TableName = "Wallets", TableDescription = "钱包")] -public class WalletEntity : SugarBaseEntity +public class WalletEntity : SugarBaseEntity , ISoftDeleted { /// /// 钱包编码 @@ -26,4 +27,7 @@ public class WalletEntity : SugarBaseEntity /// [SugarColumn(IsNullable = false, UniqueGroupNameList = new[] { "idx_wallets_factry" })] public string Factory { get; set; } + + /// + public bool IsDeleted { get; set; } } \ No newline at end of file diff --git a/Src/Dlhis.ScheduledTask/Jobs/MealSupplementHandlerJob.cs b/Src/Dlhis.ScheduledTask/Jobs/MealSupplementHandlerJob.cs index d81ca771..bed6c098 100644 --- a/Src/Dlhis.ScheduledTask/Jobs/MealSupplementHandlerJob.cs +++ b/Src/Dlhis.ScheduledTask/Jobs/MealSupplementHandlerJob.cs @@ -6,6 +6,8 @@ using Dlhis.ScheduledTask.Attributes; using Dlhis.ScheduledTask.Common.Request; using Dlhis.ScheduledTask.Common.Services; using Hangfire; +using Kurisu.AspNetCore.DataAccess.SqlSugar.Extensions; +using Kurisu.AspNetCore.Utils; namespace Dlhis.ScheduledTask.Jobs; @@ -119,7 +121,39 @@ public class MealSupplementHandlerJob : BaseJob IsDeleted = false, }); + + + if (!await DbContext.Queryable().Where(x => x.UserCode == gainfo.Code).AnyAsync()) + { + await DbContext.InsertAsync(new UserBalanceEntity + { + UserCode = gainfo.Code, + Balance = 0, + Version = 0 + }); + } + await CommonHelper.RetryAsync(async () => + { + var balance = await DbContext.Queryable() + .Where(x => x.UserCode == gainfo.Code) + .Where(x => x.Status == BalanceRecordStatusEnumType.Valid) + .Where(x => x.Source != BalanceRecordSourceEnumType.EMealVoucher) + .SumAsync(x => x.Amount); + + var version = await DbContext.Queryable() + .Where(x => x.UserCode == gainfo.Code) + .Select(x => x.Version) + .SingleAsync(); + + await DbContext.Updateable() + .SetColumns(x => x.Balance == balance) + .SetColumns(x => x.Version == version + 1) + .SetColumns(x => x.ModifiedTime == DateTime.Now) + .Where(x => x.UserCode == gainfo.Code && x.Version == version) + .ExecuteCommandThrowVersionAsync(); + }, 5); + var r = await _jinkoJIPService.SyncMealSupplementRecordsAsync(new List { new()