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