using System; using System.Collections.Generic; using System.Linq; using Model; using System.Data; namespace BLL { public class SGManPowerService { /// /// 检查并发送人力资源预警 /// public static List CheckAndSendPersonWarning(string userId) { var responeData = new Model.ResponeData(); // 合并两个集合 var allItems = new List(); var projects = Funs.DB.Base_Project.Where(p => p.ProjectState == BLL.Const.ProjectState_1).ToList(); foreach (var project in projects) { // 检查管理人员到期未到岗情况 var items1 = CheckHistoricalContinuousShortage(project.ProjectId); // 检查作业人员人力偏差情况 var items2 = CheckWorkerDeviation(project.ProjectId); if (items1 != null) { allItems.AddRange(items1); } if (items2 != null) { allItems.AddRange(items2); } } if (!string.IsNullOrEmpty(userId)) { //过滤出指定用户的数据 allItems = allItems.Where(x => x.UserId == userId).ToList(); } return allItems; } #region 检查所有历史数据中连续一周以上人力不足的情况 /// /// 检查所有历史数据中连续一周以上人力不足的情况 /// private static IEnumerable CheckHistoricalContinuousShortage(string projectId) { string strSql = @"WITH LatestVersions AS ( SELECT ProjectId, MAX(Version) AS MaxVersion FROM JDGL_SGManPower WHERE ProjectId = @ProjectId GROUP BY ProjectId ), PlanVsActual AS ( SELECT p.ProjectId, p.UnitId, p.UnitWorkId, p.WorkPostId, p.PlanDate, p.Quantity AS PlanQuantity, ISNULL(a.num, 0) AS num, CASE WHEN ISNULL(a.num, 0) < p.Quantity THEN 1 ELSE 0 END AS IsShortage, lv.MaxVersion FROM JDGL_SGManPower p INNER JOIN LatestVersions lv ON p.ProjectId = lv.ProjectId AND p.Version = lv.MaxVersion LEFT JOIN ( SELECT ProjectId,UnitId,WorkPostId,IntoOutTime,WorkAreaId,num FROM SitePerson_Checking_Statistics ) a ON p.ProjectId = a.ProjectId AND p.UnitId = a.UnitId AND p.WorkPostId = a.WorkPostId AND p.PlanDate = a.IntoOutTime AND (CHARINDEX(',' + p.UnitWorkId + ',', ',' + ISNULL(a.WorkAreaId, '') + ',') > 0 OR (ISNULL(a.WorkAreaId, '') = '' AND ISNULL(p.UnitWorkId, '') = '')) WHERE p.ProjectId = @ProjectId AND p.PlanDate <= GETDATE() ), ShortageWithRowNum AS ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY ProjectId, UnitId, UnitWorkId, WorkPostId ORDER BY PlanDate ) AS RowNum FROM PlanVsActual WHERE IsShortage = 1 ), ContinuousGroups AS ( SELECT *, DATEADD(DAY, -RowNum, PlanDate) AS GroupId FROM ShortageWithRowNum ), ContinuousCounts AS ( SELECT ProjectId, UnitId, UnitWorkId, WorkPostId, GroupId, COUNT(*) AS ContinuousDays, MIN(PlanDate) AS StartDate, MAX(PlanDate) AS EndDate, SUM(PlanQuantity) as PlanQuantity, SUM(num) as num, MaxVersion FROM ContinuousGroups GROUP BY ProjectId, UnitId, UnitWorkId, WorkPostId, GroupId,MaxVersion ) SELECT ProjectId, UnitId, UnitWorkId, WorkPostId, ContinuousDays, MaxVersion, StartDate, EndDate,PlanQuantity,num FROM ContinuousCounts WHERE ContinuousDays >= 7"; var parameters = new List { new System.Data.SqlClient.SqlParameter("@ProjectId", projectId) }; var warningItems = new List(); var dt = SQLHelper.GetDataTableRunText(strSql, parameters.ToArray()); foreach (DataRow row in dt.Rows) { warningItems.AddRange(SendManagerWarning(row["UnitId"].ToString(), row["ProjectId"].ToString(), row["WorkPostId"].ToString(), row["UnitWorkId"].ToString(), Convert.ToDateTime(row["StartDate"]), Convert.ToDateTime(row["EndDate"]), Convert.ToInt32(row["PlanQuantity"]), Convert.ToInt32(row["num"]))); } return warningItems; } /// /// 发送管理人员预警 /// /// 项目ID /// 单位id private static List SendManagerWarning(string unitId, string projectId, string workPostId, string unitWorkId, DateTime? startDate, DateTime? endDate, int? quantity, int num) { // 发送预警信息 var toDoItems = new List(); var unitWorks = (from x in Funs.DB.WBS_UnitWork where x.UnitWorkId == unitWorkId select new { x.UnitWorkId, x.UnitWorkName }).FirstOrDefault(); var projectUnits = (from x in Funs.DB.Project_ProjectUnit join y in Funs.DB.Base_Unit on x.UnitId equals y.UnitId where x.UnitId == unitId select new { x.UnitId, y.UnitName, x.UnitType }).FirstOrDefault(); if (projectUnits != null) { List toUserIds = new List(); // 施工单位人员推送至施工单位项目经理和总包单位施工经理 if (projectUnits.UnitType == Const.ProjectUnitType_2) // 施工分包单位 { // 获取施工单位项目经理 var constructionManagers = (from x in Funs.DB.Project_ProjectUser where x.ProjectId == projectId && x.UnitId == unitId && x.IsPost == true && x.RoleId.Contains(Const.ProjectManager) select x).ToList(); if (constructionManagers.Count > 0) { foreach (var projectUser in constructionManagers) { toUserIds.Add(projectUser.UserId); } } // 获取总包单位施工经理 var generalContractorUnit = Funs.DB.Project_ProjectUnit.FirstOrDefault(pu => pu.ProjectId == projectId && pu.UnitType == Const.ProjectUnitType_1); // 总包单位 if (generalContractorUnit != null) { var constructionManagerGCs = (from x in Funs.DB.Project_ProjectUser where x.ProjectId == projectId && x.UnitId == generalContractorUnit.UnitId && x.IsPost == true && x.RoleId.Contains(Const.ConstructionManager) select x).ToList(); if (constructionManagerGCs.Count > 0) { foreach (var projectUser in constructionManagerGCs) { toUserIds.Add(projectUser.UserId); } } } } // 总包单位人员推送到总包单位施工经理和项目经理 else if (projectUnits.UnitType == Const.ProjectUnitType_1) // 总包单位 { // 获取总包单位施工经理 var constructionManagers = (from x in Funs.DB.Project_ProjectUser where x.ProjectId == projectId && x.UnitId == unitId && x.IsPost == true && x.RoleId.Contains(Const.ConstructionManager) select x).ToList(); if (constructionManagers.Count() > 0) { foreach (var projectUser in constructionManagers) { toUserIds.Add(projectUser.UserId); } } // 获取总包单位项目经理 var projectManagers = (from x in Funs.DB.Project_ProjectUser where x.ProjectId == projectId && x.UnitId == unitId && x.IsPost == true && x.RoleId.Contains(Const.ProjectManager) select x).ToList(); if (projectManagers.Count() > 0) { foreach (var projectUser in projectManagers) { toUserIds.Add(projectUser.UserId); } } } string warningContent = string.Empty; if (unitWorks != null) { warningContent = $"{projectUnits.UnitName}单位{unitWorks.UnitWorkName}装置计划{string.Format("{0:yyyy-MM-dd}", startDate)}~{string.Format("{0:yyyy-MM-dd}", endDate)}投入人力{quantity}人,实际考勤为{num}人。"; } else { warningContent = $"{projectUnits.UnitName}单位计划{string.Format("{0:yyyy-MM-dd}", startDate)}~{string.Format("{0:yyyy-MM-dd}", endDate)}投入人力{quantity}人,实际考勤为{num}人。"; } string urlParams = "JDGL/SGManPower/SGWarningDetailsEdit.aspx?projectId=" + projectId; // 添加单位参数(如果已选择) if (!string.IsNullOrEmpty(unitId)) { urlParams += "&unitId=" + unitId; } // 添加装置参数(如果已选择) if (!string.IsNullOrEmpty(unitWorkId)) { urlParams += "&unitWorkId=" + unitWorkId; } // 添加岗位参数(如果已选择) if (!string.IsNullOrEmpty(workPostId)) { urlParams += "&workPostId=" + workPostId; } // 添加时间参数 if (startDate.HasValue) { urlParams += "&startTime=" + string.Format("{0:yyyy-MM-dd}", startDate); } // 添加时间参数 if (endDate.HasValue) { urlParams += "&endTime=" + string.Format("{0:yyyy-MM-dd}", endDate); } foreach (var userId in toUserIds) { Model.ToDoItem toDoItem = new Model.ToDoItem(); toDoItem.DataId = SQLHelper.GetNewID(typeof(Model.ToDoItem)); toDoItem.MenuId = ""; toDoItem.MenuName = "管理人员到岗预警"; toDoItem.ProjectCode = ""; toDoItem.Content = warningContent; toDoItem.UserId = userId; toDoItem.UserName = UserService.GetUserNameByUserId(userId); toDoItem.DataTime = DateTime.Now; toDoItem.DataTimeStr = DateTime.Now.ToString("yyyy-MM-dd"); toDoItem.PCUrl = urlParams; toDoItems.Add(toDoItem); } } return toDoItems; } #endregion #region 检查作业人员人力偏差情况 // /// // /// 检查作业人员人力偏差情况(一周内(连续7天不是最近七天)累计偏差值超过计划的10%) // /// // /// 项目ID private static IEnumerable CheckWorkerDeviation(string projectId) { string strSql = @"WITH LatestVersions AS ( SELECT ProjectId, MAX(Version) AS MaxVersion FROM JDGL_SGManPower WHERE ProjectId = @ProjectId GROUP BY ProjectId ), PlanVsActual AS ( SELECT p.ProjectId, p.UnitId, p.UnitWorkId, p.WorkPostId, p.PlanDate, p.Quantity AS PlanQuantity, ISNULL(a.num, 0) AS num, CASE WHEN p.Quantity > 0 AND ABS(CAST((p.Quantity - ISNULL(a.num, 0)) AS FLOAT) / p.Quantity) > 0.1 THEN 1 ELSE 0 END AS HasDeviation, lv.MaxVersion FROM JDGL_SGManPower p INNER JOIN LatestVersions lv ON p.ProjectId = lv.ProjectId AND p.Version = lv.MaxVersion LEFT JOIN ( SELECT ProjectId,UnitId,WorkPostId,IntoOutTime,WorkAreaId,num FROM SitePerson_Checking_Statistics ) a ON p.ProjectId = a.ProjectId AND p.UnitId = a.UnitId AND p.WorkPostId = a.WorkPostId AND p.PlanDate = a.IntoOutTime AND (CHARINDEX(',' + p.UnitWorkId + ',', ',' + ISNULL(a.WorkAreaId, '') + ',') > 0 OR (ISNULL(a.WorkAreaId, '') = '' AND ISNULL(p.UnitWorkId, '') = '')) WHERE p.ProjectId = @ProjectId AND p.PlanDate <= GETDATE() ), DeviationWithRowNum AS ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY ProjectId, UnitId, UnitWorkId, WorkPostId ORDER BY PlanDate ) AS RowNum FROM PlanVsActual WHERE HasDeviation = 1 ), ContinuousGroups AS ( SELECT *, DATEADD(DAY, -RowNum, PlanDate) AS GroupId FROM DeviationWithRowNum ), ContinuousCounts AS ( SELECT ProjectId, UnitId, UnitWorkId, WorkPostId, GroupId, COUNT(*) AS ContinuousDays, MIN(PlanDate) AS StartDate, MAX(PlanDate) AS EndDate, SUM(PlanQuantity) as TotalPlanQuantity, SUM(num) as num, MaxVersion FROM ContinuousGroups GROUP BY ProjectId, UnitId, UnitWorkId, WorkPostId, GroupId, MaxVersion ) SELECT ProjectId, UnitId, UnitWorkId, WorkPostId, ContinuousDays, MaxVersion, StartDate, EndDate, TotalPlanQuantity, num FROM ContinuousCounts WHERE ContinuousDays >= 7"; var parameters = new List { new System.Data.SqlClient.SqlParameter("@ProjectId", projectId) }; var warningItems = new List(); var dt = SQLHelper.GetDataTableRunText(strSql, parameters.ToArray()); foreach (DataRow row in dt.Rows) { warningItems.AddRange(SendWorkerDeviationWarning( row["UnitId"].ToString(), row["ProjectId"].ToString(), row["WorkPostId"].ToString(), row["UnitWorkId"].ToString(), Convert.ToDateTime(row["StartDate"]), Convert.ToDateTime(row["EndDate"]), Convert.ToInt32(row["TotalPlanQuantity"]), Convert.ToInt32(row["num"]) )); } return warningItems; } /// /// 发送作业人员偏差预警 /// /// 项目ID /// 单位ID /// 计划总人数 /// 实际总人数 /// 偏差百分比 private static List SendWorkerDeviationWarning(string unitId, string projectId, string workPostId, string unitWorkId, DateTime? startDate, DateTime? endDate, int? quantity, int num) { // 发送预警信息 var toDoItems = new List(); List toUserIds = new List(); var unitWorks = (from x in Funs.DB.WBS_UnitWork where x.UnitWorkId == unitWorkId select new { x.UnitWorkId, x.UnitWorkName }).FirstOrDefault(); var projectUnits = (from x in Funs.DB.Project_ProjectUnit join y in Funs.DB.Base_Unit on x.UnitId equals y.UnitId where x.UnitId == unitId select new { x.UnitId, y.UnitName, x.UnitType }).FirstOrDefault(); // 获取施工单位项目经理 var constructionManagers = (from x in Funs.DB.Project_ProjectUser where x.ProjectId == projectId && x.UnitId == unitId && x.IsPost == true && x.RoleId.Contains(Const.ProjectManager) select x).ToList(); if (constructionManagers.Count > 0) { foreach (var projectUser in constructionManagers) { toUserIds.Add(projectUser.UserId); } } // 获取总包单位施工经理 var generalContractorUnit = Funs.DB.Project_ProjectUnit.FirstOrDefault(pu => pu.ProjectId == projectId && pu.UnitType == Const.ProjectUnitType_1); // 总包单位 if (generalContractorUnit != null) { var constructionManagerGCs = (from x in Funs.DB.Project_ProjectUser where x.ProjectId == projectId && x.UnitId == generalContractorUnit.UnitId && x.IsPost == true && x.RoleId.Contains(Const.ConstructionManager) select x).ToList(); if (constructionManagerGCs.Count > 0) { foreach (var projectUser in constructionManagerGCs) { toUserIds.Add(projectUser.UserId); } } } // 构建预警信息内容 string warningContent = string.Empty; if (unitWorks != null) { warningContent = $"{projectUnits.UnitName}单位{unitWorks.UnitWorkName}装置计划投入人力{quantity}人,实际考勤为{num}人。"; } else { warningContent = $"{projectUnits.UnitName}单位计划投入人力{quantity}人,实际考勤为{num}人。"; } string urlParams = "JDGL/SGManPower/SGWarningDetails.aspx?projectId=" + projectId; // 添加单位参数(如果已选择) if (!string.IsNullOrEmpty(unitId)) { urlParams += "&unitId=" + unitId; } // 添加装置参数(如果已选择) if (!string.IsNullOrEmpty(unitWorkId)) { urlParams += "&unitWorkId=" + unitWorkId; } // 添加岗位参数(如果已选择) if (!string.IsNullOrEmpty(workPostId)) { urlParams += "&workPostId=" + workPostId; } // 添加时间参数 if (startDate.HasValue && endDate.HasValue) { urlParams += "&planDate=" + string.Format("{0:yyyy-MM-dd}", startDate) + "~" + string.Format("{0:yyyy-MM-dd}", endDate); } // 发送预警信息 foreach (var userId in toUserIds) { Model.ToDoItem toDoItem = new Model.ToDoItem(); toDoItem.DataId = SQLHelper.GetNewID(typeof(Model.ToDoItem)); toDoItem.MenuId = ""; toDoItem.MenuName = "人力资源偏差预警"; toDoItem.ProjectCode = ""; toDoItem.Content = warningContent; toDoItem.UserId = userId; toDoItem.UserName = UserService.GetUserNameByUserId(userId); toDoItem.DataTime = DateTime.Now; toDoItem.DataTimeStr = DateTime.Now.ToString("yyyy-MM-dd"); toDoItem.PCUrl = urlParams; toDoItems.Add(toDoItem); } return toDoItems; } #endregion } }