feat: import roster students by class name

main
chenyuan 4 weeks ago
parent d3cff4553c
commit 0c985a3c55

@ -1272,26 +1272,56 @@ public class UserController {
String teachingClassId,
String operatorId) {
Userinfo operator = userinfoMapper.selectByPrimaryKey(operatorId);
SchoolClass teachingClass = schoolClassMapper.selectByPrimaryKey(teachingClassId);
if (!isSchoolTeacher(operator) || !isOwnedTeachingClass(teachingClass, operatorId)
|| !schoolProductConfigService.isTeacherRosterManaged(operator.getSchoolId())) {
if (!isSchoolTeacher(operator) || !schoolProductConfigService.isTeacherRosterManaged(operator.getSchoolId())) {
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "无权维护该教学班名单");
}
if (rows == null || rows.isEmpty()) {
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "未读取到可导入的学生数据");
}
Map<String, SchoolClass> managedClassesByName = new HashMap<>();
if (StringUtils.isNotBlank(teachingClassId)) {
SchoolClass teachingClass = schoolClassMapper.selectByPrimaryKey(teachingClassId);
if (!canManageTeachingClass(operator, teachingClass)) {
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "无权维护该教学班名单");
}
managedClassesByName.put(teachingClass.getClassName(), teachingClass);
} else {
SchoolClassExample example = new SchoolClassExample();
SchoolClassExample.Criteria criteria = example.createCriteria()
.andSchoolIdEqualTo(operator.getSchoolId())
.andClassTypeEqualTo("TEACHING");
if (!isTeacherAdmin(operator)) {
criteria.andCreatedByEqualTo(operator.getUserId());
}
List<SchoolClass> teachingClasses = schoolClassMapper.selectByExample(example);
for (SchoolClass teachingClass : teachingClasses == null ? Collections.<SchoolClass>emptyList() : teachingClasses) {
managedClassesByName.put(teachingClass.getClassName(), teachingClass);
}
}
List<TeacherRosterImportRecord> importRecords = new ArrayList<>();
Set<String> usernames = new HashSet<>();
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)) {
String className = row == null ? "" : StringUtils.trimToEmpty(row.getClassName());
if (StringUtils.isBlank(name) || StringUtils.isBlank(username) || (StringUtils.isBlank(teachingClassId) && StringUtils.isBlank(className))) {
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "学生姓名或学号无效");
}
SchoolClass targetClass = StringUtils.isNotBlank(teachingClassId)
? managedClassesByName.values().iterator().next()
: managedClassesByName.get(className);
if (targetClass == null) {
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "班级不存在或无管理权限:" + className);
}
if (!usernames.add(username)) {
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "导入文件中学号重复:" + username);
}
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");
importRecords.add(new TeacherRosterImportRecord(targetClass.getSchoolClassId(), existingStudent, false));
continue;
}
if (userInfoService.existsByUserName(username)) {
@ -1307,16 +1337,33 @@ public class UserController {
student.setSchoolId(operator.getSchoolId());
student.setCreateTime(new Date());
student.setCodeFrom("教师教学班导入");
if (userinfoMapper.insertSelective(student) <= 0) {
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "学生导入失败");
importRecords.add(new TeacherRosterImportRecord(targetClass.getSchoolClassId(), student, true));
}
for (TeacherRosterImportRecord record : importRecords) {
Userinfo student = record.student;
if (record.needsInsert && userinfoMapper.insertSelective(student) <= 0) {
throw new IllegalStateException("学生导入失败");
}
upsertActiveTeachingClassMember(teachingClassId, student, null, "TEACHER_ROSTER_IMPORT");
upsertActiveTeachingClassMember(record.teachingClassId, student, null, "TEACHER_ROSTER_IMPORT");
}
return new ResultEntity<>(HttpStatus.OK, "导入成功");
}
private static class TeacherRosterImportRecord {
private final String teachingClassId;
private final Userinfo student;
private final boolean needsInsert;
private TeacherRosterImportRecord(String teachingClassId, Userinfo student, boolean needsInsert) {
this.teachingClassId = teachingClassId;
this.student = student;
this.needsInsert = needsInsert;
}
}
@PostMapping("/teaching-classes/{teachingClassId}/students/import")
@ApiOperation("教师教学班-导入学生名单")
@Transactional(rollbackFor = Exception.class)
public ResultEntity importTeacherRoster(@PathVariable String teachingClassId,
@RequestParam MultipartFile file,
HttpServletRequest request) {
@ -1336,6 +1383,27 @@ public class UserController {
}
}
@PostMapping("/teaching-classes/students/import")
@ApiOperation("教师教学班-按班级名称导入学生名单")
@Transactional(rollbackFor = Exception.class)
public ResultEntity importTeacherRosterByClassName(@RequestParam MultipartFile file,
HttpServletRequest request) {
JwtUser user = TokenProvider.getJWTUser(request);
if (user == null || StringUtils.isBlank(user.getUserId())) {
return new ResultEntity<>(HttpStatus.UNAUTHORIZED, "请先登录");
}
if (file == null || file.isEmpty()) {
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "请选择要导入的Excel文件");
}
try (InputStream inputStream = file.getInputStream()) {
List<TeacherRosterStudentImportDTO> rows = EasyExcel.read(inputStream)
.head(TeacherRosterStudentImportDTO.class).sheet().doReadSync();
return importTeacherRosterRows(rows, null, user.getUserId());
} catch (Exception exception) {
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "数据校验失败", exception.getMessage());
}
}
ResultEntity addSchoolClass(String schoolId,
String schoolFacultyId,
String schoolMajorId,

@ -7,9 +7,13 @@ public class TeacherRosterStudentImportDTO {
private String name;
@ExcelProperty("学号")
private String username;
@ExcelProperty("班级")
private String className;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getClassName() { return className; }
public void setClassName(String className) { this.className = className; }
}

@ -17,6 +17,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import java.util.Collections;
import java.util.Arrays;
import java.util.Date;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
@ -71,7 +72,7 @@ class TeacherRosterImportTest {
assertNull(student.getValue().getSex());
assertNull(student.getValue().getPhone());
assertNull(student.getValue().getEmail());
assertEquals(2, TeacherRosterStudentImportDTO.class.getDeclaredFields().length);
assertEquals(3, TeacherRosterStudentImportDTO.class.getDeclaredFields().length);
ArgumentCaptor<TeachingClassStudent> membership = ArgumentCaptor.forClass(TeachingClassStudent.class);
verify(controller.teachingClassStudentMapper).insertSelective(membership.capture());
assertEquals("teach-1", membership.getValue().getTeachingClassId());
@ -91,6 +92,7 @@ class TeacherRosterImportTest {
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("张三");
student.setCreateTime(new Date());
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);
@ -105,4 +107,42 @@ class TeacherRosterImportTest {
verify(controller.userinfoMapper, never()).insertSelective(any(Userinfo.class));
verify(controller.teachingClassStudentMapper).insertSelective(any(TeachingClassStudent.class));
}
@Test
void teacherAdminRosterImportRoutesStudentByClassNameWithoutSelectedClass() {
UserController controller = new UserController();
controller.userinfoMapper = mock(UserinfoMapper.class);
controller.schoolClassMapper = mock(SchoolClassMapper.class);
controller.teachingClassStudentMapper = mock(TeachingClassStudentMapper.class);
controller.userInfoService = mock(UserInfoService.class);
controller.schoolProductConfigService = mock(SchoolProductConfigService.class);
Userinfo teacherAdmin = new Userinfo();
teacherAdmin.setUserId("teacher-admin");
teacherAdmin.setRole(3);
teacherAdmin.setTeacherAdmin(true);
teacherAdmin.setSchoolId("school-zj");
SchoolClass teachingClass = new SchoolClass();
teachingClass.setSchoolClassId("teach-3");
teachingClass.setSchoolId("school-zj");
teachingClass.setClassType("TEACHING");
teachingClass.setClassName("教学三班");
teachingClass.setCreatedBy("teacher-2");
when(controller.userinfoMapper.selectByPrimaryKey("teacher-admin")).thenReturn(teacherAdmin);
when(controller.schoolProductConfigService.isTeacherRosterManaged("school-zj")).thenReturn(true);
when(controller.schoolClassMapper.selectByExample(any())).thenReturn(Collections.singletonList(teachingClass));
when(controller.userInfoService.existsByUserName("20260003")).thenReturn(false);
when(controller.userinfoMapper.insertSelective(any(Userinfo.class))).thenReturn(1);
TeacherRosterStudentImportDTO row = new TeacherRosterStudentImportDTO();
row.setName("赵六");
row.setUsername("20260003");
row.setClassName("教学三班");
ResultEntity result = controller.importTeacherRosterRows(Collections.singletonList(row), null, "teacher-admin");
assertEquals(HttpStatus.OK, result.getStatusCode());
ArgumentCaptor<TeachingClassStudent> membership = ArgumentCaptor.forClass(TeachingClassStudent.class);
verify(controller.teachingClassStudentMapper).insertSelective(membership.capture());
assertEquals("teach-3", membership.getValue().getTeachingClassId());
}
}

Loading…
Cancel
Save