111
This commit is contained in:
+10
@@ -0,0 +1,10 @@
|
||||
namespace SimpleAdmin.Application;
|
||||
|
||||
/// <summary>
|
||||
/// 定义正式员工合同快照归档能力。
|
||||
/// </summary>
|
||||
public interface IOnboardingEmployeeContractSnapshotService : ITransient
|
||||
{
|
||||
/// <summary>冻结一名员工来源任务中的全部合同和变量。</summary>
|
||||
Task Build(long employeeId, long taskId);
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user