feat(qms): 新增质检物料分类和检验标准模块功能

- 新增质检物料分类服务及其实现,支持按名称和编码模糊查询并构建树形结构
- 添加质检物料分类接口及单元测试,验证类别树查询和条件过滤功能
- 新增检验标准相关实体、服务接口及实现类,实现批量发布和启用/禁用功能
- 增加检验标准分页查询Mapper及XML配置,支持物料编号、类别编码及IQE姓名模糊过滤
- 创建检验标准控制层及对应业务逻辑服务,提供标准的REST接口
- 引入批量ID请求参数类IdsQO及相关启用请求参数支持统一校验
- 完善检验标准VO定义,支持前端展示完整信息
- 规范日志记录和异常处理,确保服务稳定性和代码健壮性
This commit is contained in:
曹鹏飞 2026-04-14 14:35:58 +08:00
parent 07718193c4
commit 0aaaf451e8
18 changed files with 1239 additions and 0 deletions

View File

@ -0,0 +1,53 @@
package com.nflg.qms.admin.controller;
import com.nflg.qms.admin.service.QmsInspectionStandardControllerService;
import com.nflg.wms.common.pojo.ApiResult;
import com.nflg.wms.common.pojo.PageData;
import com.nflg.wms.common.pojo.qo.EnableQO;
import com.nflg.wms.common.pojo.qo.IdsQO;
import com.nflg.wms.common.pojo.qo.QmsInspectionStandardSearchQO;
import com.nflg.wms.common.pojo.vo.QmsInspectionStandardVO;
import com.nflg.wms.starter.BaseController;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 检验标准
*/
@RestController
@RequestMapping("/inspection-standard")
public class QmsInspectionStandardController extends BaseController {
@Resource
private QmsInspectionStandardControllerService inspectionStandardControllerService;
/**
* 分页查询检验标准
*/
@PostMapping("search")
public ApiResult<PageData<QmsInspectionStandardVO>> search(@Valid @RequestBody QmsInspectionStandardSearchQO request) {
return ApiResult.success(inspectionStandardControllerService.search(request));
}
/**
* 批量发布检验标准
*/
@PostMapping("publish")
public ApiResult<Void> publish(@Valid @RequestBody IdsQO request) {
inspectionStandardControllerService.publish(request.getIds());
return ApiResult.success();
}
/**
* 启用/禁用检验标准单条
*/
@PostMapping("enable")
public ApiResult<Void> enable(@Valid @RequestBody EnableQO request) {
inspectionStandardControllerService.enable(request.getId(), request.getEnable());
return ApiResult.success();
}
}

View File

@ -0,0 +1,33 @@
package com.nflg.qms.admin.controller;
import com.nflg.wms.common.pojo.ApiResult;
import com.nflg.wms.common.pojo.qo.QmsQcMaterialCategorySearchQO;
import com.nflg.wms.common.pojo.vo.QmsQcMaterialCategoryVO;
import com.nflg.wms.repository.service.IQmsQcMaterialCategoryService;
import com.nflg.wms.starter.BaseController;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 质检物料类别管理
*/
@RestController
@RequestMapping("/qcMaterialCategory")
public class QmsQcMaterialCategoryController extends BaseController {
@Resource
private IQmsQcMaterialCategoryService qcMaterialCategoryService;
/**
* 查询质检物料类别树支持模糊查询不分页
*/
@PostMapping("search")
public ApiResult<List<QmsQcMaterialCategoryVO>> search(@RequestBody QmsQcMaterialCategorySearchQO request) {
return ApiResult.success(qcMaterialCategoryService.searchTree(request));
}
}

View File

