Files
OnboardXAdmin/SimpleAdmin.Application/Services/Onboarding/EmployeeContractSnapshot/OnboardingEmployeeContractSnapshotService.cs
T
2026-09-09 14:57:41 +08:00

154 lines
6.4 KiB
C#

using System.Globalization;
namespace SimpleAdmin.Application;
/// <summary>
/// 在正式员工建档时,将每份任务合同及其全部变量冻结为长期业务快照。
/// </summary>
public class OnboardingEmployeeContractSnapshotService : IOnboardingEmployeeContractSnapshotService
{
private readonly SqlSugarScope _db;
public OnboardingEmployeeContractSnapshotService()
{
_db = DbContext.DB;
}
/// <inheritdoc />
public async Task Build(long employeeId, long taskId)
{
var contracts = await _db.Queryable<ObTaskContract>()
.Where(item => item.TaskId == taskId)
.OrderBy(item => item.Id)
.ToListAsync();
if (contracts.Count == 0)
throw Oops.Bah("入职任务没有合同,无法生成员工合同快照");
var contractIds = contracts.Select(item => item.Id).ToList();
var allVariables = await _db.Queryable<ObTaskContractVariable>()
.Where(item => contractIds.Contains(item.TaskContractId))
.OrderBy(item => item.SortCode)
.OrderBy(item => item.Id)
.ToListAsync();
var now = DateTime.Now;
var snapshots = new List<ObEmployeeContractSnapshot>();
foreach (var contract in contracts)
{
var variables = allVariables
.Where(item => item.TaskContractId == contract.Id)
.OrderBy(item => item.SortCode)
.ThenBy(item => item.Id)
.ToList();
var valueMap = variables
.GroupBy(item => item.VariableCode, StringComparer.OrdinalIgnoreCase)
.ToDictionary(
group => group.Key,
group => group.Last().VariableValue,
StringComparer.OrdinalIgnoreCase);
var variableSnapshot = variables
.GroupBy(item => item.VariableCode, StringComparer.OrdinalIgnoreCase)
.ToDictionary(
group => group.Key,
group =>
{
// 历史任务若意外存在重复变量,以排序后的最后一条最终值为准,避免建档时报 500。
var item = group.Last();
return (object)new
{
variableName = item.VariableName,
variableType = item.VariableType,
dataType = item.DataType,
variableValue = item.VariableValue,
sourceType = item.SourceType,
isManualOverride = item.IsManualOverride,
sortCode = item.SortCode
};
},
StringComparer.OrdinalIgnoreCase);
snapshots.Add(new ObEmployeeContractSnapshot
{
Id = global::SimpleAdmin.Core.Utils.CommonUtils.GetSingleId(),
EmployeeId = employeeId,
TaskId = taskId,
TaskContractId = contract.Id,
TemplateId = contract.TemplateId,
TemplateVersionId = contract.TemplateVersionId,
ContractName = contract.ContractName,
ContractType = contract.ContractType,
ContractStartDate = ParseDate(GetValue(valueMap, "hr.ContractStartDate")),
ContractEndDate = ParseDate(GetValue(valueMap, "hr.ContractEndDate")),
ContractTerm = GetValue(valueMap, "hr.ContractTerm"),
ProbationStartDate = ParseDate(GetValue(valueMap, "hr.ProbationStartDate")),
ProbationEndDate = ParseDate(GetValue(valueMap, "hr.ProbationEndDate")),
ProbationTerm = GetValue(valueMap, "hr.ProbationTerm"),
ProbationSalary = ParseAmount(GetValue(valueMap, "hr.ProbationSalary")),
BaseSalary = ParseAmount(GetValue(valueMap, "hr.BaseSalary")),
PositionSalary = ParseAmount(GetValue(valueMap, "hr.PositionSalary")),
PerformanceAllowance = ParseAmount(GetValue(valueMap, "hr.PerformanceAllowance")),
AttendanceBonus = ParseAmount(GetValue(valueMap, "hr.AttendanceBonus")),
RegularSalary = ParseAmount(GetValue(valueMap, "hr.RegularSalary")),
WorkCity = GetValue(valueMap, "hr.WorkCity"),
PositionName = GetValue(valueMap, "hr.PositionName"),
EmployeeNo = GetValue(valueMap, "hr.EmployeeNo"),
VariablesJson = global::System.Text.Json.JsonSerializer.Serialize(variableSnapshot),
SnapshotVersion = 1,
SnapshotAt = now,
Status = CommonStatusConst.ENABLE,
CreateTime = now,
CreateUserId = UserManager.UserId,
CreateUser = UserManager.Name,
IsDelete = false
});
}
// Build 只在审核建档事务内执行;先删后建使异常重试保持幂等。
await _db.Deleteable<ObEmployeeContractSnapshot>()
.Where(item => item.TaskId == taskId)
.ExecuteCommandAsync();
await _db.Insertable(snapshots).ExecuteCommandAsync();
}
private static string GetValue(
IReadOnlyDictionary<string, string> valueMap,
string variableCode)
{
return valueMap.TryGetValue(variableCode, out var value) && !string.IsNullOrWhiteSpace(value)
? value.Trim()
: null;
}
private static DateTime? ParseDate(string value)
{
return DateTime.TryParse(value, out var date) ? date.Date : null;
}
private static decimal? ParseAmount(string value)
{
if (string.IsNullOrWhiteSpace(value))
return null;
var normalized = value
.Replace("¥", string.Empty)
.Replace("¥", string.Empty)
.Replace("元", string.Empty)
.Trim();
if (decimal.TryParse(
normalized,
NumberStyles.Number | NumberStyles.AllowCurrencySymbol,
CultureInfo.GetCultureInfo("zh-CN"),
out var amount)
|| decimal.TryParse(
normalized,
NumberStyles.Number,
CultureInfo.InvariantCulture,
out amount))
{
return amount;
}
return null;
}
}