Pārlūkot izejas kodu

fix(repeat-task): 周期实例透传 family_member_id + 迁移348 回填存量

createTaskFromTemplate 未复制 family_member_id,导致周期实例既不出现在
今日任务列表(列表按该字段过滤),completeTask 也会抛 NPE。存量 174 个实例中
90 个为 NULL,含既有模板实例,属既存缺陷一并修复。
迁移348 按模板回填,模板缺失时以 child_id 兜底。
Xiaogang Liao 3 dienas atpakaļ
vecāks
revīzija
3533abab15

+ 24 - 0
cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java

@@ -10931,6 +10931,7 @@ log.info("迁移298: 已为无 openid 的 child 账号补齐 family_members 记
         ensureHealthPlansTotalDaysColumn();
         seedTaskReminderTemplate();
         backfillHealthPlanTaskPrerequisite();
+        backfillTemplateInstanceFamilyMemberId();
 
         // 迁移341: BASIC 体验会员 features JSON 补 referral_commission(迁移315 未包含,前端对比表已显示可参与)
         try {
@@ -11545,6 +11546,29 @@ log.info("迁移298: 已为无 openid 的 child 账号补齐 family_members 记
      * 这里补写依赖并把前置未完成的使用任务置为 locked。
      * 幂等:每次启动只处理 prerequisite IS NULL / status=pending 的行,可重复执行。
      */
+    /**
+     * 迁移348: 回填周期实例的 family_member_id。
+     * RepeatTaskGenerator 过去未透传该字段,导致周期实例在"今日任务"列表查不到、
+     * 且 completeTask 抛 NPE。存量实例按其模板回填,模板缺失时按 child_id 兜底。
+     */
+    private void backfillTemplateInstanceFamilyMemberId() {
+        try {
+            int fromTpl = jdbcTemplate.update(
+                    "UPDATE tasks i JOIN tasks tpl ON tpl.id = i.template_id " +
+                    "SET i.family_member_id = tpl.family_member_id " +
+                    "WHERE i.family_member_id IS NULL AND tpl.family_member_id IS NOT NULL");
+            int fromChild = jdbcTemplate.update(
+                    "UPDATE tasks SET family_member_id = child_id " +
+                    "WHERE family_member_id IS NULL AND child_id IS NOT NULL AND is_template = 0");
+            if (fromTpl > 0 || fromChild > 0) {
+                log.info("迁移348: 周期实例 family_member_id 回填 模板来源={}条 child_id兜底={}条",
+                        fromTpl, fromChild);
+            }
+        } catch (Exception e) {
+            log.warn("迁移348: 周期实例 family_member_id 回填失败: " + e.getMessage());
+        }
+    }
+
     private void backfillHealthPlanTaskPrerequisite() {
         try {
             int linked = jdbcTemplate.update(

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/task/RepeatTaskGenerator.java

@@ -189,6 +189,9 @@ newTask.setCreatorId(template.getCreatorId());
 newTask.setExecutorType(template.getExecutorType());
 newTask.setExecutorId(template.getExecutorId());
 newTask.setChildId(template.getChildId());
+// 必须透传 family_member_id:任务列表按该字段过滤成员任务,缺失会导致
+// 周期实例既不出现在"今日任务"列表,也无法打卡(completeTask 会 NPE)
+newTask.setFamilyMemberId(template.getFamilyMemberId());
 newTask.setTitle(template.getTitle());
 newTask.setDescription(template.getDescription());
 newTask.setPoints(template.getPoints());