@ -0,0 +1,60 @@
package com.nflg.qms.admin.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nflg.wms.common.pojo.PageData;
import com.nflg.wms.common.pojo.qo.QmsInspectionStandardSearchQO;
import com.nflg.wms.common.pojo.vo.QmsInspectionStandardVO;
import com.nflg.wms.repository.mapper.QmsInspectionStandardMapper;
import com.nflg.wms.repository.service.IQmsInspectionStandardService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 检验标准业务逻辑
*/
@Slf4j
@Component
public class QmsInspectionStandardControllerService {
@Resource
private IQmsInspectionStandardService inspectionStandardService;
@Resource
private QmsInspectionStandardMapper inspectionStandardMapper;
/**
* 分页查询检验标准
*/
public PageData<QmsInspectionStandardVO> search(QmsInspectionStandardSearchQO request) {
IPage<QmsInspectionStandardVO> page = inspectionStandardMapper.searchPage(
request, new Page<>(request.getPage(), request.getPageSize()));
PageData<QmsInspectionStandardVO> result = new PageData<>();
result.setPage(request.getPage());
result.setPageSize(request.getPageSize());
result.setTotal((int) page.getTotal());
result.setItems(page.getRecords());
return result;
}
/**
* 批量发布检验标准
* @param ids 检验标准ID列表
*/
public void publish(List<Long> ids) {
inspectionStandardService.publish(ids);
}
/**
* 启用/禁用检验标准单条
* @param id 检验标准ID
* @param enable 是否启用
*/
public void enable(Long id, Boolean enable) {
inspectionStandardService.enable(id, enable);
}
}

View File

