package com.ruoyi.quality.service.impl; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.procurementrecord.utils.StockUtils; import com.ruoyi.production.mapper.ProductionOperationTaskMapper; import com.ruoyi.production.mapper.ProductionOrderMapper; import com.ruoyi.production.mapper.ProductionOrderRoutingMapper; import com.ruoyi.production.mapper.ProductionOrderRoutingOperationMapper; import com.ruoyi.production.mapper.ProductionProductMainMapper; import com.ruoyi.production.pojo.ProductionOperationTask; import com.ruoyi.production.pojo.ProductionOrder; import com.ruoyi.production.pojo.ProductionOrderRouting; import com.ruoyi.production.pojo.ProductionOrderRoutingOperation; import com.ruoyi.production.pojo.ProductionProductMain; import com.ruoyi.quality.mapper.QualityUnqualifiedMapper; import com.ruoyi.quality.pojo.QualityInspect; import com.ruoyi.quality.pojo.QualityUnqualified; import com.ruoyi.quality.service.IQualityInspectService; import com.ruoyi.quality.service.IQualityUnqualifiedService; import com.ruoyi.stock.service.StockUninventoryService; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; import jakarta.servlet.http.HttpServletResponse; import java.math.BigDecimal; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.HashMap; import java.util.List; import java.util.Map; @AllArgsConstructor @Service public class QualityUnqualifiedServiceImpl extends ServiceImpl implements IQualityUnqualifiedService { private final StockUtils stockUtils; private final QualityUnqualifiedMapper qualityUnqualifiedMapper; private final IQualityInspectService qualityInspectService; private final ProductionProductMainMapper productionProductMainMapper; private final ProductionOrderMapper productionOrderMapper; private final ProductionOrderRoutingMapper productionOrderRoutingMapper; private final ProductionOrderRoutingOperationMapper productionOrderRoutingOperationMapper; private final ProductionOperationTaskMapper productionOperationTaskMapper; private final StockUninventoryService stockUninventoryService; @Override public IPage qualityUnqualifiedListPage(Page page, QualityUnqualified qualityUnqualified) { return qualityUnqualifiedMapper.qualityUnqualifiedListPage(page, qualityUnqualified); } @Override public void qualityUnqualifiedExport(HttpServletResponse response, QualityUnqualified qualityUnqualified) { List qualityUnqualifieds = qualityUnqualifiedMapper.qualityUnqualifiedExport(qualityUnqualified); ExcelUtil util = new ExcelUtil<>(QualityUnqualified.class); util.exportExcel(response, qualityUnqualifieds, "不合格管理导出"); } @Override public int deal(QualityUnqualified qualityUnqualified) { QualityUnqualified unqualified = qualityUnqualifiedMapper.selectById(qualityUnqualified.getId()); QualityInspect qualityInspect = qualityInspectService.getById(unqualified.getInspectId()); if (ObjectUtils.isNotNull(qualityInspect) && qualityInspect.getInspectType() != 0) { switch (qualityUnqualified.getDealResult()) { case "返修": case "返工": if (ObjectUtils.isNotNull(qualityInspect.getProductMainId())) { ProductionProductMain sourceMain = productionProductMainMapper.selectById(qualityInspect.getProductMainId()); if (sourceMain == null || sourceMain.getProductionOperationTaskId() == null) { throw new ServiceException("历史报工未绑定生产工单,无法按新模型返修/返工"); } createReworkProductionByNewModel(sourceMain, unqualified.getQuantity()); } break; case "报废": stockUtils.addUnStock(qualityInspect.getProductModelId(), unqualified.getQuantity(), StockInUnQualifiedRecordTypeEnum.DEFECTIVE_SCRAP.getCode(), unqualified.getId()); break; case "让步放行": stockUtils.addStock(qualityInspect.getProductModelId(), unqualified.getQuantity(), StockInQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(), unqualified.getId()); break; default: break; } } else { Long modelId = qualityUnqualifiedMapper.getModelId(qualityUnqualified.getProductName(), qualityUnqualified.getModel()); switch (qualityUnqualified.getDealResult()) { case "报废": stockUtils.addUnStock(modelId, unqualified.getQuantity(), StockInUnQualifiedRecordTypeEnum.DEFECTIVE_SCRAP.getCode(), unqualified.getId()); break; case "让步放行": stockUtils.addStock(modelId, unqualified.getQuantity(), StockInQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(), unqualified.getId()); break; default: break; } } qualityUnqualified.setInspectState(1); return qualityUnqualifiedMapper.updateById(qualityUnqualified); } @Override public QualityUnqualified getUnqualified(Integer id) { return qualityUnqualifiedMapper.getUnqualified(id); } private void createReworkProductionByNewModel(ProductionProductMain sourceMain, BigDecimal quantity) { ProductionOperationTask sourceTask = productionOperationTaskMapper.selectById(sourceMain.getProductionOperationTaskId()); if (sourceTask == null) { throw new ServiceException("关联的生产工单不存在"); } ProductionOrder sourceOrder = productionOrderMapper.selectById(sourceTask.getProductionOrderId()); if (sourceOrder == null) { throw new ServiceException("关联的生产订单不存在"); } ProductionOrder newOrder = new ProductionOrder(); BeanUtils.copyProperties(sourceOrder, newOrder); newOrder.setId(null); newOrder.setNpsNo(generateNextProductionOrderNo("FG")); newOrder.setQuantity(defaultDecimal(quantity)); newOrder.setCompleteQuantity(BigDecimal.ZERO); newOrder.setStartTime(null); newOrder.setEndTime(null); newOrder.setCreateTime(null); newOrder.setUpdateTime(null); productionOrderMapper.insert(newOrder); Map routingIdMap = new HashMap<>(); List sourceRoutings = productionOrderRoutingMapper.selectList( Wrappers.lambdaQuery() .eq(ProductionOrderRouting::getProductionOrderId, sourceOrder.getId()) .orderByAsc(ProductionOrderRouting::getId)); for (ProductionOrderRouting sourceRouting : sourceRoutings) { ProductionOrderRouting newRouting = new ProductionOrderRouting(); BeanUtils.copyProperties(sourceRouting, newRouting); newRouting.setId(null); newRouting.setProductionOrderId(newOrder.getId()); newRouting.setCreateTime(null); newRouting.setUpdateTime(null); productionOrderRoutingMapper.insert(newRouting); routingIdMap.put(sourceRouting.getId(), newRouting.getId()); } List sourceOperations = productionOrderRoutingOperationMapper.selectList( Wrappers.lambdaQuery() .eq(ProductionOrderRoutingOperation::getProductionOrderId, sourceOrder.getId()) .orderByAsc(ProductionOrderRoutingOperation::getDragSort) .orderByAsc(ProductionOrderRoutingOperation::getId)); for (ProductionOrderRoutingOperation sourceOperation : sourceOperations) { ProductionOrderRoutingOperation newOperation = new ProductionOrderRoutingOperation(); BeanUtils.copyProperties(sourceOperation, newOperation); newOperation.setId(null); newOperation.setProductionOrderId(newOrder.getId()); newOperation.setOrderRoutingId(routingIdMap.get(sourceOperation.getOrderRoutingId())); newOperation.setCreateTime(null); newOperation.setUpdateTime(null); productionOrderRoutingOperationMapper.insert(newOperation); ProductionOperationTask newTask = new ProductionOperationTask(); newTask.setProductionOrderRoutingOperationId(newOperation.getId()); newTask.setProductionOrderId(newOrder.getId()); newTask.setPlanQuantity(newOrder.getQuantity()); newTask.setCompleteQuantity(BigDecimal.ZERO); newTask.setWorkOrderNo(generateNextTaskNo("FG")); newTask.setStatus(1); productionOperationTaskMapper.insert(newTask); } } private String generateNextProductionOrderNo(String prefix) { String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); String orderPrefix = prefix + datePrefix; ProductionOrder latestOrder = productionOrderMapper.selectOne( Wrappers.lambdaQuery() .likeRight(ProductionOrder::getNpsNo, orderPrefix) .orderByDesc(ProductionOrder::getNpsNo) .last("limit 1")); int sequence = 1; if (latestOrder != null && latestOrder.getNpsNo() != null && latestOrder.getNpsNo().startsWith(orderPrefix)) { try { sequence = Integer.parseInt(latestOrder.getNpsNo().substring(orderPrefix.length())) + 1; } catch (NumberFormatException ignored) { sequence = 1; } } return orderPrefix + String.format("%04d", sequence); } private String generateNextTaskNo(String prefix) { String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); String taskPrefix = prefix + datePrefix; ProductionOperationTask latestTask = productionOperationTaskMapper.selectOne( Wrappers.lambdaQuery() .likeRight(ProductionOperationTask::getWorkOrderNo, taskPrefix) .orderByDesc(ProductionOperationTask::getWorkOrderNo) .last("limit 1")); int sequence = 1; if (latestTask != null && latestTask.getWorkOrderNo() != null && latestTask.getWorkOrderNo().startsWith(taskPrefix)) { try { sequence = Integer.parseInt(latestTask.getWorkOrderNo().substring(taskPrefix.length())) + 1; } catch (NumberFormatException ignored) { sequence = 1; } } return taskPrefix + String.format("%03d", sequence); } private BigDecimal defaultDecimal(BigDecimal value) { return value == null ? BigDecimal.ZERO : value; } }