diff --git a/src/main/java/com/gxwebsoft/gxmu/mapper/ClassInfoMapper.java b/src/main/java/com/gxwebsoft/gxmu/mapper/ClassInfoMapper.java index 8a08a19..cb3e96e 100644 --- a/src/main/java/com/gxwebsoft/gxmu/mapper/ClassInfoMapper.java +++ b/src/main/java/com/gxwebsoft/gxmu/mapper/ClassInfoMapper.java @@ -26,4 +26,15 @@ public interface ClassInfoMapper extends BaseMapper { */ int batchUpsert(@Param("list") List list); + /** + * 按学生名册回填班级人数(学生同步末尾调用)。 + * + *

平台 BJRS 对新生班级返回空,只能本地按 {@code gxmu_student.class_id} 统计兜底。 + * 只补为空或 0 的班级,平台有值时不覆盖。 + * + * @param tenantId 租户ID + * @return 更新行数 + */ + int refreshStudentCountFromRoster(@Param("tenantId") int tenantId); + } diff --git a/src/main/java/com/gxwebsoft/gxmu/mapper/xml/ClassInfoMapper.xml b/src/main/java/com/gxwebsoft/gxmu/mapper/xml/ClassInfoMapper.xml index 3ac3406..7e7f165 100644 --- a/src/main/java/com/gxwebsoft/gxmu/mapper/xml/ClassInfoMapper.xml +++ b/src/main/java/com/gxwebsoft/gxmu/mapper/xml/ClassInfoMapper.xml @@ -7,6 +7,12 @@ ON DUPLICATE KEY UPDATE 里只列「平台权威字段」(docs/adr/0005): sort_number / counselor_phone 属人工维护,同步不触碰;create_time 不重复刷新。 幂等键是 uk_gxmu_class_code(tenant_id, class_code)。 + + counselor_name / student_count 用 COALESCE 保住存量:平台对 2025 级起的班级 + 不返回 BJRS、对 2026 级连 FDYH 都不返回(实测 2026-09-15 那批 1584 条里 + 2025 级 148 条全无人数、2026 级 152 条两项全空)。若照旧写 VALUES(), + 每晚同步都会把这些列刷成 NULL,人工补录的辅导员和学生人数也就一并清掉了。 + 平台有值时仍以平台为准,只有平台给空才保留原值。 --> INSERT INTO gxmu_class ( @@ -26,12 +32,40 @@ class_name = VALUES(class_name), college_id = VALUES(college_id), grade_year = VALUES(grade_year), - counselor_name = VALUES(counselor_name), - student_count = VALUES(student_count), + counselor_name = COALESCE(VALUES(counselor_name), counselor_name), + student_count = COALESCE(VALUES(student_count), student_count), status = VALUES(status), remark = VALUES(remark), update_time = VALUES(update_time), deleted = VALUES(deleted) + + + UPDATE gxmu_class c + LEFT JOIN ( + SELECT class_id, COUNT(*) AS n + FROM gxmu_student + WHERE tenant_id = #{tenantId} + AND deleted = 0 + AND class_id IS NOT NULL + GROUP BY class_id + ) s ON s.class_id = c.id + SET c.student_count = s.n, + c.update_time = NOW() + WHERE c.tenant_id = #{tenantId} + AND c.deleted = 0 + AND c.class_code IS NOT NULL + AND (c.student_count IS NULL OR c.student_count = 0) + AND s.n IS NOT NULL + AND s.n > 0 + + diff --git a/src/main/java/com/gxwebsoft/gxmu/openplat/SyncSupport.java b/src/main/java/com/gxwebsoft/gxmu/openplat/SyncSupport.java index 2375578..9277116 100644 --- a/src/main/java/com/gxwebsoft/gxmu/openplat/SyncSupport.java +++ b/src/main/java/com/gxwebsoft/gxmu/openplat/SyncSupport.java @@ -165,6 +165,22 @@ public class SyncSupport { } } + /** + * 按学生名册回填班级人数。 + * + *

平台的 BJRS 对 2025 级起的班级一律返回空(实测 2025 级 148 个班全空), + * 只能拿刚写完的名册按 class_id 统计兜底,否则班级管理页的学生人数永远为空。 + * + * @return 更新行数 + */ + public int refreshClassStudentCounts() { + int updated = classInfoMapper.refreshStudentCountFromRoster(OpenplatSyncConstants.TENANT_ID); + if (updated > 0) { + logger.warn("班级人数回填: 平台未给出人数的 {} 个班级已按学生名册补上", updated); + } + return updated; + } + /** * 分批写入部门 */ diff --git a/src/main/java/com/gxwebsoft/gxmu/openplat/sync/StudentSyncHandler.java b/src/main/java/com/gxwebsoft/gxmu/openplat/sync/StudentSyncHandler.java index 5ca5fc6..b6c3d8c 100644 --- a/src/main/java/com/gxwebsoft/gxmu/openplat/sync/StudentSyncHandler.java +++ b/src/main/java/com/gxwebsoft/gxmu/openplat/sync/StudentSyncHandler.java @@ -111,6 +111,8 @@ public class StudentSyncHandler { int deactivated = support.deactivateMissingStudents(existingHash.keySet(), incoming); result.setSkipCount(deactivated); + // 班级同步(本批更早执行)拿到的 BJRS 对新生班级一律为空,这里按刚写完的名册补上 + support.refreshClassStudentCounts(); logger.warn("学生同步完成: 平台 {} 人, 实际写入 {} 行, 未变更跳过 {} 行, 停用 {} 行, 失败 {} 条", merged.size(), changed.size(), merged.size() - changed.size(), deactivated, result.getFailCount());