fix(gxmu): 新申报按学籍补齐 college_id,不再只有存量回填
4 张在跑表(gxmu_sjqn / gxmu_tzbcy_form / gxmu_qmgc_form / gxmu_wxxzx_project) 的实体补 collegeId,save 路径在为空时按「登录用户 → gxmu_student.college_id」 补齐;解析不到(无学籍、名册未同步、学院不唯一)一律留空不报错。 更新路径不调用解析器,collegeId 为 null 时 MyBatis-Plus 忽略该字段,库里已有值不变。 解析逻辑收在一个共享组件 CollegeResolver 里,4 个 controller 只各调一行; 口径与一次性回填脚本一致(优先在校那条学籍,学院不唯一就留空)。 单测:有学籍时写入、无学籍时留空、学院多义时留空、更新不覆盖已有值。 refs #58
This commit is contained in:
@@ -15,6 +15,7 @@ import com.gxwebsoft.gxmu.param.QmgcFormParam;
|
||||
import com.gxwebsoft.gxmu.service.QmgcFormService;
|
||||
import com.gxwebsoft.gxmu.service.ReviewFlowStarterService;
|
||||
import com.gxwebsoft.gxmu.model.DeclareCheckResult;
|
||||
import com.gxwebsoft.gxmu.service.CollegeResolver;
|
||||
import com.gxwebsoft.gxmu.service.DeclareGuardService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import com.gxwebsoft.gxmu.util.GxmuQueryHelper;
|
||||
@@ -42,6 +43,8 @@ public class QmgcFormController extends BaseController {
|
||||
@Resource
|
||||
private QmgcFormService qmgcFormService;
|
||||
@Resource
|
||||
private CollegeResolver collegeResolver;
|
||||
@Resource
|
||||
private ReviewFlowStarterService reviewFlowStarterService;
|
||||
@Resource
|
||||
private DeclareGuardService declareGuardService;
|
||||
@@ -145,6 +148,9 @@ public class QmgcFormController extends BaseController {
|
||||
if (loginUser != null) {
|
||||
qmgcForm.setUserId(loginUser.getUserId());
|
||||
}
|
||||
// 新申报没有学院标识时按学籍补齐(没有学籍 / 学院不唯一就留空,不报错):
|
||||
// 审批链的 COLLEGE_ROLE 规则要靠它定位学院,一次性回填只解决存量
|
||||
qmgcForm.setCollegeId(collegeResolver.fillIfAbsent(qmgcForm.getCollegeId(), qmgcForm.getUserId()));
|
||||
DeclareCheckResult declareCheck = declareGuardService.checkBeforeCreate("gxmu_qmgc_form",
|
||||
qmgcForm.getDeclareId(), qmgcForm.getYear(), qmgcForm.getUserId());
|
||||
if (declareCheck.isRejected()) {
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.gxwebsoft.gxmu.entity.SjqnForm;
|
||||
import com.gxwebsoft.gxmu.param.SjqnFormParam;
|
||||
import com.gxwebsoft.gxmu.service.ReviewFlowStarterService;
|
||||
import com.gxwebsoft.gxmu.model.DeclareCheckResult;
|
||||
import com.gxwebsoft.gxmu.service.CollegeResolver;
|
||||
import com.gxwebsoft.gxmu.service.DeclareGuardService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import com.gxwebsoft.gxmu.service.SjqnFormService;
|
||||
@@ -46,6 +47,8 @@ public class SjqnFormController extends BaseController {
|
||||
@Resource
|
||||
private SjqnFormService sjqnFormService;
|
||||
@Resource
|
||||
private CollegeResolver collegeResolver;
|
||||
@Resource
|
||||
private ReviewFlowStarterService reviewFlowStarterService;
|
||||
@Resource
|
||||
private DeclareGuardService declareGuardService;
|
||||
@@ -162,6 +165,9 @@ public class SjqnFormController extends BaseController {
|
||||
if (loginUser != null) {
|
||||
sjqnForm.setUserId(loginUser.getUserId());
|
||||
}
|
||||
// 新申报没有学院标识时按学籍补齐(没有学籍 / 学院不唯一就留空,不报错):
|
||||
// 审批链的 COLLEGE_ROLE 规则要靠它定位学院,一次性回填只解决存量
|
||||
sjqnForm.setCollegeId(collegeResolver.fillIfAbsent(sjqnForm.getCollegeId(), sjqnForm.getUserId()));
|
||||
DeclareCheckResult declareCheck = declareGuardService.checkBeforeCreate("gxmu_sjqn",
|
||||
sjqnForm.getDeclareId(), sjqnForm.getYear(), sjqnForm.getUserId());
|
||||
if (declareCheck.isRejected()) {
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.gxwebsoft.gxmu.entity.TzbcyForm;
|
||||
import com.gxwebsoft.gxmu.model.TzbcyStatisticsResult;
|
||||
import com.gxwebsoft.gxmu.param.TzbcyFormParam;
|
||||
import com.gxwebsoft.gxmu.model.DeclareCheckResult;
|
||||
import com.gxwebsoft.gxmu.service.CollegeResolver;
|
||||
import com.gxwebsoft.gxmu.service.DeclareGuardService;
|
||||
import com.gxwebsoft.gxmu.service.ReviewFlowStarterService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -38,6 +39,8 @@ public class TzbcyFormController extends BaseController {
|
||||
@Resource
|
||||
private TzbcyFormService tzbcyFormService;
|
||||
@Resource
|
||||
private CollegeResolver collegeResolver;
|
||||
@Resource
|
||||
private ReviewFlowStarterService reviewFlowStarterService;
|
||||
@Resource
|
||||
private DeclareGuardService declareGuardService;
|
||||
@@ -99,6 +102,9 @@ public class TzbcyFormController extends BaseController {
|
||||
if (loginUser != null) {
|
||||
tzbcyForm.setUserId(loginUser.getUserId());
|
||||
}
|
||||
// 新申报没有学院标识时按学籍补齐(没有学籍 / 学院不唯一就留空,不报错):
|
||||
// 审批链的 COLLEGE_ROLE 规则要靠它定位学院,一次性回填只解决存量
|
||||
tzbcyForm.setCollegeId(collegeResolver.fillIfAbsent(tzbcyForm.getCollegeId(), tzbcyForm.getUserId()));
|
||||
DeclareCheckResult declareCheck = declareGuardService.checkBeforeCreate("gxmu_tzbcy_form",
|
||||
tzbcyForm.getDeclareId(), tzbcyForm.getYear(), tzbcyForm.getUserId());
|
||||
if (declareCheck.isRejected()) {
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.gxwebsoft.gxmu.param.WxxzxFormParam;
|
||||
import com.gxwebsoft.gxmu.service.QmgcFormService;
|
||||
import com.gxwebsoft.gxmu.service.ReviewFlowStarterService;
|
||||
import com.gxwebsoft.gxmu.model.DeclareCheckResult;
|
||||
import com.gxwebsoft.gxmu.service.CollegeResolver;
|
||||
import com.gxwebsoft.gxmu.service.DeclareGuardService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import com.gxwebsoft.gxmu.service.SjqnFormService;
|
||||
@@ -100,6 +101,8 @@ public class WxxzxFormController extends BaseController {
|
||||
@Resource
|
||||
private WxxzxFormService wxxzxFormService;
|
||||
@Resource
|
||||
private CollegeResolver collegeResolver;
|
||||
@Resource
|
||||
private SjqnFormService sjqnFormService;
|
||||
@Resource
|
||||
private SjtbzbsjFormService sjtbzbsjFormService;
|
||||
@@ -254,6 +257,9 @@ public class WxxzxFormController extends BaseController {
|
||||
if (loginUser != null) {
|
||||
wxxzxForm.setUserId(loginUser.getUserId());
|
||||
}
|
||||
// 新申报没有学院标识时按学籍补齐(没有学籍 / 学院不唯一就留空,不报错):
|
||||
// 审批链的 COLLEGE_ROLE 规则要靠它定位学院,一次性回填只解决存量
|
||||
wxxzxForm.setCollegeId(collegeResolver.fillIfAbsent(wxxzxForm.getCollegeId(), wxxzxForm.getUserId()));
|
||||
DeclareCheckResult declareCheck = declareGuardService.checkBeforeCreate("gxmu_wxxzx_project",
|
||||
wxxzxForm.getDeclareId(), wxxzxForm.getYear(), wxxzxForm.getUserId());
|
||||
if (declareCheck.isRejected()) {
|
||||
|
||||
@@ -117,6 +117,9 @@ public class QmgcForm implements Serializable {
|
||||
@ApiModelProperty("用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@ApiModelProperty("学院标识(sys_organization.organization_id),新建申报时按学籍补齐,允许为空")
|
||||
private Integer collegeId;
|
||||
|
||||
@ApiModelProperty("是否删除")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@@ -92,6 +92,9 @@ public class SjqnForm implements Serializable {
|
||||
@ApiModelProperty("用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@ApiModelProperty("学院标识(sys_organization.organization_id),新建申报时按学籍补齐,允许为空")
|
||||
private Integer collegeId;
|
||||
|
||||
@ApiModelProperty("是否删除")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@@ -114,6 +114,9 @@ public class TzbcyForm implements Serializable {
|
||||
@ApiModelProperty("用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@ApiModelProperty("学院标识(sys_organization.organization_id),新建申报时按学籍补齐,允许为空")
|
||||
private Integer collegeId;
|
||||
|
||||
@ApiModelProperty("是否删除")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@@ -143,6 +143,9 @@ public class WxxzxForm implements Serializable {
|
||||
@ApiModelProperty("用户ID")
|
||||
private Integer userId;
|
||||
|
||||
@ApiModelProperty("学院标识(sys_organization.organization_id),新建申报时按学籍补齐,允许为空")
|
||||
private Integer collegeId;
|
||||
|
||||
@ApiModelProperty("是否删除")
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.gxwebsoft.gxmu.service;
|
||||
|
||||
/**
|
||||
* 学院标识解析:把登录用户映射到申报记录的 college_id(spec #58 用户故事 2)。
|
||||
*
|
||||
* <p>申报表上的 college_id 指向 sys_organization.organization_id,与学生名册
|
||||
* gxmu_student.college_id 是同一套 ID(见 ADR 0006「学院标识」)。新建申报时按
|
||||
* 「登录用户 → gxmu_student.college_id」补齐,审批链里的 COLLEGE_ROLE 规则才有字段可用;
|
||||
* 解析不到(没有学籍、名册未同步、学院不唯一)一律返回 null,不报错、不猜。
|
||||
*
|
||||
* @author Codex
|
||||
* @since 2026-11-11
|
||||
*/
|
||||
public interface CollegeResolver {
|
||||
|
||||
/**
|
||||
* 按登录用户查学院标识。
|
||||
*
|
||||
* <p>同一用户有多条学籍时以「在校」那条为准;学院不唯一说明无法判断,返回 null。
|
||||
*
|
||||
* @param userId 登录用户 id(sys_user.user_id),可为空
|
||||
* @return 学院标识,解析不到返回 null
|
||||
*/
|
||||
Integer resolve(Integer userId);
|
||||
|
||||
/**
|
||||
* 只在申报记录还没有学院标识时补齐;已有值一律保留(更新路径不覆盖已有值)。
|
||||
*
|
||||
* @param currentCollegeId 申报记录当前的学院标识
|
||||
* @param userId 登录用户 id
|
||||
* @return 最终写入的学院标识
|
||||
*/
|
||||
Integer fillIfAbsent(Integer currentCollegeId, Integer userId);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.gxwebsoft.gxmu.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.gxwebsoft.gxmu.openplat.entity.GxmuStudent;
|
||||
import com.gxwebsoft.gxmu.openplat.mapper.GxmuStudentMapper;
|
||||
import com.gxwebsoft.gxmu.service.CollegeResolver;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 学院标识解析实现:gxmu_student.college_id 是学院标识的唯一权威来源。
|
||||
*
|
||||
* <p>口径与一次性回填脚本 sql/20261110_backfill_college_id.sql 保持一致:
|
||||
* 优先取「在校(status = 1)」那条学籍的学院;学院不唯一就留空交给人工,
|
||||
* 不做层级推导、不猜。
|
||||
*
|
||||
* @author Codex
|
||||
* @since 2026-11-11
|
||||
*/
|
||||
@Service
|
||||
public class CollegeResolverImpl implements CollegeResolver {
|
||||
|
||||
@Resource
|
||||
private GxmuStudentMapper gxmuStudentMapper;
|
||||
|
||||
@Override
|
||||
public Integer resolve(Integer userId) {
|
||||
if (userId == null) {
|
||||
return null;
|
||||
}
|
||||
List<GxmuStudent> students = gxmuStudentMapper.selectList(new LambdaQueryWrapper<GxmuStudent>()
|
||||
.select(GxmuStudent::getCollegeId, GxmuStudent::getStatus)
|
||||
.eq(GxmuStudent::getUserId, userId)
|
||||
.isNotNull(GxmuStudent::getCollegeId)
|
||||
.orderByDesc(GxmuStudent::getStatus)
|
||||
.orderByDesc(GxmuStudent::getId));
|
||||
if (students == null || students.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Integer collegeId = null;
|
||||
for (GxmuStudent student : students) {
|
||||
Integer candidate = student.getCollegeId();
|
||||
if (candidate == null) {
|
||||
continue;
|
||||
}
|
||||
if (collegeId == null) {
|
||||
collegeId = candidate;
|
||||
} else if (!collegeId.equals(candidate)) {
|
||||
// 同一用户的本科学院与研究生学院不同且没有可判定的在校行:留空,不猜
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return collegeId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer fillIfAbsent(Integer currentCollegeId, Integer userId) {
|
||||
return currentCollegeId != null ? currentCollegeId : resolve(userId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user