From 0a2801850d342688351996de02408e0d3d3e0746 Mon Sep 17 00:00:00 2001 From: weicw <594098497@qq.com> Date: Sat, 24 Oct 2026 20:41:35 +0800 Subject: [PATCH] =?UTF-8?q?fix(sync):=20=E7=8F=AD=E7=BA=A7=E4=BA=BA?= =?UTF-8?q?=E6=95=B0=E4=B8=8E=E8=BE=85=E5=AF=BC=E5=91=98=E4=B8=8D=E5=86=8D?= =?UTF-8?q?=E8=A2=AB=E7=A9=BA=E5=80=BC=E8=A6=86=E7=9B=96=EF=BC=8C=E4=BA=BA?= =?UTF-8?q?=E6=95=B0=E6=8C=89=E5=90=8D=E5=86=8C=E5=85=9C=E5=BA=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 开放平台对 2025 级起的班级不返回 BJRS,对 2026 级连 FDYH 都不返回, 而 batchUpsert 用 VALUES() 直写这两列,每晚同步都会把人工补录的辅导员和 学生人数刷成 NULL;新生班级的人数因此一直空着,班级管理页首屏(2026 级) 两列全空。 - ClassInfoMapper.xml: counselor_name / student_count 改为 COALESCE(VALUES(x), x),平台有值仍以平台为准,给空时保留存量 - 新增 refreshStudentCountFromRoster:学生同步结束时按 gxmu_student 全量在册统计(不过滤 status,与平台 BJRS 口径一致)回填人数, 只补「为空或 0」的班级,名册里没学生的班级不动 - StudentSyncHandler: 学生段写完后调用兜底 开发库已用同一语句回填 728 个班级。 --- .../gxmu/mapper/ClassInfoMapper.java | 11 ++++++ .../gxmu/mapper/xml/ClassInfoMapper.xml | 38 ++++++++++++++++++- .../gxwebsoft/gxmu/openplat/SyncSupport.java | 16 ++++++++ .../openplat/sync/StudentSyncHandler.java | 2 + 4 files changed, 65 insertions(+), 2 deletions(-) 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());