完善考勤:支持未签到学员人工登记缺勤
名册中无任何打卡记录的已报到学员此前只能"先签到再改成缺勤",会留下伪造的签到事实。 - 新增 POST /train/attendance/mark-absence,权限 train:attendance:edit,带操作日志 - 写入 attendance_status=0、sign_in_time 与 sign_out_time 保持 NULL、manual_flag=1, 缺勤原因必填,绝不伪造签到时间 - 前置条件全部 fail closed:课次已开始、与课次同属一个开班计划、 参训状态必须恰好为已报到;请假不得被自动改写为缺勤 - 已有考勤记录时拒绝新建并引导改用调整考勤记录, 并发命中唯一索引转为同一业务错误,不泄露数据库异常 - 名册新增 canMarkAbsence,前端直接采用后端判定,登记后可继续调整考勤记录 - 未改动出勤率统计口径与 Analytics 业务策略 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
b7eab13a83
commit
b7a9b89ec5
12 files changed
+1108
-9
No files matched your search
+13
@@ -17,6 +17,7 @@ import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.train.domain.TrainStudentCheckin;
|
||||
import com.ruoyi.train.domain.dto.AttendanceAdjustDTO;
|
||||
import com.ruoyi.train.domain.dto.AttendanceMarkAbsenceDTO;
|
||||
import com.ruoyi.train.domain.dto.AttendanceSignInDTO;
|
||||
import com.ruoyi.train.domain.dto.AttendanceSignOutDTO;
|
||||
import com.ruoyi.train.service.AttendanceAppService;
|
||||
@@ -72,6 +73,18 @@ public class AttendanceController extends BaseController
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 课次缺勤登记 (对名册中无任何打卡事实的学员直接登记缺勤)。
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('train:attendance:edit')")
|
||||
@Log(title = "课次缺勤登记", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/mark-absence")
|
||||
public AjaxResult markAbsence(@Validated @RequestBody AttendanceMarkAbsenceDTO dto)
|
||||
{
|
||||
TrainStudentCheckin checkin = attendanceAppService.markAbsence(dto, SecurityUtils.getUsername());
|
||||
return success(checkin);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询课次学员考勤名册 (纯只读,供培训管理员点名签到)。
|
||||
*/
|
||||
|
||||
+16
-1
@@ -9,7 +9,10 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.train.domain.dto.AttendanceAdjustDTO;
|
||||
import com.ruoyi.train.domain.dto.AttendanceMarkAbsenceDTO;
|
||||
import com.ruoyi.train.domain.dto.AttendanceSignInDTO;
|
||||
import com.ruoyi.train.domain.dto.AttendanceSignOutDTO;
|
||||
import com.ruoyi.train.domain.dto.ReportConfirmDTO;
|
||||
@@ -58,7 +61,19 @@ public class AttendanceAndReportApiControllerContractTest
|
||||
assertEquals("/{checkinId}", putAdjust.value()[0]);
|
||||
assertEquals("@ss.hasPermi('train:attendance:edit')", adjust.getAnnotation(PreAuthorize.class).value());
|
||||
|
||||
// 4. 课次学员考勤名册 (纯只读,供管理员点名签到)
|
||||
// 4. 课次缺勤登记 (对无任何打卡事实的学员直接登记缺勤)
|
||||
Method markAbsence = AttendanceController.class.getMethod("markAbsence", AttendanceMarkAbsenceDTO.class);
|
||||
assertNotNull(markAbsence);
|
||||
PostMapping postMarkAbsence = markAbsence.getAnnotation(PostMapping.class);
|
||||
assertNotNull(postMarkAbsence);
|
||||
assertEquals("/mark-absence", postMarkAbsence.value()[0]);
|
||||
assertEquals("@ss.hasPermi('train:attendance:edit')", markAbsence.getAnnotation(PreAuthorize.class).value());
|
||||
Log markAbsenceLog = markAbsence.getAnnotation(Log.class);
|
||||
assertNotNull(markAbsenceLog);
|
||||
assertEquals("课次缺勤登记", markAbsenceLog.title());
|
||||
assertEquals(BusinessType.INSERT, markAbsenceLog.businessType());
|
||||
|
||||
// 5. 课次学员考勤名册 (纯只读,供管理员点名签到)
|
||||
Method getRoster = AttendanceController.class.getMethod("getLessonRoster", Long.class);
|
||||
assertNotNull(getRoster);
|
||||
GetMapping getRosterAnnotation = getRoster.getAnnotation(GetMapping.class);
|
||||
|
||||
Reference in new issue
Block a user