@ -0,0 +1,329 @@
package com.nflg.qms.admin;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.nflg.wms.common.pojo.ApiResult;
import com.nflg.wms.common.pojo.qo.QmsQcMaterialCategorySearchQO;
import com.nflg.wms.common.pojo.vo.QmsQcMaterialCategoryVO;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import java.util.List;
/**
* QMS 质检物料类别模块接口测试
* <p>
* 测试前提
* 1. qms-admin 服务已启动默认 http://localhost:8105
* 2. 测试账号已登录将有效的 token 填入 TOKEN 常量
* 3. 数据库中已存在质检物料类别数据
* </p>
*/
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class QmsQcMaterialCategoryApiTest {
// ===================== 配置区 =====================
/** 服务地址 */
private static final String BASE_URL = "http://localhost:8105";
/** 当前登录用户的 token */
private static final String TOKEN = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOjEsInJuU3RyIjoidVFwSWM2R3RJeUoxcFNSczBadzJzb1hvMUZLZXB3czkiLCJuYW1lIjoi6LaF57qn566h55CG5ZGYIiwiY29kZSI6ImFkbWluIiwicm9sZXMiOlsiU3VwZXJBZG1pbiJdLCJ0eXBlIjoxfQ.FtQ2uVwvuxsjAFbXnB006hV1pODtRhZT0z_9nfuR0So";
// ===================== 配置区结束 =====================
// ==================== HTTP 工具方法 ====================
private static <T> ApiResult<T> post(String path, Object body, TypeReference<ApiResult<T>> typeRef) {
String url = BASE_URL + path;
String reqBody = body == null ? "" : JSONUtil.toJsonStr(body);
HttpResponse resp = HttpRequest.post(url)
.header("authorization", TOKEN)
.header("Content-Type", "application/json")
.body(reqBody)
.execute();
String raw = resp.body();
System.out.println("[POST] " + path);
System.out.println(" 请求: " + reqBody);
System.out.println(" 响应: " + raw);
return JSONUtil.toBean(raw, typeRef, false);
}
private static <T> void assertSuccess(ApiResult<T> result, String msg) {
Assert.isTrue(result != null && result.getCode() == 200,
() -> new RuntimeException(msg + " => " + JSONUtil.toJsonStr(result)));
}
// ==================== 查询类别树接口测试 ====================
/**
* 查询质检物料类别树正常查询全部类别
* 验证点
* 1. 接口返回成功
* 2. 返回树形结构数据
* 3. 根节点的parentCategoryRowId为null或0
*/
@Test
@Order(1)
public void test01_searchCategory_All() {
QmsQcMaterialCategorySearchQO request = new QmsQcMaterialCategorySearchQO();
ApiResult<List<QmsQcMaterialCategoryVO>> result = post("/qcMaterialCategory/search", request, new TypeReference<>() {});
assertSuccess(result, "查询全部类别失败");
List<QmsQcMaterialCategoryVO> categories = result.getResult();
System.out.println(" ✅ 查询全部类别成功,返回树节点数: " + categories.size());
// 验证树形结构
if (!categories.isEmpty()) {
verifyTreeStructure(categories, "根节点");
}
}
/**
* 查询质检物料类别树按类别名称模糊查询
* 验证点
* 1. 接口返回成功
* 2. 返回包含匹配名称的类别
* 3. 匹配节点的祖先节点也被返回保证树形完整
*/
@Test
@Order(2)
public void test02_searchCategory_ByCategoryName() {
QmsQcMaterialCategorySearchQO request = new QmsQcMaterialCategorySearchQO();
request.setCategoryName("测试");
ApiResult<List<QmsQcMaterialCategoryVO>> result = post("/qcMaterialCategory/search", request, new TypeReference<>() {});
assertSuccess(result, "按类别名称查询失败");
List<QmsQcMaterialCategoryVO> categories = result.getResult();
System.out.println(" ✅ 按类别名称查询成功,返回树节点数: " + categories.size());
// 验证返回的树中包含名称匹配的节点
if (!categories.isEmpty()) {
boolean hasMatchedNode = hasNodeMatchedByName(categories, "测试");
Assert.isTrue(hasMatchedNode, () -> new RuntimeException("未找到名称包含'测试'的节点"));
System.out.println(" ✅ 验证通过:返回结果包含名称匹配的节点");
}
}
/**
* 查询质检物料类别树按类别编号模糊查询
* 验证点
* 1. 接口返回成功
* 2. 返回包含匹配编号的类别
* 3. 匹配节点的祖先节点也被返回保证树形完整
*/
@Test
@Order(3)
public void test03_searchCategory_ByCategoryCode() {
QmsQcMaterialCategorySearchQO request = new QmsQcMaterialCategorySearchQO();
request.setCategoryCode("CAT");
ApiResult<List<QmsQcMaterialCategoryVO>> result = post("/qcMaterialCategory/search", request, new TypeReference<>() {});
assertSuccess(result, "按类别编号查询失败");
List<QmsQcMaterialCategoryVO> categories = result.getResult();
System.out.println(" ✅ 按类别编号查询成功,返回树节点数: " + categories.size());
// 验证返回的树中包含编号匹配的节点
if (!categories.isEmpty()) {
boolean hasMatchedNode = hasNodeMatchedCode(categories, "CAT");
Assert.isTrue(hasMatchedNode, () -> new RuntimeException("未找到编号包含'CAT'的节点"));
System.out.println(" ✅ 验证通过:返回结果包含编号匹配的节点");
}
}
/**
* 查询质检物料类别树同时按名称和编号模糊查询
* 验证点
* 1. 接口返回成功
* 2. 返回同时满足名称和编号条件的类别
* 3. 匹配节点的祖先节点也被返回
*/
@Test
@Order(4)
public void test04_searchCategory_ByNameAndCode() {
QmsQcMaterialCategorySearchQO request = new QmsQcMaterialCategorySearchQO();
request.setCategoryName("测试");
request.setCategoryCode("CAT");
ApiResult<List<QmsQcMaterialCategoryVO>> result = post("/qcMaterialCategory/search", request, new TypeReference<>() {});
assertSuccess(result, "按名称和编号联合查询失败");
List<QmsQcMaterialCategoryVO> categories = result.getResult();
System.out.println(" ✅ 按名称和编号联合查询成功,返回树节点数: " + categories.size());
// 验证树形结构
if (!categories.isEmpty()) {
verifyTreeStructure(categories, "根节点");
}
}
/**
* 查询质检物料类别树查询不存在的类别名称
* 验证点
* 1. 接口返回成功
* 2. 返回空列表
*/
@Test
@Order(5)
public void test05_searchCategory_NoMatchName() {
QmsQcMaterialCategorySearchQO request = new QmsQcMaterialCategorySearchQO();
request.setCategoryName("不存在的类别名称_xyz_123");
ApiResult<List<QmsQcMaterialCategoryVO>> result = post("/qcMaterialCategory/search", request, new TypeReference<>() {});
assertSuccess(result, "查询不存在的类别名称失败");
List<QmsQcMaterialCategoryVO> categories = result.getResult();
Assert.isTrue(categories.isEmpty(), () -> new RuntimeException("查询不存在的类别应返回空列表"));
System.out.println(" ✅ 查询不存在的类别名称成功,返回空列表");
}
/**
* 查询质检物料类别树查询不存在的类别编号
* 验证点
* 1. 接口返回成功
* 2. 返回空列表
*/
@Test
@Order(6)
public void test06_searchCategory_NoMatchCode() {
QmsQcMaterialCategorySearchQO request = new QmsQcMaterialCategorySearchQO();
request.setCategoryCode("不存在的编号_XYZ_999");
ApiResult<List<QmsQcMaterialCategoryVO>> result = post("/qcMaterialCategory/search", request, new TypeReference<>() {});
assertSuccess(result, "查询不存在的类别编号失败");
List<QmsQcMaterialCategoryVO> categories = result.getResult();
Assert.isTrue(categories.isEmpty(), () -> new RuntimeException("查询不存在的类别编号应返回空列表"));
System.out.println(" ✅ 查询不存在的类别编号成功,返回空列表");
}
/**
* 查询质检物料类别树空字符串查询条件
* 验证点
* 1. 接口返回成功
* 2. 返回全部类别树
*/
@Test
@Order(7)
public void test07_searchCategory_EmptyCondition() {
QmsQcMaterialCategorySearchQO request = new QmsQcMaterialCategorySearchQO();
request.setCategoryName("");
request.setCategoryCode("");
ApiResult<List<QmsQcMaterialCategoryVO>> result = post("/qcMaterialCategory/search", request, new TypeReference<>() {});
assertSuccess(result, "空条件查询失败");
List<QmsQcMaterialCategoryVO> categories = result.getResult();
System.out.println(" ✅ 空条件查询成功,返回树节点数: " + categories.size());
// 验证树形结构
if (!categories.isEmpty()) {
verifyTreeStructure(categories, "根节点");
}
}
/**
* 查询质检物料类别树验证返回的树形结构完整性
* 验证点
* 1. 每个节点的children字段正确设置
* 2. 叶子节点的children为null或空列表
* 3. 非叶子节点的children包含子节点
*/
@Test
@Order(8)
public void test08_searchCategory_VerifyTreeIntegrity() {
QmsQcMaterialCategorySearchQO request = new QmsQcMaterialCategorySearchQO();
ApiResult<List<QmsQcMaterialCategoryVO>> result = post("/qcMaterialCategory/search", request, new TypeReference<>() {});
assertSuccess(result, "查询类别树失败");
List<QmsQcMaterialCategoryVO> categories = result.getResult();
System.out.println(" ✅ 开始验证树形结构完整性...");
if (!categories.isEmpty()) {
int[] stats = new int[2]; // [0]=总节点数, [1]=叶子节点数
verifyTreeIntegrity(categories, stats);
System.out.println(" ✅ 树形结构验证通过");
System.out.println(" 总节点数: " + stats[0]);
System.out.println(" 叶子节点数: " + stats[1]);
} else {
System.out.println(" ⚠️ 数据库中暂无类别数据,跳过验证");
}
}
// ==================== 辅助方法 ====================
/**
* 递归验证树形结构
*/
private void verifyTreeStructure(List<QmsQcMaterialCategoryVO> nodes, String parentName) {
for (QmsQcMaterialCategoryVO node : nodes) {
System.out.println(" - " + parentName + " -> " + node.getCategoryName()
+ " (编码: " + node.getCategoryCode() + ", ID: " + node.getId() + ")");
if (node.getChildren() != null && !node.getChildren().isEmpty()) {
verifyTreeStructure(node.getChildren(), node.getCategoryName());
}
}
}
/**
* 检查树中是否包含名称匹配的节点
*/
private boolean hasNodeMatchedByName(List<QmsQcMaterialCategoryVO> nodes, String keyword) {
for (QmsQcMaterialCategoryVO node : nodes) {
if (node.getCategoryName() != null && node.getCategoryName().contains(keyword)) {
return true;
}
if (node.getChildren() != null && !node.getChildren().isEmpty()) {
if (hasNodeMatchedByName(node.getChildren(), keyword)) {
return true;
}
}
}
return false;
}
/**
* 检查树中是否包含编号匹配的节点
*/
private boolean hasNodeMatchedCode(List<QmsQcMaterialCategoryVO> nodes, String keyword) {
for (QmsQcMaterialCategoryVO node : nodes) {
if (node.getCategoryCode() != null && node.getCategoryCode().contains(keyword)) {
return true;
}
if (node.getChildren() != null && !node.getChildren().isEmpty()) {
if (hasNodeMatchedCode(node.getChildren(), keyword)) {
return true;
}
}
}
return false;
}
/**
* 递归验证树的完整性并统计节点
*/
private void verifyTreeIntegrity(List<QmsQcMaterialCategoryVO> nodes, int[] stats) {
for (QmsQcMaterialCategoryVO node : nodes) {
stats[0]++; // 总节点数+1
boolean hasChildren = node.getChildren() != null && !node.getChildren().isEmpty();
if (hasChildren) {
// 非叶子节点继续递归验证子节点
verifyTreeIntegrity(node.getChildren(), stats);
} else {
// 叶子节点
stats[1]++; // 叶子节点数+1
Assert.isNull(node.getChildren(),
() -> new RuntimeException("叶子节点的children应该为null但节点ID=" + node.getId()));
}
}
}
}

