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.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.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.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 config = JsonUtil.getJsonToBean(value, Map.class); if (config == null || !(config.get("read") instanceof Map) || !(config.get("write") instanceof Map)) return false; Map read = (Map) config.get("read"); Map write = (Map) 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 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(); } }