using Dlhis.Basic.Api; using Dlhis.Canteen.Order.Repository; using Dlhis.Canteen.Order.Request; using Dlhis.Canteen.Order.Response; using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Canteen.Entities; using Dlhis.Entity.Canteen.Entities.Voucher; using Dlhis.Entity.Canteen.Enums; using Kurisu.AspNetCore.DataAccess.SqlSugar.Extensions; using Kurisu.AspNetCore.DataAccess.SqlSugar.Services; using Kurisu.AspNetCore.UnifyResultAndValidation; using Kurisu.AspNetCore.Utils; using Kurisu.AspNetCore.Utils.Extensions; using Mapster; namespace Dlhis.Canteen.Order.Services.ConsumeHandlers; /// /// 生日券消费处理 /// [Service(nameof(BalanceRecordSourceEnumType.Birthday))] public class BirthdayConsumeHandler : IConsumeHandler { private readonly IDbContext _dbContext; private readonly IOrderCommonHandler _orderCommonHandler; private readonly IOrderRepository _orderRepository; private readonly IFactorySettingApi _factorySettingApi; public BirthdayConsumeHandler(IDbContext dbContext, IOrderCommonHandler orderCommonHandler, IOrderRepository orderRepository, IFactorySettingApi factorySettingApi) { _dbContext = dbContext; _orderCommonHandler = orderCommonHandler; _orderRepository = orderRepository; _factorySettingApi = factorySettingApi; } public async Task> ConsumeAsync(OrderAddRequest request, GainfoEntity gainfo) { var msg = string.Empty; var qrCode = request.UserUniqueNo; var voucherQrCode = await _dbContext.Queryable() .LeftJoin((x, u) => x.VoucherNo == u.VoucherNo) .Where(x => x.QrCode == qrCode) .Select((x, u) => new { x.VoucherNo, u.UserCode, u.Factory }) .SingleAsync(); voucherQrCode.ThrowIfNull("生日券无效"); try { var checkData = await _orderCommonHandler.PreCheckAsync(request.DeviceUniqueNo, request.CostDateTime!.Value); var businessPlace = await _dbContext.Queryable() .Where(x => x.Code == checkData.BusinessPlaceCode) //.Select(x => x.Catalog == CanteenBusinessPlaceCatalogEnumType.Supermarket) .SingleAsync(); businessPlace.ThrowIfNull("营业点不存在"); var isSupermarket = businessPlace.Catalog == CanteenBusinessPlaceCatalogEnumType.Supermarket; isSupermarket.ThrowIfFalse("请在超市消费"); var allowFactories = await _factorySettingApi.GetEnableUseBirthdayVoucherFactoriesAsync(voucherQrCode.Factory); allowFactories.Contains(businessPlace.TenantId).ThrowIfFalse($"该厂区({businessPlace.TenantId})不可使用此生日券"); var order = await _orderRepository.CreateDeviceConsumeOrderAsync(checkData, request.Adapt(), gainfo); await _orderCommonHandler.TryConsumeAsync(order.Id, async () => { await CommonHelper.RetryAsync(async () => { var voucher = await _dbContext.Queryable() .Where(x => x.Type == VoucherEnumType.Birthday) .Where(x => x.No == voucherQrCode.VoucherNo) .SingleAsync(); //金额+- voucher.Balance += order.Amount; (voucher.Balance < 0).ThrowIfTrue("余额不足,无法消费"); await _dbContext.Updateable() .SetColumns(x => x.Balance == voucher.Balance) .SetColumns(x => x.Version == x.Version + 1) .SetColumns(x => x.ModifiedTime == DateTime.Now) .Where(x => x.No == voucher.No && x.Version == voucher.Version) //必须与查询时的version一致 .ExecuteCommandThrowVersionAsync(); //写入记录 var balanceRecord = order.Adapt(); balanceRecord.Remark = $"{voucher.No}(生日券消费)"; await _dbContext.InsertAsync(balanceRecord); }, 5); }); } catch (Exception ex) { msg = ex.Message; } //获取餐券余额 var data = await _dbContext.Queryable() .LeftJoin((x, u) => x.No == u.VoucherNo) .LeftJoin((x, u, ga) => u.UserCode == ga.Code) .Where(x => x.Type == VoucherEnumType.Birthday && x.No == voucherQrCode.VoucherNo) .Select((x, u, ga) => new OrderResultResponse { UserCode = u.UserCode, UserName = ga.Name, CurrentBalance = x.Balance }) .SingleAsync(); return new DefaultApiResult { Code = msg.IsPresent() ? ApiStateCode.Error : ApiStateCode.Success, Data = data, Msg = msg }; } }