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.EMealVoucher; 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.EMealVoucher))] public class EMealVoucherHandler : IConsumeHandler { private readonly IDbContext _dbContext; private readonly IOrderRepository _orderRepository; private readonly IOrderCommonHandler _orderCommonHandler; public EMealVoucherHandler(IDbContext dbContext, IOrderRepository orderRepository, IOrderCommonHandler orderCommonHandler) { _dbContext = dbContext; _orderRepository = orderRepository; _orderCommonHandler = orderCommonHandler; } public async Task> ConsumeAsync(OrderAddRequest request, GainfoEntity gainfo) { var msg = string.Empty; var originData = await _dbContext.Queryable() .Where(x => x.QrCode == request.UserUniqueNo) .Select(x => x.OriginData) .SingleAsync(); if (originData.IsEmpty()) { msg = "无法识别"; return new DefaultApiResult { Code = ApiStateCode.Error, Data = null, Msg = msg }; } var originDataItems = originData.Split(":"); var no = originDataItems[0]; var idNo = originDataItems[3]; try { await EMealVoucherConsumeAsync(request.Adapt(), gainfo, originData, no, idNo); } catch (Exception ex) { msg = ex.Message; } //获取餐券余额 var data = await _dbContext.Queryable() .LeftJoin((x, d) => x.No == d.No) .Where((x, d) => x.No == no && d.IdNo == idNo) .Select((x, d) => new OrderResultResponse { UserCode = d.IdNo, UserName = d.Name, CurrentBalance = d.Balance }) .SingleAsync(); try { var v = data.UserCode ?? string.Empty; var vc = v.ToCharArray().Reverse().ToList(); for (int i = 0; i < vc.Count; i++) { if (i + 1 > 4) { vc[i] = '*'; } } vc.Reverse(); data.UserCode = string.Join("", vc); } catch (Exception) { //ignore } return new DefaultApiResult { Code = msg.IsPresent() ? ApiStateCode.Error : ApiStateCode.Success, Data = data, Msg = msg }; } /// /// 电子餐券消费 /// /// /// /// /// /// private async Task EMealVoucherConsumeAsync(ConsumeRequest request, GainfoEntity gainfo, string originData, string no, string idNo) { var now = DateTime.Now; var current = await _dbContext.Queryable() .Where(x => x.No == no && x.IdNo == idNo) .Select(x => new { x.Name, x.Start, x.End }) .SingleAsync(); (now >= current.Start && now <= current.End).ThrowIfFalse("餐券已过期"); var eMealVoucher = await _dbContext.Queryable().Where(x => x.No == no).SingleAsync(); var checkData = await _orderCommonHandler.PreCheckAsync(request.DeviceUniqueNo, request.CostDateTime); var isSupermarket = await _dbContext.Queryable() .Where(x => x.Code == checkData.BusinessPlaceCode) .Select(x => x.Catalog == CanteenBusinessPlaceCatalogEnumType.Supermarket) .SingleAsync(); isSupermarket.ThrowIfTrue("禁止在超市消费"); eMealVoucher.Factories.Contains(checkData.Factory).ThrowIfFalse("禁止在当前厂区消费"); gainfo.No = originData; var order = await _orderRepository.CreateDeviceConsumeOrderAsync(checkData, request, gainfo); await _orderCommonHandler.TryConsumeAsync(order.Id, async () => { await CommonHelper.RetryAsync(async () => { var detail = await _dbContext.Queryable().Where(x => x.No == no && x.IdNo == idNo).SingleAsync(); //金额+- detail.Balance += order.Amount; (detail.Balance < 0).ThrowIfTrue("余额不足,无法消费"); await _dbContext.Updateable() .SetColumns(x => x.Balance == detail.Balance) .SetColumns(x => x.Version == x.Version + 1) .SetColumns(x => x.ModifiedTime == DateTime.Now) .Where(x => x.No == no && x.IdNo == idNo && x.Version == detail.Version) //必须与查询时的version一致 .ExecuteCommandThrowVersionAsync(); //写入记录 var balanceRecord = order.Adapt(); balanceRecord.Remark = $"({no})" + current.Name; await _dbContext.InsertAsync(balanceRecord); }, 5); }); } }