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.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.ProductionProductMainMapper;
|
import com.ruoyi.production.service.ProductionAccountService;
|
import com.ruoyi.production.pojo.ProductionOperationTask;
|
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.stock.pojo.StockInRecord;
|
import com.ruoyi.stock.service.StockInRecordService;
|
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 org.springframework.transaction.annotation.Transactional;
|
|
import jakarta.servlet.http.HttpServletResponse;
|
import java.math.BigDecimal;
|
import java.time.LocalDate;
|
import java.time.format.DateTimeFormatter;
|
import java.util.Arrays;
|
import java.util.List;
|
|
@AllArgsConstructor
|
@Service
|
public class QualityUnqualifiedServiceImpl extends ServiceImpl<QualityUnqualifiedMapper, QualityUnqualified> implements IQualityUnqualifiedService {
|
|
private final StockUtils stockUtils;
|
private final QualityUnqualifiedMapper qualityUnqualifiedMapper;
|
private final IQualityInspectService qualityInspectService;
|
private final ProductionProductMainMapper productionProductMainMapper;
|
private final ProductionOperationTaskMapper productionOperationTaskMapper;
|
private final StockUninventoryService stockUninventoryService;
|
private final StockInRecordService stockInRecordService;
|
private final ProductionAccountService productionAccountService;
|
|
@Override
|
public IPage<QualityUnqualified> qualityUnqualifiedListPage(Page page, QualityUnqualified qualityUnqualified) {
|
return qualityUnqualifiedMapper.qualityUnqualifiedListPage(page, qualityUnqualified);
|
}
|
|
@Override
|
public void qualityUnqualifiedExport(HttpServletResponse response, QualityUnqualified qualityUnqualified) {
|
List<QualityUnqualified> qualityUnqualifieds = qualityUnqualifiedMapper.qualityUnqualifiedExport(qualityUnqualified);
|
ExcelUtil<QualityUnqualified> util = new ExcelUtil<>(QualityUnqualified.class);
|
util.exportExcel(response, qualityUnqualifieds, "不合格管理导出");
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public int deal(QualityUnqualified qualityUnqualified) {
|
QualityUnqualified unqualified = qualityUnqualifiedMapper.selectById(qualityUnqualified.getId());
|
QualityInspect qualityInspect = qualityInspectService.getById(unqualified.getInspectId());
|
String batchNo = qualityInspect == null ? null
|
: resolveProductionBatchNo(qualityInspect.getProductMainId(), qualityInspect.getId(), qualityInspect.getProductModelId());
|
if (ObjectUtils.isNotNull(qualityInspect) && qualityInspect.getInspectType() != 0) {
|
ProductionProductMain sourceMain = null;
|
if (ObjectUtils.isNotNull(qualityInspect.getProductMainId())) {
|
sourceMain = productionProductMainMapper.selectById(qualityInspect.getProductMainId());
|
}
|
switch (qualityUnqualified.getDealResult()) {
|
case "报工":
|
handleProductionReportResult(qualityUnqualified, unqualified, sourceMain);
|
break;
|
case "报废":
|
handleProductionScrapResult(qualityInspect, qualityUnqualified, unqualified, sourceMain, batchNo);
|
break;
|
case "让步放行":
|
stockUtils.addStockWithBatchNo(qualityInspect.getProductModelId(), unqualified.getQuantity(),
|
StockInQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(), unqualified.getId(), batchNo);
|
break;
|
default:
|
break;
|
}
|
} else {
|
Long modelId = qualityUnqualifiedMapper.getModelId(qualityUnqualified.getProductName(), qualityUnqualified.getModel());
|
switch (qualityUnqualified.getDealResult()) {
|
case "报废":
|
stockUtils.addUnStock(modelId, unqualified.getQuantity(),
|
StockInQualifiedRecordTypeEnum.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 handleProductionReportResult(QualityUnqualified qualityUnqualified,
|
QualityUnqualified sourceUnqualified,
|
ProductionProductMain sourceMain) {
|
Integer dealType = qualityUnqualified.getDealType();
|
if (dealType == null) {
|
throw new ServiceException("报工时必须选择不合格类型");
|
}
|
if (sourceMain == null || sourceMain.getProductionOperationTaskId() == null) {
|
throw new ServiceException("历史报工未绑定生产工单,无法执行报工处理");
|
}
|
if (Integer.valueOf(0).equals(dealType)) {
|
applyLightRework(sourceMain, qualityUnqualified);
|
return;
|
}
|
if (Integer.valueOf(1).equals(dealType)) {
|
markSourceMainAsUnpaid(sourceMain, 2);
|
createReworkProductionByNewModel(sourceMain, sourceUnqualified.getQuantity());
|
qualityUnqualified.setRegenerateNewOrder(1);
|
productionAccountService.rebuildByProductionProductMainId(sourceMain.getId());
|
return;
|
}
|
throw new ServiceException("报工处理仅支持轻微返工或严重返工");
|
}
|
|
private void handleProductionScrapResult(QualityInspect qualityInspect,
|
QualityUnqualified qualityUnqualified,
|
QualityUnqualified sourceUnqualified,
|
ProductionProductMain sourceMain,
|
String batchNo) {
|
if (sourceMain == null || sourceMain.getProductionOperationTaskId() == null) {
|
throw new ServiceException("历史报工未绑定生产工单,无法执行报废处理");
|
}
|
markSourceMainAsUnpaid(sourceMain, 3);
|
createReworkProductionByNewModel(sourceMain, sourceUnqualified.getQuantity());
|
qualityUnqualified.setRegenerateNewOrder(1);
|
productionAccountService.rebuildByProductionProductMainId(sourceMain.getId());
|
// 原有报废库存处理逻辑先按新规则注释,不再直接按不合格单执行报废出库。
|
// stockUtils.addUnStockWithBatchNo(qualityInspect.getProductModelId(), sourceUnqualified.getQuantity(),
|
// StockInQualifiedRecordTypeEnum.DEFECTIVE_SCRAP.getCode(), sourceUnqualified.getId(), batchNo);
|
}
|
|
private void applyLightRework(ProductionProductMain sourceMain, QualityUnqualified qualityUnqualified) {
|
if (qualityUnqualified.getRepairWorkHour() == null
|
|| qualityUnqualified.getRepairWorkHour().compareTo(BigDecimal.ZERO) <= 0) {
|
throw new ServiceException("轻微返工必须填写大于0的修理工时");
|
}
|
ProductionProductMain update = new ProductionProductMain();
|
update.setId(sourceMain.getId());
|
update.setReportType(1);
|
update.setRepairWorkHour(defaultDecimal(sourceMain.getRepairWorkHour()).add(defaultDecimal(qualityUnqualified.getRepairWorkHour())));
|
productionProductMainMapper.updateById(update);
|
qualityUnqualified.setRegenerateNewOrder(0);
|
productionAccountService.rebuildByProductionProductMainId(sourceMain.getId());
|
}
|
|
private void markSourceMainAsUnpaid(ProductionProductMain sourceMain, int reportType) {
|
ProductionProductMain update = new ProductionProductMain();
|
update.setId(sourceMain.getId());
|
update.setReportType(reportType);
|
productionProductMainMapper.updateById(update);
|
}
|
|
private void createReworkProductionByNewModel(ProductionProductMain sourceMain, BigDecimal quantity) {
|
ProductionOperationTask sourceTask = productionOperationTaskMapper.selectById(sourceMain.getProductionOperationTaskId());
|
if (sourceTask == null) {
|
throw new ServiceException("关联的生产工单不存在");
|
}
|
ProductionOperationTask newTask = new ProductionOperationTask();
|
BeanUtils.copyProperties(sourceTask, newTask);
|
newTask.setId(null);
|
newTask.setWorkOrderNo(generateNextTaskNo("FG"));
|
newTask.setPlanQuantity(defaultDecimal(quantity));
|
newTask.setCompleteQuantity(BigDecimal.ZERO);
|
newTask.setPlanStartTime(null);
|
newTask.setPlanEndTime(null);
|
newTask.setActualStartTime(null);
|
newTask.setActualEndTime(null);
|
newTask.setStatus(1);
|
newTask.setCreateTime(null);
|
newTask.setUpdateTime(null);
|
productionOperationTaskMapper.insert(newTask);
|
}
|
|
private String generateNextTaskNo(String prefix) {
|
String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
String taskPrefix = prefix + datePrefix;
|
ProductionOperationTask latestTask = productionOperationTaskMapper.selectOne(
|
Wrappers.<ProductionOperationTask>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;
|
}
|
|
private String resolveProductionBatchNo(Long productionProductMainId,
|
Long qualityInspectId,
|
Long productModelId) {
|
if (productModelId == null) {
|
return null;
|
}
|
if (productionProductMainId != null) {
|
StockInRecord productionRecord = stockInRecordService.getOne(
|
Wrappers.<StockInRecord>lambdaQuery()
|
.eq(StockInRecord::getRecordId, productionProductMainId)
|
.eq(StockInRecord::getProductModelId, productModelId)
|
.in(StockInRecord::getRecordType, Arrays.asList(
|
StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(),
|
StockInQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode()))
|
.isNotNull(StockInRecord::getBatchNo)
|
.orderByDesc(StockInRecord::getId)
|
.last("limit 1"),
|
false);
|
if (productionRecord != null) {
|
return productionRecord.getBatchNo();
|
}
|
}
|
if (qualityInspectId == null) {
|
return null;
|
}
|
StockInRecord inspectRecord = stockInRecordService.getOne(
|
Wrappers.<StockInRecord>lambdaQuery()
|
.eq(StockInRecord::getRecordId, qualityInspectId)
|
.eq(StockInRecord::getProductModelId, productModelId)
|
.eq(StockInRecord::getRecordType, StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode())
|
.isNotNull(StockInRecord::getBatchNo)
|
.orderByDesc(StockInRecord::getId)
|
.last("limit 1"),
|
false);
|
return inspectRecord == null ? null : inspectRecord.getBatchNo();
|
}
|
}
|