入职任务预览,入职任务cope,验证填入的信息
This commit is contained in:
+197
@@ -14,6 +14,177 @@ public class OnboardingContractDocumentService : IOnboardingContractDocumentServ
|
||||
_fileService = fileService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在任务创建前生成单份临时 DOCX,仅通过响应返回,不写文件表和 OSS。
|
||||
/// </summary>
|
||||
public async Task<OnboardingContractPreviewOutput> PreviewBeforeCreate(
|
||||
OnboardingContractPreviewInput input)
|
||||
{
|
||||
var company = await _db.Queryable<ObCompany>()
|
||||
.FirstAsync(item => item.Id == input.CompanyId
|
||||
&& item.Status == CommonStatusConst.ENABLE)
|
||||
?? throw Oops.Bah("公司不存在或未启用");
|
||||
|
||||
var departmentExists = await _db.Queryable<ObDepartment>()
|
||||
.AnyAsync(item => item.Id == input.DepartmentId
|
||||
&& item.CompanyId == input.CompanyId
|
||||
&& item.Status == CommonStatusConst.ENABLE);
|
||||
if (!departmentExists)
|
||||
throw Oops.Bah("部门不存在、未启用或不属于该公司");
|
||||
|
||||
var positionExists = await _db.Queryable<ObPosition>()
|
||||
.AnyAsync(item => item.Id == input.PositionId
|
||||
&& item.CompanyId == input.CompanyId
|
||||
&& item.DepartmentId == input.DepartmentId
|
||||
&& item.Status == CommonStatusConst.ENABLE);
|
||||
if (!positionExists)
|
||||
throw Oops.Bah("岗位不存在、未启用或不属于该部门/公司");
|
||||
|
||||
var onboardingTemplate = await _db.Queryable<ObOnboardingTemplate>()
|
||||
.FirstAsync(item => item.Id == input.OnboardingTemplateId
|
||||
&& item.CompanyId == input.CompanyId
|
||||
&& item.DepartmentId == input.DepartmentId
|
||||
&& item.Status == CommonStatusConst.ENABLE)
|
||||
?? throw Oops.Bah("入职模板不存在、未启用或不属于该公司、部门");
|
||||
|
||||
var supportsPosition = await _db.Queryable<ObOnboardingTemplatePosition>()
|
||||
.AnyAsync(item => item.OnboardingTemplateId == onboardingTemplate.Id
|
||||
&& item.PositionId == input.PositionId);
|
||||
if (!supportsPosition)
|
||||
throw Oops.Bah("所选入职模板不适用于该岗位");
|
||||
|
||||
// 当前业务只预览入职模板中排序第一的合同,后续多合同可在此扩展。
|
||||
var contractConfig = await _db.Queryable<ObOnboardingTemplateContract>()
|
||||
.Where(item => item.OnboardingTemplateId == onboardingTemplate.Id)
|
||||
.OrderBy(item => item.SortCode)
|
||||
.FirstAsync()
|
||||
?? throw Oops.Bah("入职模板尚未配置合同文件");
|
||||
|
||||
var contractTemplate = await _db.Queryable<ObContractTemplate>()
|
||||
.FirstAsync(item => item.Id == contractConfig.ContractTemplateId
|
||||
&& item.CompanyId == input.CompanyId
|
||||
&& item.DepartmentId == input.DepartmentId
|
||||
&& item.Status == CommonStatusConst.ENABLE)
|
||||
?? throw Oops.Bah("合同模板不存在、未启用或不属于当前公司、部门");
|
||||
|
||||
var contractSupportsPosition = await _db.Queryable<ObContractTemplatePosition>()
|
||||
.AnyAsync(item => item.ContractTemplateId == contractTemplate.Id
|
||||
&& item.PositionId == input.PositionId);
|
||||
if (!contractSupportsPosition)
|
||||
throw Oops.Bah("合同模板不适用于当前岗位");
|
||||
|
||||
var version = await _db.Queryable<ObContractTemplateVersion>()
|
||||
.FirstAsync(item => item.Id == contractConfig.ContractTemplateVersionId
|
||||
&& item.TemplateId == contractTemplate.Id
|
||||
&& item.VersionStatus == ContractTemplateVersionStatus.Enabled)
|
||||
?? throw Oops.Bah("合同版本不存在、未启用或不属于当前合同模板");
|
||||
|
||||
var definitions = await _db.Queryable<ObTemplateVariable>()
|
||||
.Where(item => item.TemplateVersionId == version.Id)
|
||||
.OrderBy(item => item.SortCode)
|
||||
.ToListAsync();
|
||||
var duplicateDefinition = definitions
|
||||
.GroupBy(item => item.VariableCode, StringComparer.OrdinalIgnoreCase)
|
||||
.FirstOrDefault(group => group.Count() > 1);
|
||||
if (duplicateDefinition != null)
|
||||
throw Oops.Bah($"合同变量“{duplicateDefinition.Key}”存在重复定义");
|
||||
|
||||
var inputs = input.ContractVariables
|
||||
?? new List<OnboardingInitialContractVariableInput>();
|
||||
OnboardingTaskService.ValidateInitialContractDateRanges(inputs);
|
||||
|
||||
var duplicateInput = inputs
|
||||
.GroupBy(item => new
|
||||
{
|
||||
item.ContractTemplateVersionId,
|
||||
VariableCode = item.VariableCode?.ToUpperInvariant()
|
||||
})
|
||||
.FirstOrDefault(group => group.Count() > 1);
|
||||
if (duplicateInput != null)
|
||||
throw Oops.Bah($"合同变量“{duplicateInput.Key.VariableCode}”重复提交");
|
||||
|
||||
var editableDefinitions = definitions
|
||||
.Where(IsHrEditableDefinition)
|
||||
.ToList();
|
||||
foreach (var submitted in inputs)
|
||||
{
|
||||
var definitionExists = submitted.ContractTemplateVersionId == version.Id
|
||||
&& editableDefinitions.Any(definition =>
|
||||
string.Equals(
|
||||
definition.VariableCode,
|
||||
submitted.VariableCode,
|
||||
StringComparison.OrdinalIgnoreCase));
|
||||
if (!definitionExists)
|
||||
throw Oops.Bah($"合同变量“{submitted.VariableCode}”不存在或不允许人事填写");
|
||||
}
|
||||
|
||||
var missingRequired = editableDefinitions.FirstOrDefault(definition =>
|
||||
{
|
||||
if (!definition.Required)
|
||||
return false;
|
||||
|
||||
var submitted = inputs.FirstOrDefault(item =>
|
||||
item.ContractTemplateVersionId == version.Id
|
||||
&& string.Equals(
|
||||
item.VariableCode,
|
||||
definition.VariableCode,
|
||||
StringComparison.OrdinalIgnoreCase));
|
||||
return string.IsNullOrWhiteSpace(
|
||||
submitted?.VariableValue ?? definition.DefaultValue);
|
||||
});
|
||||
if (missingRequired != null)
|
||||
throw Oops.Bah($"请填写合同变量“{missingRequired.VariableName}”");
|
||||
|
||||
var previewTask = new ObOnboardingTask
|
||||
{
|
||||
TaskNo = "【发起后自动生成】",
|
||||
CompanyId = input.CompanyId,
|
||||
DepartmentId = input.DepartmentId,
|
||||
PositionId = input.PositionId,
|
||||
OnboardingTemplateId = input.OnboardingTemplateId
|
||||
};
|
||||
var emptyDynamicValues = new Dictionary<string, string>(
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
var values = definitions.ToDictionary(
|
||||
definition => definition.VariableCode,
|
||||
definition =>
|
||||
{
|
||||
var submitted = inputs.FirstOrDefault(item =>
|
||||
item.ContractTemplateVersionId == version.Id
|
||||
&& string.Equals(
|
||||
item.VariableCode,
|
||||
definition.VariableCode,
|
||||
StringComparison.OrdinalIgnoreCase));
|
||||
if (submitted != null)
|
||||
return submitted.VariableValue ?? string.Empty;
|
||||
|
||||
return OnboardingContractSnapshotService.ResolveValue(
|
||||
definition,
|
||||
null,
|
||||
emptyDynamicValues,
|
||||
company,
|
||||
previewTask,
|
||||
true)
|
||||
?? string.Empty;
|
||||
},
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
var source = await _fileService.Download(
|
||||
new BaseIdInput { Id = version.SourceDocxFileId })
|
||||
?? throw Oops.Bah("无法读取合同源文件");
|
||||
await using var sourceStream = source.FileStream;
|
||||
using var sourceBytes = new MemoryStream();
|
||||
await sourceStream.CopyToAsync(sourceBytes);
|
||||
|
||||
return new OnboardingContractPreviewOutput
|
||||
{
|
||||
FileBytes = DocxTemplateProcessor.Render(
|
||||
sourceBytes.ToArray(),
|
||||
values),
|
||||
FileName = BuildPreviewFileName(contractTemplate.TemplateName)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据锁定的模板版本和任务变量快照生成已替换变量的合同 DOCX。
|
||||
/// </summary>
|
||||
@@ -86,4 +257,30 @@ public class OnboardingContractDocumentService : IOnboardingContractDocumentServ
|
||||
await _db.Updateable(contract).ExecuteCommandAsync();
|
||||
return fileId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断变量是否允许人事在发起任务前填写。
|
||||
/// </summary>
|
||||
private static bool IsHrEditableDefinition(ObTemplateVariable definition)
|
||||
{
|
||||
return definition.HrEditable
|
||||
&& (definition.VariableType == "hr"
|
||||
|| definition.VariableType == ContractVariableType.Contract
|
||||
|| definition.VariableType == ContractVariableType.Company
|
||||
|| definition.VariableCode.StartsWith(
|
||||
"hr.",
|
||||
StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成兼容 Windows 和 Linux 的合同预览下载文件名。
|
||||
/// </summary>
|
||||
private static string BuildPreviewFileName(string contractName)
|
||||
{
|
||||
var invalidChars = global::System.IO.Path.GetInvalidFileNameChars();
|
||||
var safeName = new string((contractName ?? "合同")
|
||||
.Select(character => invalidChars.Contains(character) ? '_' : character)
|
||||
.ToArray());
|
||||
return $"{safeName}_人事预览_{DateTime.Now:yyyyMMddHHmmss}.docx";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user