154 lines
6.4 KiB
C#
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;
|
|
}
|
|
}
|