刘光辉
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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
package jnpf.limsService.impl;
 
import jnpf.lims.api.model.TestWorkItemSnapshotBatch;
import jnpf.lims.api.model.TestWorkItemSnapshot;
import jnpf.lims.api.model.TestWorkItemSnapshotProperty;
import jnpf.lims.api.model.TestWorkItemSnapshotRequest;
import jnpf.limsEntity.JianyanStatus;
import jnpf.limsEntity.LimsJianyanXiangEntity;
import jnpf.limsMapper.LimsJianyanXiangMapper;
import jnpf.limsService.LimsTestWorkItemSnapshotService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
 
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
 
@Service
public class LimsTestWorkItemSnapshotServiceImpl implements LimsTestWorkItemSnapshotService {
 
    static final String TEST_BASIS = "test.basis";
    private static final String LEGACY_INSPECTION_BASIS = "inspection.basis";
    static final String SAMPLE_NAME = "sample.name";
    static final String SAMPLE_BATCH_NO = "sample.batch_no";
    static final String SAMPLE_PRODUCTION_DATE = "sample.production_date";
    static final String QUALITY_STANDARD_SOURCE = "quality_standard.source";
    static final String SAMPLE_SPECIFICATION = "sample.specification";
    static final String TEST_TYPE = "test.type";
    private static final String LEGACY_INSPECTION_TYPE = "inspection.type";
    private static final String LIMS_TASK = "LIMS_TASK";
    private static final String TEXT = "TEXT";
    private static final String DATE = "DATE";
    private static final List<String> ALLOWED_STATUSES = Arrays.asList(
            JianyanStatus.PENDING_TEST.getCode(),
            JianyanStatus.AUDIT_REJECTED.getCode(),
            JianyanStatus.CANCELLED.getCode());
 
    private final TaskLookup taskLookup;
 
    @Autowired
    public LimsTestWorkItemSnapshotServiceImpl(LimsJianyanXiangMapper mapper) {
        this(mapper::selectSnapshotTasks);
    }
 
    LimsTestWorkItemSnapshotServiceImpl(TaskLookup taskLookup) {
        this.taskLookup = taskLookup;
    }
 
    @Override
    public TestWorkItemSnapshotBatch resolve(TestWorkItemSnapshotRequest request,
                                               String tenantId, String userId) {
        List<String> itemIds = requestedItemIds(request);
        List<String> properties = requestedProperties(request);
        Map<String, LimsJianyanXiangEntity> tasks = findTasks(tenantId, itemIds);
        TestWorkItemSnapshotBatch batch = new TestWorkItemSnapshotBatch();
        for (String itemId : itemIds) {
            LimsJianyanXiangEntity task = tasks.get(itemId);
            TestWorkItemSnapshot item = item(itemId, task);
            boolean readable = false;
            if (task == null) {
                reject(item, "NOT_FOUND", "检验项不存在或无权访问");
            } else if (isDeleted(task)) {
                reject(item, "DELETED", "检验项已删除");
            } else if (!ALLOWED_STATUSES.contains(task.getJianyanZhuangtai())) {
                reject(item, "STATE_NOT_ALLOWED", "检验项当前状态不允许读取任务快照");
            } else if (!isResponsible(task, userId)) {
                reject(item, "FORBIDDEN", "当前用户不是检验项负责人");
            } else if (!StringUtils.hasText(task.getQingyandanId())) {
                reject(item, "TEST_REQUEST_INVALID", "检验项缺少请验单身份");
            } else if (!hasUniqueTestDefinitionReference(task)) {
                reject(item, "TEST_DEFINITION_INVALID", "检验项缺少唯一检验项目关联");
            } else {
                item.setTestRequestId(task.getQingyandanId().trim());
                applyTestDefinitionReference(item, task);
                item.setOutcomeCode("SUCCESS");
                readable = true;
            }
            addProperties(item, readable ? task : null, properties, readable);
            batch.getItems().add(item);
        }
        return batch;
    }
 
    private Map<String, LimsJianyanXiangEntity> findTasks(String tenantId, List<String> itemIds) {
        if (!StringUtils.hasText(tenantId) || itemIds.isEmpty()) {
            return Collections.emptyMap();
        }
        Map<String, LimsJianyanXiangEntity> tasks = new LinkedHashMap<>();
        for (LimsJianyanXiangEntity task : taskLookup.find(tenantId, itemIds)) {
            if (task != null && StringUtils.hasText(task.getId())
                    && tenantId.equals(task.getTenantId())) {
                tasks.put(task.getId(), task);
            }
        }
        return tasks;
    }
 
    private static List<String> requestedItemIds(TestWorkItemSnapshotRequest request) {
        if (request == null || request.getTestWorkItemIds() == null) {
            return Collections.emptyList();
        }
        LinkedHashSet<String> ids = new LinkedHashSet<>();
        for (String id : request.getTestWorkItemIds()) {
            if (StringUtils.hasText(id)) {
                ids.add(id.trim());
            }
        }
        return new ArrayList<>(ids);
    }
 
    private static List<String> requestedProperties(TestWorkItemSnapshotRequest request) {
        return request == null || request.getProperties() == null
                ? Collections.<String>emptyList() : request.getProperties();
    }
 
