工程月考勤总览

This commit is contained in:
方亮 2026-01-06 13:59:33 +08:00
parent 6265691055
commit 628dc4367a
6 changed files with 251 additions and 6 deletions

View File

@ -4,6 +4,7 @@ import com.bonus.bmw.domain.vo.*;
import com.bonus.bmw.service.BmWorkerAttService; import com.bonus.bmw.service.BmWorkerAttService;
import com.bonus.common.core.utils.poi.ExcelUtil; import com.bonus.common.core.utils.poi.ExcelUtil;
import com.bonus.common.core.web.controller.BaseController; import com.bonus.common.core.web.controller.BaseController;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.core.web.page.TableDataInfo; import com.bonus.common.core.web.page.TableDataInfo;
import com.bonus.common.log.annotation.SysLog; import com.bonus.common.log.annotation.SysLog;
import com.bonus.common.log.enums.OperaType; import com.bonus.common.log.enums.OperaType;
@ -164,6 +165,25 @@ public class BmWorkerAttController extends BaseController {
return getDataTableError(new ArrayList<>()); return getDataTableError(new ArrayList<>());
} }
/**
* 工程月考勤统计-按日期
* @param o
* @return
*/
@RequiresPermissionsOrInnerAuth(innerAuth = @InnerAuth(isUser = false))
@GetMapping("/getWorkerAttByMonth")
@SysLog(title = "月考勤总览表", businessType = OperaType.QUERY, logType = 0, module = "施工人员->考勤管理->月考勤总览表", details = "月考勤总览表")
public AjaxResult getWorkerAttByMonth(UserAttendanceVo o) {
try {
List<UserAttendanceVo> res = service.getWorkerAttByMonth(o);
return success(res);
} catch (Exception e) {
logger.error(e.toString(), e);
}
return error("系统异常,请联系管理员");
}
/** /**
* 考勤导出-工程维度 * 考勤导出-工程维度
*/ */

View File

@ -111,4 +111,13 @@ public class UserAttendanceVo {
private String remark; private String remark;
// 以下字段不返回给前端
private Integer workerId;
private String workerName;
private String teamName;
private String einDay;
private String attDay;
private String isRepair;
} }

View File

@ -1,7 +1,7 @@
package com.bonus.bmw.mapper; package com.bonus.bmw.mapper;
import com.bonus.bmw.domain.vo.BmWorkerAtt; import com.bonus.bmw.domain.vo.BmWorkerAtt;
import com.bonus.bmw.domain.vo.BmWorkerLight; import com.bonus.bmw.domain.vo.UserAttendanceVo;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import java.util.List; import java.util.List;
@ -42,4 +42,17 @@ public interface BmWorkerAttMapper {
List<BmWorkerAtt> getTeamAttListBySevenNotAtt(BmWorkerAtt o); List<BmWorkerAtt> getTeamAttListBySevenNotAtt(BmWorkerAtt o);
List<BmWorkerAtt> getSevenNotAttListByTeam(BmWorkerAtt o); List<BmWorkerAtt> getSevenNotAttListByTeam(BmWorkerAtt o);
/**
* 通过三表一册查询某工程某月人员打卡总览
* @param o
* @return
*/
List<UserAttendanceVo> getWorkerAttRecordByMonth(UserAttendanceVo o);
/**
* 查询某工程某月人员打卡数据
* @param o
* @return
*/
List<UserAttendanceVo> getWorkerAttByMonth(UserAttendanceVo o);
} }

View File

@ -1,6 +1,7 @@
package com.bonus.bmw.service; package com.bonus.bmw.service;
import com.bonus.bmw.domain.vo.BmWorkerAtt; import com.bonus.bmw.domain.vo.BmWorkerAtt;
import com.bonus.bmw.domain.vo.UserAttendanceVo;
import java.util.List; import java.util.List;
@ -47,4 +48,11 @@ public interface BmWorkerAttService {
* @return * @return
*/ */
List<BmWorkerAtt> getSevenNotAttListByTeam(BmWorkerAtt o); List<BmWorkerAtt> getSevenNotAttListByTeam(BmWorkerAtt o);
/**
* 查询某工程某月人员打卡总览
* @param o
* @return
*/
List<UserAttendanceVo> getWorkerAttByMonth(UserAttendanceVo o);
} }

View File

