LqEmployeeRosterService.cs
7.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using NCC.Common.Core.Manager;
using NCC.Common.Filter;
using NCC.Common.Util;
using NCC.Dependency;
using NCC.DynamicApiController;
using NCC.Extend.Entitys.Dto.LqEmployeeRoster;
using NCC.Extend.Entitys.lq_attendance_summary;
using NCC.Extend.Entitys.lq_mdxx;
using NCC.FriendlyException;
using NCC.System.Entitys.Model.Permission.User;
using NCC.System.Entitys.Permission;
using SqlSugar;
namespace NCC.Extend
{
/// <summary>
/// 员工花名册(按年月、组织机构查询在职人员)
/// </summary>
[ApiDescriptionSettings(Tag = "绿纤员工花名册", Name = "LqEmployeeRoster", Order = 203)]
[Route("api/Extend/LqEmployeeRoster")]
public class LqEmployeeRosterService : IDynamicApiController, ITransient
{
private readonly ISqlSugarClient _db;
private readonly IUserManager _userManager;
/// <summary>
/// 初始化员工花名册服务
/// </summary>
public LqEmployeeRosterService(ISqlSugarClient db, IUserManager userManager)
{
_db = db;
_userManager = userManager;
}
/// <summary>
/// 分页查询指定年月在职员工花名册。口径:优先取该月有效考勤汇总(F_IsEffective=1)中员工状态为在职(F_EmployeeStatus=1);
/// 无汇总且查询月不晚于当前月时:入职不晚于该月末,且(无离职日或离职日≥该月 1 日)。含义:离职日在上月或更早则本月不出现;离职日在本月或之后则本月仍出现(含当月中途离职);查下月时因「离职日≥下月1日」不成立,上月已离职者不会出现在下月(不依赖 F_IsOnJob)。
/// 有有效汇总且员工状态非在职则不列入。未来月仅认汇总。
/// </summary>
/// <param name="year">年</param>
/// <param name="month">月(1-12)</param>
/// <param name="organizeId">组织机构节点 ID,含其下级;不传则按数据权限范围内全部</param>
/// <param name="keyword">账号或姓名模糊</param>
/// <param name="page">分页参数</param>
[HttpGet("")]
public async Task<dynamic> GetList(
[FromQuery] int year,
[FromQuery] int month,
[FromQuery] string organizeId,
[FromQuery] string keyword,
[FromQuery] PageInputBase page)
{
if (year < 1990 || year > 2100 || month < 1 || month > 12)
{
throw NCCException.Oh("year/month 参数不合法");
}
page ??= new PageInputBase();
var user = await _userManager.GetUserInfo();
var orgFilter = await ResolveOrganizeFilterAsync(user, organizeId);
var now = DateTime.Now;
var isFutureMonth = year > now.Year || (year == now.Year && month > now.Month);
var monthEnd = new DateTime(year, month, DateTime.DaysInMonth(year, month), 23, 59, 59);
var firstDayOfMonth = new DateTime(year, month, 1);
var kw = string.IsNullOrWhiteSpace(keyword) ? null : keyword.Trim();
var query = _db.Queryable<UserEntity, OrganizeEntity, LqAttendanceSummaryEntity, LqMdxxEntity>(
(u, o, s, m) => new JoinQueryInfos(
JoinType.Left, o.Id == SqlFunc.ToString(u.OrganizeId),
JoinType.Left,
s.UserId == u.Id && s.Year == year && s.Month == month && s.IsEffective == 1,
JoinType.Left, m.Id == u.Mdid))
.Where((u, o, s, m) => u.DeleteMark == null)
.Where((u, o, s, m) =>
(!SqlFunc.IsNullOrEmpty(s.Id) && s.EmployeeStatus == 1)
|| (!isFutureMonth
&& SqlFunc.IsNullOrEmpty(s.Id)
&& u.EntryDate != null
&& u.EntryDate <= monthEnd
&& (u.LeaveDate == null || u.LeaveDate >= firstDayOfMonth)))
.WhereIF(kw != null, (u, o, s, m) => u.Account.Contains(kw) || u.RealName.Contains(kw))
.Select((u, o, s, m) => new LqEmployeeRosterListOutput
{
id = u.Id,
account = u.Account,
realName = u.RealName,
department = o.FullName,
organizeId = u.OrganizeId,
mdid = u.Mdid,
mdName = m.Dm,
gw = u.Gw,
zw = u.Zw,
enabledMark = u.EnabledMark,
isOnJob = u.IsOnJob,
summaryEmployeeStatus = SqlFunc.IIF(SqlFunc.IsNullOrEmpty(s.Id), (int?)null, s.EmployeeStatus),
workDays = SqlFunc.IIF(SqlFunc.IsNullOrEmpty(s.Id), (decimal?)null, s.WorkDays),
mobilePhone = u.MobilePhone,
entryDate = u.EntryDate
})
.MergeTable();
if (orgFilter != null)
{
query = query.Where(x => orgFilter.Contains(x.organizeId));
}
query = query
.OrderBy(x => x.organizeId)
.OrderBy(x => x.realName);
var paged = await query.ToPagedListAsync(page.currentPage, page.pageSize);
return PageResult<LqEmployeeRosterListOutput>.SqlSugarPageResult(paged);
}
/// <summary>
/// 管理员:未选组织时不限制;已选组织则限制为该节点及下级。非管理员:限制在数据权限机构(含下级)内,并可与所选组织求交。
/// </summary>
private async Task<List<string>> ResolveOrganizeFilterAsync(UserInfo user, string organizeId)
{
var allOrgs = await _db.Queryable<OrganizeEntity>()
.Where(x => x.DeleteMark == null)
.ToListAsync();
List<string> subtree = null;
if (!string.IsNullOrWhiteSpace(organizeId))
{
subtree = allOrgs
.TreeChildNode(organizeId.Trim(), t => t.Id, t => t.ParentId)
.Select(x => x.Id)
.ToList();
}
if (user.isAdministrator)
{
return subtree;
}
var allowed = new HashSet<string>();
foreach (var scope in user.dataScope ?? new List<UserDataScope>())
{
if (!scope.Add && !scope.Edit && !scope.Delete)
{
continue;
}
if (string.IsNullOrEmpty(scope.organizeId))
{
continue;
}
foreach (var id in allOrgs.TreeChildNode(scope.organizeId, t => t.Id, t => t.ParentId)
.Select(x => x.Id))
{
allowed.Add(id);
}
}
if (allowed.Count == 0)
{
return new List<string> { "__no_scope__" };
}
if (subtree != null && subtree.Count > 0)
{
var sel = subtree.ToHashSet();
allowed.IntersectWith(sel);
if (allowed.Count == 0)
{
return new List<string> { "__no_scope__" };
}
}
return allowed.ToList();
}
}
}