diff --git a/src/main/java/com/sztzjy/linkCommerce/controller/schooladmin/SchoolAdminController.java b/src/main/java/com/sztzjy/linkCommerce/controller/schooladmin/SchoolAdminController.java index 456a5e0..8c80a93 100644 --- a/src/main/java/com/sztzjy/linkCommerce/controller/schooladmin/SchoolAdminController.java +++ b/src/main/java/com/sztzjy/linkCommerce/controller/schooladmin/SchoolAdminController.java @@ -12,6 +12,7 @@ import com.sztzjy.linkCommerce.entity.dto.SchoolMajorDto; import com.sztzjy.linkCommerce.entity.importDto.SchoolAdminStudentImportDTO; import com.sztzjy.linkCommerce.mapper.*; import com.sztzjy.linkCommerce.service.SchoolAdminService; +import com.sztzjy.linkCommerce.service.SchoolProductConfigService; import com.sztzjy.linkCommerce.service.SchoolService; import com.sztzjy.linkCommerce.service.UserInfoService; import com.sztzjy.linkCommerce.util.ResultEntity; @@ -56,6 +57,8 @@ public class SchoolAdminController { private UserinfoMapper userinfoMapper; @Autowired private TaskAllocationMapper taskAllocationMapper; + @Autowired + private SchoolProductConfigService schoolProductConfigService; @GetMapping("/school") @ApiOperation("学校管理员-当前学校详情") @@ -81,6 +84,7 @@ public class SchoolAdminController { @RequestParam(required = false) String schoolFacultyName, HttpServletRequest request) { String schoolId = currentSchoolId(request); + requireAdministrativeOrganization(schoolId); PageInfo pageInfo = schoolService.seleteSchoolFaculty(index, size, schoolId, schoolFacultyName); return new ResultEntity<>(HttpStatus.OK, "查询成功", pageInfo); } @@ -89,6 +93,7 @@ public class SchoolAdminController { @ApiOperation("学校管理员-新增院系") public ResultEntity addFaculty(@RequestBody SchoolFaculty faculty, HttpServletRequest request) { String schoolId = currentSchoolId(request); + requireAdministrativeOrganization(schoolId); if (StringUtils.isBlank(faculty.getSchoolFacultyName())) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "院系名称不能为空"); } @@ -105,6 +110,7 @@ public class SchoolAdminController { @RequestBody SchoolFaculty faculty, HttpServletRequest request) { String schoolId = currentSchoolId(request); + requireAdministrativeOrganization(schoolId); SchoolFaculty existing = requireFaculty(id, schoolId); faculty.setSchoolFacultyId(existing.getSchoolFacultyId()); faculty.setSchoolId(schoolId); @@ -116,6 +122,7 @@ public class SchoolAdminController { @ApiOperation("学校管理员-删除院系") public ResultEntity deleteFaculty(@PathVariable String id, HttpServletRequest request) { String schoolId = currentSchoolId(request); + requireAdministrativeOrganization(schoolId); requireFaculty(id, schoolId); if (hasMajorInFaculty(id) || hasUserByFaculty(id)) { return new ResultEntity<>(HttpStatus.ACCEPTED, "院系下存在专业或用户,不能删除"); @@ -132,6 +139,7 @@ public class SchoolAdminController { @RequestParam(required = false) String schoolFacultyId, HttpServletRequest request) { String schoolId = currentSchoolId(request); + requireAdministrativeOrganization(schoolId); if (StringUtils.isNotBlank(schoolFacultyId)) { requireFaculty(schoolFacultyId, schoolId); } @@ -143,6 +151,7 @@ public class SchoolAdminController { @ApiOperation("学校管理员-新增专业") public ResultEntity addMajor(@RequestBody SchoolMajor major, HttpServletRequest request) { String schoolId = currentSchoolId(request); + requireAdministrativeOrganization(schoolId); if (StringUtils.isBlank(major.getSchoolMajorName())) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "专业名称不能为空"); } @@ -159,6 +168,7 @@ public class SchoolAdminController { @RequestBody SchoolMajor major, HttpServletRequest request) { String schoolId = currentSchoolId(request); + requireAdministrativeOrganization(schoolId); requireMajor(id, schoolId); if (StringUtils.isNotBlank(major.getSchoolFacultyId())) { requireFaculty(major.getSchoolFacultyId(), schoolId); @@ -172,6 +182,7 @@ public class SchoolAdminController { @ApiOperation("学校管理员-删除专业") public ResultEntity deleteMajor(@PathVariable String id, HttpServletRequest request) { String schoolId = currentSchoolId(request); + requireAdministrativeOrganization(schoolId); requireMajor(id, schoolId); if (hasClassInMajor(id) || hasUserByMajor(id)) { return new ResultEntity<>(HttpStatus.ACCEPTED, "专业下存在班级或用户,不能删除"); @@ -189,6 +200,7 @@ public class SchoolAdminController { @RequestParam(required = false) String schoolMajorId, HttpServletRequest request) { String schoolId = currentSchoolId(request); + requireAdministrativeOrganization(schoolId); if (StringUtils.isNotBlank(schoolMajorId)) { requireMajor(schoolMajorId, schoolId); } @@ -200,6 +212,7 @@ public class SchoolAdminController { @ApiOperation("学校管理员-新增班级") public ResultEntity addClass(@RequestBody SchoolClass schoolClass, HttpServletRequest request) { String schoolId = currentSchoolId(request); + requireAdministrativeOrganization(schoolId); if (StringUtils.isBlank(schoolClass.getClassName())) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级名称不能为空"); } @@ -217,6 +230,7 @@ public class SchoolAdminController { @RequestBody SchoolClass schoolClass, HttpServletRequest request) { String schoolId = currentSchoolId(request); + requireAdministrativeOrganization(schoolId); requireClass(id, schoolId); if (StringUtils.isNotBlank(schoolClass.getSchoolMajorId())) { requireMajor(schoolClass.getSchoolMajorId(), schoolId); @@ -231,6 +245,7 @@ public class SchoolAdminController { @ApiOperation("学校管理员-删除班级") public ResultEntity deleteClass(@PathVariable String id, HttpServletRequest request) { String schoolId = currentSchoolId(request); + requireAdministrativeOrganization(schoolId); requireClass(id, schoolId); if (hasStudentInClass(id) || hasTaskInClass(id, schoolId)) { return new ResultEntity<>(HttpStatus.ACCEPTED, "班级下存在学生或任务,不能删除"); @@ -302,6 +317,7 @@ public class SchoolAdminController { @RequestParam(required = false) String schoolClassId, HttpServletRequest request) { String schoolId = currentSchoolId(request); + requireAdministrativeOrganization(schoolId); if (StringUtils.isNotBlank(schoolClassId)) { requireClass(schoolClassId, schoolId); } @@ -313,6 +329,7 @@ public class SchoolAdminController { @ApiOperation("学校管理员-新增学生") public ResultEntity addStudent(@RequestBody Userinfo student, HttpServletRequest request) { String schoolId = currentSchoolId(request); + requireAdministrativeOrganization(schoolId); if (StringUtils.isBlank(student.getUsername()) || StringUtils.isBlank(student.getName())) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "学生姓名和学号不能为空"); } @@ -337,6 +354,7 @@ public class SchoolAdminController { @Transactional(rollbackFor = Exception.class) public ResultEntity importStudents(@RequestParam("file") MultipartFile file, HttpServletRequest request) { String schoolId = currentSchoolId(request); + requireAdministrativeOrganization(schoolId); ResultEntity fileError = validateImportFile(file); if (fileError != null) { return fileError; @@ -377,6 +395,7 @@ public class SchoolAdminController { @RequestBody Userinfo student, HttpServletRequest request) { String schoolId = currentSchoolId(request); + requireAdministrativeOrganization(schoolId); requireUser(id, schoolId, 4); if (StringUtils.isNotBlank(student.getSchoolClassId())) { requireClass(student.getSchoolClassId(), schoolId); @@ -391,6 +410,7 @@ public class SchoolAdminController { @ApiOperation("学校管理员-删除学生") public ResultEntity deleteStudent(@PathVariable String id, HttpServletRequest request) { String schoolId = currentSchoolId(request); + requireAdministrativeOrganization(schoolId); requireUser(id, schoolId, 4); int count = userinfoMapper.deleteByPrimaryKey(id); return writeResult(count, "删除成功", "删除失败"); @@ -401,6 +421,10 @@ public class SchoolAdminController { return schoolAdminService.requireSchoolAdmin(user); } + private void requireAdministrativeOrganization(String schoolId) { + schoolProductConfigService.requireAdminClassEnabled(schoolId); + } + private ResultEntity writeResult(int count, String success, String fail) { if (count > 0) { return new ResultEntity<>(HttpStatus.OK, success); diff --git a/src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java b/src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java index 49b9ec2..b770ad8 100644 --- a/src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java +++ b/src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java @@ -1115,9 +1115,20 @@ public class UserController { for (TeacherRosterStudentImportDTO row : rows) { String name = row == null ? "" : StringUtils.trimToEmpty(row.getName()); String username = row == null ? "" : StringUtils.trimToEmpty(row.getUsername()); - if (StringUtils.isBlank(name) || StringUtils.isBlank(username) || userInfoService.existsByUserName(username)) { + if (StringUtils.isBlank(name) || StringUtils.isBlank(username)) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "学生姓名或学号无效"); } + Userinfo existingStudent = userinfoMapper.selectBySchoolIdAndUsername(operator.getSchoolId(), username); + if (existingStudent != null) { + if (!Integer.valueOf(4).equals(existingStudent.getRole()) || !StringUtils.equals(existingStudent.getName(), name)) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "学号与已有学生信息冲突"); + } + upsertActiveTeachingClassMember(teachingClassId, existingStudent, null, "TEACHER_ROSTER_IMPORT"); + continue; + } + if (userInfoService.existsByUserName(username)) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "学号已被其他学校使用"); + } Userinfo student = new Userinfo(); student.setUserId(UUID.randomUUID().toString()); student.setName(name); @@ -1545,7 +1556,6 @@ public class UserController { || StringUtils.isBlank(student.getUserId())) { return; } - teachingClassStudentMapper.exitActiveByStudentUserIdExceptClass(student.getUserId(), teachingClassId); TeachingClassStudent existing = teachingClassStudentMapper .selectByStudentUserIdAndTeachingClassId(student.getUserId(), teachingClassId); if (existing != null) { diff --git a/src/main/java/com/sztzjy/linkCommerce/mapper/UserinfoMapper.java b/src/main/java/com/sztzjy/linkCommerce/mapper/UserinfoMapper.java index c4f166a..da8b8aa 100644 --- a/src/main/java/com/sztzjy/linkCommerce/mapper/UserinfoMapper.java +++ b/src/main/java/com/sztzjy/linkCommerce/mapper/UserinfoMapper.java @@ -24,6 +24,8 @@ public interface UserinfoMapper { Userinfo selectByPrimaryKey(String userId); + Userinfo selectBySchoolIdAndUsername(@Param("schoolId") String schoolId, @Param("username") String username); + int updateByExampleSelective(@Param("record") Userinfo record, @Param("example") UserinfoExample example); int updateByExample(@Param("record") Userinfo record, @Param("example") UserinfoExample example); @@ -35,4 +37,4 @@ public interface UserinfoMapper { @Select("select DISTINCT school_id from userinfo ") List selectAllSchoolIds(); -} \ No newline at end of file +} diff --git a/src/main/java/com/sztzjy/linkCommerce/service/impl/SchoolProductConfigServiceImpl.java b/src/main/java/com/sztzjy/linkCommerce/service/impl/SchoolProductConfigServiceImpl.java index e0aa5d7..46230d8 100644 --- a/src/main/java/com/sztzjy/linkCommerce/service/impl/SchoolProductConfigServiceImpl.java +++ b/src/main/java/com/sztzjy/linkCommerce/service/impl/SchoolProductConfigServiceImpl.java @@ -1,8 +1,12 @@ package com.sztzjy.linkCommerce.service.impl; import com.sztzjy.linkCommerce.config.exception.handler.ServiceException; +import com.sztzjy.linkCommerce.entity.SchoolClassExample; import com.sztzjy.linkCommerce.entity.SchoolProductConfig; +import com.sztzjy.linkCommerce.entity.UserinfoExample; +import com.sztzjy.linkCommerce.mapper.SchoolClassMapper; import com.sztzjy.linkCommerce.mapper.SchoolProductConfigMapper; +import com.sztzjy.linkCommerce.mapper.UserinfoMapper; import com.sztzjy.linkCommerce.service.SchoolProductConfigService; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -21,6 +25,12 @@ public class SchoolProductConfigServiceImpl implements SchoolProductConfigServic @Autowired public SchoolProductConfigMapper schoolProductConfigMapper; + @Autowired + public SchoolClassMapper schoolClassMapper; + + @Autowired + public UserinfoMapper userinfoMapper; + @Override public void createDefaultConfig(String schoolId) { if (StringUtils.isBlank(schoolId)) { @@ -45,7 +55,11 @@ public class SchoolProductConfigServiceImpl implements SchoolProductConfigServic if (!standard && !teacherManaged) { throw new ServiceException(HttpStatus.BAD_REQUEST, "学校组织模式与名单维护方不匹配"); } - getRequiredConfig(config.getSchoolId()); + SchoolProductConfig current = getRequiredConfig(config.getSchoolId()); + if (!StringUtils.equals(current.getOrganizationMode(), config.getOrganizationMode()) + && hasAdministrativeOrganizationData(config.getSchoolId())) { + throw new ServiceException(HttpStatus.BAD_REQUEST, "学校已有组织数据,不能直接切换组织模式"); + } config.setUpdateTime(new Date()); schoolProductConfigMapper.updateByPrimaryKey(config); return getRequiredConfig(config.getSchoolId()); @@ -79,4 +93,19 @@ public class SchoolProductConfigServiceImpl implements SchoolProductConfigServic throw new ServiceException(HttpStatus.BAD_REQUEST, "当前学校未启用行政班"); } } + + private boolean hasAdministrativeOrganizationData(String schoolId) { + SchoolClassExample classExample = new SchoolClassExample(); + classExample.createCriteria() + .andSchoolIdEqualTo(schoolId) + .andClassTypeEqualTo("ADMIN"); + if (schoolClassMapper.countByExample(classExample) > 0) { + return true; + } + UserinfoExample userExample = new UserinfoExample(); + userExample.createCriteria() + .andSchoolIdEqualTo(schoolId) + .andSchoolClassIdIsNotNull(); + return userinfoMapper.countByExample(userExample) > 0; + } } diff --git a/src/main/resources/mappers/UserinfoMapper.xml b/src/main/resources/mappers/UserinfoMapper.xml index 2cb4e6e..addc683 100644 --- a/src/main/resources/mappers/UserinfoMapper.xml +++ b/src/main/resources/mappers/UserinfoMapper.xml @@ -107,6 +107,12 @@ from userinfo where user_id = #{userId,jdbcType=VARCHAR} + delete from userinfo where user_id = #{userId,jdbcType=VARCHAR} diff --git a/src/test/java/com/sztzjy/linkCommerce/controller/schooladmin/SchoolAdminControllerTest.java b/src/test/java/com/sztzjy/linkCommerce/controller/schooladmin/SchoolAdminControllerTest.java index d081a48..d02dabf 100644 --- a/src/test/java/com/sztzjy/linkCommerce/controller/schooladmin/SchoolAdminControllerTest.java +++ b/src/test/java/com/sztzjy/linkCommerce/controller/schooladmin/SchoolAdminControllerTest.java @@ -1,11 +1,15 @@ package com.sztzjy.linkCommerce.controller.schooladmin; +import com.sztzjy.linkCommerce.service.SchoolProductConfigService; import org.junit.jupiter.api.Test; +import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.bind.annotation.PostMapping; import java.util.Arrays; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; class SchoolAdminControllerTest { @@ -18,4 +22,15 @@ class SchoolAdminControllerTest { assertTrue(exists, "School admin student import must use /api/school-admin/students/import"); } + + @Test + void administrativeOrganizationGuardDelegatesToSchoolConfiguration() { + SchoolAdminController controller = new SchoolAdminController(); + SchoolProductConfigService configService = mock(SchoolProductConfigService.class); + ReflectionTestUtils.setField(controller, "schoolProductConfigService", configService); + + ReflectionTestUtils.invokeMethod(controller, "requireAdministrativeOrganization", "school-zj"); + + verify(configService).requireAdminClassEnabled("school-zj"); + } } diff --git a/src/test/java/com/sztzjy/linkCommerce/controller/stu/TeacherRosterImportTest.java b/src/test/java/com/sztzjy/linkCommerce/controller/stu/TeacherRosterImportTest.java index 8c70ea3..e3e9695 100644 --- a/src/test/java/com/sztzjy/linkCommerce/controller/stu/TeacherRosterImportTest.java +++ b/src/test/java/com/sztzjy/linkCommerce/controller/stu/TeacherRosterImportTest.java @@ -22,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -68,5 +69,33 @@ class TeacherRosterImportTest { verify(controller.teachingClassStudentMapper).insertSelective(membership.capture()); assertEquals("teach-1", membership.getValue().getTeachingClassId()); assertEquals(null, membership.getValue().getAdminClassId()); + verify(controller.teachingClassStudentMapper, never()) + .exitActiveByStudentUserIdExceptClass(org.mockito.ArgumentMatchers.anyString(), org.mockito.ArgumentMatchers.anyString()); + } + + @Test + void teacherRosterImportReusesExistingStudentInTheSameSchool() { + UserController controller = new UserController(); + controller.userinfoMapper = mock(UserinfoMapper.class); + controller.schoolClassMapper = mock(SchoolClassMapper.class); + controller.teachingClassStudentMapper = mock(TeachingClassStudentMapper.class); + controller.schoolProductConfigService = mock(SchoolProductConfigService.class); + Userinfo teacher = new Userinfo(); + teacher.setUserId("teacher-1"); teacher.setRole(3); teacher.setSchoolId("school-zj"); + Userinfo student = new Userinfo(); + student.setUserId("student-1"); student.setRole(4); student.setSchoolId("school-zj"); student.setUsername("20260001"); student.setName("张三"); + SchoolClass teachingClass = new SchoolClass(); + teachingClass.setSchoolClassId("teach-2"); teachingClass.setSchoolId("school-zj"); teachingClass.setClassType("TEACHING"); teachingClass.setCreatedBy("teacher-1"); + when(controller.userinfoMapper.selectByPrimaryKey("teacher-1")).thenReturn(teacher); + when(controller.schoolClassMapper.selectByPrimaryKey("teach-2")).thenReturn(teachingClass); + when(controller.schoolProductConfigService.isTeacherRosterManaged("school-zj")).thenReturn(true); + when(controller.userinfoMapper.selectBySchoolIdAndUsername("school-zj", "20260001")).thenReturn(student); + TeacherRosterStudentImportDTO row = new TeacherRosterStudentImportDTO(); row.setName("张三"); row.setUsername("20260001"); + + ResultEntity result = controller.importTeacherRosterRows(Collections.singletonList(row), "teach-2", "teacher-1"); + + assertEquals(HttpStatus.OK, result.getStatusCode()); + verify(controller.userinfoMapper, never()).insertSelective(any(Userinfo.class)); + verify(controller.teachingClassStudentMapper).insertSelective(any(TeachingClassStudent.class)); } } diff --git a/src/test/java/com/sztzjy/linkCommerce/controller/stu/UserControllerTeacherAdminTest.java b/src/test/java/com/sztzjy/linkCommerce/controller/stu/UserControllerTeacherAdminTest.java index b27f5b7..301edf3 100644 --- a/src/test/java/com/sztzjy/linkCommerce/controller/stu/UserControllerTeacherAdminTest.java +++ b/src/test/java/com/sztzjy/linkCommerce/controller/stu/UserControllerTeacherAdminTest.java @@ -697,7 +697,7 @@ class UserControllerTeacherAdminTest { } @Test - void importTeachingClassStudentRowsTransfersStudentFromOtherTeachingClass() { + void importTeachingClassStudentRowsKeepsStudentInOtherTeachingClasses() { UserController controller = controllerWithCommonMocks(); SchoolClass teachingClass = classCreatedBy("teacher-1"); teachingClass.setSchoolClassId("teaching-1"); @@ -712,7 +712,8 @@ class UserControllerTeacherAdminTest { ResultEntity result = controller.importTeachingClassStudentRows(Collections.singletonList(row), "teaching-1", "teacher-1"); assertEquals(HttpStatus.OK, result.getStatusCode()); - verify(controller.teachingClassStudentMapper).exitActiveByStudentUserIdExceptClass("student-1", "teaching-1"); + verify(controller.teachingClassStudentMapper, never()) + .exitActiveByStudentUserIdExceptClass(any(), any()); verify(controller.teachingClassStudentMapper).insertSelective(any(TeachingClassStudent.class)); } @@ -789,7 +790,7 @@ class UserControllerTeacherAdminTest { } @Test - void createTeachingClassByImportRowsTransfersStudentFromOtherTeachingClass() { + void createTeachingClassByImportRowsKeepsStudentInOtherTeachingClasses() { UserController controller = controllerWithCommonMocks(); Userinfo student = student("student-1", "student-a", "2024001", "admin-1"); when(controller.schoolClassMapper.selectByExample(any())).thenReturn(Collections.emptyList()); @@ -806,7 +807,8 @@ class UserControllerTeacherAdminTest { assertEquals(HttpStatus.OK, result.getStatusCode()); verify(controller.schoolClassMapper).insert(any(SchoolClass.class)); - verify(controller.teachingClassStudentMapper).exitActiveByStudentUserIdExceptClass(argThat(id -> "student-1".equals(id)), any()); + verify(controller.teachingClassStudentMapper, never()) + .exitActiveByStudentUserIdExceptClass(any(), any()); verify(controller.teachingClassStudentMapper).insertSelective(any(TeachingClassStudent.class)); } diff --git a/src/test/java/com/sztzjy/linkCommerce/service/impl/SchoolProductConfigServiceImplTest.java b/src/test/java/com/sztzjy/linkCommerce/service/impl/SchoolProductConfigServiceImplTest.java index 6cdd661..ce9641a 100644 --- a/src/test/java/com/sztzjy/linkCommerce/service/impl/SchoolProductConfigServiceImplTest.java +++ b/src/test/java/com/sztzjy/linkCommerce/service/impl/SchoolProductConfigServiceImplTest.java @@ -2,7 +2,9 @@ package com.sztzjy.linkCommerce.service.impl; import com.sztzjy.linkCommerce.config.exception.handler.ServiceException; import com.sztzjy.linkCommerce.entity.SchoolProductConfig; +import com.sztzjy.linkCommerce.mapper.SchoolClassMapper; import com.sztzjy.linkCommerce.mapper.SchoolProductConfigMapper; +import com.sztzjy.linkCommerce.mapper.UserinfoMapper; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -67,6 +69,20 @@ class SchoolProductConfigServiceImplTest { && "SCHOOL_ADMIN".equals(config.getStudentRosterOwner()))); } + @Test + void updateRejectsOrganizationModeChangeWhenAdministrativeDataExists() { + SchoolProductConfigServiceImpl service = new SchoolProductConfigServiceImpl(); + service.schoolProductConfigMapper = mock(SchoolProductConfigMapper.class); + service.schoolClassMapper = mock(SchoolClassMapper.class); + service.userinfoMapper = mock(UserinfoMapper.class); + SchoolProductConfig current = config("school-standard", "ADMIN_CLASS_ENABLED", "SCHOOL_ADMIN"); + when(service.schoolProductConfigMapper.selectByPrimaryKey("school-standard")).thenReturn(current); + when(service.schoolClassMapper.countByExample(org.mockito.ArgumentMatchers.any())).thenReturn(1L); + + assertThrows(ServiceException.class, () -> service.updateConfig( + config("school-standard", "TEACHING_CLASS_ONLY", "TEACHER"))); + } + private SchoolProductConfig config(String schoolId, String organizationMode, String rosterOwner) { SchoolProductConfig config = new SchoolProductConfig(); config.setSchoolId(schoolId);