新增员工统计
This commit is contained in:
@@ -46,6 +46,58 @@ public class OnboardingEmployeePageInput : BasePageInput
|
|||||||
/// 社保状态。
|
/// 社保状态。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string SocialInsuranceStatus { get; set; }
|
public string SocialInsuranceStatus { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 合同即将到期筛选(30天内到期或已到期)。
|
||||||
|
/// </summary>
|
||||||
|
public bool? ContractExpiringSoon { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 正式员工档案分页数据及当前查询条件下的维度统计。
|
||||||
|
/// </summary>
|
||||||
|
public class OnboardingEmployeePageOutput : SqlSugarPagedList<ObEmployee>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 不受快捷维度筛选影响的员工维度统计。
|
||||||
|
/// </summary>
|
||||||
|
public OnboardingEmployeeStatisticsOutput Statistics { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 正式员工档案维度统计。
|
||||||
|
/// </summary>
|
||||||
|
public class OnboardingEmployeeStatisticsOutput
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 在册总数。
|
||||||
|
/// </summary>
|
||||||
|
public int Total { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 正式员工数量。
|
||||||
|
/// </summary>
|
||||||
|
public int FullTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 兼职员工数量。
|
||||||
|
/// </summary>
|
||||||
|
public int PartTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 试用期待转正数量。
|
||||||
|
/// </summary>
|
||||||
|
public int Probation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 社保已缴纳数量。
|
||||||
|
/// </summary>
|
||||||
|
public int SocialPurchased { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 合同即将到期数量(30天内到期或已到期)。
|
||||||
|
/// </summary>
|
||||||
|
public int ExpiringContract { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ namespace SimpleAdmin.Application;
|
|||||||
public interface IOnboardingEmployeeService : ITransient
|
public interface IOnboardingEmployeeService : ITransient
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 分页查询审核通过后生成的正式员工档案。
|
/// 分页查询审核通过后生成的正式员工档案及维度统计。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task<SqlSugarPagedList<ObEmployee>> Page(OnboardingEmployeePageInput input);
|
Task<OnboardingEmployeePageOutput> Page(OnboardingEmployeePageInput input);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 按当前列表筛选条件导出员工明细。
|
/// 按当前列表筛选条件导出员工明细。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -20,18 +20,30 @@ public class OnboardingEmployeeService : IOnboardingEmployeeService
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 分页查询审核通过后生成的员工档案。
|
/// 分页查询审核通过后生成的员工档案及维度统计。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task<SqlSugarPagedList<ObEmployee>> Page(OnboardingEmployeePageInput input)
|
public async Task<OnboardingEmployeePageOutput> Page(OnboardingEmployeePageInput input)
|
||||||
{
|
{
|
||||||
var result = await BuildEmployeeQuery(input)
|
var list = await BuildEmployeeQuery(input)
|
||||||
.OrderByDescending(item => item.CreateTime)
|
.OrderByDescending(item => item.CreateTime)
|
||||||
.ToPagedListAsync(input.PageNum, input.PageSize);
|
.ToPagedListAsync(input.PageNum, input.PageSize);
|
||||||
|
|
||||||
if (result.List != null && result.List.Any())
|
if (list.List != null && list.List.Any())
|
||||||
await FillEmployeeMetadata(result.List);
|
await FillEmployeeMetadata(list.List);
|
||||||
|
|
||||||
return result;
|
var stats = await CalculateStatistics(input);
|
||||||
|
|
||||||
|
return new OnboardingEmployeePageOutput
|
||||||
|
{
|
||||||
|
PageNum = list.PageNum,
|
||||||
|
PageSize = list.PageSize,
|
||||||
|
Total = list.Total,
|
||||||
|
Pages = list.Pages,
|
||||||
|
List = list.List,
|
||||||
|
HasPrevPages = list.HasPrevPages,
|
||||||
|
HasNextPages = list.HasNextPages,
|
||||||
|
Statistics = stats
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -633,21 +645,31 @@ public class OnboardingEmployeeService : IOnboardingEmployeeService
|
|||||||
await FillMissingEntryDates(employeeList);
|
await FillMissingEntryDates(employeeList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造基础员工查询(包含组织、岗位和姓名/手机号搜索),供列表、统计和导出复用。
|
||||||
|
/// </summary>
|
||||||
|
private ISugarQueryable<ObEmployee> BuildBaseEmployeeQuery(OnboardingEmployeePageInput input)
|
||||||
|
{
|
||||||
|
return _db.Queryable<ObEmployee>()
|
||||||
|
.WhereIF(
|
||||||
|
!string.IsNullOrWhiteSpace(input?.EmployeeName),
|
||||||
|
item => item.EmployeeName.Contains(input.EmployeeName)
|
||||||
|
|| item.IdCardNumber.Contains(input.EmployeeName))
|
||||||
|
.WhereIF(!string.IsNullOrWhiteSpace(input?.Phone), item => item.Phone.Contains(input.Phone))
|
||||||
|
.WhereIF(input?.CompanyId.HasValue == true, item => item.CompanyId == input.CompanyId.Value)
|
||||||
|
.WhereIF(input?.DepartmentId.HasValue == true, item => item.DepartmentId == input.DepartmentId.Value)
|
||||||
|
.WhereIF(input?.PositionId.HasValue == true, item => item.PositionId == input.PositionId.Value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造列表和导出共用的员工筛选,保证页面看到的范围与导出范围一致。
|
/// 构造列表和导出共用的员工筛选,保证页面看到的范围与导出范围一致。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private ISugarQueryable<ObEmployee> BuildEmployeeQuery(OnboardingEmployeePageInput input)
|
private ISugarQueryable<ObEmployee> BuildEmployeeQuery(OnboardingEmployeePageInput input)
|
||||||
{
|
{
|
||||||
input ??= new OnboardingEmployeePageInput();
|
input ??= new OnboardingEmployeePageInput();
|
||||||
return _db.Queryable<ObEmployee>()
|
var expiringThreshold = DateTime.Today.AddDays(30).Date.AddDays(1).AddSeconds(-1);
|
||||||
.WhereIF(
|
|
||||||
!string.IsNullOrWhiteSpace(input.EmployeeName),
|
return BuildBaseEmployeeQuery(input)
|
||||||
item => item.EmployeeName.Contains(input.EmployeeName)
|
|
||||||
|| item.IdCardNumber.Contains(input.EmployeeName))
|
|
||||||
.WhereIF(!string.IsNullOrWhiteSpace(input.Phone), item => item.Phone.Contains(input.Phone))
|
|
||||||
.WhereIF(input.CompanyId.HasValue, item => item.CompanyId == input.CompanyId.Value)
|
|
||||||
.WhereIF(input.DepartmentId.HasValue, item => item.DepartmentId == input.DepartmentId.Value)
|
|
||||||
.WhereIF(input.PositionId.HasValue, item => item.PositionId == input.PositionId.Value)
|
|
||||||
.WhereIF(
|
.WhereIF(
|
||||||
!string.IsNullOrWhiteSpace(input.EmploymentType),
|
!string.IsNullOrWhiteSpace(input.EmploymentType),
|
||||||
item => item.EmploymentType == input.EmploymentType)
|
item => item.EmploymentType == input.EmploymentType)
|
||||||
@@ -656,7 +678,50 @@ public class OnboardingEmployeeService : IOnboardingEmployeeService
|
|||||||
item => item.RegularizationStatus == input.RegularizationStatus)
|
item => item.RegularizationStatus == input.RegularizationStatus)
|
||||||
.WhereIF(
|
.WhereIF(
|
||||||
!string.IsNullOrWhiteSpace(input.SocialInsuranceStatus),
|
!string.IsNullOrWhiteSpace(input.SocialInsuranceStatus),
|
||||||
item => item.SocialInsuranceStatus == input.SocialInsuranceStatus);
|
item => item.SocialInsuranceStatus == input.SocialInsuranceStatus)
|
||||||
|
.WhereIF(
|
||||||
|
input.ContractExpiringSoon == true,
|
||||||
|
item => item.ContractEndDate != null && item.ContractEndDate <= expiringThreshold);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 计算员工档案的各项维度统计数量,受组织及关键字联动,但不受快捷状态筛选影响。
|
||||||
|
/// </summary>
|
||||||
|
private async Task<OnboardingEmployeeStatisticsOutput> CalculateStatistics(OnboardingEmployeePageInput input)
|
||||||
|
{
|
||||||
|
var expiringThreshold = DateTime.Today.AddDays(30).Date.AddDays(1).AddSeconds(-1);
|
||||||
|
|
||||||
|
var total = await BuildBaseEmployeeQuery(input).CountAsync();
|
||||||
|
if (total == 0)
|
||||||
|
{
|
||||||
|
return new OnboardingEmployeeStatisticsOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
var fullTime = await BuildBaseEmployeeQuery(input)
|
||||||
|
.Where(item => item.EmploymentType == EmployeeEmploymentType.FullTime)
|
||||||
|
.CountAsync();
|
||||||
|
var partTime = await BuildBaseEmployeeQuery(input)
|
||||||
|
.Where(item => item.EmploymentType == EmployeeEmploymentType.PartTime)
|
||||||
|
.CountAsync();
|
||||||
|
var probation = await BuildBaseEmployeeQuery(input)
|
||||||
|
.Where(item => item.RegularizationStatus == EmployeeRegularizationStatus.Probation)
|
||||||
|
.CountAsync();
|
||||||
|
var socialPurchased = await BuildBaseEmployeeQuery(input)
|
||||||
|
.Where(item => item.SocialInsuranceStatus == EmployeeSocialInsuranceStatus.Purchased)
|
||||||
|
.CountAsync();
|
||||||
|
var expiringContract = await BuildBaseEmployeeQuery(input)
|
||||||
|
.Where(item => item.ContractEndDate != null && item.ContractEndDate <= expiringThreshold)
|
||||||
|
.CountAsync();
|
||||||
|
|
||||||
|
return new OnboardingEmployeeStatisticsOutput
|
||||||
|
{
|
||||||
|
Total = total,
|
||||||
|
FullTime = fullTime,
|
||||||
|
PartTime = partTime,
|
||||||
|
Probation = probation,
|
||||||
|
SocialPurchased = socialPurchased,
|
||||||
|
ExpiringContract = expiringContract
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WriteEmployeeSheet(
|
private static void WriteEmployeeSheet(
|
||||||
|
|||||||
Reference in New Issue
Block a user