测试考勤:覆盖首次签到与未签到展示
This commit is contained in:
1 parent
dfd0133df0
commit
38d4851a18
3 files changed
+336
No files matched your search
+9
@@ -6,6 +6,7 @@ import static org.junit.Assert.assertNotNull;
|
||||
import java.lang.reflect.Method;
|
||||
import org.junit.Test;
|
||||
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.train.domain.dto.AttendanceAdjustDTO;
|
||||
@@ -56,5 +57,13 @@ public class AttendanceAndReportApiControllerContractTest
|
||||
assertNotNull(putAdjust);
|
||||
assertEquals("/{checkinId}", putAdjust.value()[0]);
|
||||
assertEquals("@ss.hasPermi('train:attendance:edit')", adjust.getAnnotation(PreAuthorize.class).value());
|
||||
|
||||
// 4. 课次学员考勤名册 (纯只读,供管理员点名签到)
|
||||
Method getRoster = AttendanceController.class.getMethod("getLessonRoster", Long.class);
|
||||
assertNotNull(getRoster);
|
||||
GetMapping getRosterAnnotation = getRoster.getAnnotation(GetMapping.class);
|
||||
assertNotNull(getRosterAnnotation);
|
||||
assertEquals("/lessons/{lessonId}/roster", getRosterAnnotation.value()[0]);
|
||||
assertEquals("@ss.hasPermi('train:attendance:list')", getRoster.getAnnotation(PreAuthorize.class).value());
|
||||
}
|
||||
}
|
||||
+137
@@ -1,15 +1,20 @@
|
||||
package com.ruoyi.train.service.impl;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -94,6 +99,19 @@ public class AttendanceActionContractTest
|
||||
checkinsByEnrollLesson.put(c.getEnrollmentId() + "_" + c.getLessonId(), c);
|
||||
return 1;
|
||||
}
|
||||
if ("selectCheckinsByLessonId".equals(name))
|
||||
{
|
||||
Long lid = (Long) args[0];
|
||||
List<TrainStudentCheckin> list = new ArrayList<>();
|
||||
for (TrainStudentCheckin c : checkinsById.values())
|
||||
{
|
||||
if (lid.equals(c.getLessonId()))
|
||||
{
|
||||
list.add(c);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
return defaultReturn(method);
|
||||
}
|
||||
});
|
||||
@@ -108,6 +126,28 @@ public class AttendanceActionContractTest
|
||||
{
|
||||
return enrollments.get((Long) args[0]);
|
||||
}
|
||||
if ("selectEnrollmentItemList".equals(name))
|
||||
{
|
||||
com.ruoyi.train.domain.query.EnrollmentQuery q = (com.ruoyi.train.domain.query.EnrollmentQuery) args[0];
|
||||
List<com.ruoyi.train.domain.vo.EnrollmentItemVO> list = new ArrayList<>();
|
||||
for (TrainEnrollment e : enrollments.values())
|
||||
{
|
||||
if (q.getPlanId() != null && q.getPlanId().equals(e.getPlanId()))
|
||||
{
|
||||
com.ruoyi.train.domain.vo.EnrollmentItemVO vo = new com.ruoyi.train.domain.vo.EnrollmentItemVO();
|
||||
vo.setEnrollmentId(e.getEnrollmentId());
|
||||
vo.setPlanId(e.getPlanId());
|
||||
vo.setStudentId(e.getStudentId() != null ? e.getStudentId() : "S_" + e.getEnrollmentId());
|
||||
vo.setStudentName("学员_" + e.getEnrollmentId());
|
||||
vo.setGender("男");
|
||||
vo.setOrgName("电务段");
|
||||
vo.setPhone("13812345678");
|
||||
vo.setEnrollmentStatus(e.getEnrollmentStatus() != null ? e.getEnrollmentStatus() : 1);
|
||||
list.add(vo);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
return defaultReturn(method);
|
||||
}
|
||||
});
|
||||
@@ -457,4 +497,101 @@ public class AttendanceActionContractTest
|
||||
assertEquals(AttendanceErrorCode.ATTENDANCE_STATUS_INVALID, (int) e.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLessonRoster_DistinguishesUncheckedFromAbsent_AndEnablesSignIn()
|
||||
{
|
||||
// 场景:E_A(201)未打卡,新增学员 E_A2(203)属于PLAN_A且有缺勤打卡记录(status=0),学员 E_A3(204)已放弃(status=3)
|
||||
TrainEnrollment ea2 = new TrainEnrollment();
|
||||
ea2.setEnrollmentId(203L);
|
||||
ea2.setPlanId("PLAN_A");
|
||||
ea2.setEnrollmentStatus(1);
|
||||
enrollments.put(203L, ea2);
|
||||
|
||||
TrainEnrollment ea3 = new TrainEnrollment();
|
||||
ea3.setEnrollmentId(204L);
|
||||
ea3.setPlanId("PLAN_A");
|
||||
ea3.setEnrollmentStatus(3); // 已放弃
|
||||
enrollments.put(204L, ea3);
|
||||
|
||||
// 为 ea2 创建一条显式缺勤(attendance_status=0, 无signInTime)
|
||||
TrainStudentCheckin absentCheckin = new TrainStudentCheckin();
|
||||
absentCheckin.setCheckinId(888L);
|
||||
absentCheckin.setEnrollmentId(203L);
|
||||
absentCheckin.setLessonId(1001L);
|
||||
absentCheckin.setAttendanceStatus(0); // 0: 缺勤
|
||||
absentCheckin.setSignInTime(null);
|
||||
checkinsById.put(888L, absentCheckin);
|
||||
checkinsByEnrollLesson.put("203_1001", absentCheckin);
|
||||
|
||||
List<com.ruoyi.train.domain.vo.AttendanceLessonRosterVO> roster = appService.getLessonRoster(1001L);
|
||||
assertNotNull(roster);
|
||||
// 应包含 201 和 203,排除已放弃的 204
|
||||
assertEquals(2, roster.size());
|
||||
|
||||
// 验证学员 201 (无 checkin 记录):
|
||||
com.ruoyi.train.domain.vo.AttendanceLessonRosterVO r201 = roster.stream()
|
||||
.filter(r -> r.getEnrollmentId().equals(201L)).findFirst().orElse(null);
|
||||
assertNotNull(r201);
|
||||
assertNull("无checkin记录的学员,checkinId必须为null", r201.getCheckinId());
|
||||
assertNull("未签到(NO_CHECKIN)绝不能被渲染为0缺勤,必须为null", r201.getAttendanceStatus());
|
||||
assertTrue("未打卡学员必须允许执行首次签到", Boolean.TRUE.equals(r201.getCanSignIn()));
|
||||
assertFalse(Boolean.TRUE.equals(r201.getCanSignOut()));
|
||||
assertFalse(Boolean.TRUE.equals(r201.getCanAdjust()));
|
||||
|
||||
// 验证学员 203 (有缺勤记录):
|
||||
com.ruoyi.train.domain.vo.AttendanceLessonRosterVO r203 = roster.stream()
|
||||
.filter(r -> r.getEnrollmentId().equals(203L)).findFirst().orElse(null);
|
||||
assertNotNull(r203);
|
||||
assertEquals(Long.valueOf(888L), r203.getCheckinId());
|
||||
assertEquals(Integer.valueOf(0), r203.getAttendanceStatus()); // 显式缺勤
|
||||
assertTrue(Boolean.TRUE.equals(r203.getCanSignIn())); // 无signInTime可补签
|
||||
assertTrue(Boolean.TRUE.equals(r203.getCanAdjust())); // 已有记录可调整
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignInThenRosterUpdatesFact_DisablesSignIn()
|
||||
{
|
||||
// 初始未签到
|
||||
List<com.ruoyi.train.domain.vo.AttendanceLessonRosterVO> rosterBefore = appService.getLessonRoster(1001L);
|
||||
com.ruoyi.train.domain.vo.AttendanceLessonRosterVO rBefore = rosterBefore.stream()
|
||||
.filter(r -> r.getEnrollmentId().equals(201L)).findFirst().orElse(null);
|
||||
assertNotNull(rBefore);
|
||||
assertTrue(Boolean.TRUE.equals(rBefore.getCanSignIn()));
|
||||
|
||||
// 执行首次签到
|
||||
AttendanceSignInDTO signInDto = new AttendanceSignInDTO();
|
||||
signInDto.setEnrollmentId(201L);
|
||||
signInDto.setLessonId(1001L);
|
||||
signInDto.setCheckinWay(4); // 代签
|
||||
TrainStudentCheckin created = appService.signIn(signInDto, "train_admin");
|
||||
assertNotNull(created);
|
||||
assertNotNull(created.getCheckinId());
|
||||
|
||||
// 刷新查询 roster
|
||||
List<com.ruoyi.train.domain.vo.AttendanceLessonRosterVO> rosterAfter = appService.getLessonRoster(1001L);
|
||||
com.ruoyi.train.domain.vo.AttendanceLessonRosterVO rAfter = rosterAfter.stream()
|
||||
.filter(r -> r.getEnrollmentId().equals(201L)).findFirst().orElse(null);
|
||||
assertNotNull(rAfter);
|
||||
assertEquals(created.getCheckinId(), rAfter.getCheckinId());
|
||||
assertEquals(Integer.valueOf(1), rAfter.getAttendanceStatus()); // 正常出勤
|
||||
assertNotNull(rAfter.getSignInTime());
|
||||
assertFalse("已成功签到的学员禁止重复执行签到", Boolean.TRUE.equals(rAfter.getCanSignIn()));
|
||||
assertTrue("已签到未签退的学员允许签退", Boolean.TRUE.equals(rAfter.getCanSignOut()));
|
||||
assertTrue(Boolean.TRUE.equals(rAfter.getCanAdjust()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLessonRoster_LessonNotFound_ThrowsException()
|
||||
{
|
||||
try
|
||||
{
|
||||
appService.getLessonRoster(99999L);
|
||||
fail("不存在的课次应当抛出异常");
|
||||
}
|
||||
catch (ServiceException e)
|
||||
{
|
||||
assertEquals(AttendanceErrorCode.LESSON_NOT_FOUND, (int) e.getCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user