Commit fcd71ca0 by ruyun.zhang@suvalue.com

Merge branch 'feature/extract' into develop

parents 1cfac1b2 d983e5f2
......@@ -25,6 +25,7 @@ public class TemplateController : Controller
{
private readonly TemplateService templateService;
private readonly ExtractService extractService;
private readonly NewExtractService newExtractService;
private HospitalService hospitalService;
private IHostingEnvironment env;
private ClaimService claim;
......@@ -36,6 +37,7 @@ public class TemplateController : Controller
public TemplateController(TemplateService templateService,
HospitalService hospitalService,
ExtractService extractService,
NewExtractService newExtractService,
IHostingEnvironment env,
ClaimService claim,
IOptions<Application> options,
......@@ -45,6 +47,7 @@ public class TemplateController : Controller
{
this.templateService = templateService;
this.extractService = extractService;
this.newExtractService = newExtractService;
this.hospitalService = hospitalService;
this.env = env;
this.claim = claim;
......@@ -74,6 +77,7 @@ public IActionResult DownFile(int type = 1)
}
memoryStream.Seek(0, SeekOrigin.Begin);
var provider = new FileExtensionContentTypeProvider();
var memi = provider.Mappings[".xlsx"];
return File(memoryStream, memi, Path.GetFileName(path));
}
......@@ -130,6 +134,7 @@ public ApiResponse Import([FromForm] IFormCollection form)
return new ApiResponse(ResponseType.OK);
}
#region 老版提取
/// <summary>
/// 提取绩效数据
/// </summary>
......@@ -190,6 +195,68 @@ public ApiResponse ExtractData([CustomizeValidator(RuleSet = "Template"), FromBo
throw ex;
}
}
#endregion
#region 新版提取
/// <summary>
/// 提取绩效数据
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[Route("NewExtractData")]
[HttpPost]
public ApiResponse NewExtractData([CustomizeValidator, FromBody]ExtractRequest request)
{
var allot = allotService.GetAllot(request.AllotId);
if (allot == null)
return new ApiResponse(ResponseType.ParameterError, "AllotID错误");
// 判断是那种抽取
try
{
string message = newExtractService.Judge(request.AllotId, request.HospitalId, request.UseScheme);
if (!string.IsNullOrEmpty(message))
return new ApiResponse(ResponseType.Fail, message);
allot.IsExtracting = allot.IsExtracting ?? 0;
if (allot.IsExtracting == 1)
return new ApiResponse(ResponseType.OK, "正在提取数据,请稍等!");
allot.IsExtracting = 1;
allotService.Update(allot);
var email = claim.GetUserClaim(JwtClaimTypes.Mail);
request.Email = email;
//if (request.UseScheme == (int)UseTemplate.Config)
//{
LogHelper.Information("请求路径:" + url.HttpPost + "/extract/extract", "提取绩效数据");
HttpHelper.HttpPostNoRequest(url.HttpPost + "/extract/extract", JsonHelper.Serialize(request), true);
//}
//else
//{
// return new ApiResponse(ResponseType.Fail, "该功能暂未实现!");
//}
return new ApiResponse(ResponseType.OK, "HIS绩效数据提取任务正在执行,稍后我们将以邮件的通知您!");
}
catch (Exception ex)
{
if (allot != null)
{
allot.IsExtracting = 3;
allotService.Update(allot);
}
logger.LogError("提取绩效数据:" + ex.ToString());
throw new Exception(ex.Message);
}
// A 使用上传绩效作为模板
// A-1 判断上传绩效是否存在,并执行成功
// A-2 医院人员名单、1.0.1 额外收入(写出列头)、2.1 成本支出统计表(写出列头)、4.1 临床科室医护绩效测算表、4.2 特殊核算单元绩效测算表(数量、考核得分率、奖罚、其他)
// A-3 收入 根据收入配置sheet名称获取抽取SQL,执行填充结果
// A-4 工作量 根据配置项获取抽取SQL,执行填充结果
// B 使用配置作为模板
}
#endregion
/// <summary>
/// 从WebAPI下载文件
......@@ -230,36 +297,54 @@ public IActionResult DownFile([FromQuery]AllotRequest request)
[AllowAnonymous]
public ApiResponse SaveFile([FromForm] IFormCollection form, int allotId, int hospitalId)
{
LogHelper.Information($"请求参数:allotId:{allotId} hospitalId:{hospitalId}", "保存提取文件");
logger.LogInformation($"保存提取文件 参数:allotId:{allotId} hospitalId:{hospitalId}");
try
{
var file = ((FormFileCollection)form.Files).FirstOrDefault();
if (file == null)
{
LogHelper.Error($"返回文件为空!", "保存提取文件");
return new ApiResponse(ResponseType.Error, "上传文件无效");
}
var dpath = Path.Combine(env.ContentRootPath, "Files", $"{hospitalId}", "autoextract");
FileHelper.CreateDirectory(dpath);
var path = Path.Combine(dpath, FileHelper.GetFileName(file.FileName));
LogHelper.Information($"保存路径:" + path, "保存提取文件");
using (var stream = file.OpenReadStream())
{
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
if (!FileHelper.CreateFile(path, bytes))
{
LogHelper.Error($"保存失败", "保存提取文件");
return new ApiResponse(ResponseType.Error, "保存失败");
}
}
var allot = allotService.GetAllot(allotId);
allot.ExtractPath = path;
allot.IsExtracting = 2;
if (!string.IsNullOrEmpty(path) && allotService.Update(allot))
if (string.IsNullOrEmpty(path) || !FileHelper.IsExistFile(path))
{
LogHelper.Information($"文件未保存成功,保存文件不存在!", "保存提取文件");
return new ApiResponse(ResponseType.Fail, "上传成功!");
}
if (!allotService.Update(allot))
{
LogHelper.Information($"更新文件路径失败!", "保存提取文件");
return new ApiResponse(ResponseType.Fail, "上传成功!");
}
return new ApiResponse(ResponseType.OK, "上传成功!");
}
catch (Exception ex)
{
logger.LogInformation($"保存提取文件异常{ex.ToString()}");
LogHelper.Error($"保存失败:" + ex.ToString(), "保存提取文件");
return new ApiResponse(ResponseType.Error,ex.Message);
}
return new ApiResponse(ResponseType.Error);
}
}
}
\ No newline at end of file
......@@ -58,9 +58,6 @@
<Content Update="wwwroot\Performance.Api.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\Performance.DtoModels.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\Performance.EntityModels.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
......@@ -75,6 +72,15 @@
</None>
</ItemGroup>
<ItemGroup>
<None Update="Template\医院二次分配绩效模板.xlsx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Template\医院绩效模板.xlsx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ProjectExtensions><VisualStudio><UserProperties appsettings_1json__JSONSchema="" /></VisualStudio></ProjectExtensions>
</Project>
......@@ -26,6 +26,7 @@
"WebapiUrl": {
"ImportFirst": "http://localhost:50997/api/extract/import",
"ExtractData": "http://localhost:50997/api/extract/index",
"ImportFile": ""
"ImportFile": "http://localhost:5001/api/template/savefile",
"HttpPost": "http://localhost:50997/api"
}
}
......@@ -27,6 +27,7 @@
"WebapiUrl": {
"ImportFirst": "http://localhost:50997/api/extract/import",
"ExtractData": "http://localhost:50997/api/extract/index",
"ImportFile": ""
"ImportFile": "http://localhost:5001/api/template/savefile",
"HttpPost": "http://localhost:50997/api"
}
}
......@@ -673,6 +673,13 @@
<param name="request"></param>
<returns></returns>
</member>
<member name="M:Performance.Api.Controllers.TemplateController.NewExtractData(Performance.DtoModels.ExtractRequest)">
<summary>
提取绩效数据
</summary>
<param name="request"></param>
<returns></returns>
</member>
<member name="M:Performance.Api.Controllers.TemplateController.DownFile(Performance.DtoModels.AllotRequest)">
<summary>
从WebAPI下载文件
......
......@@ -92,6 +92,24 @@
<member name="T:Performance.DtoModels.States">
<summary> 用户状态 </summary>
</member>
<member name="T:Performance.DtoModels.UseTemplate">
<summary> 提取数据使用模板 </summary>
</member>
<member name="F:Performance.DtoModels.UseTemplate.LastAllot">
<summary> 上次绩效 </summary>
</member>
<member name="F:Performance.DtoModels.UseTemplate.Config">
<summary> 配置模板 </summary>
</member>
<member name="T:Performance.DtoModels.DbSrouceType">
<summary> 提取数据使用模板 </summary>
</member>
<member name="F:Performance.DtoModels.DbSrouceType.Standard">
<summary> 标准库 </summary>
</member>
<member name="F:Performance.DtoModels.DbSrouceType.Performance">
<summary> 绩效库 </summary>
</member>
<member name="F:Performance.DtoModels.AllotStates.NoData">
<summary> 用户状态 </summary>
</member>
......@@ -1205,6 +1223,26 @@
发放系数
</summary>
</member>
<member name="P:Performance.DtoModels.ExtractRequest.AllotId">
<summary>
绩效ID
</summary>
</member>
<member name="P:Performance.DtoModels.ExtractRequest.HospitalId">
<summary>
医院ID
</summary>
</member>
<member name="P:Performance.DtoModels.ExtractRequest.UseScheme">
<summary>
使用方案
</summary>
</member>
<member name="P:Performance.DtoModels.ExtractRequest.Email">
<summary>
邮箱
</summary>
</member>
<member name="T:Performance.DtoModels.HospitalRequest">
<summary>
登录请求
......@@ -1609,6 +1647,11 @@
科室
</summary>
</member>
<member name="P:Performance.DtoModels.DeptResponse.ManagerNumber">
<summary>
科主任/护士长数量
</summary>
</member>
<member name="P:Performance.DtoModels.DeptResponse.Number">
<summary>
核算单元医生数量
......
......@@ -108,7 +108,7 @@ public AutoMapperConfigs()
//CreateMap<PerDataAccountBaisc, im_accountbasic>();
//CreateMap<im_accountbasic, PerDataAccountBaisc>();
CreateMap<PerDataAccountBaisc, im_accountbasic>()
.ForMember(dest => dest.UnitType, opt => opt.MapFrom(src => src.UnitType))
.ForMember(dest => dest.UnitType, opt => opt.MapFrom(src => EnumHelper.GetItems<UnitType>().First(t => t.Name == src.UnitType).Value))
.ForMember(dest => dest.DoctorAccountingUnit, opt => opt.MapFrom(src => src.AccountingUnit))
.ForMember(dest => dest.Department, opt => opt.MapFrom(src => src.Department))
.ForMember(dest => dest.DoctorDirectorNumber, opt => opt.MapFrom(src => src.ManagerNumber))
......@@ -146,8 +146,10 @@ public AutoMapperConfigs()
//CreateMap<PerDataAccountDoctor, res_accountdoctor>();
//CreateMap<PerDataAccountNurse, res_accountnurse>();
//CreateMap<res_accountdoctor, PerDataAccountBaisc>();
CreateMap<res_account, PerDataAccountBaisc>();
CreateMap<PerDataAccountBaisc, res_account>();
CreateMap<res_account, PerDataAccountBaisc>()
.ForMember(dest => dest.UnitType, opt => opt.MapFrom(src => ((UnitType)src.UnitType).ToString()));
CreateMap<PerDataAccountBaisc, res_account>()
.ForMember(dest => dest.UnitType, opt => opt.MapFrom(src => EnumHelper.GetItems<UnitType>().First(t => t.Name == src.UnitType).Value));
//CreateMap<PerDataAccountBaisc, res_accountnurse>();
//CreateMap<res_accountdoctor, ComputeSource>();
......
......@@ -23,6 +23,28 @@ public enum States
Disabled = 2,
}
/// <summary> 提取数据使用模板 </summary>
public enum UseTemplate
{
/// <summary> 上次绩效 </summary>
[Description("上次绩效")]
LastAllot = 1,
/// <summary> 配置模板 </summary>
[Description("配置模板")]
Config = 2,
}
/// <summary> 提取数据使用模板 </summary>
public enum DbSrouceType
{
/// <summary> 标准库 </summary>
[Description("标准库")]
Standard = 1,
/// <summary> 绩效库 </summary>
[Description("绩效库")]
Performance = 2,
}
public enum AllotStates
{
/// <summary> 用户状态 </summary>
......
using System;
using System.Collections.Generic;
using System.Text;
namespace Performance.DtoModels
{
public class ExtractDto
{
public string Department { get; set; }
public string Category { get; set; }
public decimal Value { get; set; }
}
}
......@@ -21,6 +21,8 @@ public enum UnitType
护理组 = 2,
[Description("医技组")]
医技组 = 3,
[Description("专家组")]
专家组 = 4,
}
public enum SheetType
......
......@@ -21,7 +21,7 @@ public class PerDataAccountBaisc : IPerData
/// <summary>
/// 核算单元类别 1 医生组 2护理组 3医技组
/// </summary>
public Nullable<int> UnitType { get; set; }
public string UnitType { get; set; }
/// <summary>
/// 核算单元
......
using System;
using System.Collections.Generic;
using System.Text;
namespace Performance.DtoModels
{
public class DownRequest
{
public int TempType { get; set; }
}
}
using FluentValidation;
using System;
using System.Collections.Generic;
using System.Text;
namespace Performance.DtoModels
{
public class ExtractRequest
{
/// <summary>
/// 绩效ID
/// </summary>
public int AllotId { get; set; }
/// <summary>
/// 医院ID
/// </summary>
public int HospitalId { get; set; }
/// <summary>
/// 使用方案
/// </summary>
public int UseScheme { get; set; }
/// <summary>
/// 邮箱
/// </summary>
public string Email { get; set; }
}
public class ExtractRequestValidator : AbstractValidator<ExtractRequest>
{
public ExtractRequestValidator()
{
RuleFor(x => x.AllotId).NotNull().GreaterThan(0);
RuleFor(x => x.HospitalId).NotNull().GreaterThan(0);
//RuleFor(x => x.UseScheme).NotNull().InclusiveBetween(1, 2);
}
}
}
......@@ -39,6 +39,11 @@ public class DeptResponse
public string Department { get; set; }
/// <summary>
/// 科主任/护士长数量
/// </summary>
public Nullable<int> ManagerNumber { get; set; }
/// <summary>
/// 核算单元医生数量
/// </summary>
public Nullable<decimal> Number { get; set; }
......
using System;
using System.Collections.Generic;
using System.Text;
namespace Performance.EntityModels
{
public class AccountUnitEntity
{
public string SheetName { get; set; }
public string AccountingUnit { get; set; }
public string Department { get; set; }
public int UnitType { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using FluentValidation.AspNetCore;
using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Internal;
......@@ -15,6 +10,11 @@
using Performance.DtoModels.AppSettings;
using Performance.Infrastructure;
using Performance.Services;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace Performance.Extract.Api.Controllers
{
......@@ -22,15 +22,20 @@ namespace Performance.Extract.Api.Controllers
public class ExtractController : Controller
{
private readonly ExtractService extractService;
private readonly NewExtractService newExtractService;
private readonly HospitalService hospitalService;
private readonly WebapiUrl url;
private readonly ILogger<ExtractController> logger;
private IHostingEnvironment evn;
public ExtractController(ExtractService extractService, HospitalService hospitalService,
IOptions<WebapiUrl> url, ILogger<ExtractController> logger,
private readonly IHostingEnvironment evn;
public ExtractController(ExtractService extractService,
NewExtractService newExtractService,
HospitalService hospitalService,
IOptions<WebapiUrl> url,
ILogger<ExtractController> logger,
IHostingEnvironment evn)
{
this.extractService = extractService;
this.newExtractService = newExtractService;
this.hospitalService = hospitalService;
this.url = url.Value;
this.logger = logger;
......@@ -100,5 +105,48 @@ public void Index([FromBody]AllotRequest request)
}
logger.LogInformation(token + ",提取结束,请求参数:" + JsonHelper.Serialize(request));
}
#region 新版提取
/// <summary>
/// 提取绩效数据
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[Route("extract")]
[HttpPost]
public void ExtractData([CustomizeValidator, FromBody]ExtractRequest request)
{
LogHelper.Information("请求参数:" + JsonHelper.Serialize(request), "提取绩效数据");
string filePath = newExtractService.ExtractData(request.AllotId, request.Email, request.HospitalId);
if (!string.IsNullOrEmpty(filePath) && FileHelper.IsExistFile(filePath))
{
LogHelper.Information("请求路径:" + url.ImportFile + ",请求参数" + JsonHelper.Serialize(new { allotId = request.AllotId, hospitalId = request.HospitalId }), "保存提取文件");
int i = 1;
while (i <= 5)
{
if (i == 5)
LogHelper.Information($"保存文件失败,已尝试执行五次,请联系开发人员!", "保存提取文件");
else
LogHelper.Information($"正在尝试第{i}次保存!", "保存提取文件");
//保存文件
string retJson = HttpHelper.HttpClient(url.ImportFile + $"?allotId={request.AllotId}&hospitalId={request.HospitalId}", filePath);
LogHelper.Information("返回结果:" + JsonHelper.Serialize(retJson), "保存提取文件");
logger.LogInformation(retJson);
var ret = JsonHelper.Deserialize<ApiResponse>(retJson);
if (ret != null && (int)ret.State == 1)
{
LogHelper.Information("保存成功!", "保存提取文件");
break;
}
i++;
}
}
else
LogHelper.Information($"提取文件不存在!", "保存提取文件");
}
#endregion
}
}
\ No newline at end of file
......@@ -25,6 +25,19 @@
<ProjectReference Include="..\Performance.Services\Performance.Services.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Template\" />
</ItemGroup>
<ItemGroup>
<None Include="..\Performance.Api\Template\医院二次分配绩效模板.xlsx" Link="Template\医院二次分配绩效模板.xlsx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="..\Performance.Api\Template\医院绩效模板.xlsx" Link="Template\医院绩效模板.xlsx">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ProjectExtensions><VisualStudio><UserProperties appsettings_1json__JSONSchema="" /></VisualStudio></ProjectExtensions>
</Project>
......@@ -31,6 +31,15 @@ public IEnumerable<TEntity> DapperQuery(string sql, object param, int? commandTi
{
return context.Database.GetDbConnection().Query<TEntity>(sql, param, commandTimeout: commandTimeout);
}
public IEnumerable<T> DapperQuery<T>(string sql, object param) where T : class, new()
{
return context.Database.GetDbConnection().Query<T>(sql, param);
}
public IEnumerable<T> DapperQuery<T>(string sql, object param, int? commandTimeout = null)
{
return context.Database.GetDbConnection().Query<T>(sql, param, commandTimeout: commandTimeout);
}
public int Execute(string sql, object param)
{
......
......@@ -29,5 +29,15 @@ public IEnumerable<im_data> GetAccountingUnit(int hospitalid, int sheettype, Lis
"where allot.hospitalid = @hospitalid and sheet.sheettype = @sheettype and im.department in @deptList";
return DapperQuery(sql, new { hospitalid, sheettype, deptList }, 1000 * 60 * 5);
}
/// <summary>
/// 삿혤뵙炬데禱
/// </summary>
/// <returns></returns>
public IEnumerable<AccountUnitEntity> GetAccountUnit(int allotId)
{
string sql = "select distinct SheetName,AccountingUnit,Department,UnitType from per_sheet st join im_data dt on st.ID = dt.SheetID where st.AllotID = @allotId";
return DapperQuery<AccountUnitEntity>(sql, new { allotId }, 1000 * 60 * 5);
}
}
}
......@@ -121,7 +121,7 @@ public List<res_baiscnorm> DocterNurseBaiscnorm(List<res_baiscnorm> baiscnormLis
var sheet = list.FirstOrDefault(t => t.SheetType == info.SheetType);
var perData = sheet.PerData.Select(t => (PerDataAccountBaisc)t);
//剔除不同科室相同核算单元
var groupData = perData.Where(t => t.UnitType == (int)info.UnitType)
var groupData = perData.Where(t => t.UnitType == info.UnitType.ToString())
.GroupBy(t => t.AccountingUnit)
.Select(t => new { AccountingUnit = t.Key, Number = t.Sum(p => p.ManagerNumber + p.Number), PerforTotal = t.Max(p => p.PerforTotal) });
......
......@@ -97,31 +97,6 @@ public bool Discern(PerExcel excel, per_allot allot)
.Select(t => t.CellName).Distinct().ToList();
if (headerCheck != null)
{
if ((int)sheet.SheetType == 4)
{
string str = sheet.SheetName.Contains("医生组") ? "医生组" : "护理组";
var filter = new List<string>() { $"核算单元({str})", "科室名称" };
var list = cellValue.Intersect(filter).ToList(); //求交集
if (list == null)
{
message = $"{sheet.SheetName} -- 列头不规范,缺少列头或命名不规范:“核算单元({str})、科室名称”不存在;";
flag = false;
}
else if (!cellValue.Contains($"核算单元({str})"))
{
message = $"{sheet.SheetName} -- 列头不规范,缺少列头或命名不规范:“核算单元({str})”不存在;";
flag = false;
}
else if (!cellValue.Contains("科室名称"))
{
message = $"{sheet.SheetName} -- 列头不规范,缺少列头或命名不规范:“科室名称”不存在;";
flag = false;
}
}
else
{
var list = cellValue.Intersect(headerCheck).ToList(); //求交集,提交的列头和数据库中保存的列头
var drugtype = perforCofdrugtypeRepository.GetEntities(t => t.AllotID == allot.ID);
if (drugtype != null && drugtype.Count > 0)
......@@ -132,7 +107,6 @@ public bool Discern(PerExcel excel, per_allot allot)
flag = false;
message = $"{sheet.SheetName} -- 列头不规范,缺少列头或命名不规范:“{String.Join("、", lack.ToArray())}”不存在;";
}
}
if (!flag)
result = false;
}
......
......@@ -243,8 +243,9 @@ private List<PerSheet> MergeCompute(PerExcel excel, int allotid)
{
var pairs = new[]
{
new { Name = "医生组临床科室单元核算表", Data = doctorWorkloadData, SheetType = SheetType.ComputeDoctorAccount, UnitTypes = new List<UnitType> { UnitType.医生组, UnitType.医技组 } },
new { Name = "医生组临床科室单元核算表", Data = doctorWorkloadData, SheetType = SheetType.ComputeDoctorAccount, UnitTypes = new List<UnitType> { UnitType.医生组, UnitType.医技组, UnitType.专家组 } },
new { Name = "护理组临床科室单元核算表", Data = nurseWorkloadData, SheetType = SheetType.ComputeNurseAccount, UnitTypes = new List<UnitType> { UnitType.护理组 } },
new { Name = "专家核算表", Data = doctorWorkloadData, SheetType = SheetType.ComputeDoctorAccount, UnitTypes = new List<UnitType> { UnitType.专家组 } },
};
List<PerSheet> result = new List<PerSheet>();
foreach (var info in pairs)
......@@ -252,14 +253,20 @@ private List<PerSheet> MergeCompute(PerExcel excel, int allotid)
PerSheet sheet = new PerSheet(info.Name, info.Name, info.SheetType, new List<PerHeader>(), new List<IPerData>());
foreach (var unitType in info.UnitTypes)
{
var atDataList = dataList.Where(t => t.UnitType == (int)unitType);
foreach (var dept in dataList.Where(t => t.UnitType == (int)unitType))
var atDataList = dataList.Where(t => t.UnitType == unitType.ToString());
if (atDataList == null || !atDataList.Any())
continue;
foreach (var dept in dataList.Where(t => t.UnitType == unitType.ToString()))
{
if (string.IsNullOrEmpty(dept.AccountingUnit))
continue;
var econDoctor = economicData.FirstOrDefault(t => t.UnitType == unitType.ToString() && t.AccountingUnit == dept.Department);
var workDoctor = info.Data.FirstOrDefault(t => t.UnitType == unitType.ToString() && t.AccountingUnit == dept.Department);
if (UnitType.专家组 == unitType)
{
econDoctor = economicData.FirstOrDefault(t => t.AccountingUnit == dept.Department);
workDoctor = info.Data.FirstOrDefault(t => t.AccountingUnit == dept.Department);
}
//保底绩效
var minimum = baiscnormList.FirstOrDefault(t => t.PositionName == dept.MinimumReference);
if (!string.IsNullOrEmpty(dept.MinimumReference) && minimum != null)
......@@ -299,9 +306,11 @@ private List<PerSheet> MergeCompute(PerExcel excel, int allotid)
}
}
}
sheet.PerData.AddRange(atDataList);
}
if ("专家核算表" == info.Name && (sheet.PerData == null || sheet.PerData.Any()))
continue;
result.Add(sheet);
}
return result;
......@@ -325,7 +334,7 @@ public List<res_baiscnorm> ComputeMinimum(IEnumerable<PerDataAccountBaisc> accou
foreach (var rule in basicRuleList)
{
var dataList = accountList.Where(t => t.UnitType == (int)rule.UnitType);
var dataList = accountList.Where(t => t.UnitType == rule.UnitType.ToString());
var count = dataList.Sum(t => t.ManagerNumber + t.Number);
decimal totalValue = 0m;
foreach (var dept in dataList)
......
using NPOI.HSSF.UserModel;
using NPOI.HSSF.Util;
using NPOI.SS.UserModel;
using System;
using System.Collections.Generic;
using System.Text;
namespace Performance.Services
{
public enum StyleType
{
//列头固定,
列头,
系数,
数据,
默认,
}
public enum CellFormat
{
数字,
数字2,
百分比,
百分比2,
时间,
默认,
}
public class CellStyle
{
public static ICellStyle CreateCellStyle(IWorkbook wb, StyleType type = StyleType.默认, CellFormat format = CellFormat.默认)
{
ICellStyle cellStyle = wb.CreateCellStyle();
//字体
IFont font = wb.CreateFont();
font.FontHeightInPoints = 11;
font.FontName = "微软雅黑";
font.Color = HSSFColor.Black.Index;
//边框
cellStyle.BorderBottom = BorderStyle.Thin;
cellStyle.BorderLeft = BorderStyle.Thin;
cellStyle.BorderRight = BorderStyle.Thin;
cellStyle.BorderTop = BorderStyle.Thin;
//边框颜色
cellStyle.BottomBorderColor = HSSFColor.Black.Index;
cellStyle.TopBorderColor = HSSFColor.Black.Index;
cellStyle.LeftBorderColor = HSSFColor.Black.Index;
cellStyle.RightBorderColor = HSSFColor.Black.Index;
cellStyle.SetFont(font);
//居中
cellStyle.Alignment = HorizontalAlignment.Center;//水平居中
cellStyle.VerticalAlignment = VerticalAlignment.Center;//垂直居中
switch (type)
{
case StyleType.列头:
cellStyle.FillForegroundColor = HSSFColor.Gold.Index;
cellStyle.FillPattern = FillPattern.SolidForeground;
break;
case StyleType.系数:
cellStyle.FillForegroundColor = HSSFColor.Green.Index;
cellStyle.FillPattern = FillPattern.SolidForeground;
break;
case StyleType.数据:
cellStyle.FillForegroundColor = HSSFColor.SkyBlue.Index;
cellStyle.FillPattern = FillPattern.SolidForeground;
break;
case StyleType.默认:
cellStyle.SetFont(font);
break;
}
IDataFormat datastyle = wb.CreateDataFormat();
switch (format)
{
case CellFormat.时间:
cellStyle.DataFormat = datastyle.GetFormat("yyyy/mm/dd");
break;
case CellFormat.数字:
cellStyle.DataFormat = datastyle.GetFormat("0");
break;
case CellFormat.数字2:
cellStyle.DataFormat = datastyle.GetFormat("0.00");
break;
case CellFormat.百分比:
cellStyle.DataFormat = datastyle.GetFormat("0%");
break;
case CellFormat.百分比2:
cellStyle.DataFormat = datastyle.GetFormat("0.00%");
break;
case CellFormat.默认:
cellStyle.SetFont(font);
break;
}
return cellStyle;
}
}
}
......@@ -333,7 +333,7 @@ private bool WriteExcel(string newpath, string originalPath, List<PerSheet> shee
var importRow = importSheet.CreateRow(maxHeaderRowNumber + i + 1);
Dictionary<string, Func<PerDataAccountBaisc, object>> keyValues = new Dictionary<string, Func<PerDataAccountBaisc, object>>
{
{ "核算单元类型", (t) => EnumHelper.GetDescription((UnitType)t.UnitType) },
{ "核算单元类型", (t) => t.UnitType },
{ "核算单元", (t) => t.AccountingUnit },
{ "科室名称", (t) => t.Department },
{ "医生组核算单元医生数量", (t) => t.Number },
......
......@@ -43,7 +43,7 @@ public List<TitleValue> ExtractScheme(int hospitalId, List<int> executeType)
var titlevalue = new List<TitleValue>();
var list = perforModextractRepository.GetEntities(t => (t.HospitalId == hospitalId || t.HospitalId == null) && executeType.Contains(t.ExecuteType.Value));
if (list != null && list.Any())
titlevalue = list.Select(t => new TitleValue { Title = string.IsNullOrEmpty(t.Description) ? t.EName : $"{t.EName}({t.Description})", Value = t.Id.ToString() }).OrderBy(t => t.Title).ToList();
titlevalue = list.OrderBy(t => t.EName).Select(t => new TitleValue { Title = string.IsNullOrEmpty(t.Description) ? t.EName : $"{t.EName}({t.Description})", Value = t.Id.ToString() }).OrderBy(t => t.Title).ToList();
return titlevalue;
}
......@@ -140,7 +140,6 @@ public List<mod_module> Module(int hospitalId)
/// <param name="hospitalId"></param>
private void AddModule(int hospitalId)
{
var extractList = perforModextractRepository.GetEntities(t => t.IsEnable == 1 && t.ExecuteType == 1);
var moduleList = new mod_module[]
{
new mod_module{ ModuleName = "1.0.1 额外收入", SheetType = (int)SheetType.OtherIncome },
......@@ -194,9 +193,9 @@ public mod_module EditModule(ModModuleRequest request)
throw new PerformanceException("绩效模板已存在!");
entity.ModuleName = request.ModuleName ?? entity.ModuleName;
entity.SheetType = request.SheetType ?? entity.SheetType;
entity.Description = request.Description ?? entity.Description;
entity.ExtractId = request.ExtractId ?? entity.ExtractId;
entity.SheetType = request.SheetType;
entity.Description = request.Description;
entity.ExtractId = request.ExtractId;
if (!perforModmoduleRepository.Update(entity))
throw new PerformanceException("修改失败!");
......@@ -236,7 +235,7 @@ public void DelModule(int moduleId)
public List<mod_item> Items(int moduleId)
{
var list = perforModitemRepository.GetEntities(t => t.ModuleId == moduleId);
return list?.OrderBy(t => t.ItemName).ToList();
return list?.OrderBy(t => t.Id).ToList();
}
/// <summary>
......@@ -427,7 +426,7 @@ public void AddItems(int moduleId)
{
var hospitalConfig = configList.First();
var connection = ConnectionBuilder.Create(DatabaseType.SqlServer, hospitalConfig.DbSource, hospitalConfig.DbName, hospitalConfig.DbUser, hospitalConfig.DbPassword);
string sql = "SELECT ITEM_TYPE FROM dbo.DIC_FEE GROUP BY ITEM_TYPE;";
string sql = "SELECT ITEM_TYPE FROM dbo.DIC_FEE GROUP BY ITEM_TYPE ORDER BY ITEM_TYPE;";
var dataList = perforExtractRepository.ExecuteScript(connection, sql, null);
if (dataList != null && dataList.Any())
{
......@@ -436,6 +435,7 @@ public void AddItems(int moduleId)
ItemName = t.Value.ToString(),
FactorValue1 = 0m,
FactorValue2 = 0m,
FactorValue3 = 0m,
ModuleId = module.Id,
ExtractId = module.ExtractId,
ReadOnly = 1
......
using Dapper;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NPOI.HSSF.UserModel;
using NPOI.HSSF.Util;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using NPOI.XSSF.UserModel;
using Performance.DtoModels;
using Performance.DtoModels.AppSettings;
using Performance.EntityModels;
using Performance.Infrastructure;
using Performance.Repository;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace Performance.Services
{
/// <summary>
/// 数据抽取服务
/// </summary>
public class NewExtractService : IAutoInjection
{
#region
private readonly ILogger<ExtractService> logger;
private readonly IHostingEnvironment environment;
private readonly IEmailService emailService;
private readonly PerSheetService perSheetService;
private readonly PerforHospitalRepository perforHospitalRepository;
private readonly PerforHospitalconfigRepository perforHospitalconfigRepository;
private readonly PerforModmoduleRepository perforModmoduleRepository;
private readonly PerforModextractRepository perforModextractRepository;
private readonly PerforModitemRepository perforModitemRepository;
private readonly PerforModspecialRepository perforModspecialRepository;
private readonly PerforPerallotRepository perforPerallotRepository;
private readonly PerforPersheetRepository perforPersheetRepository;
private readonly PerforImemployeeRepository perforImemployeeRepository;
private readonly PerforImaccountbasicRepository perforImaccountbasicRepository;
private readonly PerforImspecialunitRepository perforImspecialunitRepository;
private readonly PerforImdataRepository perforImdataRepository;
private IWorkbook workbook = null;
private ICellStyle style;
public NewExtractService(ILogger<ExtractService> logger,
IHostingEnvironment environment,
IEmailService emailService,
PerSheetService perSheetService,
PerforHospitalRepository perforHospitalRepository,
PerforHospitalconfigRepository perforHospitalconfigRepository,
PerforModmoduleRepository perforModmoduleRepository,
PerforModextractRepository perforModextractRepository,
PerforModitemRepository perforModitemRepository,
PerforModspecialRepository perforModspecialRepository,
PerforPerallotRepository perforPerallotRepository,
PerforPersheetRepository perforPersheetRepository,
PerforImemployeeRepository perforImemployeeRepository,
PerforImaccountbasicRepository perforImaccountbasicRepository,
PerforImspecialunitRepository perforImspecialunitRepository,
PerforImdataRepository perforImdataRepository)
{
this.logger = logger;
this.environment = environment;
this.emailService = emailService;
this.perSheetService = perSheetService;
this.perforHospitalRepository = perforHospitalRepository;
this.perforHospitalconfigRepository = perforHospitalconfigRepository;
this.perforModmoduleRepository = perforModmoduleRepository;
this.perforModextractRepository = perforModextractRepository;
this.perforModitemRepository = perforModitemRepository;
this.perforModspecialRepository = perforModspecialRepository;
this.perforPerallotRepository = perforPerallotRepository;
this.perforPersheetRepository = perforPersheetRepository;
this.perforImemployeeRepository = perforImemployeeRepository;
this.perforImaccountbasicRepository = perforImaccountbasicRepository;
this.perforImspecialunitRepository = perforImspecialunitRepository;
this.perforImdataRepository = perforImdataRepository;
}
#endregion
#region 改版抽取
public string ExtractData(int allotId, string email, int hospitalId)
{
// 获取绩效信息
var allot = perforPerallotRepository.GetEntity(t => t.ID == allotId);
// 获取医院信息
var hospital = perforHospitalRepository.GetEntity(t => t.ID == hospitalId);
// 获取医院配置信息
var hospitalConfigList = perforHospitalconfigRepository.GetEntities(t => t.HospitalId == hospitalId);
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();
// 获取当前医院模版信息
var modulesList = perforModmoduleRepository.GetEntities(t => t.HospitalId == hospitalId);
// 获取模板项
var moduleIdList = modulesList.Select(t => t.Id).ToList();
var itemsList = perforModitemRepository.GetEntities(t => t.ModuleId.HasValue && moduleIdList.Contains(t.ModuleId.Value));
var extractIdList = itemsList.Select(t => t.ExtractId).Union(modulesList.Select(t => t.ExtractId)).Distinct().ToList();
var extractList = perforModextractRepository.GetEntities(t => extractIdList.Contains(t.Id));
try
{
var (tempPath, newPath) = CopyOriginalFile(hospitalId);
workbook = new XSSFWorkbook(tempPath);
CreateNotExistSheet(modulesList, workbook);
style = CellStyle.CreateCellStyle(workbook, StyleType.数据);
List<AccountUnitEntity> unitList = new List<AccountUnitEntity>();
if (allotLast != null)
unitList = perforImdataRepository.GetAccountUnit(allotLast.ID).ToList();
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:
if (allotLast != null)
WriteEmployee(sheet, allotLast.ID, sheetRead);
break;
case SheetType.AccountBasic:
if (allotLast != null)
WriteAccountBasic(sheet, allotLast.ID, sheetRead);
break;
case SheetType.SpecialUnit:
WriteSpecialUnit(sheet, hospital.ID, allotLast, sheetRead);
break;
case SheetType.Income:
WriteIncome(sheet, hospital.ID, unitList, sheetRead, allot, modulesList, hospitalConfigList);
break;
case SheetType.OtherIncome:
WriteOtherIncome(sheet, hospital.ID, sheetRead);
break;
case SheetType.Expend:
WriteExpend(sheet, hospital.ID, sheetRead);
break;
case SheetType.Workload:
WriteWorkload(sheet, hospital.ID, unitList, sheetRead, allot, modulesList, hospitalConfigList);
break;
}
}
using (FileStream file = new FileStream(newPath, FileMode.OpenOrCreate))
{
workbook.Write(file);
}
LogHelper.Information($"{hospital.HosName}HIS数据提取成功,文件路径:{newPath}。", "提取绩效数据");
SendEmail(email, newPath, $"{hospital.HosName}HIS数据提取成功", $"{hospital.HosName}{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}成功提取。");
return newPath;
}
catch (Exception ex)
{
LogHelper.Error($"数据写入出现异常{ex.ToString()}", "提取绩效数据", "异常");
SendEmail(email, "", $"{hospital.HosName}HIS数据提取失败", $"{hospital.HosName}提取数据过程中出现异常情况,我们将尽快解决问题。给您带来的不便我们深感歉意!");
throw ex;
}
finally
{
allot.IsExtracting = null;
perforPerallotRepository.Update(allot);
workbook.Close();
GC.Collect();
}
}
private static void CreateNotExistSheet(List<mod_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 WriteOtherIncome(ISheet sheet, int hospitalId, IPerSheetDataRead sheetRead)
{
var module = perforModmoduleRepository.GetEntity(t => t.SheetType == (int)SheetType.OtherIncome && t.HospitalId == hospitalId);
var itemList = perforModitemRepository.GetEntities(t => t.ModuleId == module.Id);
if (itemList == null || !itemList.Any()) return;
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 = sheet.GetRow(sheetRead.Point.HeaderFirstRowNum.Value);
int cellStartIndex = sheetRead.Point.HeaderFirstCellNum.Value + 4;
LogHelper.Information($"写入列头信息 -- {module.ModuleName}", "提取绩效数据");
//写入列头信息
foreach (var item in itemList)
{
var headcell = head.GetCell(cellStartIndex);
headcell.SetCellValue(item.ItemName);
headcell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.列头);
var doctorcell = doctorFactor.GetCell(cellStartIndex);
doctorcell.SetCellValue(item.FactorValue1 != null ? (double)item.FactorValue1 : 0);
doctorcell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.系数, CellFormat.百分比);
var nursecell = nurseFactor.GetCell(cellStartIndex);
nursecell.SetCellValue(item.FactorValue2 != null ? (double)item.FactorValue2 : 0);
nursecell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.系数, CellFormat.百分比);
var techniciancell = technicianFactor.GetCell(cellStartIndex);
techniciancell.SetCellValue(item.FactorValue3 != null ? (double)item.FactorValue3 : 0);
techniciancell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.系数, CellFormat.百分比);
cellStartIndex++;
}
}
private void WriteIncome(ISheet sheet, int hospitalId, List<AccountUnitEntity> unitList, IPerSheetDataRead sheetRead, per_allot allot, List<mod_module> moduleList, List<sys_hospitalconfig> hospitalConfigList)
{
var module = moduleList.FirstOrDefault(t => t.ModuleName == sheet.SheetName && t.HospitalId == hospitalId);
if (module == null) return;
var itemList = perforModitemRepository.GetEntities(t => t.ModuleId == module.Id);
if (itemList == null || !itemList.Any()) return;
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);
LogHelper.Information($"写入列头信息 -- {module.ModuleName}", "提取绩效数据");
//写入列头信息
int cellStartIndex = sheetRead.Point.HeaderFirstCellNum.Value + 4;
foreach (var item in itemList)
{
var headcell = GetOrCreate(head, cellStartIndex);
headcell.SetCellValue(item.ItemName);
headcell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.列头);
var doctorcell = GetOrCreate(doctorFactor, cellStartIndex);
doctorcell.SetCellValue(item.FactorValue1 != null ? (double)item.FactorValue1 : 0);
doctorcell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.系数, CellFormat.百分比);
var nursecell = GetOrCreate(nurseFactor, cellStartIndex);
nursecell.SetCellValue(item.FactorValue2 != null ? (double)item.FactorValue2 : 0);
nursecell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.系数, CellFormat.百分比);
var techniciancell = GetOrCreate(technicianFactor, cellStartIndex);
techniciancell.SetCellValue(item.FactorValue3 != null ? (double)item.FactorValue3 : 0);
techniciancell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.系数, CellFormat.百分比);
cellStartIndex++;
}
//查询数据
var extractList = perforModextractRepository.GetEntities(t => module.ExtractId == t.Id);
if (extractList == null || extractList.Count == 0) return;
List<ExtractDto> allExtract = new List<ExtractDto>();
foreach (var item in extractList)
{
LogHelper.Information($"执行SQL脚本获取数据 -- {module.ModuleName},", "提取绩效数据");
var result = QueryDatabase(hospitalConfigList, item, allot);
if (result != null)
allExtract.AddRange(result);
}
LogHelper.Information($"填充数据 -- {module.ModuleName}", "提取绩效数据");
//写入数据
var rowIndex = sheetRead.Point.HeaderFirstRowNum.Value + 1;
foreach (var department in allExtract.Select(t => t.Department).Distinct())
{
var row = sheet.CreateRow(rowIndex);
for (int i = head.FirstCellNum; 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.SheetName == sheet.SheetName && t.Department == department && t.UnitType == 1)?.AccountingUnit;
newCell.SetCellValue(dept ?? "");
newCell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.默认);
}
else if (headName.Replace("\n", "") == "核算单元(护理组)")
{
var dept = unitList.FirstOrDefault(t => t.SheetName == sheet.SheetName && t.Department == department && t.UnitType == 2)?.AccountingUnit;
newCell.SetCellValue(dept ?? "");
newCell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.默认);
}
else if (headName.Replace("\n", "") == "核算单元(医技组)")
{
var dept = unitList.FirstOrDefault(t => t.SheetName == sheet.SheetName && t.Department == department && t.UnitType == 3)?.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;
value = value == 0 ? null : value;
OutToExcelCell(newCell, value);
//newCell.SetCellValue(value == null || value == 0 ? "" : value.ToString());
newCell.CellStyle = style;
}
}
rowIndex++;
}
}
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;
}
private IRow GetOrCreate(ISheet sheet, int index)
{
var row = sheet.GetRow(index);
if (row == null)
row = sheet.CreateRow(index);
return row;
}
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;
}
private void WriteWorkload(ISheet sheet, int hospitalId, List<AccountUnitEntity> unitList, IPerSheetDataRead sheetRead, per_allot allot, List<mod_module> moduleList, List<sys_hospitalconfig> hospitalConfigList)
{
var module = moduleList.FirstOrDefault(t => t.ModuleName == sheet.SheetName && t.HospitalId == hospitalId);
if (module == null) return;
var itemList = perforModitemRepository.GetEntities(t => t.ModuleId == module.Id);
if (itemList == null || !itemList.Any()) return;
var head = GetOrCreate(sheet, sheetRead.Point.HeaderFirstRowNum.Value + 0);
var factor = GetOrCreate(sheet, sheetRead.Point.HeaderFirstRowNum.Value + 1);
LogHelper.Information($"写入列头信息 -- {module.ModuleName}", "提取绩效数据");
//写入列头信息
int cellStartIndex = sheetRead.Point.HeaderFirstCellNum.Value + 2;
foreach (var item in itemList)
{
var headcell = GetOrCreate(head, cellStartIndex);
headcell.SetCellValue(item.ItemName);
headcell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.列头);
var doctorcell = GetOrCreate(factor, cellStartIndex);
doctorcell.SetCellValue(item.FactorValue1 != null ? (double)item.FactorValue1 : 0);
doctorcell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.列头, CellFormat.数字2);
cellStartIndex++;
}
//查询数据
var extractIdList = itemList.Select(t => t.ExtractId).Distinct().ToList();
var extractList = perforModextractRepository.GetEntities(t => extractIdList.Contains(t.Id));
if (extractList == null || extractList.Count == 0) return;
List<ExtractDto> allExtract = new List<ExtractDto>();
foreach (var item in extractList)
{
var category = itemList.Where(t => t.ExtractId == item.Id);
if (category == null || category.Count() == 0) continue;
foreach (var moditem in category)
{
LogHelper.Information($"执行SQL脚本获取数据 -- {moditem.ItemName},", "提取绩效数据");
var result = QueryDatabase(hospitalConfigList, item, allot, moditem.ItemName);
if (result != null)
allExtract.AddRange(result);
}
}
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();
}
LogHelper.Information($"填充数据 -- {module.ModuleName}", "提取绩效数据");
//写入数据
var rowIndex = sheetRead.Point.HeaderFirstRowNum.Value + 2;
foreach (var department in allExtract.Select(t => t.Department).Distinct())
{
var row = sheet.CreateRow(rowIndex);
for (int i = head.FirstCellNum; i < head.LastCellNum; i++)
{
var headName = head.GetCell(i).StringCellValue;
var newCell = row.CreateCell(i);
if (headName == "核算单元")
{
var dept = unitList.FirstOrDefault(t => t.SheetName == sheet.SheetName && 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 (specialHead != null && specialHead.Contains(headName))
newCell.CellStyle = style;
}
}
rowIndex++;
}
}
private List<ExtractDto> QueryDatabase(List<sys_hospitalconfig> hospitalConfigList, mod_extract extract, per_allot allot, string category = null)
{
var config = hospitalConfigList.FirstOrDefault(t => t.Type == extract.SourceType);
var executeScript = extract.ExecuteScript;
var parameters = GetParameters(allot);
using (var connection = ConnectionBuilder.Create(DatabaseType.SqlServer, config.DbSource, config.DbName, config.DbUser, config.DbPassword))
{
foreach (var item in parameters)
{
executeScript = Regex.Replace(executeScript, item.Key, item.Value, RegexOptions.IgnoreCase);
}
LogHelper.Information($"SQL脚本{executeScript},", "提取绩效数据");
var result = connection.Query<ExtractDto>(executeScript, commandTimeout: 20000);
if (result != null && result.Count() > 0)
{
if (extract.ExecuteType == 2)
{
foreach (var item in result)
{
item.Category = category;
}
}
return result.ToList();
}
}
return null;
}
private void WriteExpend(ISheet sheet, int hospitalId, IPerSheetDataRead sheetRead)
{
var module = perforModmoduleRepository.GetEntity(t => t.SheetType == (int)SheetType.Expend && t.HospitalId == hospitalId);
var itemList = perforModitemRepository.GetEntities(t => t.ModuleId == module.Id);
if (itemList == null || !itemList.Any()) return;
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 = sheet.GetRow(sheetRead.Point.HeaderFirstRowNum.Value);
int cellStartIndex = sheetRead.Point.HeaderFirstCellNum.Value + 4;
LogHelper.Information($"写入列头信息 -- {module.ModuleName}", "提取绩效数据");
//写入列头信息
foreach (var item in itemList)
{
var headcell = GetOrCreate(head, cellStartIndex);
headcell.SetCellValue(item.ItemName);
headcell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.列头);
var doctorcell = GetOrCreate(doctorFactor, cellStartIndex);
doctorcell.SetCellValue(item.FactorValue1 != null ? (double)item.FactorValue1 : 0);
doctorcell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.系数, CellFormat.百分比);
var nursecell = GetOrCreate(nurseFactor, cellStartIndex);
nursecell.SetCellValue(item.FactorValue2 != null ? (double)item.FactorValue2 : 0);
nursecell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.系数, CellFormat.百分比);
var techniciancell = GetOrCreate(technicianFactor, cellStartIndex);
techniciancell.SetCellValue(item.FactorValue3 != null ? (double)item.FactorValue3 : 0);
techniciancell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.系数, CellFormat.百分比);
cellStartIndex++;
}
}
private (string TempPath, string NewPath) CopyOriginalFile(int hospitalId)
{
string originalPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Template", "医院绩效模板.xlsx");
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 void WriteEmployee(ISheet sheet, int allotLastId, IPerSheetDataRead sheetRead)
{
LogHelper.Information($"填充数据 -- 人员信息", "提取绩效数据");
var dictionary = new Dictionary<string, Func<im_employee, object>>
{
{ "核算单元", (t) => t.AccountingUnit },
{ "医生姓名", (t) => t.DoctorName },
{ "职称", (t) => t.JobTitle },
{ "绩效基数核算参考对象", (t) => t.FitPeople },
{ "绩效基数核算系数", (t) => t.FitPeopleRatio },
{ "人员分类", (t) => t.AccountType },
{ "岗位系数", (t) => t.PostCoefficient },
{ "参加工作时间", (t) => t.WorkTime },
{ "考核得分率", (t) => t.ScoreAverageRate },
{ "出勤率", (t) => t.Attendance },
{ "其他绩效", (t) => t.OtherPerfor },
{ "医院奖罚", (t) => t.Punishment },
{ "调节系数", (t) => t.Adjust },
};
var dataList = perforImemployeeRepository.GetEntities(t => t.AllotID == allotLastId)?.OrderBy(t => t.AccountType).ToList();
for (int i = 0; i < dataList.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);
foreach (var cell in cellList)
{
var item = dictionary.FirstOrDefault(t => t.Key == cell.StringCellValue);
var value = item.Value.Invoke(dataList[i]) ?? "";
var newCell = importRow.CreateCell(cell.ColumnIndex);
OutToExcelCell(newCell, value);
newCell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.默认);
}
}
}
private void WriteSpecialUnit(ISheet sheet, int hospitalId, per_allot allotLast, IPerSheetDataRead sheetRead)
{
LogHelper.Information($"填充数据 -- 特殊核算单元绩效测算表", "提取绩效数据");
var dictionary = new Dictionary<string, Func<mod_special, List<im_specialunit>, object>>
{
{ "科室", (special,lastAllot) => special.Department },
{ "人数", (special,lastAllot) => lastAllot.Where(t=>special.Department == t.Department).Sum(t=>t.Number) },
{ "量化指标", (special,lastAllot) => special.Target},
{ "量化指标绩效分值",(special,lastAllot) => special.TargetFactor },
{ "调节系数", (special,lastAllot) => special.AdjustFactor },
};
var modDataList = perforModspecialRepository.GetEntities(t => t.HospitalId == hospitalId)?.OrderBy(t => t.Department).ToList();
if (modDataList == null || modDataList.Count == 0) return;
List<im_specialunit> allotDataList = new List<im_specialunit>();
if (allotLast != null)
allotDataList = perforImspecialunitRepository.GetEntities(t => t.AllotID == allotLast.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 = modDataList.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;
for (int i = 0; i < modDataList.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(modDataList[i], allotDataList) ?? "";
if (item.Key == "科室" && rowIndex == mergedBegin)
{
var count = modDataGroup.First(t => t.Department.ToString() == value.ToString()).Count;
mergedEnd = mergedBegin + count - 1;
}
}
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))
newCell.CellStyle = style;
cellIndex++;
}
mergedBegin = mergedEnd + 1;
}
}
private void WriteAccountBasic(ISheet sheet, int allotLastId, IPerSheetDataRead sheetRead)
{
LogHelper.Information($"填充数据 -- 临床科室医护绩效测算表", "提取绩效数据");
var dictionary = new Dictionary<string, Func<im_accountbasic, object>>
{
{ "核算单元类型", (t) => t.UnitType },
{ "核算单元", (t) => t.DoctorAccountingUnit },
{ "科室名称", (t) => t.Department },
{ "科主任/护士长人数", (t) => t.DoctorDirectorNumber },
{ "核算单元人员数量", (t) => t.DoctorNumber },
{ "预算比例", (t) => t.DoctorBasicFactor },
{ "倾斜系数", (t) => t.DoctorSlopeFactor },
{ "效率绩效系数", (t) => t.DoctorEffic },
{ "规模绩效系数", (t) => t.DoctorScale },
{ "管理绩效发放系数", (t) => t.DoctorGrant },
{ "保底绩效参考标准", (t) => t.MinimumReference },
{ "保底绩效系数", (t) => t.MinimumFactor },
{ "其他绩效1", (t) => t.DoctorOtherPerfor1 },
{ "考核得分率", (t) => t.DoctorScoringAverage },
{ "医院奖罚", (t) => t.DoctorExtra },
{ "其他绩效2", (t) => t.DoctorOtherPerfor2 },
{ "调节系数", (t) => t.DoctorAdjustFactor },
};
var dataList = perforImaccountbasicRepository.GetEntities(t => t.AllotID == allotLastId)?.OrderBy(t => t.UnitType).ThenBy(t => t.DoctorAccountingUnit).ToList();
for (int i = 0; i < dataList.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);
foreach (var cell in cellList)
{
var item = dictionary.FirstOrDefault(t => t.Key == cell.StringCellValue);
var value = item.Value.Invoke(dataList[i]) ?? "";
if (cell.StringCellValue == "核算单元类型")
{
value = value.ToString() == "1" ? "医生组" : value.ToString() == "2" ? "护理组" : "医技组";
}
var newCell = importRow.CreateCell(cell.ColumnIndex);
OutToExcelCell(newCell, value);
newCell.CellStyle = CellStyle.CreateCellStyle(workbook, StyleType.默认);
}
}
}
#region 校验数据格式
/// <summary>
/// 校验数据格式,并转换
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public void OutToExcelCell(ICell cell, object obj)
{
string value = obj?.ToString() ?? "";
try
{
var type = obj.GetType();
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
#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)
{
string result = null;
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();
// 获取当前医院模版信息
var modulesList = perforModmoduleRepository.GetEntities(t => t.HospitalId == hospitalId);
if (modulesList == null || modulesList.Count == 0)
throw new PerformanceException("当前医院还未配置模版");
// 获取模板项
var moduleIdList = modulesList.Select(t => t.Id).ToList();
var itemsList = perforModitemRepository.GetEntities(t => t.ModuleId.HasValue && moduleIdList.Contains(t.ModuleId.Value));
if (itemsList == null || itemsList.Count == 0)
throw new PerformanceException("当前医院还未配置模版项");
// 获取当前模板所有相关抽取SQL语句
var extractIdList = itemsList.Select(t => t.ExtractId).Union(modulesList.Select(t => t.ExtractId)).Distinct().ToList();
var extractList = perforModextractRepository.GetEntities(t => extractIdList.Contains(t.Id));
if (extractList == null || extractList.Count == 0)
throw new PerformanceException("当前医院配置模板无需抽取");
}
catch (PerformanceException ex)
{
LogHelper.Error(ex.ToString(), "提取绩效数据");
result = ex.Message;
}
catch (Exception ex)
{
LogHelper.Error(ex.ToString(), "提取绩效数据");
throw new Exception(ex.Message);
}
return result;
}
#endregion
#region 发送邮件
/// <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)
{
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);
}
#endregion
}
}
......@@ -102,7 +102,7 @@ public PerSheet OnceCompute(PerSheet sheet, List<CofDrugProp> confs = null)
{
//获取最大列坐标位置
int thiscell = sheet.PerHeader.OrderByDescending(t => t.PointCell).FirstOrDefault().PointCell + 1;
PerHeader perHead = new PerHeader(0, thiscell, "工作量绩效合计", 0, 2, 1, new List<PerHeader>(), 1);
PerHeader perHead = new PerHeader(0, thiscell, "工作量绩效合计", 0, 1, 1, new List<PerHeader>(), 1);
var dataList = sheet.PerData.Select(t => (PerData)t);
......
......@@ -32,7 +32,7 @@ public List<IPerData> ReadData(ISheet sheet, List<PerHeader> perHeader)
PerDataAccountBaisc unifyUnit = new PerDataAccountBaisc();
unifyUnit.RowNumber = r;
unifyUnit.UnitType = UnitType(row.GetCell(perHeader.FirstOrDefault(p => p.CellValue == "核算单元类型").PointCell)?.ToString());
unifyUnit.UnitType = row.GetCell(perHeader.FirstOrDefault(p => p.CellValue == "核算单元类型").PointCell)?.ToString();
unifyUnit.AccountingUnit = row.GetCell(perHeader.FirstOrDefault(p => p.CellValue == "核算单元").PointCell)?.ToString();
unifyUnit.Department = row.GetCell(perHeader.FirstOrDefault(p => p.CellValue == "科室名称").PointCell)?.ToString();
unifyUnit.ManagerNumber = ConvertHelper.To<decimal>(row.GetCell(perHeader.FirstOrDefault(p => p.CellValue == "科主任/护士长人数").PointCell)?.ToString());
......
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