测试考勤:覆盖参训状态签到守卫与真实前端策略
This commit is contained in:
1 parent
e2c15e6216
commit
08b8abe778
2 files changed
+344
-151
No files matched your search
+227
-2
@@ -196,16 +196,18 @@ public class AttendanceActionContractTest
|
||||
lesson.setPlanCourseId(10L);
|
||||
lessons.put(1001L, lesson);
|
||||
|
||||
// 学员 E_A 属于 PLAN_A
|
||||
// 学员 E_A 属于 PLAN_A (1:已报到在训)
|
||||
TrainEnrollment ea = new TrainEnrollment();
|
||||
ea.setEnrollmentId(201L);
|
||||
ea.setPlanId("PLAN_A");
|
||||
ea.setEnrollmentStatus(1);
|
||||
enrollments.put(201L, ea);
|
||||
|
||||
// 学员 E_B 属于 PLAN_B (跨班)
|
||||
// 学员 E_B 属于 PLAN_B (跨班, 1:已报到在训)
|
||||
TrainEnrollment eb = new TrainEnrollment();
|
||||
eb.setEnrollmentId(202L);
|
||||
eb.setPlanId("PLAN_B");
|
||||
eb.setEnrollmentStatus(1);
|
||||
enrollments.put(202L, eb);
|
||||
}
|
||||
|
||||
@@ -594,4 +596,227 @@ public class AttendanceActionContractTest
|
||||
assertEquals(AttendanceErrorCode.LESSON_NOT_FOUND, (int) e.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignInLifecycle_Status0_WaitingReport_Rejected()
|
||||
{
|
||||
// status=0 待报到学员:严禁直接签到绕过报到生命周期
|
||||
TrainEnrollment e0 = new TrainEnrollment();
|
||||
e0.setEnrollmentId(300L);
|
||||
e0.setPlanId("PLAN_A");
|
||||
e0.setEnrollmentStatus(0); // 0: 待报到
|
||||
enrollments.put(300L, e0);
|
||||
|
||||
AttendanceSignInDTO dto = new AttendanceSignInDTO();
|
||||
dto.setEnrollmentId(300L);
|
||||
dto.setLessonId(1001L);
|
||||
|
||||
try
|
||||
{
|
||||
appService.signIn(dto, "admin");
|
||||
fail("待报到学员必须被拦截禁止签到");
|
||||
}
|
||||
catch (ServiceException e)
|
||||
{
|
||||
assertEquals(AttendanceErrorCode.ATTENDANCE_SIGN_IN_REQUIRES_REPORTED_ENROLLMENT, (int) e.getCode());
|
||||
assertEquals(AttendanceErrorCode.ATTENDANCE_SIGN_IN_REQUIRES_REPORTED_ENROLLMENT_MESSAGE, e.getMessage());
|
||||
}
|
||||
// 保证无任何写产生
|
||||
assertNull(checkinsByEnrollLesson.get("300_1001"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignInLifecycle_Status1_Reported_Allowed()
|
||||
{
|
||||
// status=1 已报到学员:允许签到
|
||||
TrainEnrollment e1 = new TrainEnrollment();
|
||||
e1.setEnrollmentId(301L);
|
||||
e1.setPlanId("PLAN_A");
|
||||
e1.setEnrollmentStatus(1); // 1: 已报到
|
||||
enrollments.put(301L, e1);
|
||||
|
||||
AttendanceSignInDTO dto = new AttendanceSignInDTO();
|
||||
dto.setEnrollmentId(301L);
|
||||
dto.setLessonId(1001L);
|
||||
|
||||
TrainStudentCheckin c = appService.signIn(dto, "admin");
|
||||
assertNotNull(c);
|
||||
assertNotNull(c.getSignInTime());
|
||||
assertEquals(Integer.valueOf(1), c.getAttendanceStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignInLifecycle_Status2_Leave_Allowed_PreviewDefault()
|
||||
{
|
||||
// status=2 请假学员:Preview Default 允许签到 (LEAVE_SIGNIN_POLICY: PREVIEW_DEFAULT_ALLOWED)
|
||||
TrainEnrollment e2 = new TrainEnrollment();
|
||||
e2.setEnrollmentId(302L);
|
||||
e2.setPlanId("PLAN_A");
|
||||
e2.setEnrollmentStatus(2); // 2: 请假
|
||||
enrollments.put(302L, e2);
|
||||
|
||||
AttendanceSignInDTO dto = new AttendanceSignInDTO();
|
||||
dto.setEnrollmentId(302L);
|
||||
dto.setLessonId(1001L);
|
||||
|
||||
TrainStudentCheckin c = appService.signIn(dto, "admin");
|
||||
assertNotNull(c);
|
||||
assertNotNull(c.getSignInTime());
|
||||
assertEquals(Integer.valueOf(1), c.getAttendanceStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignInLifecycle_Status3_Abandoned_Rejected()
|
||||
{
|
||||
// status=3 放弃学员:严禁直接签到
|
||||
TrainEnrollment e3 = new TrainEnrollment();
|
||||
e3.setEnrollmentId(303L);
|
||||
e3.setPlanId("PLAN_A");
|
||||
e3.setEnrollmentStatus(3); // 3: 放弃
|
||||
enrollments.put(303L, e3);
|
||||
|
||||
AttendanceSignInDTO dto = new AttendanceSignInDTO();
|
||||
dto.setEnrollmentId(303L);
|
||||
dto.setLessonId(1001L);
|
||||
|
||||
try
|
||||
{
|
||||
appService.signIn(dto, "admin");
|
||||
fail("已放弃学员必须被拦截禁止签到");
|
||||
}
|
||||
catch (ServiceException e)
|
||||
{
|
||||
assertEquals(AttendanceErrorCode.ATTENDANCE_SIGN_IN_ENROLLMENT_ABANDONED, (int) e.getCode());
|
||||
assertEquals(AttendanceErrorCode.ATTENDANCE_SIGN_IN_ENROLLMENT_ABANDONED_MESSAGE, e.getMessage());
|
||||
}
|
||||
assertNull(checkinsByEnrollLesson.get("303_1001"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignInLifecycle_Status4_Completed_Rejected()
|
||||
{
|
||||
// status=4 已完成学员:严禁直接签到
|
||||
TrainEnrollment e4 = new TrainEnrollment();
|
||||
e4.setEnrollmentId(304L);
|
||||
e4.setPlanId("PLAN_A");
|
||||
e4.setEnrollmentStatus(4); // 4: 已完成
|
||||
enrollments.put(304L, e4);
|
||||
|
||||
AttendanceSignInDTO dto = new AttendanceSignInDTO();
|
||||
dto.setEnrollmentId(304L);
|
||||
dto.setLessonId(1001L);
|
||||
|
||||
try
|
||||
{
|
||||
appService.signIn(dto, "admin");
|
||||
fail("已结训学员必须被拦截禁止签到");
|
||||
}
|
||||
catch (ServiceException e)
|
||||
{
|
||||
assertEquals(AttendanceErrorCode.ATTENDANCE_SIGN_IN_ENROLLMENT_COMPLETED, (int) e.getCode());
|
||||
assertEquals(AttendanceErrorCode.ATTENDANCE_SIGN_IN_ENROLLMENT_COMPLETED_MESSAGE, e.getMessage());
|
||||
}
|
||||
assertNull(checkinsByEnrollLesson.get("304_1001"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignInLifecycle_UnknownOrNullStatus_Rejected()
|
||||
{
|
||||
// 未知或 null 参训状态:fail closed 严禁签到
|
||||
TrainEnrollment eNull = new TrainEnrollment();
|
||||
eNull.setEnrollmentId(305L);
|
||||
eNull.setPlanId("PLAN_A");
|
||||
eNull.setEnrollmentStatus(null);
|
||||
enrollments.put(305L, eNull);
|
||||
|
||||
AttendanceSignInDTO dto = new AttendanceSignInDTO();
|
||||
dto.setEnrollmentId(305L);
|
||||
dto.setLessonId(1001L);
|
||||
|
||||
try
|
||||
{
|
||||
appService.signIn(dto, "admin");
|
||||
fail("null 状态学员必须被 fail closed 拦截");
|
||||
}
|
||||
catch (ServiceException e)
|
||||
{
|
||||
assertEquals(AttendanceErrorCode.ATTENDANCE_SIGN_IN_ENROLLMENT_STATUS_INVALID, (int) e.getCode());
|
||||
}
|
||||
|
||||
// 状态 99
|
||||
eNull.setEnrollmentStatus(99);
|
||||
try
|
||||
{
|
||||
appService.signIn(dto, "admin");
|
||||
fail("非法状态 99 学员必须被拦截");
|
||||
}
|
||||
catch (ServiceException e)
|
||||
{
|
||||
assertEquals(AttendanceErrorCode.ATTENDANCE_SIGN_IN_ENROLLMENT_STATUS_INVALID, (int) e.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignInLifecycle_Status4_WithExistingCheckin_IdempotentRetainsFact()
|
||||
{
|
||||
// 场景:历史已经合法签到的学员,后来结训归档变为 status=4。重复调用 signIn 保持幂等返回已有事实,不产生新写
|
||||
TrainEnrollment e4 = new TrainEnrollment();
|
||||
e4.setEnrollmentId(306L);
|
||||
e4.setPlanId("PLAN_A");
|
||||
e4.setEnrollmentStatus(4); // 4: 已完成
|
||||
enrollments.put(306L, e4);
|
||||
|
||||
TrainStudentCheckin historical = new TrainStudentCheckin();
|
||||
historical.setCheckinId(6001L);
|
||||
historical.setEnrollmentId(306L);
|
||||
historical.setLessonId(1001L);
|
||||
Date historicalTime = new Date(System.currentTimeMillis() - 86400000L);
|
||||
historical.setSignInTime(historicalTime);
|
||||
historical.setAttendanceStatus(1);
|
||||
checkinsById.put(6001L, historical);
|
||||
checkinsByEnrollLesson.put("306_1001", historical);
|
||||
|
||||
AttendanceSignInDTO dto = new AttendanceSignInDTO();
|
||||
dto.setEnrollmentId(306L);
|
||||
dto.setLessonId(1001L);
|
||||
|
||||
TrainStudentCheckin returned = appService.signIn(dto, "admin");
|
||||
assertNotNull(returned);
|
||||
assertEquals(Long.valueOf(6001L), returned.getCheckinId());
|
||||
assertEquals(historicalTime, returned.getSignInTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRosterLifecycleEligibility_Status0And4_CannotSignIn_Status1And2_CanSignIn()
|
||||
{
|
||||
// 测试名册对于 status 0, 1, 2, 4 的 canSignIn 权限对齐:
|
||||
// 310 (status=0 待报到), 311 (status=1 已报到), 312 (status=2 请假), 314 (status=4 已完成)
|
||||
enrollments.clear();
|
||||
checkinsById.clear();
|
||||
checkinsByEnrollLesson.clear();
|
||||
|
||||
TrainEnrollment e0 = new TrainEnrollment(); e0.setEnrollmentId(310L); e0.setPlanId("PLAN_A"); e0.setEnrollmentStatus(0); enrollments.put(310L, e0);
|
||||
TrainEnrollment e1 = new TrainEnrollment(); e1.setEnrollmentId(311L); e1.setPlanId("PLAN_A"); e1.setEnrollmentStatus(1); enrollments.put(311L, e1);
|
||||
TrainEnrollment e2 = new TrainEnrollment(); e2.setEnrollmentId(312L); e2.setPlanId("PLAN_A"); e2.setEnrollmentStatus(2); enrollments.put(312L, e2);
|
||||
TrainEnrollment e4 = new TrainEnrollment(); e4.setEnrollmentId(314L); e4.setPlanId("PLAN_A"); e4.setEnrollmentStatus(4); enrollments.put(314L, e4);
|
||||
|
||||
List<com.ruoyi.train.domain.vo.AttendanceLessonRosterVO> roster = appService.getLessonRoster(1001L);
|
||||
assertEquals(4, roster.size());
|
||||
|
||||
com.ruoyi.train.domain.vo.AttendanceLessonRosterVO r0 = roster.stream().filter(r -> r.getEnrollmentId().equals(310L)).findFirst().orElse(null);
|
||||
assertNotNull(r0);
|
||||
assertFalse("status=0 待报到学员名册 canSignIn 必须为 false", Boolean.TRUE.equals(r0.getCanSignIn()));
|
||||
|
||||
com.ruoyi.train.domain.vo.AttendanceLessonRosterVO r1 = roster.stream().filter(r -> r.getEnrollmentId().equals(311L)).findFirst().orElse(null);
|
||||
assertNotNull(r1);
|
||||
assertTrue("status=1 已报到学员名册 canSignIn 必须为 true", Boolean.TRUE.equals(r1.getCanSignIn()));
|
||||
|
||||
com.ruoyi.train.domain.vo.AttendanceLessonRosterVO r2 = roster.stream().filter(r -> r.getEnrollmentId().equals(312L)).findFirst().orElse(null);
|
||||
assertNotNull(r2);
|
||||
assertTrue("status=2 请假学员名册 canSignIn 必须为 true (Preview Default)", Boolean.TRUE.equals(r2.getCanSignIn()));
|
||||
|
||||
com.ruoyi.train.domain.vo.AttendanceLessonRosterVO r4 = roster.stream().filter(r -> r.getEnrollmentId().equals(314L)).findFirst().orElse(null);
|
||||
assertNotNull(r4);
|
||||
assertFalse("status=4 已结训学员名册 canSignIn 必须为 false", Boolean.TRUE.equals(r4.getCanSignIn()));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user