|
@@ -221,7 +221,8 @@ public class SwdlServiceImpl extends GenericProvider implements SwdlService {
|
|
|
Map paramMap= getAttendanceMap(map);
|
|
Map paramMap= getAttendanceMap(map);
|
|
|
List<Map<String,Object>> list = updateDataTableDao.selectAttendance2Data(paramMap);
|
|
List<Map<String,Object>> list = updateDataTableDao.selectAttendance2Data(paramMap);
|
|
|
// int totalCount = updateDataTableDao.selectAttendance2DataCount(paramMap);
|
|
// int totalCount = updateDataTableDao.selectAttendance2DataCount(paramMap);
|
|
|
- List<Map<String, Object>> data = calculateAttendance(list);
|
|
|
|
|
|
|
+ String type = BeanUtils.isNotEmpty(paramMap.get("type"))?paramMap.get("type").toString():"";
|
|
|
|
|
+ List<Map<String, Object>> data = calculateAttendance(list,type);
|
|
|
data = data.stream()
|
|
data = data.stream()
|
|
|
.sorted(Comparator.comparing(map2 -> (String) map2.get("user_id_")))
|
|
.sorted(Comparator.comparing(map2 -> (String) map2.get("user_id_")))
|
|
|
.collect(Collectors.toList());
|
|
.collect(Collectors.toList());
|
|
@@ -566,6 +567,11 @@ public class SwdlServiceImpl extends GenericProvider implements SwdlService {
|
|
|
}
|
|
}
|
|
|
stringObjectHashMap.put("startDate",param.get("kaishiJianShiJ^S"));
|
|
stringObjectHashMap.put("startDate",param.get("kaishiJianShiJ^S"));
|
|
|
stringObjectHashMap.put("endDate",param.get("kaishiJianShiJ^E"));
|
|
stringObjectHashMap.put("endDate",param.get("kaishiJianShiJ^E"));
|
|
|
|
|
+
|
|
|
|
|
+ //1 或者空 表示考勤统计,2表示考勤概况
|
|
|
|
|
+ if(BeanUtils.isNotEmpty(param.get("type"))){
|
|
|
|
|
+ stringObjectHashMap.put("type",param.get("type"));
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
return stringObjectHashMap;
|
|
return stringObjectHashMap;
|
|
@@ -661,19 +667,26 @@ public class SwdlServiceImpl extends GenericProvider implements SwdlService {
|
|
|
}
|
|
}
|
|
|
return stringObjectHashMap;
|
|
return stringObjectHashMap;
|
|
|
}
|
|
}
|
|
|
- public List<Map<String, Object>> calculateAttendance(List<Map<String, Object>> attendanceRecords) {
|
|
|
|
|
|
|
+ public List<Map<String, Object>> calculateAttendance(List<Map<String, Object>> attendanceRecords,String type) {
|
|
|
// 获取当前系统日期
|
|
// 获取当前系统日期
|
|
|
String systemDate = LocalDate.now().format(DATE_FORMATTER);
|
|
String systemDate = LocalDate.now().format(DATE_FORMATTER);
|
|
|
|
|
|
|
|
// 按用户ID分组
|
|
// 按用户ID分组
|
|
|
Map<String, List<Map<String, Object>>> recordsByUser = new HashMap<>();
|
|
Map<String, List<Map<String, Object>>> recordsByUser = new HashMap<>();
|
|
|
|
|
+
|
|
|
|
|
+ // 存储每个用户的考勤统计结果(改为List)
|
|
|
|
|
+ List<Map<String, Object>> resultList = new ArrayList<>();
|
|
|
|
|
+ // 存储每个用户的考勤概况结果(改为List)
|
|
|
|
|
+ List<Map<String, Object>> resultList2 = new ArrayList<>();
|
|
|
|
|
+
|
|
|
|
|
+ if(attendanceRecords.isEmpty()){
|
|
|
|
|
+ return resultList;
|
|
|
|
|
+ }
|
|
|
for (Map<String, Object> record : attendanceRecords) {
|
|
for (Map<String, Object> record : attendanceRecords) {
|
|
|
String userId = (String) record.get("user_id_");
|
|
String userId = (String) record.get("user_id_");
|
|
|
recordsByUser.computeIfAbsent(userId, k -> new ArrayList<>()).add(record);
|
|
recordsByUser.computeIfAbsent(userId, k -> new ArrayList<>()).add(record);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 存储每个用户的统计结果(改为List)
|
|
|
|
|
- List<Map<String, Object>> resultList = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
// 遍历每个用户的考勤记录
|
|
// 遍历每个用户的考勤记录
|
|
|
for (Map.Entry<String, List<Map<String, Object>>> userEntry : recordsByUser.entrySet()) {
|
|
for (Map.Entry<String, List<Map<String, Object>>> userEntry : recordsByUser.entrySet()) {
|
|
@@ -681,8 +694,10 @@ public class SwdlServiceImpl extends GenericProvider implements SwdlService {
|
|
|
List<Map<String, Object>> userRecords = userEntry.getValue();
|
|
List<Map<String, Object>> userRecords = userEntry.getValue();
|
|
|
|
|
|
|
|
// 初始化统计指标
|
|
// 初始化统计指标
|
|
|
- Map<String, Object> userStats = initUserStats(userRecords);
|
|
|
|
|
- userStats.put("user_id_", userId); // 添加用户ID到结果中
|
|
|
|
|
|
|
+ Map<String, Object> userStats = initUserStats(userRecords);//考勤统计
|
|
|
|
|
+ //Map<String, Object> initUserEveryDayStats = initUserStatsEveryDay(userRecords);//考勤概况
|
|
|
|
|
+
|
|
|
|
|
+ userStats.put("user_id_", userId); // 添加用户ID到结果中
|
|
|
|
|
|
|
|
// 按日期分组
|
|
// 按日期分组
|
|
|
Map<String, List<Map<String, Object>>> recordsByDate = new HashMap<>();
|
|
Map<String, List<Map<String, Object>>> recordsByDate = new HashMap<>();
|
|
@@ -693,14 +708,16 @@ public class SwdlServiceImpl extends GenericProvider implements SwdlService {
|
|
|
|
|
|
|
|
// 统计每个日期的数据
|
|
// 统计每个日期的数据
|
|
|
for (Map.Entry<String, List<Map<String, Object>>> dateEntry : recordsByDate.entrySet()) {//统计天数
|
|
for (Map.Entry<String, List<Map<String, Object>>> dateEntry : recordsByDate.entrySet()) {//统计天数
|
|
|
|
|
+ Map<String, Object> initUserEveryDayStats = initUserStatsEveryDay(userRecords);//考勤概况,每个用户每天统计一次
|
|
|
String date = dateEntry.getKey();
|
|
String date = dateEntry.getKey();
|
|
|
List<Map<String, Object>> dateRecords = dateEntry.getValue();//某个日期下的多个班次数据,同时存在早班,晚班等
|
|
List<Map<String, Object>> dateRecords = dateEntry.getValue();//某个日期下的多个班次数据,同时存在早班,晚班等
|
|
|
-
|
|
|
|
|
|
|
+ initUserEveryDayStats.put("ri_qi_", date); // 添加日期到考勤概况
|
|
|
|
|
+ initUserEveryDayStats.put("user_id_", userId); // 添加用户ID到结果中
|
|
|
boolean isRestDay = false;
|
|
boolean isRestDay = false;
|
|
|
boolean hasAttendance = false;
|
|
boolean hasAttendance = false;
|
|
|
boolean isNormalDay = true;
|
|
boolean isNormalDay = true;
|
|
|
boolean isAbnormalDay = false;
|
|
boolean isAbnormalDay = false;
|
|
|
- boolean isAbsenteeism = false;//改天是否存在旷工班次
|
|
|
|
|
|
|
+ boolean isAbsenteeism = false;//该天是否存在旷工班次
|
|
|
|
|
|
|
|
boolean existAttendanceDay = false;// 非休息班次标记,当天只有有一个非休息班次就统计为true
|
|
boolean existAttendanceDay = false;// 非休息班次标记,当天只有有一个非休息班次就统计为true
|
|
|
// 比较当前记录日期与系统日期
|
|
// 比较当前记录日期与系统日期
|
|
@@ -738,13 +755,41 @@ public class SwdlServiceImpl extends GenericProvider implements SwdlService {
|
|
|
if (REST_SHIFT.equals(shiftName)) {
|
|
if (REST_SHIFT.equals(shiftName)) {
|
|
|
// increment(userStats, "xiu_xi_tian_shu", 1);
|
|
// increment(userStats, "xiu_xi_tian_shu", 1);
|
|
|
isRestDay = true;
|
|
isRestDay = true;
|
|
|
|
|
+ getAttendanceResult(initUserEveryDayStats);
|
|
|
|
|
+ resultList2.add(initUserEveryDayStats);// 休息日不参与其他统计考勤概况后面会丢失这条休息数据,故在这里加上
|
|
|
continue; // 休息日不参与其他统计
|
|
continue; // 休息日不参与其他统计
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 3. 实际出勤天数统计(有打卡记录)
|
|
// 3. 实际出勤天数统计(有打卡记录)
|
|
|
if ((checkIn1 != null && !checkIn1.isEmpty()) ||
|
|
if ((checkIn1 != null && !checkIn1.isEmpty()) ||
|
|
|
(checkIn2 != null && !checkIn2.isEmpty())) {
|
|
(checkIn2 != null && !checkIn2.isEmpty())) {
|
|
|
|
|
+ //考勤统计
|
|
|
hasAttendance = true;
|
|
hasAttendance = true;
|
|
|
|
|
+ //考勤概况
|
|
|
|
|
+ if(checkIn1 != null && !checkIn1.isEmpty()){
|
|
|
|
|
+ increment(initUserEveryDayStats, "da_ka_ci_shu_", 1);
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ compareTo 比较时间是按照 年份 → 月份 → 日期 → 小时 → 分钟 → 秒
|
|
|
|
|
+ "2025-08-27 07:00:49" vs "2025-08-27 06:59:59" → "07:00:49" > "06:59:59"
|
|
|
|
|
+ */
|
|
|
|
|
+ // 更新最早打卡时间
|
|
|
|
|
+ String currentZuiZao = (String) initUserEveryDayStats.get("zui_zao");
|
|
|
|
|
+ if (currentZuiZao == null || currentZuiZao.isEmpty() ||
|
|
|
|
|
+ checkIn1.compareTo(currentZuiZao) < 0) {
|
|
|
|
|
+ initUserEveryDayStats.put("zui_zao", checkIn1);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if(checkIn2 != null && !checkIn2.isEmpty()){
|
|
|
|
|
+ increment(initUserEveryDayStats, "da_ka_ci_shu_", 1);
|
|
|
|
|
+
|
|
|
|
|
+ // 更新最晚打卡时间
|
|
|
|
|
+ String currentZuiWan = (String) initUserEveryDayStats.get("zui_wan");
|
|
|
|
|
+ if (currentZuiWan == null || currentZuiWan.isEmpty() ||
|
|
|
|
|
+ checkIn2.compareTo(currentZuiWan) > 0) {
|
|
|
|
|
+ initUserEveryDayStats.put("zui_wan", checkIn2);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 4. 异常次数统计(不再把旷工统计到异常里面,只有异常统计为异常)
|
|
// 4. 异常次数统计(不再把旷工统计到异常里面,只有异常统计为异常)
|
|
@@ -773,9 +818,11 @@ public class SwdlServiceImpl extends GenericProvider implements SwdlService {
|
|
|
// 5. 迟到次数统计-上班异常算迟到,提前下班也算迟到(迟到/早退)
|
|
// 5. 迟到次数统计-上班异常算迟到,提前下班也算迟到(迟到/早退)
|
|
|
if (ABNORMAL_STATUS.equals(status1)) {
|
|
if (ABNORMAL_STATUS.equals(status1)) {
|
|
|
increment(userStats, "chi_dao_ci_shu", 1);
|
|
increment(userStats, "chi_dao_ci_shu", 1);
|
|
|
|
|
+ increment(initUserEveryDayStats, "chi_dao_ci_shu", 1);
|
|
|
}
|
|
}
|
|
|
if (ABNORMAL_STATUS.equals(status2)) {
|
|
if (ABNORMAL_STATUS.equals(status2)) {
|
|
|
increment(userStats, "chi_dao_ci_shu", 1);
|
|
increment(userStats, "chi_dao_ci_shu", 1);
|
|
|
|
|
+ increment(initUserEveryDayStats, "chi_dao_ci_shu", 1);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 6. 迟到时长统计
|
|
// 6. 迟到时长统计
|
|
@@ -792,10 +839,12 @@ public class SwdlServiceImpl extends GenericProvider implements SwdlService {
|
|
|
if (dateCompare < 0) {
|
|
if (dateCompare < 0) {
|
|
|
if (checkIn1 == null || checkIn1.isEmpty()) {
|
|
if (checkIn1 == null || checkIn1.isEmpty()) {
|
|
|
increment(userStats, "kuang_gong_ci_shu", 1);
|
|
increment(userStats, "kuang_gong_ci_shu", 1);
|
|
|
|
|
+ increment(initUserEveryDayStats, "que_qin_ci_shu", 1);//不统计当天
|
|
|
isAbsenteeism = true;
|
|
isAbsenteeism = true;
|
|
|
}
|
|
}
|
|
|
if (checkIn2 == null || checkIn2.isEmpty()) {
|
|
if (checkIn2 == null || checkIn2.isEmpty()) {
|
|
|
increment(userStats, "kuang_gong_ci_shu", 1);
|
|
increment(userStats, "kuang_gong_ci_shu", 1);
|
|
|
|
|
+ increment(initUserEveryDayStats, "que_qin_ci_shu", 1);//不统计当天
|
|
|
isAbsenteeism = true;
|
|
isAbsenteeism = true;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -807,6 +856,7 @@ public class SwdlServiceImpl extends GenericProvider implements SwdlService {
|
|
|
//double duration = Math.round(Double.parseDouble(shiftDuration)/60);
|
|
//double duration = Math.round(Double.parseDouble(shiftDuration)/60);
|
|
|
double duration = Math.round(Double.parseDouble(shiftDuration) / 60.0 * 100.0) / 100.0;
|
|
double duration = Math.round(Double.parseDouble(shiftDuration) / 60.0 * 100.0) / 100.0;
|
|
|
addTo(userStats, "ban_ci_shi_chang", duration);
|
|
addTo(userStats, "ban_ci_shi_chang", duration);
|
|
|
|
|
+ addTo(initUserEveryDayStats, "ban_ci_shi_chang", duration);
|
|
|
} catch (NumberFormatException e) {
|
|
} catch (NumberFormatException e) {
|
|
|
// 忽略格式错误
|
|
// 忽略格式错误
|
|
|
}
|
|
}
|
|
@@ -819,6 +869,7 @@ public class SwdlServiceImpl extends GenericProvider implements SwdlService {
|
|
|
//double duration = Math.round(Double.parseDouble(workDuration)/60);
|
|
//double duration = Math.round(Double.parseDouble(workDuration)/60);
|
|
|
double duration = Math.round(Double.parseDouble(workDuration) / 60.0 * 100.0) / 100.0;
|
|
double duration = Math.round(Double.parseDouble(workDuration) / 60.0 * 100.0) / 100.0;
|
|
|
addTo(userStats, "gong_zuo_shi_chang", duration);
|
|
addTo(userStats, "gong_zuo_shi_chang", duration);
|
|
|
|
|
+ addTo(initUserEveryDayStats, "gong_zuo_shi_chang", duration);
|
|
|
} catch (NumberFormatException e) {
|
|
} catch (NumberFormatException e) {
|
|
|
// 忽略格式错误
|
|
// 忽略格式错误
|
|
|
}
|
|
}
|
|
@@ -841,7 +892,7 @@ public class SwdlServiceImpl extends GenericProvider implements SwdlService {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ }//end 统计次数
|
|
|
//(当天不存在正常出勤的班次才能统计为休息)
|
|
//(当天不存在正常出勤的班次才能统计为休息)
|
|
|
if(!existAttendanceDay && isRestDay){
|
|
if(!existAttendanceDay && isRestDay){
|
|
|
isRestDay = true;
|
|
isRestDay = true;
|
|
@@ -849,9 +900,10 @@ public class SwdlServiceImpl extends GenericProvider implements SwdlService {
|
|
|
isRestDay = false;
|
|
isRestDay = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 休息天数统计
|
|
|
|
|
|
|
+ // 休息天数统计(该日没有非休息的应出勤班次)
|
|
|
if (isRestDay) {
|
|
if (isRestDay) {
|
|
|
increment(userStats, "xiu_xi_tian_shu", 1);
|
|
increment(userStats, "xiu_xi_tian_shu", 1);
|
|
|
|
|
+ initUserEveryDayStats.put("kao_qing_jie_guo", "休息"); // 该天班次全为休息
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
// 实际出勤天数统计(按日期)
|
|
// 实际出勤天数统计(按日期)
|
|
@@ -873,6 +925,8 @@ public class SwdlServiceImpl extends GenericProvider implements SwdlService {
|
|
|
if(!isRestDay && existAttendanceDay && isAbsenteeism && dateCompare < 0){
|
|
if(!isRestDay && existAttendanceDay && isAbsenteeism && dateCompare < 0){
|
|
|
increment(userStats, "kuang_gong_tian_shu", 1);
|
|
increment(userStats, "kuang_gong_tian_shu", 1);
|
|
|
}*/
|
|
}*/
|
|
|
|
|
+ getAttendanceResult(initUserEveryDayStats);
|
|
|
|
|
+ resultList2.add(initUserEveryDayStats);
|
|
|
}
|
|
}
|
|
|
//异常次数需要包含旷工次数,异常天数也需要包含旷工天数
|
|
//异常次数需要包含旷工次数,异常天数也需要包含旷工天数
|
|
|
int numkgcs = (Integer) userStats.get("kuang_gong_ci_shu");
|
|
int numkgcs = (Integer) userStats.get("kuang_gong_ci_shu");
|
|
@@ -884,10 +938,36 @@ public class SwdlServiceImpl extends GenericProvider implements SwdlService {
|
|
|
// 将用户统计结果添加到List中
|
|
// 将用户统计结果添加到List中
|
|
|
resultList.add(userStats);
|
|
resultList.add(userStats);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+ //type 为2时候返回考勤概况数据,其他情况默认返回考勤统计数据
|
|
|
|
|
+ if("2".equals(type)){
|
|
|
|
|
+ return resultList2;
|
|
|
|
|
+ }
|
|
|
return resultList;
|
|
return resultList;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private void getAttendanceResult(Map<String, Object> initUserEveryDayStats) {
|
|
|
|
|
+ // 组装考勤状态信息
|
|
|
|
|
+ StringBuilder statusBuilder = new StringBuilder();
|
|
|
|
|
+
|
|
|
|
|
+ int chiDaoCount = (Integer) initUserEveryDayStats.get("chi_dao_ci_shu");
|
|
|
|
|
+ int queQinCount = (Integer) initUserEveryDayStats.get("que_qin_ci_shu");
|
|
|
|
|
+
|
|
|
|
|
+ if (chiDaoCount > 0) {
|
|
|
|
|
+ statusBuilder.append("迟到").append(chiDaoCount).append("次");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (queQinCount > 0) {
|
|
|
|
|
+ if (statusBuilder.length() > 0) {
|
|
|
|
|
+ statusBuilder.append(",");
|
|
|
|
|
+ }
|
|
|
|
|
+ statusBuilder.append("缺勤").append(queQinCount).append("次");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (statusBuilder.length() == 0) {
|
|
|
|
|
+ statusBuilder.append("正常");
|
|
|
|
|
+ }
|
|
|
|
|
+ initUserEveryDayStats.put("kao_qin_zhuang_tai", statusBuilder.toString());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private Map<String, Object> initUserStats(List<Map<String, Object>> userRecords) {
|
|
private Map<String, Object> initUserStats(List<Map<String, Object>> userRecords) {
|
|
|
Map<String, Object> stats = new HashMap<>();
|
|
Map<String, Object> stats = new HashMap<>();
|
|
|
stats.put("yi_chang_ci_shu", 0);
|
|
stats.put("yi_chang_ci_shu", 0);
|
|
@@ -907,6 +987,24 @@ public class SwdlServiceImpl extends GenericProvider implements SwdlService {
|
|
|
stats.put("kuang_gong_tian_shu", 0);
|
|
stats.put("kuang_gong_tian_shu", 0);
|
|
|
return stats;
|
|
return stats;
|
|
|
}
|
|
}
|
|
|
|
|
+ private Map<String, Object> initUserStatsEveryDay(List<Map<String, Object>> userRecords) {
|
|
|
|
|
+ Map<String, Object> stats = new HashMap<>();
|
|
|
|
|
+
|
|
|
|
|
+ stats.put("ri_qi_", "");
|
|
|
|
|
+ stats.put("user_name_",userRecords.get(0).get("user_name_"));
|
|
|
|
|
+ stats.put("pos_name_",userRecords.get(0).get("pos_name_"));
|
|
|
|
|
+ stats.put("gong_hao_",userRecords.get(0).get("gong_hao_"));
|
|
|
|
|
+ stats.put("zui_zao", "");
|
|
|
|
|
+ stats.put("zui_wan", "");
|
|
|
|
|
+ stats.put("da_ka_ci_shu_", 0);
|
|
|
|
|
+ stats.put("ban_ci_shi_chang", 0.0);
|
|
|
|
|
+ stats.put("gong_zuo_shi_chang", 0.0);
|
|
|
|
|
+ stats.put("kao_qin_zhuang_tai", "");
|
|
|
|
|
+ stats.put("chi_dao_ci_shu", 0);
|
|
|
|
|
+ stats.put("que_qin_ci_shu", 0);
|
|
|
|
|
+
|
|
|
|
|
+ return stats;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
private void increment(Map<String, Object> stats, String key, int amount) {
|
|
private void increment(Map<String, Object> stats, String key, int amount) {
|
|
|
int current = (int) stats.getOrDefault(key, 0);
|
|
int current = (int) stats.getOrDefault(key, 0);
|