| | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; |
| | |
| | | import cn.iocoder.yudao.module.mes.controller.admin.qc.indicator.vo.MesQcIndicatorSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.qc.indicator.MesQcIndicatorMapper; |
| | | import cn.iocoder.yudao.module.mes.enums.qc.MesQcIndicatorItemTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.qc.MesQcResultValueTypeEnum; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; |
| | | import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; |
| | | |
| | | /** |
| | | * MES 质检指标 Service 实现类 |
| | | * |
| | | * @author 芋道源码 |
| | | * @author 超级管理员 |
| | | */ |
| | | @Service |
| | | @Validated |
| | |
| | | |
| | | // 插入 |
| | | MesQcIndicatorDO indicator = BeanUtils.toBean(createReqVO, MesQcIndicatorDO.class); |
| | | normalizeHierarchy(indicator); |
| | | indicatorMapper.insert(indicator); |
| | | return indicator.getId(); |
| | | } |
| | |
| | | |
| | | // 更新 |
| | | MesQcIndicatorDO updateObj = BeanUtils.toBean(updateReqVO, MesQcIndicatorDO.class); |
| | | normalizeHierarchy(updateObj); |
| | | indicatorMapper.updateById(updateObj); |
| | | } |
| | | |
| | |
| | | public void deleteIndicator(Long id) { |
| | | // 校验存在 |
| | | validateIndicatorExists(id); |
| | | // 级联删除子项:指标只支持两层,挂在它下面的都是它的明细项,父删了子无处可挂 |
| | | List<MesQcIndicatorDO> children = indicatorMapper.selectListByParentId(id); |
| | | if (CollUtil.isNotEmpty(children)) { |
| | | indicatorMapper.deleteByIds(convertList(children, MesQcIndicatorDO::getId)); |
| | | } |
| | | // 删除 |
| | | indicatorMapper.deleteById(id); |
| | | } |
| | |
| | | validateIndicatorCodeUnique(id, saveReqVO.getCode()); |
| | | // 校验名称唯一 |
| | | validateIndicatorNameUnique(id, saveReqVO.getName()); |
| | | // 校验层级归属(只允许两层) |
| | | validateHierarchy(id, saveReqVO); |
| | | // 校验结果值属性 |
| | | validateResultSpecification(saveReqVO.getResultType(), saveReqVO.getResultSpecification()); |
| | | validateResultSpecification(saveReqVO.getItemType(), saveReqVO.getResultType(), saveReqVO.getResultSpecification()); |
| | | } |
| | | |
| | | /** |
| | | * 校验层级归属。只允许两层:分组项必须顶级,录入项可挂到分组项下。 |
| | | * <p> |
| | | * 「父必须是分组项」这条本身就掐死了第三层,所以不再单独写一条「父必须顶级」的校验。 |
| | | * 按业务优先级只抛第一处不满足,避免一次抛多条让用户抓不住重点。 |
| | | */ |
| | | private void validateHierarchy(Long id, MesQcIndicatorSaveReqVO reqVO) { |
| | | Long parentId = ObjectUtils.defaultIfNull(reqVO.getParentId(), MesQcIndicatorDO.PARENT_ID_ROOT); |
| | | Integer itemType = ObjectUtils.defaultIfNull(reqVO.getItemType(), MesQcIndicatorItemTypeEnum.ENTRY.getType()); |
| | | // 1. 分组项只能顶级 |
| | | if (MesQcIndicatorItemTypeEnum.isGroup(itemType) && !MesQcIndicatorDO.PARENT_ID_ROOT.equals(parentId)) { |
| | | throw new ServiceException(QC_INDICATOR_GROUP_CANNOT_NEST.getCode(), |
| | | String.format("分组项[%s]必须作为顶级指标,不能挂到其它指标下(当前选择了父指标[%s])。" |
| | | + "如需调整层级,请把「条目类型」改为录入项后再选择所属分组。", |
| | | defaultStr(reqVO.getName()), nameOf(parentId))); |
| | | } |
| | | // 2. 父指标必须存在且是分组项 |
| | | if (!MesQcIndicatorDO.PARENT_ID_ROOT.equals(parentId)) { |
| | | if (Objects.equals(id, parentId)) { |
| | | throw exception(QC_INDICATOR_PARENT_SELF); |
| | | } |
| | | MesQcIndicatorDO parent = indicatorMapper.selectById(parentId); |
| | | if (parent == null) { |
| | | throw new ServiceException(QC_INDICATOR_PARENT_NOT_EXISTS.getCode(), |
| | | String.format("所属分组不存在(指标编号 %d 查无此指标,可能已被删除)。请重新选择所属分组,或清空该项作为顶级指标。", |
| | | parentId)); |
| | | } |
| | | if (!MesQcIndicatorItemTypeEnum.isGroup(parent.getItemType())) { |
| | | throw new ServiceException(QC_INDICATOR_PARENT_NOT_GROUP.getCode(), |
| | | String.format("所选父指标[%s]不是分组项(当前条目类型为[%s]),不能作为所属分组。" |
| | | + "请改选一个分组项,或先在指标列表把[%s]的条目类型改为分组项。", |
| | | defaultStr(parent.getName()), itemTypeNameOf(parent.getItemType()), defaultStr(parent.getName()))); |
| | | } |
| | | } |
| | | // 3. 录入项必须有结果值类型(分组项没有结果值,现网分组行 result_type 就是 NULL) |
| | | if (!MesQcIndicatorItemTypeEnum.isGroup(itemType) && reqVO.getResultType() == null) { |
| | | throw exception(QC_INDICATOR_RESULT_TYPE_REQUIRED); |
| | | } |
| | | // 4. 自己已经有子项时,不能再被别人收编、也不能反过来变成子项 |
| | | if (id == null) { |
| | | return; |
| | | } |
| | | Long childCount = indicatorMapper.selectCountByParentId(id); |
| | | if (childCount <= 0) { |
| | | return; |
| | | } |
| | | if (!MesQcIndicatorDO.PARENT_ID_ROOT.equals(parentId)) { |
| | | throw new ServiceException(QC_INDICATOR_HAS_CHILDREN.getCode(), |
| | | String.format("指标[%s]下已挂有 %d 个录入项,不能再挂到其它分组下(指标只支持两层)。" |
| | | + "请先删除或移走这 %d 个子项,再修改它的所属分组。", |
| | | defaultStr(reqVO.getName()), childCount, childCount)); |
| | | } |
| | | if (!MesQcIndicatorItemTypeEnum.isGroup(itemType)) { |
| | | throw new ServiceException(QC_INDICATOR_HAS_CHILDREN.getCode(), |
| | | String.format("指标[%s]下已挂有 %d 个录入项,不能再把它的条目类型改为录入项,否则这些子项会失去所属分组。" |
| | | + "请先删除或移走这 %d 个子项,再修改条目类型。", |
| | | defaultStr(reqVO.getName()), childCount, childCount)); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 落库前补齐层级字段:分组项清空结果值(现网分组行没有结果值),排序号留空则排到同级末尾 |
| | | */ |
| | | private void normalizeHierarchy(MesQcIndicatorDO indicator) { |
| | | indicator.setParentId(ObjectUtils.defaultIfNull(indicator.getParentId(), MesQcIndicatorDO.PARENT_ID_ROOT)); |
| | | indicator.setItemType(ObjectUtils.defaultIfNull(indicator.getItemType(), MesQcIndicatorItemTypeEnum.ENTRY.getType())); |
| | | if (MesQcIndicatorItemTypeEnum.isGroup(indicator.getItemType())) { |
| | | indicator.setResultType(null); |
| | | indicator.setResultSpecification(null); |
| | | } |
| | | if (indicator.getSortOrder() == null) { |
| | | Integer max = indicatorMapper.selectMaxSortOrder(indicator.getParentId()); |
| | | indicator.setSortOrder((max == null ? 0 : max) + (MesQcIndicatorDO.PARENT_ID_ROOT.equals(indicator.getParentId()) ? 10 : 1)); |
| | | } |
| | | } |
| | | |
| | | private String nameOf(Long id) { |
| | | MesQcIndicatorDO indicator = id == null ? null : indicatorMapper.selectById(id); |
| | | return indicator == null ? String.valueOf(id) : defaultStr(indicator.getName()); |
| | | } |
| | | |
| | | private static String itemTypeNameOf(Integer itemType) { |
| | | return MesQcIndicatorItemTypeEnum.isGroup(itemType) |
| | | ? MesQcIndicatorItemTypeEnum.GROUP.getName() : MesQcIndicatorItemTypeEnum.ENTRY.getName(); |
| | | } |
| | | |
| | | private static String defaultStr(String value) { |
| | | return StrUtil.blankToDefault(value, ""); |
| | | } |
| | | |
| | | private void validateIndicatorExists(Long id) { |
| | |
| | | } |
| | | } |
| | | |
| | | private void validateResultSpecification(Integer resultType, String resultSpecification) { |
| | | private void validateResultSpecification(Integer itemType, Integer resultType, String resultSpecification) { |
| | | // 分组项没有结果值,落库前会被清空,这里不校验 |
| | | if (MesQcIndicatorItemTypeEnum.isGroup(ObjectUtils.defaultIfNull(itemType, MesQcIndicatorItemTypeEnum.ENTRY.getType()))) { |
| | | return; |
| | | } |
| | | if (ObjectUtils.equalsAny(resultType, MesQcResultValueTypeEnum.FILE.getType(), |
| | | MesQcResultValueTypeEnum.DICT.getType())) { |
| | | if (StrUtil.isBlank(resultSpecification)) { |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<MesQcIndicatorDO> getIndicatorGroupList() { |
| | | return indicatorMapper.selectListByItemType(MesQcIndicatorItemTypeEnum.GROUP.getType()); |
| | | } |
| | | |
| | | @Override |
| | | public List<MesQcIndicatorDO> getIndicatorList(Collection<Long> ids) { |
| | | if (CollUtil.isEmpty(ids)) { |
| | | return Collections.emptyList(); |