刘光辉
4 小时以前 06f314545ac3514d7ce28939920866ae8188d31c
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
package jnpf.elnService.field;
 
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jnpf.elnEntity.field.ElnFieldDefEntity;
import jnpf.elnEntity.field.ElnFieldEnums;
import jnpf.elnEntity.field.ElnFieldVersionEntity;
import jnpf.elnMapper.ElnFieldDefMapper;
import jnpf.elnMapper.ElnFieldVersionMapper;
import jnpf.exception.DataException;
import jnpf.util.JsonUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
 
import java.util.Date;
import java.util.List;
import java.util.Map;
 
/**
 * 系统字段按需在访问租户时创建。字段编码是跨模板稳定的业务契约,普通字段生成器不得参与。
 */
@Service
public class ElnTestResultFieldCatalogImpl implements ElnTestResultFieldCatalog {
    private static final String ENABLED = "enabled";
    private static final String SYSTEM_BINDING = "{\"read\":{\"source\":\"NONE\"},\"write\":{\"target\":\"ELN_RECORD\"}}";
 
    private final ElnFieldDefMapper definitionMapper;
    private final ElnFieldVersionMapper versionMapper;
 
    public ElnTestResultFieldCatalogImpl(ElnFieldDefMapper definitionMapper,
                                                ElnFieldVersionMapper versionMapper) {
        this.definitionMapper = definitionMapper;
        this.versionMapper = versionMapper;
    }
 
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void ensure(String tenantId, String operatorId) {
        String tenant = required(tenantId, "租户不能为空");
        String operator = StringUtils.hasText(operatorId) ? operatorId.trim() : "system";
        ensureField(tenant, operator, ElnTestResultFields.RESULT, "检验结果", "TEXT", "{\"placeholder\":\"请输入检验结果\"}");
        ensureField(tenant, operator, ElnTestResultFields.CONCLUSION, "检验结论", "SELECT",
                "{\"placeholder\":\"请选择\",\"options\":[{\"value\":\"compliant\",\"display\":\"符合规定\"},{\"value\":\"non_compliant\",\"display\":\"不符合规定\"},{\"value\":\"not_inspected\",\"display\":\"不检\"},{\"value\":\"external\",\"display\":\"外检\"}]}");
    }
 
    private void ensureField(String tenantId, String operatorId, String code, String name,
                             String type, String controlConfig) {
        ElnFieldDefEntity definition = definition(tenantId, code);
        if (definition == null) {
            definition = createDefinition(tenantId, operatorId, code);
        }
        validateDefinition(definition, code);
        ElnFieldVersionEntity version = currentVersion(tenantId, definition);
        if (version == null) {
            version = createVersion(tenantId, operatorId, definition, name, type, controlConfig);
            definition.setDangqianZiduanBanbenId(version.getId());
            definition.setFLastModifyUserId(operatorId);
            definition.setFLastModifyTime(new Date());
            if (definitionMapper.updateById(definition) != 1) {
                throw new DataException("系统字段当前版本设置失败,请重试");
            }
        }
        validateVersion(version, code, name, type, controlConfig);
    }
 
    private ElnFieldDefEntity createDefinition(String tenantId, String operatorId, String code) {
        ElnFieldDefEntity created = new ElnFieldDefEntity();
        Date now = new Date();
        created.setId(IdUtil.getSnowflakeNextIdStr());
        created.setFTenantId(tenantId);
        created.setZiduanBianma(code);
        created.setZuoyongFanwei(ElnFieldEnums.Scope.GLOBAL.name());
        created.setBizEnabled(ENABLED);
        created.setBeizhu("ELN 系统业务字段,不可替换或停用");
        created.setFVersion(0);
        created.setFDeleteMark(0);
        created.setFCreatorUserId(operatorId);
        created.setFLastModifyUserId(operatorId);
        created.setFCreatorTime(now);
        created.setFLastModifyTime(now);
        if (definitionMapper.insertIgnoreCode(created) == 1) return created;
        ElnFieldDefEntity concurrent = definition(tenantId, code);
        if (concurrent != null) return concurrent;
        throw new DataException("系统字段创建冲突,请重试");
    }
 
