From a8e6c1570a22be89bbe1a917f1a5b40a33c3852b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9B=B9=E9=B9=8F=E9=A3=9E?= Date: Sat, 9 May 2026 10:39:00 +0800 Subject: [PATCH] =?UTF-8?q?feat(qms):=20=E4=BC=98=E5=8C=96=E6=A3=80?= =?UTF-8?q?=E9=AA=8C=E6=A0=87=E5=87=86=E7=AE=A1=E7=90=86=E5=8F=8A=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - QmsIncomingInspectionTaskNonconformanceVO新增ticketId、version和associationTaskNo字段,完善查询结果字段 - QmsInspectionStandard实体新增发布状态2=已废弃,增强状态管理 - QmsInspectionStandardController中的saveDraft接口调整,返回新建草稿ID - QmsInspectionStandardControllerService中saveDraft方法重构 - 已发布标准不允许直接修改,改为创建新的草稿记录 - 新增抽样检测方式相关必填字段校验 - 实现基于已发布检验标准创建全新草稿及其检测项和内容的逻辑 - QmsInspectionStandardServiceImpl发布方法增强 - 校验不得包含已发布的标准 - 发布后将相同物料ID的其他检验标准状态设置为已废弃 - QmsIssueTicket实体新增关联检测任务单号字段 - QmsIssueTicketControllerService中优化图片ID拼接和图片列表查询逻辑,避免空字段NullPointer异常 --- .../QmsInspectionStandardController.java | 5 +- ...msInspectionStandardControllerService.java | 120 ++++++++++++++---- .../QmsIssueTicketControllerService.java | 28 ++-- ...ncomingInspectionTaskNonconformanceVO.java | 15 +++ .../entity/QmsInspectionStandard.java | 2 +- .../wms/repository/entity/QmsIssueTicket.java | 5 + .../QmsInspectionStandardServiceImpl.java | 34 ++++- ...mingInspectionTaskNonconformanceMapper.xml | 6 +- 8 files changed, 175 insertions(+), 40 deletions(-) diff --git a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsInspectionStandardController.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsInspectionStandardController.java index 3e4a53bb..7b250bca 100644 --- a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsInspectionStandardController.java +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsInspectionStandardController.java @@ -78,9 +78,8 @@ public class QmsInspectionStandardController extends BaseController { * 暂存检验标准 */ @PostMapping("saveDraft") - public ApiResult saveDraft(@Valid @RequestBody QmsInspectionStandardSaveQO request) { - inspectionStandardControllerService.saveDraft(request); - return ApiResult.success(); + public ApiResult saveDraft(@Valid @RequestBody QmsInspectionStandardSaveQO request) { + return ApiResult.success(inspectionStandardControllerService.saveDraft(request)); } /** diff --git a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsInspectionStandardControllerService.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsInspectionStandardControllerService.java index 273473ee..228c0f49 100644 --- a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsInspectionStandardControllerService.java +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsInspectionStandardControllerService.java @@ -513,22 +513,23 @@ public class QmsInspectionStandardControllerService { * @param qo 暂存请求参数 */ @Transactional(rollbackFor = Exception.class) - public void saveDraft(QmsInspectionStandardSaveQO qo) { + public Long saveDraft(QmsInspectionStandardSaveQO qo) { // 1. 校验检验标准是否存在 QmsInspectionStandard standard = inspectionStandardService.getById(qo.getInspectionStandardId()); if (standard == null) { throw new NflgException(com.nflg.wms.common.constant.STATE.BusinessError, "检验标准不存在"); } - // 已发布的标准不允许暂存修改 - if (standard.getPublishStatus() != null && standard.getPublishStatus() == 1) { - throw new NflgException(com.nflg.wms.common.constant.STATE.BusinessError, "已发布的检验标准不允许修改"); - } - Long userId = UserUtil.getUserId(); String userName = UserUtil.getUserName(); LocalDateTime now = LocalDateTime.now(); + // 已发布的标准不允许直接修改,改为创建新的草稿记录 + if (standard.getPublishStatus() != null && standard.getPublishStatus() == 1) { + validateSamplingFields(qo); + return createNewDraftFromPublished(qo, userId, userName, now); + } + // 2. 更新检验标准信息 VUtil.trueThrowBusinessError( inspectionStandardService.lambdaQuery() @@ -539,22 +540,7 @@ public class QmsInspectionStandardControllerService { ).throwMessage("存在相同版本的检验标准"); // 检测方式为抽样时校验相关字段 - if (qo.getTestingMethodDictItemId() != null) { - List testingMethodItems = dictionaryItemService.lambdaQuery() - .eq(DictionaryItem::getId, qo.getTestingMethodDictItemId()) - .list(); - DictionaryItem testingMethod = testingMethodItems.isEmpty() ? null : testingMethodItems.get(0); - if (testingMethod != null && StrUtil.equals(testingMethod.getCode(), "抽样")) { - VUtil.trueThrowBusinessError(Objects.isNull(qo.getSamplingPlanId())) - .throwMessage("检测方式为【抽样】时,抽样方案不能为空"); - VUtil.trueThrowBusinessError(Objects.isNull(qo.getInspectionLevelDictItemId())) - .throwMessage("检测方式为【抽样】时,检验水平不能为空"); - VUtil.trueThrowBusinessError(Objects.isNull(qo.getAqlPriorityValueId())) - .throwMessage("检测方式为【抽样】时,AQL值不能为空"); - VUtil.trueThrowBusinessError(Objects.isNull(qo.getAqlTypeDictItemId())) - .throwMessage("检测方式为【抽样】时,AQL类型不能为空"); - } - } + validateSamplingFields(qo); // 3. 更新字段(不修改版本号) standard.setMaterialId(qo.getMaterialId()); @@ -578,6 +564,96 @@ public class QmsInspectionStandardControllerService { // 3. 处理检测项列表 processItems(dictionaryItemService.getListByDictionaryCode("InspectionStandardDetectionType"), qo.getInspectionStandardId(), qo.getItems(), userId, userName, now); + + return standard.getId(); + } + + /** + * 校验检测方式为抽样时的必填字段 + */ + private void validateSamplingFields(QmsInspectionStandardSaveQO qo) { + if (qo.getTestingMethodDictItemId() != null) { + List testingMethodItems = dictionaryItemService.lambdaQuery() + .eq(DictionaryItem::getId, qo.getTestingMethodDictItemId()) + .list(); + DictionaryItem testingMethod = testingMethodItems.isEmpty() ? null : testingMethodItems.get(0); + if (testingMethod != null && StrUtil.equals(testingMethod.getCode(), "抽样")) { + VUtil.trueThrowBusinessError(Objects.isNull(qo.getSamplingPlanId())) + .throwMessage("检测方式为【抽样】时,抽样方案不能为空"); + VUtil.trueThrowBusinessError(Objects.isNull(qo.getInspectionLevelDictItemId())) + .throwMessage("检测方式为【抽样】时,检验水平不能为空"); + VUtil.trueThrowBusinessError(Objects.isNull(qo.getAqlPriorityValueId())) + .throwMessage("检测方式为【抽样】时,AQL值不能为空"); + VUtil.trueThrowBusinessError(Objects.isNull(qo.getAqlTypeDictItemId())) + .throwMessage("检测方式为【抽样】时,AQL类型不能为空"); + } + } + } + + /** + * 基于已发布的检验标准创建新的草稿记录(全量新增,不复用旧记录 ID) + */ + private Long createNewDraftFromPublished(QmsInspectionStandardSaveQO qo, + Long userId, String userName, LocalDateTime now) { + // 1. 版本唯一性校验(排除原发布记录本身) + VUtil.trueThrowBusinessError( + inspectionStandardService.lambdaQuery() + .ne(QmsInspectionStandard::getId, qo.getInspectionStandardId()) + .eq(QmsInspectionStandard::getMaterialId, qo.getMaterialId()) + .eq(QmsInspectionStandard::getVersion, qo.getVersion()) + .exists() + ).throwMessage("存在相同版本的检验标准"); + + // 2. 创建新的检验标准(草稿状态) + QmsInspectionStandard newStandard = new QmsInspectionStandard(); + newStandard.setMaterialId(qo.getMaterialId()); + newStandard.setDrawingUrl(qo.getDrawingUrl()); + newStandard.setPackagingMethodId(qo.getPackagingMethodId()); + newStandard.setInspectionCycle(qo.getInspectionCycle()); + newStandard.setVersion(qo.getVersion()); + newStandard.setIsEnabled(qo.getIsEnabled()); + newStandard.setTestingMethodDictItemId(qo.getTestingMethodDictItemId()); + newStandard.setSamplingPlanId(qo.getSamplingPlanId()); + newStandard.setInspectionLevelDictItemId(qo.getInspectionLevelDictItemId()); + newStandard.setAqlPriorityValueId(qo.getAqlPriorityValueId()); + newStandard.setAqlTypeDictItemId(qo.getAqlTypeDictItemId()); + newStandard.setPublishStatus((short) 0); + newStandard.setCreateUserId(userId); + newStandard.setCreateUserName(userName); + newStandard.setCreateTime(now); + newStandard.setUpdateUserId(userId); + newStandard.setUpdateUserName(userName); + newStandard.setUpdateTime(now); + inspectionStandardService.save(newStandard); + + // 3. 全量新增检测项及内容(不引用旧记录的 ID) + if (qo.getItems() == null) { + return newStandard.getId(); + } + List dictionaryItems = dictionaryItemService.getListByDictionaryCode("InspectionStandardDetectionType"); + for (QmsInspectionStandardSaveQO.InspectionStandardItemQO itemQO : qo.getItems()) { + DictionaryItem dictionaryItem = dictionaryItems.stream() + .filter(d -> d.getId().equals(itemQO.getDetectionTypeDictItemId())) + .findFirst() + .orElse(null); + VUtil.trueThrowBusinessError(Objects.isNull(dictionaryItem)) + .throwMessage("检测项【" + itemQO.getName() + "】设置的检测类型不存在"); + + QmsInspectionStandardItem newItem = new QmsInspectionStandardItem() + .setInspectionStandardId(newStandard.getId()); + updateItemFields(newItem, itemQO, userId, userName, now); + inspectionStandardItemService.save(newItem); + + if (itemQO.getContents() != null) { + for (QmsInspectionStandardSaveQO.InspectionStandardItemContentQO contentQO : itemQO.getContents()) { + QmsInspectionStandardItemContent newContent = new QmsInspectionStandardItemContent() + .setInspectionStandardItemId(newItem.getId()); + updateContentFields(newContent, contentQO, userId, userName, now); + inspectionStandardItemContentService.save(newContent); + } + } + } + return newStandard.getId(); } /** diff --git a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsIssueTicketControllerService.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsIssueTicketControllerService.java index 68083fb0..053b2407 100644 --- a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsIssueTicketControllerService.java +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsIssueTicketControllerService.java @@ -458,22 +458,26 @@ public class QmsIssueTicketControllerService { return r1; }); r.setUnqualifiedQty(r.getUnqualifiedQty() + record.getUnqualifiedQty()); - r.setImageIds(StrUtil.join(",", r.getImageIds(), record.getImageIds())); + if (StrUtil.isNotBlank(r.getImageIds())) { + r.setImageIds(StrUtil.join(",", r.getImageIds(), record.getImageIds())); + } }); records.stream() .filter(record -> StrUtil.isNotBlank(record.getImageIds())) .forEach(record -> { - record.setImages(fileUploadRecordService.lambdaQuery() - .in(FileUploadRecord::getId, StrUtil.split(record.getImageIds(), ",")) - .list() - .stream() - .map(file -> new FileUploadVO() - .setId(file.getId()) - .setFileName(file.getFileName()) - .setUrl(file.getUrl()) - ) - .collect(Collectors.toList()) - ); + if(StrUtil.isNotBlank(record.getImageIds())) { + record.setImages(fileUploadRecordService.lambdaQuery() + .in(FileUploadRecord::getId, Arrays.stream(StrUtil.splitToLong(record.getImageIds(), ",")).boxed().toList()) + .list() + .stream() + .map(file -> new FileUploadVO() + .setId(file.getId()) + .setFileName(file.getFileName()) + .setUrl(file.getUrl()) + ) + .collect(Collectors.toList()) + ); + } }); vo.setRecords(records); } diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsIncomingInspectionTaskNonconformanceVO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsIncomingInspectionTaskNonconformanceVO.java index f0a18278..784e9285 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsIncomingInspectionTaskNonconformanceVO.java +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsIncomingInspectionTaskNonconformanceVO.java @@ -15,6 +15,11 @@ public class QmsIncomingInspectionTaskNonconformanceVO { */ private Long taskId; + /** + * 工单ID + */ + private Long ticketId; + /** * 检测单号 */ @@ -50,6 +55,11 @@ public class QmsIncomingInspectionTaskNonconformanceVO { */ private String drawingNoVer; + /** + * 检测标准版本号 + */ + private String version; + /** * 供应商编号 */ @@ -154,4 +164,9 @@ public class QmsIncomingInspectionTaskNonconformanceVO { * 流程状态:0=未发起,1=处理中,2=已完成 */ private Short status; + + /** + * 关联检测任务单号 + */ + private String associationTaskNo; } diff --git a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/entity/QmsInspectionStandard.java b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/entity/QmsInspectionStandard.java index 879a9f7a..ae77f924 100644 --- a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/entity/QmsInspectionStandard.java +++ b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/entity/QmsInspectionStandard.java @@ -82,7 +82,7 @@ public class QmsInspectionStandard implements Serializable { private Long aqlTypeDictItemId; /** - * 发布状态:0-未发布,1-已发布 + * 发布状态:0-未发布,1-已发布,2=已废弃 */ private Short publishStatus; diff --git a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/entity/QmsIssueTicket.java b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/entity/QmsIssueTicket.java index 85505e57..c2719ca9 100644 --- a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/entity/QmsIssueTicket.java +++ b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/entity/QmsIssueTicket.java @@ -164,4 +164,9 @@ public class QmsIssueTicket implements Serializable { */ @TableLogic private Integer deleted; + + /** + * 关联检测任务单号 + */ + private String associationTaskNo; } diff --git a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/impl/QmsInspectionStandardServiceImpl.java b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/impl/QmsInspectionStandardServiceImpl.java index 39ceb248..edba6015 100644 --- a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/impl/QmsInspectionStandardServiceImpl.java +++ b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/service/impl/QmsInspectionStandardServiceImpl.java @@ -4,13 +4,16 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nflg.wms.common.pojo.qo.QmsIncomingInspectionTaskTodoCheckItemsQO; import com.nflg.wms.common.pojo.vo.QmsIncomingInspectionTaskCheckItemVO; import com.nflg.wms.common.util.UserUtil; +import com.nflg.wms.common.util.VUtil; import com.nflg.wms.repository.entity.QmsInspectionStandard; import com.nflg.wms.repository.mapper.QmsInspectionStandardMapper; import com.nflg.wms.repository.service.IQmsInspectionStandardService; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.util.List; +import java.util.stream.Collectors; /** * 检验标准 服务实现类 @@ -19,15 +22,26 @@ import java.util.List; public class QmsInspectionStandardServiceImpl extends ServiceImpl implements IQmsInspectionStandardService { + @Transactional @Override public void publish(List ids) { if (ids == null || ids.isEmpty()) { return; } + + // 查询待发布的记录 + List standards = listByIds(ids); + + // 校验是否包含已发布的记录 + boolean hasPublished = standards.stream() + .anyMatch(s -> s.getPublishStatus() == 1); + VUtil.trueThrowBusinessError(hasPublished).throwMessage("包含已发布的检验标准,请重新选择"); + Long userId = UserUtil.getUserId(); String userName = UserUtil.getUserName(); LocalDateTime now = LocalDateTime.now(); - + + // 发布选中的记录 lambdaUpdate() .eq(QmsInspectionStandard::getPublishStatus, (short) 0) .in(QmsInspectionStandard::getId, ids) @@ -39,6 +53,24 @@ public class QmsInspectionStandardServiceImpl extends ServiceImpl materialIds = standards.stream() + .map(QmsInspectionStandard::getMaterialId) + .distinct() + .collect(Collectors.toList()); + + if (!materialIds.isEmpty()) { + lambdaUpdate() + .in(QmsInspectionStandard::getMaterialId, materialIds) + .notIn(QmsInspectionStandard::getId, ids) + .ne(QmsInspectionStandard::getPublishStatus, (short) 2) + .set(QmsInspectionStandard::getPublishStatus, (short) 2) + .set(QmsInspectionStandard::getUpdateUserId, userId) + .set(QmsInspectionStandard::getUpdateUserName, userName) + .set(QmsInspectionStandard::getUpdateTime, now) + .update(); + } } @Override diff --git a/nflg-wms-repository/src/main/resources/mapper/QmsIncomingInspectionTaskNonconformanceMapper.xml b/nflg-wms-repository/src/main/resources/mapper/QmsIncomingInspectionTaskNonconformanceMapper.xml index ef9a55c0..8829781b 100644 --- a/nflg-wms-repository/src/main/resources/mapper/QmsIncomingInspectionTaskNonconformanceMapper.xml +++ b/nflg-wms-repository/src/main/resources/mapper/QmsIncomingInspectionTaskNonconformanceMapper.xml @@ -5,6 +5,7 @@