using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using NCC.Extend.Entitys.lq_attendance_record;
using NCC.Extend.Entitys.lq_attendance_summary;
using NCC.Extend.Entitys.lq_employee_store_assignment;
using NCC.Extend.Entitys.lq_hytk_jksyj;
using NCC.Extend.Entitys.lq_hytk_kjbsyj;
using NCC.Extend.Entitys.lq_jinsanjiao_user;
using NCC.Extend.Entitys.lq_kd_jksyj;
using NCC.Extend.Entitys.lq_kd_kjbsyj;
using NCC.Extend.Entitys.lq_person_times_record;
using NCC.Extend.Entitys.lq_salary_statistics;
using NCC.Extend.Entitys.lq_xh_hyhk;
using NCC.Extend.Entitys.lq_xh_jksyj;
using NCC.Extend.Entitys.lq_xh_kjbsyj;
using NCC.Extend.Entitys.lq_assistant_salary_statistics;
using NCC.Extend.Entitys.lq_business_unit_manager_salary_statistics;
using NCC.Extend.Entitys.lq_director_salary_statistics;
using NCC.Extend.Entitys.lq_major_project_director_salary_statistics;
using NCC.Extend.Entitys.lq_major_project_teacher_salary_statistics;
using NCC.Extend.Entitys.lq_store_manager_salary_statistics;
using NCC.Extend.Entitys.lq_tech_general_manager_salary_statistics;
using NCC.Extend.Entitys.lq_tech_teacher_salary_statistics;
using NCC.System.Entitys.Permission;
using SqlSugar;
namespace NCC.Extend
{
///
/// 统计自然月内「有业务事实」的员工(BASE_USER.F_Id),用于月中离职仍参与当月算薪、以及各模块复用名单口径。
///
public static class LqMonthlyEmployeeFactHelper
{
private const int KeyResolveChunkSize = 500;
///
/// 汇总指定年月中,在考勤/业绩/消耗/金三角/工资归档等任一来源出现过的用户主键(已解析为 BASE_USER.F_Id)。
/// jkszh/kjblszh 等与账号或主键混存的字段会按 Id 或 Account 匹配用户行(未软删)。
///
public static async Task> GetUserIdsWithMonthBusinessFactsAsync(
ISqlSugarClient db,
int year,
int month)
{
if (year < 1990 || year > 2100 || month < 1 || month > 12)
{
return new List();
}
var startDate = new DateTime(year, month, 1);
var endDate = startDate.AddMonths(1).AddDays(-1);
var monthStr = $"{year}{month:D2}";
var endOpen = endDate.AddDays(1);
var rawKeys = new HashSet(StringComparer.Ordinal);
void AddKey(string k)
{
if (!string.IsNullOrWhiteSpace(k))
{
rawKeys.Add(k.Trim());
}
}
// 与算薪扩大候选一致
foreach (var id in await LqSalaryUserSnapshotHelper.GetSalaryCandidateUserIdsAsync(db, startDate, endDate, year, month))
{
AddKey(id);
}
var attUserIds = await db.Queryable()
.Where(x => x.AttendanceDate >= startDate.Date && x.AttendanceDate <= endDate.Date && x.IsEffective == 1)
.Select(x => x.UserId)
.ToListAsync();
foreach (var id in attUserIds)
{
AddKey(id);
}
var personIds = await db.Queryable()
.Where(x => x.WorkMonth == monthStr && x.IsEffective == 1)
.Select(x => x.PersonId)
.ToListAsync();
foreach (var id in personIds)
{
AddKey(id);
}
var jsUserIds = await db.Queryable()
.Where(x => x.Month == monthStr && x.DeleteMark == 0)
.Select(x => x.UserId)
.ToListAsync();
foreach (var id in jsUserIds)
{
AddKey(id);
}
void AddJkszhBatch(List zhList)
{
foreach (var z in zhList)
{
AddKey(z);
}
}
AddJkszhBatch(await db.Queryable()
.Where(x => x.Yjsj >= startDate && x.Yjsj < endOpen && x.IsEffective == 1)
.Select(x => x.Jkszh)
.ToListAsync());
AddJkszhBatch(await db.Queryable()
.Where(x => x.Yjsj >= startDate && x.Yjsj < endOpen && x.IsEffective == 1)
.Select(x => x.Jkszh)
.ToListAsync());
AddJkszhBatch(await db.Queryable()
.Where(x => x.Tksj >= startDate && x.Tksj < endOpen && x.IsEffective == 1)
.Select(x => x.Jkszh)
.ToListAsync());
AddJkszhBatch(await db.Queryable()
.Where(x => x.Yjsj >= startDate && x.Yjsj < endOpen && x.IsEffective == 1)
.Select(x => x.Kjblszh)
.ToListAsync());
AddJkszhBatch(await db.Queryable(
(kj, hk) => kj.Glkdbh == hk.Id && hk.IsEffective == 1)
.Where((kj, hk) => kj.IsEffective == 1 && hk.Hksj >= startDate && hk.Hksj < endOpen)
.Select((kj, hk) => kj.Kjblszh)
.ToListAsync());
AddJkszhBatch(await db.Queryable()
.Where(x => x.Tksj >= startDate && x.Tksj < endOpen && x.IsEffective == 1)
.Select(x => x.Kjblszh)
.ToListAsync());
// 各岗位工资归档(已算过薪的月份仍应出现在「有事实」名单中,便于补算/核对)
AddJkszhBatch(await db.Queryable()
.Where(x => x.StatisticsMonth == monthStr)
.Select(x => x.EmployeeId)
.ToListAsync());
AddJkszhBatch(await db.Queryable()
.Where(x => x.StatisticsMonth == monthStr)
.Select(x => x.EmployeeId)
.ToListAsync());
AddJkszhBatch(await db.Queryable()
.Where(x => x.StatisticsMonth == monthStr)
.Select(x => x.EmployeeId)
.ToListAsync());
AddJkszhBatch(await db.Queryable()
.Where(x => x.StatisticsMonth == monthStr)
.Select(x => x.EmployeeId)
.ToListAsync());
AddJkszhBatch(await db.Queryable()
.Where(x => x.StatisticsMonth == monthStr)
.Select(x => x.EmployeeId)
.ToListAsync());
AddJkszhBatch(await db.Queryable()
.Where(x => x.StatisticsMonth == monthStr)
.Select(x => x.EmployeeId)
.ToListAsync());
AddJkszhBatch(await db.Queryable()
.Where(x => x.StatisticsMonth == monthStr)
.Select(x => x.EmployeeId)
.ToListAsync());
AddJkszhBatch(await db.Queryable()
.Where(x => x.StatisticsMonth == monthStr)
.Select(x => x.EmployeeId)
.ToListAsync());
AddJkszhBatch(await db.Queryable()
.Where(x => x.StatisticsMonth == monthStr)
.Select(x => x.EmployeeId)
.ToListAsync());
var resolved = await ResolveKeysToUserIdsAsync(db, rawKeys);
return resolved.ToList();
}
///
/// 将 jkszh/账号/主键等字符串解析为未软删用户的 F_Id。
///
public static async Task> ResolveKeysToUserIdsAsync(ISqlSugarClient db, IEnumerable rawKeys)
{
var set = new HashSet(StringComparer.Ordinal);
if (rawKeys == null)
{
return set;
}
var keys = rawKeys.Where(k => !string.IsNullOrWhiteSpace(k)).Select(k => k.Trim()).Distinct().ToList();
for (var i = 0; i < keys.Count; i += KeyResolveChunkSize)
{
var chunk = keys.Skip(i).Take(KeyResolveChunkSize).ToList();
var ids = await db.Queryable()
.Where(u => u.DeleteMark == null)
.Where(u => chunk.Contains(u.Id) || chunk.Contains(u.Account))
.Select(u => u.Id)
.ToListAsync();
foreach (var id in ids)
{
if (!string.IsNullOrEmpty(id))
{
set.Add(id);
}
}
}
return set;
}
}
}