修复考勤:原子签退防止并发覆盖首次时间
This commit is contained in:
1 parent
78ea5ce387
commit
579ce861b6
3 files changed
+55
-5
No files matched your search
+15
@@ -64,4 +64,19 @@ public interface TrainStudentCheckinMapper
|
||||
* 查询指定课次的学员考勤打卡流水
|
||||
*/
|
||||
public List<TrainStudentCheckin> selectCheckinsByLessonId(@org.apache.ibatis.annotations.Param("lessonId") Long lessonId);
|
||||
|
||||
/**
|
||||
* 原子条件更新签退时间 (防并发覆盖首次签退事实)
|
||||
* 仅当记录存在、sign_in_time 不为空且 sign_out_time 为空时更新成功
|
||||
*
|
||||
* @param checkinId 打卡记录ID
|
||||
* @param signOutTime 签退时间
|
||||
* @param operator 操作人
|
||||
* @param updateTime 更新时间
|
||||
* @return 影响行数 (1: 成功; 0: 条件不满足或已被签退)
|
||||
*/
|
||||
public int signOutIfUnsigned(@org.apache.ibatis.annotations.Param("checkinId") Long checkinId,
|
||||
@org.apache.ibatis.annotations.Param("signOutTime") java.util.Date signOutTime,
|
||||
@org.apache.ibatis.annotations.Param("operator") String operator,
|
||||
@org.apache.ibatis.annotations.Param("updateTime") java.util.Date updateTime);
|
||||
}
|
||||
+28
-5
@@ -169,12 +169,35 @@ public class AttendanceAppServiceImpl implements AttendanceAppService
|
||||
AttendanceErrorCode.ATTENDANCE_ALREADY_SIGNED_OUT);
|
||||
}
|
||||
|
||||
existing.setSignOutTime(signOutTime);
|
||||
existing.setUpdateBy(operator);
|
||||
existing.setUpdateTime(new Date());
|
||||
trainStudentCheckinMapper.updateTrainStudentCheckin(existing);
|
||||
Date now = new Date();
|
||||
int affectedRows = trainStudentCheckinMapper.signOutIfUnsigned(existing.getCheckinId(), signOutTime, operator, now);
|
||||
if (affectedRows == 1)
|
||||
{
|
||||
existing.setSignOutTime(signOutTime);
|
||||
existing.setUpdateBy(operator);
|
||||
existing.setUpdateTime(now);
|
||||
return existing;
|
||||
}
|
||||
|
||||
return existing;
|
||||
// affectedRows == 0: 重新读取记录并分类报错
|
||||
TrainStudentCheckin latest = trainStudentCheckinMapper.selectTrainStudentCheckinByCheckinId(existing.getCheckinId());
|
||||
if (latest == null)
|
||||
{
|
||||
throw new ServiceException(AttendanceErrorCode.ATTENDANCE_NOT_FOUND_MESSAGE, AttendanceErrorCode.ATTENDANCE_NOT_FOUND);
|
||||
}
|
||||
if (latest.getSignInTime() == null)
|
||||
{
|
||||
throw new ServiceException(AttendanceErrorCode.ATTENDANCE_SIGN_IN_REQUIRED_BEFORE_SIGN_OUT_MESSAGE,
|
||||
AttendanceErrorCode.ATTENDANCE_SIGN_IN_REQUIRED_BEFORE_SIGN_OUT);
|
||||
}
|
||||
if (latest.getSignOutTime() != null)
|
||||
{
|
||||
throw new ServiceException(AttendanceErrorCode.ATTENDANCE_ALREADY_SIGNED_OUT_MESSAGE,
|
||||
AttendanceErrorCode.ATTENDANCE_ALREADY_SIGNED_OUT);
|
||||
}
|
||||
|
||||
throw new ServiceException(AttendanceErrorCode.ATTENDANCE_ALREADY_SIGNED_OUT_MESSAGE,
|
||||
AttendanceErrorCode.ATTENDANCE_ALREADY_SIGNED_OUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -102,4 +102,16 @@
|
||||
where a.lesson_id = #{lessonId}
|
||||
order by s.s_name asc, a.checkin_id asc
|
||||
</select>
|
||||
|
||||
<!-- 原子条件更新签退时间 (首次签退事实不可覆盖) -->
|
||||
<update id="signOutIfUnsigned">
|
||||
update train_student_checkin
|
||||
set
|
||||
sign_out_time = #{signOutTime},
|
||||
update_by = #{operator},
|
||||
update_time = #{updateTime}
|
||||
where checkin_id = #{checkinId}
|
||||
and sign_in_time is not null
|
||||
and sign_out_time is null
|
||||
</update>
|
||||
</mapper>
|
||||
Reference in new issue
Block a user