修复排课:停用教师禁止新排课并消除候选列表静默截断
停用教师仍出现在排课教师下拉且后端未校验 status;教师、教室、场地候选统一按 pageSize=100 拉取,数量超过 100 时会静默丢失合法候选。 - 后端在创建课次时强制校验目标教师在岗,修改课次仅在真的更换授课教师时校验, 维持原教师不变的历史课次继续放行,既不自动删除课次也不自动替换教师 - 新增业务错误文案"该教师当前已停用,不能安排新的授课任务",不暴露内部状态码 - 新增只读端点 GET /train/lessons/scheduling-options 全量返回教师、教室、场地候选, 不分页、服务端无条数上限;教师候选只返回在岗有效教师,且只下发下拉必需字段 - 前端排课面板改用该端点,编辑历史课次时为已停用的原教师补一条禁用选项, 保证原教师名可见但不可被重新选中 - 排课冲突策略不变,仍为前端 Warning 加二次确认后允许保存 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
dc3990b29a
commit
eb8ce6f85c
10 files changed
+1024
-23
No files matched your search
+11
@@ -82,6 +82,17 @@ public class TrainLessonController extends BaseController
|
||||
return success(schedulingAppService.checkConflict(dto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取排课候选资源选项 (教师 / 教室 / 实训场地)。
|
||||
* 排课表单下拉专用只读接口,一次性全量返回,不分页也不设条数上限。
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('train:lesson:query')")
|
||||
@GetMapping("/train/lessons/scheduling-options")
|
||||
public AjaxResult getSchedulingOptions()
|
||||
{
|
||||
return success(schedulingAppService.getSchedulingOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取计划完整课程表聚合 (UC-11 / 编辑回显必需)。
|
||||
*/
|
||||
|
||||
+9
-2
@@ -56,6 +56,12 @@ public class TrainLessonControllerTest
|
||||
assertNotNull(timetable.getAnnotation(GetMapping.class));
|
||||
assertEquals("/train/plans/{planId}/timetable", timetable.getAnnotation(GetMapping.class).value()[0]);
|
||||
assertEquals("@ss.hasPermi('train:plan:query')", timetable.getAnnotation(PreAuthorize.class).value());
|
||||
|
||||
// 6. 排课候选资源选项 (教师/教室/实训场地全量只读,不分页)
|
||||
Method options = TrainLessonController.class.getMethod("getSchedulingOptions");
|
||||
assertNotNull(options.getAnnotation(GetMapping.class));
|
||||
assertEquals("/train/lessons/scheduling-options", options.getAnnotation(GetMapping.class).value()[0]);
|
||||
assertEquals("@ss.hasPermi('train:lesson:query')", options.getAnnotation(PreAuthorize.class).value());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -90,7 +96,7 @@ public class TrainLessonControllerTest
|
||||
}
|
||||
|
||||
@Test
|
||||
public void controllerMustOnlyExposeFrozenFiveEndpoints()
|
||||
public void controllerMustOnlyExposeFrozenSixEndpoints()
|
||||
{
|
||||
int endpointCount = 0;
|
||||
for (Method method : TrainLessonController.class.getDeclaredMethods())
|
||||
@@ -104,6 +110,7 @@ public class TrainLessonControllerTest
|
||||
endpointCount++;
|
||||
}
|
||||
}
|
||||
assertEquals("Controller 必须不多不少正好暴露 5 个冻结端点", 5, endpointCount);
|
||||
// 5 个原冻结端点 + 1 个排课候选资源选项只读端点
|
||||
assertEquals("Controller 必须不多不少正好暴露 6 个冻结端点", 6, endpointCount);
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,9 @@ public final class LessonErrorCode
|
||||
/** 排课场地配置不合法:普通教室与实训场地必须二选一 */
|
||||
public static final int VENUE_CONFIG_INVALID = 40045;
|
||||
|
||||
/** 授课教师已停用:不能被指派新的授课任务 */
|
||||
public static final int TEACHER_DISABLED = 40046;
|
||||
|
||||
/** 排课课次不存在 */
|
||||
public static final int LESSON_NOT_FOUND = 40440;
|
||||
|
||||
@@ -46,6 +49,7 @@ public final class LessonErrorCode
|
||||
public static final String VENUE_CONFIG_INVALID_MESSAGE = "排课场地配置不合法:普通教室与实训场地必须二选一";
|
||||
public static final String LESSON_NOT_FOUND_MESSAGE = "排课课次不存在";
|
||||
public static final String TEACHER_NOT_FOUND_MESSAGE = "授课教师不存在或已无效";
|
||||
public static final String TEACHER_DISABLED_MESSAGE = "该教师当前已停用,不能安排新的授课任务";
|
||||
public static final String CLASSROOM_NOT_FOUND_MESSAGE = "教学教室不存在或已无效";
|
||||
public static final String SITE_NOT_FOUND_MESSAGE = "实训场地不存在或已无效";
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.ruoyi.train.service;
|
||||
|
||||
import java.util.Map;
|
||||
import com.ruoyi.train.domain.dto.LessonCreateDTO;
|
||||
import com.ruoyi.train.domain.dto.LessonConflictCheckDTO;
|
||||
import com.ruoyi.train.domain.dto.LessonUpdateDTO;
|
||||
@@ -55,4 +56,12 @@ public interface SchedulingAppService
|
||||
* @return 完整课程表 VO
|
||||
*/
|
||||
PlanTimetableVO getPlanTimetable(String planId);
|
||||
|
||||
/**
|
||||
* 获取排课候选资源选项 (教师 / 教室 / 实训场地)。
|
||||
* 供排课表单下拉一次性全量加载,服务端不做分页与任何隐式条数上限。
|
||||
*
|
||||
* @return 候选资源集合,键为 teachers / classrooms / sites
|
||||
*/
|
||||
Map<String, Object> getSchedulingOptions();
|
||||
}
|
||||
+136
-4
@@ -35,8 +35,11 @@ import com.ruoyi.train.domain.vo.PlanTimetableVO;
|
||||
import com.ruoyi.train.domain.vo.TimetableDayVO;
|
||||
import com.ruoyi.train.domain.vo.TimetableLessonItemVO;
|
||||
import com.ruoyi.train.mapper.TrainClassPlanMapper;
|
||||
import com.ruoyi.train.mapper.TrainClassroomInfoMapper;
|
||||
import com.ruoyi.train.mapper.TrainLessonMapper;
|
||||
import com.ruoyi.train.mapper.TrainPlanCourseMapper;
|
||||
import com.ruoyi.train.mapper.TrainTeacherMapper;
|
||||
import com.ruoyi.train.mapper.TrainTrainingSiteMapper;
|
||||
import com.ruoyi.train.service.SchedulingAppService;
|
||||
|
||||
/**
|
||||
@@ -52,15 +55,24 @@ public class SchedulingAppServiceImpl implements SchedulingAppService
|
||||
private final TrainLessonMapper trainLessonMapper;
|
||||
private final TrainClassPlanMapper trainClassPlanMapper;
|
||||
private final TrainPlanCourseMapper trainPlanCourseMapper;
|
||||
private final TrainTeacherMapper trainTeacherMapper;
|
||||
private final TrainClassroomInfoMapper trainClassroomInfoMapper;
|
||||
private final TrainTrainingSiteMapper trainTrainingSiteMapper;
|
||||
|
||||
@Autowired
|
||||
public SchedulingAppServiceImpl(TrainLessonMapper trainLessonMapper,
|
||||
TrainClassPlanMapper trainClassPlanMapper,
|
||||
TrainPlanCourseMapper trainPlanCourseMapper)
|
||||
TrainPlanCourseMapper trainPlanCourseMapper,
|
||||
TrainTeacherMapper trainTeacherMapper,
|
||||
TrainClassroomInfoMapper trainClassroomInfoMapper,
|
||||
TrainTrainingSiteMapper trainTrainingSiteMapper)
|
||||
{
|
||||
this.trainLessonMapper = trainLessonMapper;
|
||||
this.trainClassPlanMapper = trainClassPlanMapper;
|
||||
this.trainPlanCourseMapper = trainPlanCourseMapper;
|
||||
this.trainTeacherMapper = trainTeacherMapper;
|
||||
this.trainClassroomInfoMapper = trainClassroomInfoMapper;
|
||||
this.trainTrainingSiteMapper = trainTrainingSiteMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,7 +97,10 @@ public class SchedulingAppServiceImpl implements SchedulingAppService
|
||||
{
|
||||
lockKeys.add(new ResourceLockKey("2_SITE", dto.getSiteId()));
|
||||
}
|
||||
lockPhysicalResources(lockKeys);
|
||||
Map<String, TrainTeacher> lockedTeachers = lockPhysicalResources(lockKeys);
|
||||
|
||||
// 2.1 在岗校验:新排课次必须指派在岗教师,已停用教师不得承接新的授课任务
|
||||
assertTeacherAvailableForNewAssignment(lockedTeachers.get(dto.getTId()));
|
||||
|
||||
// 3. 落库新增课次 (排课冲突属于 Warning 告警级别,由 check-conflict 预检供管理员决策,不强制阻断入库)
|
||||
TrainLesson lesson = new TrainLesson();
|
||||
@@ -159,7 +174,15 @@ public class SchedulingAppServiceImpl implements SchedulingAppService
|
||||
lockKeys.add(new ResourceLockKey("2_SITE", dto.getSiteId()));
|
||||
}
|
||||
|
||||
lockPhysicalResources(lockKeys);
|
||||
Map<String, TrainTeacher> lockedTeachers = lockPhysicalResources(lockKeys);
|
||||
|
||||
// 3.1 在岗校验:仅当本次修改真的更换了授课教师时才要求新教师在岗。
|
||||
// 维持原教师不变的历史课次必须放行,否则教师停用后其名下课次将再也无法调整时间与场地,
|
||||
// 系统既不会自动删除课次,也不会自动替换授课教师。
|
||||
if (!Objects.equals(existingLesson.getTId(), dto.getTId()))
|
||||
{
|
||||
assertTeacherAvailableForNewAssignment(lockedTeachers.get(dto.getTId()));
|
||||
}
|
||||
|
||||
// 4. 更新课次 (排课冲突属于 Warning 告警级别,由 check-conflict 预检供管理员决策,不强制阻断更新)
|
||||
existingLesson.setPlanCourseId(dto.getPlanCourseId());
|
||||
@@ -363,6 +386,95 @@ public class SchedulingAppServiceImpl implements SchedulingAppService
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取排课候选资源选项 (教师 / 教室 / 实训场地)。
|
||||
* 一次性全量返回,不分页、不设条数上限,避免下拉候选被静默截断。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Map<String, Object> getSchedulingOptions()
|
||||
{
|
||||
Map<String, Object> options = new LinkedHashMap<>();
|
||||
options.put("teachers", buildTeacherOptions());
|
||||
options.put("classrooms", buildClassroomOptions());
|
||||
options.put("sites", buildSiteOptions());
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装教师候选:仅在岗有效教师 (status=1,Mapper 内置 del_flag='0' 过滤)。
|
||||
* 只下发下拉必需字段,手机号 / 邮箱等敏感信息一律不出网。
|
||||
*/
|
||||
private List<Map<String, Object>> buildTeacherOptions()
|
||||
{
|
||||
TrainTeacher query = new TrainTeacher();
|
||||
query.setStatus(1);
|
||||
List<TrainTeacher> teachers = trainTeacherMapper.selectTrainTeacherList(query);
|
||||
|
||||
List<Map<String, Object>> list = new ArrayList<>();
|
||||
if (teachers == null)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
for (TrainTeacher teacher : teachers)
|
||||
{
|
||||
Map<String, Object> item = new LinkedHashMap<>();
|
||||
item.put("tId", teacher.gettId());
|
||||
item.put("tName", teacher.gettName());
|
||||
item.put("orgName", teacher.getOrgName());
|
||||
list.add(item);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装普通教室候选 (沿用 del_flag='0' 语义,不额外收紧启用状态过滤)。
|
||||
*/
|
||||
private List<Map<String, Object>> buildClassroomOptions()
|
||||
{
|
||||
List<TrainClassroomInfo> classrooms = trainClassroomInfoMapper.selectTrainClassroomInfoList(new TrainClassroomInfo());
|
||||
|
||||
List<Map<String, Object>> list = new ArrayList<>();
|
||||
if (classrooms == null)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
for (TrainClassroomInfo classroom : classrooms)
|
||||
{
|
||||
Map<String, Object> item = new LinkedHashMap<>();
|
||||
item.put("classRoomId", classroom.getClassRoomId());
|
||||
item.put("roomName", classroom.getRoomName());
|
||||
item.put("roomLocation", classroom.getRoomLocation());
|
||||
item.put("capacity", classroom.getCapacity());
|
||||
list.add(item);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装实训场地候选 (沿用 del_flag='0' 语义,不额外收紧启用状态过滤)。
|
||||
*/
|
||||
private List<Map<String, Object>> buildSiteOptions()
|
||||
{
|
||||
List<TrainTrainingSite> sites = trainTrainingSiteMapper.selectTrainTrainingSiteList(new TrainTrainingSite());
|
||||
|
||||
List<Map<String, Object>> list = new ArrayList<>();
|
||||
if (sites == null)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
for (TrainTrainingSite site : sites)
|
||||
{
|
||||
Map<String, Object> item = new LinkedHashMap<>();
|
||||
item.put("siteId", site.getSiteId());
|
||||
item.put("siteName", site.getSiteName());
|
||||
item.put("siteLocation", site.getSiteLocation());
|
||||
item.put("capacity", site.getCapacity());
|
||||
list.add(item);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 基础规则验证。
|
||||
*/
|
||||
@@ -434,12 +546,16 @@ public class SchedulingAppServiceImpl implements SchedulingAppService
|
||||
|
||||
/**
|
||||
* 锁定稳定物理主资源行 (按字典序排序加锁杜绝死锁)。
|
||||
*
|
||||
* @param keys 待加锁的资源键集合
|
||||
* @return 已锁定的教师行,键为教师工号 (供调用方按新旧教师差异做在岗校验)
|
||||
*/
|
||||
private void lockPhysicalResources(Set<ResourceLockKey> keys)
|
||||
private Map<String, TrainTeacher> lockPhysicalResources(Set<ResourceLockKey> keys)
|
||||
{
|
||||
List<ResourceLockKey> sortedKeys = new ArrayList<>(keys);
|
||||
Collections.sort(sortedKeys);
|
||||
|
||||
Map<String, TrainTeacher> lockedTeachers = new LinkedHashMap<>();
|
||||
for (ResourceLockKey key : sortedKeys)
|
||||
{
|
||||
if ("1_TEACHER".equals(key.resourceType))
|
||||
@@ -450,6 +566,7 @@ public class SchedulingAppServiceImpl implements SchedulingAppService
|
||||
throw new ServiceException(LessonErrorCode.TEACHER_NOT_FOUND_MESSAGE,
|
||||
LessonErrorCode.TEACHER_NOT_FOUND);
|
||||
}
|
||||
lockedTeachers.put(key.resourceId, teacher);
|
||||
}
|
||||
else if ("2_CLASSROOM".equals(key.resourceType))
|
||||
{
|
||||
@@ -470,6 +587,21 @@ public class SchedulingAppServiceImpl implements SchedulingAppService
|
||||
}
|
||||
}
|
||||
}
|
||||
return lockedTeachers;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验教师可以承接新的授课安排 (已停用教师禁止被指派新课次)。
|
||||
*
|
||||
* @param teacher 已锁定的教师主档行
|
||||
*/
|
||||
private void assertTeacherAvailableForNewAssignment(TrainTeacher teacher)
|
||||
{
|
||||
if (teacher != null && teacher.getStatus() != null && teacher.getStatus() == 0)
|
||||
{
|
||||
throw new ServiceException(LessonErrorCode.TEACHER_DISABLED_MESSAGE,
|
||||
LessonErrorCode.TEACHER_DISABLED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-1
@@ -457,7 +457,8 @@ public class CoreBusinessScenarioMockTest
|
||||
setField(enrollmentAppService, "planMapper", planMapper);
|
||||
setField(enrollmentAppService, "studentMapper", studentMapper);
|
||||
|
||||
schedulingAppService = new SchedulingAppServiceImpl(lessonMapper, planMapper, planCourseMapper);
|
||||
// 本用例不涉及排课候选项查询,故候选项相关 Mapper 不参与
|
||||
schedulingAppService = new SchedulingAppServiceImpl(lessonMapper, planMapper, planCourseMapper, null, null, null);
|
||||
|
||||
boardService = new TrainElectronicBoardServiceImpl();
|
||||
setField(boardService, "trainElectronicBoardMapper", boardMapper);
|
||||
|
||||
+4
-3
@@ -73,7 +73,8 @@ public class SchedulingAppServiceTest
|
||||
lessonMapper = new MockLessonMapper();
|
||||
planMapper = new MockPlanMapper();
|
||||
planCourseMapper = new MockPlanCourseMapper();
|
||||
appService = new SchedulingAppServiceImpl(lessonMapper, planMapper, planCourseMapper);
|
||||
// 本用例只覆盖排课核心能力,不涉及排课候选项查询,故候选项相关 Mapper 不参与
|
||||
appService = new SchedulingAppServiceImpl(lessonMapper, planMapper, planCourseMapper, null, null, null);
|
||||
|
||||
// 初始化培训计划
|
||||
TrainClassPlan plan = new TrainClassPlan();
|
||||
@@ -96,7 +97,7 @@ public class SchedulingAppServiceTest
|
||||
teacher.settId(TEACHER_ID);
|
||||
teacher.settName("李建国");
|
||||
teacher.setDelFlag("0");
|
||||
teacher.setStatus(0);
|
||||
teacher.setStatus(1); // 1=正常在岗
|
||||
lessonMapper.teachers.put(TEACHER_ID, teacher);
|
||||
|
||||
// 初始化教室
|
||||
@@ -533,7 +534,7 @@ public class SchedulingAppServiceTest
|
||||
t2.settId("T002");
|
||||
t2.settName("王教授");
|
||||
t2.setDelFlag("0");
|
||||
t2.setStatus(0);
|
||||
t2.setStatus(1); // 1=正常在岗
|
||||
lessonMapper.teachers.put("T002", t2);
|
||||
|
||||
TrainClassroomInfo cr2 = new TrainClassroomInfo();
|
||||
|
||||
+811
@@ -0,0 +1,811 @@
|
||||
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.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.train.constant.LessonErrorCode;
|
||||
import com.ruoyi.train.domain.TrainClassPlan;
|
||||
import com.ruoyi.train.domain.TrainClassroomInfo;
|
||||
import com.ruoyi.train.domain.TrainLesson;
|
||||
import com.ruoyi.train.domain.TrainPlanCourse;
|
||||
import com.ruoyi.train.domain.TrainTeacher;
|
||||
import com.ruoyi.train.domain.TrainTrainingSite;
|
||||
import com.ruoyi.train.domain.dto.LessonCreateDTO;
|
||||
import com.ruoyi.train.domain.dto.LessonUpdateDTO;
|
||||
import com.ruoyi.train.domain.query.PlanQuery;
|
||||
import com.ruoyi.train.domain.vo.ConflictItemVO;
|
||||
import com.ruoyi.train.domain.vo.PlanCourseItemVO;
|
||||
import com.ruoyi.train.domain.vo.PlanItemVO;
|
||||
import com.ruoyi.train.domain.vo.TimetableLessonItemVO;
|
||||
import com.ruoyi.train.mapper.TrainClassPlanMapper;
|
||||
import com.ruoyi.train.mapper.TrainClassroomInfoMapper;
|
||||
import com.ruoyi.train.mapper.TrainLessonMapper;
|
||||
import com.ruoyi.train.mapper.TrainPlanCourseMapper;
|
||||
import com.ruoyi.train.mapper.TrainTeacherMapper;
|
||||
import com.ruoyi.train.mapper.TrainTrainingSiteMapper;
|
||||
|
||||
/**
|
||||
* 停用教师排课守卫与排课候选项契约测试。
|
||||
*
|
||||
* <p>覆盖两条业务约定:
|
||||
* 1) 已停用教师不得承接新的授课安排,但其名下历史课次仍可继续维护,系统不自动删课、不自动换人;
|
||||
* 2) 排课候选项为全量只读接口,仅返回在岗教师且不存在任何隐式条数上限。</p>
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class SchedulingTeacherStatusAndOptionsTest
|
||||
{
|
||||
private MockLessonMapper lessonMapper;
|
||||
private MockPlanMapper planMapper;
|
||||
private MockPlanCourseMapper planCourseMapper;
|
||||
private MockTeacherMapper teacherMapper;
|
||||
private MockClassroomMapper classroomMapper;
|
||||
private MockSiteMapper siteMapper;
|
||||
private SchedulingAppServiceImpl appService;
|
||||
|
||||
private static final String PLAN_ID = "PLAN-2026-100";
|
||||
private static final Long PLAN_COURSE_ID = 501L;
|
||||
/** 在岗教师 (status=1) */
|
||||
private static final String ACTIVE_TEACHER_ID = "T_ACTIVE";
|
||||
/** 已停用教师 (status=0) */
|
||||
private static final String DISABLED_TEACHER_ID = "T_DISABLED";
|
||||
/** 另一名已停用教师 (status=0) */
|
||||
private static final String OTHER_DISABLED_TEACHER_ID = "T_DISABLED_2";
|
||||
private static final String CLASSROOM_ID = "CR100";
|
||||
|
||||
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
lessonMapper = new MockLessonMapper();
|
||||
planMapper = new MockPlanMapper();
|
||||
planCourseMapper = new MockPlanCourseMapper();
|
||||
teacherMapper = new MockTeacherMapper();
|
||||
classroomMapper = new MockClassroomMapper();
|
||||
siteMapper = new MockSiteMapper();
|
||||
appService = new SchedulingAppServiceImpl(lessonMapper, planMapper, planCourseMapper,
|
||||
teacherMapper, classroomMapper, siteMapper);
|
||||
|
||||
TrainClassPlan plan = new TrainClassPlan();
|
||||
plan.setPlanId(PLAN_ID);
|
||||
plan.setPlanName("2026接触网检修专项班");
|
||||
plan.setStartTime(sdf.parse("2026-11-01 00:00:00"));
|
||||
plan.setEndTime(sdf.parse("2026-11-30 23:59:59"));
|
||||
plan.setPlanStatus(1);
|
||||
planMapper.plans.put(PLAN_ID, plan);
|
||||
|
||||
TrainPlanCourse planCourse = new TrainPlanCourse();
|
||||
planCourse.setPlanCourseId(PLAN_COURSE_ID);
|
||||
planCourse.setPlanId(PLAN_ID);
|
||||
planCourseMapper.planCourses.put(PLAN_COURSE_ID, planCourse);
|
||||
|
||||
lessonMapper.teachers.put(ACTIVE_TEACHER_ID, buildTeacher(ACTIVE_TEACHER_ID, "赵在岗", 1));
|
||||
lessonMapper.teachers.put(DISABLED_TEACHER_ID, buildTeacher(DISABLED_TEACHER_ID, "钱已停用", 0));
|
||||
lessonMapper.teachers.put(OTHER_DISABLED_TEACHER_ID, buildTeacher(OTHER_DISABLED_TEACHER_ID, "孙已停用", 0));
|
||||
|
||||
TrainClassroomInfo classroom = new TrainClassroomInfo();
|
||||
classroom.setClassRoomId(CLASSROOM_ID);
|
||||
classroom.setRoomName("第一实训教室");
|
||||
classroom.setDelFlag("0");
|
||||
lessonMapper.classrooms.put(CLASSROOM_ID, classroom);
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 停用教师禁止被指派新课次。
|
||||
*/
|
||||
@Test
|
||||
public void testCreateLessonRejectedForDisabledTeacher() throws Exception
|
||||
{
|
||||
LessonCreateDTO dto = buildCreateDTO(DISABLED_TEACHER_ID,
|
||||
"2026-11-10 09:00:00", "2026-11-10 11:00:00");
|
||||
|
||||
try
|
||||
{
|
||||
appService.createLesson(PLAN_ID, dto, "admin");
|
||||
fail("停用教师新建课次应被拒绝");
|
||||
}
|
||||
catch (ServiceException e)
|
||||
{
|
||||
assertEquals(LessonErrorCode.TEACHER_DISABLED, e.getCode().intValue());
|
||||
assertEquals("该教师当前已停用,不能安排新的授课任务", e.getMessage());
|
||||
}
|
||||
|
||||
// 拒绝后不得残留任何课次
|
||||
assertTrue(lessonMapper.lessons.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* 2. 在岗教师正常新建课次。
|
||||
*/
|
||||
@Test
|
||||
public void testCreateLessonSucceedsForActiveTeacher() throws Exception
|
||||
{
|
||||
LessonCreateDTO dto = buildCreateDTO(ACTIVE_TEACHER_ID,
|
||||
"2026-11-10 09:00:00", "2026-11-10 11:00:00");
|
||||
|
||||
Long lessonId = appService.createLesson(PLAN_ID, dto, "admin");
|
||||
assertNotNull(lessonId);
|
||||
assertEquals(ACTIVE_TEACHER_ID, lessonMapper.lessons.get(lessonId).getTId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 3. 停用教师名下历史课次:不换教师时必须允许继续调整时间与教室。
|
||||
*/
|
||||
@Test
|
||||
public void testUpdateLessonKeepsDisabledTeacherAllowed() throws Exception
|
||||
{
|
||||
Long lessonId = 900L;
|
||||
addExistingLesson(lessonId, DISABLED_TEACHER_ID, "2026-11-12 09:00:00", "2026-11-12 11:00:00");
|
||||
|
||||
LessonUpdateDTO dto = new LessonUpdateDTO();
|
||||
dto.setPlanCourseId(PLAN_COURSE_ID);
|
||||
dto.setTId(DISABLED_TEACHER_ID); // 维持原教师不变
|
||||
dto.setStartTime(sdf.parse("2026-11-12 14:00:00"));
|
||||
dto.setEndTime(sdf.parse("2026-11-12 16:00:00"));
|
||||
dto.setVenueType(1);
|
||||
dto.setClassRoomId(CLASSROOM_ID);
|
||||
dto.setRemark("教师停用后仍可正常调整上课时间");
|
||||
|
||||
appService.updateLesson(lessonId, dto, "admin");
|
||||
|
||||
TrainLesson updated = lessonMapper.lessons.get(lessonId);
|
||||
assertNotNull("历史课次不得被自动删除", updated);
|
||||
assertEquals("历史课次不得被自动换教师", DISABLED_TEACHER_ID, updated.getTId());
|
||||
assertEquals(sdf.parse("2026-11-12 14:00:00"), updated.getStartTime());
|
||||
assertEquals(sdf.parse("2026-11-12 16:00:00"), updated.getEndTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 4. 历史课次改派给另一名已停用教师:必须拒绝。
|
||||
*/
|
||||
@Test
|
||||
public void testUpdateLessonRejectedWhenSwitchingToDisabledTeacher() throws Exception
|
||||
{
|
||||
Long lessonId = 901L;
|
||||
addExistingLesson(lessonId, ACTIVE_TEACHER_ID, "2026-11-13 09:00:00", "2026-11-13 11:00:00");
|
||||
|
||||
LessonUpdateDTO dto = new LessonUpdateDTO();
|
||||
dto.setPlanCourseId(PLAN_COURSE_ID);
|
||||
dto.setTId(OTHER_DISABLED_TEACHER_ID); // 改派给另一名停用教师
|
||||
dto.setStartTime(sdf.parse("2026-11-13 09:00:00"));
|
||||
dto.setEndTime(sdf.parse("2026-11-13 11:00:00"));
|
||||
dto.setVenueType(1);
|
||||
dto.setClassRoomId(CLASSROOM_ID);
|
||||
|
||||
try
|
||||
{
|
||||
appService.updateLesson(lessonId, dto, "admin");
|
||||
fail("改派给停用教师应被拒绝");
|
||||
}
|
||||
catch (ServiceException e)
|
||||
{
|
||||
assertEquals(LessonErrorCode.TEACHER_DISABLED, e.getCode().intValue());
|
||||
assertEquals("该教师当前已停用,不能安排新的授课任务", e.getMessage());
|
||||
}
|
||||
|
||||
// 原教师保持不变
|
||||
assertEquals(ACTIVE_TEACHER_ID, lessonMapper.lessons.get(lessonId).getTId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 5. 排课候选项:仅返回在岗教师,超过 100 条不截断,且不下发敏感字段。
|
||||
*/
|
||||
@Test
|
||||
public void testSchedulingOptionsReturnsAllActiveTeachersWithoutTruncation()
|
||||
{
|
||||
// 构造 150 名在岗教师 + 20 名停用教师 + 5 名已删除教师
|
||||
for (int i = 1; i <= 150; i++)
|
||||
{
|
||||
teacherMapper.teachers.add(buildTeacher("T_OK_" + i, "在岗教师" + i, 1));
|
||||
}
|
||||
for (int i = 1; i <= 20; i++)
|
||||
{
|
||||
teacherMapper.teachers.add(buildTeacher("T_OFF_" + i, "停用教师" + i, 0));
|
||||
}
|
||||
for (int i = 1; i <= 5; i++)
|
||||
{
|
||||
TrainTeacher removed = buildTeacher("T_DEL_" + i, "已删除教师" + i, 1);
|
||||
removed.setDelFlag("2");
|
||||
teacherMapper.teachers.add(removed);
|
||||
}
|
||||
|
||||
// 教室与实训场地候选也一并构造超过 100 条
|
||||
for (int i = 1; i <= 120; i++)
|
||||
{
|
||||
TrainClassroomInfo classroom = new TrainClassroomInfo();
|
||||
classroom.setClassRoomId("CR_OK_" + i);
|
||||
classroom.setRoomName("教室" + i);
|
||||
classroom.setRoomLocation("综合楼" + i + "层");
|
||||
classroom.setCapacity(60L);
|
||||
classroom.setDelFlag("0");
|
||||
classroomMapper.classrooms.add(classroom);
|
||||
}
|
||||
for (int i = 1; i <= 110; i++)
|
||||
{
|
||||
TrainTrainingSite site = new TrainTrainingSite();
|
||||
site.setSiteId("SITE_OK_" + i);
|
||||
site.setSiteName("实训场地" + i);
|
||||
site.setSiteLocation("实训区" + i);
|
||||
site.setCapacity(30L);
|
||||
site.setDelFlag("0");
|
||||
siteMapper.sites.add(site);
|
||||
}
|
||||
|
||||
Map<String, Object> options = appService.getSchedulingOptions();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> teachers = (List<Map<String, Object>>) options.get("teachers");
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> classrooms = (List<Map<String, Object>>) options.get("classrooms");
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> sites = (List<Map<String, Object>>) options.get("sites");
|
||||
|
||||
// 全量返回,绝不在 100 条处静默截断
|
||||
assertEquals(150, teachers.size());
|
||||
assertEquals(120, classrooms.size());
|
||||
assertEquals(110, sites.size());
|
||||
|
||||
// 停用与已删除教师均不出现在候选中
|
||||
for (Map<String, Object> item : teachers)
|
||||
{
|
||||
String tId = (String) item.get("tId");
|
||||
assertFalse("停用教师不得进入排课候选", tId.startsWith("T_OFF_"));
|
||||
assertFalse("已删除教师不得进入排课候选", tId.startsWith("T_DEL_"));
|
||||
}
|
||||
|
||||
// 字段精简:只含下拉必需字段,不下发手机号 / 邮箱等敏感信息
|
||||
Map<String, Object> firstTeacher = teachers.get(0);
|
||||
assertEquals(3, firstTeacher.size());
|
||||
assertTrue(firstTeacher.containsKey("tId"));
|
||||
assertTrue(firstTeacher.containsKey("tName"));
|
||||
assertTrue(firstTeacher.containsKey("orgName"));
|
||||
assertFalse(firstTeacher.containsKey("tPhone"));
|
||||
assertFalse(firstTeacher.containsKey("tEmail"));
|
||||
|
||||
// 教室与场地保持下拉展示所需字段
|
||||
assertTrue(classrooms.get(0).containsKey("classRoomId"));
|
||||
assertTrue(classrooms.get(0).containsKey("roomName"));
|
||||
assertTrue(sites.get(0).containsKey("siteId"));
|
||||
assertTrue(sites.get(0).containsKey("siteName"));
|
||||
}
|
||||
|
||||
private TrainTeacher buildTeacher(String tId, String tName, Integer status)
|
||||
{
|
||||
TrainTeacher teacher = new TrainTeacher();
|
||||
teacher.settId(tId);
|
||||
teacher.settName(tName);
|
||||
teacher.setOrgName("动车运用所");
|
||||
teacher.settPhone("13800000000");
|
||||
teacher.settEmail("teacher@example.com");
|
||||
teacher.setStatus(status);
|
||||
teacher.setDelFlag("0");
|
||||
return teacher;
|
||||
}
|
||||
|
||||
private LessonCreateDTO buildCreateDTO(String tId, String startTimeStr, String endTimeStr) throws Exception
|
||||
{
|
||||
LessonCreateDTO dto = new LessonCreateDTO();
|
||||
dto.setPlanCourseId(PLAN_COURSE_ID);
|
||||
dto.setTId(tId);
|
||||
dto.setStartTime(sdf.parse(startTimeStr));
|
||||
dto.setEndTime(sdf.parse(endTimeStr));
|
||||
dto.setVenueType(1);
|
||||
dto.setClassRoomId(CLASSROOM_ID);
|
||||
return dto;
|
||||
}
|
||||
|
||||
private void addExistingLesson(Long lessonId, String tId, String startTimeStr, String endTimeStr) throws Exception
|
||||
{
|
||||
TrainLesson lesson = new TrainLesson();
|
||||
lesson.setLessonId(lessonId);
|
||||
lesson.setPlanCourseId(PLAN_COURSE_ID);
|
||||
lesson.setTId(tId);
|
||||
lesson.setVenueType(1);
|
||||
lesson.setClassRoomId(CLASSROOM_ID);
|
||||
lesson.setStartTime(sdf.parse(startTimeStr));
|
||||
lesson.setEndTime(sdf.parse(endTimeStr));
|
||||
lessonMapper.lessons.put(lessonId, lesson);
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟 Lesson Mapper。
|
||||
*/
|
||||
private static class MockLessonMapper implements TrainLessonMapper
|
||||
{
|
||||
Map<Long, TrainLesson> lessons = new HashMap<>();
|
||||
Map<String, TrainTeacher> teachers = new HashMap<>();
|
||||
Map<String, TrainClassroomInfo> classrooms = new HashMap<>();
|
||||
Map<String, TrainTrainingSite> sites = new HashMap<>();
|
||||
AtomicLong idGen = new AtomicLong(2000L);
|
||||
|
||||
@Override
|
||||
public TrainLesson selectTrainLessonById(Long lessonId)
|
||||
{
|
||||
return lessons.get(lessonId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertTrainLesson(TrainLesson trainLesson)
|
||||
{
|
||||
if (trainLesson.getLessonId() == null)
|
||||
{
|
||||
trainLesson.setLessonId(idGen.incrementAndGet());
|
||||
}
|
||||
lessons.put(trainLesson.getLessonId(), trainLesson);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateTrainLesson(TrainLesson trainLesson)
|
||||
{
|
||||
lessons.put(trainLesson.getLessonId(), trainLesson);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteTrainLessonById(Long lessonId)
|
||||
{
|
||||
lessons.remove(lessonId);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrainTeacher lockTeacherById(String tId)
|
||||
{
|
||||
return teachers.get(tId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrainClassroomInfo lockClassroomById(String classRoomId)
|
||||
{
|
||||
return classrooms.get(classRoomId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrainTrainingSite lockSiteById(String siteId)
|
||||
{
|
||||
return sites.get(siteId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countAttendanceByLessonId(Long lessonId)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConflictItemVO> selectTeacherConflicts(String tId, Date startTime, Date endTime, Long excludeLessonId)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConflictItemVO> selectClassroomConflicts(String classRoomId, Date startTime, Date endTime, Long excludeLessonId)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConflictItemVO> selectSiteConflicts(String siteId, Date startTime, Date endTime, Long excludeLessonId)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConflictItemVO> selectPlanConflicts(String planId, Date startTime, Date endTime, Long excludeLessonId)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TimetableLessonItemVO> selectScheduleLessonsByPlanId(String planId)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TimetableLessonItemVO> selectScheduleLessonsByTeacherId(String tId, Date startDate, Date endDate)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TimetableLessonItemVO> selectScheduleLessonsByStudentId(String studentId, Date startDate, Date endDate)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countTeacherInPlan(String tId, String planId)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TrainClassPlan> selectPlansByTeacherId(String tId, Integer planStatus)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countLessonsByClassRoomId(String classRoomId)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countLessonsByTeacherId(String tId)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟 Plan Mapper。
|
||||
*/
|
||||
private static class MockPlanMapper implements TrainClassPlanMapper
|
||||
{
|
||||
Map<String, TrainClassPlan> plans = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public TrainClassPlan selectTrainClassPlanByPlanId(String planId)
|
||||
{
|
||||
return plans.get(planId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrainClassPlan selectTrainClassPlanByPlanIdForUpdate(String planId)
|
||||
{
|
||||
return plans.get(planId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PlanItemVO> selectTrainClassPlanList(PlanQuery query)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countTrainClassPlanByName(String planName, String excludePlanId)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertTrainClassPlan(TrainClassPlan trainClassPlan)
|
||||
{
|
||||
plans.put(trainClassPlan.getPlanId(), trainClassPlan);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateTrainClassPlan(TrainClassPlan trainClassPlan)
|
||||
{
|
||||
plans.put(trainClassPlan.getPlanId(), trainClassPlan);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateTrainClassPlanStatus(TrainClassPlan trainClassPlan)
|
||||
{
|
||||
plans.put(trainClassPlan.getPlanId(), trainClassPlan);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟 PlanCourse Mapper。
|
||||
*/
|
||||
private static class MockPlanCourseMapper implements TrainPlanCourseMapper
|
||||
{
|
||||
Map<Long, TrainPlanCourse> planCourses = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public TrainPlanCourse selectTrainPlanCourseById(Long planCourseId)
|
||||
{
|
||||
return planCourses.get(planCourseId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PlanCourseItemVO> selectPlanCourseListByPlanId(String planId)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> selectExistingCIdsByPlanId(String planId, List<String> cIds)
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertTrainPlanCourse(TrainPlanCourse trainPlanCourse)
|
||||
{
|
||||
planCourses.put(trainPlanCourse.getPlanCourseId(), trainPlanCourse);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int batchInsertTrainPlanCourse(List<TrainPlanCourse> list)
|
||||
{
|
||||
for (TrainPlanCourse pc : list)
|
||||
{
|
||||
planCourses.put(pc.getPlanCourseId(), pc);
|
||||
}
|
||||
return list.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteTrainPlanCourseById(Long planCourseId)
|
||||
{
|
||||
planCourses.remove(planCourseId);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countLessonsByPlanCourseId(Long planCourseId)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countScoreItemsByPlanCourseId(Long planCourseId)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countStudyDurationsByPlanCourseId(Long planCourseId)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countPlanCoursesByCId(String cId)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countStudentScoresByCId(String cId)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟 Teacher Mapper:对齐 TrainTeacherMapper.xml 的 del_flag='0' 与可选 status 过滤语义,
|
||||
* 且不施加任何条数上限。
|
||||
*/
|
||||
private static class MockTeacherMapper implements TrainTeacherMapper
|
||||
{
|
||||
List<TrainTeacher> teachers = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public TrainTeacher selectTrainTeacherByTId(String tId)
|
||||
{
|
||||
for (TrainTeacher teacher : teachers)
|
||||
{
|
||||
if (tId != null && tId.equals(teacher.gettId()) && !"2".equals(teacher.getDelFlag()))
|
||||
{
|
||||
return teacher;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TrainTeacher> selectTrainTeacherList(TrainTeacher query)
|
||||
{
|
||||
List<TrainTeacher> result = new ArrayList<>();
|
||||
for (TrainTeacher teacher : teachers)
|
||||
{
|
||||
if ("2".equals(teacher.getDelFlag()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (query != null && query.getStatus() != null
|
||||
&& !query.getStatus().equals(teacher.getStatus()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
result.add(teacher);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertTrainTeacher(TrainTeacher trainTeacher)
|
||||
{
|
||||
teachers.add(trainTeacher);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateTrainTeacher(TrainTeacher trainTeacher)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrainTeacher checkPhoneUnique(String tPhone)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteTrainTeacherByTId(String tId)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteTrainTeacherRealByTId(String tId)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteTrainTeacherByTIds(String[] tIds)
|
||||
{
|
||||
return tIds == null ? 0 : tIds.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrainTeacher selectTrainTeacherByUserId(Long userId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countByUserId(Long userId)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bindUserId(String tId, Long userId)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int unbindUserId(String tId)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟 Classroom Mapper:对齐 del_flag='0' 语义,不施加条数上限。
|
||||
*/
|
||||
private static class MockClassroomMapper implements TrainClassroomInfoMapper
|
||||
{
|
||||
List<TrainClassroomInfo> classrooms = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public TrainClassroomInfo selectTrainClassroomInfoByClassRoomId(String classRoomId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TrainClassroomInfo> selectTrainClassroomInfoList(TrainClassroomInfo query)
|
||||
{
|
||||
List<TrainClassroomInfo> result = new ArrayList<>();
|
||||
for (TrainClassroomInfo classroom : classrooms)
|
||||
{
|
||||
if (!"2".equals(classroom.getDelFlag()))
|
||||
{
|
||||
result.add(classroom);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrainClassroomInfo checkRoomNameUnique(String roomName, String excludeClassRoomId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertTrainClassroomInfo(TrainClassroomInfo trainClassroomInfo)
|
||||
{
|
||||
classrooms.add(trainClassroomInfo);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateTrainClassroomInfo(TrainClassroomInfo trainClassroomInfo)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteTrainClassroomInfoByClassRoomId(String classRoomId)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteTrainClassroomInfoByClassRoomIds(String[] classRoomIds)
|
||||
{
|
||||
return classRoomIds == null ? 0 : classRoomIds.length;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟 Site Mapper:对齐 del_flag='0' 语义,不施加条数上限。
|
||||
*/
|
||||
private static class MockSiteMapper implements TrainTrainingSiteMapper
|
||||
{
|
||||
List<TrainTrainingSite> sites = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public TrainTrainingSite selectTrainTrainingSiteBySiteId(String siteId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TrainTrainingSite> selectTrainTrainingSiteList(TrainTrainingSite query)
|
||||
{
|
||||
List<TrainTrainingSite> result = new ArrayList<>();
|
||||
for (TrainTrainingSite site : sites)
|
||||
{
|
||||
if (!"2".equals(site.getDelFlag()))
|
||||
{
|
||||
result.add(site);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrainTrainingSite checkSiteNameUnique(String siteName, String excludeSiteId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertTrainTrainingSite(TrainTrainingSite trainTrainingSite)
|
||||
{
|
||||
sites.add(trainTrainingSite);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateTrainTrainingSite(TrainTrainingSite trainTrainingSite)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteTrainTrainingSiteBySiteId(String siteId)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteTrainTrainingSiteBySiteIds(String[] siteIds)
|
||||
{
|
||||
return siteIds == null ? 0 : siteIds.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user