fix 离线数据处理

This commit is contained in:
2024-04-07 19:02:09 +08:00
parent e88caccaa5
commit 11ac3c5742
2 changed files with 170 additions and 15 deletions

View File

@@ -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<OrderService> logger)
: base(canteenSettingService, dbContext, currentUser, devicePermissionApi, logger)
{
_redisCache = redisCache;
}
public async Task<DefaultApiResult<OrderResultResponse>> 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<GainfoMealEntity>().Where(x => x.UserNo == gainfo.No).AnyAsync()).ThrowIfFalse("余额不足,无法消费");
//消费
if (request.Type == BalanceRecordTypeEnumType.Out)
if (request.IsOffline)
{
if (request.ThirdNo.IsPresent())
{
await ConsumeAsync(request.Adapt<ConsumeRequest>(), gainfo);
using (var handler = await _redisCache.LockAsync($"consume:device:{request.ThirdNo}"))
{
if (handler.Acquired)
{
try
{
await HandleOfflineAsync(request.Adapt<ConsumeRequest>(), gainfo);
}
catch (Exception ex)
{
Logger.LogError(ex, "离线入库错误:{message}", ex.Message);
}
}
}
}
//充值
else
{
await RechargeAsync(request.Adapt<RechargeRequest>(), gainfo);
await HandleOfflineAsync(request.Adapt<ConsumeRequest>(), gainfo);
}
}
catch (Exception ex)
else
{
message = ex.Message;
gainfo.ThrowIfNull($"无消费权限");
await CheckPermissionAsync(gainfo.No, request.DeviceUniqueNo);
try
{
(await DbContext.Queryable<GainfoMealEntity>().Where(x => x.UserNo == gainfo.No).AnyAsync()).ThrowIfFalse("余额不足,无法消费");
//消费
if (request.Type == BalanceRecordTypeEnumType.Out)
{
await ConsumeAsync(request.Adapt<ConsumeRequest>(), gainfo);
}
//充值
else
{
await RechargeAsync(request.Adapt<RechargeRequest>(), 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<DeviceEntity>()
.Where(x => x.UniqueNo == request.DeviceUniqueNo)
.FirstAsync();
var registry = await DbContext.Queryable<DeviceRegistryEntity>()
.Where(x => x.DeviceUniqueNo == request.DeviceUniqueNo)
.FirstAsync();
var businessPlaceInfo = await DbContext.Queryable<BusinessPlaceEntity>()
.LeftJoin<BusinessPlaceShiftRelationshipEntity>((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<BusinessShiftMealRelationshipEntity>().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<TimeOnly?>(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<bool>(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<bool>(CanteenSettingItemEnumType.AllowNoBalance);
await CommonHelper.RetryAsync(async () =>
{
if (!allowNoBalance)
{
var gainfoMeal = await DbContext.Queryable<GainfoMealEntity>().Where(x => x.UserNo == order.UserNo).FirstAsync();
//金额+-
gainfoMeal.Balance += order.Amount;
await DbContext.Updateable<GainfoMealEntity>()
.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<BalanceRecordEntity>();
await DbContext.InsertAsync(balanceRecord);
}, 5);
}
/// <summary>
/// 消费
/// </summary>
@@ -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,