云
3 天以前 87733eb3623593da247c051593d64b8ff9e1d3a4
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/seedquality/MesQcSeedIndicatorRangeService.java
@@ -1,45 +1,121 @@
package cn.iocoder.yudao.module.mes.service.qc.seedquality;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.mes.controller.admin.qc.seedquality.vo.MesQcSeedIndicatorRangeSaveReqVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.qc.seedquality.MesQcSeedIndicatorRangeDO;
import cn.iocoder.yudao.module.mes.dal.mysql.qc.seedquality.MesQcSeedIndicatorRangeMapper;
import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import java.math.BigDecimal;
import java.util.stream.Collectors;
import java.util.Map;
@Service
public class MesQcSeedIndicatorRangeService {
    private static final Set<String> CODES = Set.of("purity", "cleanliness", "germination_rate", "moisture");
    @Resource private MesQcSeedIndicatorRangeMapper mapper;
    public List<MesQcSeedIndicatorRangeDO> getRanges() {
        return mapper.selectList().stream().filter(item -> CODES.contains(item.getIndicatorCode())).toList();
    @Resource
    private MesQcSeedIndicatorRangeMapper mapper;
    @Resource
    private MesMdmItemService mdmItemService;
    /** 配置页查询:itemId 为空表示通用默认项 */
    public List<MesQcSeedIndicatorRangeDO> getRanges(Long itemId, String keyword, Integer status) {
        return mapper.selectListByItemId(itemId, keyword, status);
    }
    /**
     * 生效指标:产品专属配置优先,未配置时回退通用默认项。
     */
    public List<MesQcSeedIndicatorRangeDO> getEffectiveRanges(Long itemId) {
        List<MesQcSeedIndicatorRangeDO> productRanges = itemId == null ? List.of() : mapper.selectEnabledByItemId(itemId);
        return productRanges.isEmpty() ? mapper.selectEnabledDefaults() : productRanges;
    }
    public Map<String, MesQcSeedIndicatorRangeDO> getEffectiveMap(Long itemId) {
        Map<String, MesQcSeedIndicatorRangeDO> result = new LinkedHashMap<>();
        for (MesQcSeedIndicatorRangeDO range : getEffectiveRanges(itemId)) {
            result.put(range.getIndicatorCode(), range);
        }
        return result;
    }
    @Transactional(rollbackFor = Exception.class)
    public void saveRanges(MesQcSeedIndicatorRangeSaveReqVO request) {
        List<MesQcSeedIndicatorRangeSaveReqVO.Item> items = request.getRanges();
        if (items == null || items.size() != CODES.size() || items.stream().anyMatch(item -> item == null || item.getIndicatorCode() == null
                || item.getMinValue() == null || item.getMaxValue() == null)
                || !items.stream().map(MesQcSeedIndicatorRangeSaveReqVO.Item::getIndicatorCode)
                .collect(Collectors.toSet()).equals(CODES))
            throw new IllegalArgumentException("必须完整配置纯度、净度、发芽率、水分四项指标");
        for (MesQcSeedIndicatorRangeSaveReqVO.Item item : items) {
            if (item.getMinValue().compareTo(BigDecimal.ZERO) < 0 || item.getMaxValue().compareTo(new BigDecimal("100")) > 0
                    || item.getMinValue().compareTo(item.getMaxValue()) > 0)
                throw new IllegalArgumentException("指标合格范围必须处于 0–100 且下限不大于上限:" + item.getIndicatorCode());
            MesQcSeedIndicatorRangeDO row = new MesQcSeedIndicatorRangeDO();
            row.setIndicatorCode(item.getIndicatorCode());
            row.setMinValue(item.getMinValue());
            row.setMaxValue(item.getMaxValue());
            if (mapper.selectById(item.getIndicatorCode()) == null) mapper.insert(row);
            else mapper.updateById(row);
        }
    public Long create(MesQcSeedIndicatorRangeSaveReqVO reqVO) {
        validateProduct(reqVO.getItemId());
        validateRange(reqVO);
        if (mapper.selectByItemIdAndCode(reqVO.getItemId(), reqVO.getIndicatorCode()) != null)
            throw new IllegalArgumentException("该产品已存在相同编码的质检项:" + reqVO.getIndicatorCode());
        MesQcSeedIndicatorRangeDO row = buildRow(reqVO);
        mapper.insert(row);
        return row.getId();
    }
    @Transactional(rollbackFor = Exception.class)
    public void update(Long id, MesQcSeedIndicatorRangeSaveReqVO reqVO) {
        MesQcSeedIndicatorRangeDO existing = mapper.selectById(id);
        if (existing == null) throw new IllegalArgumentException("质检项不存在或已删除");
        validateProduct(reqVO.getItemId());
        validateRange(reqVO);
        MesQcSeedIndicatorRangeDO sameCode = mapper.selectByItemIdAndCode(reqVO.getItemId(), reqVO.getIndicatorCode());
        if (sameCode != null && !sameCode.getId().equals(id))
            throw new IllegalArgumentException("该产品已存在相同编码的质检项:" + reqVO.getIndicatorCode());
        MesQcSeedIndicatorRangeDO update = buildRow(reqVO);
        update.setId(id);
        mapper.updateById(update);
    }
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        MesQcSeedIndicatorRangeDO existing = mapper.selectById(id);
        if (existing == null) throw new IllegalArgumentException("质检项不存在或已删除");
        mapper.deleteById(id);
    }
    /** 将通用默认项复制到指定产品,已存在的编码跳过 */
    @Transactional(rollbackFor = Exception.class)
    public int copyDefaults(Long itemId) {
        validateProduct(itemId);
        int copied = 0;
        for (MesQcSeedIndicatorRangeDO source : mapper.selectEnabledDefaults()) {
            if (mapper.selectByItemIdAndCode(itemId, source.getIndicatorCode()) != null) continue;
            MesQcSeedIndicatorRangeDO row = new MesQcSeedIndicatorRangeDO();
            row.setItemId(itemId);
            row.setIndicatorCode(source.getIndicatorCode());
            row.setIndicatorName(source.getIndicatorName());
            row.setUnit(source.getUnit());
            row.setMinValue(source.getMinValue());
            row.setMaxValue(source.getMaxValue());
            row.setSort(source.getSort());
            row.setStatus(0);
            mapper.insert(row);
            copied++;
        }
        return copied;
    }
    private void validateProduct(Long itemId) {
        if (itemId == null) throw new IllegalArgumentException("请先选择产品");
        if (mdmItemService.getItem(itemId) == null) throw new IllegalArgumentException("产品不存在,请重新选择");
    }
    private void validateRange(MesQcSeedIndicatorRangeSaveReqVO reqVO) {
        if (reqVO.getMinValue().compareTo(reqVO.getMaxValue()) > 0)
            throw new IllegalArgumentException("合格下限不能大于上限:" + reqVO.getIndicatorName());
    }
    private MesQcSeedIndicatorRangeDO buildRow(MesQcSeedIndicatorRangeSaveReqVO reqVO) {
        MesQcSeedIndicatorRangeDO row = new MesQcSeedIndicatorRangeDO();
        row.setItemId(reqVO.getItemId());
        row.setIndicatorCode(reqVO.getIndicatorCode().trim());
        row.setIndicatorName(reqVO.getIndicatorName().trim());
        row.setUnit(StrUtil.blankToDefault(reqVO.getUnit(), "%"));
        row.setMinValue(reqVO.getMinValue());
        row.setMaxValue(reqVO.getMaxValue());
        row.setSort(reqVO.getSort() == null ? 0 : reqVO.getSort());
        row.setStatus(reqVO.getStatus() == null ? 0 : reqVO.getStatus());
        return row;
    }
}