package cn.iocoder.yudao.module.mes.service.qc.template;
|
|
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.util.ObjUtil;
|
import cn.hutool.core.util.StrUtil;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcTemplateProcessRespVO;
|
import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.MesQcTemplateProcessSaveByTemplateReqVO;
|
import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.MesQcTemplateProcessSaveListReqVO;
|
import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.MesQcTemplateProcessSaveReqVO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateIndicatorDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateProcessDO;
|
import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateProcessMapper;
|
import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
|
import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService;
|
import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService;
|
import jakarta.annotation.Resource;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.validation.annotation.Validated;
|
|
import java.util.*;
|
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
|
|
/**
|
* MES 质检方案-工序绑定 Service 实现类
|
*
|
* @author 超级管理员
|
*/
|
@Service
|
@Validated
|
public class MesQcTemplateProcessServiceImpl implements MesQcTemplateProcessService {
|
|
@Resource
|
private MesQcTemplateProcessMapper templateProcessMapper;
|
@Resource
|
private MesProProcessService processService;
|
@Resource
|
private MesQcTemplateService templateService;
|
@Resource
|
private MesQcTemplateIndicatorService templateIndicatorService;
|
@Resource
|
private MesQcIndicatorService indicatorService;
|
|
@Override
|
public List<MesQcTemplateProcessDO> getListByProcessId(Long processId) {
|
if (processId == null) {
|
return Collections.emptyList();
|
}
|
return templateProcessMapper.selectListByProcessId(processId);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void saveList(MesQcTemplateProcessSaveListReqVO reqVO) {
|
processService.validateProcessExists(reqVO.getProcessId());
|
List<MesQcTemplateProcessSaveReqVO> list = reqVO.getList() == null
|
? Collections.emptyList() : reqVO.getList();
|
validateList(reqVO.getProcessId(), list);
|
|
List<MesQcTemplateProcessDO> existingList = templateProcessMapper.selectListByProcessId(reqVO.getProcessId());
|
Set<Long> existingIds = convertSet(existingList, MesQcTemplateProcessDO::getId);
|
Set<Long> retainedIds = new HashSet<>();
|
for (MesQcTemplateProcessSaveReqVO item : list) {
|
MesQcTemplateProcessDO binding = BeanUtils.toBean(item, MesQcTemplateProcessDO.class)
|
.setProcessId(reqVO.getProcessId())
|
.setDefaultFlag(Boolean.TRUE.equals(item.getDefaultFlag()))
|
.setStatus(item.getStatus() != null ? item.getStatus() : CommonStatusEnum.ENABLE.getStatus())
|
.setSort(item.getSort() != null ? item.getSort() : 0);
|
if (binding.getId() == null) {
|
templateProcessMapper.insert(binding);
|
} else {
|
if (!existingIds.contains(binding.getId())) {
|
throw exception(QC_TEMPLATE_PROCESS_NOT_EXISTS);
|
}
|
templateProcessMapper.updateById(binding);
|
}
|
retainedIds.add(binding.getId());
|
// 同一工序、同一质检种类只允许一个默认方案
|
if (Boolean.TRUE.equals(binding.getDefaultFlag())) {
|
clearOtherDefaults(reqVO.getProcessId(), binding.getQcType(), binding.getId());
|
}
|
}
|
for (Long existingId : existingIds) {
|
if (!retainedIds.contains(existingId)) {
|
templateProcessMapper.deleteById(existingId);
|
}
|
}
|
}
|
|
@Override
|
public List<MesQcTemplateProcessDO> getListByTemplateId(Long templateId) {
|
if (templateId == null) {
|
return Collections.emptyList();
|
}
|
return templateProcessMapper.selectListByTemplateId(templateId);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void saveByTemplate(MesQcTemplateProcessSaveByTemplateReqVO reqVO) {
|
// 1. 校验方案与质检种类
|
MesQcTemplateDO template = templateService.getTemplate(reqVO.getTemplateId());
|
if (template == null) {
|
throw new ServiceException(QC_TEMPLATE_PROCESS_NOT_EXISTS.getCode(),
|
StrUtil.format("质检方案 ID={} 不存在;请刷新质检方案列表后重新选择", reqVO.getTemplateId()));
|
}
|
if (CollUtil.isNotEmpty(template.getTypes())
|
&& !template.getTypes().contains(reqVO.getQcType())) {
|
throw new ServiceException(QC_TEMPLATE_PROCESS_NOT_EXISTS.getCode(),
|
StrUtil.format("质检方案[{}]的检测种类为{},不包含[{}];请先在质检方案中维护该检测种类",
|
template.getName(), template.getTypes(), qcTypeName(reqVO.getQcType())));
|
}
|
List<MesQcTemplateProcessSaveByTemplateReqVO.ProcessItem> list = reqVO.getList() == null
|
? Collections.emptyList() : reqVO.getList();
|
Map<Long, MesQcTemplateProcessSaveByTemplateReqVO.ProcessItem> requestedMap = new LinkedHashMap<>();
|
for (MesQcTemplateProcessSaveByTemplateReqVO.ProcessItem item : list) {
|
if (requestedMap.putIfAbsent(item.getProcessId(), item) != null) {
|
throw new ServiceException(QC_TEMPLATE_PROCESS_DUPLICATE.getCode(),
|
StrUtil.format("质检方案[{}]重复选择了工序 ID={};请删除重复的工序后重试",
|
template.getName(), item.getProcessId()));
|
}
|
}
|
|
// 2. 以「已有绑定工序 ∪ 本次选择工序」为范围,逐工序重算绑定列表
|
List<MesQcTemplateProcessDO> existingList = templateProcessMapper.selectListByTemplateId(reqVO.getTemplateId());
|
Set<Long> processIds = new LinkedHashSet<>(convertSet(existingList, MesQcTemplateProcessDO::getProcessId));
|
processIds.addAll(requestedMap.keySet());
|
for (Long processId : processIds) {
|
List<MesQcTemplateProcessDO> processBindings = templateProcessMapper.selectListByProcessId(processId);
|
List<MesQcTemplateProcessSaveReqVO> targetList = new ArrayList<>();
|
for (MesQcTemplateProcessDO binding : processBindings) {
|
// 本方案 + 本质检种类的旧绑定由本次请求整体替换
|
if (ObjUtil.equal(binding.getTemplateId(), reqVO.getTemplateId())
|
&& ObjUtil.equal(binding.getQcType(), reqVO.getQcType())) {
|
continue;
|
}
|
targetList.add(BeanUtils.toBean(binding, MesQcTemplateProcessSaveReqVO.class));
|
}
|
MesQcTemplateProcessSaveByTemplateReqVO.ProcessItem requested = requestedMap.get(processId);
|
if (requested == null && targetList.isEmpty()) {
|
continue;
|
}
|
if (requested != null) {
|
targetList.add(new MesQcTemplateProcessSaveReqVO()
|
.setProcessId(processId)
|
.setTemplateId(reqVO.getTemplateId())
|
.setQcType(reqVO.getQcType())
|
.setDefaultFlag(Boolean.TRUE.equals(requested.getDefaultFlag()))
|
.setSort(requested.getSort() != null ? requested.getSort() : 0));
|
}
|
MesQcTemplateProcessSaveListReqVO saveReqVO = new MesQcTemplateProcessSaveListReqVO();
|
saveReqVO.setProcessId(processId);
|
saveReqVO.setList(targetList);
|
saveList(saveReqVO);
|
}
|
}
|
|
@Override
|
public Long resolveTemplateId(Long processId, Integer qcType) {
|
if (processId == null || qcType == null) {
|
return null;
|
}
|
return templateProcessMapper.selectListByProcessId(processId).stream()
|
.filter(binding -> ObjUtil.equal(binding.getQcType(), qcType))
|
.filter(binding -> ObjUtil.equal(binding.getStatus(), CommonStatusEnum.ENABLE.getStatus()))
|
.sorted(Comparator
|
.comparing((MesQcTemplateProcessDO binding) -> Boolean.TRUE.equals(binding.getDefaultFlag()))
|
.reversed()
|
.thenComparing(binding -> binding.getSort() != null ? binding.getSort() : 0)
|
.thenComparing(MesQcTemplateProcessDO::getId))
|
.map(MesQcTemplateProcessDO::getTemplateId)
|
.findFirst().orElse(null);
|
}
|
|
@Override
|
public MesQcIpqcTemplateProcessRespVO resolveTemplate(Long processId, Integer qcType) {
|
MesQcIpqcTemplateProcessRespVO resp = new MesQcIpqcTemplateProcessRespVO()
|
.setProcessId(processId).setQcType(qcType);
|
Long templateId = resolveTemplateId(processId, qcType);
|
if (templateId == null) {
|
return resp;
|
}
|
MesQcTemplateDO template = templateService.getTemplate(templateId);
|
if (template == null) {
|
return resp;
|
}
|
resp.setTemplateId(template.getId()).setTemplateCode(template.getCode()).setTemplateName(template.getName());
|
List<MesQcTemplateIndicatorDO> templateIndicators =
|
templateIndicatorService.getTemplateIndicatorListByTemplateId(templateId);
|
if (CollUtil.isEmpty(templateIndicators)) {
|
resp.setIndicators(Collections.emptyList());
|
return resp;
|
}
|
Map<Long, MesQcIndicatorDO> indicatorMap = indicatorService.getIndicatorMap(
|
convertSet(templateIndicators, MesQcTemplateIndicatorDO::getIndicatorId));
|
List<MesQcIpqcTemplateProcessRespVO.IndicatorItem> items = new ArrayList<>(templateIndicators.size());
|
for (MesQcTemplateIndicatorDO templateIndicator : templateIndicators) {
|
MesQcIndicatorDO indicator = indicatorMap.get(templateIndicator.getIndicatorId());
|
items.add(new MesQcIpqcTemplateProcessRespVO.IndicatorItem()
|
.setTemplateIndicatorId(templateIndicator.getId())
|
.setIndicatorId(templateIndicator.getIndicatorId())
|
.setIndicatorCode(indicator != null ? indicator.getCode() : null)
|
.setIndicatorName(indicator != null ? indicator.getName() : null)
|
.setItemType(indicator != null ? indicator.getItemType() : null)
|
.setResultType(indicator != null ? indicator.getResultType() : null)
|
.setResultSpecification(indicator != null ? indicator.getResultSpecification() : null)
|
.setUnitText(indicator != null ? indicator.getUnitText() : null)
|
.setTool(indicator != null ? indicator.getTool() : null)
|
.setCheckMethod(templateIndicator.getCheckMethod())
|
.setStandardValue(templateIndicator.getStandardValue())
|
.setUnitMeasureId(templateIndicator.getUnitMeasureId())
|
.setThresholdMax(templateIndicator.getThresholdMax())
|
.setThresholdMin(templateIndicator.getThresholdMin()));
|
}
|
resp.setIndicators(items);
|
return resp;
|
}
|
|
@Override
|
public void deleteListByTemplateId(Long templateId) {
|
List<MesQcTemplateProcessDO> list = templateProcessMapper.selectListByTemplateId(templateId);
|
if (CollUtil.isEmpty(list)) {
|
return;
|
}
|
templateProcessMapper.deleteBatch(MesQcTemplateProcessDO::getId,
|
convertSet(list, MesQcTemplateProcessDO::getId));
|
}
|
|
private void clearOtherDefaults(Long processId, Integer qcType, Long keepId) {
|
templateProcessMapper.selectListByProcessId(processId).stream()
|
.filter(binding -> ObjUtil.equal(binding.getQcType(), qcType))
|
.filter(binding -> Boolean.TRUE.equals(binding.getDefaultFlag()))
|
.filter(binding -> !ObjUtil.equal(binding.getId(), keepId))
|
.forEach(binding -> templateProcessMapper.updateById(
|
new MesQcTemplateProcessDO().setId(binding.getId()).setDefaultFlag(false)));
|
}
|
|
private static String qcTypeName(Integer qcType) {
|
return Arrays.stream(MesQcTypeEnum.values())
|
.filter(item -> ObjUtil.equal(item.getType(), qcType))
|
.map(MesQcTypeEnum::getName).findFirst().orElse("未知(" + qcType + ")");
|
}
|
|
private void validateList(Long processId, List<MesQcTemplateProcessSaveReqVO> list) {
|
if (CollUtil.isEmpty(list)) {
|
return;
|
}
|
Set<String> keys = new HashSet<>();
|
Set<String> defaultKeys = new HashSet<>();
|
for (MesQcTemplateProcessSaveReqVO item : list) {
|
if (!Arrays.asList(MesQcTypeEnum.ARRAYS).contains(item.getQcType())) {
|
throw new ServiceException(QC_TEMPLATE_PROCESS_NOT_EXISTS.getCode(),
|
StrUtil.format("工序绑定的质检种类[{}]不合法;期望 1-来料检验 / 2-过程检验 / 3-出货检验 / 4-退货检验,请重新选择",
|
item.getQcType()));
|
}
|
if (templateService.getTemplate(item.getTemplateId()) == null) {
|
throw new ServiceException(QC_TEMPLATE_PROCESS_NOT_EXISTS.getCode(),
|
StrUtil.format("工序 ID={} 绑定的质检方案 ID={} 不存在;请刷新质检方案后重新选择",
|
processId, item.getTemplateId()));
|
}
|
String key = item.getQcType() + ":" + item.getTemplateId();
|
if (!keys.add(key)) {
|
throw new ServiceException(QC_TEMPLATE_PROCESS_DUPLICATE.getCode(),
|
StrUtil.format("工序 ID={} 在质检种类[{}]下重复绑定了质检方案 ID={};请删除重复行后重试",
|
processId, qcTypeName(item.getQcType()), item.getTemplateId()));
|
}
|
if (Boolean.TRUE.equals(item.getDefaultFlag())) {
|
String defaultKey = String.valueOf(item.getQcType());
|
if (!defaultKeys.add(defaultKey)) {
|
throw new ServiceException(QC_TEMPLATE_PROCESS_DUPLICATE.getCode(),
|
StrUtil.format("工序 ID={} 在质检种类[{}]下只能设置一个默认方案;请取消多余的默认标记后重试",
|
processId, qcTypeName(item.getQcType())));
|
}
|
}
|
}
|
}
|
|
}
|