Commit 072dee28 by lcx

抽取

parent cba3328a
......@@ -31,7 +31,7 @@ public PersonController(PersonService personService, ClaimService claimService)
[HttpPost]
public ApiResponse GetPersons(int allotId)
{
var list = personService.GetPersons(allotId);
var list = personService.GetPersons(allotId, claimService.GetUserId());
return new ApiResponse(ResponseType.OK, list);
}
......@@ -42,7 +42,7 @@ public ApiResponse GetPersons(int allotId)
/// <returns></returns>
[Route("person/add")]
[HttpPost]
public ApiResponse CreatePerson([FromBody] per_employee request)
public ApiResponse CreatePerson([FromBody] PerEmployeeResponse request)
{
request.CreateUser = claimService.GetUserId();
var employeee = personService.CreatePerson(request);
......@@ -57,7 +57,7 @@ public ApiResponse CreatePerson([FromBody] per_employee request)
/// <returns></returns>
[Route("person/edit")]
[HttpPost]
public ApiResponse UpdatePerson([FromBody] per_employee request)
public ApiResponse UpdatePerson([FromBody] PerEmployeeResponse request)
{
var result = personService.UpdatePerson(request);
return result ? new ApiResponse(ResponseType.OK, "修改成功!")
......@@ -87,7 +87,7 @@ public ApiResponse DeletePerson(int employeeId)
[HttpPost]
public ApiResponse GetDepartments(int hospitalId)
{
var list = personService.GetPersons(hospitalId);
var list = personService.GetDepartments(hospitalId);
return new ApiResponse(ResponseType.OK, list);
}
......@@ -100,6 +100,9 @@ public ApiResponse GetDepartments(int hospitalId)
[HttpPost]
public ApiResponse CreateDeptDic([FromBody] per_dept_dic request)
{
if (string.IsNullOrEmpty(request.Department) || string.IsNullOrEmpty(request.HISDeptName))
return new ApiResponse(ResponseType.ParameterError, "标准科室,系统科室不可为空!");
request.CreateUser = claimService.GetUserId();
var employeee = personService.CreateDeptDic(request);
return employeee.Id > 0 ? new ApiResponse(ResponseType.OK, "添加成功!", employeee)
......@@ -113,8 +116,11 @@ public ApiResponse CreateDeptDic([FromBody] per_dept_dic request)
/// <returns></returns>
[Route("deptdic/edit")]
[HttpPost]
public ApiResponse UpdateDeptDic([FromBody] per_dept_dic request)
public ApiResponse UpdateDeptDic([FromBody] DeptdicResponse request)
{
if (string.IsNullOrEmpty(request.Department) || string.IsNullOrEmpty(request.HISDeptName))
return new ApiResponse(ResponseType.ParameterError, "标准科室,系统科室不可为空!");
var result = personService.UpdateDeptDic(request);
return result ? new ApiResponse(ResponseType.OK, "修改成功!")
: new ApiResponse(ResponseType.OK, "修改失败!");
......@@ -123,15 +129,32 @@ public ApiResponse UpdateDeptDic([FromBody] per_dept_dic request)
/// <summary>
/// 删除科室
/// </summary>
/// <param name="deptdicId"></param>
/// <param name="request"></param>
/// <returns></returns>
[Route("deptdic/delete/{deptdicId}")]
[Route("deptdic/delete")]
[HttpPost]
public ApiResponse DeleteDeptDic(int deptdicId)
public ApiResponse DeleteDeptDic([FromBody] DeptdicResponse request)
{
var result = personService.DeleteDeptDic(deptdicId);
var result = personService.DeleteDeptDic(request);
return result ? new ApiResponse(ResponseType.OK, "删除成功!")
: new ApiResponse(ResponseType.OK, "删除失败!");
}
/// <summary>
/// 系统/标准科室字典
/// </summary>
/// <param name="hospitalId">医院Id</param>
/// <param name="type">1系统科室 2标准科室 3核算单元</param>
/// <returns></returns>
[Route("deptdic/{hospitalId}/dict/{type}")]
[HttpPost]
public ApiResponse DeptDics(int hospitalId, int type)
{
if (!new int[] { 1, 2, 3 }.Contains(type))
return new ApiResponse(ResponseType.ParameterError, "参数错误!");
var result = personService.DeptDics(hospitalId, type);
return new ApiResponse(ResponseType.OK, result);
}
}
}
......@@ -796,14 +796,14 @@
<param name="allotId"></param>
<returns></returns>
</member>
<member name="M:Performance.Api.Controllers.PersonController.CreatePerson(Performance.EntityModels.per_employee)">
<member name="M:Performance.Api.Controllers.PersonController.CreatePerson(Performance.DtoModels.PerEmployeeResponse)">
<summary>
新增员工信息
</summary>
<param name="request"></param>
<returns></returns>
</member>
<member name="M:Performance.Api.Controllers.PersonController.UpdatePerson(Performance.EntityModels.per_employee)">
<member name="M:Performance.Api.Controllers.PersonController.UpdatePerson(Performance.DtoModels.PerEmployeeResponse)">
<summary>
修改员工信息
</summary>
......@@ -831,18 +831,26 @@
<param name="request"></param>
<returns></returns>
</member>
<member name="M:Performance.Api.Controllers.PersonController.UpdateDeptDic(Performance.EntityModels.per_dept_dic)">
<member name="M:Performance.Api.Controllers.PersonController.UpdateDeptDic(Performance.DtoModels.DeptdicResponse)">
<summary>
修改科室信息
</summary>
<param name="request"></param>
<returns></returns>
</member>
<member name="M:Performance.Api.Controllers.PersonController.DeleteDeptDic(System.Int32)">
<member name="M:Performance.Api.Controllers.PersonController.DeleteDeptDic(Performance.DtoModels.DeptdicResponse)">
<summary>
删除科室
</summary>
<param name="deptdicId"></param>
<param name="request"></param>
<returns></returns>
</member>
<member name="M:Performance.Api.Controllers.PersonController.DeptDics(System.Int32,System.Int32)">
<summary>
系统/标准科室字典
</summary>
<param name="hospitalId">医院Id</param>
<param name="type">1系统科室 2标准科室 3核算单元</param>
<returns></returns>
</member>
<member name="T:Performance.Api.Controllers.ReportController">
......
......@@ -2590,6 +2590,16 @@
菜单状态 1 启用 2禁用
</summary>
</member>
<member name="P:Performance.DtoModels.PerEmployeeResponse.WorkTime">
<summary>
参加工作时间
</summary>
</member>
<member name="P:Performance.DtoModels.PerEmployeeResponse.BirthDate">
<summary>
出生年月
</summary>
</member>
<member name="P:Performance.DtoModels.ResComputeResponse.ID">
<summary>
......
......@@ -3233,9 +3233,14 @@
出勤率
</summary>
</member>
<member name="P:Performance.EntityModels.per_employee.Efficiency">
<member name="P:Performance.EntityModels.per_employee.PermanentStaff">
<summary>
效率绩效
核算人数
</summary>
</member>
<member name="P:Performance.EntityModels.per_employee.EfficiencyNumber">
<summary>
效率人数
</summary>
</member>
<member name="P:Performance.EntityModels.per_employee.WorkTime">
......
......@@ -209,6 +209,11 @@ public AutoMapperConfigs()
CreateMap<per_budget_ratio, BudgetResponse>()
.ForMember(dest => dest.Type, opt => opt.MapFrom(src => 2));
CreateMap<BudgetResponse, per_budget_ratio>();
CreateMap<per_employee, PerEmployeeResponse>()
.ForMember(dest => dest.WorkTime, opt => opt.MapFrom(src => src.WorkTime == null ? null : src.WorkTime.ToString()))
.ForMember(dest => dest.BirthDate, opt => opt.MapFrom(src => src.BirthDate == null ? null : src.BirthDate.ToString()))
.ReverseMap();
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace Performance.DtoModels
{
public class DeptdicResponse
{
public int HospitalId { get; set; }
public string HISDeptName { get; set; }
public string Department { get; set; }
public Deptdic OutDoctorAccounting { get; set; }
public Deptdic OutNurseAccounting { get; set; }
public Deptdic OutTechnicAccounting { get; set; }
public Deptdic InpatDoctorAccounting { get; set; }
public Deptdic InpatNurseAccounting { get; set; }
public Deptdic InpatTechnicAccounting { get; set; }
public DateTime? CreateTime { get; set; }
}
public class Deptdic
{
public int Id { get; set; }
public string AccountingUnit { get; set; }
}
}
using Performance.EntityModels;
using System;
using System.Collections.Generic;
using System.Text;
namespace Performance.DtoModels
{
public class PerEmployeeResponse : per_employee
{
/// <summary>
/// 参加工作时间
/// </summary>
public new string WorkTime { get; set; }
/// <summary>
/// 出生年月
/// </summary>
public new string BirthDate { get; set; }
}
}
......@@ -7,55 +7,55 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Performance.EntityModels
namespace Performance.EntityModels
{
/// <summary>
/// 绩效人员表
/// </summary>
[Table("per_employee")]
public class per_employee
public class per_employee
{
/// <summary>
///
/// </summary>
[Key]
public int Id { get; set; }
public int Id { get; set; }
/// <summary>
/// 核算单元
/// </summary>
public string AccountingUnit { get; set; }
/// <summary>
/// 科室
/// </summary>
public string Department { get; set; }
/// <summary>
/// 姓名
/// </summary>
public string DoctorName { get; set; }
/// <summary>
/// 员工工号
/// </summary>
public string PersonnelNumber { get; set; }
/// <summary>
/// 正式/临聘
/// </summary>
public string JobCategory { get; set; }
/// <summary>
/// 职务
/// </summary>
public string Duty { get; set; }
/// <summary>
/// 职称
/// </summary>
public string JobTitle { get; set; }
/// <summary>
/// 人员类别
/// </summary>
......@@ -70,37 +70,43 @@ public class per_employee
/// 出勤率
/// </summary>
public Nullable<decimal> Attendance { get; set; }
/// <summary>
/// 效率绩效
/// 核算人数
/// </summary>
public Nullable<decimal> Efficiency { get; set; }
public Nullable<decimal> PermanentStaff { get; set; }
/// <summary>
/// 效率人数
/// </summary>
public Nullable<decimal> EfficiencyNumber { get; set; }
/// <summary>
/// 参加工作时间
/// </summary>
public Nullable<DateTime> WorkTime { get; set; }
/// <summary>
/// 出生年月
/// </summary>
public Nullable<DateTime> BirthDate { get; set; }
/// <summary>
/// 年龄
/// </summary>
public Nullable<int> Age { get; set; }
/// <summary>
/// 备注
/// </summary>
public string Remark { get; set; }
/// <summary>
/// 医院Id
/// </summary>
public Nullable<int> HospitalId { get; set; }
/// <summary>
/// 绩效Id
/// </summary>
......
......@@ -21,12 +21,12 @@ namespace Performance.Extract.Api.Controllers
[Route("api/[controller]")]
public class ExtractController : Controller
{
private readonly DFExtractService extractService;
private readonly DFExtractService1 extractService;
private readonly HospitalService hospitalService;
private readonly WebapiUrl url;
private readonly ILogger<ExtractController> logger;
private readonly IHostingEnvironment evn;
public ExtractController(DFExtractService extractService,
public ExtractController(DFExtractService1 extractService,
HospitalService hospitalService,
IOptions<WebapiUrl> url,
ILogger<ExtractController> logger,
......
......@@ -13,6 +13,7 @@ public enum StyleType
列头,
系数,
数据,
Remove,
默认,
}
public enum CellFormat
......@@ -69,6 +70,10 @@ public static ICellStyle CreateCellStyle(IWorkbook wb, StyleType type = StyleTyp
cellStyle.FillForegroundColor = HSSFColor.SkyBlue.Index;
cellStyle.FillPattern = FillPattern.SolidForeground;
break;
case StyleType.Remove:
cellStyle.FillForegroundColor = HSSFColor.LightTurquoise.Index;
cellStyle.FillPattern = FillPattern.SolidForeground;
break;
case StyleType.默认:
cellStyle.SetFont(font);
break;
......
using Dapper;
using Dapper;
using Microsoft.Extensions.Logging;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
using Performance.DtoModels;
using Performance.EntityModels;
using Performance.Infrastructure;
using Performance.Repository;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Text.RegularExpressions;
namespace Performance.Services
{
public class DFExtractService1 : IAutoInjection
{
#region
private readonly ILogger<DFExtractService1> logger;
private readonly IEmailService emailService;
private readonly PerSheetService perSheetService;
private readonly PerforHospitalRepository perforHospitalRepository;
private readonly PerforHospitalconfigRepository perforHospitalconfigRepository;
private readonly PerforPerallotRepository perforPerallotRepository;
private readonly PerforImspecialunitRepository perforImspecialunitRepository;
private readonly PerforImdataRepository perforImdataRepository;
private readonly PerforRepimportconfigRepository repimportconfigRepository;
private readonly PerforExitemRepository perforExitemRepository;
private readonly PerforExmoduleRepository perforExmoduleRepository;
private readonly PerforExspecialRepository perforExspecialRepository;
private readonly PerforExresultRepository perforExresultRepository;
private readonly PerforExscriptRepository perforExscriptRepository;
private readonly PerforPerdeptdicRepository perforPerdeptdicRepository;
private readonly PerforPeremployeeRepository perforPeremployeeRepository;
private IWorkbook workbook = null;
private ICellStyle style;
private per_allot Allot;
private const string specialname = "4.2 特殊核算单元绩效测算表";
public DFExtractService1(ILogger<DFExtractService1> logger,
IEmailService emailService,
PerSheetService perSheetService,
PerforHospitalRepository perforHospitalRepository,
PerforHospitalconfigRepository perforHospitalconfigRepository,
PerforPerallotRepository perforPerallotRepository,
PerforImspecialunitRepository perforImspecialunitRepository,
PerforImdataRepository perforImdataRepository,
PerforRepimportconfigRepository repimportconfigRepository,
PerforExitemRepository perforExitemRepository,
PerforExmoduleRepository perforExmoduleRepository,
PerforExspecialRepository perforExspecialRepository,
PerforExresultRepository perforExresultRepository,
PerforExscriptRepository perforExscriptRepository,
PerforPerdeptdicRepository perforPerdeptdicRepository,
PerforPeremployeeRepository perforPeremployeeRepository)
{
this.logger = logger;
this.emailService = emailService;
this.perSheetService = perSheetService;
this.perforHospitalRepository = perforHospitalRepository;
this.perforHospitalconfigRepository = perforHospitalconfigRepository;
this.perforPerallotRepository = perforPerallotRepository;
this.perforImspecialunitRepository = perforImspecialunitRepository;
this.perforImdataRepository = perforImdataRepository;
this.repimportconfigRepository = repimportconfigRepository;
this.perforExitemRepository = perforExitemRepository;
this.perforExmoduleRepository = perforExmoduleRepository;
this.perforExspecialRepository = perforExspecialRepository;
this.perforExresultRepository = perforExresultRepository;
this.perforExscriptRepository = perforExscriptRepository;
this.perforPerdeptdicRepository = perforPerdeptdicRepository;
this.perforPeremployeeRepository = perforPeremployeeRepository;
}
#endregion
#region 抽取
public string ExtractData(int allotId, string email, int hospitalId, string filePath = null)
{
var hospital = perforHospitalRepository.GetEntity(t => t.ID == hospitalId);
try
{
var allot = perforPerallotRepository.GetEntity(t => t.ID == allotId);
Allot = allot ?? throw new PerformanceException("");
var statesArray = new int[] { (int)AllotStates.GenerateSucceed, (int)AllotStates.Archive };
var allots = perforPerallotRepository.GetEntities(t => t.HospitalId == hospitalId && statesArray.Contains(t.States));
var lastAllot = allots?.OrderByDescending(t => t.Year).ThenByDescending(t => t.Month).First();
var configs = perforHospitalconfigRepository.GetEntities(t => t.HospitalId == hospitalId);
var typeIds = new List<int>();
var modules = perforExmoduleRepository.GetEntities(t => t.HospitalId == hospitalId);
var items = new List<ex_item>();
if (modules != null && modules.Any())
{
typeIds.AddRange(modules.Select(t => t.TypeId ?? 0));
items = perforExitemRepository.GetEntities(t => t.ModuleId.HasValue
&& modules.Select(m => m.Id).Contains(t.ModuleId.Value));
typeIds.AddRange(items?.Select(t => t.TypeId ?? 0) ?? new List<int>());
}
var specials = perforExspecialRepository.GetEntities(t => t.HospitalId == hospitalId);
if (specials != null && specials.Any())
typeIds.AddRange(specials.Select(t => t.TypeId ?? 0));
typeIds = typeIds.Distinct().ToList();
var data = new List<ex_result>();
var scripts = perforExscriptRepository.GetEntities(t => typeIds.Contains(t.TypeId));
ClearHistData(allot);
var otherItems = items.Where(t => modules.Where(m => m.SheetType != (int)SheetType.Income).Select(m => m.Id).Contains(t.ModuleId.Value)).ToList();
if (scripts != null && scripts.Any())
{
data.AddRange(ExtractIncome(modules, scripts, configs, allot));
data.AddRange(ExtractItems(otherItems, scripts, configs, allot, modules));
data.AddRange(ExtractSpcial(specials, scripts, configs, allot));
}
return lastAllot == null ? TemplateExecute(email, hospital, configs, modules, items, specials, data)
: AlllotExecute(email, hospital, configs, modules, items, specials, data, lastAllot, filePath);
}
catch (Exception ex)
{
logger.LogError($"提取绩效数据异常 数据写入出现异常{ex.ToString()}");
//SendEmail(email, "", $"{hospital.HosName}HIS数据提取失败", $"{hospital.HosName}提取数据过程中出现异常情况,我们将尽快解决问题。给您带来的不便我们深感歉意!");
throw ex;
}
finally
{
Allot.IsExtracting = null;
perforPerallotRepository.Update(Allot);
if (workbook != null)
workbook.Close();
GC.Collect();
}
}
/// <summary>
/// 抽取收入费用
/// </summary>
/// <typeparam name="TEntity">ex_module</typeparam>
/// <param name="entities"></param>
/// <param name="scripts">抽取配置项</param>
/// <param name="configs">数据连接项</param>
/// <param name="allot">绩效</param>
/// <returns></returns>
private List<ex_result> ExtractIncome<TEntity>(List<TEntity> entities, List<ex_script> scripts, List<sys_hospitalconfig> configs, per_allot allot)
{
var data = new List<ex_result>();
var modules = entities as List<ex_module>;
if (modules == null || !modules.Any(t => t.SheetType == (int)SheetType.Income && t.TypeId > 0))
return data;
foreach (var module in modules.Where(t => t.TypeId > 0))
{
foreach (var config in configs)
{
var item = scripts.FirstOrDefault(t => t.TypeId == module.TypeId && t.DatabaseType == config.DataBaseType);
if (item == null) continue;
var querydata = QueryData(config, allot, item.ExecScript, module.ModuleName);
if (querydata != null && querydata.Any())
{
perforExresultRepository.AddRange(querydata.ToArray());
data.AddRange(querydata);
}
}
}
return data;
}
/// <summary>
/// 抽取支出、工作量等费用
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="entities"></param>
/// <param name="scripts"></param>
/// <param name="configs"></param>
/// <param name="allot"></param>
/// <param name="modules"></param>
/// <returns></returns>
private List<ex_result> ExtractItems<TEntity>(List<TEntity> entities, List<ex_script> scripts, List<sys_hospitalconfig> configs, per_allot allot, List<ex_module> modules)
{
var data = new List<ex_result>();
var items = entities as List<ex_item>;
if (items == null || !items.Any(t => t.TypeId > 0))
return data;
foreach (var exitem in items.Where(t => t.TypeId > 0))
{
var module = modules.FirstOrDefault(t => t.Id == exitem.ModuleId);
foreach (var config in configs)
{
var item = scripts.FirstOrDefault(t => t.TypeId == exitem.TypeId && t.DatabaseType == config.DataBaseType);
if (item == null) continue;
var result = QueryData(config, allot, item.ExecScript, module.ModuleName);
if (result != null && result.Any())
{
result.ForEach(t => t.Category = exitem.ItemName);
perforExresultRepository.AddRange(result.ToArray());
data.AddRange(result);
}
}
}
return data;
}
/// <summary>
/// 抽取特殊科室数据
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="entities"></param>
/// <param name="scripts"></param>
/// <param name="configs"></param>
/// <param name="allot"></param>
/// <returns></returns>
private List<ex_result> ExtractSpcial<TEntity>(List<TEntity> entities, List<ex_script> scripts, List<sys_hospitalconfig> configs, per_allot allot)
{
var data = new List<ex_result>();
var specials = entities as List<ex_special>;
if (specials == null || !specials.Any(t => t.TypeId > 0))
return data;
foreach (var special in specials.Where(t => t.TypeId > 0))
{
foreach (var config in configs)
{
var item = scripts.FirstOrDefault(t => t.TypeId == special.TypeId && t.DatabaseType == config.DataBaseType);
if (item == null) continue;
var result = QueryData(config, allot, item.ExecScript, specialname);
result.ForEach(t =>
{
t.Category = special.Target;
t.Department = special.Department;
});
data.AddRange(result);
}
}
if (data != null && data.Any())
perforExresultRepository.AddRange(data.ToArray());
return data;
}
/// <summary>
/// 清除历史抽取数据
/// </summary>
/// <param name="allot"></param>
private void ClearHistData(per_allot allot)
{
logger.LogInformation($"开始清除历史提取数据");
var data = perforExresultRepository.GetEntities(t => t.AllotId == allot.ID);
if (data == null || !data.Any(t => t.Id > 0))
return;
perforExresultRepository.RemoveRange(data.ToArray());
}
/// <summary>
/// 空白模板
/// </summary>
/// <param name="email"></param>
/// <param name="lastAllot"></param>
/// <param name="hospital"></param>
/// <param name="configs"></param>
/// <param name="modules"></param>
/// <param name="items"></param>
/// <param name="specials"></param>
/// <param name="extracts"></param>
/// <returns></returns>
public string TemplateExecute(string email, sys_hospital hospital, List<sys_hospitalconfig> configs, List<ex_module> modules, List<ex_item> items, List<ex_special> specials, List<ex_result> data)
{
string originalPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Template", "医院绩效模板.xlsx");
var (tempPath, newPath) = CopyOriginalFile(hospital.ID, originalPath);
workbook = new XSSFWorkbook(tempPath);
CreateNotExistSheet(modules, workbook);
style = CellStyle.CreateCellStyle(workbook, StyleType.数据);
List<AccountUnitEntity> unitList = new List<AccountUnitEntity>();
var deptDict = perforPerdeptdicRepository.GetEntities(t => t.HospitalId == Allot.HospitalId);
var units = EnumHelper.GetItems<UnitType>();
if (deptDict != null && deptDict.Any())
{
unitList = deptDict.Select(t => new AccountUnitEntity
{
AccountingUnit = t.AccountingUnit,
Department = t.Department,
UnitType = units.FirstOrDefault(en => en.Description == t.UnitType)?.Value ?? 0
}).ToList();
}
logger.LogInformation($"unitList count: {unitList?.Count ?? 0}");
for (int i = 0; i < workbook.NumberOfSheets; i++)
{
var sheet = workbook.GetSheetAt(i);
var sheetType = perSheetService.GetSheetType(sheet.SheetName);
if (sheetType == SheetType.Unidentifiable) continue;
var sheetRead = PerSheetDataFactory.GetDataRead(sheetType);
switch (sheetType)
{
case SheetType.Employee:
WriteEmployee(sheet, sheetRead);
break;
case SheetType.ClinicEmployee:
WriteClinicEmployee(sheet, sheetRead);
break;
case SheetType.OtherIncome:
WriteOtherIncome(sheet, sheetRead, unitList, modules, items, data);
break;
case SheetType.Income:
WriteIncome(sheet, sheetRead, unitList, modules, items, data);
break;
case SheetType.Expend:
WriteExpend(sheet, sheetRead, unitList, modules, items, data);
break;
case SheetType.Workload:
WriteWorkload(sheet, sheetRead, unitList, modules, items, data);
break;
case SheetType.AccountBasic:
WriteAccountBasic(sheet, sheetRead);
break;
case SheetType.SpecialUnit:
WriteSpecialUnit(sheet, sheetRead, specials, data);
break;
}
}
using (FileStream file = new FileStream(newPath, FileMode.OpenOrCreate))
{
workbook.Write(file);
}
logger.LogInformation($"提取绩效数据 {hospital.HosName}HIS数据提取成功,文件路径:{newPath}。");
ImportData(Allot, configs);
SendEmail(email, newPath, $"{hospital.HosName}HIS数据提取成功", $"{hospital.HosName}{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}成功提取。");
return newPath;
}
/// <summary>
/// 历史绩效为模板
/// </summary>
/// <param name="email"></param>
/// <param name="lastAllot"></param>
/// <param name="hospital"></param>
/// <param name="configs"></param>
/// <param name="modules"></param>
/// <param name="items"></param>
/// <param name="specials"></param>
/// <param name="extracts"></param>
/// <returns></returns>
public string AlllotExecute(string email, sys_hospital hospital, List<sys_hospitalconfig> configs, List<ex_module> modules, List<ex_item> items, List<ex_special> specials, List<ex_result> extracts, per_allot lastAllot, string path)
{
if (string.IsNullOrEmpty(path)) throw new PerformanceException("历史绩效文件不存在!");
var (tempPath, newPath) = CopyOriginalFile(hospital.ID, path);
workbook = new XSSFWorkbook(tempPath);
CreateNotExistSheet(modules, workbook);
style = CellStyle.CreateCellStyle(workbook, StyleType.数据);
List<AccountUnitEntity> unitList = new List<AccountUnitEntity>();
if (lastAllot != null)
{
var deptDict = perforPerdeptdicRepository.GetEntities(t => t.HospitalId == Allot.HospitalId);
var units = EnumHelper.GetItems<UnitType>();
if (deptDict != null && deptDict.Any())
{
unitList = deptDict.Select(t => new AccountUnitEntity
{
AccountingUnit = t.AccountingUnit,
Department = t.Department,
UnitType = units.FirstOrDefault(en => en.Description == t.UnitType)?.Value ?? 0
}).ToList();
}
logger.LogInformation($"lastAllot.ID: {lastAllot.ID}, lastAllot date: {lastAllot.Year}-{lastAllot.Month}, unitList count: {unitList?.Count ?? 0}");
}
for (int i = 0; i < workbook.NumberOfSheets; i++)
{
var sheet = workbook.GetSheetAt(i);
var sheetType = perSheetService.GetSheetType(sheet.SheetName);
var sheetRead = PerSheetDataFactory.GetDataRead(sheetType);
switch (sheetType)
{
case SheetType.Employee:
WriteEmployee(sheet, sheetRead, false);
break;
case SheetType.ClinicEmployee:
WriteClinicEmployee(sheet, sheetRead, false);
break;
case SheetType.OtherIncome:
ClearData(sheet, 5, 7);
WriteOtherIncome(sheet, sheetRead, unitList, modules, items, extracts, false);
break;
case SheetType.Income:
ClearData(sheet, 5, 7, true);
WriteIncome(sheet, sheetRead, unitList, modules, items, extracts, false);
break;
case SheetType.Expend:
ClearData(sheet, 5, 7);
WriteExpend(sheet, sheetRead, unitList, modules, items, extracts, false);
break;
case SheetType.Workload:
ClearData(sheet, 3, 3);
WriteWorkload(sheet, sheetRead, unitList, modules, items, extracts, false);
break;
case SheetType.AccountBasic:
WriteAccountBasic(sheet, sheetRead, false);
break;
case SheetType.SpecialUnit:
ClearData(sheet, 2, 0);
WriteSpecialUnit(sheet, sheetRead, specials, extracts, lastAllot, false);
break;
}
}
using (FileStream file = new FileStream(newPath, FileMode.OpenOrCreate))
{
workbook.Write(file);
}
logger.LogInformation($"提取绩效数据 {hospital.HosName}HIS数据提取成功,文件路径:{newPath}。");
ImportData(Allot, configs);
SendEmail(email, newPath, $"{hospital.HosName}HIS数据提取成功", $"{hospital.HosName}{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}成功提取。");
return newPath;
}
#endregion
#region QueryData
/// <summary>
/// 查询数据
/// </summary>
/// <param name="config"></param>
/// <param name="allot"></param>
/// <param name="execsql"></param>
/// <param name="source"></param>
/// <param name="category"></param>
/// <returns></returns>
private List<ex_result> QueryData(sys_hospitalconfig config, per_allot allot, string execsql, string source, string category = "")
{
var data = new List<ex_result>();
var parameters = GetParameters(allot);
using (var connection = ConnectionBuilder.Create((DatabaseType)config.DataBaseType, config.DbSource, config.DbName, config.DbUser, config.DbPassword))
{
foreach (var item in parameters)
{
execsql = Regex.Replace(execsql, item.Key, item.Value, RegexOptions.IgnoreCase);
}
logger.LogInformation($"提取绩效数据 {category ?? ""}SQL脚本{execsql}");
var result = connection.Query<ExtractDto>(execsql, commandTimeout: 20000);
logger.LogInformation($"提取绩效数据 {category ?? ""} 执行脚本获取数据{result?.Count() ?? 0}条记录");
if (result != null && result.Count() > 0)
{
data = result.Select(t => new ex_result
{
Department = t.Department,
Category = t.Category?.Trim(),
Fee = t.Value,
Source = source,
DatabaseType = config.DataBaseType,
ConfigId = config.Id,
AllotId = allot.ID,
}).ToList();
}
return data;
}
}
/// <summary>
/// 获取参数
/// </summary>
/// <param name="allot"></param>
/// <returns></returns>
private Dictionary<string, string> GetParameters(per_allot allot)
{
DateTime beginTime = new DateTime(allot.Year, allot.Month, 1);
Dictionary<string, string> pairs = new Dictionary<string, string>
{
{ "@beginTime", $"'{beginTime.ToString("yyyy-MM-dd")}'" },
{ "@endTime", $"'{beginTime.AddMonths(1).ToString("yyyy-MM-dd")}'"},
};
return pairs;
}
/// <summary>
/// 从HIS抽取报表数据
/// </summary>
/// <param name="allot"></param>
/// <param name="configs"></param>
public void ImportData(per_allot allot, List<sys_hospitalconfig> configs)
{
Dictionary<string, object> pairs = new Dictionary<string, object>
{
{ "@allotid", allot.ID },
{ "@hospitalid", allot.HospitalId },
{ "@year", allot.Year },
{ "@month", allot.Month },
};
var imports = repimportconfigRepository.GetEntities(w => w.ScriptType == 1);
if (imports == null || !imports.Any()) return;
foreach (var import in imports)
{
var conf = configs.FirstOrDefault(w => w.HospitalId == allot.HospitalId && w.Id == import.ConfigId);
if (conf != null)
{
var timeRanges = import.TimeRange.SplitRemoveEmpty(",");
if (timeRanges == null || !timeRanges.Any()) continue;
foreach (var item in timeRanges)
{
if (item == "1")
{
pairs["@year"] = allot.Year;
pairs["@month"] = allot.Month;
}
else if (item == "2")
{
pairs["@year"] = allot.Year - 1;
pairs["@month"] = allot.Month;
}
else if (item == "3")
{
pairs["@year"] = allot.Year;
pairs["@month"] = allot.Month - 1;
}
try
{
DatabaseType type = (DatabaseType)conf.DataBaseType;
var connection = ConnectionBuilder.Create(type, conf.DbSource, conf.DbName, conf.DbUser, conf.DbPassword);
var data = connection.Query(import.ImportScript, new DynamicParameters(pairs), commandTimeout: 60 * 60);
perforPerallotRepository.ImportData(import, pairs, data);
}
catch (Exception ex)
{
logger.LogError(ex.ToString());
}
}
}
}
}
#endregion
#region Excel
private (string TempPath, string NewPath) CopyOriginalFile(int hospitalId, string originalPath)
{
var dpath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Files", $"{hospitalId}", "autoextract");
FileHelper.CreateDirectory(dpath);
string tempPath = Path.Combine(dpath, $"Template{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.xlsx");
FileHelper.Copy(originalPath, tempPath);
string newPath = Path.Combine(dpath, $"绩效提取数据{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.xlsx");
return (tempPath, newPath);
}
private static void CreateNotExistSheet(List<ex_module> modulesList, IWorkbook workbook)
{
SortedDictionary<string, int> pairs = new SortedDictionary<string, int>();
for (int i = 0; i < workbook.NumberOfSheets; i++)
{
pairs.Add(workbook.GetSheetAt(i).SheetName, i);
}
int sheetIndex = 0;
foreach (var module in modulesList.Where(t => t.SheetType == (int)SheetType.Income)?.OrderBy(t => t.ModuleName))
{
var sheet = workbook.GetSheet(module.ModuleName);
if (sheet == null)
{
string[] keyArray = new string[] { "开单", "执行" };
if (keyArray.Any(key => module.ModuleName.Contains(key)))
{
var item = pairs.Where(t => t.Key.StartsWith("1.")).OrderByDescending(t => t.Key).First();
if (sheetIndex == 0)
sheetIndex = item.Value + 1;
var copysheet = workbook.GetSheet(item.Key);
var newSheet = copysheet.CopySheet(item.Key, true);
workbook.SetSheetOrder(newSheet.SheetName, sheetIndex);
workbook.SetSheetName(sheetIndex, module.ModuleName);
sheetIndex++;
}
}
}
}
private void ClearData(ISheet sheet, int beginRowNum, int beginCellNum, bool isIncome = false)
{
if (sheet == null)
return;
for (int i = beginRowNum; i < sheet.LastRowNum + 1; i++)
{
var row = sheet.GetRow(i);
if (row != null)
{
//跳过核算单元和科室
for (int j = beginCellNum; j < row.LastCellNum; j++)
{
var cell = row.GetCell(j);
if (cell != null && (cell.CellType != CellType.Formula || isIncome))
{
cell.RemoveCellComment();
row.RemoveCell(cell);
}
}
}
}
sheet.ForceFormulaRecalculation = true;
}
private (Dictionary<string, int> dictClear, Dictionary<string, int> dictVerify) ClearDataDict(ISheet sheet, IPerSheetDataRead sheetRead, List<string> header, int sheetType)
{
Dictionary<int, string[]> verify = new Dictionary<int, string[]>
{
{ (int)SheetType.Employee, new string[]{ "核算单元", "人员工号", "医生姓名" } },
{ (int)SheetType.ClinicEmployee, new string[]{ "核算单元", "人员工号", "医生姓名" } },
{ (int)SheetType.AccountBasic, new string[]{ "核算单元类型", "核算单元", "科室名称" } },
};
Dictionary<string, int> dictClear = new Dictionary<string, int>();
Dictionary<string, int> dictVerify = new Dictionary<string, int>();
var headRow = GetOrCreate(sheet, sheetRead.Point.HeaderFirstRowNum.Value + 0);
for (int i = 0; i < headRow.LastCellNum; i++)
{
var headvalue = headRow.GetCell(i)?.ToString()?.Trim();
if (string.IsNullOrEmpty(headvalue)) continue;
if (header.Contains(headvalue)) dictClear.Add(headvalue, i);
if (verify[sheetType].Contains(headvalue)) dictVerify.Add(headvalue, i);
}
return (dictClear, dictVerify);
}
private IRow GetOrCreate(ISheet sheet, int index)
{
var row = sheet.GetRow(index);
if (row == null)
row = sheet.CreateRow(index);
return row;
}
private ICell GetOrCreate(IRow row, int index)
{
var cell = row.GetCell(index);
if (cell == null)
cell = row.CreateCell(index);
//cell.CellStyle.FillBackgroundColor = NPOI.HSSF.Util.HSSFColor.Orange.Index;
return cell;
}
public void GenRowStyle(IRow r, ICellStyle cellStyle)
{
List<ICell> clist = r.Cells;
foreach (var cItem in clist)
{
cItem.CellStyle = cellStyle;
}
r.RowStyle = cellStyle;
}
#endregion
#region SheetData
private void WriteEmployee(ISheet sheet, IPerSheetDataRead sheetRead, bool isNewTemp = true)
{
var accountingunits = new string[] { AccountUnitType.行政高层.ToString(), AccountUnitType.行政中层.ToString(), AccountUnitType.行政工勤.ToString() };
var validData = perforPeremployeeRepository.GetEntities(t => t.AllotId == Allot.ID && accountingunits.Contains(t.UnitType))?.ToList();
if (validData == null || !validData.Any()) return;
Dictionary<string, Func<per_employee, object>> dict = new Dictionary<string, Func<per_employee, object>>
{
{ "人员分类", (t) => t.UnitType },
{ "核算单元", (t) => t.AccountingUnit },
{ "人员工号", (t) => t.PersonnelNumber },
{ "医生姓名", (t) => t.DoctorName },
{ "参加工作时间", (t) => t.WorkTime },
{ "出勤率", (t) => t.Attendance },
};
var lastnum = sheet.LastRowNum + 1;
var headRow = GetOrCreate(sheet, sheetRead.Point.HeaderFirstRowNum.Value + 0);
var beginRowIndex = sheetRead.Point.HeaderFirstRowNum.Value + 1;
// 清楚历史数据
if (!isNewTemp)
{
var (dictClear, dictVerify) = ClearDataDict(sheet, sheetRead, new List<string> { "出勤率" }, (int)SheetType.Employee);
var delEmployees = new List<per_employee>();
foreach (var item in validData)
{
if (beginRowIndex > lastnum) break;
var row = GetOrCreate(sheet, beginRowIndex);
var accountingunit = GetOrCreate(row, dictVerify["核算单元"]).ToString();
var personnel = GetOrCreate(row, dictVerify["人员工号"]).ToString();
var doctorname = GetOrCreate(row, dictVerify["医生姓名"]).ToString();
var employee = validData.FirstOrDefault(t => (t.AccountingUnit ?? "") == accountingunit && (t.PersonnelNumber ?? "") == personnel && (t.DoctorName ?? "") == doctorname);
if (employee == null)
{
//sheet.RemoveRow(row);
GenRowStyle(row, CellStyle.CreateCellStyle(workbook, StyleType.Remove));
beginRowIndex++;
continue;
}
else
{
foreach (var pair in dictClear)
{
if (pair.Value == -1) continue;
var cell = GetOrCreate(row, pair.Value);
cell.SetCellValue("");
}
//validData.Remove(employee);
delEmployees.Add(employee);
}
beginRowIndex++;
}
if (delEmployees.Any(t => t.Id > 0))
validData.RemoveAll(t => delEmployees.Select(e => e.Id).Contains(t.Id));
}
//新增数据
foreach (var item in validData)
{
var row = GetOrCreate(sheet, beginRowIndex);
for (int i = 0; i < headRow.LastCellNum; i++)
{
var headvalue = headRow.GetCell(i)?.ToString()?.Trim();
if (string.IsNullOrEmpty(headvalue) || !dict.ContainsKey(headvalue)) continue;
var func = dict[headvalue];
if (func != null)
{
var cell = GetOrCreate(row, i);
OutToExcelCell(cell, func.Invoke(item));
}
}
GenRowStyle(row, CellStyle.CreateCellStyle(workbook, StyleType.数据));
beginRowIndex++;
}
}
private void WriteClinicEmployee(ISheet sheet, IPerSheetDataRead sheetRead, bool isNewTemp = true)
{
var accountingunits = new string[] { AccountUnitType.行政高层.ToString(), AccountUnitType.行政中层.ToString(), AccountUnitType.行政工勤.ToString() };
var validData = perforPeremployeeRepository.GetEntities(t => t.AllotId == Allot.ID && !accountingunits.Contains(t.UnitType))?.ToList();
if (validData == null || !validData.Any()) return;
Dictionary<string, Func<per_employee, object>> dict = new Dictionary<string, Func<per_employee, object>>
{
{ "核算单元分类", (t) => t.UnitType },
{ "核算单元", (t) => t.AccountingUnit },
{ "人员工号", (t) => t.PersonnelNumber },
{ "医生姓名", (t) => t.DoctorName },
{ "职务分类", (t) => t.JobTitle },
{ "出勤率", (t) => t.Attendance },
};
var lastnum = sheet.LastRowNum + 1;
var headRow = GetOrCreate(sheet, sheetRead.Point.HeaderFirstRowNum.Value + 0);
var beginRowIndex = sheetRead.Point.HeaderFirstRowNum.Value + 1;
// 清楚历史数据
if (!isNewTemp)
{
var (dictClear, dictVerify) = ClearDataDict(sheet, sheetRead, new List<string> { "出勤率" }, (int)SheetType.ClinicEmployee);
var delEmployees = new List<per_employee>();
foreach (var item in validData)
{
if (beginRowIndex > lastnum) break;
var row = GetOrCreate(sheet, beginRowIndex);
var accountingunit = GetOrCreate(row, dictVerify["核算单元"]).ToString();
var personnel = GetOrCreate(row, dictVerify["人员工号"]).ToString();
var doctorname = GetOrCreate(row, dictVerify["医生姓名"]).ToString();
var employee = validData.FirstOrDefault(t => (t.AccountingUnit ?? "") == accountingunit && (t.PersonnelNumber ?? "") == personnel && (t.DoctorName ?? "") == doctorname);
if (employee == null)
{
//sheet.RemoveRow(row);
GenRowStyle(row, CellStyle.CreateCellStyle(workbook, StyleType.Remove));
beginRowIndex++;
continue;
}
else
{
foreach (var pair in dictClear)
{
if (pair.Value == -1) continue;
var cell = GetOrCreate(row, pair.Value);
cell.SetCellValue("");
}
//validData.Remove(employee);
delEmployees.Add(employee);
}
beginRowIndex++;
}
if (delEmployees.Any(t => t.Id > 0))
validData.RemoveAll(t => delEmployees.Select(e => e.Id).Contains(t.Id));
}
//新增数据
foreach (var item in validData)
{
var row = GetOrCreate(sheet, beginRowIndex);
for (int i = 0; i < headRow.LastCellNum; i++)
{
var headvalue = headRow.GetCell(i)?.ToString()?.Trim();
if (string.IsNullOrEmpty(headvalue) || !dict.ContainsKey(headvalue)) continue;
var func = dict[headvalue];
if (func != null)
{
var cell = GetOrCreate(row, i);
OutToExcelCell(cell, func.Invoke(item));
}
}
GenRowStyle(row, CellStyle.CreateCellStyle(workbook, StyleType.数据));
beginRowIndex++;
}
}
private void WriteAccountBasic(ISheet sheet, IPerSheetDataRead sheetRead, bool isNewTemp = true)
{
var accountingunits = new string[] { AccountUnitType.行政高层.ToString(), AccountUnitType.行政中层.ToString(), AccountUnitType.行政工勤.ToString() };
var validData = perforPeremployeeRepository.GetEntities(t => t.AllotId == Allot.ID && !accountingunits.Contains(t.UnitType))?.ToList();
if (validData == null || !validData.Any()) return;
#region 计算数据
bool duty(per_employee t) => !string.IsNullOrEmpty(t.Duty) && (t.Duty.IndexOf("科主任") > -1 || t.Duty.IndexOf("副主任") > -1
|| t.Duty.IndexOf("护士长") > -1 || t.Duty.IndexOf("副护士长") > -1);
var groupData = validData.GroupBy(t => new { t.Department, t.UnitType }).Select(t => new AccountBasic
{
UnitType = t.Key.UnitType,
Department = t.Key.Department,
AccountingUnit = t.FirstOrDefault(group => group.Department == t.Key.Department)?.AccountingUnit,
EfficiencyNumber = t.Sum(group => group.EfficiencyNumber),
DirectorNumber = t.Count(duty),
PermanentStaff = t.Sum(group => group.PermanentStaff * group.Attendance),
IsDelete = 0,
}).OrderBy(t => t.UnitType).ThenBy(t => t.AccountingUnit).ToList();
Dictionary<string, Func<dynamic, object>> dict = new Dictionary<string, Func<dynamic, object>>
{
{ "核算单元类型", (t) => t.UnitType },
{ "核算单元", (t) => t.AccountingUnit },
{ "科室名称", (t) => t.Department },
{ "效率绩效人数", (t) => t.EfficiencyNumber },
{ "科主任/护士长人数", (t) => t.DirectorNumber },
{ "核算单元人员数量", (t) => t.PermanentStaff },
};
#endregion
var lastnum = sheet.LastRowNum + 1;
var headRow = GetOrCreate(sheet, sheetRead.Point.HeaderFirstRowNum.Value + 0);
var beginRowIndex = sheetRead.Point.HeaderFirstRowNum.Value + 1;
// 清楚历史数据
if (!isNewTemp)
{
var (dictClear, dictVerify) = ClearDataDict(sheet, sheetRead, new List<string> { "效率绩效人数", "科主任/护士长人数", "核算单元人员数量" }, (int)SheetType.AccountBasic);
foreach (var item in groupData)
{
if (beginRowIndex > lastnum) break;
var row = GetOrCreate(sheet, beginRowIndex);
var unittype = GetOrCreate(row, dictVerify["核算单元类型"]).ToString();
var accountingunit = GetOrCreate(row, dictVerify["核算单元"]).ToString();
var department = GetOrCreate(row, dictVerify["科室名称"]).ToString();
var data = groupData.FirstOrDefault(t => (t.UnitType ?? "") == unittype && (t.AccountingUnit ?? "") == accountingunit && (t.Department ?? "") == department);
if (data == null)
{
//sheet.RemoveRow(row);
GenRowStyle(row, CellStyle.CreateCellStyle(workbook, StyleType.Remove));
beginRowIndex++;
continue;
}
else
{
foreach (var pair in dictClear)
{
if (pair.Value == -1) continue;
var cell = GetOrCreate(row, pair.Value);
cell.SetCellValue("");
}
data.IsDelete = 1;
}
beginRowIndex++;
}
}
//新增数据
foreach (var item in groupData.Where(t => t.IsDelete == 0))
{
var row = GetOrCreate(sheet, beginRowIndex);
for (int i = 0; i < headRow.LastCellNum; i++)
{
var headvalue = headRow.GetCell(i)?.ToString()?.Trim();
if (string.IsNullOrEmpty(headvalue) || !dict.ContainsKey(headvalue)) continue;
var func = dict[headvalue];
if (func != null)
{
var cell = GetOrCreate(row, i);
OutToExcelCell(cell, func.Invoke(item));
}
}
GenRowStyle(row, CellStyle.CreateCellStyle(workbook, StyleType.数据));
beginRowIndex++;
}
}
private void WriteOtherIncome(ISheet sheet, IPerSheetDataRead sheetRead, List<AccountUnitEntity> unitList, List<ex_module> modules, List<ex_item> items, List<ex_result> data, bool isNewTemp = true)
{
logger.LogInformation($"{sheet.SheetName}开始执行写入.");
var module = modules.FirstOrDefault(t => t.SheetType == (int)SheetType.OtherIncome);
if (module == null) return;
var itemList = items.Where(t => t.ModuleId == module.Id);
logger.LogInformation($"item有{itemList?.Count() ?? 0}个.");
if (itemList == null || !itemList.Any()) return;
logger.LogInformation($"{sheet.SheetName}开始写入列头系数.");
WriteHeaderAndFactor(sheet, sheetRead, itemList.ToList(), isNewTemp);
var extractdata = data.Where(t => t.AllotId == Allot.ID && t.Source == module.ModuleName);
logger.LogInformation($"data有{extractdata?.Count() ?? 0}个.");
if (extractdata == null || !extractdata.Any())
return;
//查询数据
List<ExtractDto> allExtract = extractdata.Select(t => new ExtractDto { Department = t.Department, Category = t.Category, Value = t.Fee ?? 0 }).ToList();
logger.LogInformation($"{sheet.SheetName}开始写入数据.");
WriteSheetData(sheet, sheetRead, unitList, allExtract, itemList.Select(t => t.ItemName), isNewTemp);
logger.LogInformation($"{sheet.SheetName}写入结束.");
}
private void WriteIncome(ISheet sheet, IPerSheetDataRead sheetRead, List<AccountUnitEntity> unitList, List<ex_module> modules, List<ex_item> items, List<ex_result> data, bool isNewTemp = true)
{
logger.LogInformation($"{sheet.SheetName}开始执行写入.");
var module = modules.FirstOrDefault(t => t.ModuleName.Replace(" ", "") == sheet.SheetName.Replace(" ", ""));
if (module == null) return;
var itemList = items.Where(t => t.ModuleId == module.Id)?.ToList() ?? new List<ex_item>();
var extractdata = data.Where(t => t.AllotId == Allot.ID && t.Source == module.ModuleName);
logger.LogInformation($"data有{extractdata?.Count() ?? 0}个.");
if (extractdata == null || !extractdata.Any())
{
var itemCount = itemList?.Count ?? 0;
logger.LogInformation($"item有{itemCount}个.");
if (itemCount > 0) WriteHeaderAndFactor(sheet, sheetRead, itemList, isNewTemp);
return;
}
//查询数据
List<ExtractDto> allExtract = extractdata.Select(t => new ExtractDto { Department = t.Department, Category = t.Category, Value = t.Fee ?? 0 }).ToList();
var category = allExtract.Select(t => t.Category?.Trim()).Distinct().ToList();
var existHead = category.Except(itemList.Select(i => i.ItemName?.Trim()));
if (existHead != null && existHead.Any())
itemList.AddRange(existHead.Select(t => new ex_item { ItemName = t, FactorValue1 = 0, FactorValue2 = 0, FactorValue3 = 0 }));
logger.LogInformation($"item有{itemList?.Count ?? 0}个.{sheet.SheetName}开始写入列头系数.");
WriteHeaderAndFactor(sheet, sheetRead, itemList, isNewTemp);
logger.LogInformation($"{sheet.SheetName}开始写入数据.");
WriteSheetData(sheet, sheetRead, unitList, allExtract, itemList.Select(t => t.ItemName), isNewTemp, true);
logger.LogInformation($"{sheet.SheetName}写入结束.");
}
private void WriteExpend(ISheet sheet, IPerSheetDataRead sheetRead, List<AccountUnitEntity> unitList, List<ex_module> modules, List<ex_item> items, List<ex_result> data, bool isNewTemp = true)
{
logger.LogInformation($"{sheet.SheetName}开始执行写入.");
var module = modules.FirstOrDefault(t => t.SheetType == (int)SheetType.Expend);
if (module == null) return;
var itemList = items.Where(t => t.ModuleId == module.Id);
logger.LogInformation($"item有{itemList?.Count() ?? 0}个.");
if (itemList == null || !itemList.Any()) return;
logger.LogInformation($"{sheet.SheetName}开始写入列头系数.");
WriteHeaderAndFactor(sheet, sheetRead, itemList.ToList(), isNewTemp);
var extractdata = data.Where(t => t.AllotId == Allot.ID && t.Source == module.ModuleName);
logger.LogInformation($"data有{extractdata?.Count() ?? 0}个.");
if (extractdata == null || !extractdata.Any())
return;
//查询数据
List<ExtractDto> allExtract = extractdata.Select(t => new ExtractDto { Department = t.Department, Category = t.Category, Value = t.Fee ?? 0 }).ToList();
logger.LogInformation($"{sheet.SheetName}开始写入数据.");
WriteSheetData(sheet, sheetRead, unitList, allExtract, itemList.Select(t => t.ItemName), isNewTemp);
logger.LogInformation($"{sheet.SheetName}写入结束.");
}
private void WriteWorkload(ISheet sheet, IPerSheetDataRead sheetRead, List<AccountUnitEntity> unitList, List<ex_module> modules, List<ex_item> items, List<ex_result> data, bool isNewTemp = true)
{
logger.LogInformation($"{sheet.SheetName}开始执行写入.");
var module = modules.FirstOrDefault(t => t.ModuleName.Replace(" ", "") == sheet.SheetName.Replace(" ", ""));
if (module == null) return;
var itemList = items.Where(t => t.ModuleId == module.Id);
logger.LogInformation($"item有{itemList?.Count() ?? 0}个.");
if (itemList == null || !itemList.Any()) return;
logger.LogInformation($"{sheet.SheetName}开始写入列头系数.");
WriteWorkHeader(sheet, sheetRead, itemList.ToList(), isNewTemp);
var extractdata = data.Where(t => t.AllotId == Allot.ID && t.Source == module.ModuleName);
logger.LogInformation($"data有{extractdata?.Count() ?? 0}个.");
if (extractdata == null || !extractdata.Any())
return;
//查询数据
List<ExtractDto> allExtract = extractdata.Select(t => new ExtractDto { Department = t.Department, Category = t.Category, Value = t.Fee ?? 0 }).ToList();
var specialHead = new List<string>();
var extractHead = allExtract?.Select(t => t.Category);
if (extractHead != null && extractHead.Any())
specialHead = itemList.Select(t => t.ItemName).Intersect(extractHead.Distinct())?.ToList(); // 有数据的列添加样式
//写入数据
logger.LogInformation($"{sheet.SheetName}开始写入数据.");
WriteWorkData(sheet, sheetRead, unitList, allExtract, specialHead, isNewTemp);
logger.LogInformation($"{sheet.SheetName}写入结束.");
}
private void WriteSpecialUnit(ISheet sheet, IPerSheetDataRead sheetRead, List<ex_special> specials, List<ex_result> data, per_allot lastAllot = null, bool IsWriteHead = true)
{
logger.LogInformation($"{sheet.SheetName}开始执行写入.");
var dictionary = new Dictionary<string, Func<ex_special, List<im_specialunit>, object>>
{
{ "科室", (special,lastallot) => special.Department },
{ "人数", (special,lastallot) => lastallot.Where(t=>special.Department == t.Department).Max(t=>t.Number) },
{ "量化指标", (special,lastallot) => special.Target},
{ "量化指标绩效分值",(special,lastallot) => special.TargetFactor },
{ "调节系数", (special,lastallot) => special.AdjustFactor },
};
var speaialList = specials?.OrderBy(t => t.Department).ToList();
logger.LogInformation($"item有{speaialList?.Count ?? 0}个.");
if (speaialList == null || !speaialList.Any()) return;
List<im_specialunit> allotDataList = new List<im_specialunit>();
if (lastAllot != null)
allotDataList = perforImspecialunitRepository.GetEntities(t => t.AllotID == lastAllot.ID);
//取消合并单元格
int mergedCount = sheet.NumMergedRegions;
for (int i = mergedCount - 1; i >= 0; i--)
{
var temp = sheet.GetMergedRegion(i);
if (temp.FirstRow > sheetRead.Point.HeaderFirstRowNum)
sheet.RemoveMergedRegion(i);
}
var modDataGroup = speaialList.GroupBy(t => new { t.Department }).Select(group => new
{
Department = group.Key.Department,
Count = group.Count()
})?.OrderBy(t => t.Department);
int mergedBegin = sheetRead.Point.DataFirstRowNum.Value;
int mergedEnd = sheetRead.Point.DataFirstRowNum.Value;
var extractdata = data.Where(t => t.AllotId == Allot.ID && t.Source == specialname).ToList();
logger.LogInformation($"data有{extractdata?.Count ?? 0}个.");
logger.LogInformation($"{sheet.SheetName}开始写入数据.");
for (int i = 0; i < speaialList.Count; i++)
{
var headIndex = sheetRead.Point.HeaderFirstRowNum;
var cellList = sheet.GetRow(headIndex.Value).Cells;
var rowIndex = sheetRead.Point.DataFirstRowNum.Value + i;
var importRow = sheet.CreateRow(rowIndex);
int cellIndex = 0;
foreach (var cell in cellList)
{
object value = null;
if (dictionary.ContainsKey(cell.StringCellValue))
{
var item = dictionary.First(t => t.Key == cell.StringCellValue);
value = item.Value.Invoke(speaialList[i], allotDataList) ?? "";
if (item.Key == "科室" && rowIndex == mergedBegin)
{
var count = modDataGroup.First(t => t.Department.ToString() == value.ToString()).Count;
mergedEnd = mergedBegin + count - 1;
}
}
if (cell.StringCellValue == "数量" && speaialList[i]?.TypeId > 0)
{
value = extractdata?.FirstOrDefault(t => t.Category == speaialList[i].Target)?.Fee;
}
if (!new List<string> { "量化指标", "数量", "量化指标绩效分值" }.Contains(cell.StringCellValue) && rowIndex == mergedBegin)
{
CellRangeAddress region = new CellRangeAddress(mergedBegin, mergedEnd, cellIndex, cellIndex);
sheet.AddMergedRegion(region); //合并单元格
}
var newCell = importRow.CreateCell(cellIndex);
//newCell.SetCellValue(Verify(value));
OutToExcelCell(newCell, value);
if (dictionary.ContainsKey(cell.StringCellValue) || (cell.StringCellValue == "数量" && !string.IsNullOrEmpty(value?.ToString())))
newCell.CellStyle = style;
cellIndex++;
}
mergedBegin = mergedEnd + 1;
}
logger.LogInformation($"{sheet.SheetName}写入结束.");
}
#region 写入数据
/// <summary>
/// 写入列头
/// </summary>
/// <param name="sheet"></param>
/// <param name="sheetRead"></param>
/// <param name="items">列头数据(列名、系数)</param>
/// <param name="isNewTemp">是否为空白模板</param>
private void WriteHeaderAndFactor(ISheet sheet, IPerSheetDataRead sheetRead, List<ex_item> items, bool isNewTemp)
{
var nurseFactor = sheet.GetRow(sheetRead.Point.AccountingUnit.First(t => t.UnitType == "护理组").FactorRow.Value);
var doctorFactor = sheet.GetRow(sheetRead.Point.AccountingUnit.First(t => t.UnitType == "医生组").FactorRow.Value);
var technicianFactor = sheet.GetRow(sheetRead.Point.AccountingUnit.First(t => t.UnitType == "医技组").FactorRow.Value);
var head = GetOrCreate(sheet, sheetRead.Point.HeaderFirstRowNum.Value);
logger.LogInformation($"提取绩效数据 提取绩效数据 写入列头信息 -- {sheet.SheetName}");
var cellItems = new List<ex_item>();
cellItems.AddRange(items);
if (!isNewTemp)
{
List<string> original = new List<string>();
#region 过滤历史模板中已有的列头
//写入列头信息
int cellStartIndex = sheetRead.Point.HeaderFirstCellNum.Value + 4;
for (int i = cellStartIndex; i < head.LastCellNum; i++)
{
var cellvalue = head.GetCell(i)?.ToString()?.Trim();
if (string.IsNullOrEmpty(cellvalue)) continue;
cellItems.RemoveAll(t => t.ItemName == cellvalue);
}
#endregion
}
if (cellItems == null || !cellItems.Any()) return;
#region 新增模板中不存在的列头
var lastcellIndex = isNewTemp ? sheetRead.Point.HeaderFirstCellNum.Value + 4 : head.LastCellNum;
foreach (var item in cellItems)
{
var headcell = GetOrCreate(head, lastcellIndex);
headcell.SetCellValue(item.ItemName);
headcell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.列头);
var doctorcell = GetOrCreate(doctorFactor, lastcellIndex);
doctorcell.SetCellValue(item.FactorValue1 != null ? (double)item.FactorValue1 : 0);
doctorcell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.系数, CellFormat.百分比);
var nursecell = GetOrCreate(nurseFactor, lastcellIndex);
nursecell.SetCellValue(item.FactorValue2 != null ? (double)item.FactorValue2 : 0);
nursecell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.系数, CellFormat.百分比);
var techniciancell = GetOrCreate(technicianFactor, lastcellIndex);
techniciancell.SetCellValue(item.FactorValue3 != null ? (double)item.FactorValue3 : 0);
techniciancell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.系数, CellFormat.百分比);
lastcellIndex++;
}
#endregion
}
/// <summary>
/// 写入数据
/// </summary>
/// <param name="sheet"></param>
/// <param name="sheetRead"></param>
/// <param name="unitList">核算单元</param>
/// <param name="allExtract">抽取的数据(科室、列头、数据)</param>
/// <param name="header">设定抽取的列头</param>
/// <param name="isNewTemp">是否为空白模板</param>
/// <param name="isIncom">是否是开单、执行收入</param>
private void WriteSheetData(ISheet sheet, IPerSheetDataRead sheetRead, List<AccountUnitEntity> unitList, List<ExtractDto> allExtract, IEnumerable<string> header, bool isNewTemp, bool isIncom = false)
{
logger.LogInformation($"提取绩效数据 填充数据 -- {sheet.SheetName}");
//写入数据
var head = GetOrCreate(sheet, sheetRead.Point.HeaderFirstRowNum.Value);
var rowIndex = sheetRead.Point.HeaderFirstRowNum.Value + 1;
if (!isNewTemp)
{
#region 给历史模板已有科室补充数据
for (int i = rowIndex; i < sheet.LastRowNum + 1; i++)
{
var row = sheet.GetRow(i);
if (row != null)
{
var department = row.GetCell(6)?.ToString(); // 科室名称
if (string.IsNullOrEmpty(department)) continue;
var deptData = allExtract.Where(t => t.Department == department);
if (deptData == null || !deptData.Any()) continue;
for (int j = 7; j < head.LastCellNum; j++)
{
var headName = head.GetCell(j).StringCellValue;
var newCell = GetOrCreate(row, j);
if (newCell == null) continue;
var value = deptData.FirstOrDefault(t => t.Category == headName)?.Value;
if (isIncom)
{
value = value == 0 ? null : value;
OutToExcelCell(newCell, value);
newCell.CellStyle = style;
}
else if (newCell.CellType != CellType.Formula)
{
value = value == 0 ? null : value;
OutToExcelCell(newCell, value);
if (header != null && header.Contains(headName))
newCell.CellStyle = style;
}
}
allExtract.RemoveAll(t => t.Department == department);
}
}
#endregion
}
if (allExtract == null || !allExtract.Any()) return;
#region 补充新的科室及数据
var lastrowIndex = isNewTemp ? rowIndex : sheet.LastRowNum + 1;
foreach (var department in allExtract.Select(t => t.Department).Where(t => !string.IsNullOrEmpty(t)).Distinct())
{
var row = sheet.CreateRow(lastrowIndex);
for (int i = head.FirstCellNum + 3; i < head.LastCellNum; i++)
{
var headName = head.GetCell(i).StringCellValue;
var newCell = row.CreateCell(i);
if (headName.Replace("\n", "") == "核算单元(医生组)")
{
var dept = unitList.FirstOrDefault(t => t.Department == department && t.UnitType == (int)UnitType.医生组)?.AccountingUnit;
newCell.SetCellValue(dept ?? "");
newCell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.默认);
}
else if (headName.Replace("\n", "") == "核算单元(护理组)")
{
var dept = unitList.FirstOrDefault(t => t.Department == department && t.UnitType == (int)UnitType.护理组)?.AccountingUnit;
newCell.SetCellValue(dept ?? "");
newCell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.默认);
}
else if (headName.Replace("\n", "") == "核算单元(医技组)")
{
var dept = unitList.FirstOrDefault(t => t.Department == department && t.UnitType == (int)UnitType.医技组)?.AccountingUnit;
newCell.SetCellValue(dept ?? "");
newCell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.默认);
}
else if (headName == "科室名称")
{
newCell.SetCellValue(department ?? "");
newCell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.默认);
}
else
{
var value = allExtract.FirstOrDefault(t => t.Department == department && t.Category == headName)?.Value;
if (isIncom)
{
value = value == 0 ? null : value;
OutToExcelCell(newCell, value);
newCell.CellStyle = style;
}
else if (header != null && header.Contains(headName))
{
value = value == 0 ? null : value;
OutToExcelCell(newCell, value);
newCell.CellStyle = style;
}
}
}
lastrowIndex++;
}
#endregion
}
/// <summary>
/// 写入工作量列头
/// </summary>
/// <param name="sheet"></param>
/// <param name="sheetRead"></param>
/// <param name="items"></param>
/// <param name="isNewTemp"></param>
private void WriteWorkHeader(ISheet sheet, IPerSheetDataRead sheetRead, List<ex_item> items, bool isNewTemp)
{
var head = GetOrCreate(sheet, sheetRead.Point.HeaderFirstRowNum.Value + 0);
var factor = GetOrCreate(sheet, sheetRead.Point.HeaderFirstRowNum.Value + 1);
var cellItems = new List<ex_item>();
cellItems.AddRange(items);
if (!isNewTemp)
{
#region 过滤历史模板中已有的列头
//写入列头信息
int cellStartIndex = sheetRead.Point.HeaderFirstCellNum.Value + 2;
for (int i = cellStartIndex; i < head.LastCellNum; i++)
{
var cellvalue = head.GetCell(i)?.ToString();
if (string.IsNullOrEmpty(cellvalue)) continue;
cellItems.RemoveAll(t => t.ItemName == cellvalue);
}
#endregion
}
if (cellItems == null || !cellItems.Any()) return;
#region 新增模板中不存在的列头
var lastcellIndex = isNewTemp ? sheetRead.Point.HeaderFirstCellNum.Value + 2 : head.LastCellNum;
foreach (var item in cellItems)
{
var headcell = GetOrCreate(head, lastcellIndex);
headcell.SetCellValue(item.ItemName);
headcell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.列头);
var doctorcell = GetOrCreate(factor, lastcellIndex);
doctorcell.SetCellValue(item.FactorValue1 != null ? (double)item.FactorValue1 : 0);
doctorcell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.列头, CellFormat.数字2);
lastcellIndex++;
}
#endregion
}
/// <summary>
/// 写入工作量数据
/// </summary>
/// <param name="sheet"></param>
/// <param name="sheetRead"></param>
/// <param name="unitList"></param>
/// <param name="allExtract"></param>
/// <param name="header"></param>
/// <param name="isNewTemp"></param>
private void WriteWorkData(ISheet sheet, IPerSheetDataRead sheetRead, List<AccountUnitEntity> unitList, List<ExtractDto> allExtract, IEnumerable<string> header, bool isNewTemp)
{
var head = GetOrCreate(sheet, sheetRead.Point.HeaderFirstRowNum.Value + 0);
var rowIndex = sheetRead.Point.HeaderFirstRowNum.Value + 2;
if (!isNewTemp)
{
#region 给历史模板已有科室补充数据
for (int i = rowIndex; i < sheet.LastRowNum + 1; i++)
{
var row = sheet.GetRow(i);
if (row != null)
{
var department = row.GetCell(2)?.ToString(); // 科室名称
if (string.IsNullOrEmpty(department)) continue;
var deptData = allExtract.Where(t => t.Department == department);
if (deptData == null || !deptData.Any()) continue;
for (int j = 3; j < head.LastCellNum; j++)
{
var headName = head.GetCell(j).StringCellValue;
var newCell = GetOrCreate(row, j);
if (newCell == null) continue;
if (newCell.CellType != CellType.Formula)
{
var extract = deptData.FirstOrDefault(t => t.Category == headName);
var value = extract?.Value == 0 ? null : extract?.Value;
OutToExcelCell(newCell, value);
if (header != null && header.Contains(headName))
newCell.CellStyle = style;
}
}
allExtract.RemoveAll(t => t.Department == department);
}
}
#endregion
}
if (allExtract == null || !allExtract.Any()) return;
var unit = sheet.SheetName.IndexOf("医生") > -1 ? new int[] { (int)UnitType.医生组, (int)UnitType.医技组 } : new int[] { (int)UnitType.护理组 };
#region 补充新的科室及数据
var lastrowIndex = isNewTemp ? rowIndex : sheet.LastRowNum + 1;
foreach (var department in allExtract.Select(t => t.Department).Where(t => !string.IsNullOrEmpty(t)).Distinct())
{
var row = sheet.CreateRow(lastrowIndex);
for (int i = head.FirstCellNum + 1; i < head.LastCellNum; i++)
{
var headName = head.GetCell(i).StringCellValue;
var newCell = row.CreateCell(i);
if (headName == "核算单元")
{
var dept = unitList.FirstOrDefault(t => unit.Contains(t.UnitType) && t.Department == department)?.AccountingUnit
?? unitList.FirstOrDefault(t => t.Department == department)?.AccountingUnit;
newCell.SetCellValue(dept ?? "");
newCell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.默认);
}
else if (headName == "科室名称")
{
newCell.SetCellValue(department ?? "");
newCell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.默认);
}
else
{
var extract = allExtract.FirstOrDefault(t => t.Department == department && t.Category == headName);
var value = extract?.Value == 0 ? null : extract?.Value;
OutToExcelCell(newCell, value);
if (header != null && header.Contains(headName))
newCell.CellStyle = style;
}
}
lastrowIndex++;
}
#endregion
}
#endregion
#endregion
#region Common
/// <summary>
/// 发送邮件
/// </summary>
/// <param name="path"></param>
/// <param name="subject"></param>
/// <param name="body"></param>
private void SendEmail(string mail, string path, string subject, string body)
{
if (string.IsNullOrEmpty(mail)) return;
var message = new EmailMessage
{
To = new List<string> { mail },
DisplayName = "溯直健康",
Subject = subject,
Body = body
};
if (!string.IsNullOrEmpty(path))
message.Attachments = new List<string> { path };
emailService.Send(message);
}
/// <summary>
/// 校验数据格式,并转换
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public void OutToExcelCell(ICell cell, object obj)
{
string value = obj?.ToString() ?? "";
try
{
var type = obj?.GetType() ?? typeof(string);
switch (type.ToString())
{
case "System.String"://字符串类型
cell.SetCellValue(value);
break;
case "System.DateTime"://日期类型
DateTime dateV;
DateTime.TryParse(value, out dateV);
cell.SetCellValue(dateV.ToString("yyyy/M/d"));
break;
case "System.Boolean"://布尔型
bool boolV = false;
bool.TryParse(value, out boolV);
cell.SetCellValue(boolV);
break;
case "System.Int16"://整型
case "System.Int32":
case "System.Int64":
case "System.Byte":
int intV = 0;
int.TryParse(value, out intV);
cell.SetCellValue(intV);
break;
case "System.Decimal"://浮点型
case "System.Double":
double doubV = 0;
double.TryParse(value, out doubV);
cell.SetCellValue(doubV);
break;
case "System.DBNull"://空值处理
cell.SetCellValue("");
break;
default:
cell.SetCellValue("");
break;
}
}
catch
{
cell.SetCellValue(value);
}
}
#endregion
#region 配置校验
/// <summary>
/// 配置校验
/// </summary>
/// <param name="allotId"></param>
/// <param name="hospitalId"></param>
/// <param name="useTemplate"></param>
public string Judge(int allotId, int hospitalId, int useTemplate, out string filePath)
{
string result = null;
filePath = "";
try
{
// 获取绩效信息
var allot = perforPerallotRepository.GetEntity(t => t.ID == allotId);
if (allot == null)
throw new PerformanceException("AllotID错误");
// 获取医院信息
var hospital = perforHospitalRepository.GetEntity(t => t.ID == hospitalId);
if (hospital == null)
throw new PerformanceException("医院ID错误");
// 获取医院配置信息
var hospitalConfigList = perforHospitalconfigRepository.GetEntities(t => t.HospitalId == hospitalId);
if (hospitalConfigList == null || hospitalConfigList.Count == 0)
throw new PerformanceException("当前医院暂不支持HIS数据抽取");
// 获取最近一次绩效
var statesArray = new int[] { (int)AllotStates.GenerateSucceed, (int)AllotStates.Archive };
var allotList = perforPerallotRepository.GetEntities(t => t.HospitalId == hospitalId && statesArray.Contains(t.States));
var allotLast = allotList?.OrderByDescending(t => t.Year).ThenByDescending(t => t.Month).First();
if (allotLast != null)
filePath = allotLast.Path;
// 获取当前医院模版信息
var modulesList = perforExmoduleRepository.GetEntities(t => t.HospitalId == hospitalId);
if (modulesList == null || modulesList.Count == 0)
throw new PerformanceException("当前医院还未配置模版");
// 获取模板项
var moduleIdList = modulesList.Select(t => t.Id).ToList();
var itemsList = perforExitemRepository.GetEntities(t => t.ModuleId.HasValue && moduleIdList.Contains(t.ModuleId.Value));
if (itemsList == null || itemsList.Count == 0)
throw new PerformanceException("当前医院还未配置模版项");
// 获取当前模板所有相关抽取SQL语句
var extypeIds = itemsList.Select(t => t.TypeId).Union(modulesList.Select(t => t.TypeId)).Distinct().ToList();
var extractList = perforExscriptRepository.GetEntities(t => extypeIds.Contains(t.TypeId));
if (extractList == null || extractList.Count == 0)
throw new PerformanceException("当前医院配置模板无需抽取");
}
catch (PerformanceException ex)
{
logger.LogError($"提取绩效数据异常 {ex.ToString()}");
result = ex.Message;
}
catch (Exception ex)
{
logger.LogError($"提取绩效数据异常 {ex.ToString()}");
throw new Exception(ex.Message);
}
return result;
}
#endregion
}
public class AccountBasic
{
public string UnitType { get; set; }
public string Department { get; set; }
public string AccountingUnit { get; set; }
public decimal? EfficiencyNumber { get; set; }
public decimal? DirectorNumber { get; set; }
public decimal? PermanentStaff { get; set; }
public int IsDelete { get; set; }
}
}
......@@ -375,16 +375,30 @@ private bool QueryAndAddItem(List<sys_hospitalconfig> hospitalconfigs, string sq
{
var connection = ConnectionBuilder.Create((DatabaseType)hospitalConfig.DataBaseType, hospitalConfig.DbSource, hospitalConfig.DbName, hospitalConfig.DbUser, hospitalConfig.DbPassword);
logger.LogInformation($"执行sql:{sql}");
var dataList = extractRepository.ExecuteScript(connection, sql, null);
logger.LogInformation($"获取数据{dataList?.Count ?? 0}条");
if (dataList != null && dataList.Any())
itemNames.AddRange(dataList.Select(t => t.Value.ToString()));
try
{
var dataList = extractRepository.ExecuteScript(connection, sql, null);
logger.LogInformation($"获取数据{dataList?.Count ?? 0}条");
if (dataList != null && dataList.Any())
itemNames.AddRange(dataList.Select(t => t.Value.ToString()));
}
catch (Exception ex)
{
logger.LogError(ex.ToString());
}
}
var items = exitemRepository.GetEntities(t => t.ModuleId == module.Id);
if (items == null && (itemNames == null || !itemNames.Any()))
return true;
var delItems = items?.Where(t => !itemNames.Contains(t.ItemName));
if (delItems != null && delItems.Any())
{
logger.LogInformation($"删除默认收费项 受影响行数{delItems.Count()}");
exitemRepository.RemoveRange(delItems.ToArray());
}
if (itemNames != null && itemNames.Any(t => !string.IsNullOrEmpty(t)))
{
if (items != null)
......
using AutoMapper;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Performance.DtoModels;
using Performance.DtoModels.AppSettings;
using Performance.EntityModels;
using Performance.Infrastructure;
using Performance.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace Performance.Services
......@@ -18,6 +21,10 @@ public class PersonService : IAutoInjection
private readonly PerforPerdeptdicRepository perdeptdicRepository;
private readonly PerforPeremployeeRepository peremployeeRepository;
private readonly PerforPerallotRepository perallotRepository;
private readonly PerforUserRepository perforUserRepository;
private readonly PerforUserroleRepository perforUserroleRepository;
private readonly PerforRoleRepository perforRoleRepository;
private readonly Application application;
private readonly Dictionary<string, (string, string)> dict = new Dictionary<string, (string, string)>
{
{ nameof(DeptdicResponse.OutDoctorAccounting), (UnitType.医生组.ToString(), "门诊") },
......@@ -31,12 +38,20 @@ public class PersonService : IAutoInjection
public PersonService(ILogger<PersonService> logger,
PerforPerdeptdicRepository perdeptdicRepository,
PerforPeremployeeRepository peremployeeRepository,
PerforPerallotRepository perallotRepository)
PerforPerallotRepository perallotRepository,
PerforUserRepository perforUserRepository,
PerforUserroleRepository perforUserroleRepository,
PerforRoleRepository perforRoleRepository,
IOptions<Application> application)
{
this.logger = logger;
this.perdeptdicRepository = perdeptdicRepository;
this.peremployeeRepository = peremployeeRepository;
this.perallotRepository = perallotRepository;
this.perforUserRepository = perforUserRepository;
this.perforUserroleRepository = perforUserroleRepository;
this.perforRoleRepository = perforRoleRepository;
this.application = application.Value;
}
/// <summary>
......@@ -79,6 +94,8 @@ public void CreateAllotPersons(int hospitalId, int allotId, int prevAllotId = -1
UnitType = t.UnitType,
AttendanceDay = day,
Attendance = 1,
PermanentStaff = t.PermanentStaff,
EfficiencyNumber = t.EfficiencyNumber,
WorkTime = t.WorkTime,
BirthDate = t.BirthDate,
Age = t.Age,
......@@ -116,9 +133,20 @@ private void SaveAllotPersons(List<per_employee> employees)
/// </summary>
/// <param name="allotId"></param>
/// <returns></returns>
public List<per_employee> GetPersons(int allotId)
public List<per_employee> GetPersons(int allotId, int userId)
{
return peremployeeRepository.GetEntities(t => t.AllotId == allotId);
var (dept, unittype) = GetDeptByUser(userId);
Expression<Func<per_employee, bool>> exp = t => t.AllotId == allotId;
if (!string.IsNullOrEmpty(dept) && unittype.Any())
{
exp = exp.And(t => t.AccountingUnit == dept && unittype.Contains(t.UnitType));
}
var list = peremployeeRepository.GetEntities(exp);
if (list != null && list.Any())
return list.OrderBy(t => t.Id).ToList();
return new List<per_employee>();
}
/// <summary>
......@@ -126,25 +154,28 @@ public List<per_employee> GetPersons(int allotId)
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public per_employee CreatePerson(per_employee request)
public per_employee CreatePerson(PerEmployeeResponse request)
{
var employee = peremployeeRepository.GetEntity(t => t.AllotId == request.AllotId && t.PersonnelNumber == request.PersonnelNumber
&& t.DoctorName == request.DoctorName && t.Department == request.Department);
if (employee != null)
throw new PerformanceException($"员工工号为{request.PersonnelNumber}的数据已存在!");
if (!EnumHelper.GetItems<UnitType>().Select(t => t.Description).Contains(request.UnitType))
var unittype = EnumHelper.GetItems<UnitType>().Select(t => t.Description).ToList();
unittype.AddRange(EnumHelper.GetItems<AccountUnitType>().Select(t => t.Description));
if (!unittype.Contains(request.UnitType))
throw new PerformanceException($"人员类别不符合规范!");
var entity = Mapper.Map<per_employee>(request);
var allot = perallotRepository.GetEntity(t => t.ID == request.AllotId);
int day = DateTime.DaysInMonth(allot.Year, allot.Month);
request.Attendance = request.AttendanceDay / day;
request.CreateTime = DateTime.Now;
request.CreateUser = 0;
entity.Attendance = request.AttendanceDay / day;
entity.CreateTime = DateTime.Now;
//CheckAccountingDept(request.HospitalId.Value, request.AccountingUnit, request.Department);
peremployeeRepository.Add(request);
return request;
peremployeeRepository.Add(entity);
return entity;
}
/// <summary>
......@@ -152,24 +183,44 @@ public per_employee CreatePerson(per_employee request)
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public bool UpdatePerson(per_employee request)
public bool UpdatePerson(PerEmployeeResponse request)
{
var employee = peremployeeRepository.GetEntity(t => t.AllotId == request.AllotId && t.PersonnelNumber == request.PersonnelNumber
&& t.DoctorName == request.DoctorName && t.Department == request.Department);
if (employee != null && employee.Id != request.Id)
throw new PerformanceException($"员工工号为{request.PersonnelNumber}的数据已存在!");
if (!EnumHelper.GetItems<UnitType>().Select(t => t.Description).Contains(request.UnitType))
var unittype = EnumHelper.GetItems<UnitType>().Select(t => t.Description).ToList();
unittype.AddRange(EnumHelper.GetItems<AccountUnitType>().Select(t => t.Description));
if (!unittype.Contains(request.UnitType))
throw new PerformanceException($"人员类别不符合规范!");
if (employee == null)
employee = peremployeeRepository.GetEntity(t => t.Id == request.Id) ?? throw new PerformanceException("人员信息无效!");
Mapper.Map(request, employee, typeof(per_employee), typeof(per_employee));
//Mapper.Map(request, employee, typeof(per_employee), typeof(per_employee));
employee.AccountingUnit = request.AccountingUnit;
employee.Department = request.Department;
employee.DoctorName = request.DoctorName;
employee.PersonnelNumber = request.PersonnelNumber;
employee.JobCategory = request.JobCategory;
employee.Duty = request.Duty;
employee.JobTitle = request.JobTitle;
employee.UnitType = request.UnitType;
employee.WorkTime = request.WorkTime == null ? null : ConvertHelper.To<DateTime?>(request.WorkTime);
employee.BirthDate = request.BirthDate == null ? null : ConvertHelper.To<DateTime?>(request.BirthDate);
employee.Age = request.Age;
employee.Remark = request.Remark;
employee.EfficiencyNumber = request.EfficiencyNumber;
employee.PermanentStaff = request.PermanentStaff;
employee.AttendanceDay = request.AttendanceDay;
// 出勤率
var allot = perallotRepository.GetEntity(t => t.ID == request.AllotId);
int day = DateTime.DaysInMonth(allot.Year, allot.Month);
request.Attendance = request.AttendanceDay / day;
var day = (decimal)DateTime.DaysInMonth(allot.Year, allot.Month);
employee.Attendance = Math.Round((request.AttendanceDay ?? 0) / day, 4);
//CheckAccountingDept(request.HospitalId.Value, request.AccountingUnit, request.Department);
return peremployeeRepository.Update(employee);
......@@ -216,24 +267,62 @@ private void CheckAccountingDept(int hosapitalId, string accountingUnit, string
/// </summary>
/// <param name="hospitalId"></param>
/// <returns></returns>
public dynamic GetDepartments(int hospitalId)
public IEnumerable<DeptdicResponse> GetDepartments(int hospitalId)
{
var depts = perdeptdicRepository.GetEntities(t => t.HospitalId == hospitalId);
if (depts == null || !depts.Any()) return null;
var result = depts.GroupBy(t => new { t.HISDeptName, t.Department }).Select(t => new
var result = depts.GroupBy(t => new { t.HISDeptName, t.Department }).Select(t => new DeptdicResponse
{
t.Key.HISDeptName,
t.Key.Department,
OutDoctorAccounting = t.FirstOrDefault(group => group.Department == t.Key.Department && group.UnitType == UnitType.医生组.ToString() && group.Source == "门诊"),
OutNurseAccounting = t.FirstOrDefault(group => group.Department == t.Key.Department && group.UnitType == UnitType.护理组.ToString() && group.Source == "门诊"),
OutTechnicAccounting = t.FirstOrDefault(group => group.Department == t.Key.Department && group.UnitType == UnitType.医技组.ToString() && group.Source == "门诊"),
InpatDoctorAccounting = t.FirstOrDefault(group => group.Department == t.Key.Department && group.UnitType == UnitType.医生组.ToString() && group.Source == "住院"),
InpatNurseAccounting = t.FirstOrDefault(group => group.Department == t.Key.Department && group.UnitType == UnitType.护理组.ToString() && group.Source == "住院"),
InpatTechnicAccounting = t.FirstOrDefault(group => group.Department == t.Key.Department && group.UnitType == UnitType.医技组.ToString() && group.Source == "住院"),
HospitalId = hospitalId,
HISDeptName = t.Key.HISDeptName,
Department = t.Key.Department,
OutDoctorAccounting = GetDeptdic(t.FirstOrDefault(group => group.Department == t.Key.Department && group.UnitType == UnitType.医生组.ToString() && group.Source == "门诊")),
OutNurseAccounting = GetDeptdic(t.FirstOrDefault(group => group.Department == t.Key.Department && group.UnitType == UnitType.护理组.ToString() && group.Source == "门诊")),
OutTechnicAccounting = GetDeptdic(t.FirstOrDefault(group => group.Department == t.Key.Department && group.UnitType == UnitType.医技组.ToString() && group.Source == "门诊")),
InpatDoctorAccounting = GetDeptdic(t.FirstOrDefault(group => group.Department == t.Key.Department && group.UnitType == UnitType.医生组.ToString() && group.Source == "住院")),
InpatNurseAccounting = GetDeptdic(t.FirstOrDefault(group => group.Department == t.Key.Department && group.UnitType == UnitType.护理组.ToString() && group.Source == "住院")),
InpatTechnicAccounting = GetDeptdic(t.FirstOrDefault(group => group.Department == t.Key.Department && group.UnitType == UnitType.医技组.ToString() && group.Source == "住院")),
CreateTime = t.Max(group => group.CreateTime)
});
return result;
return result.OrderByDescending(t => t.CreateTime).ThenBy(t => t.Department);
}
private (string dept, string[] unittype) GetDeptByUser(int userId)
{
var user = perforUserRepository.GetEntity(t => t.ID == userId && t.IsDelete == 1);
if (user == null) throw new PerformanceException("用户信息错误");
var userrole = perforUserroleRepository.GetEntity(t => t.UserID == user.ID);
var role = perforRoleRepository.GetEntity(t => t.ID == userrole.RoleID);
if (role == null) return ("", new string[] { });
Dictionary<int, string[]> dict = new Dictionary<int, string[]>
{
{ application.DirectorRole, new string[]{ UnitType.医生组.ToString(), UnitType.医技组.ToString() } },
{ application.NurseRole, new string[]{ UnitType.护理组.ToString() } },
{ application.SpecialRole, new string[]{ UnitType.特殊核算组.ToString() } },
};
if (dict.Keys.Contains(role.Type.Value))
{
return (user.Department, dict[role.Type.Value]);
}
return ("", new string[] { });
}
private Deptdic GetDeptdic(per_dept_dic dic)
{
if (dic == null) return new Deptdic();
return new Deptdic
{
Id = dic.Id,
AccountingUnit = dic.AccountingUnit
};
}
/// <summary>
......@@ -243,10 +332,10 @@ public dynamic GetDepartments(int hospitalId)
/// <returns></returns>
public per_dept_dic CreateDeptDic(per_dept_dic request)
{
var accountDept = perdeptdicRepository.GetEntity(t => t.HospitalId == request.HospitalId && t.AccountingUnit == request.AccountingUnit
&& t.Department == request.Department && t.Source == request.Source && t.UnitType == request.UnitType);
var deptdic = perdeptdicRepository.GetEntity(t => t.HospitalId == request.HospitalId && t.AccountingUnit == request.AccountingUnit
&& t.Department == request.Department && t.HISDeptName == request.HISDeptName && t.Source == request.Source && t.UnitType == request.UnitType);
if (accountDept != null)
if (deptdic != null)
throw new PerformanceException($"{request.Department}数据重复!");
request.CreateTime = DateTime.Now;
......@@ -273,27 +362,101 @@ public bool UpdateDeptDic(per_dept_dic request)
}
/// <summary>
/// 更新科室核算信息
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public bool UpdateDeptDic(DeptdicResponse request)
{
try
{
foreach (var item in dict)
{
var property = typeof(DeptdicResponse).GetProperty(item.Key);
if (property == null) continue;
var deptdic = property.GetValue(request);
if (deptdic is Deptdic)
{
var data = (Deptdic)deptdic;
if (string.IsNullOrEmpty(data.AccountingUnit) && data.Id == 0)
continue;
if (data.Id > 0)
{
var entity = perdeptdicRepository.GetEntity(t => t.Id == data.Id);
if (entity == null) continue;
entity.HISDeptName = request.HISDeptName;
entity.Department = request.Department;
entity.AccountingUnit = data.AccountingUnit;
perdeptdicRepository.Update(entity);
}
else
{
var entity = new per_dept_dic
{
HospitalId = request.HospitalId,
HISDeptName = request.HISDeptName,
Department = request.Department,
AccountingUnit = data.AccountingUnit,
UnitType = item.Value.Item1,
Source = item.Value.Item2,
CreateTime = DateTime.Now,
};
perdeptdicRepository.Add(entity);
}
}
}
}
catch (Exception ex)
{
logger.LogError(ex.ToString());
return false;
}
return true;
}
/// <summary>
/// 删除科室核算信息
/// </summary>
/// <param name="deptdicId"></param>
/// <returns></returns>
public bool DeleteDeptDic(int deptdicId)
public bool DeleteDeptDic(DeptdicResponse request)
{
var deptdic = perdeptdicRepository.GetEntity(t => t.Id == deptdicId);
if (deptdic == null)
var deptdics = perdeptdicRepository.GetEntities(t => (t.HISDeptName ?? "") == request.HISDeptName
&& (t.Department ?? "") == request.Department && t.HospitalId == request.HospitalId);
if (deptdics == null || !deptdics.Any())
throw new PerformanceException("科室记录不存在!");
return perdeptdicRepository.Remove(deptdic);
return perdeptdicRepository.RemoveRange(deptdics.ToArray());
}
}
public class DeptdicResponse
{
public string OutDoctorAccounting { get; set; }
public string OutNurseAccounting { get; set; }
public string OutTechnicAccounting { get; set; }
public string InpatDoctorAccounting { get; set; }
public string InpatNurseAccounting { get; set; }
public string InpatTechnicAccounting { get; set; }
/// <summary>
/// 系统/标准科室字典
/// </summary>
/// <param name="hospitalId">医院Id</param>
/// <param name="type">1系统科室 2标准科室 3核算单元</param>
/// <returns></returns>
public List<TitleValue> DeptDics(int hospitalId, int type)
{
var deptdics = perdeptdicRepository.GetEntities(t => t.HospitalId == hospitalId);
if (deptdics == null || !deptdics.Any()) return new List<TitleValue>();
var result = new List<string>();
if (type == 1)
{
result = deptdics.Select(t => t.HISDeptName).Distinct().ToList();
}
else if (type == 2)
{
result = deptdics.Select(t => t.Department).Distinct().ToList();
}
else if (type == 3)
{
result = deptdics.Select(t => t.AccountingUnit).Distinct().ToList();
}
return result.Select(t => new TitleValue { Title = t, Value = t }).ToList();
}
}
}
......@@ -27,6 +27,7 @@ public class UserService : IAutoInjection
private PerforPerallotRepository _perforPerallotRepository;
private PerforImaccountbasicRepository _imaccountbasicRepository;
private PerforImspecialunitRepository _imspecialunitRepository;
private PerforPerdeptdicRepository _perdeptdicRepository;
public UserService(IOptions<Application> application,
PerforSmsRepository smsRepository,
PerforUserRepository userRepository,
......@@ -37,7 +38,8 @@ public class UserService : IAutoInjection
PerforImemployeeRepository employeeRepository,
PerforPerallotRepository perforPerallotRepository,
PerforImaccountbasicRepository imaccountbasicRepository,
PerforImspecialunitRepository imspecialunitRepository)
PerforImspecialunitRepository imspecialunitRepository,
PerforPerdeptdicRepository perdeptdicRepository)
{
this.application = application.Value;
this._userRepository = userRepository;
......@@ -50,6 +52,7 @@ public class UserService : IAutoInjection
this._perforPerallotRepository = perforPerallotRepository;
this._imaccountbasicRepository = imaccountbasicRepository;
this._imspecialunitRepository = imspecialunitRepository;
this._perdeptdicRepository = perdeptdicRepository;
}
/// <summary>
......@@ -330,9 +333,9 @@ public List<sys_role> RoleList(int userId)
/// 科室列表
/// </summary>
/// <returns></returns>
public List<TitleValue> Department(int hospitalID)
public List<TitleValue> Department(int hospitalId)
{
var allotList = _perforPerallotRepository.GetEntities(t => t.HospitalId == hospitalID);
var allotList = _perforPerallotRepository.GetEntities(t => t.HospitalId == hospitalId);
var result = new List<string>();
if (allotList != null)
{
......@@ -355,6 +358,10 @@ public List<TitleValue> Department(int hospitalID)
result = result.Distinct().OrderBy(t => t).ToList();
}
}
//var list = _perdeptdicRepository.GetEntities(t => t.HospitalId == hospitalId);
//if (list == null || !list.Any()) return new List<TitleValue>();
//var result = list.Select(t => t.AccountingUnit).Distinct().OrderBy(t => t);
return result?.Select(t => new TitleValue { Title = t, Value = t }).ToList();
}
......
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