using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Basic.Enums; using Dlhis.Entity.Visitor.Entity; using Dlhis.Entity.Visitor.Enums; using Dlhis.External.Appointment.Request; using Kurisu.AspNetCore.CustomClass; using Kurisu.AspNetCore.DataAccess.SqlSugar.Services; using Kurisu.AspNetCore.Utils; using Kurisu.AspNetCore.Utils.Extensions; using SqlSugar; namespace Dlhis.External.Appointment.Services.Implements; public class AppointmentService : IAppointmentService { private readonly IDbContext _dbContext; private readonly RedisCache _redisCache; public AppointmentService(IDbContext dbContext, RedisCache redisCache) { _dbContext = dbContext; _redisCache = redisCache; } public async Task ReceiveAsync(VisitorAppointmentReceiveRequest request) { var exists = await _dbContext.Queryable().Where(x => x.No == request.No).AnyAsync(); exists.ThrowIfTrue("已经存在申请"); var areas = await _dbContext.Queryable().Where(x => x.TenantId == request.Factory).ToListAsync(); var mst = new VisitorAppointmentEntity { No = request.No, Title = request.Title, Code = request.Code, Source = request.Source, Date = request.Date, Factory = request.Factory, Reason = request.Reason, Remark = request.Remark, }; await _dbContext.InsertAsync(mst); var invalids = new[] { GainfoUserTypeEnumType.Normal, GainfoUserTypeEnumType.SecurityWhite }; foreach (var item in request.Items) { if (item.IsEnterDoorArea && areas.Where(x => x.Type == AppointmentAreaEnumType.Door) .Select(x => x.CustomCode) .Contains(item.ApplyDoorArea) == false) { throw new UserFriendlyException($"门岗区域{item.ApplyDoorArea}无效"); } if (item.IsEnterWorkplace && item.ApplyWorkplaceAreas.All(p => areas.Where(x => x.Type == AppointmentAreaEnumType.Workplace) .Select(x => x.CustomCode) .Contains(p)) == false) { var workplaceAreas = areas.Where(x => x.Type == AppointmentAreaEnumType.Workplace).Select(x => x.CustomCode); var notExistsAreas = item.ApplyWorkplaceAreas.Where(x => !workplaceAreas.Contains(x)); throw new UserFriendlyException($"车间区域{notExistsAreas.Join(",")}无效"); } var gainfo = await _dbContext.Queryable().Where(x => x.IdNo == item.IdNo || x.Code == item.IdNo).SingleAsync(); //外部人员 if (gainfo == null) { gainfo = new GainfoEntity { No = Guid.NewGuid().ToString(), Code = await GetExternalCodeAsync(), Gender = GetGender(item.IdNo), Type = GainfoUserTypeEnumType.External, IdNo = item.IdNo, Name = item.Name, Source = request.Source, Phone = item.Phone, Factory = mst.Factory }; await _dbContext.InsertAsync(gainfo); } else { (invalids.Contains(gainfo.Type) && item.IsEnterDoorArea).ThrowIfTrue("内部人员无法发起门岗预约"); if (gainfo.Type == GainfoUserTypeEnumType.External) { gainfo.Source = request.Source; gainfo.Phone = item.Phone; gainfo.Factory = mst.Factory; await _dbContext.UpdateAsync(gainfo); } } var detail = new VisitorAppointmentDetailEntity { UserNo = gainfo.No, No = request.No, IdType = item.IdType, IdNo = item.IdNo, Name = item.Name, Phone = item.Phone, Remark = item.Remark, DoorStatus = item.IsEnterDoorArea && areas.Where(x => x.Type == AppointmentAreaEnumType.Door) .Select(x => x.CustomCode) .Contains(item.ApplyDoorArea) ? VisitorAppointmentDetailStatusEnumType.Wait : VisitorAppointmentDetailStatusEnumType.Obsolete, LicensePlate = item.LicensePlate, IsEnterDoorArea = item.IsEnterDoorArea, ApplyDoorArea = item.ApplyDoorArea, DoorStart = item.DoorStart, DoorEnd = item.DoorEnd, IsEnterWorkplace = item.IsEnterWorkplace, WorkplaceStatus = item.IsEnterWorkplace && item.ApplyWorkplaceAreas.All(p => areas.Where(x => x.Type == AppointmentAreaEnumType.Workplace) .Select(x => x.CustomCode) .Contains(p)) ? VisitorAppointmentDetailStatusEnumType.Wait : VisitorAppointmentDetailStatusEnumType.Obsolete, ApplyWorkplaceAreas = item.ApplyWorkplaceAreas, WorkplaceStart = item.WorkplaceStart, WorkplaceEnd = item.WorkplaceEnd, ImageUrl = item.ImageUrl }; await _dbContext.InsertAsync(detail); } } private GenderEnumType GetGender(string idNo) { try { if (idNo.Length == 18) { return int.Parse(idNo.ToCharArray()[16].ToString()) % 2 == 0 ? GenderEnumType.Female : GenderEnumType.Male; } } catch (Exception e) { } return GenderEnumType.Unknown; } private async Task GetExternalCodeAsync() { await using var handler = await _redisCache.LockAsync("gainfo:external:code-generate", expiry: TimeSpan.FromSeconds(3), retryInterval: TimeSpan.FromSeconds(1), retryCount: 3); handler.Acquired.ThrowIfFalse("生成虚拟工号失败"); int code; var entity = await _dbContext.Queryable() .Where(x => x.Type == GainfoUserTypeEnumType.External && x.Code.StartsWith("EXT")) .OrderBy(x => x.Id, OrderByType.Desc) .FirstAsync(); if (entity == null) { code = 1; } else { code = int.Parse(entity.Code.Replace("EXT", "").TrimStart('0')) + 1; } return "EXT" + code.ToString().PadLeft(6, '0'); } }