174 lines
7.1 KiB
C#
174 lines
7.1 KiB
C#
namespace SimpleAdmin.Application;
|
|
|
|
/// <summary>
|
|
/// 员工手机端公开入口,仅凭一次性任务链接访问入职资料。
|
|
/// </summary>
|
|
public class OnboardingPublicTaskService : IOnboardingPublicTaskService
|
|
{
|
|
private readonly SqlSugarScope _db;
|
|
private readonly IOnboardingContractSnapshotService _snapshotService;
|
|
private readonly IOnboardingContractDocumentService _contractDocumentService;
|
|
|
|
public OnboardingPublicTaskService(
|
|
IOnboardingContractSnapshotService snapshotService,
|
|
IOnboardingContractDocumentService contractDocumentService)
|
|
{
|
|
_db = DbContext.DB;
|
|
_snapshotService = snapshotService;
|
|
_contractDocumentService = contractDocumentService;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 通过有效 Token 获取任务创建时冻结的材料、合同和新版入职登记表信息。
|
|
/// </summary>
|
|
public async Task<OnboardingTaskPublicDetailOutput> Detail(OnboardingTaskPublicAccessInput input)
|
|
{
|
|
var link = await GetActiveLink(input.Token);
|
|
var task = await _db.Queryable<ObOnboardingTask>().InSingleAsync(link.TaskId)
|
|
?? throw Oops.Bah("入职任务不存在");
|
|
|
|
link.AccessCount++;
|
|
link.LastAccessedAt = DateTime.Now;
|
|
await _db.Updateable(link).ExecuteCommandAsync();
|
|
var materialRequirements = await _db.Queryable<ObTaskMaterialRequirement>()
|
|
.Where(item => item.TaskId == task.Id)
|
|
.OrderBy(item => item.SortCode)
|
|
.ToListAsync();
|
|
|
|
var contracts = await _db.Queryable<ObTaskContract>()
|
|
.Where(item => item.TaskId == task.Id)
|
|
.ToListAsync();
|
|
var templateVersionIds = contracts
|
|
.Select(item => item.TemplateVersionId)
|
|
.Distinct()
|
|
.ToList();
|
|
var contractVariables = new List<OnboardingPublicContractVariableOutput>();
|
|
if (templateVersionIds.Count > 0)
|
|
{
|
|
var employeeVariables = await _db.Queryable<ObTemplateVariable>()
|
|
.Where(item => templateVersionIds.Contains(item.TemplateVersionId)
|
|
&& item.VariableType == ContractVariableType.Employee)
|
|
.OrderBy(item => item.SortCode)
|
|
.ToListAsync();
|
|
contractVariables = employeeVariables.Select(item => new OnboardingPublicContractVariableOutput
|
|
{
|
|
VariableCode = item.VariableCode,
|
|
VariableName = item.VariableName,
|
|
VariableType = item.VariableType,
|
|
DataType = item.DataType,
|
|
DefaultValue = item.DefaultValue,
|
|
OptionsJson = item.OptionsJson,
|
|
Required = item.Required
|
|
}).ToList();
|
|
}
|
|
|
|
return new OnboardingTaskPublicDetailOutput
|
|
{
|
|
Task = task,
|
|
EmployeeInfo = await _db.Queryable<ObTaskEmployeeInfo>()
|
|
.FirstAsync(item => item.TaskId == task.Id),
|
|
Contracts = contracts,
|
|
DynamicValues = new List<ObTaskFormValue>(),
|
|
Materials = await _db.Queryable<ObTaskMaterial>()
|
|
.Where(item => item.TaskId == task.Id)
|
|
.ToListAsync(),
|
|
FormFields = new List<OnboardingPublicFormFieldOutput>(),
|
|
MaterialRequirements = materialRequirements.Select(requirement => new OnboardingPublicMaterialOutput
|
|
{
|
|
MaterialTypeId = requirement.MaterialTypeId,
|
|
MaterialName = requirement.MaterialName,
|
|
AllowedExtensions = requirement.AllowedExtensions,
|
|
MaxFileCount = requirement.MaxFileCount,
|
|
Required = requirement.Required
|
|
}).ToList(),
|
|
ContractVariables = contractVariables
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// 保存候选人的固定基础信息并刷新尚未确认的合同变量快照。
|
|
/// </summary>
|
|
public async Task SaveEmployeeInfo(OnboardingTaskPublicSaveInput input)
|
|
{
|
|
var link = await GetActiveLink(input.Token);
|
|
var task = await _db.Queryable<ObOnboardingTask>().InSingleAsync(link.TaskId)
|
|
?? throw Oops.Bah("入职任务不存在");
|
|
if (task.TaskStatus != OnboardingTaskStatus.PendingFill
|
|
&& task.TaskStatus != OnboardingTaskStatus.Rejected)
|
|
{
|
|
throw Oops.Bah("当前任务不可编辑");
|
|
}
|
|
|
|
var old = await _db.Queryable<ObTaskEmployeeInfo>()
|
|
.FirstAsync(item => item.TaskId == task.Id);
|
|
var entity = input.Adapt<ObTaskEmployeeInfo>();
|
|
entity.TaskId = task.Id;
|
|
entity.IsDelete = false;
|
|
|
|
if (old == null)
|
|
{
|
|
entity.Id = global::SimpleAdmin.Core.Utils.CommonUtils.GetSingleId();
|
|
entity.Status = CommonStatusConst.ENABLE;
|
|
entity.CreateTime = DateTime.Now;
|
|
entity.CreateUserId = null;
|
|
entity.CreateUser = null;
|
|
await _db.Insertable(entity).ExecuteCommandAsync();
|
|
}
|
|
else
|
|
{
|
|
entity.Id = old.Id;
|
|
entity.Status = old.Status;
|
|
entity.CreateTime = old.CreateTime;
|
|
entity.CreateUserId = old.CreateUserId;
|
|
entity.CreateUser = old.CreateUser;
|
|
entity.ExtJson = old.ExtJson;
|
|
entity.IsDelete = old.IsDelete;
|
|
entity.UpdateTime = DateTime.Now;
|
|
entity.UpdateUserId = null;
|
|
entity.UpdateUser = null;
|
|
await _db.Updateable(entity).ExecuteCommandAsync();
|
|
}
|
|
|
|
await _snapshotService.Build(task.Id, entity, invalidateGeneratedPreview: true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 根据员工当前已填写信息生成合同预览,并返回已替换变量的 DOCX 文件 Id。
|
|
/// </summary>
|
|
public async Task<long> GetContractSourceFileId(OnboardingPublicContractSourceInput input)
|
|
{
|
|
var link = await GetActiveLink(input.Token);
|
|
var contract = await _db.Queryable<ObTaskContract>()
|
|
.FirstAsync(item => item.Id == input.TaskContractId && item.TaskId == link.TaskId)
|
|
?? throw Oops.Bah("合同不存在");
|
|
|
|
await _snapshotService.Build(link.TaskId);
|
|
var fileId = await _contractDocumentService.Generate(new OnboardingGenerateContractInput
|
|
{
|
|
TaskContractId = contract.Id
|
|
});
|
|
|
|
contract.ReadAt ??= DateTime.Now;
|
|
if (contract.ContractStatus == TaskContractStatus.PendingGenerate)
|
|
contract.ContractStatus = TaskContractStatus.PendingConfirm;
|
|
await _db.Updateable(contract).ExecuteCommandAsync();
|
|
return fileId;
|
|
}
|
|
|
|
private async Task<ObTaskLink> GetActiveLink(string token)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(token))
|
|
throw Oops.Bah("入职链接 Token 不能为空");
|
|
|
|
var hash = Convert.ToHexString(
|
|
global::System.Security.Cryptography.SHA256.HashData(
|
|
global::System.Text.Encoding.UTF8.GetBytes(token)));
|
|
var link = await _db.Queryable<ObTaskLink>().FirstAsync(item => item.TokenHash == hash)
|
|
?? throw Oops.Bah("链接不存在");
|
|
|
|
if (link.LinkStatus != OnboardingLinkStatus.Active || link.ExpiresAt <= DateTime.Now)
|
|
throw Oops.Bah("链接已失效");
|
|
|
|
return link;
|
|
}
|
|
} |