    private static TestWorkItemSnapshot item(String itemId, LimsJianyanXiangEntity task) {
        TestWorkItemSnapshot item = new TestWorkItemSnapshot();
        item.setTestWorkItemId(itemId);
        item.setTaskStatus(task == null ? null : task.getJianyanZhuangtai());
        return item;
    }
 
    private static boolean hasUniqueTestDefinitionReference(LimsJianyanXiangEntity task) {
        return StringUtils.hasText(task.getTestDefinitionId())
                && StringUtils.hasText(task.getJianyanXiangmuBianma())
                && StringUtils.hasText(task.getJianyanXiangmuMingcheng())
                && Long.valueOf(1L).equals(task.getTestDefinitionMatchCount());
    }
 
    private static void applyTestDefinitionReference(TestWorkItemSnapshot item,
                                                        LimsJianyanXiangEntity task) {
        item.setTestDefinitionId(task.getTestDefinitionId().trim());
        item.setTestDefinitionCode(task.getJianyanXiangmuBianma().trim());
        item.setTestDefinitionName(task.getJianyanXiangmuMingcheng().trim());
    }
 
    private static void addProperties(TestWorkItemSnapshot item, LimsJianyanXiangEntity task,
                                      List<String> requestedProperties, boolean readable) {
        for (String property : requestedProperties) {
            TestWorkItemSnapshotProperty result = new TestWorkItemSnapshotProperty();
            result.setProperty(property);
            PropertySpec spec = propertySpec(property);
            if (spec == null) {
                result.setOutcomeCode("UNSUPPORTED_PROPERTY");
                result.setReason("未支持的 LIMS_TASK property:" + property);
            } else {
                result.setDataType(spec.dataType);
                result.setSource(LIMS_TASK);
                result.setSourceRef(item.getTestWorkItemId());
                if (!readable) {
                    result.setOutcomeCode("NOT_AVAILABLE");
                    result.setReason("检验项任务快照不可读取");
                } else if (!StringUtils.hasText(spec.value(task))) {
                    result.setOutcomeCode("MISSING");
                    result.setReason("检验任务快照中缺少" + spec.label);
                } else {
                    result.setValue(spec.value(task));
                    result.setOutcomeCode("SUCCESS");
                }
            }
            item.getProperties().add(result);
        }
    }
 
    private static PropertySpec propertySpec(String property) {
        if (TEST_BASIS.equals(property) || LEGACY_INSPECTION_BASIS.equals(property)) {
            return new PropertySpec(TEXT, "检验依据", LimsJianyanXiangEntity::getBiaozhunGuiding);
        }
        if (SAMPLE_NAME.equals(property)) return new PropertySpec(TEXT, "供试品名称", LimsJianyanXiangEntity::getChanpinMingcheng);
        if (SAMPLE_BATCH_NO.equals(property)) return new PropertySpec(TEXT, "批号", LimsJianyanXiangEntity::getPihao);
        if (SAMPLE_PRODUCTION_DATE.equals(property)) return new PropertySpec(DATE, "生产日期", task -> formatDate(task.getShengchanRiqi()));
        if (QUALITY_STANDARD_SOURCE.equals(property)) return new PropertySpec(TEXT, "质量标准来源", LimsJianyanXiangEntity::getQualityStandardSource);
        if (SAMPLE_SPECIFICATION.equals(property)) return new PropertySpec(TEXT, "规格/浓度", LimsJianyanXiangEntity::getGuige);
        if (TEST_TYPE.equals(property) || LEGACY_INSPECTION_TYPE.equals(property)) {
            return new PropertySpec(TEXT, "检验类型", LimsJianyanXiangEntity::getJianyanLeixing);
        }
        return null;
    }
 
    private static String formatDate(java.util.Date value) {
        if (value == null) return null;
        return new java.text.SimpleDateFormat("yyyy-MM-dd").format(value);
    }
 
    private interface PropertyValue {
        String value(LimsJianyanXiangEntity task);
    }
 
    private static final class PropertySpec {
        private final String dataType;
        private final String label;
        private final PropertyValue value;
 
        private PropertySpec(String dataType, String label, PropertyValue value) {
            this.dataType = dataType;
            this.label = label;
            this.value = value;
        }
 
        private String value(LimsJianyanXiangEntity task) {
            return value.value(task);
        }
    }
 
    private static boolean isDeleted(LimsJianyanXiangEntity task) {
        return task.getDeleteMark() != null && task.getDeleteMark() == 1;
    }
 
    private static boolean isResponsible(LimsJianyanXiangEntity task, String userId) {
        if (!StringUtils.hasText(userId)) {
            return false;
        }
        String responsible = "yes".equalsIgnoreCase(task.getShifouWaijian())
                ? task.getWaijianLururen() : task.getJianchaRen();
        return userId.equals(responsible);
    }
 
    private static void reject(TestWorkItemSnapshot item, String code, String reason) {
        item.setOutcomeCode(code);
        item.setReason(reason);
    }
 
    @FunctionalInterface
    interface TaskLookup {
        List<LimsJianyanXiangEntity> find(String tenantId, List<String> ids);
    }
}