Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
attendance-performance-platform
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
赵啸非
attendance-performance-platform
Commits
c0c01b1a
Commit
c0c01b1a
authored
Aug 01, 2023
by
赵啸非
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修改固定班次考勤
parent
5e32ade9
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
687 additions
and
39 deletions
+687
-39
attendance-performance-manager-ui/admin/src/views/attendance/record/hik/list.vue
...manager-ui/admin/src/views/attendance/record/hik/list.vue
+1
-1
attendance-performance-manager/src/main/java/com/mortals/xhx/base/login/web/LoginForm.java
...c/main/java/com/mortals/xhx/base/login/web/LoginForm.java
+11
-0
attendance-performance-manager/src/main/java/com/mortals/xhx/base/system/user/service/impl/UserServiceImpl.java
...ls/xhx/base/system/user/service/impl/UserServiceImpl.java
+15
-0
attendance-performance-manager/src/main/java/com/mortals/xhx/busiz/h5/req/ReviewSaveReq.java
...main/java/com/mortals/xhx/busiz/h5/req/ReviewSaveReq.java
+2
-0
attendance-performance-manager/src/main/java/com/mortals/xhx/busiz/h5/web/ApiLoginController.java
...java/com/mortals/xhx/busiz/h5/web/ApiLoginController.java
+6
-0
attendance-performance-manager/src/main/java/com/mortals/xhx/busiz/h5/web/DingTalkLoginController.java
...com/mortals/xhx/busiz/h5/web/DingTalkLoginController.java
+1
-1
attendance-performance-manager/src/main/java/com/mortals/xhx/busiz/h5/web/InspectApiController.java
...va/com/mortals/xhx/busiz/h5/web/InspectApiController.java
+6
-4
attendance-performance-manager/src/main/java/com/mortals/xhx/busiz/h5/web/PerformApiController.java
...va/com/mortals/xhx/busiz/h5/web/PerformApiController.java
+64
-7
attendance-performance-manager/src/main/java/com/mortals/xhx/module/attendance/service/impl/AttendanceRecordHikServiceImpl.java
...tendance/service/impl/AttendanceRecordHikServiceImpl.java
+172
-7
attendance-performance-manager/src/main/java/com/mortals/xhx/module/attendance/service/work/AttendanceWorkAbstract.java
...odule/attendance/service/work/AttendanceWorkAbstract.java
+11
-3
attendance-performance-manager/src/main/java/com/mortals/xhx/module/attendance/service/work/CommonData.java
...ortals/xhx/module/attendance/service/work/CommonData.java
+8
-0
attendance-performance-manager/src/main/java/com/mortals/xhx/module/attendance/service/work/FixWorkAttendance.java
...xhx/module/attendance/service/work/FixWorkAttendance.java
+74
-3
attendance-performance-manager/src/main/java/com/mortals/xhx/module/attendance/service/work/FixWorkOtherAttendance.java
...odule/attendance/service/work/FixWorkOtherAttendance.java
+308
-0
attendance-performance-manager/src/main/java/com/mortals/xhx/module/attendance/service/work/FreedomWorkAttendance.java
...module/attendance/service/work/FreedomWorkAttendance.java
+7
-12
attendance-performance-manager/src/main/resources/config/mybatis-sqlmap-config.xml
...nager/src/main/resources/config/mybatis-sqlmap-config.xml
+1
-1
No files found.
attendance-performance-manager-ui/admin/src/views/attendance/record/hik/list.vue
View file @
c0c01b1a
...
...
@@ -134,7 +134,7 @@
}
this
.
$post
(
'
/attendance/record/hik/addAttendanceRecord
'
,{...
params
}).
then
(
res
=>
{
if
(
res
.
code
==
1
){
this
.
$message
.
success
(
"
生成打卡记录成功!
"
)
}
})
},
...
...
attendance-performance-manager/src/main/java/com/mortals/xhx/base/login/web/LoginForm.java
View file @
c0c01b1a
...
...
@@ -10,6 +10,9 @@ public class LoginForm extends BaseForm {
private
String
securityCode
;
private
String
dingCode
;
public
String
getLoginName
()
{
return
loginName
;
}
...
...
@@ -35,6 +38,14 @@ public class LoginForm extends BaseForm {
this
.
securityCode
=
securityCode
;
}
public
String
getDingCode
()
{
return
dingCode
;
}
public
void
setDingCode
(
String
dingCode
)
{
this
.
dingCode
=
dingCode
;
}
@Override
public
String
toString
()
{
return
"loginName:"
+
this
.
loginName
+
" password:"
+
this
.
password
+
" securityCode:"
+
this
.
securityCode
;
...
...
attendance-performance-manager/src/main/java/com/mortals/xhx/base/system/user/service/impl/UserServiceImpl.java
View file @
c0c01b1a
...
...
@@ -14,6 +14,7 @@ import com.mortals.framework.exception.AppException;
import
com.mortals.framework.model.Context
;
import
com.mortals.framework.model.PageInfo
;
import
com.mortals.framework.model.Result
;
import
com.mortals.framework.service.ICacheService
;
import
com.mortals.framework.service.IUser
;
import
com.mortals.framework.service.impl.AbstractCRUDServiceImpl
;
import
com.mortals.framework.util.SecurityUtil
;
...
...
@@ -56,6 +57,9 @@ public class UserServiceImpl extends AbstractCRUDServiceImpl<UserDao, UserEntity
private
ResourceService
resourceService
;
@Autowired
private
RoleUserService
roleUserService
;
@Autowired
private
ICacheService
cacheService
;
@Override
public
void
doHandlerUser
(
UserEntity
entity
)
throws
AppException
{
if
(
StringUtils
.
isNotEmpty
(
entity
.
getLoginPwd
()))
{
...
...
@@ -97,6 +101,17 @@ public class UserServiceImpl extends AbstractCRUDServiceImpl<UserDao, UserEntity
}
}
@Override
protected
void
updateAfter
(
UserEntity
entity
,
Context
context
)
throws
AppException
{
//更新用户后 删除当前用户的token
Set
<
String
>
keys
=
cacheService
.
scan
(
SysConstains
.
LOGIN_TOKEN_KEY
+
entity
.
getId
());
if
(!
ObjectUtils
.
isEmpty
(
keys
))
{
for
(
String
key
:
keys
)
{
cacheService
.
del
(
key
);
}
}
}
@Override
protected
void
saveAfter
(
UserEntity
entity
,
Context
context
)
throws
AppException
{
//更新角色
...
...
attendance-performance-manager/src/main/java/com/mortals/xhx/busiz/h5/req/ReviewSaveReq.java
View file @
c0c01b1a
...
...
@@ -33,4 +33,6 @@ public class ReviewSaveReq extends BaseReq {
*/
private
String
windowNum
;
private
String
filePaths
;
}
attendance-performance-manager/src/main/java/com/mortals/xhx/busiz/h5/web/ApiLoginController.java
View file @
c0c01b1a
...
...
@@ -93,6 +93,12 @@ public class ApiLoginController extends BaseJsonBodyController {
userEntity
.
setExpireTime
(
DateUtils
.
addCurrDate
(
3
).
getTime
());
String
token
=
authTokenService
.
createToken
(
userEntity
);
data
.
put
(
"token"
,
token
);
if
(!
ObjectUtils
.
isEmpty
(
loginForm
.
getDingCode
()))
{
//更新绑定钉钉
userEntity
.
setDingUserId
(
loginForm
.
getDingCode
());
userService
.
getUserDao
().
update
(
userEntity
);
}
ret
.
put
(
KEY_RESULT_DATA
,
data
);
ret
.
put
(
KEY_RESULT_CODE
,
VALUE_RESULT_SUCCESS
);
ret
.
put
(
KEY_RESULT_MSG
,
"用户登录系统成功!"
);
...
...
attendance-performance-manager/src/main/java/com/mortals/xhx/busiz/h5/web/DingTalkLoginController.java
View file @
c0c01b1a
...
...
@@ -113,7 +113,7 @@ public class DingTalkLoginController extends BaseCRUDJsonBodyMappingController<U
userEntity
=
userService
.
selectOne
(
userQuery
);
if
(
ObjectUtils
.
isEmpty
(
userEntity
))
{
ret
.
put
(
"openId"
,
personRest
.
getData
());
throw
new
AppException
(
REGISTER_AUTH_FAIL
,
"不存在当前匹配的钉钉关联用户
2
!"
);
throw
new
AppException
(
REGISTER_AUTH_FAIL
,
"不存在当前匹配的钉钉关联用户!"
);
}
data
.
put
(
"id"
,
userEntity
.
getId
());
...
...
attendance-performance-manager/src/main/java/com/mortals/xhx/busiz/h5/web/InspectApiController.java
View file @
c0c01b1a
...
...
@@ -427,7 +427,7 @@ public class InspectApiController extends AbstractBaseController<PerformReq> {
BeanUtils
.
copyProperties
(
req
,
recordEntity
);
// recordEntity.setStaffId(staffEntity.getId());
recordEntity
.
setStaffName
(
staffEntity
.
getName
());
recordEntity
.
setWorkNum
(
staffEntity
.
getWorkNum
());
recordEntity
.
setDeductTime
(
new
Date
());
StaffEntity
custStaff
=
getStaff
(
context
.
getUser
().
getCustomerId
().
toString
());
recordEntity
.
setDeductPerson
(
custStaff
==
null
?
"系统管理员"
:
custStaff
.
getName
());
...
...
@@ -459,7 +459,7 @@ public class InspectApiController extends AbstractBaseController<PerformReq> {
BeanUtils
.
copyProperties
(
req
,
recordEntity
);
// recordEntity.setStaffId(staffEntity.getId());
recordEntity
.
setStaffName
(
staffEntity
.
getName
());
recordEntity
.
setWorkNum
(
staffEntity
.
getWorkNum
());
recordEntity
.
setDeptId
(
staffEntity
.
getDeptId
());
recordEntity
.
setDeptName
(
staffEntity
.
getDeptName
());
...
...
@@ -493,7 +493,7 @@ public class InspectApiController extends AbstractBaseController<PerformReq> {
BeanUtils
.
copyProperties
(
req
,
recordEntity
);
// recordEntity.setStaffId(staffEntity.getId());
recordEntity
.
setStaffName
(
staffEntity
.
getName
());
recordEntity
.
setWorkNum
(
staffEntity
.
getWorkNum
());
recordEntity
.
setDeductTime
(
new
Date
());
StaffEntity
custStaff
=
getStaff
(
context
.
getUser
().
getCustomerId
().
toString
());
recordEntity
.
setDeductPerson
(
custStaff
==
null
?
"系统管理员"
:
custStaff
.
getName
());
...
...
@@ -526,6 +526,8 @@ public class InspectApiController extends AbstractBaseController<PerformReq> {
//recordEntity.setStaffId(staffEntity.getId());
recordEntity
.
setStaffName
(
staffEntity
.
getName
());
recordEntity
.
setWorkNum
(
staffEntity
.
getWorkNum
());
recordEntity
.
setDeductTime
(
new
Date
());
StaffEntity
custStaff
=
getStaff
(
context
.
getUser
().
getCustomerId
().
toString
());
recordEntity
.
setDeductPerson
(
custStaff
==
null
?
"系统管理员"
:
custStaff
.
getName
());
...
...
@@ -557,7 +559,7 @@ public class InspectApiController extends AbstractBaseController<PerformReq> {
BeanUtils
.
copyProperties
(
req
,
recordEntity
);
//recordEntity.setStaffId(staffEntity.getId());
recordEntity
.
setStaffName
(
staffEntity
.
getName
());
recordEntity
.
setWorkNum
(
staffEntity
.
getWorkNum
());
recordEntity
.
setDeductTime
(
new
Date
());
StaffEntity
custStaff
=
getStaff
(
context
.
getUser
().
getCustomerId
().
toString
());
recordEntity
.
setDeductPerson
(
custStaff
==
null
?
"系统管理员"
:
custStaff
.
getName
());
...
...
attendance-performance-manager/src/main/java/com/mortals/xhx/busiz/h5/web/PerformApiController.java
View file @
c0c01b1a
...
...
@@ -188,7 +188,12 @@ public class PerformApiController extends AbstractBaseController<PerformReq> {
List
<
PerformInfo
>
collect
=
allCheckRecord
.
stream
().
map
(
item
->
{
PerformInfo
performInfo
=
new
PerformInfo
();
BeanUtils
.
copyProperties
(
item
,
performInfo
,
BeanUtil
.
getNullPropertyNames
(
item
));
PerformAttendAppealEntity
entity
=
appealService
.
selectOne
(
new
PerformAttendAppealQuery
().
checkRecordId
(
item
.
getId
()).
performType
(
item
.
getPerformType
()));
PerformAttendAppealQuery
appealQuery
=
new
PerformAttendAppealQuery
();
appealQuery
.
setCheckRecordId
(
item
.
getId
());
appealQuery
.
setPerformType
(
item
.
getPerformType
());
appealQuery
.
setOrderColList
(
Arrays
.
asList
(
new
OrderCol
(
"appealResult"
,
OrderCol
.
DESCENDING
)));
PerformAttendAppealEntity
entity
=
appealService
.
selectOne
(
appealQuery
);
updateAppealResult
(
performInfo
,
entity
);
return
performInfo
;
}).
collect
(
Collectors
.
toList
());
...
...
@@ -212,7 +217,12 @@ public class PerformApiController extends AbstractBaseController<PerformReq> {
BeanUtils
.
copyProperties
(
item
,
performInfo
,
BeanUtil
.
getNullPropertyNames
(
item
));
performInfo
.
setPerformType
(
PerformTypeEnum
.
考勤绩效
.
getValue
());
//判断是否存在申诉
PerformAttendAppealEntity
entity
=
appealService
.
selectOne
(
new
PerformAttendAppealQuery
().
checkRecordId
(
item
.
getId
()).
performType
(
performInfo
.
getPerformType
()));
PerformAttendAppealQuery
appealQuery
=
new
PerformAttendAppealQuery
();
appealQuery
.
setCheckRecordId
(
item
.
getId
());
appealQuery
.
setPerformType
(
performInfo
.
getPerformType
());
appealQuery
.
setOrderColList
(
Arrays
.
asList
(
new
OrderCol
(
"appealResult"
,
OrderCol
.
DESCENDING
)));
PerformAttendAppealEntity
entity
=
appealService
.
selectOne
(
appealQuery
);
//PerformAttendAppealEntity entity = appealService.selectOne(new PerformAttendAppealQuery().checkRecordId(item.getId()).performType(performInfo.getPerformType()));
updateAppealResult
(
performInfo
,
entity
);
return
performInfo
;
}).
collect
(
Collectors
.
toList
());
...
...
@@ -235,7 +245,12 @@ public class PerformApiController extends AbstractBaseController<PerformReq> {
BeanUtils
.
copyProperties
(
item
,
performInfo
,
BeanUtil
.
getNullPropertyNames
(
item
));
performInfo
.
setPerformType
(
PerformTypeEnum
.
评价差评绩效
.
getValue
());
//判断是否存在申诉
PerformAttendAppealEntity
entity
=
appealService
.
selectOne
(
new
PerformAttendAppealQuery
().
checkRecordId
(
item
.
getId
()).
performType
(
performInfo
.
getPerformType
()));
PerformAttendAppealQuery
appealQuery
=
new
PerformAttendAppealQuery
();
appealQuery
.
setCheckRecordId
(
item
.
getId
());
appealQuery
.
setPerformType
(
performInfo
.
getPerformType
());
appealQuery
.
setOrderColList
(
Arrays
.
asList
(
new
OrderCol
(
"appealResult"
,
OrderCol
.
DESCENDING
)));
PerformAttendAppealEntity
entity
=
appealService
.
selectOne
(
appealQuery
);
//PerformAttendAppealEntity entity = appealService.selectOne(new PerformAttendAppealQuery().checkRecordId(item.getId()).performType(performInfo.getPerformType()));
updateAppealResult
(
performInfo
,
entity
);
return
performInfo
;
...
...
@@ -259,7 +274,12 @@ public class PerformApiController extends AbstractBaseController<PerformReq> {
performInfo
.
setPerformType
(
PerformTypeEnum
.
评价投诉绩效
.
getValue
());
//判断是否存在申诉
PerformAttendAppealEntity
entity
=
appealService
.
selectOne
(
new
PerformAttendAppealQuery
().
checkRecordId
(
item
.
getId
()).
performType
(
performInfo
.
getPerformType
()));
PerformAttendAppealQuery
appealQuery
=
new
PerformAttendAppealQuery
();
appealQuery
.
setCheckRecordId
(
item
.
getId
());
appealQuery
.
setPerformType
(
performInfo
.
getPerformType
());
appealQuery
.
setOrderColList
(
Arrays
.
asList
(
new
OrderCol
(
"appealResult"
,
OrderCol
.
DESCENDING
)));
PerformAttendAppealEntity
entity
=
appealService
.
selectOne
(
appealQuery
);
//PerformAttendAppealEntity entity = appealService.selectOne(new PerformAttendAppealQuery().checkRecordId(item.getId()).performType(performInfo.getPerformType()));
updateAppealResult
(
performInfo
,
entity
);
return
performInfo
;
}).
collect
(
Collectors
.
toList
());
...
...
@@ -281,7 +301,12 @@ public class PerformApiController extends AbstractBaseController<PerformReq> {
BeanUtils
.
copyProperties
(
item
,
performInfo
,
BeanUtil
.
getNullPropertyNames
(
item
));
performInfo
.
setPerformType
(
PerformTypeEnum
.
办件绩效
.
getValue
());
//判断是否存在申诉
PerformAttendAppealEntity
entity
=
appealService
.
selectOne
(
new
PerformAttendAppealQuery
().
checkRecordId
(
item
.
getId
()).
performType
(
performInfo
.
getPerformType
()));
PerformAttendAppealQuery
appealQuery
=
new
PerformAttendAppealQuery
();
appealQuery
.
setCheckRecordId
(
item
.
getId
());
appealQuery
.
setPerformType
(
performInfo
.
getPerformType
());
appealQuery
.
setOrderColList
(
Arrays
.
asList
(
new
OrderCol
(
"appealResult"
,
OrderCol
.
DESCENDING
)));
PerformAttendAppealEntity
entity
=
appealService
.
selectOne
(
appealQuery
);
// PerformAttendAppealEntity entity = appealService.selectOne(new PerformAttendAppealQuery().checkRecordId(item.getId()).performType(performInfo.getPerformType()));
updateAppealResult
(
performInfo
,
entity
);
return
performInfo
;
...
...
@@ -304,7 +329,12 @@ public class PerformApiController extends AbstractBaseController<PerformReq> {
BeanUtils
.
copyProperties
(
item
,
performInfo
,
BeanUtil
.
getNullPropertyNames
(
item
));
performInfo
.
setPerformType
(
PerformTypeEnum
.
效能绩效
.
getValue
());
//判断是否存在申诉
PerformAttendAppealEntity
entity
=
appealService
.
selectOne
(
new
PerformAttendAppealQuery
().
checkRecordId
(
item
.
getId
()).
performType
(
performInfo
.
getPerformType
()));
PerformAttendAppealQuery
appealQuery
=
new
PerformAttendAppealQuery
();
appealQuery
.
setCheckRecordId
(
item
.
getId
());
appealQuery
.
setPerformType
(
performInfo
.
getPerformType
());
appealQuery
.
setOrderColList
(
Arrays
.
asList
(
new
OrderCol
(
"appealResult"
,
OrderCol
.
DESCENDING
)));
PerformAttendAppealEntity
entity
=
appealService
.
selectOne
(
appealQuery
);
// PerformAttendAppealEntity entity = appealService.selectOne(new PerformAttendAppealQuery().checkRecordId(item.getId()).performType(performInfo.getPerformType()));
updateAppealResult
(
performInfo
,
entity
);
return
performInfo
;
}).
collect
(
Collectors
.
toList
());
...
...
@@ -324,7 +354,12 @@ public class PerformApiController extends AbstractBaseController<PerformReq> {
BeanUtils
.
copyProperties
(
item
,
performInfo
,
BeanUtil
.
getNullPropertyNames
(
item
));
performInfo
.
setPerformType
(
PerformTypeEnum
.
其它绩效
.
getValue
());
//判断是否存在申诉
PerformAttendAppealEntity
entity
=
appealService
.
selectOne
(
new
PerformAttendAppealQuery
().
checkRecordId
(
item
.
getId
()).
performType
(
performInfo
.
getPerformType
()));
PerformAttendAppealQuery
appealQuery
=
new
PerformAttendAppealQuery
();
appealQuery
.
setCheckRecordId
(
item
.
getId
());
appealQuery
.
setPerformType
(
performInfo
.
getPerformType
());
appealQuery
.
setOrderColList
(
Arrays
.
asList
(
new
OrderCol
(
"appealResult"
,
OrderCol
.
DESCENDING
)));
PerformAttendAppealEntity
entity
=
appealService
.
selectOne
(
appealQuery
);
// PerformAttendAppealEntity entity = appealService.selectOne(new PerformAttendAppealQuery().checkRecordId(item.getId()).performType(performInfo.getPerformType()));
updateAppealResult
(
performInfo
,
entity
);
return
performInfo
;
...
...
@@ -370,6 +405,28 @@ public class PerformApiController extends AbstractBaseController<PerformReq> {
}
}
private
void
updateAppealResult
(
PerformInfo
performInfo
,
List
<
PerformAttendAppealEntity
>
list
)
{
if
(!
ObjectUtils
.
isEmpty
(
list
))
{
for
(
PerformAttendAppealEntity
entity
:
list
)
{
if
(
ObjectUtils
.
isEmpty
(
entity
.
getAppealResult
()))
{
performInfo
.
setAppealStatus
(
AppealStatusEnum
.
申诉中
.
getValue
());
}
else
{
if
(
AppealResultEnum
.
通过
.
getValue
()
==
entity
.
getAppealResult
())
{
performInfo
.
setAppealStatus
(
AppealStatusEnum
.
申诉通过
.
getValue
());
}
else
if
(
AppealResultEnum
.
不通过
.
getValue
()
==
entity
.
getAppealResult
())
{
performInfo
.
setAppealStatus
(
AppealStatusEnum
.
申诉拒绝
.
getValue
());
}
else
{
performInfo
.
setAppealStatus
(
AppealStatusEnum
.
申诉中
.
getValue
());
}
}
}
}
else
{
performInfo
.
setAppealStatus
(
AppealStatusEnum
.
未申诉
.
getValue
());
}
}
/**
* 详细
*/
...
...
attendance-performance-manager/src/main/java/com/mortals/xhx/module/attendance/service/impl/AttendanceRecordHikServiceImpl.java
View file @
c0c01b1a
...
...
@@ -68,21 +68,160 @@ public class AttendanceRecordHikServiceImpl extends AbstractCRUDServiceImpl<Atte
@Override
public
void
addAttendanceRecord
(
AttendanceRecordHikEntity
hikEntity
,
Context
context
)
throws
Exception
{
List
<
AttendanceRecordHikEntity
>
hikEntityList
=
new
ArrayList
<>();
addAttendanceRecordList
(
hikEntityList
,
context
);
addAttendance
Other
RecordList
(
hikEntityList
,
context
);
}
@Override
public
void
addAttendanceRecordByQuery
(
AttendanceRecordHikEntity
attendanceRecordHikQuery
,
Context
context
)
throws
Exception
{
List
<
AttendanceRecordHikEntity
>
hikEntityList
=
attendanceRecordHikService
.
find
(
attendanceRecordHikQuery
);
addAttendanceRecordList
(
hikEntityList
,
context
);
addAttendance
Other
RecordList
(
hikEntityList
,
context
);
}
public
void
addAttendanceOtherRecordList
(
List
<
AttendanceRecordHikEntity
>
hikEntityList
,
Context
context
)
throws
Exception
{
List
<
AttendanceRecordHikEntity
>
collect
=
hikEntityList
.
stream
().
sorted
(
Comparator
.
comparing
(
AttendanceRecordHikEntity:
:
getAttendanceDate
)).
collect
(
Collectors
.
toList
());
//另一种实现
Map
<
Long
,
List
<
AttendanceRecordHikEntity
>>
listMap
=
collect
.
stream
().
collect
(
Collectors
.
groupingBy
(
AttendanceRecordHikEntity:
:
getStaffId
));
for
(
Map
.
Entry
<
Long
,
List
<
AttendanceRecordHikEntity
>>
itemEntry
:
listMap
.
entrySet
())
{
//按人员
Long
staffId
=
itemEntry
.
getKey
();
List
<
AttendanceRecordHikEntity
>
recordHikEntityList
=
itemEntry
.
getValue
();
Map
<
String
,
List
<
AttendanceRecordHikEntity
>>
dateRecordMap
=
recordHikEntityList
.
stream
().
collect
(
Collectors
.
groupingBy
(
hikEntity
->
DateUtil
.
formatDate
(
hikEntity
.
getAttendanceDate
())));
for
(
Map
.
Entry
<
String
,
List
<
AttendanceRecordHikEntity
>>
dateEntry
:
dateRecordMap
.
entrySet
())
{
//按每日
String
dateStr
=
dateEntry
.
getKey
();
List
<
AttendanceRecordHikEntity
>
recordHikEntities
=
dateEntry
.
getValue
();
if
(
ObjectUtils
.
isEmpty
(
recordHikEntities
))
continue
;
AttendanceRecordHikEntity
item
=
recordHikEntities
.
get
(
0
);
AttendanceRecordEntity
attendanceRecordEntity
=
new
AttendanceRecordEntity
();
attendanceRecordEntity
.
initAttrValue
();
attendanceRecordEntity
.
setStaffId
(
item
.
getStaffId
());
attendanceRecordEntity
.
setStaffName
(
item
.
getStaffName
());
attendanceRecordEntity
.
setDeptId
(
item
.
getDeptId
());
attendanceRecordEntity
.
setDeptName
(
item
.
getDeptName
());
attendanceRecordEntity
.
setPositionId
(
item
.
getPositionId
());
attendanceRecordEntity
.
setPositionName
(
item
.
getPositionName
());
attendanceRecordEntity
.
setWorkNum
(
item
.
getWorkNum
());
attendanceRecordEntity
.
setAttendanceDate
(
item
.
getAttendanceDate
());
attendanceRecordEntity
.
setCreateTime
(
item
.
getAttendanceDate
());
attendanceRecordEntity
.
setCreateUserId
(
this
.
getContextUserId
(
context
));
StaffEntity
staffEntity
=
staffService
.
getExtCache
(
staffId
.
toString
());
if
(
ObjectUtils
.
isEmpty
(
staffEntity
))
{
log
.
info
(
"staffEntity is null ,staffId:{}"
,
staffId
);
continue
;
}
//通过员工id查询考勤组人员信息
List
<
AttendanceGroupStaffEntity
>
attendanceGroupStaffEntities
=
attendanceGroupStaffService
.
find
(
new
AttendanceGroupStaffQuery
().
staffId
(
staffId
));
List
<
AttendanceRecordDetailEntity
>
detailEntityList
=
new
ArrayList
<>();
if
(!
ObjectUtils
.
isEmpty
(
attendanceGroupStaffEntities
)
&&
attendanceGroupStaffEntities
.
size
()
==
1
)
{
//checkAttendGroupByOne(attendanceRecordEntity, detailEntityList, attendanceDate, attendanceGroupStaffEntities.get(0), context);
//查询考勤组
AttendanceGroupEntity
attendanceGroupEntity
=
attendanceGroupService
.
get
(
attendanceGroupStaffEntities
.
get
(
0
).
getGroupId
(),
context
);
attendanceRecordEntity
.
setAttendanceGroupId
(
attendanceGroupEntity
==
null
?
0L
:
attendanceGroupEntity
.
getId
());
attendanceRecordEntity
.
setAttendanceGroupName
(
attendanceGroupEntity
==
null
?
""
:
attendanceGroupEntity
.
getGroupName
());
//查询考勤组详细信息获取班次 todo 默认固定班次 还有自由 与排班制
AttendanceWorkAbstract
workAbstract
=
AttendanceWorkAbstract
.
newType
(
attendanceGroupEntity
.
getType
());
CommonData
commonData
=
new
CommonData
();
commonData
.
setContext
(
context
);
commonData
.
setAttendanceGroupEntity
(
attendanceGroupEntity
);
commonData
.
setAttendanceRecordEntity
(
attendanceRecordEntity
);
commonData
.
setDetailEntityList
(
detailEntityList
);
commonData
.
setStaffId
(
attendanceRecordEntity
.
getStaffId
());
commonData
.
setDateStr
(
dateStr
);
workAbstract
.
doHandleWork
(
commonData
);
}
//如果考勤人员信息list长度大于1 则该考勤人员有多个考勤组.
if
(
StringUtils
.
isNotNull
(
attendanceGroupStaffEntities
)
&&
attendanceGroupStaffEntities
.
size
()
>
1
)
{
for
(
AttendanceGroupStaffEntity
groupStaffEntity
:
attendanceGroupStaffEntities
)
{
//多考勤组 todo 暂时和单一覆盖
//checkAttendGroupByOne(attendanceRecordEntity, detailEntityList, attendanceDate, groupStaffEntity, context);
//查询考勤组
AttendanceGroupEntity
attendanceGroupEntity
=
attendanceGroupService
.
get
(
groupStaffEntity
.
getGroupId
(),
context
);
attendanceRecordEntity
.
setAttendanceGroupId
(
attendanceGroupEntity
==
null
?
0L
:
attendanceGroupEntity
.
getId
());
attendanceRecordEntity
.
setAttendanceGroupName
(
attendanceGroupEntity
==
null
?
""
:
attendanceGroupEntity
.
getGroupName
());
//查询考勤组详细信息获取班次 todo 默认固定班次 还有自由 与排班制
AttendanceWorkAbstract
workAbstract
=
AttendanceWorkAbstract
.
newType
(
attendanceGroupEntity
.
getType
());
CommonData
commonData
=
new
CommonData
();
commonData
.
setContext
(
context
);
commonData
.
setAttendanceGroupEntity
(
attendanceGroupEntity
);
commonData
.
setAttendanceRecordEntity
(
attendanceRecordEntity
);
commonData
.
setDetailEntityList
(
detailEntityList
);
commonData
.
setStaffId
(
attendanceRecordEntity
.
getStaffId
());
commonData
.
setDateStr
(
dateStr
);
workAbstract
.
doHandleWork
(
commonData
);
}
}
if
(!
ObjectUtils
.
isEmpty
(
detailEntityList
))
{
attendanceRecordEntity
.
setAttendanceRecordDetailList
(
detailEntityList
);
//判断签到 只要存在一次正常打卡详细记录 就判断签到
for
(
AttendanceRecordDetailEntity
detailEntity
:
detailEntityList
)
{
if
(
GoWorkResultEnum
.
正常
.
getValue
()
==
detailEntity
.
getGoWorkResult
()
||
GoWorkResultEnum
.
迟到
.
getValue
()
==
detailEntity
.
getOffWorkResult
())
{
attendanceRecordEntity
.
setSignInResult
(
YesNoEnum
.
YES
.
getValue
());
break
;
}
}
for
(
AttendanceRecordDetailEntity
detailEntity
:
detailEntityList
)
{
if
(
OffWorkResultEnum
.
正常
.
getValue
()
==
detailEntity
.
getOffWorkResult
()
||
OffWorkResultEnum
.
早退
.
getValue
()
==
detailEntity
.
getOffWorkResult
())
{
attendanceRecordEntity
.
setSignOutResult
(
YesNoEnum
.
YES
.
getValue
());
break
;
}
}
for
(
AttendanceRecordDetailEntity
detailEntity
:
detailEntityList
)
{
if
(
OffWorkResultEnum
.
缺卡
.
getValue
()
==
detailEntity
.
getOffWorkResult
())
{
attendanceRecordEntity
.
setPunchResult
(
YesNoEnum
.
NO
.
getValue
());
break
;
}
if
(
OffWorkResultEnum
.
缺卡
.
getValue
()
==
detailEntity
.
getOffWorkResult
())
{
attendanceRecordEntity
.
setPunchResult
(
YesNoEnum
.
NO
.
getValue
());
break
;
}
}
if
(
YesNoEnum
.
YES
.
getValue
()
==
attendanceRecordEntity
.
getSignInResult
()
&&
YesNoEnum
.
YES
.
getValue
()
==
attendanceRecordEntity
.
getSignOutResult
())
{
attendanceRecordEntity
.
setPunchResult
(
YesNoEnum
.
YES
.
getValue
());
}
attendanceRecordEntity
.
setAttendType
(
"现场打卡"
);
//判断是否存在记录 如果存在 则更新 维度 staffId attendanceDate shiftsId attendanceGroupId
AttendanceRecordQuery
query
=
new
AttendanceRecordQuery
();
query
.
setStaffId
(
attendanceRecordEntity
.
getStaffId
());
query
.
setShiftsId
(
attendanceRecordEntity
.
getShiftsId
());
query
.
setAttendanceGroupId
(
attendanceRecordEntity
.
getAttendanceGroupId
());
query
.
setAttendanceDate
(
attendanceRecordEntity
.
getAttendanceDate
());
AttendanceRecordEntity
recordEntity
=
attendanceRecordService
.
selectOne
(
query
);
if
(!
ObjectUtils
.
isEmpty
(
recordEntity
))
{
attendanceRecordEntity
.
setId
(
recordEntity
.
getId
());
attendanceRecordEntity
.
setUpdateTime
(
new
Date
());
attendanceRecordEntity
.
setUpdateUserId
(
this
.
getContextUserId
(
context
));
attendanceRecordService
.
update
(
attendanceRecordEntity
,
context
);
}
else
{
attendanceRecordService
.
save
(
attendanceRecordEntity
,
context
);
}
}
}
}
}
public
void
addAttendanceRecordList
(
List
<
AttendanceRecordHikEntity
>
hikEntityList
,
Context
context
)
throws
Exception
{
//对考勤数据根据考勤时间进行排序
List
<
AttendanceRecordHikEntity
>
collect
=
hikEntityList
.
stream
().
sorted
(
Comparator
.
comparing
(
AttendanceRecordHikEntity:
:
getAttendanceDate
)).
collect
(
Collectors
.
toList
());
//根据工号对考勤数据进行分组
Map
<
String
,
List
<
AttendanceRecordHikEntity
>>
listMap
=
collect
.
stream
().
collect
(
Collectors
.
groupingBy
(
AttendanceRecordHikEntity:
:
getWorkNum
));
//Map<String, Map<String, List<AttendanceRecordHikEntity>>> groupMap = collect.stream().collect(Collectors.groupingBy(AttendanceRecordHikEntity::getWorkNum, Collectors.groupingBy(x -> com.mortals.framework.util.DateUtils.getDateTimeStr(x.getAttendanceDate(), "yyyy-MM-dd"))));
for
(
Map
.
Entry
<
String
,
List
<
AttendanceRecordHikEntity
>>
itemEntry
:
listMap
.
entrySet
())
{
String
workNum
=
itemEntry
.
getKey
();
List
<
AttendanceRecordHikEntity
>
recordHikEntityList
=
itemEntry
.
getValue
();
...
...
@@ -92,10 +231,10 @@ public class AttendanceRecordHikServiceImpl extends AbstractCRUDServiceImpl<Atte
for
(
Map
.
Entry
<
String
,
List
<
AttendanceRecordHikEntity
>>
dateEntry
:
dateRecordMap
.
entrySet
())
{
String
dateStr
=
dateEntry
.
getKey
();
List
<
AttendanceRecordHikEntity
>
attendanceRecordHikEntities
=
dateEntry
.
getValue
();
//对相同工号的人员进行遍历判断考勤规则
AttendanceRecordEntity
attendanceRecordEntity
=
new
AttendanceRecordEntity
();
attendanceRecordEntity
.
initAttrValue
();
List
<
AttendanceRecordDetailEntity
>
detailEntityList
=
new
ArrayList
<>();
//分日期 遍历考勤记录 考勤记录一天只生成一条 详细多条
for
(
AttendanceRecordHikEntity
item
:
attendanceRecordHikEntities
)
{
//对主表的对象进行赋值
attendanceRecordEntity
.
setStaffId
(
item
.
getStaffId
());
...
...
@@ -119,14 +258,40 @@ public class AttendanceRecordHikServiceImpl extends AbstractCRUDServiceImpl<Atte
//通过员工id查询考勤组人员信息
List
<
AttendanceGroupStaffEntity
>
attendanceGroupStaffEntities
=
attendanceGroupStaffService
.
find
(
new
AttendanceGroupStaffQuery
().
staffId
(
staffEntity
.
getId
()));
//查询该考勤人员,如果查出来的考勤人员信息list长度为1 则该考勤人员只有一个考勤组
if
(!
ObjectUtils
.
isEmpty
(
attendanceGroupStaffEntities
)
&&
attendanceGroupStaffEntities
.
size
()
==
1
)
checkAttendGroupByOne
(
attendanceRecordEntity
,
detailEntityList
,
attendanceDate
,
attendanceGroupStaffEntities
.
get
(
0
),
context
);
if
(!
ObjectUtils
.
isEmpty
(
attendanceGroupStaffEntities
)
&&
attendanceGroupStaffEntities
.
size
()
==
1
)
{
//checkAttendGroupByOne(attendanceRecordEntity, detailEntityList, attendanceDate, attendanceGroupStaffEntities.get(0), context);
//查询考勤组
AttendanceGroupEntity
attendanceGroupEntity
=
attendanceGroupService
.
get
(
attendanceGroupStaffEntities
.
get
(
0
).
getGroupId
(),
context
);
attendanceRecordEntity
.
setAttendanceGroupId
(
attendanceGroupEntity
==
null
?
0L
:
attendanceGroupEntity
.
getId
());
attendanceRecordEntity
.
setAttendanceGroupName
(
attendanceGroupEntity
==
null
?
""
:
attendanceGroupEntity
.
getGroupName
());
//查询考勤组详细信息获取班次 todo 默认固定班次 还有自由 与排班制
AttendanceWorkAbstract
workAbstract
=
AttendanceWorkAbstract
.
newType
(
attendanceGroupEntity
.
getType
());
CommonData
commonData
=
new
CommonData
();
commonData
.
setAttendanceGroupEntity
(
attendanceGroupEntity
);
commonData
.
setAttendanceDate
(
attendanceDate
);
commonData
.
setDetailEntityList
(
detailEntityList
);
commonData
.
setStaffId
(
attendanceRecordEntity
.
getStaffId
());
workAbstract
.
doHandleWork
(
commonData
);
}
//如果考勤人员信息list长度大于1 则该考勤人员有多个考勤组.
if
(
StringUtils
.
isNotNull
(
attendanceGroupStaffEntities
)
&&
attendanceGroupStaffEntities
.
size
()
>
1
)
{
for
(
AttendanceGroupStaffEntity
groupStaffEntity
:
attendanceGroupStaffEntities
)
{
//多考勤组 todo 暂时和单一覆盖
checkAttendGroupByOne
(
attendanceRecordEntity
,
detailEntityList
,
attendanceDate
,
groupStaffEntity
,
context
);
//checkAttendGroupByOne(attendanceRecordEntity, detailEntityList, attendanceDate, groupStaffEntity, context);
//查询考勤组
AttendanceGroupEntity
attendanceGroupEntity
=
attendanceGroupService
.
get
(
groupStaffEntity
.
getGroupId
(),
context
);
attendanceRecordEntity
.
setAttendanceGroupId
(
attendanceGroupEntity
==
null
?
0L
:
attendanceGroupEntity
.
getId
());
attendanceRecordEntity
.
setAttendanceGroupName
(
attendanceGroupEntity
==
null
?
""
:
attendanceGroupEntity
.
getGroupName
());
//查询考勤组详细信息获取班次 todo 默认固定班次 还有自由 与排班制
AttendanceWorkAbstract
workAbstract
=
AttendanceWorkAbstract
.
newType
(
attendanceGroupEntity
.
getType
());
CommonData
commonData
=
new
CommonData
();
commonData
.
setAttendanceGroupEntity
(
attendanceGroupEntity
);
commonData
.
setAttendanceDate
(
attendanceDate
);
commonData
.
setDetailEntityList
(
detailEntityList
);
commonData
.
setStaffId
(
attendanceRecordEntity
.
getStaffId
());
workAbstract
.
doHandleWork
(
commonData
);
}
}
}
...
...
attendance-performance-manager/src/main/java/com/mortals/xhx/module/attendance/service/work/AttendanceWorkAbstract.java
View file @
c0c01b1a
...
...
@@ -2,10 +2,15 @@ package com.mortals.xhx.module.attendance.service.work;
import
cn.hutool.core.date.DateUtil
;
import
com.mortals.framework.exception.AppException
;
import
com.mortals.xhx.common.code.TypeEnum
;
import
com.mortals.xhx.module.attendance.model.AttendanceGroupFixedworkEntity
;
import
com.mortals.framework.model.Context
;
import
com.mortals.xhx.common.code.*
;
import
com.mortals.xhx.module.attendance.model.*
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.util.ObjectUtils
;
import
java.util.ArrayList
;
import
java.util.Date
;
import
java.util.List
;
/**
* 工作排班抽象类
...
...
@@ -26,7 +31,8 @@ public abstract class AttendanceWorkAbstract {
public
static
AttendanceWorkAbstract
newType
(
int
type
)
{
if
(
type
==
TypeEnum
.
固定班制
.
getValue
())
{
return
new
FixWorkAttendance
(
type
);
//return new FixWorkAttendance(type);
return
new
FixWorkOtherAttendance
(
type
);
}
else
if
(
type
==
TypeEnum
.
自由工时
.
getValue
())
{
return
new
FreedomWorkAttendance
(
type
);
}
...
...
@@ -115,6 +121,8 @@ public abstract class AttendanceWorkAbstract {
return
weekClassId
;
}
public
AttendanceWorkAbstract
(
int
type
)
{
this
.
type
=
type
;
}
...
...
attendance-performance-manager/src/main/java/com/mortals/xhx/module/attendance/service/work/CommonData.java
View file @
c0c01b1a
package
com.mortals.xhx.module.attendance.service.work
;
import
com.mortals.framework.model.Context
;
import
com.mortals.xhx.module.attendance.model.AttendanceGroupEntity
;
import
com.mortals.xhx.module.attendance.model.AttendanceRecordDetailEntity
;
import
com.mortals.xhx.module.attendance.model.AttendanceRecordEntity
;
import
lombok.Data
;
import
java.util.Date
;
...
...
@@ -24,6 +26,12 @@ public class CommonData {
private
Date
attendanceDate
;
private
Long
staffId
;
//当前日期
private
String
dateStr
;
//当天考勤信息
private
AttendanceRecordEntity
attendanceRecordEntity
;
private
Context
context
;
}
attendance-performance-manager/src/main/java/com/mortals/xhx/module/attendance/service/work/FixWorkAttendance.java
View file @
c0c01b1a
...
...
@@ -2,19 +2,24 @@ package com.mortals.xhx.module.attendance.service.work;
import
cn.hutool.core.date.DateUtil
;
import
com.mortals.xhx.common.code.GoWorkResultEnum
;
import
com.mortals.xhx.common.code.MustEnum
;
import
com.mortals.xhx.common.code.TypeEnum
;
import
com.mortals.xhx.module.attendance.model.*
;
import
com.mortals.xhx.module.attendance.service.AttendanceClassService
;
import
com.mortals.xhx.module.attendance.service.AttendanceGroupFixedworkService
;
import
com.mortals.xhx.module.attendance.service.AttendanceGroupFixedworkSpecialService
;
import
com.mortals.xhx.utils.SpringUtils
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.util.ObjectUtils
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
/**
* 固定班
*
* @author:
* @date: 2023/7/31 15:15
*/
...
...
@@ -26,11 +31,14 @@ public class FixWorkAttendance extends AttendanceWorkAbstract {
private
AttendanceClassService
attendanceClassService
;
private
AttendanceGroupFixedworkSpecialService
specialService
;
public
FixWorkAttendance
(
int
type
)
{
super
(
type
);
this
.
attendanceGroupFixedworkService
=
SpringUtils
.
getBean
(
AttendanceGroupFixedworkService
.
class
);
this
.
attendanceClassService
=
SpringUtils
.
getBean
(
AttendanceClassService
.
class
);
this
.
specialService
=
SpringUtils
.
getBean
(
AttendanceGroupFixedworkSpecialService
.
class
);
}
...
...
@@ -45,7 +53,7 @@ public class FixWorkAttendance extends AttendanceWorkAbstract {
}
@Override
public
void
doHandleWork
(
CommonData
commonData
)
{
public
void
doHandleWork
(
CommonData
commonData
)
{
AttendanceGroupFixedworkEntity
attendanceGroupFixedworkEntity
=
attendanceGroupFixedworkService
.
selectOne
(
new
AttendanceGroupFixedworkQuery
()
.
groupId
(
commonData
.
getAttendanceGroupEntity
().
getId
()));
//判断当前考勤日期为周几
...
...
@@ -64,6 +72,68 @@ public class FixWorkAttendance extends AttendanceWorkAbstract {
//跳过本次循环
return
;
}
//特殊日期考勤配置
List
<
AttendanceGroupFixedworkSpecialEntity
>
specialEntities
=
specialService
.
find
(
new
AttendanceGroupFixedworkSpecialQuery
().
fixedWorkId
(
attendanceGroupFixedworkEntity
.
getId
()));
if
(!
ObjectUtils
.
isEmpty
(
specialEntities
))
{
//分组 需要考勤与不需要考勤
Map
<
Boolean
,
List
<
AttendanceGroupFixedworkSpecialEntity
>>
collect
=
specialEntities
.
stream
().
collect
(
Collectors
.
partitioningBy
(
item
->
item
.
getMust
()
==
MustEnum
.
是
.
getValue
()));
List
<
AttendanceGroupFixedworkSpecialEntity
>
mustList
=
collect
.
get
(
true
);
if
(!
ObjectUtils
.
isEmpty
(
mustList
))
{
//需要打卡
for
(
AttendanceGroupFixedworkSpecialEntity
specialEntity
:
mustList
)
{
//必须考勤时间,单位日
Date
specialTime
=
specialEntity
.
getSpecialTime
();
//判断当前考勤日期是否需要考勤,如果需要重叠 则更新为特殊日期考勤
//判断考勤日期与特殊日期是否一致
if
(
DateUtil
.
formatDate
(
commonData
.
getAttendanceDate
()).
equals
(
DateUtil
.
formatDate
(
specialTime
)))
{
//更新打卡情况
weekClassId
=
specialEntity
.
getClassId
();
}
}
}
List
<
AttendanceGroupFixedworkSpecialEntity
>
mustNotList
=
collect
.
get
(
false
);
if
(!
ObjectUtils
.
isEmpty
(
mustNotList
))
{
//不需要考勤 查看是时间段还是单独时间
for
(
AttendanceGroupFixedworkSpecialEntity
specialEntity
:
mustNotList
)
{
Date
specialTime
=
specialEntity
.
getSpecialTime
();
if
(!
ObjectUtils
.
isEmpty
(
specialTime
))
{
if
(
DateUtil
.
formatDate
(
commonData
.
getAttendanceDate
()).
equals
(
DateUtil
.
formatDate
(
specialTime
)))
{
//当前日期不需要考勤打卡
//获取班次信息
AttendanceClassEntity
attendanceClassEntity
=
attendanceClassService
.
get
(
weekClassId
);
if
(
ObjectUtils
.
isEmpty
(
attendanceClassEntity
))
{
log
.
info
(
"attendanceClassEntity is null ,weekClassId:{}"
,
weekClassId
);
return
;
}
//List<AttendanceClassDetailEntity> attendanceClassDetailEntities = attendanceClassDetailService.find(new AttendanceClassDetailQuery().classId(attendanceClassEntity.getId()));
//获取当前班的多个班次,一个班次为一个上下班时间段
List
<
AttendanceClassDetailEntity
>
attendanceClassDetailEntities
=
attendanceClassEntity
.
getAttendanceClassDetailList
();
for
(
AttendanceClassDetailEntity
classDetail
:
attendanceClassDetailEntities
)
{
for
(
AttendanceRecordDetailEntity
attendanceRecordDetailEntity
:
commonData
.
getDetailEntityList
())
{
if
(
attendanceRecordDetailEntity
.
getShiftsId
()
==
classDetail
.
getId
())
{
attendanceRecordDetailEntity
.
setGoWorkResult
(
GoWorkResultEnum
.
正常
.
getValue
());
attendanceRecordDetailEntity
.
setGoWorkDate
(
commonData
.
getAttendanceDate
());
}
}
for
(
AttendanceRecordDetailEntity
attendanceRecordDetailEntity
:
commonData
.
getDetailEntityList
())
{
if
(
attendanceRecordDetailEntity
.
getShiftsId
()
==
classDetail
.
getId
())
{
attendanceRecordDetailEntity
.
setOffWorkResult
(
GoWorkResultEnum
.
正常
.
getValue
());
attendanceRecordDetailEntity
.
setOffWorkDate
(
commonData
.
getAttendanceDate
());
}
}
}
}
return
;
}
}
}
}
//获取班次信息
AttendanceClassEntity
attendanceClassEntity
=
attendanceClassService
.
get
(
weekClassId
);
if
(
ObjectUtils
.
isEmpty
(
attendanceClassEntity
))
{
...
...
@@ -77,7 +147,7 @@ public class FixWorkAttendance extends AttendanceWorkAbstract {
Integer
orderNum
=
0
;
//构造数据
if
(
ObjectUtils
.
isEmpty
(
commonData
.
getDetailEntityList
()))
{
//遍历班次 构建
详细考勤数据
//遍历班次 构建
初始详细考勤数据 当天的第二次考勤记录进来时不做初始化
for
(
AttendanceClassDetailEntity
classDetailEntity
:
attendanceClassDetailEntities
)
{
orderNum
++;
AttendanceRecordDetailEntity
recordDetailEntity
=
new
AttendanceRecordDetailEntity
();
...
...
@@ -89,6 +159,7 @@ public class FixWorkAttendance extends AttendanceWorkAbstract {
commonData
.
getDetailEntityList
().
add
(
recordDetailEntity
);
}
}
//遍历班次详细记录
for
(
AttendanceClassDetailEntity
classDetail
:
attendanceClassDetailEntities
)
{
//计算区间范围
//上班打卡前时间
...
...
@@ -147,7 +218,7 @@ public class FixWorkAttendance extends AttendanceWorkAbstract {
}
}
}
}
}
}
attendance-performance-manager/src/main/java/com/mortals/xhx/module/attendance/service/work/FixWorkOtherAttendance.java
0 → 100644
View file @
c0c01b1a
package
com.mortals.xhx.module.attendance.service.work
;
import
cn.hutool.core.date.DateUtil
;
import
com.mortals.framework.model.Context
;
import
com.mortals.framework.model.OrderCol
;
import
com.mortals.xhx.common.code.*
;
import
com.mortals.xhx.module.attendance.model.*
;
import
com.mortals.xhx.module.attendance.service.*
;
import
com.mortals.xhx.utils.SpringUtils
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.util.ObjectUtils
;
import
java.util.*
;
import
java.util.stream.Collectors
;
/**
* 固定班
*
* @author:
* @date: 2023/7/31 15:15
*/
@Slf4j
public
class
FixWorkOtherAttendance
extends
AttendanceWorkAbstract
{
private
AttendanceGroupFixedworkService
attendanceGroupFixedworkService
;
private
AttendanceClassService
attendanceClassService
;
private
AttendanceClassDetailService
attendanceClassDetailService
;
private
AttendanceGroupFixedworkSpecialService
specialService
;
private
AttendanceRecordService
attendanceRecordService
;
private
AttendanceRecordHikService
recordHikService
;
private
AttendanceRecordErrorService
errorService
;
public
FixWorkOtherAttendance
(
int
type
)
{
super
(
type
);
this
.
attendanceGroupFixedworkService
=
SpringUtils
.
getBean
(
AttendanceGroupFixedworkService
.
class
);
this
.
attendanceClassService
=
SpringUtils
.
getBean
(
AttendanceClassService
.
class
);
this
.
specialService
=
SpringUtils
.
getBean
(
AttendanceGroupFixedworkSpecialService
.
class
);
this
.
attendanceRecordService
=
SpringUtils
.
getBean
(
AttendanceRecordService
.
class
);
this
.
recordHikService
=
SpringUtils
.
getBean
(
AttendanceRecordHikService
.
class
);
this
.
attendanceClassDetailService
=
SpringUtils
.
getBean
(
AttendanceClassDetailService
.
class
);
this
.
errorService
=
SpringUtils
.
getBean
(
AttendanceRecordErrorService
.
class
);
}
@Override
int
getType
()
{
return
TypeEnum
.
固定班制
.
getValue
();
}
@Override
void
initData
()
{
}
@Override
public
void
doHandleWork
(
CommonData
commonData
)
{
AttendanceGroupFixedworkEntity
attendanceGroupFixedworkEntity
=
attendanceGroupFixedworkService
.
selectOne
(
new
AttendanceGroupFixedworkQuery
()
.
groupId
(
commonData
.
getAttendanceGroupEntity
().
getId
()));
if
(
ObjectUtils
.
isEmpty
(
attendanceGroupFixedworkEntity
))
{
log
.
info
(
"attendanceGroupFixedworkEntity is null ! groupId:{}"
,
commonData
.
getAttendanceGroupEntity
().
getId
());
return
;
}
//判断当前考勤日期为周几
String
week
=
super
.
getWeek
(
DateUtil
.
parseDate
(
commonData
.
getDateStr
()));
//log.info("week:{}", week);
//通过考勤日期的星期拿到班次id.
//获取当前日期的详细班次
Long
weekClassId
=
this
.
getWeekClassId
(
attendanceGroupFixedworkEntity
,
week
);
//log.info("weekClassId:{}", weekClassId);
//weekClassId为-1 则不在考勤
if
(
weekClassId
==
-
1L
)
{
//跳过本次循环
return
;
}
//特殊日期考勤配置
List
<
AttendanceGroupFixedworkSpecialEntity
>
specialEntities
=
specialService
.
find
(
new
AttendanceGroupFixedworkSpecialQuery
().
fixedWorkId
(
attendanceGroupFixedworkEntity
.
getId
()));
if
(!
ObjectUtils
.
isEmpty
(
specialEntities
))
{
//分组 需要考勤与不需要考勤
Map
<
Boolean
,
List
<
AttendanceGroupFixedworkSpecialEntity
>>
collect
=
specialEntities
.
stream
().
collect
(
Collectors
.
partitioningBy
(
item
->
item
.
getMust
()
==
MustEnum
.
是
.
getValue
()));
List
<
AttendanceGroupFixedworkSpecialEntity
>
mustList
=
collect
.
get
(
true
);
if
(!
ObjectUtils
.
isEmpty
(
mustList
))
{
//需要打卡
for
(
AttendanceGroupFixedworkSpecialEntity
specialEntity
:
mustList
)
{
//必须考勤时间,单位日
Date
specialTime
=
specialEntity
.
getSpecialTime
();
//判断当前考勤日期是否需要考勤,如果需要重叠 则更新为特殊日期考勤
//判断考勤日期与特殊日期是否一致
if
(!
ObjectUtils
.
isEmpty
(
specialTime
)
&&
DateUtil
.
formatDate
(
commonData
.
getAttendanceDate
()).
equals
(
DateUtil
.
formatDate
(
specialTime
)))
{
//更新打卡情况
if
(!
ObjectUtils
.
isEmpty
(
specialEntity
.
getClassId
()))
{
weekClassId
=
specialEntity
.
getClassId
();
}
}
}
}
List
<
AttendanceGroupFixedworkSpecialEntity
>
mustNotList
=
collect
.
get
(
false
);
if
(!
ObjectUtils
.
isEmpty
(
mustNotList
))
{
//不需要考勤 查看是时间段还是单独时间
for
(
AttendanceGroupFixedworkSpecialEntity
specialEntity
:
mustNotList
)
{
if
(
AddWayEnum
.
单个日期
.
getValue
()
==
specialEntity
.
getAddWay
())
{
Date
specialTime
=
specialEntity
.
getSpecialTime
();
if
(!
ObjectUtils
.
isEmpty
(
specialTime
)
&&
DateUtil
.
parseDate
(
commonData
.
getDateStr
()).
equals
(
DateUtil
.
formatDate
(
specialTime
)))
{
log
.
info
(
"当天特殊日期,无需考勤!dateStr:{}"
,
commonData
.
getDateStr
());
return
;
}
}
if
(
AddWayEnum
.
时间段
.
getValue
()
==
specialEntity
.
getAddWay
())
{
Date
specialStartTime
=
specialEntity
.
getSpecialStartTime
();
Date
specialEndTime
=
specialEntity
.
getSpecialEndTime
();
if
(!
ObjectUtils
.
isEmpty
(
specialStartTime
)
&&
!
ObjectUtils
.
isEmpty
(
specialEndTime
))
{
boolean
in
=
DateUtil
.
isIn
(
DateUtil
.
parseDate
(
commonData
.
getDateStr
()),
specialStartTime
,
specialEndTime
);
if
(
in
)
{
//直接返回 无班次信息
log
.
info
(
"当天特殊日期,无需考勤!dateStr:{}"
,
commonData
.
getDateStr
());
return
;
}
}
}
}
}
}
//获取班次信息
AttendanceClassEntity
attendanceClassEntity
=
attendanceClassService
.
get
(
weekClassId
);
if
(
ObjectUtils
.
isEmpty
(
attendanceClassEntity
))
{
log
.
info
(
"attendanceClassEntity is null ,weekClassId:{}"
,
weekClassId
);
return
;
}
//查询当天,该人员的考勤记录
AttendanceRecordHikQuery
recordHikQuery
=
new
AttendanceRecordHikQuery
();
recordHikQuery
.
setAttendanceDateStart
(
commonData
.
getDateStr
());
recordHikQuery
.
setAttendanceDateEnd
(
commonData
.
getDateStr
());
recordHikQuery
.
setStaffId
(
commonData
.
getStaffId
());
recordHikQuery
.
setOrderColList
(
Arrays
.
asList
(
new
OrderCol
(
"attendanceDate"
)));
List
<
AttendanceRecordHikEntity
>
recordHikEntities
=
recordHikService
.
find
(
recordHikQuery
);
List
<
AttendanceClassDetailEntity
>
attendanceClassDetailEntities
=
attendanceClassEntity
.
getAttendanceClassDetailList
();
Integer
orderNum
=
0
;
for
(
AttendanceClassDetailEntity
classDetailEntity
:
attendanceClassDetailEntities
)
{
orderNum
++;
AttendanceRecordDetailEntity
recordDetailEntity
=
new
AttendanceRecordDetailEntity
();
recordDetailEntity
.
setShiftsId
(
classDetailEntity
.
getId
());
recordDetailEntity
.
setShiftsName
(
classDetailEntity
.
getClassName
());
recordDetailEntity
.
setGoWorkResult
(
GoWorkResultEnum
.
缺卡
.
getValue
());
recordDetailEntity
.
setOffWorkResult
(
GoWorkResultEnum
.
缺卡
.
getValue
());
recordDetailEntity
.
setOrderNum
(
orderNum
);
commonData
.
getDetailEntityList
().
add
(
recordDetailEntity
);
}
if
(!
ObjectUtils
.
isEmpty
(
recordHikEntities
))
{
//针对当天的考勤记录进行计算与判断
//获取当前班的多个班次,一个班次为一个上下班时间段
for
(
AttendanceRecordHikEntity
recordHikEntity
:
recordHikEntities
)
{
Date
attendanceDate
=
recordHikEntity
.
getAttendanceDate
();
//遍历班次详细记录
for
(
AttendanceClassDetailEntity
classDetail
:
attendanceClassDetailEntities
)
{
//计算区间范围
//上班打卡前时间
Date
goWorkDateBefore
=
DateUtil
.
offsetMinute
(
classDetail
.
getGoWorkDate
(),
-
classDetail
.
getGoWorkDateBefore
());
//上班打卡后时间
Date
goWorkDateAfter
=
DateUtil
.
offsetMinute
(
classDetail
.
getGoWorkDate
(),
classDetail
.
getGoWorkDateAfter
());
// 下班打卡前时间
Date
offWorkDateBefore
=
DateUtil
.
offsetMinute
(
classDetail
.
getOffWorkDate
(),
-
classDetail
.
getOffWorkDateBefore
());
//下班打卡后时间
Date
offWorkDateAfter
=
DateUtil
.
offsetMinute
(
classDetail
.
getOffWorkDate
(),
classDetail
.
getOffWorkDateAfter
());
//判断考勤时间是否在上班打卡区间内 true 在 false 不在 格式化时间
//String currDate = DateUtil.formatTime(attendanceDate);
Date
curDateTime
=
DateUtil
.
parseTime
(
DateUtil
.
formatTime
(
attendanceDate
));
boolean
goInTime
=
DateUtil
.
isIn
(
curDateTime
,
goWorkDateBefore
,
goWorkDateAfter
);
//判断考勤时间是否在下班打卡区间内
boolean
offInTime
=
DateUtil
.
isIn
(
curDateTime
,
offWorkDateBefore
,
offWorkDateAfter
);
if
(
goInTime
==
false
&&
offInTime
==
false
)
{
log
.
info
(
"考勤时间不在上班区间与下班区间中,不做处理!attendDate:{}"
,
DateUtil
.
formatDateTime
(
commonData
.
getAttendanceDate
()));
continue
;
}
if
(
goInTime
)
{
//如果是上班打卡区间范围,判断是否迟到
boolean
inTime
=
DateUtil
.
isIn
(
curDateTime
,
goWorkDateBefore
,
classDetail
.
getGoWorkDate
());
if
(
inTime
)
{
for
(
AttendanceRecordDetailEntity
attendanceRecordDetailEntity
:
commonData
.
getDetailEntityList
())
{
if
(
attendanceRecordDetailEntity
.
getShiftsId
()
==
classDetail
.
getId
())
{
attendanceRecordDetailEntity
.
setGoWorkResult
(
GoWorkResultEnum
.
正常
.
getValue
());
attendanceRecordDetailEntity
.
setGoWorkDate
(
commonData
.
getAttendanceDate
());
}
}
}
else
{
for
(
AttendanceRecordDetailEntity
attendanceRecordDetailEntity
:
commonData
.
getDetailEntityList
())
{
if
(
attendanceRecordDetailEntity
.
getShiftsId
()
==
classDetail
.
getId
())
{
attendanceRecordDetailEntity
.
setGoWorkResult
(
GoWorkResultEnum
.
迟到
.
getValue
());
attendanceRecordDetailEntity
.
setGoWorkDate
(
commonData
.
getAttendanceDate
());
}
}
}
}
if
(
offInTime
)
{
boolean
inTime
=
DateUtil
.
isIn
(
curDateTime
,
classDetail
.
getOffWorkDate
(),
offWorkDateAfter
);
if
(
inTime
)
{
for
(
AttendanceRecordDetailEntity
attendanceRecordDetailEntity
:
commonData
.
getDetailEntityList
())
{
if
(
attendanceRecordDetailEntity
.
getShiftsId
()
==
classDetail
.
getId
())
{
attendanceRecordDetailEntity
.
setOffWorkResult
(
GoWorkResultEnum
.
正常
.
getValue
());
attendanceRecordDetailEntity
.
setOffWorkDate
(
commonData
.
getAttendanceDate
());
}
}
}
else
{
for
(
AttendanceRecordDetailEntity
attendanceRecordDetailEntity
:
commonData
.
getDetailEntityList
())
{
if
(
attendanceRecordDetailEntity
.
getShiftsId
()
==
classDetail
.
getId
())
{
attendanceRecordDetailEntity
.
setOffWorkResult
(
GoWorkResultEnum
.
早退
.
getValue
());
attendanceRecordDetailEntity
.
setOffWorkDate
(
commonData
.
getAttendanceDate
());
}
}
}
}
}
}
}
if
(!
ObjectUtils
.
isEmpty
(
commonData
.
getDetailEntityList
()))
{
AttendanceClassDetailEntity
attendanceClassDetailEntity
=
attendanceClassDetailService
.
get
(
commonData
.
getDetailEntityList
().
get
(
0
).
getShiftsId
());
commonData
.
getAttendanceRecordEntity
().
setShiftsId
(
attendanceClassDetailEntity
==
null
?
0L
:
attendanceClassDetailEntity
.
getClassId
());
commonData
.
getAttendanceRecordEntity
().
setShiftsName
(
attendanceClassDetailEntity
==
null
?
""
:
attendanceClassDetailEntity
.
getClassName
());
}
//生成异常记录
genErrorAttendRecord
(
commonData
.
getContext
(),
commonData
.
getDateStr
(),
commonData
.
getAttendanceRecordEntity
(),
commonData
.
getDetailEntityList
());
}
public
void
genErrorAttendRecord
(
Context
context
,
String
dateStr
,
AttendanceRecordEntity
attendanceRecordEntity
,
List
<
AttendanceRecordDetailEntity
>
detailEntityList
)
{
//处理异常打卡,所以异常打卡的 都新增一条记录
List
<
AttendanceRecordErrorEntity
>
errorEntityList
=
new
ArrayList
<>();
for
(
AttendanceRecordDetailEntity
recordDetailEntity
:
detailEntityList
)
{
Integer
goWorkResult
=
recordDetailEntity
.
getGoWorkResult
();
Integer
offWorkResult
=
recordDetailEntity
.
getOffWorkResult
();
//判断上班
AttendanceClassDetailEntity
attendanceClassDetailEntity
=
attendanceClassDetailService
.
get
(
recordDetailEntity
.
getShiftsId
());
if
(
ObjectUtils
.
isEmpty
(
attendanceClassDetailEntity
))
continue
;
AttendanceRecordErrorEntity
errorEntity
=
new
AttendanceRecordErrorEntity
();
errorEntity
.
initAttrValue
();
BeanUtils
.
copyProperties
(
attendanceRecordEntity
,
errorEntity
,
new
String
[]{
"id"
});
errorEntity
.
setGoOffDateTime
(
errorEntity
.
getErrorDateTime
());
errorEntity
.
setProcessStatus
(
YesNoEnum
.
NO
.
getValue
());
errorEntity
.
setCreateTime
(
new
Date
());
errorEntity
.
setCreateUserId
(
context
.
getUser
().
getId
());
//判断上班
if
(
GoWorkResultEnum
.
正常
.
getValue
()
!=
goWorkResult
)
{
Date
goWorkDate
=
attendanceClassDetailEntity
.
getGoWorkDate
();
errorEntity
.
setGoOffDateTime
(
goWorkDate
);
if
(!
ObjectUtils
.
isEmpty
(
recordDetailEntity
.
getGoWorkDate
()))
{
errorEntity
.
setErrorDateTime
(
recordDetailEntity
.
getGoWorkDate
());
errorEntity
.
setActualAttendanceDateTime
(
recordDetailEntity
.
getGoWorkDate
());
}
else
{
errorEntity
.
setErrorDateTime
(
DateUtil
.
parseDateTime
(
dateStr
+
" "
+
DateUtil
.
formatTime
(
goWorkDate
)).
toJdkDate
());
}
if
(
GoWorkResultEnum
.
早退
.
getValue
()
==
recordDetailEntity
.
getGoWorkResult
())
{
errorEntity
.
setErrorStatus
(
ErrorStatusEnum
.
早退
.
getValue
());
}
if
(
GoWorkResultEnum
.
迟到
.
getValue
()
==
recordDetailEntity
.
getGoWorkResult
())
{
errorEntity
.
setErrorStatus
(
ErrorStatusEnum
.
迟到
.
getValue
());
}
if
(
GoWorkResultEnum
.
缺卡
.
getValue
()
==
recordDetailEntity
.
getGoWorkResult
())
{
errorEntity
.
setErrorStatus
(
ErrorStatusEnum
.
缺卡
.
getValue
());
}
errorEntityList
.
add
(
errorEntity
);
}
//判断下班
if
(
OffWorkResultEnum
.
正常
.
getValue
()
!=
offWorkResult
)
{
Date
offWorkDate
=
attendanceClassDetailEntity
.
getOffWorkDate
();
errorEntity
.
setGoOffDateTime
(
offWorkDate
);
if
(!
ObjectUtils
.
isEmpty
(
recordDetailEntity
.
getGoWorkDate
()))
{
errorEntity
.
setErrorDateTime
(
recordDetailEntity
.
getGoWorkDate
());
errorEntity
.
setActualAttendanceDateTime
(
recordDetailEntity
.
getGoWorkDate
());
}
else
{
errorEntity
.
setErrorDateTime
(
DateUtil
.
parseDateTime
(
dateStr
+
" "
+
DateUtil
.
formatTime
(
offWorkDate
)).
toJdkDate
());
}
if
(
OffWorkResultEnum
.
缺卡
.
getValue
()
==
recordDetailEntity
.
getOffWorkResult
())
{
errorEntity
.
setErrorStatus
(
ErrorStatusEnum
.
缺卡
.
getValue
());
}
if
(
OffWorkResultEnum
.
早退
.
getValue
()
==
recordDetailEntity
.
getOffWorkResult
())
{
errorEntity
.
setErrorStatus
(
ErrorStatusEnum
.
早退
.
getValue
());
}
if
(
OffWorkResultEnum
.
迟到
.
getValue
()
==
recordDetailEntity
.
getOffWorkResult
())
{
errorEntity
.
setErrorStatus
(
ErrorStatusEnum
.
迟到
.
getValue
());
}
errorEntityList
.
add
(
errorEntity
);
}
}
if
(!
ObjectUtils
.
isEmpty
(
errorEntityList
))
{
errorService
.
save
(
errorEntityList
,
context
);
}
}
}
attendance-performance-manager/src/main/java/com/mortals/xhx/module/attendance/service/work/FreedomWorkAttendance.java
View file @
c0c01b1a
...
...
@@ -35,8 +35,6 @@ public class FreedomWorkAttendance extends AttendanceWorkAbstract {
private
AttendanceGroupFreeworkSpecialService
specialService
;
@Autowired
private
AttendanceRecordHikService
recordHikService
;
...
...
@@ -46,6 +44,7 @@ public class FreedomWorkAttendance extends AttendanceWorkAbstract {
this
.
attendanceClassService
=
SpringUtils
.
getBean
(
AttendanceClassService
.
class
);
this
.
attendanceRecordService
=
SpringUtils
.
getBean
(
AttendanceRecordService
.
class
);
this
.
specialService
=
SpringUtils
.
getBean
(
AttendanceGroupFreeworkSpecialService
.
class
);
this
.
recordHikService
=
SpringUtils
.
getBean
(
AttendanceRecordHikService
.
class
);
}
@Override
...
...
@@ -72,8 +71,9 @@ public class FreedomWorkAttendance extends AttendanceWorkAbstract {
// 查询当前这个人今日的考勤数据,并且按打卡时间进行升序排列
AttendanceRecordHikQuery
recordHikQuery
=
new
AttendanceRecordHikQuery
();
recordHikQuery
.
setAttendanceDateStart
(
DateUtil
.
today
());
recordHikQuery
.
setAttendanceDateEnd
(
DateUtil
.
today
());
recordHikQuery
.
setAttendanceDateStart
(
DateUtil
.
date
(
commonData
.
getAttendanceDate
()).
toDateStr
());
recordHikQuery
.
setAttendanceDateEnd
(
DateUtil
.
date
(
commonData
.
getAttendanceDate
()).
toDateStr
());
recordHikQuery
.
setStaffId
(
commonData
.
getStaffId
());
recordHikQuery
.
setOrderColList
(
Arrays
.
asList
(
new
OrderCol
(
"attendanceDate"
)));
List
<
AttendanceRecordHikEntity
>
recordHikEntities
=
recordHikService
.
find
(
recordHikQuery
);
...
...
@@ -122,19 +122,14 @@ public class FreedomWorkAttendance extends AttendanceWorkAbstract {
//分组 需要考勤与不需要考勤
Map
<
Boolean
,
List
<
AttendanceGroupFreeworkSpecialEntity
>>
collect
=
specialEntities
.
stream
().
collect
(
Collectors
.
partitioningBy
(
item
->
item
.
getMust
()
==
MustEnum
.
是
.
getValue
()));
List
<
AttendanceGroupFreeworkSpecialEntity
>
mustList
=
collect
.
get
(
true
);
if
(!
ObjectUtils
.
isEmpty
(
mustList
))
{
if
(!
ObjectUtils
.
isEmpty
(
mustList
))
{
//需要打卡
for
(
AttendanceGroupFreeworkSpecialEntity
specialEntity
:
mustList
)
{
}
}
List
<
AttendanceGroupFreeworkSpecialEntity
>
mustNotList
=
collect
.
get
(
false
);
}
...
...
attendance-performance-manager/src/main/resources/config/mybatis-sqlmap-config.xml
View file @
c0c01b1a
...
...
@@ -20,7 +20,7 @@
<plugin
interceptor=
"com.mortals.framework.thirty.mybatis.LogInterceptor"
>
<property
name=
"enableExecutorTime"
value=
"true"
/>
<property
name=
"showSql"
value=
"
tru
e"
/>
<property
name=
"showSql"
value=
"
fals
e"
/>
</plugin>
</plugins>
</configuration>
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment