From 16813c10f4c51b904100754e018ecb599894acb0 Mon Sep 17 00:00:00 2001 From: liguoyang Date: Thu, 11 Jan 2024 11:53:26 +0800 Subject: [PATCH] =?UTF-8?q?fix=20=E4=BC=98=E5=8C=96=E6=B6=88=E8=B4=B9?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Order/Controllers/OrdersController.cs | 4 +- .../Order/Response/BalanceRecordResponse.cs | 2 +- .../Order/Response/OrderConsumeResponse.cs | 29 +++ .../Order/Services/IOrderService.cs | 2 +- .../Services/Implements/BalanceService.cs | 30 ++- .../Order/Services/Implements/OrderService.cs | 198 +++++++++++++----- .../Canteen/Entities/BalanceRecordEntity.cs | 2 +- .../Enums/BalanceRecordStatusEnumType.cs | 1 - 8 files changed, 203 insertions(+), 65 deletions(-) create mode 100644 Src/Dlhis.Canteen/Order/Response/OrderConsumeResponse.cs diff --git a/Src/Dlhis.Canteen/Order/Controllers/OrdersController.cs b/Src/Dlhis.Canteen/Order/Controllers/OrdersController.cs index f7d0cf09..4189e6b8 100644 --- a/Src/Dlhis.Canteen/Order/Controllers/OrdersController.cs +++ b/Src/Dlhis.Canteen/Order/Controllers/OrdersController.cs @@ -40,8 +40,8 @@ public class OrdersController : ControllerBase /// [AllowAnonymous] [HttpPost] - public async Task AddAsync(OrderAddRequest request) + public async Task AddAsync(OrderAddRequest request) { - await _orderService.AddAsync(request); + return await _orderService.AddAsync(request); } } diff --git a/Src/Dlhis.Canteen/Order/Response/BalanceRecordResponse.cs b/Src/Dlhis.Canteen/Order/Response/BalanceRecordResponse.cs index bae8e194..8fdba839 100644 --- a/Src/Dlhis.Canteen/Order/Response/BalanceRecordResponse.cs +++ b/Src/Dlhis.Canteen/Order/Response/BalanceRecordResponse.cs @@ -13,7 +13,7 @@ public class BalanceRecordResponse /// /// 档案号/QRCode /// - public string UserId { get; set; } + public string UserNo { get; set; } /// /// 姓名 diff --git a/Src/Dlhis.Canteen/Order/Response/OrderConsumeResponse.cs b/Src/Dlhis.Canteen/Order/Response/OrderConsumeResponse.cs new file mode 100644 index 00000000..969483d8 --- /dev/null +++ b/Src/Dlhis.Canteen/Order/Response/OrderConsumeResponse.cs @@ -0,0 +1,29 @@ +namespace Dlhis.Canteen.Order.Response; + +public class OrderConsumeResponse +{ + /// + /// 用户工号 + /// + public string UserCode { get; set; } + + /// + /// 用户名称 + /// + public string UserName { get; set; } + + /// + /// 部门号 + /// + public string DepartmentNo { get; set; } + + /// + /// 部门名称 + /// + public string DepartmentName { get; set; } + + /// + /// 余额 + /// + public decimal Balance { get; set; } +} diff --git a/Src/Dlhis.Canteen/Order/Services/IOrderService.cs b/Src/Dlhis.Canteen/Order/Services/IOrderService.cs index e7e36fca..c7e53edb 100644 --- a/Src/Dlhis.Canteen/Order/Services/IOrderService.cs +++ b/Src/Dlhis.Canteen/Order/Services/IOrderService.cs @@ -8,5 +8,5 @@ public interface IOrderService : IScopeDependency { Task> GetPageAsync(OrderPageRequest request); - Task AddAsync(OrderAddRequest request); + Task AddAsync(OrderAddRequest request); } diff --git a/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs b/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs index 8bb905f9..912179fe 100644 --- a/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs +++ b/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs @@ -1,5 +1,6 @@ using Dlhis.Canteen.Order.Request; using Dlhis.Canteen.Order.Response; +using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Canteen.Entities; using Kurisu.Core.DataAccess.Dto; using Kurisu.SqlSugar.Extensions; @@ -19,10 +20,37 @@ public class BalanceService : IBalanceService public async Task> GetPageAsync(BalanceRecordPageRequest request) { var page = await _dbContext.Queryable() + .LeftJoin((record, ga) => record.UserNo == ga.No) + .LeftJoin((record, ga, department) => ga.DepartmentNo == department.No) + .LeftJoin((record, ga, department, bplace) => record.BusinessPlaceCode == bplace.Code) + .LeftJoin((record, ga, department, bplace, bshift) => record.BusinessShiftCode == bshift.Code) .WhereIF(request.SearchDateTimePeriod?.Start.HasValue == true, record => record.CreateTime >= request.SearchDateTimePeriod.Start) .WhereIF(request.SearchDateTimePeriod?.End.HasValue == true, record => record.CreateTime <= request.SearchDateTimePeriod.End) .OrderBy(record => record.CreateTime) - .Select() + .Select((record, ga, department, bplace, bshift) => new BalanceRecordResponse + { + Amount = record.Amount, + BusinessPlaceCode = record.BusinessPlaceCode, + BusinessShiftCode = record.BusinessShiftCode, + CostDate = record.CostDate, + CostId = record.CostId, + DepartmentNo = record.DepartmentNo, + DeviceInfo = record.DeviceInfo, + IP = record.IP, + UserNo = record.UserNo, + UserCode = record.UserCode, + Type = record.Type, + SubsidiesFromMonth = record.SubsidiesFromMonth, + Status = record.Status, + Source = record.Source, + No = record.No, + IsCostCrossTenant = record.IsCostCrossTenant, + OriginTenantId = record.OriginTenantId, + Name = record.Name, + DepartmentName = department.Name, + BusinessPlaceName = bplace.Name, + BusinessShiftName = bshift.Name, + }) .ToPageListAsync(request); return page; diff --git a/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs b/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs index 0a44bcf6..7e3ef6de 100644 --- a/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs +++ b/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs @@ -41,7 +41,7 @@ public class OrderService : IOrderService } [IgnoreTenant] - public async Task AddAsync(OrderAddRequest request) + public async Task AddAsync(OrderAddRequest request) { var device = await _dbContext.Queryable().Where(x => x.UniqueNo == request.DeviceUniqueNo).Where(x => x.Enable).FirstAsync(); device.ThrowIfNull("设备不存在或者尚未启用"); @@ -107,10 +107,9 @@ public class OrderService : IOrderService RequestJson = request.ToJson(), ThirdNo = request.ThirdNo, Type = request.Type.Value, - OrderStatus = CanteenOrderStatusEnumType.Wait, Name = gafinfo.Name, Source = request.Source, - UserId = canteenUser.UserNo, + UserNo = canteenUser.UserNo, UserCode = canteenUser.UserCode, Amount = request.Amount, BusinessPlaceCode = businessPlace.Code, @@ -127,14 +126,139 @@ public class OrderService : IOrderService OriginTenantId = canteenUser.TenantId,//人员可能跨基地消费 - Status = BalanceRecordStatusEnumType.Doubtful, - TenantId = device.TenantId, //设备才能标识当前消费的基地 + //餐别异常处理 + Status = shift == null ? BalanceRecordStatusEnumType.Doubtful : BalanceRecordStatusEnumType.Valid, + OrderStatus = CanteenOrderStatusEnumType.Wait, + //设备才能标识当前消费的基地 + TenantId = device.TenantId, + + //默认为admin + CreatedBy = 1, + CreateTime = DateTime.Now, + ModifiedBy = 1, + ModifiedTime = DateTime.Now, }; var id = await _dbContext.InsertReturnIdentityAsync(order); - await GenerateChargeRecordAsync(id, settings, shifts, request.CostDateTime); + var result = await _dbContext.UseTransactionAsync(async () => + { + try + { + var r = await GenerateChargeRecordAsync(id, settings, shifts, request.CostDateTime); + return r; + } + catch (Exception) + { + throw; + } + finally + { + //订单消费成功 + order.OrderStatus = CanteenOrderStatusEnumType.Successful; + await _dbContext.UpdateAsync(order); + } + }); + + if (!result.IsSuccess) + { + throw new UserFriendlyException(result.ErrorMessage); + } + + return result.Data; } + public async Task GenerateChargeRecordAsync(long orderId, + Dictionary settings, + List shifts, + DateTime costDateTime) + { + var order = await _dbContext.Queryable().Where(x => x.Id == orderId).FirstAsync(); + + //校验 + await Verify(settings, shifts, costDateTime, order); + + + return await ContinueUpdateAsync(async () => + { + var canteenUser = await _dbContext.Queryable().Where(x => x.UserNo == order.UserNo).FirstAsync(); + //金额+- + canteenUser.Balance += order.Amount; + + if (order.Type == BalanceRecordTypeEnumType.Out) + { + if (canteenUser.Balance < 0) + { + throw new UserFriendlyException("余额不足,无法消费"); + } + } + + var effect = await _dbContext.Updateable() + .SetColumns(x => x.Balance == canteenUser.Balance + order.Amount) + .SetColumns(x => x.Version == x.Version + 1) + .Where(x => x.UserNo == order.UserNo && x.Version == canteenUser.Version)//必须与查询时的version一致 + .ExecuteCommandAsync(); + + if (effect <= 0) throw new VersionExceptions("更新版本冲突"); + + //写入消费记录 + var balanceRecord = order.Adapt(); + await _dbContext.InsertAsync(balanceRecord); + + return await _dbContext.Queryable() + .LeftJoin((ga, department) => ga.DepartmentNo == department.No) + .LeftJoin((ga, department, mealUser) => ga.No == mealUser.UserNo) + .Select((ga, department, mealUser) => new OrderConsumeResponse + { + UserCode = ga.Code, + UserName = ga.Name, + DepartmentNo = ga.DepartmentNo, + DepartmentName = department.Name, + Balance = mealUser.Balance + }) + .FirstAsync(); + }, 5); + } + + //******************************************************* help methods ************************************************************/ + + /// + /// 设备并发更新 + /// + /// + /// + /// + /// + /// + private async Task ContinueUpdateAsync(Func> func, int retry) + { + for (int i = 0; i < retry; i++) + { + try + { + return await func(); + } + catch (Exception ex) when (ex is VersionExceptions) + { + _logger.LogWarning(ex, ex.Message); + } + catch (Exception) + { + throw; + } + } + + throw new UserFriendlyException("消费失败,请重试"); + } + + + /// + /// 获取参数配置 + /// + /// + /// + /// + /// + /// private static T GetSetting(Dictionary settings, CanteenSettingItemEnumType item, T defaultValue = default) { if (settings.TryGetValue(item, out var v)) @@ -145,59 +269,17 @@ public class OrderService : IOrderService return defaultValue; } - public async Task GenerateChargeRecordAsync(long orderId, - Dictionary settings, - List shifts, - DateTime costDateTime) - { - var order = await _dbContext.Queryable().Where(x => x.Id == orderId).FirstAsync(); - await Verify(settings, shifts, costDateTime, order);//校验 - - for (int i = 0; i < 5; i++) - { - try - { - var canteenUser = await _dbContext.Queryable().Where(x => x.UserNo == order.UserId).FirstAsync(); - //金额+- - canteenUser.Balance += order.Amount; - - if (order.Type == BalanceRecordTypeEnumType.Out) - { - if (canteenUser.Balance < 0) - { - throw new UserFriendlyException("余额不足,无法消费"); - } - } - - var effect = await _dbContext.Updateable() - .SetColumns(x => x.Balance == canteenUser.Balance + order.Amount) - .SetColumns(x => x.Version == x.Version + 1) - .Where(x => x.UserNo == order.UserId && x.Version == canteenUser.Version)//必须与查询时的version一致 - .ExecuteCommandAsync(); - - if (effect <= 0) - { - throw new VersionExceptions("更新版本冲突"); - } - - var balanceRecord = order.Adapt(); - await _dbContext.InsertAsync(balanceRecord); - order.Status = BalanceRecordStatusEnumType.Valid; //订单改为有效 - - break; - } - catch (Exception ex) when (ex is VersionExceptions) - { - _logger.LogError(ex, ex.Message); - } - catch (Exception) - { - throw; - } - } - } + /// + /// 验证参数 + /// + /// + /// + /// + /// + /// + /// private async Task Verify(Dictionary settings, List shifts, DateTime costDateTime, CanteenOrderEntity order) { //在线 @@ -215,7 +297,7 @@ public class OrderService : IOrderService var endOfDay = beginOfDay.AddHours(23).AddMinutes(59).AddSeconds(59); var balanceRecords = await _dbContext.Queryable() - .Where(x => x.UserId == order.UserId) + .Where(x => x.UserNo == order.UserNo) .Where(x => x.CreateTime <= beginOfDay && x.CreateTime <= endOfDay) //今天消费记录 .ToListAsync(); diff --git a/Src/Dlhis.Entity/Canteen/Entities/BalanceRecordEntity.cs b/Src/Dlhis.Entity/Canteen/Entities/BalanceRecordEntity.cs index 61daa06e..28c29ef6 100644 --- a/Src/Dlhis.Entity/Canteen/Entities/BalanceRecordEntity.cs +++ b/Src/Dlhis.Entity/Canteen/Entities/BalanceRecordEntity.cs @@ -22,7 +22,7 @@ public class BalanceRecordEntity : SugarBaseEntity, ITenantId /// 档案号/QRCode /// [SugarColumn(ColumnDescription = "档案号/QRCode")] - public string UserId { get; set; } + public string UserNo { get; set; } /// /// 姓名 diff --git a/Src/Dlhis.Entity/Canteen/Enums/BalanceRecordStatusEnumType.cs b/Src/Dlhis.Entity/Canteen/Enums/BalanceRecordStatusEnumType.cs index 7bb3a02f..1c00c06f 100644 --- a/Src/Dlhis.Entity/Canteen/Enums/BalanceRecordStatusEnumType.cs +++ b/Src/Dlhis.Entity/Canteen/Enums/BalanceRecordStatusEnumType.cs @@ -15,7 +15,6 @@ public enum BalanceRecordStatusEnumType [Description("有效数据")] Valid = 1, - /// /// 存疑 ///