View File

@ -0,0 +1,16 @@
package com.nflg.wms.common.pojo.qo;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.util.List;
/**
* 批量ID请求参数
*/
@Data
public class IdsQO {
@NotEmpty(message = "ID列表不能为空")
private List<Long> ids;
}

View File

@ -0,0 +1,27 @@
package com.nflg.wms.common.pojo.qo;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 检验标准搜索请求参数
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class QmsInspectionStandardSearchQO extends PageQO {
/**
* 物料编号模糊匹配
*/
private String materialNo;
/**
* 物料类别编码模糊匹配
*/
private String materialCategoryCode;
/**
* 所属IQE姓名模糊匹配
*/
private String iqeName;
}

View File

@ -0,0 +1,20 @@
package com.nflg.wms.common.pojo.qo;
import lombok.Data;
/**
* 查询质检物料分类参数
*/
@Data
public class QmsQcMaterialCategorySearchQO {
/**
* 类别名称模糊匹配
*/
private String categoryName;
/**
* 类别编号模糊匹配
*/
private String categoryCode;
}

View File

@ -0,0 +1,97 @@
package com.nflg.wms.common.pojo.vo;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 检验标准搜索结果VO
*/
@Data
public class QmsInspectionStandardVO {
/**
* 检验标准ID
*/
private Long id;
/**
* 物料编号
*/
private String materialNo;
/**
* 物料类别
*/
private String materialCategoryCodePathName;
/**
* 物料描述
*/
private String materialDesc;
/**
* 图号版本号
*/
private String drawingNoVer;
/**
* 检测版本号
*/
private String versionNo;
/**
* 所属IQE
*/
private String iqeName;
/**
* 检测周期
*/
private Integer inspectionCycle;
/**
* 包装类型ID
*/
private Long packagingMethodId;
/**
* 启用状态
*/
private Boolean isEnabled;
/**
* 发布状态0-未发布1-已发布
*/
private Short publishStatus;
/**
* 发布人
*/
private String publishUserName;
/**
* 发布时间
*/
private LocalDateTime publishTime;
/**
* 创建人姓名
*/
private String createUserName;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新人姓名
*/
private String updateUserName;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,42 @@
package com.nflg.wms.common.pojo.vo;
import lombok.Data;
import java.util.List;
/**
* 质检物料分类 VO
*/
@Data
public class QmsQcMaterialCategoryVO {
/**
* 分类ID
*/
private Long id;
/**
* 分类编码
*/
private String categoryCode;
/**
* 分类名称
*/
private String categoryName;
/**
* 父级分类ID
*/
private Long parentCategoryRowId;
/**
* 父级树路径ltree类型
*/
private String parentTree;
/**
* 子节点列表树形结构
*/
private List<QmsQcMaterialCategoryVO> children;
}

View File

@ -0,0 +1,113 @@
package com.nflg.wms.repository.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 检验标准
*/
@Getter
@Setter
@ToString
@Accessors(chain = true)
@TableName("qms_inspection_standard")
public class QmsInspectionStandard implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**
* 物料ID
*/
private Long materialId;
/**
* 检验任务项ID
*/
private Long inspectionTaskItemId;
/**
* 图纸URL
*/
private String drawingUrl;
/**
* 版本号
*/
private String versionNo;
/**
* 是否启用
*/
private Boolean isEnabled;
/**
* 包装方式ID
*/
private Long packagingMethodId;
/**
* 检验周期
*/
private Integer inspectionCycle;
/**
* 发布状态0-未发布1-已发布
*/
private Short publishStatus;
/**
* 发布人ID
*/
private Long publishUserId;
/**
* 发布人姓名
*/
private String publishUserName;
/**
* 发布时间
*/
private LocalDateTime publishTime;
/**
* 创建人ID
*/
private Long createUserId;
/**
* 创建人姓名
*/
private String createUserName;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新人ID
*/
private Long updateUserId;
/**
* 更新人姓名
*/
private String updateUserName;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,113 @@
package com.nflg.wms.repository.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 检验标准项
*/
@Getter
@Setter
@ToString
@Accessors(chain = true)
@TableName("qms_inspection_standard_item")
public class QmsInspectionStandardItem implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**
* 检验标准ID
*/
private Long inspectionStandardId;
/**
* 检测项名称
*/
private String name;
/**
* 排序号
*/
private Integer sortNo;
/**
* 检测方式关联字典项id字典编码InspectionStandardTestingMethod
*/
private Long testingMethodDictItemId;
/**
* 抽样方式关联字典项id字典编码InspectionStandardSamplingMethod
*/
private Long samplingMethodDictItemId;
/**
* 抽样方案ID
*/
private Long samplingPlanId;
/**
* 检验水平关联字典项id字典编码SamplingPlanSpecialInspection或SamplingPlanGeneralInspection
*/
private Long inspectionLevelDictItemId;
/**
* AQL值关联AQL优先值预定义表id
*/
private Long aqlPriorityValueId;
/**
* AQL类型关联字典项id字典编码InspectionStandardSQLType
*/
private Long aqlTypeDictItemId;
/**
* 检验标准项类型0-标准检测项1-尺寸检测项
*/
private Short itemType;
/**
* PDF图纸
*/
private String pdfDrawing;
/**
* 创建人ID
*/
private Long createUserId;
/**
* 创建人姓名
*/
private String createUserName;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新人ID
*/
private Long updateUserId;
/**
* 更新人姓名
*/
private String updateUserName;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,93 @@
package com.nflg.wms.repository.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 检验标准项内容
*/
@Getter
@Setter
@ToString
@Accessors(chain = true)
@TableName("qms_inspection_standard_item_content")
public class QmsInspectionStandardItemContent implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**
* 检验标准项ID
*/
private Long inspectionStandardItemId;
/**
* 排序号
*/
private Integer sortNo;
/**
* 检测项名称
*/
private String name;
/**
* 检测标准
*/
private String testStandard;
/**
* 图例
*/
private String legend;
/**
* PDF信息
*/
private String pdfInfo;
/**
* 判定类型关联字典项id字典编码InspectionStandardJudgmentType
*/
private Long judgmentTypeDictItemId;
/**
* 创建人ID
*/
private Long createUserId;
/**
* 创建人姓名
*/
private String createUserName;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新人ID
*/
private Long updateUserId;
/**
* 更新人姓名
*/
private String updateUserName;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,20 @@
package com.nflg.wms.repository.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nflg.wms.common.pojo.qo.QmsInspectionStandardSearchQO;
import com.nflg.wms.common.pojo.vo.QmsInspectionStandardVO;
import com.nflg.wms.repository.entity.QmsInspectionStandard;
import org.apache.ibatis.annotations.Param;
/**
* 检验标准 Mapper
*/
public interface QmsInspectionStandardMapper extends BaseMapper<QmsInspectionStandard> {
/**
* 分页查询检验标准
*/
IPage<QmsInspectionStandardVO> searchPage(@Param("request") QmsInspectionStandardSearchQO request, Page<QmsInspectionStandardVO> page);
}

View File

@ -0,0 +1,25 @@
package com.nflg.wms.repository.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.nflg.wms.repository.entity.QmsInspectionStandard;
import java.util.List;
/**
* 检验标准 服务类
*/
public interface IQmsInspectionStandardService extends IService<QmsInspectionStandard> {
/**
* 批量发布检验标准
* @param ids 检验标准ID列表
*/
void publish(List<Long> ids);
/**
* 启用/禁用检验标准单条
* @param id 检验标准ID
* @param enable 是否启用
*/
void enable(Long id, Boolean enable);
}

View File

@ -1,10 +1,22 @@
package com.nflg.wms.repository.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.nflg.wms.common.pojo.qo.QmsQcMaterialCategorySearchQO;
import com.nflg.wms.common.pojo.vo.QmsQcMaterialCategoryVO;
import com.nflg.wms.repository.entity.QmsQcMaterialCategory;
import java.util.List;
/**
* 质检物料分类 服务类
*/
public interface IQmsQcMaterialCategoryService extends IService<QmsQcMaterialCategory> {
/**
* 查询质检物料分类树支持模糊查询不分页
*
* @param request 查询条件
* @return 树形结构列表
*/
List<QmsQcMaterialCategoryVO> searchTree(QmsQcMaterialCategorySearchQO request);
}

View File

@ -0,0 +1,57 @@
package com.nflg.wms.repository.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nflg.wms.common.util.UserUtil;
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 java.time.LocalDateTime;
import java.util.List;
/**
* 检验标准 服务实现类
*/
@Service
public class QmsInspectionStandardServiceImpl extends ServiceImpl<QmsInspectionStandardMapper, QmsInspectionStandard>
implements IQmsInspectionStandardService {
@Override
public void publish(List<Long> ids) {
if (ids == null || ids.isEmpty()) {
return;
}
Long userId = UserUtil.getUserId();
String userName = UserUtil.getUserName();
LocalDateTime now = LocalDateTime.now();
lambdaUpdate()
.eq(QmsInspectionStandard::getPublishStatus, (short) 0)
.in(QmsInspectionStandard::getId, ids)
.set(QmsInspectionStandard::getPublishStatus, (short) 1)
.set(QmsInspectionStandard::getPublishUserId, userId)
.set(QmsInspectionStandard::getPublishUserName, userName)
.set(QmsInspectionStandard::getPublishTime, now)
.set(QmsInspectionStandard::getUpdateUserId, userId)
.set(QmsInspectionStandard::getUpdateUserName, userName)
.set(QmsInspectionStandard::getUpdateTime, now)
.update();
}
@Override
public void enable(Long id, Boolean enable) {
Long userId = UserUtil.getUserId();
String userName = UserUtil.getUserName();
LocalDateTime now = LocalDateTime.now();
lambdaUpdate()
.eq(QmsInspectionStandard::getIsEnabled, !enable)
.eq(QmsInspectionStandard::getId, id)
.set(QmsInspectionStandard::getIsEnabled, enable)
.set(QmsInspectionStandard::getUpdateUserId, userId)
.set(QmsInspectionStandard::getUpdateUserName, userName)
.set(QmsInspectionStandard::getUpdateTime, now)
.update();
}
}

View File

@ -1,15 +1,94 @@
package com.nflg.wms.repository.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nflg.wms.common.pojo.qo.QmsQcMaterialCategorySearchQO;
import com.nflg.wms.common.pojo.vo.QmsQcMaterialCategoryVO;
import com.nflg.wms.repository.entity.QmsQcMaterialCategory;
import com.nflg.wms.repository.mapper.QmsQcMaterialCategoryMapper;
import com.nflg.wms.repository.service.IQmsQcMaterialCategoryService;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 质检物料分类 服务实现类
*/
@Service
public class QmsQcMaterialCategoryServiceImpl extends ServiceImpl<QmsQcMaterialCategoryMapper, QmsQcMaterialCategory>
implements IQmsQcMaterialCategoryService {
@Override
public List<QmsQcMaterialCategoryVO> searchTree(QmsQcMaterialCategorySearchQO request) {
// 查询所有分类
List<QmsQcMaterialCategory> all = this.lambdaQuery()
.orderByAsc(QmsQcMaterialCategory::getCategoryCode)
.list();
// 按条件过滤
List<QmsQcMaterialCategory> filteredList = all;
if (StrUtil.isNotBlank(request.getCategoryName()) || StrUtil.isNotBlank(request.getCategoryCode())) {
// 有条件时过滤匹配节点并补全祖先
Map<Long, QmsQcMaterialCategory> idMap = all.stream()
.collect(Collectors.toMap(QmsQcMaterialCategory::getId, c -> c));
List<QmsQcMaterialCategory> matched = all.stream()
.filter(c -> {
boolean nameMatch = StrUtil.isBlank(request.getCategoryName())
|| c.getCategoryName().contains(request.getCategoryName());
boolean codeMatch = StrUtil.isBlank(request.getCategoryCode())
|| c.getCategoryCode().contains(request.getCategoryCode());
return nameMatch && codeMatch;
})
.collect(Collectors.toList());
Set<Long> visibleIds = new HashSet<>();
for (QmsQcMaterialCategory node : matched) {
QmsQcMaterialCategory cur = node;
while (cur != null) {
visibleIds.add(cur.getId());
cur = cur.getParentCategoryRowId() != null && cur.getParentCategoryRowId() > 0
? idMap.get(cur.getParentCategoryRowId())
: null;
}
}
filteredList = all.stream()
.filter(c -> visibleIds.contains(c.getId()))
.collect(Collectors.toList());
}
// VO
List<QmsQcMaterialCategoryVO> voList = filteredList.stream()
.map(c -> BeanUtil.copyProperties(c, QmsQcMaterialCategoryVO.class))
.collect(Collectors.toList());
// 构建树形结构根节点的parentCategoryRowId为null或0
return buildTree(voList, null);
}
/**
* 递归构建树形结构
*/
private List<QmsQcMaterialCategoryVO> buildTree(List<QmsQcMaterialCategoryVO> all, Long parentId) {
List<QmsQcMaterialCategoryVO> result = new ArrayList<>();
for (QmsQcMaterialCategoryVO vo : all) {
boolean isRoot = parentId == null
? (vo.getParentCategoryRowId() == null || vo.getParentCategoryRowId() == 0)
: Objects.equals(vo.getParentCategoryRowId(), parentId);
if (isRoot) {
List<QmsQcMaterialCategoryVO> children = buildTree(all, vo.getId());
vo.setChildren(children.isEmpty() ? null : children);
result.add(vo);
}
}
return result;
}
}

View File

@ -0,0 +1,50 @@
<?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.QmsInspectionStandardMapper">
<!--
分页查询检验标准
支持动态过滤:物料编号模糊(materialNo)、物料类别编码模糊(materialCategoryCode)、所属IQE姓名模糊(iqeName)
一个物料可对应多个IQE使用STRING_AGG合并显示
-->
<select id="searchPage" resultType="com.nflg.wms.common.pojo.vo.QmsInspectionStandardVO">
SELECT
s.id,
m.material_no AS materialNo,
m.material_category_code_path_name AS materialCategoryCodePathName,
m.material_desc AS materialDesc,
m.drawing_no_ver AS drawingNoVer,
s.version_no AS versionNo,
STRING_AGG(DISTINCT iqe_user.user_name, ',') AS iqeName,
s.inspection_cycle AS inspectionCycle,
s.packaging_method_id AS packagingMethodId,
s.is_enabled AS isEnabled,
s.publish_status AS publishStatus,
s.publish_user_name AS publishUserName,
s.publish_time AS publishTime,
s.create_user_name AS createUserName,
s.create_time AS createTime,
s.update_user_name AS updateUserName,
s.update_time AS updateTime
FROM qms_inspection_standard s
LEFT JOIN qms_qc_material m ON s.material_id = m.id
LEFT JOIN qms_quality_inspector iqe ON m.id = iqe.material_id AND iqe.inspection_type = 1 AND iqe.enable = true
LEFT JOIN "user" iqe_user ON iqe.user_id = iqe_user.id
<where>
<if test="request.materialNo != null and request.materialNo != ''">
AND m.material_no ilike concat('%', #{request.materialNo}, '%')
</if>
<if test="request.materialCategoryCode != null and request.materialCategoryCode != ''">
AND m.material_category_code ilike concat('%', #{request.materialCategoryCode}, '%')
</if>
<if test="request.iqeName != null and request.iqeName != ''">
AND iqe_user.user_name ilike concat('%', #{request.iqeName}, '%')
</if>
</where>
GROUP BY s.id, m.material_no, m.material_category_code_path_name, m.material_desc, m.drawing_no_ver,
s.version_no, s.inspection_cycle, s.packaging_method_id, s.is_enabled, s.publish_status,
s.publish_user_name, s.publish_time, s.create_user_name, s.create_time, s.update_user_name, s.update_time
ORDER BY s.id DESC
</select>
</mapper>