using Furion.DatabaseAccessor.Extensions;
using NPOI.SS.UserModel;
using YBEE.EQM.Core;
namespace YBEE.EQM.Application;
///
/// 监测教师管理服务
///
public class ExamTeacherService : IExamTeacherService, ITransient
{
private readonly IRepository _rep;
private readonly ISysDictDataService _sysDictDataService;
public ExamTeacherService(IRepository rep, ISysDictDataService sysDictDataService)
{
_rep = rep;
_sysDictDataService = sysDictDataService;
}
#region 批量导入
///
/// 上传监测教师批量导入文件
///
///
///
///
public async Task> Upload(string filePath, int examPlanId)
{
UploadExamDataOutput result = new();
try
{
using FileStream fs = new(filePath, FileMode.Open, FileAccess.Read);
IWorkbook workbook = ExcelUtil.GetWorkbook(filePath, fs);
var sheet = workbook.GetSheetAt(0);
var rows = sheet.GetRowEnumerator();
#region 验证表结构
// 少于2行验证
if (sheet.LastRowNum < 2)
{
result.ErrorMessage.Add("第一行应为填写说明,第二行应为标题行,请勿修改模板结构。");
return result;
}
// 跳过第一行
rows.MoveNext();
// 读取表头
rows.MoveNext();
IRow headerRow = (IRow)rows.Current;
int index = 0;
int NAME_INDEX = index++;
int CERT_TYPE_INDEX = index++;
int ID_NUM_INDEX = index++;
int GENDER_INDEX = index++;
int JOB_INDEX = index++;
int MOBILE_INDEX = index++;
int EMAIL_INDEX = index++;
int REMARK_INDEX = index;
Dictionary headers = new()
{
{ NAME_INDEX, "姓名" },
{ CERT_TYPE_INDEX, "证件类型" },
{ ID_NUM_INDEX, "证件号码" },
{ GENDER_INDEX, "性别" },
{ JOB_INDEX, "校内职务" },
{ MOBILE_INDEX, "手机号码" },
{ EMAIL_INDEX, "电子邮箱" },
{ REMARK_INDEX, "备注" },
};
List headerErrors = new();
for (int i = 0; i <= index; i++)
{
if (headerRow.GetCell(i)?.ToString() != headers[i])
{
char letter = (char)('A' + i);
headerErrors.Add(letter.ToString());
}
}
if (headerErrors.Any())
{
string columnErrors = string.Join("、", headerErrors);
result.ErrorMessage.Add($"第2行标题行{columnErrors}列名错误。从A列开始依次应为姓名、证件类型、证件号码、性别、校内职务、手机号码、电子邮箱和备注。");
return result;
}
result.StructureCorrect = true;
#endregion
#region 处理数据
// 获取证件类型
var cts = await _sysDictDataService.GetListByDictTypeId(304);
var certificateTypes = cts.ToDictionary(x => x.Name, y => y.Value);
// 获取选科组全
var sjs = await _sysDictDataService.GetListByDictTypeId(306);
var jobs = sjs.ToDictionary(x => x.Name, y => y.Value);
// 读取数据
List data = new();
int rn = 0;
while (rows.MoveNext())
{
IRow row = (IRow)rows.Current;
string rv = row.GetCell(0)?.ToString().Trim() ?? "";
rv += row.GetCell(1)?.ToString().Trim() ?? "";
if (rv == "")
{
break;
}
UploadExamTeacherOutput item = new() { RowNumber = ++rn };
// 姓名
item.Name = StringUtil.ClearWhite(row.GetCell(NAME_INDEX)?.ToString() ?? "");
if (item.Name == "")
{
item.ErrorMessage.Add(headers[NAME_INDEX]);
}
// 证件类型
item.CertificateTypeName = StringUtil.ClearWhite(row.GetCell(CERT_TYPE_INDEX)?.ToString() ?? "");
if (item.CertificateTypeName == "" || !certificateTypes.ContainsKey(item.CertificateTypeName))
{
item.ErrorMessage.Add(headers[CERT_TYPE_INDEX]);
}
else
{
item.CertificateType = (CertificateType)certificateTypes[item.CertificateTypeName];
}
// 证件号码
item.IdNumber = StringUtil.ClearWhite(row.GetCell(ID_NUM_INDEX)?.ToString() ?? "").ToUpper();
if (item.CertificateType == CertificateType.ID_CARD)
{
var idNumberValidate = CertificateNumberValidator.ValidateIdCard(item.IdNumber);
if (!idNumberValidate.Success)
{
item.ErrorMessage.Add($"{item.CertificateTypeName}{idNumberValidate.ErrorMessage}");
}
else
{
item.GenderName = idNumberValidate.Gender == Gender.MALE ? "男" : "女";
item.Gender = idNumberValidate.Gender;
}
}
else
{
// 性别
item.GenderName = StringUtil.ClearWhite(row.GetCell(GENDER_INDEX)?.ToString() ?? "");
if (item.CertificateType != CertificateType.ID_CARD)
{
item.Gender = item.GenderName == "男" ? Gender.MALE : item.GenderName == "女" ? Gender.FEMALE : Gender.UNKNOWN;
}
}
// 校内职务
item.SchoolJobTitleName = StringUtil.ClearWhite(row.GetCell(JOB_INDEX)?.ToString() ?? "");
if (item.SchoolJobTitleName == "")
{
item.SchoolJobTitle = SchoolJobTitle.TEACHER;
}
else if (jobs.ContainsKey(item.SchoolJobTitleName))
{
item.SchoolJobTitle = (SchoolJobTitle)jobs[item.SchoolJobTitleName];
}
else
{
item.ErrorMessage.Add(headers[JOB_INDEX]);
}
// 手机号码
item.Mobile = StringUtil.ClearWhite(row.GetCell(MOBILE_INDEX)?.ToString() ?? "");
// 电子邮箱
item.Email = StringUtil.ClearWhite(row.GetCell(EMAIL_INDEX)?.ToString() ?? "");
// 备注
item.Remark = StringUtil.ClearWhite(row.GetCell(REMARK_INDEX)?.ToString() ?? "");
// 行是否验证通过
item.IsSuccess = item.ErrorMessage.Count == 0;
data.Add(item);
result.TotalRowCount++;
if (!item.IsSuccess)
{
result.ErrorRowCount++;
}
}
result.Rows = data;
#endregion
workbook.Close();
fs.Close();
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
finally
{
File.Delete(filePath);
}
return result;
}
///
/// 批量导入监测教师
///
///
///
public async Task Import(ImportExamTeacherInput input)
{
// 删除同一监测计划中监测机构内所有数据
await _rep.Where(t => t.ExamPlanId == input.ExamPlanId && t.SysOrgId == input.SysOrgId).ExecuteDeleteAsync();
foreach (var item in input.Items)
{
item.SysOrgId ??= CurrentSysUserInfo.SysOrgId;
}
var items = input.Items.Select(t => t.Adapt()).ToList();
await _rep.InsertAsync(items);
}
#endregion
#region 创建编辑
///
/// 添加监测教师
///
///
///
public async Task Add(AddExamTeacherInput input)
{
var orgId = input.SysOrgId ?? CurrentSysUserInfo.SysOrgId;
// 检测同一监测计划中同机构内是否有相同证件号码的教师
var sameItems = await _rep.DetachedEntities.Where(t => t.ExamPlanId == input.ExamPlanId && t.SysOrgId == orgId && t.CertificateType == input.CertificateType && t.IdNumber == input.IdNumber).ProjectToType().ToListAsync();
if (sameItems.Any())
{
throw Oops.Oh(ErrorCode.E2003, "", "证件号码");
}
var item = input.Adapt();
if (!input.SysOrgId.HasValue)
{
item.SysOrgId = orgId;
}
await item.InsertAsync();
}
///
/// 更新监测教师
///
///
///
public async Task Update(UpdateExamTeacherInput input)
{
var oitem = await _rep.DetachedEntities.FirstOrDefaultAsync(t => t.Id == input.Id) ?? throw Oops.Oh(ErrorCode.E2001);
var item = input.Adapt();
await item.UpdateIncludeAsync(new[] {
nameof(item.Name),
nameof(item.CertificateType),
nameof(item.SchoolJobTitle),
nameof(item.IdNumber),
nameof(item.Gender),
nameof(item.BirthDate),
nameof(item.Mobile),
nameof(item.Email),
nameof(item.Remark),
});
}
///
/// 删除监测教师
///
///
///
public async Task Del(BaseId input)
{
var item = await _rep.FirstOrDefaultAsync(t => t.Id == input.Id) ?? throw Oops.Oh(ErrorCode.E2001);
await item.DeleteAsync();
}
///
/// 清空监测教师
///
///
///
public async Task Clear(ClearExamTeacherInput input)
{
var orgId = CurrentSysUserInfo.SysOrgId;
await _rep.Where(t => t.ExamPlanId == input.ExamPlanId && t.SysOrgId == orgId).ExecuteDeleteAsync();
}
#endregion
#region 查询统计
///
/// 分页查询监测教师列表
///
///
///
public async Task> QueryPageList(ExamTeacherPageInput input)
{
var query = GetQueryBase(input);
query = query.Where(t => t.ExamPlanId == input.ExamPlanId && t.SysOrgId == CurrentSysUserInfo.SysOrgId);
var ret = await query.OrderBy(t => t.Id).ProjectToType().ToADPagedListAsync(input.PageIndex, input.PageSize);
return ret;
}
#endregion
#region 私有方法
///
/// 构建查询
///
///
///
private IQueryable GetQueryBase(ExamTeacherPageInput input)
{
var name = !string.IsNullOrEmpty(input.Name?.Trim());
var idNumber = !string.IsNullOrEmpty(input.IdNumber?.Trim());
var mobile = !string.IsNullOrEmpty(input.Mobile?.Trim());
var email = !string.IsNullOrEmpty(input.Email?.Trim());
var query = _rep.DetachedEntities.Where((name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")))
.Where((idNumber, u => EF.Functions.Like(u.IdNumber, $"%{input.IdNumber.Trim()}%")))
.Where((mobile, u => EF.Functions.Like(u.Mobile, $"%{input.Mobile.Trim()}%")))
.Where((email, u => EF.Functions.Like(u.Email, $"%{input.Email.Trim()}%")))
.Where(input.CertificateType.HasValue, t => t.CertificateType == input.CertificateType)
.Where(input.SchoolJobTitle.HasValue, t => t.SchoolJobTitle == input.SchoolJobTitle)
.Where(input.Gender.HasValue, t => t.Gender == input.Gender);
return query;
}
#endregion
}