修复相关bug
This commit is contained in:
+63
-2
@@ -147,7 +147,7 @@ public class OnboardingContractTemplateService : DbRepository<ObContractTemplate
|
|||||||
"合同模板");
|
"合同模板");
|
||||||
NormalizeInput(input);
|
NormalizeInput(input);
|
||||||
await ValidateBusinessScope(input.CompanyId, input.DepartmentId, input.PositionIds);
|
await ValidateBusinessScope(input.CompanyId, input.DepartmentId, input.PositionIds);
|
||||||
await ValidateReferencedOnboardingTemplates(input);
|
await ValidateReferencedOnboardingTemplates(input, template.Status);
|
||||||
await EnsureCodeUnique(input.TemplateCode, input.Id);
|
await EnsureCodeUnique(input.TemplateCode, input.Id);
|
||||||
|
|
||||||
var entity = BuildEntity(input.Id, input);
|
var entity = BuildEntity(input.Id, input);
|
||||||
@@ -370,6 +370,18 @@ public class OnboardingContractTemplateService : DbRepository<ObContractTemplate
|
|||||||
?? throw Oops.Bah("模板版本不存在");
|
?? throw Oops.Bah("模板版本不存在");
|
||||||
await EnsureTemplateCanManage(version.TemplateId);
|
await EnsureTemplateCanManage(version.TemplateId);
|
||||||
|
|
||||||
|
if (version.VersionStatus == ContractTemplateVersionStatus.Enabled
|
||||||
|
&& input.VersionStatus == ContractTemplateVersionStatus.Disabled)
|
||||||
|
{
|
||||||
|
var referencedNames = await GetEnabledOnboardingTemplateNames(
|
||||||
|
version.TemplateId,
|
||||||
|
version.Id);
|
||||||
|
if (referencedNames.Count > 0)
|
||||||
|
{
|
||||||
|
throw Oops.Bah(
|
||||||
|
$"该签署材料版本正在被启用中的入职模板{FormatTemplateNames(referencedNames)}引用,不能停用,请先调整或停用这些入职模板");
|
||||||
|
}
|
||||||
|
}
|
||||||
if (input.VersionStatus == ContractTemplateVersionStatus.Enabled)
|
if (input.VersionStatus == ContractTemplateVersionStatus.Enabled)
|
||||||
{
|
{
|
||||||
ContractTemplateVersionValidity.ValidateRange(version.EffectiveDate, version.ExpiryDate);
|
ContractTemplateVersionValidity.ValidateRange(version.EffectiveDate, version.ExpiryDate);
|
||||||
@@ -550,7 +562,8 @@ public class OnboardingContractTemplateService : DbRepository<ObContractTemplate
|
|||||||
/// 防止修改合同模板归属后破坏已经保存的入职模板配置。
|
/// 防止修改合同模板归属后破坏已经保存的入职模板配置。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task ValidateReferencedOnboardingTemplates(
|
private async Task ValidateReferencedOnboardingTemplates(
|
||||||
OnboardingContractTemplateEditInput input)
|
OnboardingContractTemplateEditInput input,
|
||||||
|
string currentStatus)
|
||||||
{
|
{
|
||||||
var relations = await Context.Queryable<ObOnboardingTemplateContract>()
|
var relations = await Context.Queryable<ObOnboardingTemplateContract>()
|
||||||
.Where(item => item.ContractTemplateId == input.Id)
|
.Where(item => item.ContractTemplateId == input.Id)
|
||||||
@@ -565,6 +578,21 @@ public class OnboardingContractTemplateService : DbRepository<ObContractTemplate
|
|||||||
var onboardingTemplates = await Context.Queryable<ObOnboardingTemplate>()
|
var onboardingTemplates = await Context.Queryable<ObOnboardingTemplate>()
|
||||||
.Where(item => onboardingTemplateIds.Contains(item.Id))
|
.Where(item => onboardingTemplateIds.Contains(item.Id))
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
if (string.Equals(currentStatus, "enable", StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& !string.Equals(input.Status, "enable", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
var enabledTemplateNames = onboardingTemplates
|
||||||
|
.Where(item => !item.IsDelete && item.Status == "enable")
|
||||||
|
.Select(item => item.TemplateName)
|
||||||
|
.Distinct()
|
||||||
|
.OrderBy(item => item)
|
||||||
|
.ToList();
|
||||||
|
if (enabledTemplateNames.Count > 0)
|
||||||
|
{
|
||||||
|
throw Oops.Bah(
|
||||||
|
$"该签署材料模板正在被启用中的入职模板{FormatTemplateNames(enabledTemplateNames)}引用,不能停用,请先调整或停用这些入职模板");
|
||||||
|
}
|
||||||
|
}
|
||||||
var positionRelations = await Context.Queryable<ObOnboardingTemplatePosition>()
|
var positionRelations = await Context.Queryable<ObOnboardingTemplatePosition>()
|
||||||
.Where(item => onboardingTemplateIds.Contains(item.OnboardingTemplateId))
|
.Where(item => onboardingTemplateIds.Contains(item.OnboardingTemplateId))
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
@@ -589,6 +617,39 @@ public class OnboardingContractTemplateService : DbRepository<ObContractTemplate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<List<string>> GetEnabledOnboardingTemplateNames(
|
||||||
|
long contractTemplateId,
|
||||||
|
long? contractTemplateVersionId = null)
|
||||||
|
{
|
||||||
|
var relations = await Context.Queryable<ObOnboardingTemplateContract>()
|
||||||
|
.Where(item => item.ContractTemplateId == contractTemplateId)
|
||||||
|
.WhereIF(contractTemplateVersionId.HasValue,
|
||||||
|
item => item.ContractTemplateVersionId == contractTemplateVersionId.Value)
|
||||||
|
.ToListAsync();
|
||||||
|
if (relations.Count == 0)
|
||||||
|
return new List<string>();
|
||||||
|
|
||||||
|
var onboardingTemplateIds = relations
|
||||||
|
.Select(item => item.OnboardingTemplateId)
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
var names = await Context.Queryable<ObOnboardingTemplate>()
|
||||||
|
.Where(item => onboardingTemplateIds.Contains(item.Id)
|
||||||
|
&& !item.IsDelete
|
||||||
|
&& item.Status == "enable")
|
||||||
|
.Select(item => item.TemplateName)
|
||||||
|
.ToListAsync();
|
||||||
|
return names
|
||||||
|
.Where(item => !string.IsNullOrWhiteSpace(item))
|
||||||
|
.Distinct()
|
||||||
|
.OrderBy(item => item)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatTemplateNames(IEnumerable<string> templateNames)
|
||||||
|
{
|
||||||
|
return string.Join("、", templateNames.Select(item => $"“{item}”"));
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构建合同模板主档案实体。
|
/// 构建合同模板主档案实体。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+27
-4
@@ -31,6 +31,14 @@ public class OnboardingIdentityValidationService : IOnboardingIdentityValidation
|
|||||||
throw Oops.Bah("该姓名和身份证号已完成正式员工建档,请勿重复提交入职资料");
|
throw Oops.Bah("该姓名和身份证号已完成正式员工建档,请勿重复提交入职资料");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 身份证号码代表唯一自然人。即使姓名填写不同,也不能绕过正式员工重复校验。
|
||||||
|
var formalEmployeeIdCardExists = await _db.Queryable<ObEmployee>()
|
||||||
|
.AnyAsync(item => item.IdCardNumber == idCardNumber);
|
||||||
|
if (formalEmployeeIdCardExists)
|
||||||
|
{
|
||||||
|
throw Oops.Bah("该身份证号码已完成正式员工建档,请核对姓名和身份证号码;如需更正,请联系 HR");
|
||||||
|
}
|
||||||
|
|
||||||
// 待填写任务不占用身份,以实际先提交的任务为准;撤销或过期任务允许重新发起。
|
// 待填写任务不占用身份,以实际先提交的任务为准;撤销或过期任务允许重新发起。
|
||||||
var duplicateTaskExists = await _db.Queryable<ObTaskEmployeeInfo>()
|
var duplicateTaskExists = await _db.Queryable<ObTaskEmployeeInfo>()
|
||||||
.InnerJoin<ObOnboardingTask>((info, task) => info.TaskId == task.Id)
|
.InnerJoin<ObOnboardingTask>((info, task) => info.TaskId == task.Id)
|
||||||
@@ -42,9 +50,24 @@ public class OnboardingIdentityValidationService : IOnboardingIdentityValidation
|
|||||||
|| task.TaskStatus == OnboardingTaskStatus.Approved
|
|| task.TaskStatus == OnboardingTaskStatus.Approved
|
||||||
|| task.TaskStatus == OnboardingTaskStatus.Archived))
|
|| task.TaskStatus == OnboardingTaskStatus.Archived))
|
||||||
.AnyAsync();
|
.AnyAsync();
|
||||||
if (!duplicateTaskExists)
|
if (duplicateTaskExists)
|
||||||
return;
|
{
|
||||||
|
throw Oops.Bah("该姓名和身份证号已存在正在办理的入职任务,请勿重复提交;如需补充材料,请联系 HR 继续使用原任务链接");
|
||||||
|
}
|
||||||
|
|
||||||
throw Oops.Bah("该姓名和身份证号已存在正在办理的入职任务,请勿重复提交;如需补充材料,请联系 HR 继续使用原任务链接");
|
// 再单独按身份证号码校验,防止不同姓名使用同一证件重复提交不同任务。
|
||||||
|
var duplicateIdCardTaskExists = await _db.Queryable<ObTaskEmployeeInfo>()
|
||||||
|
.InnerJoin<ObOnboardingTask>((info, task) => info.TaskId == task.Id)
|
||||||
|
.Where((info, task) => info.TaskId != currentTaskId
|
||||||
|
&& info.IdCardNumber == idCardNumber
|
||||||
|
&& (task.TaskStatus == OnboardingTaskStatus.Reviewing
|
||||||
|
|| task.TaskStatus == OnboardingTaskStatus.Rejected
|
||||||
|
|| task.TaskStatus == OnboardingTaskStatus.Approved
|
||||||
|
|| task.TaskStatus == OnboardingTaskStatus.Archived))
|
||||||
|
.AnyAsync();
|
||||||
|
if (duplicateIdCardTaskExists)
|
||||||
|
{
|
||||||
|
throw Oops.Bah("该身份证号码已存在正在办理的入职任务,请核对姓名和身份证号码;如需补充材料,请联系 HR 继续使用原任务链接");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+59
-1
@@ -229,7 +229,65 @@ public class OnboardingTemplateService : IOnboardingTemplateService
|
|||||||
&& templateIds.Contains(item.Id))
|
&& templateIds.Contains(item.Id))
|
||||||
.OrderBy(item => item.TemplateName)
|
.OrderBy(item => item.TemplateName)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
return await BuildOutputs(templates);
|
if (templates.Count == 0)
|
||||||
|
return await BuildOutputs(templates);
|
||||||
|
|
||||||
|
var onboardingTemplateIds = templates.Select(item => item.Id).ToList();
|
||||||
|
var contractConfigs = await _db.Queryable<ObOnboardingTemplateContract>()
|
||||||
|
.Where(item => onboardingTemplateIds.Contains(item.OnboardingTemplateId))
|
||||||
|
.ToListAsync();
|
||||||
|
if (contractConfigs.Count == 0)
|
||||||
|
return await BuildOutputs(new List<ObOnboardingTemplate>());
|
||||||
|
|
||||||
|
var contractTemplateIds = contractConfigs
|
||||||
|
.Select(item => item.ContractTemplateId)
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
var contractVersionIds = contractConfigs
|
||||||
|
.Select(item => item.ContractTemplateVersionId)
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
var contractTemplates = await _db.Queryable<ObContractTemplate>()
|
||||||
|
.Where(item => contractTemplateIds.Contains(item.Id))
|
||||||
|
.ToListAsync();
|
||||||
|
var contractVersions = await _db.Queryable<ObContractTemplateVersion>()
|
||||||
|
.Where(item => contractVersionIds.Contains(item.Id))
|
||||||
|
.ToListAsync();
|
||||||
|
var contractPositions = await _db.Queryable<ObContractTemplatePosition>()
|
||||||
|
.Where(item => contractTemplateIds.Contains(item.ContractTemplateId)
|
||||||
|
&& item.PositionId == positionId)
|
||||||
|
.ToListAsync();
|
||||||
|
var now = DateTime.Now;
|
||||||
|
var availableTemplates = templates.Where(template =>
|
||||||
|
{
|
||||||
|
var configs = contractConfigs
|
||||||
|
.Where(item => item.OnboardingTemplateId == template.Id)
|
||||||
|
.ToList();
|
||||||
|
if (configs.Count == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return configs.All(config =>
|
||||||
|
{
|
||||||
|
var contractTemplate = contractTemplates
|
||||||
|
.FirstOrDefault(item => item.Id == config.ContractTemplateId);
|
||||||
|
var version = contractVersions
|
||||||
|
.FirstOrDefault(item => item.Id == config.ContractTemplateVersionId);
|
||||||
|
return contractTemplate != null
|
||||||
|
&& string.Equals(
|
||||||
|
contractTemplate.Status,
|
||||||
|
"enable",
|
||||||
|
StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& contractTemplate.CompanyId == template.CompanyId
|
||||||
|
&& contractTemplate.DepartmentId == template.DepartmentId
|
||||||
|
&& contractPositions.Any(item =>
|
||||||
|
item.ContractTemplateId == config.ContractTemplateId)
|
||||||
|
&& version != null
|
||||||
|
&& version.TemplateId == config.ContractTemplateId
|
||||||
|
&& ContractTemplateVersionValidity.IsAvailable(version, now);
|
||||||
|
});
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
return await BuildOutputs(availableTemplates);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void NormalizeAndValidateInput(OnboardingTemplateSaveInput input)
|
private static void NormalizeAndValidateInput(OnboardingTemplateSaveInput input)
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ public class ConfigService : DbRepository<SysConfig>, IConfigService
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public async Task<List<SysConfig>> GetConfigsByCategory(string category)
|
public async Task<List<SysConfig>> GetConfigsByCategory(string category)
|
||||||
{
|
{
|
||||||
|
// 业务自定义配置需立即生效,始终以数据库中的最新数据为准。
|
||||||
|
if (category == CateGoryConst.CONFIG_BIZ_DEFINE)
|
||||||
|
return await GetListAsync(it => it.Category == category);
|
||||||
|
|
||||||
var key = SystemConst.CACHE_DEV_CONFIG + category;//系统配置key
|
var key = SystemConst.CACHE_DEV_CONFIG + category;//系统配置key
|
||||||
//先从redis拿配置
|
//先从redis拿配置
|
||||||
var configList = _simpleCacheService.HashGetAll<SysConfig>(key).Values.ToList();
|
var configList = _simpleCacheService.HashGetAll<SysConfig>(key).Values.ToList();
|
||||||
@@ -51,6 +55,10 @@ public class ConfigService : DbRepository<SysConfig>, IConfigService
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public async Task<SysConfig> GetByConfigKey(string category, string configKey)
|
public async Task<SysConfig> GetByConfigKey(string category, string configKey)
|
||||||
{
|
{
|
||||||
|
// 业务自定义配置不走缓存,避免修改后仍读取到本机旧值。
|
||||||
|
if (category == CateGoryConst.CONFIG_BIZ_DEFINE)
|
||||||
|
return await GetFirstAsync(it => it.Category == category && it.ConfigKey == configKey);
|
||||||
|
|
||||||
var key = SystemConst.CACHE_DEV_CONFIG + category;//系统配置key
|
var key = SystemConst.CACHE_DEV_CONFIG + category;//系统配置key
|
||||||
//先从redis拿配置
|
//先从redis拿配置
|
||||||
var config = _simpleCacheService.HashGetOne<SysConfig>(key, configKey);
|
var config = _simpleCacheService.HashGetOne<SysConfig>(key, configKey);
|
||||||
|
|||||||
Reference in New Issue
Block a user