Compare commits

...

8 Commits

Author SHA1 Message Date
funny 07718193c4 Merge branch 'qms/yf' into qms/develop 2026-04-14 10:00:17 +08:00
funny ec41c6596c 测试修改完成 2026-04-14 09:59:20 +08:00
funny 36b6dce7d6 修改 2026-04-13 20:24:35 +08:00
funny 3dab9dfacd Merge branch 'qms/develop' into qms/yf 2026-04-13 18:03:34 +08:00
funny 6b33a25627 修改 2026-04-13 17:51:46 +08:00
funny 7350061d49 修改 2026-04-13 16:58:00 +08:00
funny ef15359155 Merge branch 'qms/develop' into qms/yf 2026-04-13 16:16:47 +08:00
funny 593c8547a5 修改 2026-04-13 16:15:13 +08:00
19 changed files with 382 additions and 73 deletions

View File

@ -52,7 +52,7 @@ public class QmsCoaReviewController extends BaseController {
}
/**
* 修改COA审核记录
* 修改COA内容
* 状态0时都可以改状态3时只能改COA报告
*/
@Transactional
@ -86,12 +86,23 @@ public class QmsCoaReviewController extends BaseController {
}
/**
* 分页查询只返回当前账号的数据
* 支持供应商编号/名称采购单号物料编码过滤供应商名称模糊查询
* 分页查询-供应商
* 供应商查看自己创建的审核记录
* 支持供应商编号/名称采购单号物料编码过滤
*/
@PostMapping("search")
public ApiResult<PageData<QmsCoaReviewVO>> search(@Valid @RequestBody QmsCoaReviewSearchQO qo) {
return ApiResult.success(coaReviewService.search(qo));
@PostMapping("searchForSupplier")
public ApiResult<PageData<QmsCoaReviewVO>> searchForSupplier(@Valid @RequestBody QmsCoaReviewSearchQO qo) {
return ApiResult.success(coaReviewService.searchForSupplier(qo));
}
/**
* 分页查询-SQE
* SQE查看待审核的记录基于task.user_id
* 支持供应商编号/名称采购单号物料编码过滤
*/
@PostMapping("searchForSqe")
public ApiResult<PageData<QmsCoaReviewVO>> searchForSqe(@Valid @RequestBody QmsCoaReviewSearchQO qo) {
return ApiResult.success(coaReviewService.searchForSqe(qo));
}
/**

View File

@ -73,7 +73,7 @@ public class QmsCoaTaskController extends BaseController {
}
/**
* 分页查询当前账号只能看自己创建的数据
* 分页查询当前账号只能看属于自己的数据
* 支持供应商名称模糊供应商编号精确物料编号精确过滤
*/
@PostMapping("search")

View File

@ -1,6 +1,8 @@
package com.nflg.qms.admin.controller;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.nflg.wms.common.constant.STATE;
import com.nflg.wms.common.exception.NflgException;
import com.nflg.wms.common.pojo.ApiResult;
@ -18,7 +20,6 @@ import com.nflg.wms.common.util.EecExcelUtil;
import com.nflg.wms.repository.service.IQmsInspectionItemService;
import com.nflg.wms.starter.BaseController;
import com.nflg.wms.starter.service.FileUploadService;
import cn.hutool.core.util.IdUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
@ -28,12 +29,14 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.ttzero.excel.entity.ListSheet;
import org.ttzero.excel.entity.Workbook;
import org.ttzero.excel.reader.Drawings;
import org.ttzero.excel.reader.ExcelReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
/**
@ -162,7 +165,7 @@ public class QmsInspectionItemController extends BaseController {
example.setLegend("示例图例URL可不填");
example.setDeterminationType(0);
EecExcelUtil.export("检测项导入模板", "检测项导入模板", Collections.singletonList(example), response);
EecExcelUtil.export("检测项导入模板", "检测项导入模板", List.of(example), response);
}
// ==================== 导入 ====================
@ -170,18 +173,45 @@ public class QmsInspectionItemController extends BaseController {
/**
* 导入检测项
* 校验失败时返回带错误信息的文件URL
* 图例字段填写图片URL需先通过文件上传接口上传图片获取URL
* 图例字段支持图片URL
*
* @param file 导入文件
*/
@Transactional
@PostMapping("import")
public ApiResult<String> importFromExcel(@RequestParam("file") MultipartFile file) throws IOException {
public ApiResult<String> importFromExcel(@RequestParam("file") MultipartFile file) throws Exception {
List<QmsInspectionItemImportDTO> data = EecExcelUtil.getExcelContext(file.getInputStream(), QmsInspectionItemImportDTO.class);
if (CollectionUtil.isEmpty(data)) {
throw new NflgException(STATE.BusinessError, "导入文件内容为空");
}
// 2. 读取 Excel 里的所有图片EEC 标准方式
List<Drawings.Picture> pictures = new ExcelReader(file.getInputStream()).listPictures();
// 3. 遍历 DTO遇到 DISPIMG 就上传图片并替换地址
for (int i = 0; i < data.size(); i++) {
QmsInspectionItemImportDTO dto = data.get(i);
String legend = dto.getLegend();
// 如果是图片公式就取图片上传把地址填回去
if (StrUtil.isNotBlank(legend) && legend.startsWith("=DISPIMG(")) {
if (i < pictures.size()) {
Drawings.Picture pic = pictures.get(i);
FileInputStream fis = new FileInputStream(pic.getLocalPath().toFile());
// 上传图片 获取地址
String imageUrl = fileUploadService.upload(
"image/" + IdUtil.fastUUID() + ".png",
fis,
"image/png"
);
dto.setLegend(imageUrl); // 把地址塞回去
} else {
dto.setLegend(null);
}
}
}
// 校验必填字段
boolean hasError = false;
for (QmsInspectionItemImportDTO dto : data) {

View File

@ -5,7 +5,7 @@ import org.ttzero.excel.annotation.ExcelColumn;
import org.ttzero.excel.annotation.MediaColumn;
/**
* 检测项导出 DTO不含错误信息字段
* 检测项导出 DTO
*/
@Data
public class QmsInspectionItemExportDTO {
@ -43,6 +43,7 @@ public class QmsInspectionItemExportDTO {
/**
* 图例图片URL导出时自动转为图片
*/
@ExcelColumn("图例")
@MediaColumn
private String legend;

View File

@ -5,17 +5,10 @@ import org.ttzero.excel.annotation.ExcelColumn;
/**
* 检测项导入 DTO
* ExcelColumn 注解用于列头映射 * 的为必填字段
*/
@Data
public class QmsInspectionItemImportDTO {
/**
* 错误信息导入校验结果
*/
@ExcelColumn("错误信息")
private String error;
/**
* 物料类别ID
*/
@ -47,7 +40,7 @@ public class QmsInspectionItemImportDTO {
private String testStandard;
/**
* 图例图片URL
* 图例图片URL由Controller上传后设置
*/
@ExcelColumn("图例")
private String legend;
@ -57,4 +50,10 @@ public class QmsInspectionItemImportDTO {
*/
@ExcelColumn("判定类型(0目视/1量具)*")
private Integer determinationType;
/**
* 错误信息导入校验结果
*/
@ExcelColumn("错误信息")
private String error;
}

View File

@ -1,6 +1,7 @@
package com.nflg.wms.common.pojo.qo;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
@ -10,7 +11,13 @@ import lombok.Data;
public class QmsCoaReviewAddQO {
/**
* 物料编码必传用于查询 qms_qc_material.id
* 任务ID关联 qms_coa_task.id必传
*/
@NotNull(message = "任务ID不能为空")
private Long taskId;
/**
* 物料编码必传用于与任务中的物料进行校验
*/
@NotBlank(message = "物料编码不能为空")
private String materialNo;
@ -21,6 +28,12 @@ public class QmsCoaReviewAddQO {
@NotBlank(message = "采购单号不能为空")
private String purchaseNo;
/**
* 批次号必传
*/
@NotBlank(message = "批次号不能为空")
private String batchNo;
/**
* COA报告/文件地址必传
*/

View File

@ -4,7 +4,7 @@ import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.time.LocalDateTime;
import java.time.LocalDate;
/**
* 新增COA通知任务参数
@ -34,7 +34,7 @@ public class QmsCoaTaskAddQO {
* 最晚提交时间必传
*/
@NotNull(message = "最晚提交时间不能为空")
private LocalDateTime lastSubTime;
private LocalDate lastSubTime;
/**
* 报告模板可选

View File

@ -3,7 +3,7 @@ package com.nflg.wms.common.pojo.qo;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.time.LocalDateTime;
import java.time.LocalDate;
/**
* 修改COA通知任务参数id必传其余可选
@ -35,7 +35,7 @@ public class QmsCoaTaskUpdateQO {
/**
* 最晚提交时间可选
*/
private LocalDateTime lastSubTime;
private LocalDate lastSubTime;
/**
* 报告模板可选

View File

@ -27,6 +27,11 @@ public class QmsCoaReviewDetailVO {
*/
private String purchaseNo;
/**
* 批次号
*/
private String batchNo;
/**
* 物料编码
*/

View File

@ -27,6 +27,11 @@ public class QmsCoaReviewVO {
*/
private String purchaseNo;
/**
* 批次号
*/
private String batchNo;
/**
* 物料编码
*/

View File

@ -2,6 +2,7 @@ package com.nflg.wms.common.pojo.vo;
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
@ -60,7 +61,7 @@ public class QmsCoaTaskVO {
/**
* 最晚提交时间
*/
private LocalDateTime lastSubTime;
private LocalDate lastSubTime;
/**
* 创建人

View File

@ -56,6 +56,11 @@ public class QmsCoaReview implements Serializable {
*/
private String purchaseNo;
/**
* 批次号
*/
private String batchNo;
/**
* COA审核状态0=待提交1=待审核2=已通过3=已驳回
*/

View File

@ -9,6 +9,7 @@ import lombok.ToString;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
@ -69,7 +70,7 @@ public class QmsCoaTask implements Serializable {
/**
* 最晚提交时间
*/
private LocalDateTime lastSubTime;
private LocalDate lastSubTime;
/**
* 创建人

View File

@ -45,9 +45,14 @@ public interface IQmsCoaReviewService extends IService<QmsCoaReview> {
void audit(QmsCoaReviewAuditQO qo);
/**
* 分页查询只返回当前账号的数据
* 分页查询-供应商供应商查看自己创建的审核记录
*/
PageData<QmsCoaReviewVO> search(QmsCoaReviewSearchQO qo);
PageData<QmsCoaReviewVO> searchForSupplier(QmsCoaReviewSearchQO qo);
/**
* 分页查询-SQESQE查看待审核的记录基于task.user_id
*/
PageData<QmsCoaReviewVO> searchForSqe(QmsCoaReviewSearchQO qo);
/**
* 按ID查详情

View File

@ -62,6 +62,7 @@ public interface IQmsInspectionItemService extends IService<QmsInspectionItem> {
/**
* 批量导入
* 按编号+名称分组主表插一条明细表插多条
*/
void importItems(List<QmsInspectionItemImportDTO> dtos);
}

View File

@ -1,5 +1,6 @@
package com.nflg.wms.repository.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@ -13,11 +14,13 @@ import com.nflg.wms.common.pojo.qo.QmsCoaReviewUpdateQO;
import com.nflg.wms.common.pojo.vo.QmsCoaReviewDetailVO;
import com.nflg.wms.common.pojo.vo.QmsCoaReviewVO;
import com.nflg.wms.common.util.UserUtil;
import com.nflg.wms.repository.entity.QmsCoaTask;
import com.nflg.wms.repository.entity.QmsCoaReview;
import com.nflg.wms.repository.entity.QmsQcMaterial;
import com.nflg.wms.repository.entity.User;
import com.nflg.wms.repository.entity.UserSupplier;
import com.nflg.wms.repository.mapper.QmsCoaReviewMapper;
import com.nflg.wms.repository.service.IQmsCoaTaskService;
import com.nflg.wms.repository.service.IQmsCoaReviewService;
import com.nflg.wms.repository.service.IQmsQcMaterialService;
import com.nflg.wms.repository.service.IUserService;
@ -49,12 +52,34 @@ public class QmsCoaReviewServiceImpl extends ServiceImpl<QmsCoaReviewMapper, Qms
@Resource
private IUserService userService;
@Resource
private IQmsCoaTaskService coaTaskService;
// ==================== 新增 ====================
@Transactional
@Override
public void add(QmsCoaReviewAddQO qo) {
// 按物料编码查物料
Long currentUserId = UserUtil.getUserId();
// 1. 查询COA任务
QmsCoaTask task = coaTaskService.getById(qo.getTaskId());
if (Objects.isNull(task) || Boolean.TRUE.equals(task.getDeleted())) {
throw new NflgException(STATE.BusinessError, "COA任务不存在");
}
// 2. 验证任务状态状态0待发送不能新建
if (Objects.equals(task.getStatus(), 0)) {
throw new NflgException(STATE.BusinessError, "任务状态为待发送无法新建COA审核");
}
// 3. 验证当前账号是否与任务中的供应商一致
UserSupplier supplier = userSupplierService.getById(task.getSupplierId());
if (Objects.isNull(supplier) || !Objects.equals(supplier.getUserId(), currentUserId)) {
throw new NflgException(STATE.BusinessError, "当前账号与任务中的供应商不匹配,无权操作此任务");
}
// 4. 根据物料编码查询 qms_qc_material 表获取物料ID
QmsQcMaterial material = qcMaterialService.lambdaQuery()
.eq(QmsQcMaterial::getMaterialNo, qo.getMaterialNo())
.last("LIMIT 1")
@ -63,13 +88,32 @@ public class QmsCoaReviewServiceImpl extends ServiceImpl<QmsCoaReviewMapper, Qms
throw new NflgException(STATE.BusinessError, "物料编码不存在:" + qo.getMaterialNo());
}
// 5. 验证物料ID是否与任务中的物料ID一致
if (!Objects.equals(task.getMaterialId(), material.getId())) {
throw new NflgException(STATE.BusinessError, "物料编码与任务中的物料不匹配");
}
// 6. 校验批次号唯一性同task_id + 同采购单号 + 同批次号 不能重复
boolean exists = lambdaQuery()
.eq(QmsCoaReview::getTaskId, qo.getTaskId())
.eq(QmsCoaReview::getPurchaseNo, qo.getPurchaseNo())
.eq(QmsCoaReview::getBatchNo, qo.getBatchNo())
.ne(QmsCoaReview::getDeleted, true)
.exists();
if (exists) {
throw new NflgException(STATE.BusinessError, "该采购单号下已存在相同批次号,无法重复新增");
}
String operator = UserUtil.getUserName();
LocalDateTime now = LocalDateTime.now();
QmsCoaReview review = new QmsCoaReview()
.setTaskId(qo.getTaskId())
.setSupplierId(task.getSupplierId())
.setMaterialId(material.getId())
.setUserId(UserUtil.getUserId())
.setUserId(currentUserId)
.setPurchaseNo(qo.getPurchaseNo())
.setBatchNo(qo.getBatchNo())
.setCoaFile(qo.getCoaFile())
.setStatus(0)
.setDeleted(false)
@ -89,6 +133,9 @@ public class QmsCoaReviewServiceImpl extends ServiceImpl<QmsCoaReviewMapper, Qms
if (Objects.isNull(review) || Boolean.TRUE.equals(review.getDeleted())) {
throw new NflgException(STATE.BusinessError, "记录不存在");
}
// 校验供应商权限
validateSupplierPermission(review.getSupplierId());
if (!Objects.equals(review.getStatus(), 0)) {
throw new NflgException(STATE.BusinessError, "当前状态不允许删除只有待提交状态0的记录才能删除");
}
@ -109,6 +156,8 @@ public class QmsCoaReviewServiceImpl extends ServiceImpl<QmsCoaReviewMapper, Qms
if (Objects.isNull(review) || Boolean.TRUE.equals(review.getDeleted())) {
throw new NflgException(STATE.BusinessError, "记录不存在");
}
// 校验供应商权限
validateSupplierPermission(review.getSupplierId());
Integer status = review.getStatus();
String operator = UserUtil.getUserName();
@ -162,24 +211,44 @@ public class QmsCoaReviewServiceImpl extends ServiceImpl<QmsCoaReviewMapper, Qms
if (ids == null || ids.isEmpty()) {
throw new NflgException(STATE.BusinessError, "提交ID列表不能为空");
}
// 校验所有记录状态是否为0
// 校验所有记录状态是否为0并收集taskId
List<QmsCoaReview> reviews = lambdaQuery()
.in(QmsCoaReview::getId, ids)
.list();
Set<Long> taskIds = new java.util.HashSet<>();
for (QmsCoaReview r : reviews) {
if (!Objects.equals(r.getStatus(), 0)) {
throw new NflgException(STATE.BusinessError, "ID=" + r.getId() + " 的记录不是待提交状态,无法提交");
}
// 校验供应商权限
validateSupplierPermission(r.getSupplierId());
// 收集taskId
if (Objects.nonNull(r.getTaskId())) {
taskIds.add(r.getTaskId());
}
}
String operator = UserUtil.getUserName();
LocalDateTime now = LocalDateTime.now();
// 更新审核记录状态为1待审核
lambdaUpdate()
.in(QmsCoaReview::getId, ids)
.set(QmsCoaReview::getStatus, 1)
.set(QmsCoaReview::getUpdateBy, operator)
.set(QmsCoaReview::getUpdateTime, now)
.update();
// 更新关联的任务状态为2已上传
if (!taskIds.isEmpty()) {
coaTaskService.lambdaUpdate()
.in(QmsCoaTask::getId, taskIds)
.set(QmsCoaTask::getStatus, 2)
.set(QmsCoaTask::getUpdateBy, operator)
.set(QmsCoaTask::getUpdateTime, now)
.update();
}
}
// ==================== 审核 ====================
@ -195,6 +264,14 @@ public class QmsCoaReviewServiceImpl extends ServiceImpl<QmsCoaReviewMapper, Qms
throw new NflgException(STATE.BusinessError, "当前状态不是待审核,无法进行审核操作");
}
// 校验当前用户是否与任务中的SQE用户一致
if (Objects.nonNull(review.getTaskId())) {
QmsCoaTask task = coaTaskService.getById(review.getTaskId());
if (Objects.nonNull(task) && !Objects.equals(task.getUserId(), UserUtil.getUserId())) {
throw new NflgException(STATE.BusinessError, "当前账号与任务中的SQE用户不匹配无权审核");
}
}
Integer newStatus = qo.getStatus();
if (!Objects.equals(newStatus, 2) && !Objects.equals(newStatus, 3)) {
throw new NflgException(STATE.BusinessError, "审核状态只能为2已通过或3已驳回");
@ -229,21 +306,41 @@ public class QmsCoaReviewServiceImpl extends ServiceImpl<QmsCoaReviewMapper, Qms
// ==================== 分页查询 ====================
/**
* 供应商分页查询供应商查看自己创建的审核记录
*/
@Override
public PageData<QmsCoaReviewVO> search(QmsCoaReviewSearchQO qo) {
// 当前账号只能看自己创建的数据
public PageData<QmsCoaReviewVO> searchForSupplier(QmsCoaReviewSearchQO qo) {
Long currentUserId = UserUtil.getUserId();
// 处理供应商过滤名称模糊 or 编号精确
// 获取当前用户关联的供应商ID
UserSupplier supplier = userSupplierService.lambdaQuery()
.eq(UserSupplier::getUserId, currentUserId)
.last("LIMIT 1")
.one();
if (Objects.isNull(supplier)) {
throw new NflgException(STATE.BusinessError, "当前账号未关联供应商");
}
Long currentSupplierId = supplier.getId();
// 处理供应商过滤连接供应商表查询ID
Set<Long> filteredSupplierIds = null;
boolean hasSupplierFilter = (Objects.nonNull(qo.getSupplierName()) && !qo.getSupplierName().isEmpty())
|| (Objects.nonNull(qo.getSupplierCode()) && !qo.getSupplierCode().isEmpty());
if (hasSupplierFilter) {
boolean hasSupplierNameFilter = StrUtil.isNotBlank(qo.getSupplierName());
boolean hasSupplierCodeFilter = StrUtil.isNotBlank(qo.getSupplierCode());
if (hasSupplierNameFilter || hasSupplierCodeFilter) {
List<UserSupplier> suppliers = userSupplierService.lambdaQuery()
.like(Objects.nonNull(qo.getSupplierName()) && !qo.getSupplierName().isEmpty(),
UserSupplier::getSupplierName, qo.getSupplierName())
.eq(Objects.nonNull(qo.getSupplierCode()) && !qo.getSupplierCode().isEmpty(),
UserSupplier::getSupplierCode, qo.getSupplierCode())
.nested(i -> {
if (hasSupplierNameFilter) {
i.like(UserSupplier::getSupplierName, qo.getSupplierName());
}
if (hasSupplierCodeFilter) {
if (hasSupplierNameFilter) {
i.or();
}
i.eq(UserSupplier::getSupplierCode, qo.getSupplierCode());
}
})
.list();
filteredSupplierIds = suppliers.stream().map(UserSupplier::getId).collect(Collectors.toSet());
if (filteredSupplierIds.isEmpty()) {
@ -253,7 +350,7 @@ public class QmsCoaReviewServiceImpl extends ServiceImpl<QmsCoaReviewMapper, Qms
// 处理物料编号过滤
Set<Long> filteredMaterialIds = null;
if (Objects.nonNull(qo.getMaterialNo()) && !qo.getMaterialNo().isEmpty()) {
if (StrUtil.isNotBlank(qo.getMaterialNo())) {
List<QmsQcMaterial> materials = qcMaterialService.lambdaQuery()
.eq(QmsQcMaterial::getMaterialNo, qo.getMaterialNo())
.list();
@ -266,21 +363,122 @@ public class QmsCoaReviewServiceImpl extends ServiceImpl<QmsCoaReviewMapper, Qms
final Set<Long> finalSupplierIds = filteredSupplierIds;
final Set<Long> finalMaterialIds = filteredMaterialIds;
IPage<QmsCoaReview> page = lambdaQuery()
.eq(QmsCoaReview::getUserId, currentUserId)
// 构建查询只能查看当前供应商的数据
var query = lambdaQuery()
.eq(QmsCoaReview::getSupplierId, currentSupplierId)
.ne(QmsCoaReview::getDeleted, true)
.in(Objects.nonNull(finalSupplierIds), QmsCoaReview::getSupplierId, finalSupplierIds != null ? finalSupplierIds : List.of())
.in(Objects.nonNull(finalMaterialIds), QmsCoaReview::getMaterialId, finalMaterialIds != null ? finalMaterialIds : List.of())
.eq(Objects.nonNull(qo.getPurchaseNo()) && !qo.getPurchaseNo().isEmpty(),
QmsCoaReview::getPurchaseNo, qo.getPurchaseNo())
.orderByDesc(QmsCoaReview::getCreateTime)
.page(new Page<>(qo.getPage(), qo.getPageSize()));
.eq(StrUtil.isNotBlank(qo.getPurchaseNo()), QmsCoaReview::getPurchaseNo, qo.getPurchaseNo())
.orderByDesc(QmsCoaReview::getCreateTime);
// 供应商ID过滤只在有过滤条件时添加
if (finalSupplierIds != null && !finalSupplierIds.isEmpty()) {
query.in(QmsCoaReview::getSupplierId, finalSupplierIds);
}
// 物料ID过滤只在有过滤条件时添加
if (finalMaterialIds != null && !finalMaterialIds.isEmpty()) {
query.in(QmsCoaReview::getMaterialId, finalMaterialIds);
}
IPage<QmsCoaReview> page = query.page(new Page<>(qo.getPage(), qo.getPageSize()));
List<QmsCoaReview> records = page.getRecords();
if (records.isEmpty()) {
return buildPageData(page, List.of());
}
// 批量查询关联数据
return buildPageDataWithRelations(page, records);
}
/**
* SQE分页查询SQE查看待审核的记录基于task.user_id
*/
@Override
public PageData<QmsCoaReviewVO> searchForSqe(QmsCoaReviewSearchQO qo) {
Long currentUserId = UserUtil.getUserId();
// 查询当前SQE用户关联的任务ID列表
List<QmsCoaTask> tasks = coaTaskService.lambdaQuery()
.eq(QmsCoaTask::getUserId, currentUserId)
.ne(QmsCoaTask::getDeleted, true)
.list();
if (tasks.isEmpty()) {
return emptyPage(qo.getPage(), qo.getPageSize());
}
Set<Long> taskIds = tasks.stream().map(QmsCoaTask::getId).collect(Collectors.toSet());
// 处理供应商过滤
Set<Long> filteredSupplierIds = null;
boolean hasSupplierNameFilter = StrUtil.isNotBlank(qo.getSupplierName());
boolean hasSupplierCodeFilter = StrUtil.isNotBlank(qo.getSupplierCode());
if (hasSupplierNameFilter || hasSupplierCodeFilter) {
List<UserSupplier> suppliers = userSupplierService.lambdaQuery()
.nested(i -> {
if (hasSupplierNameFilter) {
i.like(UserSupplier::getSupplierName, qo.getSupplierName());
}
if (hasSupplierCodeFilter) {
if (hasSupplierNameFilter) {
i.or();
}
i.eq(UserSupplier::getSupplierCode, qo.getSupplierCode());
}
})
.list();
filteredSupplierIds = suppliers.stream().map(UserSupplier::getId).collect(Collectors.toSet());
if (filteredSupplierIds.isEmpty()) {
return emptyPage(qo.getPage(), qo.getPageSize());
}
}
// 处理物料编号过滤
Set<Long> filteredMaterialIds = null;
if (StrUtil.isNotBlank(qo.getMaterialNo())) {
List<QmsQcMaterial> materials = qcMaterialService.lambdaQuery()
.eq(QmsQcMaterial::getMaterialNo, qo.getMaterialNo())
.list();
filteredMaterialIds = materials.stream().map(QmsQcMaterial::getId).collect(Collectors.toSet());
if (filteredMaterialIds.isEmpty()) {
return emptyPage(qo.getPage(), qo.getPageSize());
}
}
final Set<Long> finalSupplierIds = filteredSupplierIds;
final Set<Long> finalMaterialIds = filteredMaterialIds;
// 构建查询只能查看属于当前SQE任务的审核记录
var query = lambdaQuery()
.in(QmsCoaReview::getTaskId, taskIds)
.ne(QmsCoaReview::getDeleted, true)
.eq(StrUtil.isNotBlank(qo.getPurchaseNo()), QmsCoaReview::getPurchaseNo, qo.getPurchaseNo())
.orderByDesc(QmsCoaReview::getCreateTime);
// 供应商ID过滤
if (finalSupplierIds != null && !finalSupplierIds.isEmpty()) {
query.in(QmsCoaReview::getSupplierId, finalSupplierIds);
}
// 物料ID过滤
if (finalMaterialIds != null && !finalMaterialIds.isEmpty()) {
query.in(QmsCoaReview::getMaterialId, finalMaterialIds);
}
IPage<QmsCoaReview> page = query.page(new Page<>(qo.getPage(), qo.getPageSize()));
List<QmsCoaReview> records = page.getRecords();
if (records.isEmpty()) {
return buildPageData(page, List.of());
}
return buildPageDataWithRelations(page, records);
}
/**
* 构建分页结果并填充关联数据
*/
private PageData<QmsCoaReviewVO> buildPageDataWithRelations(IPage<QmsCoaReview> page, List<QmsCoaReview> records) {
// 批量查询关联数据
Set<Long> supplierIds = records.stream().map(QmsCoaReview::getSupplierId).filter(Objects::nonNull).collect(Collectors.toSet());
Set<Long> materialIds = records.stream().map(QmsCoaReview::getMaterialId).filter(Objects::nonNull).collect(Collectors.toSet());
@ -314,6 +512,7 @@ public class QmsCoaReviewServiceImpl extends ServiceImpl<QmsCoaReviewMapper, Qms
QmsCoaReviewDetailVO vo = new QmsCoaReviewDetailVO();
vo.setId(review.getId());
vo.setPurchaseNo(review.getPurchaseNo());
vo.setBatchNo(review.getBatchNo());
vo.setStatus(review.getStatus());
vo.setReviewBy(review.getReviewBy());
vo.setReviewTime(review.getReviewTime());
@ -356,6 +555,7 @@ public class QmsCoaReviewServiceImpl extends ServiceImpl<QmsCoaReviewMapper, Qms
QmsCoaReviewVO vo = new QmsCoaReviewVO();
vo.setId(r.getId());
vo.setPurchaseNo(r.getPurchaseNo());
vo.setBatchNo(r.getBatchNo());
vo.setStatus(r.getStatus());
vo.setReviewBy(r.getReviewBy());
vo.setReviewTime(r.getReviewTime());
@ -397,4 +597,16 @@ public class QmsCoaReviewServiceImpl extends ServiceImpl<QmsCoaReviewMapper, Qms
result.setTotal(0);
return result;
}
/**
* 校验当前用户是否与供应商关联
* @param supplierId 供应商ID
*/
private void validateSupplierPermission(Long supplierId) {
Long currentUserId = UserUtil.getUserId();
UserSupplier supplier = userSupplierService.getById(supplierId);
if (Objects.isNull(supplier) || !Objects.equals(supplier.getUserId(), currentUserId)) {
throw new NflgException(STATE.BusinessError, "当前账号与供应商不匹配,无权操作");
}
}
}

View File

@ -1,5 +1,6 @@
package com.nflg.wms.repository.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@ -178,27 +179,36 @@ public class QmsCoaTaskServiceImpl extends ServiceImpl<QmsCoaTaskMapper, QmsCoaT
// 当前账号只能看自己创建的数据
Long currentUserId = UserUtil.getUserId();
// 处理供应商过滤名称模糊 or 编号精确
// 处理供应商过滤连接供应商表查询ID
Set<Long> filteredSupplierIds = null;
boolean hasSupplierFilter = (Objects.nonNull(qo.getSupplierName()) && !qo.getSupplierName().isEmpty())
|| (Objects.nonNull(qo.getSupplierCode()) && !qo.getSupplierCode().isEmpty());
if (hasSupplierFilter) {
boolean hasSupplierNameFilter = StrUtil.isNotBlank(qo.getSupplierName());
boolean hasSupplierCodeFilter = StrUtil.isNotBlank(qo.getSupplierCode());
if (hasSupplierNameFilter || hasSupplierCodeFilter) {
// 构建OR条件查询供应商
List<UserSupplier> suppliers = userSupplierService.lambdaQuery()
.like(Objects.nonNull(qo.getSupplierName()) && !qo.getSupplierName().isEmpty(),
UserSupplier::getSupplierName, qo.getSupplierName())
.eq(Objects.nonNull(qo.getSupplierCode()) && !qo.getSupplierCode().isEmpty(),
UserSupplier::getSupplierCode, qo.getSupplierCode())
.nested(i -> {
if (hasSupplierNameFilter) {
i.like(UserSupplier::getSupplierName, qo.getSupplierName());
}
if (hasSupplierCodeFilter) {
if (hasSupplierNameFilter) {
i.or();
}
i.eq(UserSupplier::getSupplierCode, qo.getSupplierCode());
}
})
.list();
filteredSupplierIds = suppliers.stream().map(UserSupplier::getId).collect(Collectors.toSet());
if (filteredSupplierIds.isEmpty()) {
// 供应商过滤结果为空直接返回空分页
return emptyPage(qo.getPage(), qo.getPageSize());
}
}
// 处理物料编号过滤
Set<Long> filteredMaterialIds = null;
if (Objects.nonNull(qo.getMaterialNo()) && !qo.getMaterialNo().isEmpty()) {
boolean hasMaterialNoFilter = StrUtil.isNotBlank(qo.getMaterialNo());
if (hasMaterialNoFilter) {
List<QmsQcMaterial> materials = qcMaterialService.lambdaQuery()
.eq(QmsQcMaterial::getMaterialNo, qo.getMaterialNo())
.list();
@ -211,13 +221,23 @@ public class QmsCoaTaskServiceImpl extends ServiceImpl<QmsCoaTaskMapper, QmsCoaT
final Set<Long> finalSupplierIds = filteredSupplierIds;
final Set<Long> finalMaterialIds = filteredMaterialIds;
IPage<QmsCoaTask> page = lambdaQuery()
// 构建查询
var query = lambdaQuery()
.eq(QmsCoaTask::getUserId, currentUserId)
.ne(QmsCoaTask::getDeleted, true)
.in(Objects.nonNull(finalSupplierIds), QmsCoaTask::getSupplierId, finalSupplierIds != null ? finalSupplierIds : List.of())
.in(Objects.nonNull(finalMaterialIds), QmsCoaTask::getMaterialId, finalMaterialIds != null ? finalMaterialIds : List.of())
.orderByDesc(QmsCoaTask::getCreateTime)
.page(new Page<>(qo.getPage(), qo.getPageSize()));
.orderByDesc(QmsCoaTask::getCreateTime);
// 供应商ID过滤只在有过滤条件时添加
if (finalSupplierIds != null && !finalSupplierIds.isEmpty()) {
query.in(QmsCoaTask::getSupplierId, finalSupplierIds);
}
// 物料ID过滤只在有过滤条件时添加
if (finalMaterialIds != null && !finalMaterialIds.isEmpty()) {
query.in(QmsCoaTask::getMaterialId, finalMaterialIds);
}
IPage<QmsCoaTask> page = query.page(new Page<>(qo.getPage(), qo.getPageSize()));
// 组装 VO批量查供应商和物料
List<QmsCoaTask> records = page.getRecords();

View File

@ -290,15 +290,10 @@ public class QmsInspectionItemServiceImpl extends ServiceImpl<QmsInspectionItemM
// 所有行作为明细插入
for (QmsInspectionItemImportDTO dto : list) {
// 过滤无效的图片公式只保留有效的 URL
String legend = dto.getLegend();
if (StrUtil.isNotBlank(legend) && legend.startsWith("=DISPIMG(")) {
legend = null; // 忽略无效的 Excel 图片公式
}
QmsInspectionItemDetails detail = new QmsInspectionItemDetails()
.setInspectionItemId(item.getId())
.setTestStandard(dto.getTestStandard())
.setLegend(legend)
.setLegend(dto.getLegend())
.setDeterminationType(dto.getDeterminationType());
detailsService.save(detail);
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nflg.wms.repository.mapper.QmsCoaTaskMapper">
</mapper>