PQC和PDI不良品列表查询修改

PQC上传校验修改
This commit is contained in:
yf001217 2026-06-03 10:06:23 +08:00
parent 73e65add54
commit c354a94d9f
8 changed files with 152 additions and 177 deletions

View File

@ -105,7 +105,7 @@ public class QmsPqcTaskRecordController {
QmsPqcTaskRecordControllerService.SubmitResult result = pqcTaskRecordService.submit(request);
if (result.getType() == 1) {
throw new NflgException(STATE.BusinessError, "有未填写的检项");
throw new NflgException(STATE.BusinessError, "有未填写的");
} else if (result.getType() == 2) {
return ApiResult.success(result.getUnqualifiedItems());
} else {

View File

@ -1,39 +0,0 @@
package com.nflg.qms.admin.event;
import org.springframework.context.ApplicationEvent;
/**
* PQC不合格任务提交成功事件
*/
public class PqcUnqualifiedTaskSubmittedEvent extends ApplicationEvent {
private final Long taskId;
private final Long currentUserId;
private final String currentUserName;
private final String traceId;
public PqcUnqualifiedTaskSubmittedEvent(Object source, Long taskId, Long currentUserId,
String currentUserName, String traceId) {
super(source);
this.taskId = taskId;
this.currentUserId = currentUserId;
this.currentUserName = currentUserName;
this.traceId = traceId;
}
public Long getTaskId() {
return taskId;
}
public Long getCurrentUserId() {
return currentUserId;
}
public String getCurrentUserName() {
return currentUserName;
}
public String getTraceId() {
return traceId;
}
}

View File

@ -1,29 +0,0 @@
package com.nflg.qms.admin.listener;
import com.nflg.qms.admin.event.PqcUnqualifiedTaskSubmittedEvent;
import com.nflg.qms.admin.service.QmsPqcTaskRecordControllerService;
import jakarta.annotation.Resource;
import org.slf4j.MDC;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionalEventListener;
import org.springframework.transaction.event.TransactionPhase;
@Component
public class PqcUnqualifiedTaskEventListener {
@Resource
private QmsPqcTaskRecordControllerService pqcTaskRecordService;
@Async("ticketTaskExecutor")
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handle(PqcUnqualifiedTaskSubmittedEvent event) {
MDC.put("traceId", event.getTraceId());
try {
pqcTaskRecordService.generateUnqualifiedTicketAsync(
event.getTaskId(), event.getCurrentUserId(), event.getCurrentUserName());
} finally {
MDC.clear();
}
}
}

View File

@ -1,20 +0,0 @@
package com.nflg.qms.admin.publisher;
import com.nflg.qms.admin.event.PqcUnqualifiedTaskSubmittedEvent;
import com.nflg.wms.common.constant.Constant;
import jakarta.annotation.Resource;
import org.slf4j.MDC;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
@Service
public class PqcUnqualifiedTaskEventPublisher {
@Resource
private ApplicationEventPublisher eventPublisher;
public void publish(Long taskId, Long currentUserId, String currentUserName) {
eventPublisher.publishEvent(new PqcUnqualifiedTaskSubmittedEvent(
this, taskId, currentUserId, currentUserName, MDC.get(Constant.TRACE_ID)));
}
}

View File

@ -11,7 +11,6 @@ import com.nflg.wms.repository.entity.*;
import com.nflg.wms.repository.service.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -92,9 +91,9 @@ public class QmsIssueTicketProcessControllerService {
}
/**
* 步新增工单处理并推送待办供内部服务调用
* 步新增工单处理并推送待办供内部服务调用
*/
@Async("ticketTaskExecutor")
@Transactional(rollbackFor = Exception.class)
public void addAsync(Long issueTicketId, Long handlerUserId, List<Long> taskResultIds, String ticketNo) {
Long processId = doAdd(issueTicketId, handlerUserId, taskResultIds);

View File

@ -70,9 +70,6 @@ public class QmsPqcTaskRecordControllerService {
@Resource
private IDictionaryItemService dictionaryItemService;
@Resource
private com.nflg.qms.admin.publisher.PqcUnqualifiedTaskEventPublisher pqcUnqualifiedTaskEventPublisher;
/**
* 1. 新增PQC任务仅Service层供暂存/提交调用
*/
@ -119,19 +116,22 @@ public class QmsPqcTaskRecordControllerService {
details.add(new QmsPqcTaskRecordDetails()
.setTaskId(taskRecord.getId())
.setInspectionPointItemId(item.getId())
.setType((short) 0));
.setType((short) 0)
.setSelfCheck(false));
// 类型1关键物料拍照
details.add(new QmsPqcTaskRecordDetails()
.setTaskId(taskRecord.getId())
.setInspectionPointItemId(item.getId())
.setType((short) 1));
.setType((short) 1)
.setSelfCheck(false));
} else {
// 其他类型直接创建
details.add(new QmsPqcTaskRecordDetails()
.setTaskId(taskRecord.getId())
.setInspectionPointItemId(item.getId())
.setType(item.getInspectionType() != null ? item.getInspectionType().shortValue() : null));
.setType(item.getInspectionType() != null ? item.getInspectionType().shortValue() : null)
.setSelfCheck(false));
}
}
@ -148,8 +148,6 @@ public class QmsPqcTaskRecordControllerService {
public PageData<QmsPqcTaskRecordPageVO> searchPqcTaskList(QmsPqcTaskRecordSearchQO request) {
LambdaQueryWrapper<QmsPqcTaskRecord> queryWrapper = new LambdaQueryWrapper<>();
Set<Long> unqualifiedTaskIds = getUnqualifiedTaskIds();
if (StrUtil.isNotBlank(request.getTaskNo())) {
queryWrapper.eq(QmsPqcTaskRecord::getTaskNo, request.getTaskNo());
}
@ -175,9 +173,6 @@ public class QmsPqcTaskRecordControllerService {
queryWrapper.and(wrapper -> wrapper.isNull(QmsPqcTaskRecord::getEnable)
.or()
.eq(QmsPqcTaskRecord::getEnable, true));
if (!unqualifiedTaskIds.isEmpty()) {
queryWrapper.notIn(QmsPqcTaskRecord::getId, unqualifiedTaskIds);
}
queryWrapper.orderByDesc(QmsPqcTaskRecord::getCreateTime);
return buildPqcTaskPageData(request.getPage(), request.getPageSize(), queryWrapper);
@ -186,7 +181,6 @@ public class QmsPqcTaskRecordControllerService {
public PageData<QmsPqcTaskRecordPageVO> searchPqcTaskUnqualifiedList(QmsPqcTaskRecordUnqualifiedSearchQO request) {
LambdaQueryWrapper<QmsPqcTaskRecord> queryWrapper = new LambdaQueryWrapper<>();
Set<Long> unqualifiedTaskIds = getUnqualifiedTaskIds();
Set<Long> pointIdsByKeyword = findInspectionPointIdsByKeyword(request.getInspectionPointKeyword());
if (StrUtil.isNotBlank(request.getTaskNo())) {
@ -209,12 +203,7 @@ public class QmsPqcTaskRecordControllerService {
}
}
queryWrapper.and(wrapper -> {
wrapper.eq(QmsPqcTaskRecord::getEnable, false);
if (!unqualifiedTaskIds.isEmpty()) {
wrapper.or().in(QmsPqcTaskRecord::getId, unqualifiedTaskIds);
}
});
queryWrapper.eq(QmsPqcTaskRecord::getEnable, false);
queryWrapper.orderByDesc(QmsPqcTaskRecord::getCreateTime);
return buildPqcTaskPageData(request.getPage(), request.getPageSize(), queryWrapper);
@ -319,17 +308,6 @@ public class QmsPqcTaskRecordControllerService {
return pageData;
}
private Set<Long> getUnqualifiedTaskIds() {
return pqcTaskRecordDetailsService.lambdaQuery()
.eq(QmsPqcTaskRecordDetails::getReviewEnable, false)
.select(QmsPqcTaskRecordDetails::getTaskId)
.list()
.stream()
.map(QmsPqcTaskRecordDetails::getTaskId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
}
private Set<Long> findInspectionPointIdsByKeyword(String inspectionPointKeyword) {
if (StrUtil.isBlank(inspectionPointKeyword)) {
return Collections.emptySet();
@ -685,9 +663,12 @@ public class QmsPqcTaskRecordControllerService {
processVO.setInspectionMethods(item.getInspectionMethods());
processVO.setInspectionLevel(item.getInspectionLevel());
processVO.setInspectionExampleImage(item.getInspectionImgUrl());
processVO.setQcTestData(detail.getQcTestData());
processVO.setQcTestData(StrUtil.isNotBlank(detail.getReviewData()) ? detail.getReviewData() : detail.getQcTestData());
processVO.setEnable(detail.getReviewEnable());
processVO.setQcTestFiles(convertToFileVO(parseFileList(detail.getQcTestAttachments()),
processVO.setQcTestFiles(convertToFileVO(parseFileList(
StrUtil.isNotBlank(detail.getReviewAttachments())
? detail.getReviewAttachments()
: detail.getQcTestAttachments()),
QmsPqcTaskRecordReviewVO.FileDetailVO.class));
processInspectionsLevel3.add(processVO);
}
@ -917,7 +898,7 @@ public class QmsPqcTaskRecordControllerService {
pqcTaskRecordService.updateById(taskRecord);
// 5. 保存详情数据
saveTaskDetails(taskRecord.getId(), request);
saveTaskDetails(taskRecord.getId(), request, hasReviewContent);
}
/**
@ -949,16 +930,16 @@ public class QmsPqcTaskRecordControllerService {
}
// 2. 校验数据完整性
List<String> emptyFields = validateData(request);
boolean isSelfTestSubmit = emptyFields.stream().allMatch(field -> field.contains("review"));
boolean hasReviewContent = hasReviewContent(request);
List<String> emptyFields = validateData(taskRecord.getId(), request, hasReviewContent);
if (!emptyFields.isEmpty() && !isSelfTestSubmit) {
if (!emptyFields.isEmpty()) {
// 情况1有数据为空且不是自检提交返回空值明细
return SubmitResult.emptyFields(emptyFields);
}
// 3. 保存详情数据
saveTaskDetails(taskRecord.getId(), request);
saveTaskDetails(taskRecord.getId(), request, hasReviewContent);
// 4. 更新任务状态
taskRecord.setCompleteTime(now);
@ -967,7 +948,6 @@ public class QmsPqcTaskRecordControllerService {
}
// 设置自检人/复核人
boolean hasReviewContent = hasReviewContent(request);
if (!hasReviewContent) {
if (taskRecord.getSelfTesterId() == null) {
taskRecord.setSelfTesterId(currentUserId);
@ -992,10 +972,11 @@ public class QmsPqcTaskRecordControllerService {
sendTodoMessageToAllQC(taskRecord.getId(), currentUserId, currentUserName, now);
}
// 6. 检查不合格项生成工单和新任务
if (request.getEnable() != null && !request.getEnable()) {
pqcUnqualifiedTaskEventPublisher.publish(taskRecord.getId(), currentUserId, currentUserName);
return SubmitResult.unqualified(buildUnqualifiedItems(request));
// 6. 同步生成工单仅当任务总体不合格时才额外生成重检任务
List<QmsPqcUnqualifiedItemVO> unqualifiedItems = buildUnqualifiedItems(request);
if (!unqualifiedItems.isEmpty()) {
handleUnqualifiedTask(taskRecord, currentUserId, currentUserName, now);
return SubmitResult.unqualified(unqualifiedItems);
}
return SubmitResult.success();
@ -1009,7 +990,17 @@ public class QmsPqcTaskRecordControllerService {
for (QmsPqcTaskRecordDraftQO.ProcessInspectionItem item : request.getProcessInspections()) {
if (StrUtil.isNotBlank(item.getReviewData())
|| item.getReviewFiles() != null && !item.getReviewFiles().isEmpty()
|| StrUtil.isNotBlank(item.getReviewOpinion())) {
|| StrUtil.isNotBlank(item.getReviewOpinion())
|| item.getEnable() != null) {
return true;
}
}
}
if (request.getProcessInspectionsLevel3() != null) {
for (QmsPqcTaskRecordDraftQO.ProcessInspectionLevel3Item item : request.getProcessInspectionsLevel3()) {
if (StrUtil.isNotBlank(item.getQcTestData())
|| item.getQcTestFiles() != null && !item.getQcTestFiles().isEmpty()
|| item.getEnable() != null) {
return true;
}
}
@ -1060,10 +1051,91 @@ public class QmsPqcTaskRecordControllerService {
return emptyFields;
}
private List<String> validateData(Long taskId, QmsPqcTaskRecordDraftQO request, boolean hasReviewContent) {
List<QmsPqcTaskRecordDetails> details = pqcTaskRecordDetailsService.lambdaQuery()
.eq(QmsPqcTaskRecordDetails::getTaskId, taskId)
.list();
List<QmsPqcTaskRecordDetails> type0Details = details.stream()
.filter(d -> d.getType() != null && d.getType() == 0)
.collect(Collectors.toList());
Set<Long> itemIds = type0Details.stream()
.map(QmsPqcTaskRecordDetails::getInspectionPointItemId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
Map<Long, QmsPqcInspectionPointItems> itemMap = itemIds.isEmpty()
? new HashMap<>()
: pqcInspectionPointItemsService.listByIds(itemIds).stream()
.collect(Collectors.toMap(QmsPqcInspectionPointItems::getId, item -> item, (a, b) -> a));
List<String> emptyFields = new ArrayList<>();
if (hasReviewContent) {
validateReviewData(request, type0Details, itemMap, emptyFields);
} else {
validateSelfTestData(request, type0Details, itemMap, emptyFields);
}
return emptyFields;
}
private void validateSelfTestData(QmsPqcTaskRecordDraftQO request,
List<QmsPqcTaskRecordDetails> type0Details,
Map<Long, QmsPqcInspectionPointItems> itemMap,
List<String> emptyFields) {
if (request.getMaterialCollections() != null) {
for (int i = 0; i < request.getMaterialCollections().size(); i++) {
QmsPqcTaskRecordDraftQO.MaterialCollectionItem item = request.getMaterialCollections().get(i);
if (item.getFiles() == null || item.getFiles().isEmpty()) {
emptyFields.add("materialCollections[" + i + "].files");
}
}
}
if (request.getProcessInspections() == null) {
return;
}
for (int i = 0; i < request.getProcessInspections().size() && i < type0Details.size(); i++) {
QmsPqcTaskRecordDraftQO.ProcessInspectionItem item = request.getProcessInspections().get(i);
QmsPqcTaskRecordDetails detail = type0Details.get(i);
QmsPqcInspectionPointItems pointItem = itemMap.get(detail.getInspectionPointItemId());
if (pointItem == null || !Boolean.TRUE.equals(detail.getSelfCheck())) {
continue;
}
if (Objects.equals(pointItem.getInspectionMethods(), 2) && StrUtil.isBlank(item.getSelfTestData())) {
emptyFields.add("processInspections[" + i + "].selfTestData");
}
}
}
private void validateReviewData(QmsPqcTaskRecordDraftQO request,
List<QmsPqcTaskRecordDetails> type0Details,
Map<Long, QmsPqcInspectionPointItems> itemMap,
List<String> emptyFields) {
if (request.getProcessInspections() != null) {
for (int i = 0; i < request.getProcessInspections().size() && i < type0Details.size(); i++) {
QmsPqcTaskRecordDraftQO.ProcessInspectionItem item = request.getProcessInspections().get(i);
QmsPqcTaskRecordDetails detail = type0Details.get(i);
QmsPqcInspectionPointItems pointItem = itemMap.get(detail.getInspectionPointItemId());
if (item.getEnable() == null) {
emptyFields.add("processInspections[" + i + "].enable");
continue;
}
if (pointItem != null && Objects.equals(pointItem.getInspectionMethods(), 2)
&& StrUtil.isBlank(item.getReviewData())) {
emptyFields.add("processInspections[" + i + "].reviewData");
}
}
}
if (request.getProcessInspectionsLevel3() != null) {
for (int i = 0; i < request.getProcessInspectionsLevel3().size(); i++) {
QmsPqcTaskRecordDraftQO.ProcessInspectionLevel3Item item = request.getProcessInspectionsLevel3().get(i);
if (item.getEnable() == null) {
emptyFields.add("processInspectionsLevel3[" + i + "].enable");
}
}
}
}
/**
* 保存任务详情
*/
private void saveTaskDetails(Long taskId, QmsPqcTaskRecordDraftQO request) {
private void saveTaskDetails(Long taskId, QmsPqcTaskRecordDraftQO request, boolean hasReviewContent) {
LocalDateTime now = LocalDateTime.now();
// 删除前先记录旧详情的 inspectionPointItemId type 分组
@ -1097,6 +1169,7 @@ public class QmsPqcTaskRecordControllerService {
.setType((short) 1)
.setInspectionPointItemId(i < type1ItemIds.size() ? type1ItemIds.get(i) : null)
.setSelfTestData(item.getSerialNo())
.setSelfCheck(item.getFiles() != null && !item.getFiles().isEmpty())
.setReviewData(item.getBatchNo())
.setSelfTestAttachments(serializeFileList(item.getFiles()))
.setSelfTestUploadTime(now);
@ -1113,6 +1186,8 @@ public class QmsPqcTaskRecordControllerService {
.setType((short) 0)
.setInspectionPointItemId(i < type0ItemIds.size() ? type0ItemIds.get(i) : null)
.setSelfTestData(item.getSelfTestData())
.setSelfCheck(StrUtil.isNotBlank(item.getSelfTestData())
|| (item.getSelfTestFiles() != null && !item.getSelfTestFiles().isEmpty()))
.setReviewData(item.getReviewData())
.setReviewEnable(item.getEnable())
.setSelfTestAttachments(serializeFileList(item.getSelfTestFiles()))
@ -1134,10 +1209,20 @@ public class QmsPqcTaskRecordControllerService {
.setTaskId(taskId)
.setType((short) 0)
.setInspectionPointItemId(idx < type0ItemIds.size() ? type0ItemIds.get(idx) : null)
.setQcTestData(item.getQcTestData())
.setReviewEnable(item.getEnable())
.setQcTestAttachments(serializeFileList(item.getQcTestFiles()))
.setSelfTestUploadTime(now);
.setSelfCheck(false)
.setReviewEnable(item.getEnable());
if (hasReviewContent) {
detail.setReviewData(item.getQcTestData())
.setReviewAttachments(serializeFileList(item.getQcTestFiles()))
.setReviewUploadTime(item.getEnable() != null
|| StrUtil.isNotBlank(item.getQcTestData())
|| item.getQcTestFiles() != null && !item.getQcTestFiles().isEmpty()
? now : null);
} else {
detail.setQcTestData(item.getQcTestData())
.setQcTestAttachments(serializeFileList(item.getQcTestFiles()))
.setSelfTestUploadTime(now);
}
pqcTaskRecordDetailsService.save(detail);
}
}
@ -1155,19 +1240,6 @@ public class QmsPqcTaskRecordControllerService {
.collect(Collectors.joining(","));
}
/**
* 处理不合格任务生成工单
* @return 生成的工单编号
*/
@Transactional(rollbackFor = Exception.class)
public void generateUnqualifiedTicketAsync(Long taskRecordId, Long currentUserId, String currentUserName) {
QmsPqcTaskRecord taskRecord = pqcTaskRecordService.getById(taskRecordId);
if (taskRecord == null) {
return;
}
handleUnqualifiedTask(taskRecord, currentUserId, currentUserName, LocalDateTime.now());
}
private List<QmsPqcUnqualifiedItemVO> buildUnqualifiedItems(QmsPqcTaskRecordDraftQO request) {
List<QmsPqcUnqualifiedItemVO> items = new ArrayList<>();
if (request.getProcessInspections() != null) {
@ -1251,7 +1323,12 @@ public class QmsPqcTaskRecordControllerService {
issueTicketService.save(ticket);
// 2. 创建返修任务
// 2. 任务总体合格时仅生成工单不创建重检任务
if (!Boolean.FALSE.equals(taskRecord.getEnable())) {
return ticketNo;
}
// 3. 创建返修任务
String repairTaskNo = basdeSerialNumberControllerService.generateSerialNumber(42);
QmsPqcTaskRecord repairTask = new QmsPqcTaskRecord()
.setTaskNo(repairTaskNo)
@ -1265,7 +1342,7 @@ public class QmsPqcTaskRecordControllerService {
.setCreateTime(now);
pqcTaskRecordService.save(repairTask);
// 3. 复制详情记录合格项保留全部数据不合格项清空自检/QC数据附件及复核意见
// 4. 复制详情记录合格项保留全部数据不合格项清空自检/QC数据附件及复核意见
List<QmsPqcTaskRecordDetails> oldDetails = pqcTaskRecordDetailsService.lambdaQuery()
.eq(QmsPqcTaskRecordDetails::getTaskId, taskRecord.getId())
.list();
@ -1275,11 +1352,13 @@ public class QmsPqcTaskRecordControllerService {
QmsPqcTaskRecordDetails newDetail = new QmsPqcTaskRecordDetails()
.setTaskId(repairTask.getId())
.setInspectionPointItemId(old.getInspectionPointItemId())
.setType(old.getType());
.setType(old.getType())
.setSelfCheck(false);
if (old.getType() != null && old.getType() == 1) {
// 关键物料采集全部复制
newDetail.setSelfTestData(old.getSelfTestData())
.setSelfCheck(old.getSelfCheck())
.setReviewData(old.getReviewData())
.setSelfTestAttachments(old.getSelfTestAttachments());
} else {
@ -1287,6 +1366,7 @@ public class QmsPqcTaskRecordControllerService {
if (Boolean.TRUE.equals(old.getReviewEnable())) {
// 合格项保留全部数据
newDetail.setSelfTestData(old.getSelfTestData())
.setSelfCheck(old.getSelfCheck())
.setReviewData(old.getReviewData())
.setReviewEnable(old.getReviewEnable())
.setSelfTestAttachments(old.getSelfTestAttachments())
@ -1304,7 +1384,7 @@ public class QmsPqcTaskRecordControllerService {
pqcTaskRecordDetailsService.saveBatch(newDetails);
}
// 4. 推送通知原自检人重新自检
// 5. 推送通知原自检人重新自检
if (taskRecord.getSelfTesterId() != null) {
Long repairTypeId = dictionaryItemService.getId("消息类型", "PQCRepairTask");
if (repairTypeId != null) {

View File

@ -48,6 +48,8 @@ public class QmsPqcTaskRecordDetails implements Serializable {
*/
private String selfTestData;
private Boolean selfCheck;
/**
* 自检提交时间
*/

View File

@ -58,18 +58,8 @@
)
<!-- 合格物料过滤inspection_enable=0/1/3不校验inspection_enable=2校验自身结果+检测项结果(type=2除外) -->
AND (
t.inspection_enable IN (0, 1, 3)
OR (
t.inspection_enable = 2
AND t.inspection_inspection = true
AND NOT EXISTS (
SELECT 1
FROM qms_pdi_inspection_results ir
WHERE ir.task_id = t.id
AND ir.inspection_item_type != 2
AND ir.inspection_item_results = false
)
)
t.inspection_inspection IS NULL
OR t.inspection_inspection = true
)
</where>
ORDER BY t.id DESC
@ -112,15 +102,7 @@
<where>
<!-- 固定条件:已完成/待流转,且(总体不合格 或 存在不合格检测项) -->
AND t.inspection_enable IN (2, 3)
AND (
t.inspection_inspection = false
OR EXISTS (
SELECT 1
FROM qms_pdi_inspection_results ir
WHERE ir.task_id = t.id
AND ir.inspection_item_results = false
)
)
AND t.inspection_inspection = false
<!-- 权限校验:当前登录用户只能看到自己负责的数据 -->
AND (
<!-- 无工单时:显示给质检人或帮办人 -->