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();
|
}
|
}
|