修复考勤:禁止无签到记录直接签退生成正常出勤

This commit is contained in:
wangzhibiao committed 2026-09-21 21:43:52 +08:00
1 parent 8900dcb101
commit 8df14882cb
2 files changed
+22 -41

No files matched your search

@@ -29,6 +29,14 @@ public final class AttendanceErrorCode
public static final int ATTENDANCE_STATUS_INVALID = 40082;
public static final String ATTENDANCE_STATUS_INVALID_MESSAGE = "考勤状态不合法 (必须在0~4范围内)";
/** 签退前必须先有签到记录,禁止直接签退生成正常出勤 */
public static final int ATTENDANCE_SIGN_IN_REQUIRED_BEFORE_SIGN_OUT = 40083;
public static final String ATTENDANCE_SIGN_IN_REQUIRED_BEFORE_SIGN_OUT_MESSAGE = "签退前必须先有签到记录,禁止直接签退生成正常出勤";
/** 该考勤记录已完成签退,不可重复签退 */
public static final int ATTENDANCE_ALREADY_SIGNED_OUT = 40084;
public static final String ATTENDANCE_ALREADY_SIGNED_OUT_MESSAGE = "该考勤记录已完成签退,不可重复签退";
private AttendanceErrorCode()
{
}
@@ -155,52 +155,25 @@ public class AttendanceAppServiceImpl implements AttendanceAppService
Date signOutTime = dto.getSignOutTime() != null ? dto.getSignOutTime() : new Date();
TrainStudentCheckin existing = trainStudentCheckinMapper.selectTrainStudentCheckinByEnrollmentAndLesson(dto.getEnrollmentId(), dto.getLessonId());
if (existing == null)
if (existing == null || existing.getSignInTime() == null)
{
// 若尚无签到记录,初始化一条考勤记录并记录签退时间
existing = new TrainStudentCheckin();
existing.setEnrollmentId(dto.getEnrollmentId());
existing.setLessonId(dto.getLessonId());
existing.setCheckinWay(1);
existing.setSignOutTime(signOutTime);
existing.setAttendanceStatus(1);
existing.setManualFlag(0);
existing.setCreateBy(operator);
existing.setCreateTime(new Date());
try
{
trainStudentCheckinMapper.insertTrainStudentCheckin(existing);
}
catch (DuplicateKeyException e)
{
existing = trainStudentCheckinMapper.selectTrainStudentCheckinByEnrollmentAndLesson(dto.getEnrollmentId(), dto.getLessonId());
if (existing != null)
{
if (existing.getSignOutTime() != null)
{
return existing;
}
existing.setSignOutTime(signOutTime);
existing.setUpdateBy(operator);
existing.setUpdateTime(new Date());
trainStudentCheckinMapper.updateTrainStudentCheckin(existing);
}
}
// 禁止无签到记录直接签退生成正常出勤记录 (C05)
throw new ServiceException(AttendanceErrorCode.ATTENDANCE_SIGN_IN_REQUIRED_BEFORE_SIGN_OUT_MESSAGE,
AttendanceErrorCode.ATTENDANCE_SIGN_IN_REQUIRED_BEFORE_SIGN_OUT);
}
else
// 重复签退拒绝,禁止默默覆盖历史签退时间 (保留首次签退事实)
if (existing.getSignOutTime() != null)
{
// 若同一 enrollment_id + lesson_id 已经存在非空 sign_out_time:
// 后续重复 sign-out 必须直接返回已有记录,禁止覆盖第一次 sign_out_time。
if (existing.getSignOutTime() != null)
{
return existing;
}
existing.setSignOutTime(signOutTime);
existing.setUpdateBy(operator);
existing.setUpdateTime(new Date());
trainStudentCheckinMapper.updateTrainStudentCheckin(existing);
throw new ServiceException(AttendanceErrorCode.ATTENDANCE_ALREADY_SIGNED_OUT_MESSAGE,
AttendanceErrorCode.ATTENDANCE_ALREADY_SIGNED_OUT);
}
existing.setSignOutTime(signOutTime);
existing.setUpdateBy(operator);
existing.setUpdateTime(new Date());
trainStudentCheckinMapper.updateTrainStudentCheckin(existing);
return existing;
}