From 70aea4d9e226e32fcd96c39b9b55ae59fbbcb4a4 Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期二, 10 二月 2026 15:48:08 +0800
Subject: [PATCH] 生成缺勤记录
---
src/main/java/com/ruoyi/staff/service/impl/PersonalAttendanceRecordsServiceImpl.java | 246 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 241 insertions(+), 5 deletions(-)
diff --git a/src/main/java/com/ruoyi/staff/service/impl/PersonalAttendanceRecordsServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/PersonalAttendanceRecordsServiceImpl.java
index 1fc363b..bcc3d5d 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/PersonalAttendanceRecordsServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/PersonalAttendanceRecordsServiceImpl.java
@@ -3,21 +3,257 @@
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.staff.mapper.PersonalAttendanceRecordsMapper;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.project.system.domain.SysDept;
+import com.ruoyi.project.system.mapper.SysDeptMapper;
+import com.ruoyi.project.system.service.ISysDictDataService;
+import com.ruoyi.staff.dto.PersonalAttendanceRecordsDto;
+import com.ruoyi.staff.dto.StaffOnJobDto;
+import com.ruoyi.staff.mapper.StaffOnJobMapper;
import com.ruoyi.staff.pojo.PersonalAttendanceRecords;
+import com.ruoyi.staff.mapper.PersonalAttendanceRecordsMapper;
+import com.ruoyi.staff.pojo.StaffOnJob;
import com.ruoyi.staff.service.PersonalAttendanceRecordsService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+
+/**
+ * <p>
+ * 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-02-09 01:20:07
+ */
@Service
public class PersonalAttendanceRecordsServiceImpl extends ServiceImpl<PersonalAttendanceRecordsMapper, PersonalAttendanceRecords> implements PersonalAttendanceRecordsService {
@Autowired
private PersonalAttendanceRecordsMapper personalAttendanceRecordsMapper;
+ @Autowired
+ private StaffOnJobMapper staffOnJobMapper;
+
+ @Autowired
+ private ISysDictDataService dictDataService;
+
+ @Autowired
+ private SysDeptMapper sysDeptMapper;
+
@Override
- public IPage listPage(Page page, PersonalAttendanceRecords personalAttendanceRecords) {
-// return personalAttendanceRecordsMapper.ListPage(page, personalAttendanceRecords);
- return baseMapper.selectPage(page, new QueryWrapper<>(personalAttendanceRecords));
+ @Transactional(rollbackFor = Exception.class)
+ public int add(PersonalAttendanceRecords personalAttendanceRecords) {
+ // 褰撳墠鏃堕棿
+ LocalDate currentDate = LocalDate.now();
+
+ // 棣栧厛鏍规嵁鐢ㄦ埛ID鏌ヨ鍛樺伐淇℃伅
+ QueryWrapper<StaffOnJob> staffQueryWrapper = new QueryWrapper<>();
+ staffQueryWrapper.eq("staff_no", SecurityUtils.getUsername());
+ StaffOnJob staffOnJob = staffOnJobMapper.selectOne(staffQueryWrapper);
+ if (staffOnJob == null) {
+ throw new BaseException("褰撳墠鐢ㄦ埛娌℃湁瀵瑰簲鐨勫憳宸ヤ俊鎭�");
+ }
+
+ // 褰撳墠鏃堕棿
+ LocalDateTime currentDateTime = LocalDateTime.now();
+
+ // 濡傛灉鎵撳崱鏃堕棿瓒呰繃鑰冨嫟涓嬬彮鏃堕棿涓嶈兘鎵撳崱
+ // 鑾峰彇鑰冨嫟涓嬬彮鏃堕棿鐐�
+ String[] timeConfigs = getAttendanceTimeConfig();
+ String timeConfig = timeConfigs[1];
+ String[] timeParts = timeConfig.split(":");
+ int standardHour = Integer.parseInt(timeParts[0]);
+ int standardMinute = Integer.parseInt(timeParts[1]);
+ // 褰撳墠鏃堕棿
+ int actualHour = currentDateTime.getHour();
+ int actualMinute = currentDateTime.getMinute();
+ // 鍒ゆ柇鎵撳崱鏃堕棿鏄惁鏅氫簬褰撳墠鏃堕棿
+ if (actualHour > standardHour || (actualHour == standardHour && actualMinute > standardMinute)) {
+ throw new BaseException("鎵撳崱鏃堕棿涓嶈兘鏅氫簬涓嬬彮鏃堕棿");
+ }
+
+ // 鏍规嵁鍛樺伐ID鍜屽綋鍓嶆棩鏈熸煡璇㈡墦鍗¤褰�
+ QueryWrapper<PersonalAttendanceRecords> attendanceQueryWrapper = new QueryWrapper<>();
+ attendanceQueryWrapper.eq("staff_on_job_id", staffOnJob.getId())
+ .eq("date", currentDate);
+ PersonalAttendanceRecords attendanceRecord = personalAttendanceRecordsMapper.selectOne(attendanceQueryWrapper);
+ // 鏍规嵁瀛楀吀璁剧疆鐨勮�冨嫟鏃堕棿鍒ゆ柇杩熷埌鏃╅��
+ if (attendanceRecord == null) {
+ // 涓嶅瓨鍦ㄦ墦鍗¤褰曪紝鍒涘缓鏂拌褰�
+ personalAttendanceRecords.setStaffOnJobId(staffOnJob.getId());
+ personalAttendanceRecords.setDate(currentDate);
+ personalAttendanceRecords.setWorkStartAt(currentDateTime);
+ personalAttendanceRecords.setStatus(determineAttendanceStatus(personalAttendanceRecords, true));
+ personalAttendanceRecords.setRemark(personalAttendanceRecords.getRemark());
+ personalAttendanceRecords.setTenantId(staffOnJob.getTenantId());
+ return personalAttendanceRecordsMapper.insert(personalAttendanceRecords);
+ } else {
+ if (attendanceRecord.getWorkEndAt() == null) {
+ // 鏇存柊宸ヤ綔缁撴潫鏃堕棿鍜屽伐浣滄椂闀�
+ attendanceRecord.setWorkEndAt(currentDateTime);
+ // 璁$畻宸ヤ綔鏃堕暱锛堢簿纭埌鍒嗛挓锛屼繚鐣�2浣嶅皬鏁帮級
+ LocalDateTime startTime = attendanceRecord.getWorkStartAt();
+ LocalDateTime endTime = attendanceRecord.getWorkEndAt();
+ // 璁$畻涓や釜鏃堕棿涔嬮棿鐨勫垎閽熸暟
+ long totalMinutes = java.time.Duration.between(startTime, endTime).toMinutes();
+ BigDecimal workHours = BigDecimal.valueOf(totalMinutes)
+ .divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP);
+ attendanceRecord.setWorkHours(workHours);
+ // 鏇存柊鑰冨嫟鐘舵��
+ attendanceRecord.setStatus(determineAttendanceStatus(attendanceRecord, false));
+ return personalAttendanceRecordsMapper.updateById(attendanceRecord);
+ } else {
+ throw new BaseException("鎮ㄥ凡缁忔墦杩囧崱浜�,鏃犻渶閲嶅鎵撳崱!!!");
+ }
+ }
+ }
+
+ // 鑾峰彇鑰冨嫟鏃堕棿閰嶇疆
+ private String[] getAttendanceTimeConfig() {
+ String[] timeConfigs = new String[2];
+ try {
+ String dictType = "sys_work_time";
+
+ // 鑾峰彇涓婄彮鏃堕棿閰嶇疆锛岄粯璁や负09:00
+ String startTimeConfig = dictDataService.selectDictLabel(dictType, "start_at");
+ timeConfigs[0] = (startTimeConfig == null || startTimeConfig.trim().isEmpty()) ? "09:00" : startTimeConfig;
+
+ // 鑾峰彇涓嬬彮鏃堕棿閰嶇疆锛岄粯璁や负18:00
+ String endTimeConfig = dictDataService.selectDictLabel(dictType, "end_at");
+ timeConfigs[1] = (endTimeConfig == null || endTimeConfig.trim().isEmpty()) ? "18:00" : endTimeConfig;
+
+ return timeConfigs;
+ } catch (Exception e) {
+ timeConfigs[0] = "09:00"; // 榛樿涓婄彮鏃堕棿
+ timeConfigs[1] = "18:00"; // 榛樿涓嬬彮鏃堕棿
+ return timeConfigs;
+ }
+ }
+
+ // 鏍规嵁瀹為檯鏃堕棿鍜屾槸鍚︿笂鐝椂闂村垽鏂�冨嫟鐘舵��
+ // 0 姝e父 1 杩熷埌 2 鏃╅�� 3 杩熷埌鏃╅�� 4 缂哄嫟
+ private Integer determineAttendanceStatus(PersonalAttendanceRecords attendanceRecord, boolean isStart) {
+ LocalDateTime actualTime = isStart ? attendanceRecord.getWorkStartAt() : attendanceRecord.getWorkEndAt();
+ try {
+ // 鑾峰彇鑰冨嫟鏃堕棿閰嶇疆
+ String[] timeConfigs = getAttendanceTimeConfig();
+ String timeConfig = isStart ? timeConfigs[0] : timeConfigs[1];
+
+ // 瑙f瀽鏍囧噯鏃堕棿
+ String[] timeParts = timeConfig.split(":");
+ int standardHour = Integer.parseInt(timeParts[0]);
+ int standardMinute = Integer.parseInt(timeParts[1]);
+
+ // 鑾峰彇瀹為檯鏃堕棿鐨勬椂鍒�
+ int actualHour = actualTime.getHour();
+ int actualMinute = actualTime.getMinute();
+
+ // 鍒ゆ柇鐘舵��
+ if (isStart) {
+ // 涓婄彮鎵撳崱锛氳秴杩囨爣鍑嗘椂闂寸畻杩熷埌
+ if (actualHour > standardHour || (actualHour == standardHour && actualMinute > standardMinute)) {
+ return 1; // 杩熷埌
+ }
+ } else {
+ // 涓嬬彮鎵撳崱锛氭棭浜庢爣鍑嗘椂闂寸畻鏃╅��
+ if (actualHour < standardHour || (actualHour == standardHour && actualMinute < standardMinute)) {
+ if (attendanceRecord.getStatus() == 1) {
+ return 3; // 杩熷埌鏃╅��
+ }
+ return 2; // 鏃╅��
+ }
+ }
+
+ return 0; // 姝e父
+
+ } catch (Exception e) {
+ // 濡傛灉鑾峰彇閰嶇疆澶辫触锛岄粯璁よ繑鍥炴甯哥姸鎬�
+ log.warn("鑾峰彇鑰冨嫟鏃堕棿閰嶇疆澶辫触锛屼娇鐢ㄩ粯璁ょ姸鎬侊細" + e.getMessage());
+ return 0;
+ }
+ }
+
+ @Override
+ public IPage<PersonalAttendanceRecordsDto> listPage(Page page, PersonalAttendanceRecordsDto personalAttendanceRecordsDto) {
+ boolean admin = SecurityUtils.isAdmin(SecurityUtils.getUserId());
+ if (!admin) {
+ QueryWrapper<StaffOnJob> staffQueryWrapper = new QueryWrapper<>();
+ staffQueryWrapper.eq("staff_no", SecurityUtils.getUsername());
+ StaffOnJob staffOnJob = staffOnJobMapper.selectOne(staffQueryWrapper);
+ if (staffOnJob == null) {
+ return new Page<>(page.getCurrent(), page.getSize(), 0);
+ }
+ personalAttendanceRecordsDto.setStaffOnJobId(staffOnJob.getId());
+ }
+
+ return personalAttendanceRecordsMapper.listPage(page,personalAttendanceRecordsDto);
+ }
+
+ @Override
+ public PersonalAttendanceRecordsDto todayInfo(PersonalAttendanceRecordsDto personalAttendanceRecordsDto) {
+ // 鑾峰彇褰撳墠鏃ユ湡
+ LocalDate currentDate = LocalDate.now();
+
+ // 棣栧厛鏍规嵁鐢ㄦ埛ID鏌ヨ鍛樺伐淇℃伅
+ QueryWrapper<StaffOnJob> staffQueryWrapper = new QueryWrapper<>();
+ staffQueryWrapper.eq("staff_no", SecurityUtils.getUsername());
+ StaffOnJob staffOnJob = staffOnJobMapper.selectOne(staffQueryWrapper);
+
+ if (staffOnJob == null) {
+ return null; // 褰撳墠鐢ㄦ埛娌℃湁瀵瑰簲鐨勫憳宸ヤ俊鎭�
+ }
+
+ // 鏍规嵁鍛樺伐ID鍜屽綋鍓嶆棩鏈熸煡璇㈡墦鍗¤褰�
+ QueryWrapper<PersonalAttendanceRecords> attendanceQueryWrapper = new QueryWrapper<>();
+ attendanceQueryWrapper.eq("staff_on_job_id", staffOnJob.getId())
+ .eq("date", currentDate);
+ PersonalAttendanceRecords attendanceRecord = personalAttendanceRecordsMapper.selectOne(attendanceQueryWrapper);
+
+ // 杩斿洖鍙傛暟
+ PersonalAttendanceRecordsDto resultDto = new PersonalAttendanceRecordsDto();
+
+ if (attendanceRecord != null) {
+ // 濡傛灉鏈夋墦鍗¤褰曪紝澶嶅埗鎵撳崱璁板綍淇℃伅
+ BeanUtils.copyProperties(attendanceRecord, resultDto);
+ }
+
+ // 鍛樺伐鐩稿叧淇℃伅
+ resultDto.setStaffName(staffOnJob.getStaffName());
+ resultDto.setStaffNo(staffOnJob.getStaffNo());
+ resultDto.setDeptId(staffOnJob.getSysDeptId() != null ? staffOnJob.getSysDeptId() : null);
+ SysDept dept = sysDeptMapper.selectDeptById(staffOnJob.getSysDeptId());
+ resultDto.setDeptName(dept != null ? dept.getDeptName() : null);
+
+ return resultDto;
+ }
+
+ @Override
+ public void export(HttpServletResponse response, PersonalAttendanceRecordsDto personalAttendanceRecordsDto) {
+ boolean admin = SecurityUtils.isAdmin(SecurityUtils.getUserId());
+ if (!admin) {
+ QueryWrapper<StaffOnJob> staffQueryWrapper = new QueryWrapper<>();
+ staffQueryWrapper.eq("staff_no", SecurityUtils.getUsername());
+ StaffOnJob staffOnJob = staffOnJobMapper.selectOne(staffQueryWrapper);
+ if (staffOnJob == null) {
+ throw new ServiceException("娌℃湁鍛樺伐淇℃伅锛屾棤娉曞鍑鸿�冨嫟璁板綍");
+ }
+ personalAttendanceRecordsDto.setStaffOnJobId(staffOnJob.getId());
+ }
+ List<PersonalAttendanceRecordsDto> personalAttendanceRecords = personalAttendanceRecordsMapper.listPage(new Page<>(1, Integer.MAX_VALUE), personalAttendanceRecordsDto).getRecords();
+ ExcelUtil<PersonalAttendanceRecordsDto> util = new ExcelUtil<PersonalAttendanceRecordsDto>(PersonalAttendanceRecordsDto.class);
+ util.exportExcel(response, personalAttendanceRecords, "鑰冨嫟璁板綍瀵煎嚭");
}
}
--
Gitblit v1.9.3