namespace SimpleAdmin.Application; /// 合同模板主档案;具体 DOCX 文件、变量与适用范围均挂在此档案下。 public class OnboardingContractTemplateService : DbRepository, IOnboardingContractTemplateService { public async Task> Page(OnboardingContractTemplatePageInput input) { return await Context.Queryable() .WhereIF(!string.IsNullOrWhiteSpace(input.TemplateName), it => it.TemplateName.Contains(input.TemplateName) || it.TemplateCode.Contains(input.TemplateName)) .WhereIF(!string.IsNullOrWhiteSpace(input.ContractType), it => it.ContractType == input.ContractType) .WhereIF(!string.IsNullOrWhiteSpace(input.Status), it => it.Status == input.Status) .OrderByIF(!string.IsNullOrWhiteSpace(input.SortField), $"{input.SortField} {input.SortOrder}") .OrderBy(it => it.TemplateName) .ToPagedListAsync(input.PageNum, input.PageSize); } public async Task Detail(BaseIdInput input) => await GetByIdAsync(input.Id) ?? throw Oops.Bah("合同模板不存在"); public async Task Add(OnboardingContractTemplateAddInput input) { await EnsureCodeUnique(input.TemplateCode, 0); await InsertAsync(input.Adapt()); } public async Task Edit(OnboardingContractTemplateEditInput input) { await Detail(new BaseIdInput { Id = input.Id }); await EnsureCodeUnique(input.TemplateCode, input.Id); await UpdateAsync(input.Adapt()); } public async Task Delete(BaseIdListInput input) { if (input.Ids.Count == 0) return; if (await Context.Queryable().AnyAsync(it => input.Ids.Contains(it.TemplateId))) throw Oops.Bah("模板已有版本,不能删除"); if (await Context.Queryable().AnyAsync(it => input.Ids.Contains(it.TemplateId))) throw Oops.Bah("模板已配置适用范围,不能删除"); if (await Context.Queryable().AnyAsync(it => input.Ids.Contains(it.TemplateId))) throw Oops.Bah("模板已生成入职合同,不能删除"); await DeleteByIdsAsync(input.Ids.Cast().ToArray()); } private async Task EnsureCodeUnique(string code, long id) { if (await Context.Queryable().AnyAsync(it => it.TemplateCode == code && it.Id != id)) throw Oops.Bah("模板编码已存在"); } public async Task> VersionPage(OnboardingContractVersionPageInput input) { return await Context.Queryable().Where(it => it.TemplateId == input.TemplateId) .WhereIF(!string.IsNullOrWhiteSpace(input.VersionStatus), it => it.VersionStatus == input.VersionStatus) .OrderByDescending(it => it.CreateTime).ToPagedListAsync(input.PageNum, input.PageSize); } public async Task AddVersion(OnboardingContractVersionAddInput input) { await Detail(new BaseIdInput { Id = input.TemplateId }); var file = await Context.Queryable().InSingleAsync(input.SourceDocxFileId) ?? throw Oops.Bah("DOCX源文件不存在"); if (!string.Equals(file.Suffix, "docx", StringComparison.OrdinalIgnoreCase)) throw Oops.Bah("合同模板仅支持DOCX文件"); if (await Context.Queryable().AnyAsync(it => it.TemplateId == input.TemplateId && it.VersionNo == input.VersionNo)) throw Oops.Bah("该模板版本号已存在"); await Context.Insertable(input.Adapt()).ExecuteCommandAsync(); } public async Task SetVersionStatus(OnboardingContractVersionStatusInput input) { if (input.VersionStatus != ContractTemplateVersionStatus.Enabled && input.VersionStatus != ContractTemplateVersionStatus.Disabled) throw Oops.Bah("版本状态仅支持启用或停用"); var version = await Context.Queryable().InSingleAsync(input.Id) ?? throw Oops.Bah("模板版本不存在"); if (input.VersionStatus == ContractTemplateVersionStatus.Enabled && !await Context.Queryable().AnyAsync(it => it.TemplateVersionId == input.Id)) throw Oops.Bah("请先配置模板变量后再启用"); version.VersionStatus = input.VersionStatus; await Context.Updateable(version).ExecuteCommandAsync(); } public async Task> VariablePage(OnboardingTemplateVariablePageInput input) { return await Context.Queryable().Where(it => it.TemplateVersionId == input.TemplateVersionId) .OrderBy(it => it.SortCode).OrderBy(it => it.VariableCode).ToPagedListAsync(input.PageNum, input.PageSize); } public async Task AddVariable(OnboardingTemplateVariableAddInput input) { await EnsureVersionDraft(input.TemplateVersionId); await EnsureVariableUnique(input.TemplateVersionId, input.VariableCode, 0); await Context.Insertable(input.Adapt()).ExecuteCommandAsync(); } public async Task EditVariable(OnboardingTemplateVariableEditInput input) { var variable = await Context.Queryable().InSingleAsync(input.Id) ?? throw Oops.Bah("模板变量不存在"); if (variable.TemplateVersionId != input.TemplateVersionId) throw Oops.Bah("不允许变更变量所属版本"); await EnsureVersionDraft(input.TemplateVersionId); await EnsureVariableUnique(input.TemplateVersionId, input.VariableCode, input.Id); await Context.Updateable(input.Adapt()).ExecuteCommandAsync(); } public async Task DeleteVariable(BaseIdListInput input) { if (input.Ids.Count == 0) return; var versionIds = await Context.Queryable().Where(it => input.Ids.Contains(it.Id)).Select(it => it.TemplateVersionId).ToListAsync(); foreach (var versionId in versionIds.Distinct()) await EnsureVersionDraft(versionId); await Context.Deleteable().In(input.Ids).ExecuteCommandAsync(); } private async Task EnsureVersionDraft(long versionId) { var version = await Context.Queryable().InSingleAsync(versionId) ?? throw Oops.Bah("模板版本不存在"); if (version.VersionStatus != ContractTemplateVersionStatus.Draft) throw Oops.Bah("只有草稿版本可维护变量"); } private async Task EnsureVariableUnique(long versionId, string code, long id) { if (await Context.Queryable().AnyAsync(it => it.TemplateVersionId == versionId && it.VariableCode == code && it.Id != id)) throw Oops.Bah("该版本变量编码已存在"); } public async Task> ScopePage(OnboardingContractScopePageInput input) { return await Context.Queryable() .WhereIF(input.CompanyId.HasValue, it => it.CompanyId == input.CompanyId.Value) .WhereIF(input.PositionId.HasValue, it => it.PositionId == input.PositionId.Value) .WhereIF(input.TemplateId.HasValue, it => it.TemplateId == input.TemplateId.Value) .OrderBy(it => it.SortCode).ToPagedListAsync(input.PageNum, input.PageSize); } public async Task AddScope(OnboardingContractScopeAddInput input) { await EnsureScopeValid(input.CompanyId, input.PositionId, input.TemplateId, input.TemplateVersionId); await EnsureScopeUnique(input.CompanyId, input.PositionId, input.TemplateVersionId, 0); await Context.Insertable(input.Adapt()).ExecuteCommandAsync(); } public async Task EditScope(OnboardingContractScopeEditInput input) { if (!await Context.Queryable().AnyAsync(it => it.Id == input.Id)) throw Oops.Bah("合同适用范围不存在"); await EnsureScopeValid(input.CompanyId, input.PositionId, input.TemplateId, input.TemplateVersionId); await EnsureScopeUnique(input.CompanyId, input.PositionId, input.TemplateVersionId, input.Id); await Context.Updateable(input.Adapt()).ExecuteCommandAsync(); } public async Task DeleteScope(BaseIdListInput input) { if (input.Ids.Count > 0) await Context.Deleteable().In(input.Ids).ExecuteCommandAsync(); } private async Task EnsureScopeValid(long companyId, long? positionId, long templateId, long versionId) { if (!await Context.Queryable().AnyAsync(it => it.Id == companyId && it.Status == "enable")) throw Oops.Bah("所属公司不存在或未启用"); if (positionId.HasValue && !await Context.Queryable().AnyAsync(it => it.Id == positionId.Value && it.CompanyId == companyId && it.Status == "enable")) throw Oops.Bah("岗位不存在、未启用或不属于该公司"); var version = await Context.Queryable().InSingleAsync(versionId) ?? throw Oops.Bah("合同版本不存在"); if (version.TemplateId != templateId || version.VersionStatus != ContractTemplateVersionStatus.Enabled) throw Oops.Bah("只能配置该模板的已启用合同版本"); } private async Task EnsureScopeUnique(long companyId, long? positionId, long versionId, long id) { if (await Context.Queryable().AnyAsync(it => it.CompanyId == companyId && it.PositionId == positionId && it.TemplateVersionId == versionId && it.Id != id)) throw Oops.Bah("该公司、岗位和合同版本的适用范围已存在"); }}