using Dlhis.Basic.Organization.Request; using Dlhis.Basic.Organization.Response; using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Basic.Enums; using Dlhis.Scheduled.Api; using Dlhis.Scheduled.Api.Request; using Dlhis.Sys.Api; using Kurisu.AspNetCore.Authentication.Abstractions; using Kurisu.AspNetCore.DataAccess.Dto; using Kurisu.AspNetCore.DataAccess.SqlSugar.Extensions; using Kurisu.AspNetCore.DataAccess.SqlSugar.Services; using Kurisu.AspNetCore.Utils.Extensions; using Microsoft.AspNetCore.DataProtection; using SqlSugar; namespace Dlhis.Basic.Organization.Services.Implements; public class GainfoService : IGainfoService { private readonly IGainfoStore _gainfoStore; private readonly IDbContext _dbContext; private readonly IDataProtectionProvider _dataProtectionProvider; private readonly ICurrentUser _currentUser; private readonly ITenantApi _tenantApi; private readonly IHangfireApi _hangfireApi; private readonly IGainfoPermissionService _gainfoPermissionService; private readonly ILogger _logger; public GainfoService(IGainfoStore gainfoStore, IDbContext dbContext, IDataProtectionProvider dataProtectionProvider, ICurrentUser currentUser, ITenantApi tenantApi, IHangfireApi hangfireApi, IGainfoPermissionService gainfoPermissionService, ILogger logger) { _gainfoStore = gainfoStore; _dbContext = dbContext; _dataProtectionProvider = dataProtectionProvider; _currentUser = currentUser; _tenantApi = tenantApi; _hangfireApi = hangfireApi; _gainfoPermissionService = gainfoPermissionService; _logger = logger; } /// /// 档案分页 /// /// /// public async Task> GetPageAsync(GainfoPageRequest request) { var currentTenantId = _currentUser.GetStringTenantId(); //根据组织架构搜索档案 var where = LinqExpressionExtensions.False(); foreach (var item in request.DepartmentSelections) { var searchDepartments = await GetRecursionDepartmentNosAsync(item.DepartmentNos); where = searchDepartments.Any() ? where.Or(gainfo => gainfo.Factory == item.Tenant && searchDepartments.Contains(gainfo.DepartmentNo)) : where.Or(gainfo => gainfo.Factory == item.Tenant); } var page = await _gainfoStore.Queryable(request.Status) .WhereIF(request.DepartmentSelections.IsPresent(), where) .WhereIF(request.DepartmentSelections.IsEmpty(), gainfo => gainfo.Factory == currentTenantId) .WhereIF(request.IsOutsource.HasValue && request.IsOutsource.Value, gainfo => SqlFunc.Subqueryable().Where(x => x.Code == gainfo.Code).Any()) .WhereIF(request.IsOutsource.HasValue && !request.IsOutsource.Value, gainfo => SqlFunc.Subqueryable().Where(x => x.Code == gainfo.Code).NotAny()) .WhereIF(request.Search.IsPresent(), gainfo => gainfo.Name.Contains(request.Search) || gainfo.Code == request.Search || gainfo.IdNo == request.Search) .Select() .ToPageListAsync(request); return page; } public async Task> GetPageByCodeAsync(string code) { var page = await _gainfoStore.Queryable() .Where(x => x.Code == code) .Select() .ToPageListAsync(new PageDto { PageIndex = 1, PageSize = 1 }); var tenantsResult = await _tenantApi.GetTenantsInternalAsync(); var tenants = tenantsResult.Data; page.Data.ForEach(x => { x.Workplace = tenants.FirstOrDefault(item => item.Code == x.Workplace)?.Name; x.Factory = tenants.FirstOrDefault(item => item.Code == x.Factory)?.Name; }); return page; } public async Task CurrentUserInfoAsync() { var code = _currentUser.GetUserClaim("jinko-code"); if (code.IsEmpty()) { _logger.LogWarning("工号为空尝试获取人员信息"); return null; } var gainfo = await _gainfoStore.Queryable().Where(x => x.Code == code).SingleAsync(); if (gainfo == null) { //开启同步处理 await _hangfireApi.SyncSapPersonAsync(new SapNoRequest { Code = code }); return null; } var info = await _gainfoStore.Queryable(GainfoStatusEnumType.Working) .LeftJoin((ga, department) => ga.DepartmentNo == department.No) .LeftJoin((ga, department, mealUser) => ga.No == mealUser.UserNo) .Where((ga, department) => ga.Id == gainfo.Id) .Select((ga, department, mealUser) => new GainfoCurrentResponse { UserNo = ga.No, Birthday = ga.Birthday, DepartmentNo = department.No, DepartmentName = department.Name, Gender = ga.Gender, UserCode = ga.Code, UserName = ga.Name, Factory = ga.Factory, MealInfo = new GainfoCurrentMealInfoResponse { Balance = mealUser.Balance } }).SingleAsync(); if (info != null) { try { var tenantResult = await _tenantApi.GetTenantByCodeAsync(info.Factory); if (tenantResult is { Data: not null }) { info.Factory = tenantResult.Data.Name; } } catch (Exception) { // ignored } } return info; } public async Task CheckIdNoAndNameMatchAsync(GainfoCheckIdNoAndNameRequest request) { var match = await _gainfoStore.Queryable(GainfoStatusEnumType.External).AnyAsync(x => x.IdNo == request.IdNo && x.Name == request.Name); if (!match) { match = await _gainfoStore.Queryable(GainfoStatusEnumType.Working).AnyAsync(x => x.IdNo == request.IdNo && x.Name == request.Name); } match.ThrowIfFalse("验证失败!"); var protector = _dataProtectionProvider.CreateProtector("gainfo:external:idno"); return protector.Protect(request.IdNo); } public async Task ResignAsync(GainfoResignRequest request) { var gainfo = await _dbContext.Queryable().FirstAsync(x => x.Id == request.Id); gainfo.ThrowIfNull("档案数据不存在"); if (request.IsOutsource) { var outsource = await _dbContext.Queryable().FirstAsync(x => x.Code == gainfo.Code); (outsource == null).ThrowIfTrue("非外包人员不可手动离职"); } await _gainfoPermissionService.ResetPermissionsAsync(new GainfoPermissionResetRequest { UserNo = gainfo.No, IsLeave = true }); //先写入离职表 gainfo.IdentityUserId = (int)gainfo.Id; //记录原始id gainfo.ResignationDate = request.Date; gainfo.Remark = request.Reason; gainfo.Id = 0; if (!await _dbContext.Queryable().AS("GainfoLeave").AnyAsync(x => x.Code == gainfo.Code)) { await _dbContext.Client.Insertable(gainfo).AS("GainfoLeave").ExecuteCommandAsync(); } gainfo.Id = gainfo.IdentityUserId; await _dbContext.DeleteReallyAsync(gainfo); } /// /// 档案列表 /// /// /// public async Task> GetGainfoListAsync(GainfoListRequest request) { var page = await _gainfoStore.Queryable(request.Status) .LeftJoin((ga, de) => ga.DepartmentNo == de.No) .WhereIF(!request.Name.IsEmpty(), ga => ga.Name == request.Name) .WhereIF(!request.IdNo.IsEmpty(), ga => ga.IdNo == request.IdNo) .WhereIF(!request.DepartmentNo.IsEmpty(), ga => ga.DepartmentNo == request.DepartmentNo) .WhereIF(!request.Code.IsEmpty(), ga => ga.Code == request.Code) .Select((ga, de) => new GainfoListResponse { No = ga.No, Name = ga.Name, Code = ga.Code, IdNo = ga.IdNo, Gender = ga.Gender, Phone = ga.Phone, DepartmentNo = de.No, DepartmentName = de.Name, Address = ga.Address, }).ToPageListAsync(request); return page; } /// /// 档案详情 /// /// /// public async Task GetGainfoDetailAsync(GainfoDetailRequest request) { var info = await _gainfoStore.Queryable(request.Status) .LeftJoin((ga, de) => ga.DepartmentNo == de.No) .LeftJoin((ga, de, pos) => ga.PositionNo == pos.No) .Where(ga => ga.No == request.No) .Select((ga, de, pos) => new GainfoDetailResponse { No = ga.No, SapNo = ga.SapNo, Name = ga.Name, Code = ga.Code, IdClass = ga.IdClass, IdNo = ga.IdNo, Gender = ga.Gender, Address = ga.Address, Birthday = ga.Birthday, Phone = ga.Phone, Grade = ga.Grade, Title = ga.Title, Degree = ga.Degree, Werks = ga.Werks, CostId = ga.CostId, NativeName = ga.Native, CountryName = ga.CountryNo, NationName = ga.Nation, ClassName = ga.IdClass, EntryDate = ga.EntryDate, Workplace = ga.Workplace, Factory = ga.Factory, DepartmentName = de.Name, Position = pos.Name, }) .SingleAsync(); if (info != null) { var searchTypes = new List() { "native", "country", "nation", "cls" }; var types = await _dbContext.Queryable().Where(x => searchTypes.Contains(x.Type)).ToListAsync(); info.NativeName = types.Where(x => x.Type == "native").FirstOrDefault(x => x.Code == info.NativeName)?.Display; info.CountryName = types.Where(x => x.Type == "country").FirstOrDefault(x => x.Code == info.CountryName)?.Display ?? "中国"; info.NationName = types.Where(x => x.Type == "nation").FirstOrDefault(x => x.Code == info.NationName)?.Display; info.ClassName = types.Where(x => x.Type == "cls").FirstOrDefault(x => x.Code == info.ClassName)?.Display ?? "身份证"; if (request.WithFace) { info.Face = await _dbContext.ChangeDb("face").Queryable().Where(x => x.UserCode == info.Code).Select(x => x.Face).SingleAsync(); } try { var tenantsResult = await _tenantApi.GetTenantsInternalAsync(); var tenants = tenantsResult.Data; info.Workplace = tenants.FirstOrDefault(x => x.Code == info.Workplace)?.Name; info.Factory = tenants.FirstOrDefault(x => x.Code == info.Factory)?.Name; } catch (Exception) { } } return info; } public async Task MigrationAsync(MigrationRequest request) { //档案数据 var gainfo = await _gainfoStore.Queryable().Where(x => x.Code == request.Code).FirstAsync(); if (gainfo == null) { return; } //卡号为空则更新 if (gainfo.CardNo.IsEmpty()) { gainfo.CardNo = request.CardNo; await _gainfoStore.UpdateAsync(gainfo); } //外部传入人脸 if (request.Face.IsPresent()) { var faceDbContext = _dbContext.ChangeDb("face"); var exists = await faceDbContext.Queryable().AnyAsync(x => x.UserCode == gainfo.Code); //人脸不存在则写入 if (!exists) { await faceDbContext.InsertAsync(new GainfoFaceEntity { CreatedBy = 1, CreateTime = DateTime.Now, ModifiedBy = 1, ModifiedTime = DateTime.Now, UserCode = gainfo.Code, Face = request.Face, }); } } } //-------------------------------------------help methods ------------------------------------------------ /// /// 递归获取部门No /// /// /// private async Task> GetRecursionDepartmentNosAsync(List departmentNos) { if (departmentNos.IsEmpty()) { return new List(); } var departments = await _dbContext.Queryable().ToListAsync(); var currentNos = departments.Where(x => departmentNos.Contains(x.No)).ToList(); foreach (var item in currentNos) { RecursionGetNext(item.No, departments, departmentNos); } return departmentNos.Distinct().ToList(); //local method void RecursionGetNext(string currentNo, List departments, List result) { var next = departments.Where(x => x.PNo == currentNo).ToList(); foreach (var item in next) { result.Add(item.No); RecursionGetNext(item.No, departments, result); } } } }