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)
throw new PerformanceException("绩效记录不存在!");
// 年资职称绩效占比与工作量绩效占比 校验
var loads = _redistributionService.GetWorkLoads(allot.HospitalId, second.UnitType, second.Department);
var workloadGroups = _redistributionService.GetTopWorkloadBodyGroups(loads);
if ((ComputeMode)request.ComputeMode != ComputeMode.NotCalculate)
{
var workloadGroups = _redistributionService.GetTopWorkloadBodyGroups(loads);
var workloadRatio = workloadGroups.Select(w => request.Head.GetValue($"Workload_Ratio_{w.Name}", 0m));
if (workloadRatio.Any(w => w > 1 || w < 0))
throw new PerformanceException("工作量绩效占比存在异常值!");
......@@ -629,8 +630,20 @@ public ApiResponse RedistributionCheck([FromBody] SecondComputeDto request)
else if (seniorityTitlesAccountedPerformance + workloadRatio.Sum() < 1)
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);
}
catch (PerformanceException ex)
......@@ -737,10 +750,16 @@ public ApiResponse RedistributionSave([FromBody] SecondComputeDto request)
throw new PerformanceException("绩效记录不存在!");
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);
if (checkDatas != null && checkDatas.Any(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标签的数据才是要计算的数据
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)
throw new PerformanceException("绩效未下发,无法提交!");
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);
if (checkDatas != null && checkDatas.Any(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标签的数据才是要计算的数据
var cleanDatas = request.Body.Where(w => w.Count > 0 && w.GetValue(nameof(ResponseType), "") == ResponseType.OK.ToString()).ToList();
if (cleanDatas == null || cleanDatas.Count == 0)
......
......@@ -4108,6 +4108,11 @@
颜色class名称
</summary>
</member>
<member name="P:Performance.DtoModels.SecondColumnDictionary.IsNumber">
<summary>
格式
</summary>
</member>
<member name="P:Performance.DtoModels.SecondEmployeeDto.ComputeMode">
<summary>
计算方式:11 不计算 12 横向计算 13 纵向计算
......
......@@ -34,12 +34,16 @@ public class SecondColumnDictionary
/// 颜色class名称
/// </summary>
public string Color { get; set; }
/// <summary>
/// 格式
/// </summary>
public bool IsNumber { get; set; }
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;
Key = key;
......@@ -49,6 +53,7 @@ public SecondColumnDictionary(string label, string key, bool isTrue, int sort, s
Type = type;
Color = color;
Width = width.HasValue ? width.ToString() : ((label ?? "").Length * 20 + 10).ToString();
IsNumber = isNumber;
}
}
}
......@@ -174,38 +174,38 @@ public List<SecondColumnDictionary> GetTableHeaderDictionary(ComputeMode compute
*/
var maps = new List<SecondColumnDictionary>()
{
new SecondColumnDictionary("人员工号",nameof(ag_bodysource.WorkNumber),true,100),
new SecondColumnDictionary("姓名",nameof(ag_bodysource.Name),true,100),
new SecondColumnDictionary("分配科室",nameof(ag_bodysource.Department),true,100),
new SecondColumnDictionary("核算单元",nameof(ag_bodysource.AccountingUnit),true,100),
new SecondColumnDictionary("人员工号",nameof(ag_bodysource.WorkNumber),true,100, isNumber: false),
new SecondColumnDictionary("姓名",nameof(ag_bodysource.Name),true,100, isNumber: false),
new SecondColumnDictionary("分配科室",nameof(ag_bodysource.Department),true,100, isNumber: false),
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.DeptReward),true,499 ),
new SecondColumnDictionary("工作量绩效合计",nameof(ag_bodysource.WorkPerformance),true,399, isNumber: true ),
new SecondColumnDictionary("单项奖励合计",nameof(ag_bodysource.DeptReward),true,499 , isNumber: true),
new SecondColumnDictionary("可分配绩效",nameof(ag_bodysource.DistPerformance),true,500 ),
new SecondColumnDictionary("医院发放夜班绩效",nameof(ag_bodysource.NightWorkPerformance),true,502 ),
new SecondColumnDictionary("可分配绩效",nameof(ag_bodysource.DistPerformance),true,500 , isNumber: true),
new SecondColumnDictionary("医院发放夜班绩效",nameof(ag_bodysource.NightWorkPerformance),true,502 , isNumber: true),
//new SecondColumnDictionary("预留比例",nameof(ag_bodysource.ReservedRatio),false,601 ),
//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.ReferToRealAmount),false,802, color: "referto_color"),
new SecondColumnDictionary("备注",nameof(ag_bodysource.Remark),false,803,width:200),
new SecondColumnDictionary("医院其他绩效",nameof(ag_bodysource.OtherPerformance),false,801, color: "referto_color" , isNumber: true),
new SecondColumnDictionary("实发绩效",nameof(ag_bodysource.ReferToRealAmount),false,802, color: "referto_color" , isNumber: true),
new SecondColumnDictionary("备注",nameof(ag_bodysource.Remark),false,803,width:200, isNumber: false),
};
// 填报模板不含一下展示信息
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.ActualAttendance), false, 201, color: "title_color"));
maps.Add(new SecondColumnDictionary("职称", nameof(ag_bodysource.JobTitle), false, 202, color: "title_color"));
maps.Add(new SecondColumnDictionary("职称系数", nameof(ag_bodysource.TitleCoefficient), false, 203, color: "title_color"));
maps.Add(new SecondColumnDictionary("职称绩效得分", nameof(ag_bodysource.TitlePerformanceScore), false, 204, 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", isNumber: true));
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", isNumber: true));
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
{
string factor = item.Title.StartsWith("Workload_") ? $"({item.State ?? 0:0.####})" : "";
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
var headDynamic = _agworktypesourceRepository.GetEntities(t => t.SecondId == second.Id) ?? new List<ag_worktype_source>();
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
......@@ -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>();
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_Amount_{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", isNumber: true));
}
}
}
......@@ -257,7 +257,7 @@ public List<SecondColumnDictionary> GetTableHeaderDictionary(ComputeMode compute
int singleAwardsSort = 400;
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();
}
......@@ -1283,7 +1283,47 @@ public List<SecondWorkLoadDto> GetTopWorkloadBodyGroups(List<TitleValue<string,
}
#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>
......
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