@ -1,18 +1,25 @@
package com.bonus.bmw.service.impl; package com.bonus.bmw.service.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.bonus.bmw.domain.dto.WorkerAttDayVo;
import com.bonus.bmw.domain.vo.BmWorkerAtt; import com.bonus.bmw.domain.vo.BmWorkerAtt;
import com.bonus.bmw.mapper.BmWorkerAttMapper; import com.bonus.bmw.domain.vo.MapBeanVo;
import com.bonus.bmw.domain.vo.UserAttendanceVo;
import com.bonus.bmw.mapper.BmWorkerAttMapper; import com.bonus.bmw.mapper.BmWorkerAttMapper;
import com.bonus.bmw.service.BmWorkerAttService; import com.bonus.bmw.service.BmWorkerAttService;
import com.bonus.bmw.service.BmWorkerAttService; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Slf4j
@Service @Service
public class BmWorkerAttServiceImpl implements BmWorkerAttService { public class BmWorkerAttServiceImpl implements BmWorkerAttService {
@ -111,10 +118,148 @@ public class BmWorkerAttServiceImpl implements BmWorkerAttService {
@Override @Override
public List<BmWorkerAtt> getSevenNotAttListByTeam(BmWorkerAtt o) { public List<BmWorkerAtt> getSevenNotAttListByTeam(BmWorkerAtt o) {
List<BmWorkerAtt> list = mapper.getSevenNotAttListByTeam(o); return mapper.getSevenNotAttListByTeam(o);
return list;
} }
/**
* 询某工程某月人员打卡总览
* @param o
* @return
*/
@Override
public List<UserAttendanceVo> getWorkerAttByMonth(UserAttendanceVo o) {
//1.是否是当月 --当月需重新查询 --之前月份的可以从三表一册中读取
if (isCurrentMonth(o.getMonth())) {
//--当月需重新查询
List<UserAttendanceVo> listAtt = mapper.getWorkerAttByMonth(o);
return dealAttData(listAtt, o.getMonth());
}else{
//--之前月份的可以从三表一册中读取
return mapper.getWorkerAttRecordByMonth(o);
}
}
public boolean isCurrentMonth(String yyyyMM) {
try {
YearMonth input = YearMonth.parse(yyyyMM, DateTimeFormatter.ofPattern("yyyy-MM"));
YearMonth current = YearMonth.now(); // 使用系统默认时区
return input.equals(current);
} catch (Exception e) {
log.error("isCurrentMonth-日期格式错误", e);
return false;
}
}
private List<UserAttendanceVo> dealAttData(List<UserAttendanceVo> listAtt, String lastMonth) {
// 按照 workerId 分组
Map<Integer, List<UserAttendanceVo>> groupedByWorkerId = listAtt.stream()
.collect(Collectors.groupingBy(UserAttendanceVo::getWorkerId));
// 获取上个月的所有日期
List<MapBeanVo> daysOfMonth = generateDaysOfMonth(lastMonth);
// 处理每个员工的考勤数据
// 处理每个员工的考勤数据
// 获取第一条数据作为基础数据
// 处理考勤日数据
// 将处理后的考勤日数据设置到基础数据中
return groupedByWorkerId.entrySet().stream()
.map(entry -> {
Integer workerId = entry.getKey();
List<UserAttendanceVo> workerAttendance = entry.getValue();
// 获取第一条数据作为基础数据
UserAttendanceVo baseData = workerAttendance.get(0);
// 处理考勤日数据
List<WorkerAttDayVo> attendanceDays = processWorkerAttendance(workerAttendance, daysOfMonth);
//计算出勤天数
int attNum = 0;
int repairNum = 0;
double salary = 0.0;
for (WorkerAttDayVo attendanceDay : attendanceDays) {
if("1".equals(attendanceDay.getIsAtt())){
attNum++;
if("1".equals(attendanceDay.getIsRepair())){
repairNum++;
}
}
}
baseData.setAttendanceNum(attNum);
baseData.setRepairNum(repairNum);
baseData.setCheckDay(attNum-repairNum);
JSONArray o = (JSONArray) JSON.toJSON(attendanceDays);
// 将处理后的考勤日数据设置到基础数据中
baseData.setAttendanceDay(JSON.toJSONString(o));
return baseData;
})
.collect(Collectors.toList());
}
/**
* 生成指定年月的所有日期列表
* @param yearMonthString 指定的年月
* @return 日期列表包含 yyyy-MM-dd dd 两个字段的 MapBeanVo
*/
private List<MapBeanVo> generateDaysOfMonth(String yearMonthString) {
List<MapBeanVo> days = new ArrayList<>();
YearMonth yearMonth = YearMonth.parse(yearMonthString, DateTimeFormatter.ofPattern("yyyy-MM"));
LocalDate firstDay = yearMonth.atDay(1);
LocalDate lastDay = yearMonth.atEndOfMonth();
LocalDate currentDate = firstDay;
while (!currentDate.isAfter(lastDay)) {
MapBeanVo dayInfo = new MapBeanVo();
dayInfo.setValue(currentDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
dayInfo.setKey(String.format("%02d", currentDate.getDayOfMonth()));
days.add(dayInfo);
currentDate = currentDate.plusDays(1);
}
return days;
}
/**
* 处理单个员工的考勤数据
* @param attendanceRecords 该员工的考勤记录
* @param daysOfMonth 月份中的所有日期
* @return 处理后的考勤数据列表
*/
private List<WorkerAttDayVo> processWorkerAttendance(List<UserAttendanceVo> attendanceRecords, List<MapBeanVo> daysOfMonth) {
List<WorkerAttDayVo> result = new ArrayList<>();
// 将该员工的考勤记录按日期分组便于快速查找
Map<String, UserAttendanceVo> einByDate = attendanceRecords.stream()
.collect(Collectors.toMap(
UserAttendanceVo::getEinDay,
record -> record,
(existing, replacement) -> existing));
// 遍历月份中的每一天
for (MapBeanVo dayInfo : daysOfMonth) {
String dateStr = dayInfo.getValue();
String dayStr = dayInfo.getKey();
WorkerAttDayVo dayRecord = new WorkerAttDayVo();
dayRecord.setDay(dayStr);
// 查找该日期是否有考勤记录
UserAttendanceVo einForDate = einByDate.get(dateStr);
if (einForDate != null) {
// 存在入场记录
dayRecord.setIsEin("1"); // 在场
// 检查是否有打卡记录
if (einForDate.getAttDay() != null) {
dayRecord.setIsAtt("1"); // 打卡
}else{
dayRecord.setIsAtt("0");
}
// 检查是否有补卡记录
if ("1".equals(einForDate.getIsRepair())) {
dayRecord.setIsRepair("1"); // 补卡
}else {
dayRecord.setIsRepair("0");
}
} else {
// 无考勤记录
dayRecord.setIsEin("0"); // 不在场
dayRecord.setIsAtt("0"); // 未打卡
dayRecord.setIsRepair("0"); // 未补卡
}
result.add(dayRecord);
}
return result;
}
/** /**
* 人员考勤统计 * 人员考勤统计

View File

@ -263,5 +263,55 @@
AND pro_id = #{proId} AND pro_id = #{proId}
AND team_id = #{teamId} AND team_id = #{teamId}
</select> </select>
<select id="getWorkerAttRecordByMonth" resultType="com.bonus.bmw.domain.vo.UserAttendanceVo">
select id,pro_id,`month`,pro_name,month_day,sub_id,sub_name,team_name,user_name,
id_card,work_name,work_id,attendance_day,check_day,repair_num,attendance_num,signature,remark
from
tb_pro_month_table_roster tpmtr
where tpmtr.pro_id = #{proId} and tpmtr.month = #{month}
<if test="subName != null">
and sub_name LIKE CONCAT('%', #{subName}, '%')
</if>
<if test="teamName != null">
and team_name LIKE CONCAT('%', #{teamName}, '%')
</if>
<if test="workerName != null">
and user_name LIKE CONCAT('%', #{workerName}, '%')
</if>
</select>
<select id="getWorkerAttByMonth" resultType="com.bonus.bmw.domain.vo.UserAttendanceVo">
SELECT
d.pro_id,
d.att_month as month,
d.worker_id,
pw.`name` as user_name,
d.id_number as id_card,
d.pro_name,
d.sub_name,
d.team_name,
d.post_name AS work_name,
d.ein_day,
bap.att_day,
bap.is_repair
FROM
bm_worker_ein_day_record d
LEFT JOIN pm_worker pw ON pw.id = d.worker_id
LEFT JOIN bm_att_person bap ON bap.att_day = d.ein_day and bap.pro_id = d.pro_id and bap.worker_id = d.worker_id
LEFT JOIN bm_worker_contract bwc on d.contract_id = bwc.id
WHERE
d.pro_id = #{proId}
AND d.att_month = #{month}
<if test="subName != null">
and d.sub_name LIKE CONCAT('%', #{subName}, '%')
</if>
<if test="teamName != null">
and d.team_name LIKE CONCAT('%', #{teamName}, '%')
</if>
<if test="workerName != null">
and pw.`name` LIKE CONCAT('%', #{workerName}, '%')
</if>
</select>
</mapper> </mapper>