|
|
@@ -0,0 +1,381 @@
|
|
|
+using AutoMapper;
|
|
|
+using OASystem.Domain.Entities.PersonnelModule;
|
|
|
+using OASystem.Domain.ViewModels.PersonnelModule;
|
|
|
+using OASystem.Infrastructure.Repositories.System;
|
|
|
+
|
|
|
+namespace OASystem.Infrastructure.Repositories.PersonnelModule
|
|
|
+{
|
|
|
+ /// <summary>
|
|
|
+ /// 公司日常KPI考核仓储
|
|
|
+ /// </summary>
|
|
|
+ public class CompanyDailyKpiRepository : BaseRepository<Pm_CompanyDailyKpi, Pm_CompanyDailyKpi>
|
|
|
+ {
|
|
|
+ private readonly IMapper _mapper;
|
|
|
+ private JsonView _jv;
|
|
|
+ public CompanyDailyKpiRepository(SqlSugarClient sqlSugar,
|
|
|
+ IMapper mapper,
|
|
|
+ ApprovalProcessRepository approvalProcessRep)
|
|
|
+ : base(sqlSugar)
|
|
|
+ {
|
|
|
+ _mapper = mapper;
|
|
|
+ _jv = new JsonView() { Code = StatusCodes.Status400BadRequest, Msg = "操作失败!" };
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 绩效模板数据(保持原方法签名)
|
|
|
+ /// </summary>
|
|
|
+ public async Task<(bool isSuccess, string msg, List<KpiTempTypeInfo> data)> KpiTemplateDataAsync(string depName, string jobName)
|
|
|
+ {
|
|
|
+ var result = new List<KpiTempTypeInfo>();
|
|
|
+ // 获取配置
|
|
|
+ var config = await _sqlSugar.Queryable<Sys_SetDataType>()
|
|
|
+ .Where(x => x.IsDel == 0 && x.Id == 132)
|
|
|
+ .FirstAsync();
|
|
|
+
|
|
|
+ if (config?.Remark == null)
|
|
|
+ return (false, "绩效考核-数据类型ID存储为空", result);
|
|
|
+
|
|
|
+ var typeIds = JsonSerializer.Deserialize<List<int>>(config.Remark);
|
|
|
+ if (typeIds?.Any() != true)
|
|
|
+ return (false, "绩效考核-数据类型ID存储为空", result);
|
|
|
+
|
|
|
+ // 构建查询
|
|
|
+ var query = _sqlSugar.Queryable<Sys_SetData>()
|
|
|
+ .LeftJoin<Sys_SetDataType>((sd, sdt) => sd.STid == sdt.Id)
|
|
|
+ .Where((sd, sdt) => sd.IsDel == 0 && typeIds.Contains(sd.STid));
|
|
|
+
|
|
|
+ // 条件过滤
|
|
|
+ if (!string.IsNullOrWhiteSpace(depName))
|
|
|
+ query = query.Where((sd, sdt) => sdt.Name.Contains(depName));
|
|
|
+
|
|
|
+ if (!string.IsNullOrWhiteSpace(jobName))
|
|
|
+ query = query.Where((sd, sdt) => sdt.Name.Contains(jobName));
|
|
|
+
|
|
|
+ // 查询数据
|
|
|
+ var data = await query
|
|
|
+ .Select((sd, sdt) => new
|
|
|
+ {
|
|
|
+ KpiTypeId = sd.STid,
|
|
|
+ KpiTypeName = sdt.Name,
|
|
|
+ KpiId = sd.Id,
|
|
|
+ KpiContent = sd.Remark,
|
|
|
+ KpiSort = sd.Name
|
|
|
+ })
|
|
|
+ .ToListAsync();
|
|
|
+
|
|
|
+ if (data?.Any() != true)
|
|
|
+ return (false, "绩效考核模板信息为空", result);
|
|
|
+
|
|
|
+ // 分组处理
|
|
|
+ result = data
|
|
|
+ .GroupBy(x => new { x.KpiTypeId, x.KpiTypeName })
|
|
|
+ .Select(g => new KpiTempTypeInfo()
|
|
|
+ {
|
|
|
+ TypeId = g.Key.KpiTypeId,
|
|
|
+ TypeName = g.Key.KpiTypeName,
|
|
|
+ Contents = g
|
|
|
+ .OrderBy(x => int.TryParse(x.KpiSort, out int s) ? s : int.MaxValue)
|
|
|
+ .ThenBy(x => x.KpiSort)
|
|
|
+ .Select(x => new KpiTempContentInfo(x.KpiId, x.KpiContent, x.KpiSort))
|
|
|
+ .ToList()
|
|
|
+ })
|
|
|
+ .Where(g => g.Contents.Any())
|
|
|
+ .OrderBy(g => g.TypeId)
|
|
|
+ .ToList();
|
|
|
+
|
|
|
+ return (true, "操作成功", result);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取部门和岗位
|
|
|
+ /// </summary>
|
|
|
+ public async Task<object> KpiDepartmentsAndJobs()
|
|
|
+ {
|
|
|
+ var config = await _sqlSugar.Queryable<Sys_SetDataType>()
|
|
|
+ .Where(x => x.IsDel == 0 && x.Id == 132)
|
|
|
+ .FirstAsync();
|
|
|
+
|
|
|
+ if (config == null) return new { Success = false, Message = "配置为空" };
|
|
|
+
|
|
|
+ var typeIds = JsonSerializer.Deserialize<List<int>>(config.Remark ?? "[]");
|
|
|
+ if (typeIds == null || typeIds.Count < 1)
|
|
|
+ return new { Success = false, Message = "类型ID为空" };
|
|
|
+
|
|
|
+ var names = await _sqlSugar.Queryable<Sys_SetData>()
|
|
|
+ .LeftJoin<Sys_SetDataType>((sd, sdt) => sd.STid == sdt.Id)
|
|
|
+ .Where((sd, sdt) => sd.IsDel == 0 && typeIds.Contains(sd.STid))
|
|
|
+ .Select((sd, sdt) => sdt.Name)
|
|
|
+ .Distinct()
|
|
|
+ .ToListAsync();
|
|
|
+
|
|
|
+ // 解析部门和岗位
|
|
|
+ var deptJobList = names
|
|
|
+ .Select(name =>
|
|
|
+ {
|
|
|
+ var clean = name.Split('(')[0].Trim();
|
|
|
+ string dept, job;
|
|
|
+
|
|
|
+ if (clean.Contains(" - "))
|
|
|
+ {
|
|
|
+ var parts = clean.Split(" - ");
|
|
|
+ dept = parts[0].EndsWith("部") ? parts[0] : parts[0] + "部";
|
|
|
+ job = parts.Length > 1 ? parts[1] : "通用";
|
|
|
+ }
|
|
|
+ else if (clean.Contains("-"))
|
|
|
+ {
|
|
|
+ var parts = clean.Split('-');
|
|
|
+ dept = parts[0].EndsWith("部") ? parts[0] : parts[0] + "部";
|
|
|
+ job = parts.Length > 1 ? parts[1] : "通用";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ dept = clean.EndsWith("部") ? clean : "未分类";
|
|
|
+ job = clean.EndsWith("部") ? "通用" : clean;
|
|
|
+ }
|
|
|
+
|
|
|
+ return new { Department = dept, Job = job };
|
|
|
+ })
|
|
|
+ .Where(x => x.Department != "未分类")
|
|
|
+ .GroupBy(x => x.Department)
|
|
|
+ .Select(g => new
|
|
|
+ {
|
|
|
+ Department = g.Key,
|
|
|
+ Jobs = g.Select(x => x.Job).Distinct().Where(j => j != "通用").OrderBy(j => j).ToList()
|
|
|
+ })
|
|
|
+ .OrderBy(g => g.Department)
|
|
|
+ .ToList();
|
|
|
+
|
|
|
+ return new
|
|
|
+ {
|
|
|
+ Success = true,
|
|
|
+ Departments = deptJobList.Select(g => g.Department).ToList(),
|
|
|
+ DepartmentsWithJobs = deptJobList
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ #region 财务部日常绩效
|
|
|
+ /// <summary>
|
|
|
+ /// 基础数据
|
|
|
+ /// </summary>
|
|
|
+ /// <returns></returns>
|
|
|
+ public async Task<JsonView> FinanceInit()
|
|
|
+ {
|
|
|
+ var userInfos = await _sqlSugar.Queryable<Sys_Users>()
|
|
|
+ .LeftJoin<Sys_JobPost>((u, jp) => u.JobPostId == jp.Id)
|
|
|
+ .LeftJoin<Sys_Department>((u, jp, d) => u.DepId == d.Id)
|
|
|
+ .LeftJoin<Sys_Company>((u, jp, d, c) => u.CompanyId == c.Id)
|
|
|
+ .Where((u, jp, d, c) => u.IsDel == 0)
|
|
|
+ .Select((u, jp, d, c) => new
|
|
|
+ {
|
|
|
+ UserId = u.Id,
|
|
|
+ u.CompanyId,
|
|
|
+ c.CompanyName,
|
|
|
+ u.DepId,
|
|
|
+ d.DepName,
|
|
|
+ u.JobPostId,
|
|
|
+ jp.JobName,
|
|
|
+ UserName = u.CnName
|
|
|
+ })
|
|
|
+ .OrderBy(u => u.CompanyId)
|
|
|
+ .ToListAsync();
|
|
|
+
|
|
|
+ if (userInfos?.Any() != true)
|
|
|
+ {
|
|
|
+ _jv.Code = StatusCodes.Status200OK;
|
|
|
+ _jv.Msg = $"暂无人员数据";
|
|
|
+ return _jv;
|
|
|
+ }
|
|
|
+
|
|
|
+ //转换为层级结构
|
|
|
+ #region 层级转换 公司 -> 部门 -> 岗位 -> 人员
|
|
|
+ //var result = userInfos
|
|
|
+ // .GroupBy(u => new { u.CompanyId, u.CompanyName })
|
|
|
+ // .Select(companyGroup => new
|
|
|
+ // {
|
|
|
+ // CompanyId = companyGroup.Key.CompanyId,
|
|
|
+ // CompanyName = companyGroup.Key.CompanyName,
|
|
|
+ // Departments = companyGroup
|
|
|
+ // .GroupBy(u => new { u.DepId, u.DepName })
|
|
|
+ // .Select(departmentGroup => new
|
|
|
+ // {
|
|
|
+ // DepId = departmentGroup.Key.DepId,
|
|
|
+ // DepartmentName = departmentGroup.Key.DepName,
|
|
|
+ // JobPosts = departmentGroup
|
|
|
+ // .GroupBy(u => new { u.JobPostId, u.JobName })
|
|
|
+ // .Select(jobGroup => new
|
|
|
+ // {
|
|
|
+ // JobPostId = jobGroup.Key.JobPostId,
|
|
|
+ // JobName = jobGroup.Key.JobName,
|
|
|
+ // Employees = jobGroup
|
|
|
+ // .Select(u => new
|
|
|
+ // {
|
|
|
+ // Id = u.UserId,
|
|
|
+ // UserName = u.UserName,
|
|
|
+ // })
|
|
|
+ // .OrderBy(e => e.UserName)
|
|
|
+ // .ToList()
|
|
|
+ // })
|
|
|
+ // .OrderBy(j => j.JobName)
|
|
|
+ // .ToList()
|
|
|
+ // })
|
|
|
+ // .OrderBy(d => d.DepartmentName)
|
|
|
+ // .ToList()
|
|
|
+ // })
|
|
|
+ // .OrderBy(c => c.CompanyName)
|
|
|
+ // .ToList();
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ //转换为层级结构
|
|
|
+ #region 层级转换 公司 -> 部门 -> 人员
|
|
|
+ // 构建树形结构
|
|
|
+ var result = userInfos
|
|
|
+ .GroupBy(u => new { u.CompanyId, u.CompanyName })
|
|
|
+ .Select(companyGroup => new
|
|
|
+ {
|
|
|
+ CompanyId = companyGroup.Key.CompanyId,
|
|
|
+ CompanyName = companyGroup.Key.CompanyName,
|
|
|
+ Departments = companyGroup
|
|
|
+ .GroupBy(u => new { u.DepId, u.DepName })
|
|
|
+ .Where(deptGroup => deptGroup.Key.DepId > 0) // 过滤掉无部门的人员
|
|
|
+ .Select(deptGroup => new
|
|
|
+ {
|
|
|
+ DepartmentId = deptGroup.Key.DepId,
|
|
|
+ DepartmentName = deptGroup.Key.DepName,
|
|
|
+ Users = deptGroup
|
|
|
+ .Select(u => new
|
|
|
+ {
|
|
|
+ u.UserId,
|
|
|
+ u.UserName,
|
|
|
+ u.JobPostId,
|
|
|
+ u.JobName
|
|
|
+ })
|
|
|
+ .OrderBy(u => u.UserName)
|
|
|
+ .ToList()
|
|
|
+ })
|
|
|
+ .Where(dept => dept.Users.Any())
|
|
|
+ .OrderBy(dept => dept.DepartmentName)
|
|
|
+ .ToList(),
|
|
|
+ // 无部门的人员(直接挂载到公司下)
|
|
|
+ NoDepartmentUsers = companyGroup
|
|
|
+ .Where(u => u.DepId <= 0)
|
|
|
+ .Select(u => new
|
|
|
+ {
|
|
|
+ u.UserId,
|
|
|
+ u.UserName,
|
|
|
+ u.JobPostId,
|
|
|
+ u.JobName
|
|
|
+ })
|
|
|
+ .OrderBy(u => u.UserName)
|
|
|
+ .ToList()
|
|
|
+ })
|
|
|
+ .OrderBy(c => c.CompanyName)
|
|
|
+ .ToList();
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ _jv.Code = StatusCodes.Status200OK;
|
|
|
+ _jv.Data = result;
|
|
|
+ _jv.Msg = $"操作成功";
|
|
|
+ return _jv;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 日常考勤详情
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="month">月份 2025-12</param>
|
|
|
+ /// <param name="userId">考核人</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public async Task<JsonView> FinanceInfo(string month, int evaluator)
|
|
|
+ {
|
|
|
+ if (string.IsNullOrEmpty(month))
|
|
|
+ {
|
|
|
+ _jv.Msg = $"请选择月份!";
|
|
|
+ return _jv;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 格式:2025-11
|
|
|
+ const string pattern = @"^(\d{4})-(0[1-9]|1[0-2])$";
|
|
|
+ if (!Regex.IsMatch(month, pattern))
|
|
|
+ {
|
|
|
+ _jv.Msg = $"请选择正确的月份!格式:2025-12";
|
|
|
+ return _jv;
|
|
|
+ }
|
|
|
+ var evaluatorInfo = await _sqlSugar.Queryable<Sys_Users>()
|
|
|
+ .LeftJoin<Sys_Company>((u, c) => u.CompanyId == c.Id)
|
|
|
+ .LeftJoin<Sys_Department>((u, c, d) => u.DepId == d.Id)
|
|
|
+ .LeftJoin<Sys_JobPost>((u, c, d, jp) => u.JobPostId == d.Id)
|
|
|
+ .Where((u, c, d, jp) => u.IsDel == 0)
|
|
|
+ .Select((u, c, d, jp) => new
|
|
|
+ {
|
|
|
+ UserId = u.Id,
|
|
|
+ u.CompanyId,
|
|
|
+ c.CompanyName,
|
|
|
+ u.DepId,
|
|
|
+ d.DepName,
|
|
|
+ u.JobPostId,
|
|
|
+ jp.JobName,
|
|
|
+ UserName = u.CnName
|
|
|
+ })
|
|
|
+ .FirstAsync();
|
|
|
+ if (evaluatorInfo == null)
|
|
|
+ {
|
|
|
+ _jv.Msg = $"请选择有效的考核人!";
|
|
|
+ return _jv;
|
|
|
+ }
|
|
|
+
|
|
|
+ var info = await _sqlSugar
|
|
|
+ .Queryable<Pm_CompanyDailyKpi>()
|
|
|
+ .LeftJoin<Sys_SetData>((cdk, sd) => cdk.EvalContent == sd.Id)
|
|
|
+ .LeftJoin<Sys_Users>((cdk, sd, u) => cdk.Evaluator == u.Id)
|
|
|
+ .Where((cdk, sd, u) => cdk.IsDel == 0 && cdk.Evaluator == evaluator && cdk.Month.Equals(month))
|
|
|
+ .Select((cdk, sd, u) => new CompanyDailyKpiView()
|
|
|
+ {
|
|
|
+ Id = cdk.Id,
|
|
|
+ Month = cdk.Month,
|
|
|
+ EvaluatorId = cdk.Evaluator,
|
|
|
+ Evaluator = u.CnName,
|
|
|
+ EvalContentId = cdk.EvalContent,
|
|
|
+ EvalContent = sd.Remark,
|
|
|
+ IsMistake = cdk.IsMistake,
|
|
|
+ MistakeReason = cdk.MistakeReason
|
|
|
+ })
|
|
|
+ .ToListAsync();
|
|
|
+
|
|
|
+ if (!info.Any())
|
|
|
+ {
|
|
|
+ var tempInfo = await KpiTemplateDataAsync(evaluatorInfo.DepName, evaluatorInfo.JobName);
|
|
|
+ if (!tempInfo.isSuccess)
|
|
|
+ {
|
|
|
+ _jv.Msg = $"{evaluatorInfo.DepName} - {evaluatorInfo.JobName},未配置日常绩效考核。";
|
|
|
+ return _jv;
|
|
|
+ }
|
|
|
+
|
|
|
+ tempInfo.data.ForEach(t =>
|
|
|
+ {
|
|
|
+ t.Contents.ForEach(c =>
|
|
|
+ {
|
|
|
+ info.Add(new CompanyDailyKpiView()
|
|
|
+ {
|
|
|
+ Month = month,
|
|
|
+ EvaluatorId = evaluatorInfo.UserId,
|
|
|
+ Evaluator = evaluatorInfo.UserName,
|
|
|
+ EvalContentId = c.KpiId,
|
|
|
+ EvalContent = c.KpiContent,
|
|
|
+ IsMistake = false,
|
|
|
+ MistakeReason = string.Empty
|
|
|
+ });
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ }
|
|
|
+ _jv.Code = StatusCodes.Status200OK;
|
|
|
+ _jv.Data = info;
|
|
|
+ _jv.Msg = $"操作成功";
|
|
|
+ return _jv;
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ }
|
|
|
+}
|