package jnpf.elnService.template.impl; import cn.hutool.core.util.IdUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import jnpf.elnEntity.template.ElnTemplateRepeatGroupEntity; import jnpf.elnEntity.template.ElnTemplateVos; import jnpf.elnMapper.ElnTemplateRepeatGroupMapper; import jnpf.elnService.template.ElnTemplateRepeatGroupService; import jnpf.exception.DataException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import java.util.ArrayList; import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.function.Supplier; @Service public class ElnTemplateRepeatGroupServiceImpl implements ElnTemplateRepeatGroupService { public static final int DEFAULT_MIN_ROWS = 0; public static final int DEFAULT_MAX_ROWS = 100; public static final int HARD_MAX_ROWS = 1000; private final Store store; private final Supplier idSupplier; @Autowired public ElnTemplateRepeatGroupServiceImpl(ElnTemplateRepeatGroupMapper mapper) { this(new MyBatisStore(mapper), IdUtil::getSnowflakeNextIdStr); } public ElnTemplateRepeatGroupServiceImpl(Store store, Supplier idSupplier) { this.store = store; this.idSupplier = idSupplier; } @Override public List list(String tenantId, String templateId) { requireIdentity(tenantId, templateId); List result = new ArrayList<>(); for (ElnTemplateRepeatGroupEntity entity : store.list(tenantId.trim(), templateId.trim())) { result.add(toVo(entity)); } result.sort(Comparator.comparing(ElnTemplateVos.RepeatGroup::getGroupCode)); return result; } @Override @Transactional public ElnTemplateVos.RepeatGroup ensureConfigured(String tenantId, String templateId, String groupCode, Integer minRows, Integer maxRows, String stepId, String operatorId) { requireIdentity(tenantId, templateId); String normalizedCode = requireGroupCode(groupCode); String normalizedStepId = requireStepId(stepId); ElnTemplateRepeatGroupEntity existing = store.find( tenantId.trim(), templateId.trim(), normalizedCode); if (existing != null) { validateRange(existing.getMinRows(), existing.getMaxRows()); if ((minRows != null && !Objects.equals(minRows, existing.getMinRows())) || (maxRows != null && !Objects.equals(maxRows, existing.getMaxRows())) || !normalizedStepId.equals(existing.getStepId())) { throw new DataException("重复组配置与已有配置不一致"); } return toVo(existing); } int normalizedMin = minRows == null ? DEFAULT_MIN_ROWS : minRows; int normalizedMax = maxRows == null ? DEFAULT_MAX_ROWS : maxRows; validateRange(normalizedMin, normalizedMax); ElnTemplateRepeatGroupEntity created = new ElnTemplateRepeatGroupEntity(); created.setId(requireId(idSupplier.get())); created.setFTenantId(tenantId.trim()); created.setMubanId(templateId.trim()); created.setRepeatGroupCode(normalizedCode); created.setMinRows(normalizedMin); created.setMaxRows(normalizedMax); created.setStepId(normalizedStepId); created.setFVersion(0); created.setFCreatorUserId(trim(operatorId)); created.setFCreatorTime(new Date()); created.setFDeleteMark(0); store.insert(created); return toVo(created); } @Override @Transactional public void afterBindingsActivated(String tenantId, String sourceTemplateId, String targetTemplateId, Map bindingIdMap) { copyForVersion(tenantId, sourceTemplateId, targetTemplateId); } @Override @Transactional public void copyForVersion(String tenantId, String sourceTemplateId, String targetTemplateId) { requireIdentity(tenantId, sourceTemplateId); requireIdentity(tenantId, targetTemplateId); for (ElnTemplateRepeatGroupEntity source : store.list(tenantId.trim(), sourceTemplateId.trim())) { ElnTemplateVos.RepeatGroup validated = toVo(source); ElnTemplateRepeatGroupEntity existing = store.find(tenantId.trim(), targetTemplateId.trim(), validated.getGroupCode()); if (existing != null) { ElnTemplateVos.RepeatGroup current = toVo(existing); if (!Objects.equals(validated.getMinRows(), current.getMinRows()) || !Objects.equals(validated.getMaxRows(), current.getMaxRows())) { throw new DataException("目标模板重复组配置与来源版本不一致"); } continue; } ElnTemplateRepeatGroupEntity copied = new ElnTemplateRepeatGroupEntity(); copied.setId(requireId(idSupplier.get())); copied.setFTenantId(tenantId.trim()); copied.setMubanId(targetTemplateId.trim()); copied.setRepeatGroupCode(validated.getGroupCode()); copied.setMinRows(validated.getMinRows()); copied.setMaxRows(validated.getMaxRows()); copied.setFVersion(0); copied.setFCreatorTime(new Date()); copied.setFDeleteMark(0); store.insert(copied); } } private static ElnTemplateVos.RepeatGroup toVo(ElnTemplateRepeatGroupEntity entity) { if (entity == null) { throw new DataException("重复组配置不存在"); } String code = requireGroupCode(entity.getRepeatGroupCode()); validateRange(entity.getMinRows(), entity.getMaxRows()); ElnTemplateVos.RepeatGroup result = new ElnTemplateVos.RepeatGroup(); result.setGroupCode(code); result.setMinRows(entity.getMinRows()); result.setMaxRows(entity.getMaxRows()); result.setStepId(entity.getStepId()); return result; } private static void validateRange(Integer minRows, Integer maxRows) { if (minRows == null || maxRows == null || minRows < 0 || maxRows < minRows || maxRows > HARD_MAX_ROWS) { throw new DataException("重复组行数约束无效"); } } private static String requireGroupCode(String value) { String code = trim(value); if (code == null || !code.matches("[A-Za-z0-9_-]{1,80}")) { throw new DataException("重复组编码无效"); } return code; } private static void requireIdentity(String tenantId, String templateId) { if (!StringUtils.hasText(tenantId) || !StringUtils.hasText(templateId)) { throw new DataException("租户或模板标识无效"); } } private static String requireId(String value) { if (!StringUtils.hasText(value)) { throw new DataException("重复组配置标识生成失败"); } return value.trim(); } private static String requireStepId(String value) { if (!StringUtils.hasText(value)) { throw new DataException("重复组所属步骤无效"); } return value.trim(); } private static String trim(String value) { return StringUtils.hasText(value) ? value.trim() : null; } public interface Store { ElnTemplateRepeatGroupEntity find(String tenantId, String templateId, String groupCode); List list(String tenantId, String templateId); void insert(ElnTemplateRepeatGroupEntity entity); } private static final class MyBatisStore implements Store { private final ElnTemplateRepeatGroupMapper mapper; private MyBatisStore(ElnTemplateRepeatGroupMapper mapper) { this.mapper = mapper; } @Override public ElnTemplateRepeatGroupEntity find(String tenantId, String templateId, String groupCode) { return mapper.selectOne(Wrappers.lambdaQuery() .eq(ElnTemplateRepeatGroupEntity::getFTenantId, tenantId) .eq(ElnTemplateRepeatGroupEntity::getMubanId, templateId) .eq(ElnTemplateRepeatGroupEntity::getRepeatGroupCode, groupCode) .and(q -> q.isNull(ElnTemplateRepeatGroupEntity::getFDeleteMark) .or().eq(ElnTemplateRepeatGroupEntity::getFDeleteMark, 0))); } @Override public List list(String tenantId, String templateId) { return mapper.selectList(Wrappers.lambdaQuery() .eq(ElnTemplateRepeatGroupEntity::getFTenantId, tenantId) .eq(ElnTemplateRepeatGroupEntity::getMubanId, templateId) .and(q -> q.isNull(ElnTemplateRepeatGroupEntity::getFDeleteMark) .or().eq(ElnTemplateRepeatGroupEntity::getFDeleteMark, 0)) .orderByAsc(ElnTemplateRepeatGroupEntity::getRepeatGroupCode)); } @Override public void insert(ElnTemplateRepeatGroupEntity entity) { mapper.insert(entity); } } }