    private ElnFieldVersionEntity createVersion(String tenantId, String operatorId,
                                                ElnFieldDefEntity definition, String name,
                                                String type, String controlConfig) {
        ElnFieldVersionEntity version = new ElnFieldVersionEntity();
        Date now = new Date();
        version.setId(IdUtil.getSnowflakeNextIdStr());
        version.setFTenantId(tenantId);
        version.setZiduanDingyiId(definition.getId());
        version.setBanbenHao(1);
        version.setZiduanMingcheng(name);
        version.setShujuLeixing(type);
        version.setShifouBitian(1);
        version.setPiciMoshi(ElnFieldEnums.BatchMode.RECORD_PRIVATE.name());
        version.setBangdingPeizhi(SYSTEM_BINDING);
        version.setKongjianPeizhi(controlConfig);
        version.setBizStatus(ElnFieldEnums.VersionStatus.PUBLISHED.name());
        version.setFVersion(0);
        version.setFDeleteMark(0);
        version.setFCreatorUserId(operatorId);
        version.setFLastModifyUserId(operatorId);
        version.setFCreatorTime(now);
        version.setFLastModifyTime(now);
        if (versionMapper.insertIgnoreVersionNo(version) == 1) return version;
        ElnFieldVersionEntity concurrent = versionMapper.selectOne(Wrappers.<ElnFieldVersionEntity>lambdaQuery()
                .eq(ElnFieldVersionEntity::getFTenantId, tenantId)
                .eq(ElnFieldVersionEntity::getZiduanDingyiId, definition.getId())
                .eq(ElnFieldVersionEntity::getBanbenHao, 1).last("limit 1"));
        if (concurrent != null) return concurrent;
        throw new DataException("系统字段版本创建冲突,请重试");
    }
 
    private ElnFieldDefEntity definition(String tenantId, String code) {
        return definitionMapper.selectOne(Wrappers.<ElnFieldDefEntity>lambdaQuery()
                .eq(ElnFieldDefEntity::getFTenantId, tenantId).eq(ElnFieldDefEntity::getZiduanBianma, code)
                .and(q -> q.isNull(ElnFieldDefEntity::getFDeleteMark).or().eq(ElnFieldDefEntity::getFDeleteMark, 0))
                .last("limit 1"));
    }
 
    private ElnFieldVersionEntity currentVersion(String tenantId, ElnFieldDefEntity definition) {
        if (!StringUtils.hasText(definition.getDangqianZiduanBanbenId())) return null;
        return versionMapper.selectOne(Wrappers.<ElnFieldVersionEntity>lambdaQuery()
                .eq(ElnFieldVersionEntity::getFTenantId, tenantId)
                .eq(ElnFieldVersionEntity::getId, definition.getDangqianZiduanBanbenId())
                .eq(ElnFieldVersionEntity::getZiduanDingyiId, definition.getId())
                .and(q -> q.isNull(ElnFieldVersionEntity::getFDeleteMark).or().eq(ElnFieldVersionEntity::getFDeleteMark, 0))
                .last("limit 1"));
    }
 
    private static void validateDefinition(ElnFieldDefEntity definition, String code) {
        if (!ElnFieldEnums.Scope.GLOBAL.name().equals(definition.getZuoyongFanwei())
                || !ENABLED.equals(definition.getBizEnabled())) {
            throw new DataException("系统字段 " + code + " 已被修改,无法用于结果提交");
        }
    }
 
    private static void validateVersion(ElnFieldVersionEntity version, String code, String name,
                                        String type, String controlConfig) {
        if (!ElnFieldEnums.VersionStatus.PUBLISHED.name().equals(version.getBizStatus())
                || version.getBanbenHao() == null || version.getBanbenHao() != 1
                || !name.equals(version.getZiduanMingcheng()) || !type.equals(version.getShujuLeixing())
                || !Integer.valueOf(1).equals(version.getShifouBitian())
                || !ElnFieldEnums.BatchMode.RECORD_PRIVATE.name().equals(version.getPiciMoshi())
                || !validSystemBinding(version.getBangdingPeizhi())
                || !validControlConfig(code, version.getKongjianPeizhi())) {
            throw new DataException("系统字段 " + code + " 的发布规则已被修改,无法用于结果提交");
        }
    }
 
    @SuppressWarnings("unchecked")
    private static boolean validSystemBinding(String value) {
        try {
            Map<String, Object> config = JsonUtil.getJsonToBean(value, Map.class);
            if (config == null || !(config.get("read") instanceof Map)
                    || !(config.get("write") instanceof Map)) return false;
            Map<String, Object> read = (Map<String, Object>) config.get("read");
            Map<String, Object> write = (Map<String, Object>) config.get("write");
            return "NONE".equals(read.get("source")) && "ELN_RECORD".equals(write.get("target"));
        } catch (RuntimeException e) {
            return false;
        }
    }
 
    @SuppressWarnings("unchecked")
    private static boolean validControlConfig(String code, String value) {
        if (!ElnTestResultFields.CONCLUSION.equals(code)) return true;
        try {
            Map<String, Object> config = JsonUtil.getJsonToBean(value, Map.class);
            if (config == null || !(config.get("options") instanceof List)) return false;
            List<?> options = (List<?>) config.get("options");
            if (options.size() != ElnTestResultFields.CONCLUSION_CODES.size()) return false;
            int index = 0;
            for (String expected : ElnTestResultFields.CONCLUSION_CODES) {
                Object option = options.get(index++);
                if (!(option instanceof Map)
                        || !expected.equals(((Map<?, ?>) option).get("value"))) return false;
            }
            return true;
        } catch (RuntimeException e) {
            return false;
        }
    }
 
    private static String required(String value, String message) {
        if (!StringUtils.hasText(value)) throw new DataException(message);
        return value.trim();
    }
}