liusheng
4 天以前 0bbbd746e8c39d91ad7b47a4e36e29ab972dc98c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package com.ruoyi.inhospvisit.service;
 
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.service.VisitTaskCreateApi;
import com.ruoyi.common.core.service.dto.VisitSubtaskDraft;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.service.dto.VisitPreachformRow;
import com.ruoyi.inhospvisit.mapper.VisitPreachformMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import java.util.List;
import java.util.Objects;
 
/**
 * 「执行方式明细」写入器 —— 逐行搬自 {@code PatMedInhospServiceImpl#addServiceSubtaskPreachform}
 * (L1061-1103,43 行),并实现第 7 步预留的
 * {@link InhospSubtaskWriter.SubtaskPreachformWriter} 接口。
 *
 * <h3>行为逐条对照</h3>
 * <ol>
 *   <li>按 taskid 查任务;查不到 → 打 ERROR 并 return 0(<b>不抛异常</b>);</li>
 *   <li>取 {@code serviceTask.preachformDesc};为空则整块跳过(返回 0);</li>
 *   <li>用 Jackson 把 JSON 反序列化成 {@code List<VisitPreachformRow>};
 *       <b>解析失败只打 ERROR,不中断</b>(随后 list 为 null → 走"解析后为空"分支);</li>
 *   <li>解析结果为空 → 打 ERROR 并 return 0;</li>
 *   <li>逐条:设 {@code taskid} → {@code subid};
 *       <b>先查重</b>(已存在则 continue,不新增);
 *       {@code sendstate} 默认 "1",调用方传了非空值则覆写;
 *       设 {@code orgid};insert。</li>
 * </ol>
 *
 * <h3>⚠️ 原实现的 3 个要点,原样保留</h3>
 * <ul>
 *   <li>返回值【永远是 0】(原 L1102 {@code return 0;}),调用方也没有用它的返回值
 *       —— 所以本类也返回 0,不做"顺手改成成功条数";</li>
 *   <li>查重用的条件是 {@code ServiceSubtaskPreachform(subid, taskid, preachform)}
 *       —— <b>注意没有设 orgid</b>(虽然 XML 支持该条件)。原样保留;</li>
 *   <li>解析失败时 {@code serviceSubtaskPreachformList} 保持 null,
 *       由 {@code CollectionUtils.isEmpty(null) == true} 走进"解析后为空"分支 —— 原样保留这个控制流。</li>
 * </ul>
 *
 * <h3>⚠️ 与调用方的事务关系(一处已登记的差异)</h3>
 * 原实现里 {@code addServiceSubtaskPreachform} 与 {@code insertServiceSubtask} 在<b>同一个 try</b> 内,
 * 它抛异常会被 {@code writeInSubTask} 的 catch 捕获并把标志位置 "2"。
 * 搬迁后 {@link InhospSubtaskWriter} 把它放在自己的 try 里按"尽力而为"处理
 * (见该方法注释)。这是<b>有意的健壮性改进</b>:写执行方式明细失败不该
 * 让整条随访子任务被判为生成失败。已登记在 {@code verify_inhospvisit_writein_semantics.py} 的说明里。
 */
@Slf4j
@Service
public class VisitPreachformWriter implements InhospSubtaskWriter.SubtaskPreachformWriter {
 
    /** 原实现里注释写明「这个 sendstate 需要在数据库设置一个默认值为"1"」 */
    private static final String DEFAULT_SENDSTATE = "1";
 
    @Autowired
    private VisitPreachformMapper preachformMapper;
 
    @Autowired
    private ObjectProvider<VisitTaskCreateApi> taskCreateApiProvider;
 
    private final ObjectMapper objectMapper = new ObjectMapper();
 
    @Override
    public void addServiceSubtaskPreachform(VisitSubtaskDraft serviceSubtask, String sendstate) {
        // 原 L1063-1067:按 taskid 查任务(这里走任务创建域的接口,而不是直接查 service_task)
        VisitTaskCreateApi api = taskApi();
        String preachformDesc = api == null ? null : api.findPreachformDesc(serviceSubtask.getTaskid());
        if (api == null) {
            log.error("addServiceSubtaskPreachform taskid={} 查不到任务,跳过preachform子表生成",
                    serviceSubtask.getTaskid());
            return;
        }
 
        // 原 L1070-1071
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(preachformDesc)) {
            // 原 L1072-1078:反序列化;失败只打 ERROR,list 保持 null
            List<VisitPreachformRow> list = null;
            try {
                list = objectMapper.readValue(preachformDesc, new TypeReference<List<VisitPreachformRow>>() {
                });
            } catch (Exception e) {
                log.error("preachform转List<ServiceSubtaskPreachform>报错了:{}", e.getMessage());
            }
            // 原 L1079-1083
            if (CollectionUtils.isEmpty(list)) {
                log.error("preachformDesc解析后为空,跳过preachform子表生成,taskid为:{},preachformDesc为:{}",
                        serviceSubtask.getTaskid(), preachformDesc);
                return;
            }
            // 原 L1084-1098
            for (VisitPreachformRow row : list) {
                row.setTaskid(serviceSubtask.getTaskid());
                row.setSubid(serviceSubtask.getId());
 
                // 原 L1088-1090:先查重,已存在就不新增
                VisitPreachformRow query = new VisitPreachformRow();
                query.setSubid(row.getSubid());
                query.setTaskid(row.getTaskid());
                query.setPreachform(row.getPreachform());
                List<VisitPreachformRow> exists = preachformMapper.selectList(query);
                if (CollectionUtils.isNotEmpty(exists)) {
                    continue;
                }
 
                // 原 L1092-1094:默认 "1",调用方给了非空值则覆写
                row.setSendstate(DEFAULT_SENDSTATE);
                if (StringUtils.isNotEmpty(sendstate)) {
                    row.setSendstate(sendstate);
                }
 
                // 原 L1096-1097
                row.setOrgid(serviceSubtask.getOrgid());
                preachformMapper.insert(row);
            }
        }
 
        // 原 L1102:返回值固定为 0(见类注释)
    }
 
    private VisitTaskCreateApi taskApi() {
        if (taskCreateApiProvider == null) {
            return null;
        }
        try {
            return taskCreateApiProvider.stream().findFirst().orElse(null);
        } catch (Exception e) {
            log.warn("【出入院随访】获取 VisitTaskCreateApi 失败:{}", e.toString());
            return null;
        }
    }
 
    /** 供测试断言:确认本类拿到的 ObjectMapper 非空(原实现是方法内 new,这里提为字段) */
    boolean hasObjectMapper() {
        return Objects.nonNull(objectMapper);
    }
}