From 11ac3c5742d79e5fffaaa4dea0fe18deedf2c658 Mon Sep 17 00:00:00 2001 From: liguoyang Date: Sun, 7 Apr 2024 19:02:09 +0800 Subject: [PATCH] =?UTF-8?q?fix=20=E7=A6=BB=E7=BA=BF=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/Implements/BaseOrderService.cs | 1 + .../Order/Services/Implements/OrderService.cs | 184 ++++++++++++++++-- 2 files changed, 170 insertions(+), 15 deletions(-) diff --git a/Src/Dlhis.Canteen/Order/Services/Implements/BaseOrderService.cs b/Src/Dlhis.Canteen/Order/Services/Implements/BaseOrderService.cs index 21cc28b5..c081c53c 100644 --- a/Src/Dlhis.Canteen/Order/Services/Implements/BaseOrderService.cs +++ b/Src/Dlhis.Canteen/Order/Services/Implements/BaseOrderService.cs @@ -31,6 +31,7 @@ public abstract class BaseOrderService _logger = logger; } + protected ILogger Logger => _logger; protected IDbContext DbContext => _dbContext; diff --git a/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs b/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs index e7f1aceb..066ad46b 100644 --- a/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs +++ b/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs @@ -23,13 +23,17 @@ namespace Dlhis.Canteen.Order.Services.Implements; public class OrderService : BaseOrderService, IOrderService { + private readonly RedisCache _redisCache; + public OrderService(ICanteenSettingService canteenSettingService, IDbContext dbContext, ICurrentUser currentUser, IDevicePermissionApi devicePermissionApi, + RedisCache redisCache, ILogger logger) : base(canteenSettingService, dbContext, currentUser, devicePermissionApi, logger) { + _redisCache = redisCache; } public async Task> DeviceConsume(OrderAddRequest request) @@ -47,29 +51,56 @@ public class OrderService : BaseOrderService, IOrderService .Where(x => x.No == request.UserUniqueNo || x.Code == request.UserUniqueNo || x.Id == userId || x.CardNo == request.UserUniqueNo) .FirstAsync(); - gainfo.ThrowIfNull($"无消费权限"); - //消费权限控制 - await CheckPermissionAsync(gainfo.No, request.DeviceUniqueNo); - var message = string.Empty; - try - { - (await DbContext.Queryable().Where(x => x.UserNo == gainfo.No).AnyAsync()).ThrowIfFalse("余额不足,无法消费"); - //消费 - if (request.Type == BalanceRecordTypeEnumType.Out) + if (request.IsOffline) + { + if (request.ThirdNo.IsPresent()) { - await ConsumeAsync(request.Adapt(), gainfo); + using (var handler = await _redisCache.LockAsync($"consume:device:{request.ThirdNo}")) + { + if (handler.Acquired) + { + try + { + await HandleOfflineAsync(request.Adapt(), gainfo); + } + catch (Exception ex) + { + Logger.LogError(ex, "离线入库错误:{message}", ex.Message); + } + } + } } - //充值 else { - await RechargeAsync(request.Adapt(), gainfo); + await HandleOfflineAsync(request.Adapt(), gainfo); } } - catch (Exception ex) + else { - message = ex.Message; + gainfo.ThrowIfNull($"无消费权限"); + await CheckPermissionAsync(gainfo.No, request.DeviceUniqueNo); + + try + { + (await DbContext.Queryable().Where(x => x.UserNo == gainfo.No).AnyAsync()).ThrowIfFalse("余额不足,无法消费"); + + //消费 + if (request.Type == BalanceRecordTypeEnumType.Out) + { + await ConsumeAsync(request.Adapt(), gainfo); + } + //充值 + else + { + await RechargeAsync(request.Adapt(), gainfo); + } + } + catch (Exception ex) + { + message = ex.Message; + } } //获取人员余额 @@ -95,6 +126,129 @@ public class OrderService : BaseOrderService, IOrderService }; } + + private async Task HandleOfflineAsync(ConsumeRequest request, GainfoEntity gainfo) + { + var device = await DbContext.Queryable() + .Where(x => x.UniqueNo == request.DeviceUniqueNo) + .FirstAsync(); + + var registry = await DbContext.Queryable() + .Where(x => x.DeviceUniqueNo == request.DeviceUniqueNo) + .FirstAsync(); + + var businessPlaceInfo = await DbContext.Queryable() + .LeftJoin((x, sr) => x.Code == sr.PlaceCode) + .Where(x => x.Code == registry.BusinessPlaceCode) + .Select((x, sr) => new + { + x.Code, + sr.ShiftCode, + x.TenantId + }) + .FirstAsync(); + + + //获取当前消费餐次 + var shifts = await DbContext.Queryable().Where(x => x.ShiftCode == businessPlaceInfo.ShiftCode).ToListAsync(); + + var shift = shifts.FirstOrDefault(x => new TimePeriod() + { + Start = x.Start, + End = x.End + + }.IsPresent1(request.CostDateTime)); + + var switchTime = await GetSettingAsync(CanteenSettingItemEnumType.BusinessSwitchTime); + + var shiftTimePeriod = new TimePeriod() + { + Start = shift?.Start, + End = shift?.End + }; + + //计算成本日期 todo 优化 + var costDate = DateTime.Now; + if (shift == null) + { + costDate = DateTime.Now; + } + else + { + if (switchTime.HasValue) + { + var beginOfDay = DateTime.Today; + + var setTime = beginOfDay.Add(switchTime.Value.ToTimeSpan()); + if (DateTime.Now < setTime) + costDate = DateTime.Now.AddDays(-1); + } + } + + var order = new CanteenOrderEntity + { + RequestJson = request.ToJson(), + ThirdNo = request.ThirdNo, + Type = BalanceRecordTypeEnumType.Out, + ApplicationType = CanteenApplicaitonTypeEnumType.Device, + Name = gainfo.Name, + Source = request.Source, + UserNo = gainfo.No, + UserCode = gainfo.Code, + Amount = request.Amount, + BusinessPlaceCode = businessPlaceInfo?.Code, + BusinessShiftCode = shift?.ShiftCode, + ShiftType = shift?.ShiftType, + CostDate = costDate.Date, + CostId = gainfo.CostId, + DepartmentNo = gainfo.DepartmentNo, + DeviceUniqueNo = request.DeviceUniqueNo, + + No = SnowFlakeHelper.Instance.NextId().ToString(), + SubsidiesFromMonth = request.CostDateTime.ToString("yyyyMM"), + IsOffline = request.IsOffline, + IsCostCrossTenant = await GetSettingAsync(CanteenSettingItemEnumType.AllowCrossTenant), + + OriginTenantId = gainfo.Factory,//人员可能跨基地消费 + + //餐别异常处理 + Status = BalanceRecordStatusEnumType.Valid, + + OrderStatus = CanteenOrderStatusEnumType.Wait, + + CostDateTime = request.CostDateTime, + + //标识当前消费的基地 + TenantId = businessPlaceInfo.TenantId, + }; + + + var orderId = await DbContext.InsertReturnIdentityAsync(order); + + var allowNoBalance = await GetSettingAsync(CanteenSettingItemEnumType.AllowNoBalance); + + await CommonHelper.RetryAsync(async () => + { + if (!allowNoBalance) + { + var gainfoMeal = await DbContext.Queryable().Where(x => x.UserNo == order.UserNo).FirstAsync(); + //金额+- + gainfoMeal.Balance += order.Amount; + + await DbContext.Updateable() + .SetColumns(x => x.Balance == gainfoMeal.Balance) + .SetColumns(x => x.Version == x.Version + 1) + .Where(x => x.UserNo == order.UserNo && x.Version == gainfoMeal.Version)//必须与查询时的version一致 + .ExecuteCommandThrowVersionAsync(); + } + + //写入记录 + var balanceRecord = order.Adapt(); + await DbContext.InsertAsync(balanceRecord); + + }, 5); + } + /// /// 消费 /// @@ -166,7 +320,7 @@ public class OrderService : BaseOrderService, IOrderService UserNo = gainfo.No, UserCode = gainfo.Code, Amount = request.Amount, - BusinessPlaceCode = businessPlaceInfo.Code, + BusinessPlaceCode = businessPlaceInfo?.Code, BusinessShiftCode = shift?.ShiftCode, ShiftType = shift?.ShiftType, CostDate = costDate.Date,