From f4f354b367ead21292900f8a32e316f7c4122500 Mon Sep 17 00:00:00 2001 From: chenyuan Date: Thu, 30 Jul 2026 11:57:10 +0800 Subject: [PATCH] feat: add school organization capability switches --- ...7-30-school-organization-menu-switches.sql | 9 ++ .../schooladmin/SchoolAdminController.java | 24 ++++-- .../controller/stu/UserController.java | 85 ++++++++++++++----- .../entity/SchoolProductConfig.java | 9 ++ .../service/SchoolProductConfigService.java | 10 +++ .../impl/SchoolProductConfigServiceImpl.java | 84 +++++++++++------- .../service/impl/UserInfoServiceImpl.java | 9 +- .../mappers/SchoolProductConfigMapper.xml | 11 ++- .../SchoolAdminControllerTest.java | 13 +++ .../stu/UserControllerTeacherAdminTest.java | 35 ++++++++ .../SchoolProductConfigServiceImplTest.java | 29 +++++-- ...erInfoServiceImplOrganizationModeTest.java | 40 +++++++++ 12 files changed, 282 insertions(+), 76 deletions(-) create mode 100644 docs/sql/2026-07-30-school-organization-menu-switches.sql create mode 100644 src/test/java/com/sztzjy/linkCommerce/service/impl/UserInfoServiceImplOrganizationModeTest.java diff --git a/docs/sql/2026-07-30-school-organization-menu-switches.sql b/docs/sql/2026-07-30-school-organization-menu-switches.sql new file mode 100644 index 0000000..7148758 --- /dev/null +++ b/docs/sql/2026-07-30-school-organization-menu-switches.sql @@ -0,0 +1,9 @@ +ALTER TABLE school_product_config + ADD COLUMN faculty_management_enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT 'whether faculty management is enabled' AFTER student_roster_owner, + ADD COLUMN major_management_enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT 'whether major management is enabled' AFTER faculty_management_enabled, + ADD COLUMN admin_class_management_enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT 'whether administrative class management is enabled' AFTER major_management_enabled; + +UPDATE school_product_config +SET faculty_management_enabled = CASE WHEN organization_mode = 'TEACHING_CLASS_ONLY' THEN 0 ELSE 1 END, + major_management_enabled = CASE WHEN organization_mode = 'TEACHING_CLASS_ONLY' THEN 0 ELSE 1 END, + admin_class_management_enabled = CASE WHEN organization_mode = 'TEACHING_CLASS_ONLY' THEN 0 ELSE 1 END; 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 8c80a93..454c1ec 100644 --- a/src/main/java/com/sztzjy/linkCommerce/controller/schooladmin/SchoolAdminController.java +++ b/src/main/java/com/sztzjy/linkCommerce/controller/schooladmin/SchoolAdminController.java @@ -84,7 +84,7 @@ public class SchoolAdminController { @RequestParam(required = false) String schoolFacultyName, HttpServletRequest request) { String schoolId = currentSchoolId(request); - requireAdministrativeOrganization(schoolId); + requireFacultyManagement(schoolId); PageInfo pageInfo = schoolService.seleteSchoolFaculty(index, size, schoolId, schoolFacultyName); return new ResultEntity<>(HttpStatus.OK, "查询成功", pageInfo); } @@ -93,7 +93,7 @@ public class SchoolAdminController { @ApiOperation("学校管理员-新增院系") public ResultEntity addFaculty(@RequestBody SchoolFaculty faculty, HttpServletRequest request) { String schoolId = currentSchoolId(request); - requireAdministrativeOrganization(schoolId); + requireFacultyManagement(schoolId); if (StringUtils.isBlank(faculty.getSchoolFacultyName())) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "院系名称不能为空"); } @@ -110,7 +110,7 @@ public class SchoolAdminController { @RequestBody SchoolFaculty faculty, HttpServletRequest request) { String schoolId = currentSchoolId(request); - requireAdministrativeOrganization(schoolId); + requireFacultyManagement(schoolId); SchoolFaculty existing = requireFaculty(id, schoolId); faculty.setSchoolFacultyId(existing.getSchoolFacultyId()); faculty.setSchoolId(schoolId); @@ -122,7 +122,7 @@ public class SchoolAdminController { @ApiOperation("学校管理员-删除院系") public ResultEntity deleteFaculty(@PathVariable String id, HttpServletRequest request) { String schoolId = currentSchoolId(request); - requireAdministrativeOrganization(schoolId); + requireFacultyManagement(schoolId); requireFaculty(id, schoolId); if (hasMajorInFaculty(id) || hasUserByFaculty(id)) { return new ResultEntity<>(HttpStatus.ACCEPTED, "院系下存在专业或用户,不能删除"); @@ -139,7 +139,7 @@ public class SchoolAdminController { @RequestParam(required = false) String schoolFacultyId, HttpServletRequest request) { String schoolId = currentSchoolId(request); - requireAdministrativeOrganization(schoolId); + requireMajorManagement(schoolId); if (StringUtils.isNotBlank(schoolFacultyId)) { requireFaculty(schoolFacultyId, schoolId); } @@ -151,7 +151,7 @@ public class SchoolAdminController { @ApiOperation("学校管理员-新增专业") public ResultEntity addMajor(@RequestBody SchoolMajor major, HttpServletRequest request) { String schoolId = currentSchoolId(request); - requireAdministrativeOrganization(schoolId); + requireMajorManagement(schoolId); if (StringUtils.isBlank(major.getSchoolMajorName())) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "专业名称不能为空"); } @@ -168,7 +168,7 @@ public class SchoolAdminController { @RequestBody SchoolMajor major, HttpServletRequest request) { String schoolId = currentSchoolId(request); - requireAdministrativeOrganization(schoolId); + requireMajorManagement(schoolId); requireMajor(id, schoolId); if (StringUtils.isNotBlank(major.getSchoolFacultyId())) { requireFaculty(major.getSchoolFacultyId(), schoolId); @@ -182,7 +182,7 @@ public class SchoolAdminController { @ApiOperation("学校管理员-删除专业") public ResultEntity deleteMajor(@PathVariable String id, HttpServletRequest request) { String schoolId = currentSchoolId(request); - requireAdministrativeOrganization(schoolId); + requireMajorManagement(schoolId); requireMajor(id, schoolId); if (hasClassInMajor(id) || hasUserByMajor(id)) { return new ResultEntity<>(HttpStatus.ACCEPTED, "专业下存在班级或用户,不能删除"); @@ -425,6 +425,14 @@ public class SchoolAdminController { schoolProductConfigService.requireAdminClassEnabled(schoolId); } + private void requireFacultyManagement(String schoolId) { + schoolProductConfigService.requireFacultyManagementEnabled(schoolId); + } + + private void requireMajorManagement(String schoolId) { + schoolProductConfigService.requireMajorManagementEnabled(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 b770ad8..86e1c86 100644 --- a/src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java +++ b/src/main/java/com/sztzjy/linkCommerce/controller/stu/UserController.java @@ -164,7 +164,7 @@ public class UserController { if (school == null) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "该学校不存在"); } - if (!canManageSchoolStructure(userId, schoolId)) { + if (!canManageFaculty(userId, schoolId)) { return noManagePermission(); } //查询该学校下院系下 专业名称是否重复 @@ -220,7 +220,7 @@ public class UserController { if (schoolFaculty == null) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "院系不存在"); } - if (!canManageSchoolStructure(userId, schoolFaculty.getSchoolId())) { + if (!canManageFaculty(userId, schoolFaculty.getSchoolId())) { return noManagePermission(); } if (hasMajorUnderFaculty(schoolFacultyId)) { @@ -244,7 +244,7 @@ public class UserController { if (existing == null) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "院系不存在"); } - if (!canManageSchoolStructure(userId, existing.getSchoolId())) { + if (!canManageFaculty(userId, existing.getSchoolId())) { return noManagePermission(); } int i = schoolFacultyMapper.updateByPrimaryKey(schoolFaculty); @@ -272,7 +272,7 @@ public class UserController { if (school == null) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "该学校不存在"); } - if (!canManageSchoolStructure(userId, schoolId)) { + if (!canManageMajorStructure(userId, schoolId)) { return noManagePermission(); } //再根据schoolFacultyId查询 如果不存在则返回 @@ -374,8 +374,8 @@ public class UserController { @ApiOperation("班级管理-添加班级") @AnonymousAccess public ResultEntity addSchoolClass(@ApiParam("学校ID") @RequestParam String schoolId, - @ApiParam("院系ID") @RequestParam String schoolFacultyId, - @ApiParam("专业ID") @RequestParam String schoolMajorId, + @ApiParam("院系ID") @RequestParam(required = false) String schoolFacultyId, + @ApiParam("专业ID") @RequestParam(required = false) String schoolMajorId, @ApiParam("班级名称") @RequestParam String className, @RequestParam(required = false) String userId, @RequestParam(required = false) String classType, @@ -386,18 +386,22 @@ public class UserController { if (school == null) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "该学校不存在"); } - //再根据schoolFacultyId查询 如果不存在则返回 - SchoolFaculty schoolFaculty = schoolFacultyMapper.selectByPrimaryKey(schoolFacultyId); - if (schoolFaculty == null) { - return new ResultEntity<>(HttpStatus.BAD_REQUEST, "该院系不存在"); - } - //再根据schoolMajorId查询 如果不存在则返回 - SchoolMajor schoolMajor = schoolMajorMapper.selectByPrimaryKey(schoolMajorId); - if (schoolMajor == null) { - return new ResultEntity<>(HttpStatus.BAD_REQUEST, "该专业不存在"); + String requestedClassType = StringUtils.defaultIfBlank(classType, StringUtils.isBlank(userId) ? "ADMIN" : "TEACHING"); + boolean majorManagementEnabled = isMajorManagementEnabled(schoolId); + if (!isAdminClassManagementEnabled(schoolId) && !"TEACHING".equals(requestedClassType)) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "当前学校只支持教学班"); + } + if (majorManagementEnabled) { + SchoolFaculty schoolFaculty = schoolFacultyMapper.selectByPrimaryKey(schoolFacultyId); + if (schoolFaculty == null) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "该院系不存在"); + } + SchoolMajor schoolMajor = schoolMajorMapper.selectByPrimaryKey(schoolMajorId); + if (schoolMajor == null) { + return new ResultEntity<>(HttpStatus.BAD_REQUEST, "该专业不存在"); + } } //查询班级名称是否存在 - String requestedClassType = StringUtils.defaultIfBlank(classType, StringUtils.isBlank(userId) ? "ADMIN" : "TEACHING"); if (!canCreateSchoolClass(userId, schoolId, requestedClassType)) { return new ResultEntity<>(HttpStatus.BAD_REQUEST, "No permission to add this class type"); } @@ -2016,7 +2020,7 @@ public class UserController { } Userinfo operator = userinfoMapper.selectByPrimaryKey(operatorId); if (isPlatformAdmin(operator)) { - return true; + return !"ADMIN".equals(classType) || isAdminClassManagementEnabled(schoolId); } if (!Integer.valueOf(3).equals(operator == null ? null : operator.getRole()) || !StringUtils.equals(operator.getSchoolId(), schoolId)) { @@ -2026,7 +2030,7 @@ public class UserController { return true; } if ("ADMIN".equals(classType)) { - return true; + return isAdminClassManagementEnabled(schoolId); } return false; } @@ -2048,10 +2052,11 @@ public class UserController { return false; } if (isPlatformAdmin(operator)) { - return true; + return isAdminClassManagementEnabled(schoolClass.getSchoolId()); } return isSchoolTeacher(operator) - && StringUtils.equals(operator.getSchoolId(), schoolClass.getSchoolId()); + && StringUtils.equals(operator.getSchoolId(), schoolClass.getSchoolId()) + && isAdminClassManagementEnabled(schoolClass.getSchoolId()); } private boolean canManageSchoolStructure(String operatorId, String schoolId) { @@ -2062,7 +2067,43 @@ public class UserController { if (isPlatformAdmin(operator)) { return true; } - return isTeacherAdmin(operator) && StringUtils.equals(operator.getSchoolId(), schoolId); + return isTeacherAdmin(operator) + && StringUtils.equals(operator.getSchoolId(), schoolId) + && !isTeacherRosterMode(schoolId); + } + + private boolean canManageFaculty(String operatorId, String schoolId) { + return hasSchoolStructureAuthority(operatorId, schoolId) && isFacultyManagementEnabled(schoolId); + } + + private boolean canManageMajorStructure(String operatorId, String schoolId) { + return hasSchoolStructureAuthority(operatorId, schoolId) && isMajorManagementEnabled(schoolId); + } + + private boolean hasSchoolStructureAuthority(String operatorId, String schoolId) { + if (StringUtils.isAnyBlank(operatorId, schoolId)) { + return false; + } + Userinfo operator = userinfoMapper.selectByPrimaryKey(operatorId); + return isPlatformAdmin(operator) + || (isTeacherAdmin(operator) && StringUtils.equals(operator.getSchoolId(), schoolId)); + } + + private boolean isFacultyManagementEnabled(String schoolId) { + return schoolProductConfigService != null && schoolProductConfigService.isFacultyManagementEnabled(schoolId); + } + + private boolean isMajorManagementEnabled(String schoolId) { + return schoolProductConfigService != null && schoolProductConfigService.isMajorManagementEnabled(schoolId); + } + + private boolean isAdminClassManagementEnabled(String schoolId) { + return schoolProductConfigService != null && schoolProductConfigService.isAdminClassManagementEnabled(schoolId); + } + + private boolean isTeacherRosterMode(String schoolId) { + return schoolProductConfigService != null + && schoolProductConfigService.isTeacherRosterManaged(schoolId); } private boolean canManageMajor(String operatorId, String schoolMajorId) { @@ -2074,7 +2115,7 @@ public class UserController { return false; } SchoolFaculty faculty = schoolFacultyMapper.selectByPrimaryKey(major.getSchoolFacultyId()); - return faculty != null && canManageSchoolStructure(operatorId, faculty.getSchoolId()); + return faculty != null && canManageMajorStructure(operatorId, faculty.getSchoolId()); } private boolean teacherHasCreatedClass(String teacherId) { diff --git a/src/main/java/com/sztzjy/linkCommerce/entity/SchoolProductConfig.java b/src/main/java/com/sztzjy/linkCommerce/entity/SchoolProductConfig.java index 1efca7f..87fe736 100644 --- a/src/main/java/com/sztzjy/linkCommerce/entity/SchoolProductConfig.java +++ b/src/main/java/com/sztzjy/linkCommerce/entity/SchoolProductConfig.java @@ -6,6 +6,9 @@ public class SchoolProductConfig { private String schoolId; private String organizationMode; private String studentRosterOwner; + private Boolean facultyManagementEnabled; + private Boolean majorManagementEnabled; + private Boolean adminClassManagementEnabled; private Date createTime; private Date updateTime; @@ -15,6 +18,12 @@ public class SchoolProductConfig { public void setOrganizationMode(String organizationMode) { this.organizationMode = organizationMode == null ? null : organizationMode.trim(); } public String getStudentRosterOwner() { return studentRosterOwner; } public void setStudentRosterOwner(String studentRosterOwner) { this.studentRosterOwner = studentRosterOwner == null ? null : studentRosterOwner.trim(); } + public Boolean getFacultyManagementEnabled() { return facultyManagementEnabled; } + public void setFacultyManagementEnabled(Boolean facultyManagementEnabled) { this.facultyManagementEnabled = facultyManagementEnabled; } + public Boolean getMajorManagementEnabled() { return majorManagementEnabled; } + public void setMajorManagementEnabled(Boolean majorManagementEnabled) { this.majorManagementEnabled = majorManagementEnabled; } + public Boolean getAdminClassManagementEnabled() { return adminClassManagementEnabled; } + public void setAdminClassManagementEnabled(Boolean adminClassManagementEnabled) { this.adminClassManagementEnabled = adminClassManagementEnabled; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Date getUpdateTime() { return updateTime; } diff --git a/src/main/java/com/sztzjy/linkCommerce/service/SchoolProductConfigService.java b/src/main/java/com/sztzjy/linkCommerce/service/SchoolProductConfigService.java index e018a37..9644b3d 100644 --- a/src/main/java/com/sztzjy/linkCommerce/service/SchoolProductConfigService.java +++ b/src/main/java/com/sztzjy/linkCommerce/service/SchoolProductConfigService.java @@ -11,6 +11,16 @@ public interface SchoolProductConfigService { boolean requiresAdminClass(String schoolId); + boolean isFacultyManagementEnabled(String schoolId); + + boolean isMajorManagementEnabled(String schoolId); + + boolean isAdminClassManagementEnabled(String schoolId); + + void requireFacultyManagementEnabled(String schoolId); + + void requireMajorManagementEnabled(String schoolId); + boolean isTeacherRosterManaged(String schoolId); void requireAdminClassEnabled(String schoolId); 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 3ebc3cd..74bd51c 100644 --- a/src/main/java/com/sztzjy/linkCommerce/service/impl/SchoolProductConfigServiceImpl.java +++ b/src/main/java/com/sztzjy/linkCommerce/service/impl/SchoolProductConfigServiceImpl.java @@ -1,12 +1,8 @@ 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; @@ -19,18 +15,13 @@ import java.util.Date; public class SchoolProductConfigServiceImpl implements SchoolProductConfigService { public static final String ADMIN_CLASS_ENABLED = "ADMIN_CLASS_ENABLED"; public static final String TEACHING_CLASS_ONLY = "TEACHING_CLASS_ONLY"; + public static final String CUSTOM = "CUSTOM"; public static final String SCHOOL_ADMIN = "SCHOOL_ADMIN"; public static final String TEACHER = "TEACHER"; @Autowired public SchoolProductConfigMapper schoolProductConfigMapper; - @Autowired - public SchoolClassMapper schoolClassMapper; - - @Autowired - public UserinfoMapper userinfoMapper; - @Override public void createDefaultConfig(String schoolId) { if (StringUtils.isBlank(schoolId)) { @@ -40,6 +31,9 @@ public class SchoolProductConfigServiceImpl implements SchoolProductConfigServic config.setSchoolId(schoolId); config.setOrganizationMode(ADMIN_CLASS_ENABLED); config.setStudentRosterOwner(SCHOOL_ADMIN); + config.setFacultyManagementEnabled(true); + config.setMajorManagementEnabled(true); + config.setAdminClassManagementEnabled(true); config.setCreateTime(new Date()); config.setUpdateTime(new Date()); schoolProductConfigMapper.insert(config); @@ -50,16 +44,8 @@ public class SchoolProductConfigServiceImpl implements SchoolProductConfigServic if (config == null || StringUtils.isBlank(config.getSchoolId())) { throw new ServiceException(HttpStatus.BAD_REQUEST, "学校组织配置不存在"); } - boolean standard = ADMIN_CLASS_ENABLED.equals(config.getOrganizationMode()) && SCHOOL_ADMIN.equals(config.getStudentRosterOwner()); - boolean teacherManaged = TEACHING_CLASS_ONLY.equals(config.getOrganizationMode()) && TEACHER.equals(config.getStudentRosterOwner()); - if (!standard && !teacherManaged) { - throw new ServiceException(HttpStatus.BAD_REQUEST, "学校组织模式与名单维护方不匹配"); - } SchoolProductConfig current = getRequiredConfig(config.getSchoolId()); - if (!StringUtils.equals(current.getOrganizationMode(), config.getOrganizationMode()) - && hasAdministrativeOrganizationData(config.getSchoolId())) { - throw new ServiceException(HttpStatus.BAD_REQUEST, "学校已有组织数据,不能直接切换组织模式"); - } + normalizeManagementCapabilities(config); config.setCreateTime(current.getCreateTime()); config.setUpdateTime(new Date()); schoolProductConfigMapper.updateByPrimaryKey(config); @@ -80,7 +66,36 @@ public class SchoolProductConfigServiceImpl implements SchoolProductConfigServic @Override public boolean requiresAdminClass(String schoolId) { - return ADMIN_CLASS_ENABLED.equals(getRequiredConfig(schoolId).getOrganizationMode()); + return isAdminClassManagementEnabled(schoolId); + } + + @Override + public boolean isFacultyManagementEnabled(String schoolId) { + return Boolean.TRUE.equals(getRequiredConfig(schoolId).getFacultyManagementEnabled()); + } + + @Override + public boolean isMajorManagementEnabled(String schoolId) { + return Boolean.TRUE.equals(getRequiredConfig(schoolId).getMajorManagementEnabled()); + } + + @Override + public boolean isAdminClassManagementEnabled(String schoolId) { + return Boolean.TRUE.equals(getRequiredConfig(schoolId).getAdminClassManagementEnabled()); + } + + @Override + public void requireFacultyManagementEnabled(String schoolId) { + if (!isFacultyManagementEnabled(schoolId)) { + throw new ServiceException(HttpStatus.BAD_REQUEST, "当前学校未启用院系管理"); + } + } + + @Override + public void requireMajorManagementEnabled(String schoolId) { + if (!isMajorManagementEnabled(schoolId)) { + throw new ServiceException(HttpStatus.BAD_REQUEST, "当前学校未启用专业管理"); + } } @Override @@ -95,18 +110,23 @@ public class SchoolProductConfigServiceImpl implements SchoolProductConfigServic } } - private boolean hasAdministrativeOrganizationData(String schoolId) { - SchoolClassExample classExample = new SchoolClassExample(); - classExample.createCriteria() - .andSchoolIdEqualTo(schoolId) - .andClassTypeEqualTo("ADMIN"); - if (schoolClassMapper.countByExample(classExample) > 0) { - return true; + private void normalizeManagementCapabilities(SchoolProductConfig config) { + boolean defaultEnabled = ADMIN_CLASS_ENABLED.equals(config.getOrganizationMode()); + boolean facultyEnabled = config.getFacultyManagementEnabled() == null ? defaultEnabled : config.getFacultyManagementEnabled(); + boolean majorEnabled = facultyEnabled && (config.getMajorManagementEnabled() == null ? defaultEnabled : config.getMajorManagementEnabled()); + boolean adminClassEnabled = majorEnabled && (config.getAdminClassManagementEnabled() == null ? defaultEnabled : config.getAdminClassManagementEnabled()); + config.setFacultyManagementEnabled(facultyEnabled); + config.setMajorManagementEnabled(majorEnabled); + config.setAdminClassManagementEnabled(adminClassEnabled); + if (facultyEnabled && majorEnabled && adminClassEnabled) { + config.setOrganizationMode(ADMIN_CLASS_ENABLED); + config.setStudentRosterOwner(SCHOOL_ADMIN); + } else if (!facultyEnabled && !majorEnabled && !adminClassEnabled) { + config.setOrganizationMode(TEACHING_CLASS_ONLY); + config.setStudentRosterOwner(TEACHER); + } else { + config.setOrganizationMode(CUSTOM); + config.setStudentRosterOwner(TEACHER); } - UserinfoExample userExample = new UserinfoExample(); - userExample.createCriteria() - .andSchoolIdEqualTo(schoolId) - .andSchoolClassIdIsNotNull(); - return userinfoMapper.countByExample(userExample) > 0; } } diff --git a/src/main/java/com/sztzjy/linkCommerce/service/impl/UserInfoServiceImpl.java b/src/main/java/com/sztzjy/linkCommerce/service/impl/UserInfoServiceImpl.java index d03799e..ae0cb07 100644 --- a/src/main/java/com/sztzjy/linkCommerce/service/impl/UserInfoServiceImpl.java +++ b/src/main/java/com/sztzjy/linkCommerce/service/impl/UserInfoServiceImpl.java @@ -54,7 +54,14 @@ public class UserInfoServiceImpl implements UserInfoService { Userinfo userinfo = userInfoMapper.selectByPrimaryKey(userId); String schoolMajorId = userinfo.getSchoolMajorId(); SchoolClassExample schoolClassExample = new SchoolClassExample(); - schoolClassExample.createCriteria().andSchoolMajorIdEqualTo(schoolMajorId); + SchoolClassExample.Criteria criteria = schoolClassExample.createCriteria(); + if (StringUtils.hasText(schoolMajorId)) { + criteria.andSchoolMajorIdEqualTo(schoolMajorId); + } else { + criteria.andSchoolIdEqualTo(userinfo.getSchoolId()) + .andClassTypeEqualTo("TEACHING") + .andCreatedByEqualTo(userId); + } List schoolClasses = schoolClassMapper.selectByExample(schoolClassExample); List list=new ArrayList<>(); for (int i = 0; i < schoolClasses.size(); i++) { diff --git a/src/main/resources/mappers/SchoolProductConfigMapper.xml b/src/main/resources/mappers/SchoolProductConfigMapper.xml index bf91bf8..ee0c1a4 100644 --- a/src/main/resources/mappers/SchoolProductConfigMapper.xml +++ b/src/main/resources/mappers/SchoolProductConfigMapper.xml @@ -5,18 +5,21 @@ + + + - school_id, organization_mode, student_roster_owner, create_time, update_time + school_id, organization_mode, student_roster_owner, faculty_management_enabled, major_management_enabled, admin_class_management_enabled, create_time, update_time - insert into school_product_config (school_id, organization_mode, student_roster_owner, create_time, update_time) - values (#{schoolId,jdbcType=VARCHAR}, #{organizationMode,jdbcType=VARCHAR}, #{studentRosterOwner,jdbcType=VARCHAR}, #{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP}) + insert into school_product_config (school_id, organization_mode, student_roster_owner, faculty_management_enabled, major_management_enabled, admin_class_management_enabled, create_time, update_time) + values (#{schoolId,jdbcType=VARCHAR}, #{organizationMode,jdbcType=VARCHAR}, #{studentRosterOwner,jdbcType=VARCHAR}, #{facultyManagementEnabled,jdbcType=BIT}, #{majorManagementEnabled,jdbcType=BIT}, #{adminClassManagementEnabled,jdbcType=BIT}, #{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP}) - update school_product_config set organization_mode = #{organizationMode,jdbcType=VARCHAR}, student_roster_owner = #{studentRosterOwner,jdbcType=VARCHAR}, update_time = #{updateTime,jdbcType=TIMESTAMP} where school_id = #{schoolId,jdbcType=VARCHAR} + update school_product_config set organization_mode = #{organizationMode,jdbcType=VARCHAR}, student_roster_owner = #{studentRosterOwner,jdbcType=VARCHAR}, faculty_management_enabled = #{facultyManagementEnabled,jdbcType=BIT}, major_management_enabled = #{majorManagementEnabled,jdbcType=BIT}, admin_class_management_enabled = #{adminClassManagementEnabled,jdbcType=BIT}, update_time = #{updateTime,jdbcType=TIMESTAMP} where school_id = #{schoolId,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 d02dabf..7fd1a23 100644 --- a/src/test/java/com/sztzjy/linkCommerce/controller/schooladmin/SchoolAdminControllerTest.java +++ b/src/test/java/com/sztzjy/linkCommerce/controller/schooladmin/SchoolAdminControllerTest.java @@ -33,4 +33,17 @@ class SchoolAdminControllerTest { verify(configService).requireAdminClassEnabled("school-zj"); } + + @Test + void facultyAndMajorGuardsDelegateToTheirOwnConfigurationSwitches() { + SchoolAdminController controller = new SchoolAdminController(); + SchoolProductConfigService configService = mock(SchoolProductConfigService.class); + ReflectionTestUtils.setField(controller, "schoolProductConfigService", configService); + + ReflectionTestUtils.invokeMethod(controller, "requireFacultyManagement", "school-zj"); + ReflectionTestUtils.invokeMethod(controller, "requireMajorManagement", "school-zj"); + + verify(configService).requireFacultyManagementEnabled("school-zj"); + verify(configService).requireMajorManagementEnabled("school-zj"); + } } 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 301edf3..2238724 100644 --- a/src/test/java/com/sztzjy/linkCommerce/controller/stu/UserControllerTeacherAdminTest.java +++ b/src/test/java/com/sztzjy/linkCommerce/controller/stu/UserControllerTeacherAdminTest.java @@ -14,6 +14,7 @@ import com.sztzjy.linkCommerce.mapper.SchoolMajorMapper; import com.sztzjy.linkCommerce.mapper.TeachingClassStudentMapper; import com.sztzjy.linkCommerce.mapper.UserinfoMapper; import com.sztzjy.linkCommerce.service.UserInfoService; +import com.sztzjy.linkCommerce.service.SchoolProductConfigService; import com.sztzjy.linkCommerce.entity.importDto.SchoolAdminStudentImportDTO; import com.sztzjy.linkCommerce.entity.importDto.TeachingClassStudentImportDTO; import com.sztzjy.linkCommerce.util.Pinyin4jUtil; @@ -80,6 +81,18 @@ class UserControllerTeacherAdminTest { verify(controller.schoolFacultyMapper).insert(any(SchoolFaculty.class)); } + @Test + void teacherAdminCannotAddFacultyWhenFacultyManagementSwitchIsOff() { + UserController controller = controllerWithCommonMocks(); + when(controller.userinfoMapper.selectByPrimaryKey("teacher-admin")).thenReturn(teacher("teacher-admin", true)); + when(controller.schoolProductConfigService.isFacultyManagementEnabled("school-1")).thenReturn(false); + + ResultEntity result = controller.addSchoolFaculty("school-1", "faculty", null, null, null, "teacher-admin"); + + assertEquals(HttpStatus.BAD_REQUEST, result.getStatusCode()); + verify(controller.schoolFacultyMapper, never()).insert(any(SchoolFaculty.class)); + } + @Test void ordinaryTeacherCannotAddMajor() { UserController controller = controllerWithCommonMocks(); @@ -123,6 +136,24 @@ class UserControllerTeacherAdminTest { assertEquals("LOCAL", captor.getValue().getDataSource()); } + @Test + void teacherRosterSchoolCreatesTeachingClassWithoutFacultyOrMajor() { + UserController controller = controllerWithCommonMocks(); + controller.schoolProductConfigService = mock(SchoolProductConfigService.class); + when(controller.schoolProductConfigService.isTeacherRosterManaged("school-1")).thenReturn(true); + when(controller.schoolClassMapper.selectByExample(any())).thenReturn(Collections.emptyList()); + when(controller.schoolClassMapper.insert(any(SchoolClass.class))).thenReturn(1); + when(controller.pinyin4jUtil.convertToPinyin(any())).thenReturn("py"); + + ResultEntity result = controller.addSchoolClass("school-1", null, null, "teaching-class", + "teacher-1", "TEACHING", null); + + assertEquals(HttpStatus.OK, result.getStatusCode()); + verify(controller.schoolClassMapper).insert(argThat(schoolClass -> + "TEACHING".equals(schoolClass.getClassType()) + && schoolClass.getSchoolMajorId() == null)); + } + @Test void ordinaryTeacherCanAddAdminClassWithinOwnSchool() { UserController controller = controllerWithCommonMocks(); @@ -943,6 +974,7 @@ class UserControllerTeacherAdminTest { controller.teachingClassStudentMapper = mock(TeachingClassStudentMapper.class); controller.userinfoMapper = mock(UserinfoMapper.class); controller.userInfoService = mock(UserInfoService.class); + controller.schoolProductConfigService = mock(SchoolProductConfigService.class); controller.pinyin4jUtil = mock(Pinyin4jUtil.class); controller.cptfController = mock(CptfController.class); @@ -961,6 +993,9 @@ class UserControllerTeacherAdminTest { when(controller.schoolMajorMapper.selectByPrimaryKey("major-1")).thenReturn(major); when(controller.userinfoMapper.selectByPrimaryKey("teacher-1")).thenReturn(teacher("teacher-1")); when(controller.userinfoMapper.selectByPrimaryKey("teacher-admin")).thenReturn(teacher("teacher-admin", true)); + when(controller.schoolProductConfigService.isFacultyManagementEnabled("school-1")).thenReturn(true); + when(controller.schoolProductConfigService.isMajorManagementEnabled("school-1")).thenReturn(true); + when(controller.schoolProductConfigService.isAdminClassManagementEnabled("school-1")).thenReturn(true); return controller; } 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 e954243..9b05266 100644 --- a/src/test/java/com/sztzjy/linkCommerce/service/impl/SchoolProductConfigServiceImplTest.java +++ b/src/test/java/com/sztzjy/linkCommerce/service/impl/SchoolProductConfigServiceImplTest.java @@ -68,29 +68,37 @@ class SchoolProductConfigServiceImplTest { verify(service.schoolProductConfigMapper).insert(org.mockito.ArgumentMatchers.argThat(config -> "school-new".equals(config.getSchoolId()) && "ADMIN_CLASS_ENABLED".equals(config.getOrganizationMode()) - && "SCHOOL_ADMIN".equals(config.getStudentRosterOwner()))); + && "SCHOOL_ADMIN".equals(config.getStudentRosterOwner()) + && config.getFacultyManagementEnabled() + && config.getMajorManagementEnabled() + && config.getAdminClassManagementEnabled())); } @Test - void updateRejectsOrganizationModeChangeWhenAdministrativeDataExists() { + void disablingFacultyManagementCascadesToMajorAndAdministrativeClassWithoutDeletingData() { 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"))); + SchoolProductConfig requested = config("school-standard", "CUSTOM", "TEACHER"); + requested.setFacultyManagementEnabled(false); + requested.setMajorManagementEnabled(true); + requested.setAdminClassManagementEnabled(true); + + service.updateConfig(requested); + + verify(service.schoolProductConfigMapper).updateByPrimaryKey(org.mockito.ArgumentMatchers.argThat(updated -> + !updated.getFacultyManagementEnabled() + && !updated.getMajorManagementEnabled() + && !updated.getAdminClassManagementEnabled() + && "TEACHING_CLASS_ONLY".equals(updated.getOrganizationMode()))); } @Test void updateKeepsTheOriginalCreationTime() { 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"); Date createdAt = new Date(1000L); current.setCreateTime(createdAt); @@ -107,6 +115,9 @@ class SchoolProductConfigServiceImplTest { config.setSchoolId(schoolId); config.setOrganizationMode(organizationMode); config.setStudentRosterOwner(rosterOwner); + config.setFacultyManagementEnabled("ADMIN_CLASS_ENABLED".equals(organizationMode)); + config.setMajorManagementEnabled("ADMIN_CLASS_ENABLED".equals(organizationMode)); + config.setAdminClassManagementEnabled("ADMIN_CLASS_ENABLED".equals(organizationMode)); return config; } } diff --git a/src/test/java/com/sztzjy/linkCommerce/service/impl/UserInfoServiceImplOrganizationModeTest.java b/src/test/java/com/sztzjy/linkCommerce/service/impl/UserInfoServiceImplOrganizationModeTest.java new file mode 100644 index 0000000..7363474 --- /dev/null +++ b/src/test/java/com/sztzjy/linkCommerce/service/impl/UserInfoServiceImplOrganizationModeTest.java @@ -0,0 +1,40 @@ +package com.sztzjy.linkCommerce.service.impl; + +import com.sztzjy.linkCommerce.entity.SchoolClass; +import com.sztzjy.linkCommerce.entity.Userinfo; +import com.sztzjy.linkCommerce.mapper.SchoolClassMapper; +import com.sztzjy.linkCommerce.mapper.UserinfoMapper; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import java.util.Collections; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class UserInfoServiceImplOrganizationModeTest { + + @Test + void teacherWithoutMajorSeesOnlyTeachingClassesTheyCreated() { + UserInfoServiceImpl service = new UserInfoServiceImpl(); + service.userInfoMapper = mock(UserinfoMapper.class); + service.schoolClassMapper = mock(SchoolClassMapper.class); + Userinfo teacher = new Userinfo(); + teacher.setUserId("teacher-zj"); + teacher.setSchoolId("school-zj"); + teacher.setSchoolMajorId(null); + SchoolClass teachingClass = new SchoolClass(); + teachingClass.setClassName("电商实训一班"); + when(service.userInfoMapper.selectByPrimaryKey("teacher-zj")).thenReturn(teacher); + when(service.schoolClassMapper.selectByExample(org.mockito.ArgumentMatchers.any())) + .thenReturn(Collections.singletonList(teachingClass)); + + assertEquals(Collections.singletonList("电商实训一班"), service.getClassNameList("teacher-zj")); + + ArgumentCaptor example = ArgumentCaptor.forClass(com.sztzjy.linkCommerce.entity.SchoolClassExample.class); + verify(service.schoolClassMapper).selectByExample(example.capture()); + assertEquals(3, example.getValue().getOredCriteria().get(0).getAllCriteria().size()); + } +}