package com.ruoyi.quality.service.impl;
|
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
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.basic.enums.RecordTypeEnum;
|
import com.ruoyi.basic.utils.FileUtil;
|
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.utils.bean.BeanUtils;
|
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.mapper.QualityUnqualifiedOrderMapper;
|
import com.ruoyi.quality.pojo.QualityInspect;
|
import com.ruoyi.quality.pojo.QualityUnqualified;
|
import com.ruoyi.quality.pojo.QualityUnqualifiedOrder;
|
import com.ruoyi.quality.service.IQualityInspectService;
|
import com.ruoyi.quality.service.IQualityUnqualifiedOrderService;
|
import jakarta.servlet.http.HttpServletResponse;
|
import lombok.AllArgsConstructor;
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
import org.apache.poi.ss.usermodel.*;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.io.InputStream;
|
import java.io.OutputStream;
|
import java.math.BigDecimal;
|
import java.net.URLEncoder;
|
import java.time.LocalDate;
|
import java.time.format.DateTimeFormatter;
|
import java.util.Date;
|
import java.util.HashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
@AllArgsConstructor
|
@Service
|
public class QualityUnqualifiedOrderServiceImpl extends ServiceImpl<QualityUnqualifiedOrderMapper, QualityUnqualifiedOrder> implements IQualityUnqualifiedOrderService {
|
|
private final QualityUnqualifiedOrderMapper orderMapper;
|
private final FileUtil fileUtil;
|
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;
|
|
@Override
|
public IPage<QualityUnqualifiedOrder> listPage(Page page, QualityUnqualifiedOrder query) {
|
return orderMapper.listPage(page, query);
|
}
|
|
@Override
|
public QualityUnqualifiedOrder getDetail(Long id) {
|
QualityUnqualifiedOrder order = orderMapper.selectById(id);
|
if (order != null) {
|
order.setStorageBlobVOs(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.QUALITY_UNQUALIFIED_ORDER, order.getId()));
|
}
|
return order;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public boolean save(QualityUnqualifiedOrder order) {
|
boolean result = super.save(order);
|
// 处置方式包含"维修"(2=厂内维修, 3=返厂维修)时,自动创建返修生产订单
|
if (order.getDisposalMethod() != null && (order.getDisposalMethod() == 2 || order.getDisposalMethod() == 3)) {
|
createReworkProductionOrder(order);
|
}
|
return result;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public boolean deal(QualityUnqualifiedOrder order) {
|
QualityUnqualifiedOrder existing = orderMapper.selectById(order.getId());
|
if (existing == null) {
|
return false;
|
}
|
existing.setDisposalMethod(order.getDisposalMethod());
|
existing.setRepairEvaluation(order.getRepairEvaluation());
|
existing.setReasonAnalysis(order.getReasonAnalysis());
|
existing.setCorrectionAction(order.getCorrectionAction());
|
existing.setPreventiveAction(order.getPreventiveAction());
|
existing.setRemark(order.getRemark());
|
existing.setDeptOpinion(order.getDeptOpinion());
|
existing.setCompanyDecision(order.getCompanyDecision());
|
existing.setGeneralManagerOpinion(order.getGeneralManagerOpinion());
|
existing.setStatus(3);
|
boolean result = updateById(existing);
|
if (result && existing.getDisposalMethod() != null
|
&& (existing.getDisposalMethod() == 2 || existing.getDisposalMethod() == 3)) {
|
createReworkProductionOrder(existing);
|
}
|
return result;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public boolean updateWithRework(QualityUnqualifiedOrder order) {
|
boolean result = updateById(order);
|
if (result && order.getDisposalMethod() != null
|
&& (order.getDisposalMethod() == 2 || order.getDisposalMethod() == 3)) {
|
createReworkProductionOrder(order);
|
}
|
return result;
|
}
|
|
@Override
|
public void export(Long id, HttpServletResponse response) {
|
QualityUnqualifiedOrder order = getDetail(id);
|
if (order == null) {
|
throw new ServiceException("处理单不存在");
|
}
|
try (InputStream is = this.getClass().getResourceAsStream("/static/不合格品处理单.xls");
|
POIFSFileSystem fs = new POIFSFileSystem(is);
|
HSSFWorkbook wb = new HSSFWorkbook(fs)) {
|
Sheet sheet = wb.getSheetAt(0);
|
|
setCellValue(sheet, 2, 1, order.getProjectName());
|
setCellValue(sheet, 2, 5, order.getProjectNo());
|
setCellValue(sheet, 3, 1, order.getEquipmentName());
|
setCellValue(sheet, 3, 5, order.getEquipmentDrawingNo());
|
setCellValue(sheet, 4, 1, order.getMaterialName());
|
setCellValue(sheet, 4, 5, order.getMaterialDrawingNo());
|
setCellValue(sheet, 5, 1, order.getSpecificationModel());
|
setCellValue(sheet, 5, 3, order.getMaterialQuality());
|
setCellValue(sheet, 5, 5, order.getQuantity());
|
setCellValue(sheet, 5, 7, order.getUnqualifiedQuantity());
|
|
// 不合格工序 - 只替换对应的□为√
|
if (order.getUnqualifiedProcess() != null) {
|
String origin = "□来料 □制程 □成品";
|
int idx = order.getUnqualifiedProcess() - 1;
|
if (idx >= 0 && idx < 3) {
|
origin = origin.replaceFirst("□", "√");
|
if (idx >= 1) origin = origin.replaceFirst("□", idx == 1 ? "√" : "□");
|
if (idx >= 2) origin = origin.replaceFirst("□", "√");
|
}
|
// 按索引依次替换
|
StringBuilder sb = new StringBuilder();
|
int found = 0;
|
for (char c : "□来料 □制程 □成品".toCharArray()) {
|
if (c == '□') {
|
sb.append(found == idx ? '☑' : '□');
|
found++;
|
} else {
|
sb.append(c);
|
}
|
}
|
setCellValue(sheet, 6, 1, sb.toString());
|
}
|
setCellValue(sheet, 6, 5, order.getSupplierName());
|
|
setCellValue(sheet, 7, 1, order.getInspectorName());
|
setCellValue(sheet, 7, 3, order.getInspectDate());
|
setCellValue(sheet, 7, 5, order.getResponsiblePerson());
|
setCellValue(sheet, 7, 7, order.getResponsibleDept());
|
|
setCellValue(sheet, 8, 1, order.getProblemDescription());
|
setCellValue(sheet, 9, 1, order.getReasonAnalysis());
|
setCellValue(sheet, 10, 1, order.getCorrectionAction());
|
|
// 处置方式 - 只替换对应的□为√
|
if (order.getDisposalMethod() != null) {
|
String template = "□让步接收 □厂内维修 □返厂维修 □换货 □退货 □报废";
|
int idx = order.getDisposalMethod() - 1;
|
StringBuilder sb = new StringBuilder();
|
int found = 0;
|
for (char c : template.toCharArray()) {
|
if (c == '□') {
|
sb.append(found == idx ? '☑' : '□');
|
found++;
|
} else {
|
sb.append(c);
|
}
|
}
|
setCellValue(sheet, 11, 1, sb.toString());
|
}
|
setCellValue(sheet, 12, 1, order.getRepairEvaluation());
|
setCellValue(sheet, 13, 1, order.getPreventiveAction());
|
setCellValue(sheet, 14, 1, order.getDeptOpinion());
|
setCellValue(sheet, 15, 1, order.getCompanyDecision());
|
setCellValue(sheet, 16, 1, order.getGeneralManagerOpinion());
|
|
response.setContentType("application/vnd.ms-excel");
|
String fileName = URLEncoder.encode("不合格品处理单_" + order.getOrderNo(), "UTF-8");
|
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
|
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xls");
|
OutputStream os = response.getOutputStream();
|
wb.write(os);
|
os.flush();
|
os.close();
|
} catch (Exception e) {
|
throw new RuntimeException("导出失败", e);
|
}
|
}
|
|
private void setCellValue(Sheet sheet, int rowIdx, int colIdx, Object value) {
|
if (value == null) return;
|
Row row = sheet.getRow(rowIdx);
|
if (row == null) row = sheet.createRow(rowIdx);
|
Cell cell = row.getCell(colIdx);
|
if (cell == null) cell = row.createCell(colIdx);
|
if (value instanceof Date) {
|
cell.setCellValue((Date) value);
|
} else if (value instanceof Number) {
|
cell.setCellValue(((Number) value).doubleValue());
|
} else {
|
cell.setCellValue(value.toString());
|
}
|
}
|
|
private void createReworkProductionOrder(QualityUnqualifiedOrder order) {
|
if (order.getUnqualifiedId() == null) {
|
return;
|
}
|
QualityUnqualified unqualified = qualityUnqualifiedMapper.selectById(order.getUnqualifiedId());
|
if (unqualified == null || unqualified.getInspectId() == null) {
|
return;
|
}
|
QualityInspect qualityInspect = qualityInspectService.getById(unqualified.getInspectId());
|
if (qualityInspect == null || qualityInspect.getProductMainId() == null) {
|
return;
|
}
|
ProductionProductMain sourceMain = productionProductMainMapper.selectById(qualityInspect.getProductMainId());
|
if (sourceMain == null || sourceMain.getProductionOperationTaskId() == null) {
|
return;
|
}
|
ProductionOperationTask sourceTask = productionOperationTaskMapper.selectById(sourceMain.getProductionOperationTaskId());
|
if (sourceTask == null) {
|
return;
|
}
|
ProductionOrder sourceOrder = productionOrderMapper.selectById(sourceTask.getProductionOrderId());
|
if (sourceOrder == null) {
|
return;
|
}
|
|
BigDecimal reworkQty = order.getUnqualifiedQuantity() != null ? order.getUnqualifiedQuantity()
|
: unqualified.getQuantity() != null ? unqualified.getQuantity() : BigDecimal.ONE;
|
|
ProductionOrder newOrder = new ProductionOrder();
|
BeanUtils.copyProperties(sourceOrder, newOrder);
|
newOrder.setId(null);
|
newOrder.setNpsNo(generateNextProductionOrderNo("FG"));
|
newOrder.setQuantity(reworkQty);
|
newOrder.setCompleteQuantity(BigDecimal.ZERO);
|
newOrder.setStartTime(null);
|
newOrder.setEndTime(null);
|
newOrder.setCreateTime(null);
|
newOrder.setUpdateTime(null);
|
newOrder.setDisposalMethod(order.getDisposalMethod());
|
productionOrderMapper.insert(newOrder);
|
|
Map<Long, Long> routingIdMap = new HashMap<>();
|
List<ProductionOrderRouting> sourceRoutings = productionOrderRoutingMapper.selectList(
|
Wrappers.<ProductionOrderRouting>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<ProductionOrderRoutingOperation> sourceOperations = productionOrderRoutingOperationMapper.selectList(
|
Wrappers.<ProductionOrderRoutingOperation>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.<ProductionOrder>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.<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);
|
}
|
}
|