feat(qms): 实现不合格品记录查询和统计功能

- 添加了不合格品记录的分页查询功能,包括按条件查询和日期范围查询
- 实现了不合格品的统计功能,包括总数、待评审数、已评审数等
- 优化了不合格品评审记录的生成逻辑
- 修复了一些代码格式和导入问题
master
zch 7 days ago
parent b16301a671
commit f73b17aeca

@ -9,6 +9,7 @@ import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.qms.domain.QcUnqualifiedReview;
import org.springframework.stereotype.Service;
import org.dromara.qms.domain.bo.QcUnqualifiedRecordBo;
import org.dromara.qms.domain.vo.QcUnqualifiedRecordVo;
@ -133,16 +134,35 @@ public class QcUnqualifiedRecordServiceImpl implements IQcUnqualifiedRecordServi
@Override
public TableDataInfo<QcUnqualifiedRecordVo> queryPageListWithDetails(QcUnqualifiedRecordBo bo, PageQuery pageQuery) {
return null;
MPJLambdaWrapper<QcUnqualifiedRecord> lqw = new MPJLambdaWrapper<>();
lqw.selectAll(QcUnqualifiedRecord.class)
.leftJoin(QcUnqualifiedReview.class, QcUnqualifiedReview::getReviewId, QcUnqualifiedRecord::getReviewId)
.select(QcUnqualifiedReview::getUnqualifiedNo, QcUnqualifiedReview::getReviewResult)
// 添加更多关联如果需要
.eq(bo.getRecordId() != null, QcUnqualifiedRecord::getRecordId, bo.getRecordId())
.eq(bo.getReviewId() != null, QcUnqualifiedRecord::getReviewId, bo.getReviewId())
.orderByDesc(QcUnqualifiedRecord::getCreateTime);
Page<QcUnqualifiedRecordVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@Override
public TableDataInfo<QcUnqualifiedRecordVo> queryPageUserRecords(String reviewer, PageQuery pageQuery) {
return null;
QcUnqualifiedRecordBo bo = new QcUnqualifiedRecordBo();
// 假设QcUnqualifiedRecord有reviewer字段否则需关联
// bo.setReviewer(reviewer);
return queryPageListWithDetails(bo, pageQuery); // 或自定义
}
@Override
public TableDataInfo<QcUnqualifiedRecordVo> queryPageRecordsByDateRange(QcUnqualifiedRecordBo bo, PageQuery pageQuery) {
return null;
MPJLambdaWrapper<QcUnqualifiedRecord> lqw = buildQueryWrapper(bo);
Map<String, Object> params = bo.getParams();
if (params != null) {
lqw.ge(params.get("beginTime") != null, QcUnqualifiedRecord::getCreateTime, params.get("beginTime"))
.le(params.get("endTime") != null, QcUnqualifiedRecord::getCreateTime, params.get("endTime"));
}
Page<QcUnqualifiedRecordVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
}

@ -14,6 +14,7 @@ import org.dromara.qms.domain.QcInspectionMain;
import org.dromara.qms.domain.QcInspectionType;
import org.dromara.qms.domain.bo.QcInspectionMainBo;
import org.dromara.qms.domain.bo.QcInspectionResultBo;
import org.dromara.qms.domain.vo.QcInspectionMainVo;
import org.dromara.qms.domain.vo.QcInspectionResultVo;
import org.dromara.qms.service.IQcInspectionResultService;
import org.springframework.stereotype.Service;
@ -108,12 +109,12 @@ public class QcUnqualifiedReviewServiceImpl implements IQcUnqualifiedReviewServi
}
// 强制设置reviewResult为null查询待评审记录
pendingBo.setReviewResult(null);
MPJLambdaWrapper<QcUnqualifiedReview> lqw = buildQueryWrapper(pendingBo);
// 添加条件reviewResult为空或null
lqw.and(wrapper -> wrapper.isNull(QcUnqualifiedReview::getReviewResult)
.or().eq(QcUnqualifiedReview::getReviewResult, ""));
Page<QcUnqualifiedReviewVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
@ -133,7 +134,7 @@ public class QcUnqualifiedReviewServiceImpl implements IQcUnqualifiedReviewServi
QcInspectionResultBo resultBo = new QcInspectionResultBo();
resultBo.setInspectionId(reviewVo.getInspectionId());
List<QcInspectionResultVo> inspectionResults = qcInspectionResultService.queryList(resultBo);
// 可以将检测项结果添加到reviewVo中但由于QcUnqualifiedReviewVo没有相应字段
// 这里暂时通过日志记录或者扩展VO类来处理
// 实际项目中可能需要扩展QcUnqualifiedReviewVo类添加inspectionResults字段
@ -152,15 +153,15 @@ public class QcUnqualifiedReviewServiceImpl implements IQcUnqualifiedReviewServi
public Boolean submitReview(QcUnqualifiedReviewBo bo) {
// 设置评审时间
bo.setReviewTime(new Date());
// 更新评审结果
Boolean updated = updateByBo(bo);
if (updated) {
// 根据评审结果触发后续流程
triggerWorkflowProcess(bo);
}
return updated;
}
@ -173,7 +174,7 @@ public class QcUnqualifiedReviewServiceImpl implements IQcUnqualifiedReviewServi
@Override
public Map<String, Object> getUnqualifiedSummary(String dateRange) {
Map<String, Object> summary = new HashMap<>();
// 解析日期范围
LocalDate startDate = null;
LocalDate endDate = null;
@ -194,30 +195,30 @@ public class QcUnqualifiedReviewServiceImpl implements IQcUnqualifiedReviewServi
startDate = LocalDate.now().withDayOfMonth(1);
endDate = LocalDate.now();
}
// 构建查询条件
QcUnqualifiedReviewBo bo = new QcUnqualifiedReviewBo();
Map<String, Object> params = new HashMap<>();
params.put("beginTime", startDate.toString());
params.put("endTime", endDate.toString());
bo.setParams(params);
// 查询所有不合格品记录
List<QcUnqualifiedReviewVo> allRecords = queryList(bo);
// 统计总数
summary.put("totalCount", allRecords.size());
// 统计待评审数量
long pendingCount = allRecords.stream()
.filter(record -> StringUtils.isBlank(record.getReviewResult()))
.count();
summary.put("pendingCount", pendingCount);
// 统计已评审数量
long reviewedCount = allRecords.size() - pendingCount;
summary.put("reviewedCount", reviewedCount);
// 按评审结果分组统计
Map<String, Long> reviewResultStats = allRecords.stream()
.filter(record -> StringUtils.isNotBlank(record.getReviewResult()))
@ -225,13 +226,13 @@ public class QcUnqualifiedReviewServiceImpl implements IQcUnqualifiedReviewServi
QcUnqualifiedReviewVo::getReviewResult,
Collectors.counting()
));
summary.put("scrapCount", reviewResultStats.getOrDefault("0", 0L)); // 报废
summary.put("reworkCount", reviewResultStats.getOrDefault("1", 0L)); // 返工
summary.put("returnCount", reviewResultStats.getOrDefault("2", 0L)); // 退货
summary.put("acceptCount", reviewResultStats.getOrDefault("3", 0L)); // 让步接收
summary.put("transferCount", reviewResultStats.getOrDefault("4", 0L)); // 流转
// 按物料分组统计
Map<String, Long> materialStats = allRecords.stream()
.filter(record -> StringUtils.isNotBlank(record.getMaterialName()))
@ -240,7 +241,7 @@ public class QcUnqualifiedReviewServiceImpl implements IQcUnqualifiedReviewServi
Collectors.counting()
));
summary.put("materialStats", materialStats);
// 按工序分组统计
Map<String, Long> processStats = allRecords.stream()
.filter(record -> StringUtils.isNotBlank(record.getProcessName()))
@ -249,7 +250,7 @@ public class QcUnqualifiedReviewServiceImpl implements IQcUnqualifiedReviewServi
Collectors.counting()
));
summary.put("processStats", processStats);
return summary;
}
@ -266,10 +267,10 @@ public class QcUnqualifiedReviewServiceImpl implements IQcUnqualifiedReviewServi
log.error("评审结果为空,无法触发工作流程");
return false;
}
try {
log.info("开始触发工作流程: 评审ID={}, 评审结果={}", bo.getReviewId(), bo.getReviewResult());
// 根据评审结果触发不同的后续流程
switch (bo.getReviewResult()) {
case "0": // 报废
@ -299,19 +300,19 @@ public class QcUnqualifiedReviewServiceImpl implements IQcUnqualifiedReviewServi
private Boolean handleScrapProcess(QcUnqualifiedReviewBo bo) {
try {
log.info("执行报废流程: 评审ID={}", bo.getReviewId());
// 1. 更新库存状态为报废
updateInventoryStatus(bo, "SCRAPPED");
// 2. 生成报废单据
generateScrapDocument(bo);
// 3. 更新质检主表状态
updateInspectionMainStatus(bo, "SCRAPPED");
// 4. 记录处理日志
recordProcessLog(bo, "报废流程执行完成");
log.info("报废流程执行成功: 评审ID={}", bo.getReviewId());
return true;
} catch (Exception e) {
@ -327,22 +328,22 @@ public class QcUnqualifiedReviewServiceImpl implements IQcUnqualifiedReviewServi
private Boolean handleReworkProcess(QcUnqualifiedReviewBo bo) {
try {
log.info("执行返工流程: 评审ID={}", bo.getReviewId());
// 1. 生成返工工单
generateReworkOrder(bo);
// 2. 分派返工任务给相关人员
assignReworkTask(bo);
// 3. 更新质检主表状态为返工中
updateInspectionMainStatus(bo, "REWORKING");
// 4. 更新库存状态
updateInventoryStatus(bo, "REWORKING");
// 5. 记录处理日志
recordProcessLog(bo, "返工流程执行完成,已生成返工工单");
log.info("返工流程执行成功: 评审ID={}", bo.getReviewId());
return true;
} catch (Exception e) {
@ -358,22 +359,22 @@ public class QcUnqualifiedReviewServiceImpl implements IQcUnqualifiedReviewServi
private Boolean handleReturnProcess(QcUnqualifiedReviewBo bo) {
try {
log.info("执行退货流程: 评审ID={}", bo.getReviewId());
// 1. 生成退货单据
generateReturnDocument(bo);
// 2. 通知供应商
notifySupplier(bo);
// 3. 更新库存状态为待退货
updateInventoryStatus(bo, "RETURNING");
// 4. 更新质检主表状态
updateInspectionMainStatus(bo, "RETURNED");
// 5. 记录处理日志
recordProcessLog(bo, "退货流程执行完成,已通知供应商");
log.info("退货流程执行成功: 评审ID={}", bo.getReviewId());
return true;
} catch (Exception e) {
@ -389,22 +390,22 @@ public class QcUnqualifiedReviewServiceImpl implements IQcUnqualifiedReviewServi
private Boolean handleAcceptProcess(QcUnqualifiedReviewBo bo) {
try {
log.info("执行让步接收流程: 评审ID={}", bo.getReviewId());
// 1. 更新质检状态为让步合格
updateInspectionMainStatus(bo, "CONDITIONALLY_ACCEPTED");
// 2. 更新库存状态为可用
updateInventoryStatus(bo, "AVAILABLE");
// 3. 生成让步接收单据
generateAcceptanceDocument(bo);
// 4. 触发入库流程
triggerInboundProcess(bo);
// 5. 记录处理日志
recordProcessLog(bo, "让步接收流程执行完成,产品已入库");
log.info("让步接收流程执行成功: 评审ID={}", bo.getReviewId());
return true;
} catch (Exception e) {
@ -420,25 +421,25 @@ public class QcUnqualifiedReviewServiceImpl implements IQcUnqualifiedReviewServi
private Boolean handleTransferProcess(QcUnqualifiedReviewBo bo) {
try {
log.info("执行流转流程: 评审ID={}", bo.getReviewId());
// 1. 确定流转目标部门或工序
String transferTarget = determineTransferTarget(bo);
// 2. 生成流转单据
generateTransferDocument(bo, transferTarget);
// 3. 通知目标部门
notifyTargetDepartment(bo, transferTarget);
// 4. 更新质检主表状态
updateInspectionMainStatus(bo, "TRANSFERRED");
// 5. 更新库存状态
updateInventoryStatus(bo, "TRANSFERRED");
// 6. 记录处理日志
recordProcessLog(bo, "流转流程执行完成,已转移至: " + transferTarget);
log.info("流转流程执行成功: 评审ID={}, 流转目标={}", bo.getReviewId(), transferTarget);
return true;
} catch (Exception e) {
@ -619,7 +620,7 @@ public class QcUnqualifiedReviewServiceImpl implements IQcUnqualifiedReviewServi
.leftJoin(QcInspectionMain.class, QcInspectionMain::getInspectionId, QcUnqualifiedReview::getInspectionId)
//关联检测类型
.select(QcInspectionType::getTypeName, QcInspectionType::getQcInspectionType, QcInspectionType::getTypeCode, QcInspectionType::getQcInspectionType)
.leftJoin(QcInspectionType.class, QcInspectionType::getTypeId, QcInspectionMain::getTypeId)
.leftJoin(QcInspectionType.class, QcInspectionType::getTypeId, QcUnqualifiedReview::getTypeId)
.eq(bo.getReviewId() != null, QcUnqualifiedReview::getReviewId, bo.getReviewId())
.eq(StringUtils.isNotBlank(bo.getUnqualifiedNo()), QcUnqualifiedReview::getUnqualifiedNo, bo.getUnqualifiedNo())
@ -690,4 +691,57 @@ public class QcUnqualifiedReviewServiceImpl implements IQcUnqualifiedReviewServi
}
return baseMapper.deleteByIds(ids) > 0;
}
@Override
public Boolean autoGenerateUnqualifiedReview(QcInspectionMainVo inspectionVo, List<QcInspectionResultVo> inspectionResults) {
// 检查是否有不合格项
boolean hasUnqualified = inspectionResults.stream()
.anyMatch(result -> Long.valueOf(1).equals(result.getDetectResult()));
if (!hasUnqualified) {
log.info("无不合格项,无需生成评审记录: inspectionId={}", inspectionVo.getInspectionId());
return false;
}
QcUnqualifiedReviewBo bo = new QcUnqualifiedReviewBo();
bo.setInspectionId(inspectionVo.getInspectionId());
// bo.setTypeId(inspectionVo.getTypeId());
bo.setMaterialCode(inspectionVo.getMaterialCode());
bo.setMaterialName(inspectionVo.getMaterialName());
bo.setProcessName(inspectionVo.getProcessName());
bo.setWorkOrder(inspectionVo.getProductionOrder());
bo.setBatchNo(inspectionVo.getBatchNo());
bo.setInspectorResult(inspectionVo.getResult().toString());
// 生成唯一的不合格编号
String unqualifiedNo = generateUnqualifiedNo();
bo.setUnqualifiedNo(unqualifiedNo);
// 设置默认值
bo.setReviewResult(null); // 待评审
Boolean inserted = insertByBo(bo);
if (inserted) {
log.info("不合格品评审记录生成成功: reviewId={}, unqualifiedNo={}", bo.getReviewId(), unqualifiedNo);
} else {
log.error("不合格品评审记录生成失败: inspectionId={}", inspectionVo.getInspectionId());
}
return inserted;
}
/**
*
* : UNQ-yyyyMMdd-XXXX (XXXX4)
*/
private String generateUnqualifiedNo() {
LocalDate today = LocalDate.now();
String prefix = "UNQ-" + today.format(DateTimeFormatter.ofPattern("yyyyMMdd")) + "-";
// 查询当天已生成的记录数
long count = baseMapper.selectCount(Wrappers.<QcUnqualifiedReview>lambdaQuery()
.likeRight(QcUnqualifiedReview::getUnqualifiedNo, prefix));
// 生成序列号
String seq = String.format("%04d", count + 1);
return prefix + seq;
}
}

Loading…
Cancel
Save