class id 不允许null
This commit is contained in:
@@ -41,6 +41,9 @@ public interface ISendUserBaseService {
|
||||
/** 导入失败回滚:删除已推送成功的教师平台账号(syncedList 与 groupIds 按下标一一对应) */
|
||||
void rollbackSyncedTeachers(List<BoaUser> syncedList, List<Integer> groupIds, Integer schId);
|
||||
|
||||
/** 导入失败回滚:删除已成功推送到平台的组(年级组/班级组/学段组),避免留下孤儿组 */
|
||||
void rollbackCreatedGroups(List<Integer> groupIds, Integer schId);
|
||||
|
||||
void moveTeacherToGroup(List<SendMoveGroupUserDTO> teacherList, Integer schId);
|
||||
|
||||
void moveStudentToGroup(List<Integer> stuIds,Integer classId,Integer schId);
|
||||
|
||||
+122
-46
@@ -108,6 +108,10 @@ public class SchClassImportService {
|
||||
schsystemIdByAcademicStage.put(schsystemId,stuParentId);
|
||||
}
|
||||
}
|
||||
|
||||
Map<Integer, List<SelectIntVO>> schGradeGroupMap = comSchTreeService.getSchGroupTypeList(schId, NodeType.GRADE.getId());
|
||||
Map<Integer, List<SelectIntVO>> schClassGroupMap = comSchTreeService.getSchGroupTypeList(schId, NodeType.CLASS.getId());
|
||||
|
||||
try (InputStream is = file.getInputStream()) {
|
||||
List<SchTeacher> schTeacherList = schTeacherService.getSchTeacherList(schId);
|
||||
List<SelectIntVO> gradeList = baseSchsystemGradeService.getGradeSelect(schId, null, null);
|
||||
@@ -147,13 +151,15 @@ public class SchClassImportService {
|
||||
|
||||
Map<Integer, Integer> nowYearGradeMap = baseSchsystemGradeService.getNowYearGradeMap(user.getSchId(), schsystemId);
|
||||
|
||||
Map<Integer, List<SelectIntVO>> schGradeGroupMap = comSchTreeService.getSchGroupTypeList(schId, NodeType.GRADE.getId());
|
||||
Map<Integer, List<SelectIntVO>> schClassGroupMap = comSchTreeService.getSchGroupTypeList(schId, NodeType.CLASS.getId());
|
||||
|
||||
List<SelectIntVO> gradeGroupList = schGradeGroupMap.get(schsystemId);
|
||||
List<SelectIntVO> classGroupList = schClassGroupMap.get(schsystemId);
|
||||
|
||||
Integer year = nowYearGradeMap.get(gradeId);
|
||||
if (year == null) {
|
||||
errorMsgArr.add(new ErrorExcelColumn(currentRow, item.getGradeName(), "该年级未匹配到入学年份,无法导入!"));
|
||||
continue;
|
||||
}
|
||||
Integer sort = OtherUtil.extractClassNumber(item.getClazzName());
|
||||
String clazzName = sort + "班";
|
||||
|
||||
@@ -197,25 +203,26 @@ public class SchClassImportService {
|
||||
clazz.setGroupId(parentId);
|
||||
|
||||
// 班级组推送平台,classId 取平台组 ID(与 addBaseSchClass 一致);同理防重复创建
|
||||
// classCacheKey 需带 schsystemId:多学制下不同学段可能同一年份+班号(如初中/高中都有 202501),
|
||||
// 若只用 code 作 key,会导致第二个学制的班级复用第一个学制的平台组,造成班级组缺失。
|
||||
String classCacheKey = schsystemId + "_" + code;
|
||||
Integer existClassId = (classGroupList == null) ? null
|
||||
: classGroupList.stream()
|
||||
.filter(s -> Objects.equals(code, s.getName()))
|
||||
.map(SelectIntVO::getId).findFirst().orElse(null);
|
||||
if (existClassId == null) {
|
||||
existClassId = createdClassCache.get(code);
|
||||
if (existClassId == null) {
|
||||
existClassId = createdClassCache.get(classCacheKey);
|
||||
}
|
||||
if (existClassId != null && existClassId > 0) {
|
||||
clazz.setClassId(existClassId);
|
||||
} else {
|
||||
BoaGroup classGroup = sendUserBaseService.addGroup(code, parentId, sort, NodeType.CLASS, schId);
|
||||
clazz.setClassId(classGroup.getId());
|
||||
createdGroupIds.add(classGroup.getId());
|
||||
createdClassCache.put(classCacheKey, classGroup.getId());
|
||||
}
|
||||
}
|
||||
if (existClassId != null && existClassId > 0) {
|
||||
clazz.setClassId(existClassId);
|
||||
} else {
|
||||
BoaGroup classGroup = sendUserBaseService.addGroup(code, parentId, sort, NodeType.CLASS, schId);
|
||||
clazz.setClassId(classGroup.getId());
|
||||
createdGroupIds.add(classGroup.getId());
|
||||
createdClassCache.put(code, classGroup.getId());
|
||||
}
|
||||
}
|
||||
|
||||
clazz.setCname(item.getClazzCName());
|
||||
|
||||
// 班主任
|
||||
if (StringUtils.isNotBlank(item.getBzr())) {
|
||||
Optional<SchTeacher> teacherOpt = schTeacherList.stream()
|
||||
@@ -256,27 +263,17 @@ public class SchClassImportService {
|
||||
throw new DException(ErrorCode.CUSTOM,"导入失败,请检查错误列表",errorMsgArr);
|
||||
}
|
||||
|
||||
saveClassList = schClassRepository.saveAll(saveClassList);
|
||||
for (SchClass clazz : saveClassList) {
|
||||
if (clazz.getClassId().equals(0)) {
|
||||
clazz.setClassId(clazz.getId());
|
||||
}
|
||||
}
|
||||
schClassRepository.saveAll(saveClassList);
|
||||
cacheService.clearClassCache(user.getSchId());
|
||||
logService.importLogs(user, saveClassList);
|
||||
|
||||
} catch (DException e) {
|
||||
// 业务/校验异常也要回滚已推送到平台的组,避免孤儿组
|
||||
sendUserBaseService.rollbackCreatedGroups(createdGroupIds, schId);
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
// 导入失败:回滚已成功推送到平台的班级组/年级组,避免孤儿组
|
||||
for (Integer groupId : createdGroupIds) {
|
||||
try {
|
||||
sendUserBaseService.deleteGroup(groupId, schId);
|
||||
} catch (Exception ignore) {
|
||||
log.error("回滚平台组失败 groupId={}", groupId, ignore);
|
||||
}
|
||||
}
|
||||
sendUserBaseService.rollbackCreatedGroups(createdGroupIds, schId);
|
||||
log.error("导入班级时发生系统异常,操作人:" + user.getUserName(), e);
|
||||
throw new DException(ErrorCode.CUSTOM,"导入失败,请联系管理员",null,e);
|
||||
}
|
||||
@@ -292,12 +289,26 @@ public class SchClassImportService {
|
||||
params.setTitleRows(1);
|
||||
params.setHeadRows(1);
|
||||
Date now = new Date();
|
||||
Integer schId = user.getSchId();
|
||||
List<Integer> createdGroupIds = new ArrayList<>();
|
||||
|
||||
Map<Integer, List<SelectIntVO>> schGradeGroupMap = comSchTreeService.getSchGroupTypeList(user.getSchId(), NodeType.GRADE.getId());
|
||||
// 单学制:年级组直接挂在学生组下,无需再建学段组
|
||||
BoaGroup stuGroup = comSchTreeService.getStuTree(schId, false);
|
||||
if (stuGroup == null) {
|
||||
throw new DException("学生组不存在!");
|
||||
}
|
||||
Integer stuParentId = stuGroup.getId();
|
||||
|
||||
Map<Integer, List<SelectIntVO>> schGradeGroupMap = comSchTreeService.getSchGroupTypeList(schId, NodeType.GRADE.getId());
|
||||
if (schGradeGroupMap.isEmpty()) {
|
||||
throw new DException("该学制下没有学级,请先同步年级组数据!");
|
||||
}
|
||||
//Map<Integer, List<SelectIntVO>> schClassGroupMap = comSchTreeService.getSchGroupTypeList(user.getSchId(), NodeType.CLASS.getId());
|
||||
// 构建「年级组ID -> (班级组名 -> 班级组ID)」映射,使同名班级按年级区分,避免跨年级误复用平台组
|
||||
Map<Integer, Map<String, Integer>> gradeClassGroupMap = buildGradeClassGroupMap(schId);
|
||||
|
||||
// 同批导入时缓存已创建的年级组/班级组 ID,避免同一 Excel 多行重复推送平台组
|
||||
Map<String, Integer> createdGradeCache = new HashMap<>();
|
||||
Map<String, Integer> createdClassCache = new HashMap<>();
|
||||
|
||||
try (InputStream is = file.getInputStream()) {
|
||||
List<SchTeacher> schTeacherList = schTeacherService.getSchTeacherList(user.getSchId());
|
||||
@@ -343,14 +354,21 @@ public class SchClassImportService {
|
||||
Integer schsystemId = baseSchsystemGradeService.getSchGradeIdBySchsystemId(user.getSchId(), gradeId);
|
||||
List<SelectIntVO> gradeGroupList = schGradeGroupMap.get(schsystemId);
|
||||
|
||||
Optional<SelectIntVO> gradeGroupOpt= gradeGroupList.stream().filter(s->s.getName().equals(gradeId.toString())).findFirst();
|
||||
if(gradeGroupOpt.isPresent())
|
||||
{
|
||||
clazz.setGroupId(gradeGroupOpt.get().getId());
|
||||
}else {
|
||||
errorMsgArr.add(new ErrorExcelColumn(currentRow, item.getGradeName(), "年级组不存在!"));
|
||||
continue;
|
||||
// 定位年级组(单学制:年级组直接挂在学生组下);缺失则推送平台创建,并缓存避免同批重复创建
|
||||
Integer parentId = (gradeGroupList == null) ? null
|
||||
: gradeGroupList.stream()
|
||||
.filter(s -> Objects.equals(gradeId.toString(), s.getName()))
|
||||
.map(SelectIntVO::getId).findFirst().orElse(null);
|
||||
if (parentId == null) {
|
||||
parentId = createdGradeCache.get(schsystemId + "_" + gradeId);
|
||||
}
|
||||
if (parentId == null || parentId == 0) {
|
||||
BoaGroup gradeGroup = sendUserBaseService.addGroup(gradeId.toString(), stuParentId, gradeId, NodeType.GRADE, schId);
|
||||
parentId = gradeGroup.getId();
|
||||
createdGroupIds.add(parentId);
|
||||
createdGradeCache.put(schsystemId + "_" + gradeId, parentId);
|
||||
}
|
||||
clazz.setGroupId(parentId);
|
||||
|
||||
clazz.setName(item.getClazzName());
|
||||
clazz.setCname(item.getClazzCName());
|
||||
@@ -367,12 +385,35 @@ public class SchClassImportService {
|
||||
} else {
|
||||
clazz.setCreateDate(now);
|
||||
clazz.setCreateUserId(user.getUserId());
|
||||
clazz.setSchId(user.getSchId());
|
||||
clazz.setSchId(schId);
|
||||
clazz.setCode(item.getClazzCode());
|
||||
clazz.setGraduate(false);
|
||||
clazz.setEnrollYear(gradeId);
|
||||
clazz.setGroupId(0);
|
||||
clazz.setClassId(0);
|
||||
|
||||
// 班级组推送平台(单学制:班级组挂在年级组下);缺失则创建,并缓存避免同批重复创建
|
||||
Integer sort = OtherUtil.extractClassNumber(item.getClazzName());
|
||||
if (sort == null || sort <= 0) {
|
||||
sort = 1;
|
||||
}
|
||||
clazz.setSort(sort);
|
||||
// 班级组按年级区分:key 含年级ID,且平台组查找限定在当前年级组(parentId)下,避免跨年级同名班级复用同一平台组
|
||||
String classCacheKey = schsystemId + "_" + gradeId + "_" + item.getClazzName();
|
||||
Integer existClassId = null;
|
||||
Map<String, Integer> gradeClassMap = gradeClassGroupMap.get(parentId);
|
||||
if (gradeClassMap != null) {
|
||||
existClassId = gradeClassMap.get(item.getClazzName());
|
||||
}
|
||||
if (existClassId == null) {
|
||||
existClassId = createdClassCache.get(classCacheKey);
|
||||
}
|
||||
if (existClassId != null && existClassId > 0) {
|
||||
clazz.setClassId(existClassId);
|
||||
} else {
|
||||
BoaGroup classGroup = sendUserBaseService.addGroup(item.getClazzName(), parentId, sort, NodeType.CLASS, schId);
|
||||
clazz.setClassId(classGroup.getId());
|
||||
createdGroupIds.add(classGroup.getId());
|
||||
createdClassCache.put(classCacheKey, classGroup.getId());
|
||||
}
|
||||
}
|
||||
|
||||
clazz.setCname(item.getClazzCName());
|
||||
@@ -430,23 +471,58 @@ public class SchClassImportService {
|
||||
throw new DException(ErrorCode.CUSTOM,"导入失败,请检查错误列表",errorMsgArr);
|
||||
}
|
||||
|
||||
saveClassList = schClassRepository.saveAll(saveClassList);
|
||||
for (SchClass clazz : saveClassList) {
|
||||
if (clazz.getClassId().equals(0)) {
|
||||
clazz.setClassId(clazz.getId());
|
||||
}
|
||||
}
|
||||
schClassRepository.saveAll(saveClassList);
|
||||
cacheService.clearClassCache(user.getSchId());
|
||||
logService.importLogs(user, saveClassList);
|
||||
|
||||
} catch (DException e) {
|
||||
// 业务/校验异常也要回滚已推送到平台的组,避免孤儿组
|
||||
sendUserBaseService.rollbackCreatedGroups(createdGroupIds, schId);
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
// 导入失败:回滚已成功推送到平台的班级组/年级组,避免孤儿组
|
||||
sendUserBaseService.rollbackCreatedGroups(createdGroupIds, schId);
|
||||
log.error("导入班级时发生系统异常,操作人:" + user.getUserName(), e);
|
||||
throw new DException(ErrorCode.CUSTOM,"导入失败,请联系管理员",null,e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从平台组树构建「年级组ID -> (班级组名 -> 班级组ID)」映射。
|
||||
* 班级组是年级组的直接子节点,按年级隔离,使同名班级跨年级可正确区分,
|
||||
* 避免单学制下高一/高二/高三都叫"1班"时误复用同一个平台班级组。
|
||||
*/
|
||||
private Map<Integer, Map<String, Integer>> buildGradeClassGroupMap(Integer schId) {
|
||||
Map<Integer, Map<String, Integer>> result = new HashMap<>();
|
||||
List<BoaGroup> tree = comSchTreeService.getSchTree(schId);
|
||||
if (tree == null) {
|
||||
return result;
|
||||
}
|
||||
for (BoaGroup root : tree) {
|
||||
collectGradeClassGroups(root, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void collectGradeClassGroups(BoaGroup node, Map<Integer, Map<String, Integer>> result) {
|
||||
if (node == null || node.getChildren() == null) {
|
||||
return;
|
||||
}
|
||||
if (node.getType() == NodeType.GRADE.getId()) {
|
||||
Map<String, Integer> classMap = new HashMap<>();
|
||||
for (BoaGroup child : node.getChildren()) {
|
||||
if (child.getType() == NodeType.CLASS.getId() && child.getName() != null) {
|
||||
classMap.put(child.getName(), child.getId());
|
||||
}
|
||||
}
|
||||
if (!classMap.isEmpty()) {
|
||||
result.put(node.getId(), classMap);
|
||||
}
|
||||
}
|
||||
for (BoaGroup child : node.getChildren()) {
|
||||
collectGradeClassGroups(child, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -17,6 +17,8 @@ import com.yunhai.platform.utils.exception.DException;
|
||||
import com.yunhai.platform.utils.model.BoaGroup;
|
||||
import com.yunhai.platform.utils.model.BoaUser;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -224,6 +226,25 @@ public class SendUserBaseService implements ISendUserBaseService {
|
||||
}
|
||||
}
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SendUserBaseService.class);
|
||||
|
||||
/**
|
||||
* 导入失败回滚:删除已成功推送到平台的组(年级组/班级组/学段组),避免留下孤儿组。
|
||||
* 逐组删除并吞掉单组失败,避免回滚途中二次崩溃。
|
||||
*/
|
||||
public void rollbackCreatedGroups(List<Integer> groupIds, Integer schId) {
|
||||
if (groupIds == null) {
|
||||
return;
|
||||
}
|
||||
for (Integer groupId : groupIds) {
|
||||
try {
|
||||
deleteGroup(groupId, schId);
|
||||
} catch (Exception ignore) {
|
||||
log.error("回滚平台组失败 groupId={}", groupId, ignore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//移动教师
|
||||
@SyncOpLog(SyncDataType.SEND_MOVE_TEACHER)
|
||||
public void moveTeacherToGroup(List<SendMoveGroupUserDTO> teacherList,Integer schId){
|
||||
|
||||
Reference in New Issue
Block a user