namespace SimpleAdmin.Application; /// /// 实现入职业务岗位业务能力。 /// public class OnboardingPositionService : DbRepository, IOnboardingPositionService { /// /// 分页查询入职业务岗位。 /// public async Task> Page(OnboardingPositionPageInput input) { var list = await Context.Queryable() .WhereIF(input.CompanyId.HasValue, it => it.CompanyId == input.CompanyId.Value) .WhereIF(input.DepartmentId.HasValue, it => it.DepartmentId == input.DepartmentId.Value) .WhereIF(!string.IsNullOrWhiteSpace(input.PositionCode), it => it.PositionCode.Contains(input.PositionCode)) .WhereIF(!string.IsNullOrWhiteSpace(input.PositionName), it => it.PositionName.Contains(input.PositionName)) .WhereIF(!string.IsNullOrWhiteSpace(input.Status), it => it.Status == input.Status) .OrderByIF(!string.IsNullOrWhiteSpace(input.SortField), $"{input.SortField} {input.SortOrder}") .OrderByDescending(it => it.CreateTime) .OrderBy(it => it.PositionName) .ToPagedListAsync(input.PageNum, input.PageSize); if (list.List != null && list.List.Any()) { var companyIds = list.List.Select(p => p.CompanyId).Distinct().ToList(); var departmentIds = list.List.Where(p => p.DepartmentId.HasValue).Select(p => p.DepartmentId.Value).Distinct().ToList(); var companies = await Context.Queryable() .Where(c => companyIds.Contains(c.Id)) .ToListAsync(); var departments = departmentIds.Count == 0 ? new List() : await Context.Queryable().Where(d => departmentIds.Contains(d.Id)).ToListAsync(); var companyMap = companies.ToDictionary(c => c.Id, c => c.CompanyName); var departmentMap = departments.ToDictionary(d => d.Id, d => d.DepartmentName); foreach (var item in list.List) { if (companyMap.TryGetValue(item.CompanyId, out var cName)) { item.CompanyName = cName; } if (item.DepartmentId.HasValue && departmentMap.TryGetValue(item.DepartmentId.Value, out var dName)) { item.DepartmentName = dName; } } } return list; } /// /// 查询指定公司下全部已启用岗位。 /// public Task> ListEnabled(long companyId) { return Context.Queryable() .Where(it => it.CompanyId == companyId && it.Status == "enable") .OrderBy(it => it.PositionName) .ToListAsync(); } /// /// 查询指定部门下全部已启用岗位。 /// public Task> ListEnabledByDepartment(long departmentId) { return Context.Queryable() .Where(it => it.DepartmentId == departmentId && it.Status == "enable") .OrderBy(it => it.PositionName) .ToListAsync(); } /// /// 查询岗位详情。 /// public async Task Detail(BaseIdInput input) { return await GetByIdAsync(input.Id) ?? throw Oops.Bah("岗位不存在"); } /// /// 新增入职业务岗位。 /// public async Task Add(OnboardingPositionAddInput input) { NormalizeInput(input); if (!input.DepartmentId.HasValue) throw Oops.Bah("请选择所属部门"); await EnsureCompanyExists(input.CompanyId); await EnsureDepartmentExists(input.CompanyId, input.DepartmentId.Value); await EnsureCodeUnique(input.CompanyId, input.PositionCode, 0); await InsertAsync(input.Adapt()); } /// /// 编辑入职业务岗位。 /// public async Task Edit(OnboardingPositionEditInput input) { NormalizeInput(input); if (!input.DepartmentId.HasValue) throw Oops.Bah("请选择所属部门"); var position = await Detail(new BaseIdInput { Id = input.Id }); await EnsureScopeCanChange(position, input.CompanyId, input.DepartmentId.Value); await EnsureCompanyExists(input.CompanyId); await EnsureDepartmentExists(input.CompanyId, input.DepartmentId.Value); await EnsureCodeUnique(input.CompanyId, input.PositionCode, input.Id); await UpdateAsync(input.Adapt()); } /// /// 删除未被任务或正式员工引用的岗位。 /// public async Task Delete(BaseIdListInput input) { if (input.Ids.Count == 0) return; var hasTasks = await Context.Queryable() .AnyAsync(it => input.Ids.Contains(it.PositionId)); if (hasTasks) throw Oops.Bah("岗位已有入职任务,不能删除"); var hasEmployees = await Context.Queryable() .AnyAsync(it => input.Ids.Contains(it.PositionId)); if (hasEmployees) throw Oops.Bah("岗位已有正式员工,不能删除"); var hasOnboardingTemplates = await Context.Queryable() .AnyAsync(item => input.Ids.Contains(item.PositionId)); if (hasOnboardingTemplates) throw Oops.Bah("岗位已被入职模板引用,不能删除"); var hasContractTemplates = await Context.Queryable() .AnyAsync(item => input.Ids.Contains(item.PositionId)); if (hasContractTemplates) throw Oops.Bah("岗位已被合同模板引用,不能删除"); await DeleteByIdsAsync(input.Ids.Cast().ToArray()); } private async Task EnsureCompanyExists(long companyId) { var exists = await Context.Queryable() .AnyAsync(it => it.Id == companyId && it.Status == "enable"); if (!exists) throw Oops.Bah("所属公司不存在、已删除或未启用"); } private async Task EnsureDepartmentExists(long companyId, long departmentId) { var exists = await Context.Queryable() .AnyAsync(it => it.Id == departmentId && it.CompanyId == companyId && it.Status == "enable"); if (!exists) throw Oops.Bah("所属部门不存在、未启用或不属于该公司"); } /// /// 标准化岗位输入并拒绝非法状态。 /// private static void NormalizeInput(OnboardingPositionAddInput input) { input.PositionCode = input.PositionCode?.Trim(); input.PositionName = input.PositionName?.Trim(); if (string.IsNullOrWhiteSpace(input.PositionCode) || string.IsNullOrWhiteSpace(input.PositionName)) { throw Oops.Bah("请填写岗位编码和岗位名称"); } if (input.Status != "enable" && input.Status != "disable") throw Oops.Bah("岗位状态不正确"); } /// /// 已被业务配置或历史数据引用的岗位不允许直接改变公司、部门归属。 /// private async Task EnsureScopeCanChange( ObPosition position, long companyId, long departmentId) { if (position.CompanyId == companyId && position.DepartmentId == departmentId) return; var hasTask = await Context.Queryable() .AnyAsync(item => item.PositionId == position.Id); var hasEmployee = await Context.Queryable() .AnyAsync(item => item.PositionId == position.Id); var hasOnboardingTemplate = await Context.Queryable() .AnyAsync(item => item.PositionId == position.Id); var hasContractTemplate = await Context.Queryable() .AnyAsync(item => item.PositionId == position.Id); if (hasTask || hasEmployee || hasOnboardingTemplate || hasContractTemplate) throw Oops.Bah("岗位已被模板、任务或员工引用,不能直接变更所属公司、部门"); } private async Task EnsureCodeUnique(long companyId, string code, long id) { var exists = await Context.Queryable() .AnyAsync(it => it.CompanyId == companyId && it.PositionCode == code && it.Id != id); if (exists) throw Oops.Bah("该公司下岗位编码已存在"); } }