Commit 0d417378 by ruyun.zhang@suvalue.com

Merge branch 'feature/二次分配格式验证' into develop

parents 08b3652d fb8bf243
...@@ -613,9 +613,10 @@ public ApiResponse RedistributionCheck([FromBody] SecondComputeDto request) ...@@ -613,9 +613,10 @@ public ApiResponse RedistributionCheck([FromBody] SecondComputeDto request)
throw new PerformanceException("绩效记录不存在!"); throw new PerformanceException("绩效记录不存在!");
// 年资职称绩效占比与工作量绩效占比 校验 // 年资职称绩效占比与工作量绩效占比 校验
var loads = _redistributionService.GetWorkLoads(allot.HospitalId, second.UnitType, second.Department); var loads = _redistributionService.GetWorkLoads(allot.HospitalId, second.UnitType, second.Department);
var workloadGroups = _redistributionService.GetTopWorkloadBodyGroups(loads);
if ((ComputeMode)request.ComputeMode != ComputeMode.NotCalculate) if ((ComputeMode)request.ComputeMode != ComputeMode.NotCalculate)
{ {
var workloadGroups = _redistributionService.GetTopWorkloadBodyGroups(loads);
var workloadRatio = workloadGroups.Select(w => request.Head.GetValue($"Workload_Ratio_{w.Name}", 0m)); var workloadRatio = workloadGroups.Select(w => request.Head.GetValue($"Workload_Ratio_{w.Name}", 0m));
if (workloadRatio.Any(w => w > 1 || w < 0)) if (workloadRatio.Any(w => w > 1 || w < 0))
throw new PerformanceException("工作量绩效占比存在异常值!"); throw new PerformanceException("工作量绩效占比存在异常值!");
...@@ -629,8 +630,20 @@ public ApiResponse RedistributionCheck([FromBody] SecondComputeDto request) ...@@ -629,8 +630,20 @@ public ApiResponse RedistributionCheck([FromBody] SecondComputeDto request)
else if (seniorityTitlesAccountedPerformance + workloadRatio.Sum() < 1) else if (seniorityTitlesAccountedPerformance + workloadRatio.Sum() < 1)
throw new PerformanceException("年资职称绩效占比与工作量绩效占比总和,不足100%!"); throw new PerformanceException("年资职称绩效占比与工作量绩效占比总和,不足100%!");
} }
List<SecondComputeCheckResultDto> result = new List<SecondComputeCheckResultDto>();
// 二次分配人员信息 校验 // 二次分配人员信息 校验
var result = _redistributionService.CheckData(second, (ComputeMode)request.ComputeMode, request.Body, loads); var checkData = _redistributionService.CheckData(second, (ComputeMode)request.ComputeMode, request.Body, loads);
if (checkData != null && checkData.Count > 0)
result.AddRange(checkData);
// 二次分配提交数据格式 校验
var dic = _redistributionService.GetTableHeaderDictionary((ComputeMode)request.ComputeMode, allot, second, loads, workloadGroups);
var checkFormat = _redistributionService.CheckFormat(request.Head, request.Body, dic);
if (checkFormat != null && checkFormat.Count > 0)
result.AddRange(checkFormat);
return new ApiResponse(ResponseType.OK, result); return new ApiResponse(ResponseType.OK, result);
} }
catch (PerformanceException ex) catch (PerformanceException ex)
...@@ -737,10 +750,16 @@ public ApiResponse RedistributionSave([FromBody] SecondComputeDto request) ...@@ -737,10 +750,16 @@ public ApiResponse RedistributionSave([FromBody] SecondComputeDto request)
throw new PerformanceException("绩效记录不存在!"); throw new PerformanceException("绩效记录不存在!");
var loads = _redistributionService.GetWorkLoads(allot.HospitalId, second.UnitType, second.Department); var loads = _redistributionService.GetWorkLoads(allot.HospitalId, second.UnitType, second.Department);
var workloadGroups = _redistributionService.GetTopWorkloadBodyGroups(loads);
// 二次分配人员信息 校验 // 二次分配人员信息 校验
var checkDatas = _redistributionService.CheckData(second, (ComputeMode)request.ComputeMode, request.Body, loads); var checkDatas = _redistributionService.CheckData(second, (ComputeMode)request.ComputeMode, request.Body, loads);
if (checkDatas != null && checkDatas.Any(w => w.Level == ResponseType.Error.ToString())) if (checkDatas != null && checkDatas.Any(w => w.Level == ResponseType.Error.ToString()))
return new ApiResponse(ResponseType.Fail, "数据验证未通过,请修复后查看计算结果!", checkDatas.Where(w => w.Level == ResponseType.Error.ToString())); return new ApiResponse(ResponseType.Fail, "数据验证未通过,请修复后查看计算结果!", checkDatas.Where(w => w.Level == ResponseType.Error.ToString()));
// 二次分配提交数据格式 校验
var dic = _redistributionService.GetTableHeaderDictionary((ComputeMode)request.ComputeMode, allot, second, loads, workloadGroups);
var checkFormat = _redistributionService.CheckFormat(request.Head, request.Body, dic);
if (checkFormat != null && checkFormat.Any(w => w.Level == ResponseType.Error.ToString()))
return new ApiResponse(ResponseType.Fail, "数据验证未通过,请修复后查看计算结果!", checkFormat.Where(w => w.Level == ResponseType.Error.ToString()));
// 清理无效数据 没有Tab标签的数据才是要计算的数据 // 清理无效数据 没有Tab标签的数据才是要计算的数据
var cleanDatas = request.Body.Where(w => w.Count > 0 && w.GetValue(nameof(ResponseType), "") == ResponseType.OK.ToString()).ToList(); var cleanDatas = request.Body.Where(w => w.Count > 0 && w.GetValue(nameof(ResponseType), "") == ResponseType.OK.ToString()).ToList();
...@@ -786,11 +805,19 @@ public ApiResponse RedistributionSubmit([FromBody] SecondComputeDto request) ...@@ -786,11 +805,19 @@ public ApiResponse RedistributionSubmit([FromBody] SecondComputeDto request)
throw new PerformanceException("绩效未下发,无法提交!"); throw new PerformanceException("绩效未下发,无法提交!");
var loads = _redistributionService.GetWorkLoads(allot.HospitalId, second.UnitType, second.Department); var loads = _redistributionService.GetWorkLoads(allot.HospitalId, second.UnitType, second.Department);
var workloadGroups = _redistributionService.GetTopWorkloadBodyGroups(loads);
// 二次分配人员信息 校验 // 二次分配人员信息 校验
var checkDatas = _redistributionService.CheckData(second, (ComputeMode)request.ComputeMode, request.Body, loads); var checkDatas = _redistributionService.CheckData(second, (ComputeMode)request.ComputeMode, request.Body, loads);
if (checkDatas != null && checkDatas.Any(w => w.Level == ResponseType.Error.ToString())) if (checkDatas != null && checkDatas.Any(w => w.Level == ResponseType.Error.ToString()))
return new ApiResponse(ResponseType.Fail, "数据验证未通过,请修复后查看计算结果!", checkDatas.Where(w => w.Level == ResponseType.Error.ToString())); return new ApiResponse(ResponseType.Fail, "数据验证未通过,请修复后查看计算结果!", checkDatas.Where(w => w.Level == ResponseType.Error.ToString()));
// 二次分配提交数据格式 校验
var dic = _redistributionService.GetTableHeaderDictionary((ComputeMode)request.ComputeMode, allot, second, loads, workloadGroups);
var checkFormat = _redistributionService.CheckFormat(request.Head, request.Body, dic);
if (checkFormat != null && checkFormat.Any(w => w.Level == ResponseType.Error.ToString()))
return new ApiResponse(ResponseType.Fail, "数据验证未通过,请修复后查看计算结果!", checkFormat.Where(w => w.Level == ResponseType.Error.ToString()));
// 清理无效数据 没有Tab标签的数据才是要计算的数据 // 清理无效数据 没有Tab标签的数据才是要计算的数据
var cleanDatas = request.Body.Where(w => w.Count > 0 && w.GetValue(nameof(ResponseType), "") == ResponseType.OK.ToString()).ToList(); var cleanDatas = request.Body.Where(w => w.Count > 0 && w.GetValue(nameof(ResponseType), "") == ResponseType.OK.ToString()).ToList();
if (cleanDatas == null || cleanDatas.Count == 0) if (cleanDatas == null || cleanDatas.Count == 0)
......
...@@ -4108,6 +4108,11 @@ ...@@ -4108,6 +4108,11 @@
颜色class名称 颜色class名称
</summary> </summary>
</member> </member>
<member name="P:Performance.DtoModels.SecondColumnDictionary.IsNumber">
<summary>
格式
</summary>
</member>
<member name="P:Performance.DtoModels.SecondEmployeeDto.ComputeMode"> <member name="P:Performance.DtoModels.SecondEmployeeDto.ComputeMode">
<summary> <summary>
计算方式:11 不计算 12 横向计算 13 纵向计算 计算方式:11 不计算 12 横向计算 13 纵向计算
......
...@@ -34,12 +34,16 @@ public class SecondColumnDictionary ...@@ -34,12 +34,16 @@ public class SecondColumnDictionary
/// 颜色class名称 /// 颜色class名称
/// </summary> /// </summary>
public string Color { get; set; } public string Color { get; set; }
/// <summary>
/// 格式
/// </summary>
public bool IsNumber { get; set; }
public SecondColumnDictionary() public SecondColumnDictionary()
{ {
} }
public SecondColumnDictionary(string label, string key, bool isTrue, int sort, string site = "Table", string type = "", string color = "", int? width = null) public SecondColumnDictionary(string label, string key, bool isTrue, int sort, string site = "Table", string type = "", string color = "", int? width = null, bool isNumber = true)
{ {
Label = label; Label = label;
Key = key; Key = key;
...@@ -49,6 +53,7 @@ public SecondColumnDictionary(string label, string key, bool isTrue, int sort, s ...@@ -49,6 +53,7 @@ public SecondColumnDictionary(string label, string key, bool isTrue, int sort, s
Type = type; Type = type;
Color = color; Color = color;
Width = width.HasValue ? width.ToString() : ((label ?? "").Length * 20 + 10).ToString(); Width = width.HasValue ? width.ToString() : ((label ?? "").Length * 20 + 10).ToString();
IsNumber = isNumber;
} }
} }
} }
...@@ -174,38 +174,38 @@ public List<SecondColumnDictionary> GetTableHeaderDictionary(ComputeMode compute ...@@ -174,38 +174,38 @@ public List<SecondColumnDictionary> GetTableHeaderDictionary(ComputeMode compute
*/ */
var maps = new List<SecondColumnDictionary>() var maps = new List<SecondColumnDictionary>()
{ {
new SecondColumnDictionary("人员工号",nameof(ag_bodysource.WorkNumber),true,100), new SecondColumnDictionary("人员工号",nameof(ag_bodysource.WorkNumber),true,100, isNumber: false),
new SecondColumnDictionary("姓名",nameof(ag_bodysource.Name),true,100), new SecondColumnDictionary("姓名",nameof(ag_bodysource.Name),true,100, isNumber: false),
new SecondColumnDictionary("分配科室",nameof(ag_bodysource.Department),true,100), new SecondColumnDictionary("分配科室",nameof(ag_bodysource.Department),true,100, isNumber: false),
new SecondColumnDictionary("核算单元",nameof(ag_bodysource.AccountingUnit),true,100), new SecondColumnDictionary("核算单元",nameof(ag_bodysource.AccountingUnit),true,100, isNumber: false),
new SecondColumnDictionary("职称绩效", nameof(ag_bodysource.TitlePerformance), true, 299), new SecondColumnDictionary("职称绩效", nameof(ag_bodysource.TitlePerformance), true, 299, isNumber: true),
new SecondColumnDictionary("工作量绩效合计",nameof(ag_bodysource.WorkPerformance),true,399 ), new SecondColumnDictionary("工作量绩效合计",nameof(ag_bodysource.WorkPerformance),true,399, isNumber: true ),
new SecondColumnDictionary("单项奖励合计",nameof(ag_bodysource.DeptReward),true,499 ), new SecondColumnDictionary("单项奖励合计",nameof(ag_bodysource.DeptReward),true,499 , isNumber: true),
new SecondColumnDictionary("可分配绩效",nameof(ag_bodysource.DistPerformance),true,500 ), new SecondColumnDictionary("可分配绩效",nameof(ag_bodysource.DistPerformance),true,500 , isNumber: true),
new SecondColumnDictionary("医院发放夜班绩效",nameof(ag_bodysource.NightWorkPerformance),true,502 ), new SecondColumnDictionary("医院发放夜班绩效",nameof(ag_bodysource.NightWorkPerformance),true,502 , isNumber: true),
//new SecondColumnDictionary("预留比例",nameof(ag_bodysource.ReservedRatio),false,601 ), //new SecondColumnDictionary("预留比例",nameof(ag_bodysource.ReservedRatio),false,601 ),
//new SecondColumnDictionary("预留金额",nameof(ag_bodysource.ReservedAmount),false,602 ), //new SecondColumnDictionary("预留金额",nameof(ag_bodysource.ReservedAmount),false,602 ),
new SecondColumnDictionary("绩效分配合计",nameof(ag_bodysource.RealAmount),true,700 ), new SecondColumnDictionary("绩效分配合计",nameof(ag_bodysource.RealAmount),true,700 , isNumber: true),
new SecondColumnDictionary("医院其他绩效",nameof(ag_bodysource.OtherPerformance),false,801, color: "referto_color" ), new SecondColumnDictionary("医院其他绩效",nameof(ag_bodysource.OtherPerformance),false,801, color: "referto_color" , isNumber: true),
new SecondColumnDictionary("实发绩效",nameof(ag_bodysource.ReferToRealAmount),false,802, color: "referto_color"), new SecondColumnDictionary("实发绩效",nameof(ag_bodysource.ReferToRealAmount),false,802, color: "referto_color" , isNumber: true),
new SecondColumnDictionary("备注",nameof(ag_bodysource.Remark),false,803,width:200), new SecondColumnDictionary("备注",nameof(ag_bodysource.Remark),false,803,width:200, isNumber: false),
}; };
// 填报模板不含一下展示信息 // 填报模板不含一下展示信息
if (computeMode != ComputeMode.NotCalculate) if (computeMode != ComputeMode.NotCalculate)
{ {
maps.Add(new SecondColumnDictionary("领取平均绩效", nameof(ag_bodysource.Post), true, 100)); maps.Add(new SecondColumnDictionary("领取平均绩效", nameof(ag_bodysource.Post), true, 100, isNumber: false));
maps.Add(new SecondColumnDictionary("人员系数", nameof(ag_bodysource.StaffCoefficient), false, 200, color: "title_color")); maps.Add(new SecondColumnDictionary("人员系数", nameof(ag_bodysource.StaffCoefficient), false, 200, color: "title_color", isNumber: true)); ;
maps.Add(new SecondColumnDictionary("出勤", nameof(ag_bodysource.ActualAttendance), false, 201, color: "title_color")); maps.Add(new SecondColumnDictionary("出勤", nameof(ag_bodysource.ActualAttendance), false, 201, color: "title_color", isNumber: true));
maps.Add(new SecondColumnDictionary("职称", nameof(ag_bodysource.JobTitle), false, 202, color: "title_color")); maps.Add(new SecondColumnDictionary("职称", nameof(ag_bodysource.JobTitle), false, 202, color: "title_color", isNumber: false));
maps.Add(new SecondColumnDictionary("职称系数", nameof(ag_bodysource.TitleCoefficient), false, 203, color: "title_color")); maps.Add(new SecondColumnDictionary("职称系数", nameof(ag_bodysource.TitleCoefficient), false, 203, color: "title_color", isNumber: true));
maps.Add(new SecondColumnDictionary("职称绩效得分", nameof(ag_bodysource.TitlePerformanceScore), false, 204, color: "title_color")); maps.Add(new SecondColumnDictionary("职称绩效得分", nameof(ag_bodysource.TitlePerformanceScore), false, 204, color: "title_color", isNumber: true));
} }
// 工作量 // 工作量
...@@ -228,7 +228,7 @@ public List<SecondColumnDictionary> GetTableHeaderDictionary(ComputeMode compute ...@@ -228,7 +228,7 @@ public List<SecondColumnDictionary> GetTableHeaderDictionary(ComputeMode compute
{ {
string factor = item.Title.StartsWith("Workload_") ? $"({item.State ?? 0:0.####})" : ""; string factor = item.Title.StartsWith("Workload_") ? $"({item.State ?? 0:0.####})" : "";
var label = isAttachFactor == true ? $"{item.Value}{factor}" : item.Value; var label = isAttachFactor == true ? $"{item.Value}{factor}" : item.Value;
maps.Add(new SecondColumnDictionary(label, item.Title, false, ++workloadSort, type: "Workload", color: $"workload_color{index}")); maps.Add(new SecondColumnDictionary(label, item.Title, false, ++workloadSort, type: "Workload", color: $"workload_color{index}", isNumber: true));
} }
} }
// 多工作量加载 // 多工作量加载
...@@ -239,7 +239,7 @@ public List<SecondColumnDictionary> GetTableHeaderDictionary(ComputeMode compute ...@@ -239,7 +239,7 @@ public List<SecondColumnDictionary> GetTableHeaderDictionary(ComputeMode compute
var headDynamic = _agworktypesourceRepository.GetEntities(t => t.SecondId == second.Id) ?? new List<ag_worktype_source>(); var headDynamic = _agworktypesourceRepository.GetEntities(t => t.SecondId == second.Id) ?? new List<ag_worktype_source>();
foreach (var item in headDynamic.OrderBy(t => t.Id)) foreach (var item in headDynamic.OrderBy(t => t.Id))
{ {
maps.Add(new SecondColumnDictionary(item.FieldName, item.FieldId, true, 1, "Top")); maps.Add(new SecondColumnDictionary(item.FieldName, item.FieldId, true, 1, "Top", isNumber: true));
} }
} }
else else
...@@ -248,8 +248,8 @@ public List<SecondColumnDictionary> GetTableHeaderDictionary(ComputeMode compute ...@@ -248,8 +248,8 @@ public List<SecondColumnDictionary> GetTableHeaderDictionary(ComputeMode compute
.GetEntities(t => t.HospitalId == allot.HospitalId && t.Department == second.Department && t.UnitType == second.UnitType) ?? new List<ag_workload_type>(); .GetEntities(t => t.HospitalId == allot.HospitalId && t.Department == second.Department && t.UnitType == second.UnitType) ?? new List<ag_workload_type>();
foreach (var item in workloadTypes.OrderBy(t => t.Id)) foreach (var item in workloadTypes.OrderBy(t => t.Id))
{ {
maps.Add(new SecondColumnDictionary($"{item.TypeName}占比", $"Workload_Ratio_{item.Id}", true, 1, "Top")); maps.Add(new SecondColumnDictionary($"{item.TypeName}占比", $"Workload_Ratio_{item.Id}", true, 1, "Top", isNumber: true));
maps.Add(new SecondColumnDictionary($"{item.TypeName}金额", $"Workload_Amount_{item.Id}", true, 1, "Top")); maps.Add(new SecondColumnDictionary($"{item.TypeName}金额", $"Workload_Amount_{item.Id}", true, 1, "Top", isNumber: true));
} }
} }
} }
...@@ -257,7 +257,7 @@ public List<SecondColumnDictionary> GetTableHeaderDictionary(ComputeMode compute ...@@ -257,7 +257,7 @@ public List<SecondColumnDictionary> GetTableHeaderDictionary(ComputeMode compute
int singleAwardsSort = 400; int singleAwardsSort = 400;
foreach (var item in loads.Where(w => w.Title.StartsWithIgnoreCase("SingleAwards_"))) foreach (var item in loads.Where(w => w.Title.StartsWithIgnoreCase("SingleAwards_")))
{ {
maps.Add(new SecondColumnDictionary(item.Value, item.Title, false, ++singleAwardsSort, type: "SingleAwards", color: "singleawards_color")); maps.Add(new SecondColumnDictionary(item.Value, item.Title, false, ++singleAwardsSort, type: "SingleAwards", color: "singleawards_color", isNumber: true));
} }
return maps.OrderBy(w => w.Sort).ToList(); return maps.OrderBy(w => w.Sort).ToList();
} }
...@@ -1283,7 +1283,47 @@ public List<SecondWorkLoadDto> GetTopWorkloadBodyGroups(List<TitleValue<string, ...@@ -1283,7 +1283,47 @@ public List<SecondWorkLoadDto> GetTopWorkloadBodyGroups(List<TitleValue<string,
} }
#endregion #endregion
#region 检查工号和姓名是否匹配 #region 检查工号和姓名是否匹配
/// <summary>
/// 二次分配提交数据格式 校验
/// </summary>
/// <param name="head"></param>
/// <param name="body"></param>
/// <param name="dic"></param>
/// <returns></returns>
public List<SecondComputeCheckResultDto> CheckFormat(Dictionary<string, object> head, List<Dictionary<string, object>> body, List<SecondColumnDictionary> dic)
{
if (body == null || body.Count == 0)
throw new PerformanceException("分配人员信息不存在!");
Regex regex = new Regex(@"^(\-|\+)?\d+(\.\d+)?$");
List<SecondComputeCheckResultDto> result = new List<SecondComputeCheckResultDto>();
foreach (var col in dic.Where(w => w.Site == "Top" && w.IsNumber))
{
if (head.TryGetValue(col.Key.ToLower(), out object value) && value != null && !string.IsNullOrEmpty(value.ToString()) && !regex.IsMatch(value.ToString()))
result.Add(new SecondComputeCheckResultDto(nameof(ResponseType.Error), "", "", $"总览信息:“{col.Label}”错误,当前:“{value}”,仅支持数字,请修复!"));
else if (head.TryGetValue(col.Key, out value) && value != null && !string.IsNullOrEmpty(value.ToString()) && !regex.IsMatch(value.ToString()))
result.Add(new SecondComputeCheckResultDto(nameof(ResponseType.Error), "", "", $"总览信息:“{col.Label}”错误,当前:“{value}”,仅支持数字,请修复!"));
}
for (int i = 0; i < body.Count; i++)
{
var row = body[i];
foreach (var col in dic.Where(w => w.Site == "Table" && w.IsNumber))
{
var number = row.GetString(nameof(ag_bodysource.WorkNumber));
var name = row.GetString(nameof(ag_bodysource.Name));
if (row.TryGetValue(col.Key.ToLower(), out object value) && value != null && !string.IsNullOrEmpty(value.ToString()) && !regex.IsMatch(value.ToString()))
result.Add(new SecondComputeCheckResultDto(nameof(ResponseType.Error), number, name, $"第{(i + 1)}行:“{col.Label}”错误,当前:“{value}”,仅支持数字,请修复!"));
else if (row.TryGetValue(col.Key, out value) && value != null && !string.IsNullOrEmpty(value.ToString()) && !regex.IsMatch(value.ToString()))
result.Add(new SecondComputeCheckResultDto(nameof(ResponseType.Error), number, name, $"第{(i + 1)}行:“{col.Label}”错误,当前:“{value}”,仅支持数字,请修复!"));
}
}
return result;
}
/// <summary> /// <summary>
/// 检查工号和姓名是否匹配 /// 检查工号和姓名是否匹配
/// </summary> /// </summary>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment