add(qms): 新增不合格品评审(内含PDA方法待修改)

master
zch 5 days ago
parent 688635ef01
commit 3521daebab

@ -0,0 +1,129 @@
package org.dromara.qms.controller;
import java.util.List;
import java.util.ArrayList;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.qms.domain.vo.QcUnqualifiedRecordVo;
import org.dromara.qms.domain.bo.QcUnqualifiedRecordBo;
import org.dromara.qms.service.IQcUnqualifiedRecordService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
*
* 访:/qms/qcUnqualifiedRecord
*
* @author zch
* @date 2025-07-18
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/qcUnqualifiedRecord")
public class QcUnqualifiedRecordController extends BaseController {
private final IQcUnqualifiedRecordService qcUnqualifiedRecordService;
/**
*
*/
@SaCheckPermission("qms:qcUnqualifiedRecord:list")
@GetMapping("/list")
public TableDataInfo<QcUnqualifiedRecordVo> list(QcUnqualifiedRecordBo bo, PageQuery pageQuery) {
return qcUnqualifiedRecordService.queryPageList(bo, pageQuery);
}
/**
*
*/
@SaCheckPermission("qms:qcUnqualifiedRecord:export")
@Log(title = "不合格品评审记录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(QcUnqualifiedRecordBo bo, HttpServletResponse response) {
List<QcUnqualifiedRecordVo> list = qcUnqualifiedRecordService.queryList(bo);
ExcelUtil.exportExcel(list, "不合格品评审记录", QcUnqualifiedRecordVo.class, response);
}
/**
*
*/
@SaCheckPermission("qms:qcUnqualifiedRecord:export")
@Log(title = "不合格品评审记录", businessType = BusinessType.EXPORT)
@PostMapping("/exportTemplate")
public void exportTemplate(QcUnqualifiedRecordBo bo, HttpServletResponse response) {
List<QcUnqualifiedRecordVo> list = new ArrayList<>();
ExcelUtil.exportExcel(list, "不合格品评审记录", QcUnqualifiedRecordVo.class, response);
}
/**
*
*
* @param recordId
*/
@SaCheckPermission("qms:qcUnqualifiedRecord:query")
@GetMapping("/{recordId}")
public R<QcUnqualifiedRecordVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long recordId) {
return R.ok(qcUnqualifiedRecordService.queryById(recordId));
}
/**
*
*/
@SaCheckPermission("qms:qcUnqualifiedRecord:add")
@Log(title = "不合格品评审记录", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody QcUnqualifiedRecordBo bo) {
return toAjax(qcUnqualifiedRecordService.insertByBo(bo));
}
/**
*
*/
@SaCheckPermission("qms:qcUnqualifiedRecord:edit")
@Log(title = "不合格品评审记录", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody QcUnqualifiedRecordBo bo) {
return toAjax(qcUnqualifiedRecordService.updateByBo(bo));
}
/**
*
*
* @param recordIds
*/
@SaCheckPermission("qms:qcUnqualifiedRecord:remove")
@Log(title = "不合格品评审记录", businessType = BusinessType.DELETE)
@DeleteMapping("/{recordIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] recordIds) {
return toAjax(qcUnqualifiedRecordService.deleteWithValidByIds(List.of(recordIds), true));
}
/**
*
*/
@GetMapping("/getQcUnqualifiedRecordList")
public R<List<QcUnqualifiedRecordVo>> getQcUnqualifiedRecordList(QcUnqualifiedRecordBo bo) {
List<QcUnqualifiedRecordVo> list = qcUnqualifiedRecordService.queryList(bo);
return R.ok(list);
}
}

@ -0,0 +1,129 @@
package org.dromara.qms.controller;
import java.util.List;
import java.util.ArrayList;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.qms.domain.vo.QcUnqualifiedReviewVo;
import org.dromara.qms.domain.bo.QcUnqualifiedReviewBo;
import org.dromara.qms.service.IQcUnqualifiedReviewService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
*
* 访:/qms/qcUnqualifiedReview
*
* @author zch
* @date 2025-07-18
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/qcUnqualifiedReview")
public class QcUnqualifiedReviewController extends BaseController {
private final IQcUnqualifiedReviewService qcUnqualifiedReviewService;
/**
*
*/
@SaCheckPermission("qms:qcUnqualifiedReview:list")
@GetMapping("/list")
public TableDataInfo<QcUnqualifiedReviewVo> list(QcUnqualifiedReviewBo bo, PageQuery pageQuery) {
return qcUnqualifiedReviewService.queryPageList(bo, pageQuery);
}
/**
*
*/
@SaCheckPermission("qms:qcUnqualifiedReview:export")
@Log(title = "不合格品待评审", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(QcUnqualifiedReviewBo bo, HttpServletResponse response) {
List<QcUnqualifiedReviewVo> list = qcUnqualifiedReviewService.queryList(bo);
ExcelUtil.exportExcel(list, "不合格品待评审", QcUnqualifiedReviewVo.class, response);
}
/**
*
*/
@SaCheckPermission("qms:qcUnqualifiedReview:export")
@Log(title = "不合格品待评审", businessType = BusinessType.EXPORT)
@PostMapping("/exportTemplate")
public void exportTemplate(QcUnqualifiedReviewBo bo, HttpServletResponse response) {
List<QcUnqualifiedReviewVo> list = new ArrayList<>();
ExcelUtil.exportExcel(list, "不合格品待评审", QcUnqualifiedReviewVo.class, response);
}
/**
*
*
* @param reviewId
*/
@SaCheckPermission("qms:qcUnqualifiedReview:query")
@GetMapping("/{reviewId}")
public R<QcUnqualifiedReviewVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long reviewId) {
return R.ok(qcUnqualifiedReviewService.queryById(reviewId));
}
/**
*
*/
@SaCheckPermission("qms:qcUnqualifiedReview:add")
@Log(title = "不合格品待评审", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody QcUnqualifiedReviewBo bo) {
return toAjax(qcUnqualifiedReviewService.insertByBo(bo));
}
/**
*
*/
@SaCheckPermission("qms:qcUnqualifiedReview:edit")
@Log(title = "不合格品待评审", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody QcUnqualifiedReviewBo bo) {
return toAjax(qcUnqualifiedReviewService.updateByBo(bo));
}
/**
*
*
* @param reviewIds
*/
@SaCheckPermission("qms:qcUnqualifiedReview:remove")
@Log(title = "不合格品待评审", businessType = BusinessType.DELETE)
@DeleteMapping("/{reviewIds}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] reviewIds) {
return toAjax(qcUnqualifiedReviewService.deleteWithValidByIds(List.of(reviewIds), true));
}
/**
*
*/
@GetMapping("/getQcUnqualifiedReviewList")
public R<List<QcUnqualifiedReviewVo>> getQcUnqualifiedReviewList(QcUnqualifiedReviewBo bo) {
List<QcUnqualifiedReviewVo> list = qcUnqualifiedReviewService.queryList(bo);
return R.ok(list);
}
}

@ -0,0 +1,47 @@
package org.dromara.qms.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* qc_unqualified_record
*
* @author zch
* @date 2025-07-18
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("qc_unqualified_record")
public class QcUnqualifiedRecord extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId(value = "record_id", type = IdType.ASSIGN_ID)
private Long recordId;
/**
* ID
*/
private Long reviewId;
/**
*
*/
private String remark;
/**
* 02
*/
@TableLogic
private String delFlag;
}

@ -0,0 +1,126 @@
package org.dromara.qms.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
/**
* qc_unqualified_review
*
* @author zch
* @date 2025-07-18
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("qc_unqualified_review")
public class QcUnqualifiedReview extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId(value = "review_id", type = IdType.ASSIGN_ID)
private Long reviewId;
/**
*
*/
private String unqualifiedNo;
/**
* ID
*/
private Long inspectionId;
/**
* ID
*/
private Long typeId;
/**
*
*/
private String workOrder;
/**
*
*/
private String processCode;
/**
*
*/
private String processName;
/**
*
*/
private String batchNo;
/**
*
*/
private String materialName;
/**
*
*/
private String materialCode;
/**
*
*/
private String inspectorResult;
/**
* 0/1/2退
*/
private String reviewResult;
/**
*
*/
private String reviewer;
/**
*
*/
private Date reviewTime;
/**
* 02
*/
@TableLogic
private String delFlag;
/**
* /
*/
@TableField(exist = false)
private String inspectionNo;//JOIN
/**
*
*/
@TableField(exist = false)
private String typeCode;//JOIN
/**
*
*/
@TableField(exist = false)
private String typeName;//JOIN
/**
* (
*/
@TableField(exist = false)
private Long qcInspectionType;//JOIN
}

@ -0,0 +1,75 @@
package org.dromara.qms.domain.bo;
import org.dromara.qms.domain.QcUnqualifiedRecord;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.util.Date;
/**
* qc_unqualified_record
*
* @author zch
* @date 2025-07-18
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = QcUnqualifiedRecord.class, reverseConvertGenerate = false)
public class QcUnqualifiedRecordBo extends BaseEntity {
/**
*
*/
private Long recordId;
/**
* ID
*/
private Long reviewId;
/**
*
*/
private String remark;
/**
* PDA
*/
private String reviewer;
/**
* PDA
*/
private Date startTime;
/**
* PDA
*/
private Date endTime;
/**
* PDA
*/
private String materialCode;
/**
* PDA
*/
private String materialName;
/**
* PDA
*/
private String reviewResult;
/**
* PDA
*/
private String unqualifiedNo;
}

@ -0,0 +1,116 @@
package org.dromara.qms.domain.bo;
import org.dromara.qms.domain.QcUnqualifiedReview;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* qc_unqualified_review
*
* @author zch
* @date 2025-07-18
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = QcUnqualifiedReview.class, reverseConvertGenerate = false)
public class QcUnqualifiedReviewBo extends BaseEntity {
/**
*
*/
private Long reviewId;
/**
*
*/
private String unqualifiedNo;
/**
* ID
*/
private Long inspectionId;
/**
* ID
*/
private Long typeId;
/**
*
*/
private String workOrder;
/**
*
*/
private String processCode;
/**
*
*/
private String processName;
/**
*
*/
private String batchNo;
/**
*
*/
private String materialName;
/**
*
*/
private String materialCode;
/**
*
*/
private String inspectorResult;
/**
* 0/1/2退
*/
private String reviewResult;
/**
*
*/
private String reviewer;
/**
*
*/
private Date reviewTime;
/**
* /
*/
private String inspectionNo;//JOIN
/**
*
*/
private String typeCode;//JOIN
/**
*
*/
private String typeName;//JOIN
/**
* (
*/
private Long qcInspectionType;//JOIN
}

@ -0,0 +1,195 @@
package org.dromara.qms.domain.vo;
import java.math.BigDecimal;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* - PDA
*
*
* @author zch
* @date 2025-07-18
*/
@Data
@ExcelIgnoreUnannotated
public class QcInspectionItemDetailVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
private Long itemId;
/**
*
*/
@ExcelProperty(value = "检测项编码")
private String itemCode;
/**
*
*/
@ExcelProperty(value = "检测项名称")
private String itemName;
/**
*
*/
@ExcelProperty(value = "检测位置")
private String location;
/**
*
*/
@ExcelProperty(value = "检测项目类别")
private String category;
/**
*
*/
@ExcelProperty(value = "检测方法")
private String method;
/**
*
*/
private String methodText;
/**
* 0,1
*/
@ExcelProperty(value = "检测方式", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "detect_type")
private Long detectType;
/**
* /
*/
private String detectTypeText;
/**
*
*/
@ExcelProperty(value = "检测结果")
private String result;
/**
* 使
*/
@ExcelProperty(value = "检测值")
private BigDecimal value;
/**
*
*/
@ExcelProperty(value = "控制上限")
private BigDecimal upperLimit;
/**
*
*/
@ExcelProperty(value = "控制下限")
private BigDecimal lowerLimit;
/**
*
*/
@ExcelProperty(value = "规格质检值")
private BigDecimal specValue;
/**
*
*/
@ExcelProperty(value = "规格上限")
private BigDecimal specUpperLimit;
/**
*
*/
@ExcelProperty(value = "规格下限")
private BigDecimal specLowerLimit;
/**
*
*/
@ExcelProperty(value = "检测项说明")
private String description;
/**
*
*/
private Boolean isRequired;
/**
*
*/
private Boolean isCompleted;
/**
* 0/1
*/
private Long resultStatus;
/**
* /
*/
private String resultStatusText;
/**
*
*/
private Boolean isOutOfControlLimit;
/**
*
*/
private Boolean isOutOfSpecLimit;
/**
* 使
*/
private String optionCode;
/**
*
*/
private String optionName;
/**
*
*/
private String isDefault;
/**
*
*/
private String inspector;
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date inspectionTime;
/**
*
*/
private Integer sortOrder;
/**
*
*/
private String remark;
}

@ -0,0 +1,136 @@
package org.dromara.qms.domain.vo;
import org.dromara.qms.domain.QcUnqualifiedRecord;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* qc_unqualified_record
*
* @author zch
* @date 2025-07-18
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = QcUnqualifiedRecord.class)
public class QcUnqualifiedRecordVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
@ExcelProperty(value = "记录主键")
private Long recordId;
/**
* ID
*/
@ExcelProperty(value = "关联待评审表ID")
private Long reviewId;
/**
*
*/
@ExcelProperty(value = "备注")
private String remark;
// PDA需要的关联信息来自QcUnqualifiedReview表
/**
*
*/
@ExcelProperty(value = "不合格检测单号")
private String unqualifiedNo;
/**
* ID
*/
@ExcelProperty(value = "关联质检主表ID")
private Long inspectionId;
/**
* /
*/
@ExcelProperty(value = "检测单号/卡号")
private String inspectionNo;
/**
*
*/
@ExcelProperty(value = "检测类型名称")
private String typeName;
/**
*
*/
@ExcelProperty(value = "派工单号")
private String workOrder;
/**
*
*/
@ExcelProperty(value = "工序名称")
private String processName;
/**
*
*/
@ExcelProperty(value = "批次号")
private String batchNo;
/**
*
*/
@ExcelProperty(value = "物料名称")
private String materialName;
/**
*
*/
@ExcelProperty(value = "物料编码")
private String materialCode;
/**
*
*/
@ExcelProperty(value = "质检员检测结果")
private String inspectorResult;
/**
* 0/1/2退/3/4
*/
@ExcelProperty(value = "评审结果")
@ExcelDictFormat(dictType = "qc_review_result")
private String reviewResult;
/**
*
*/
@ExcelProperty(value = "评审人")
private String reviewer;
/**
*
*/
@ExcelProperty(value = "评审时间")
private Date reviewTime;
/**
*
*/
@ExcelProperty(value = "创建时间")
private Date createTime;
}

@ -0,0 +1,141 @@
package org.dromara.qms.domain.vo;
import java.util.Date;
import java.util.List;
import java.math.BigDecimal;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.dromara.qms.domain.QcUnqualifiedReview;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* qc_unqualified_review
*
* @author zch
* @date 2025-07-18
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = QcUnqualifiedReview.class)
public class QcUnqualifiedReviewVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
@ExcelProperty(value = "评审主键")
private Long reviewId;
/**
*
*/
@ExcelProperty(value = "不合格检测单号")
private String unqualifiedNo;
/**
* ID
*/
@ExcelProperty(value = "关联质检主表ID")
private Long inspectionId;
/**
* ID
*/
@ExcelProperty(value = "检测类型ID")
private Long typeId;
/**
*
*/
@ExcelProperty(value = "派工单号")
private String workOrder;
/**
*
*/
@ExcelProperty(value = "工序编码")
private String processCode;
/**
*
*/
@ExcelProperty(value = "工序名称")
private String processName;
/**
*
*/
@ExcelProperty(value = "批次号")
private String batchNo;
/**
*
*/
@ExcelProperty(value = "物料名称")
private String materialName;
/**
*
*/
@ExcelProperty(value = "物料编码")
private String materialCode;
/**
*
*/
@ExcelProperty(value = "质检员检测结果")
private String inspectorResult;
/**
* 0/1/2退
*/
@ExcelProperty(value = "评审结果", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "review_result")
private String reviewResult;
/**
*
*/
@ExcelProperty(value = "评审人")
private String reviewer;
/**
*
*/
@ExcelProperty(value = "评审时间")
private Date reviewTime;
/**
* /
*/
private String inspectionNo;//JOIN
/**
*
*/
private String typeCode;//JOIN
/**
*
*/
private String typeName;//JOIN
/**
* (
*/
private Long qcInspectionType;//JOIN
}

@ -0,0 +1,34 @@
package org.dromara.qms.mapper;
import org.dromara.qms.domain.bo.QcUnqualifiedRecordBo;
import org.dromara.qms.domain.QcUnqualifiedRecord;
import org.dromara.qms.domain.vo.QcUnqualifiedRecordVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import java.util.List;
/**
* Mapper
*
* @author zch
* @date 2025-07-18
*/
public interface QcUnqualifiedRecordMapper extends BaseMapperPlus<QcUnqualifiedRecord, QcUnqualifiedRecordVo> {
/**
*
*
* @param bo
* @return
*/
List<QcUnqualifiedRecordVo> selectVoList(QcUnqualifiedRecordBo bo);
/**
*
*
* @param recordId
* @return
*/
QcUnqualifiedRecordVo selectVoByRecordId(Long recordId);
}

@ -0,0 +1,34 @@
package org.dromara.qms.mapper;
import org.dromara.qms.domain.bo.QcUnqualifiedReviewBo;
import org.dromara.qms.domain.QcUnqualifiedReview;
import org.dromara.qms.domain.vo.QcUnqualifiedReviewVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import java.util.List;
/**
* Mapper
*
* @author zch
* @date 2025-07-18
*/
public interface QcUnqualifiedReviewMapper extends BaseMapperPlus<QcUnqualifiedReview, QcUnqualifiedReviewVo> {
/**
*
*
* @param bo
* @return
*/
List<QcUnqualifiedReviewVo> selectVoList(QcUnqualifiedReviewBo bo);
/**
*
*
* @param reviewId
* @return
*/
QcUnqualifiedReviewVo selectVoByReviewId(Long reviewId);
}

@ -0,0 +1,96 @@
package org.dromara.qms.service;
import org.dromara.qms.domain.QcUnqualifiedRecord;
import org.dromara.qms.domain.vo.QcUnqualifiedRecordVo;
import org.dromara.qms.domain.bo.QcUnqualifiedRecordBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
/**
* Service
*
* @author zch
* @date 2025-07-18
*/
public interface IQcUnqualifiedRecordService {
/**
*
*
* @param recordId
* @return
*/
QcUnqualifiedRecordVo queryById(Long recordId);
/**
*
*
* @param bo
* @param pageQuery
* @return
*/
TableDataInfo<QcUnqualifiedRecordVo> queryPageList(QcUnqualifiedRecordBo bo, PageQuery pageQuery);
/**
*
*
* @param bo
* @return
*/
List<QcUnqualifiedRecordVo> queryList(QcUnqualifiedRecordBo bo);
/**
*
*
* @param bo
* @return
*/
Boolean insertByBo(QcUnqualifiedRecordBo bo);
/**
*
*
* @param bo
* @return
*/
Boolean updateByBo(QcUnqualifiedRecordBo bo);
/**
*
*
* @param ids
* @param isValid
* @return
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* PDA
*
* @param bo
* @param pageQuery
* @return
*/
TableDataInfo<QcUnqualifiedRecordVo> queryPageListWithDetails(QcUnqualifiedRecordBo bo, PageQuery pageQuery);
/**
* PDA
*
* @param reviewer
* @param pageQuery
* @return
*/
TableDataInfo<QcUnqualifiedRecordVo> queryPageUserRecords(String reviewer, PageQuery pageQuery);
/**
* PDA
*
* @param bo
* @param pageQuery
* @return
*/
TableDataInfo<QcUnqualifiedRecordVo> queryPageRecordsByDateRange(QcUnqualifiedRecordBo bo, PageQuery pageQuery);
}

@ -0,0 +1,101 @@
package org.dromara.qms.service;
import org.dromara.qms.domain.QcUnqualifiedReview;
import org.dromara.qms.domain.vo.QcUnqualifiedReviewVo;
import org.dromara.qms.domain.bo.QcUnqualifiedReviewBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* Service
*
* @author zch
* @date 2025-07-18
*/
public interface IQcUnqualifiedReviewService {
/**
*
*
* @param reviewId
* @return
*/
QcUnqualifiedReviewVo queryById(Long reviewId);
/**
*
*
* @param bo
* @param pageQuery
* @return
*/
TableDataInfo<QcUnqualifiedReviewVo> queryPageList(QcUnqualifiedReviewBo bo, PageQuery pageQuery);
/**
*
*
* @param bo
* @return
*/
List<QcUnqualifiedReviewVo> queryList(QcUnqualifiedReviewBo bo);
/**
*
*
* @param bo
* @return
*/
Boolean insertByBo(QcUnqualifiedReviewBo bo);
/**
*
*
* @param bo
* @return
*/
Boolean updateByBo(QcUnqualifiedReviewBo bo);
/**
*
*
* @param ids
* @param isValid
* @return
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* (for PDA)
*/
TableDataInfo<QcUnqualifiedReviewVo> queryPagePendingReviews(QcUnqualifiedReviewBo bo, PageQuery pageQuery);
/**
* (for PDA)
*/
QcUnqualifiedReviewVo queryByIdWithItems(Long reviewId);
/**
* (for PDA),
*/
Boolean submitReview(QcUnqualifiedReviewBo bo);
/**
* (for PDA)
*
* @param dateRange
* @return
*/
Map<String, Object> getUnqualifiedSummary(String dateRange);
/**
* (for PDA)
*
* @param bo
* @return
*/
Boolean triggerWorkflowProcess(QcUnqualifiedReviewBo bo);
}

@ -0,0 +1,278 @@
package org.dromara.qms.service.impl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.qms.domain.bo.QcUnqualifiedReviewBo;
import org.dromara.qms.domain.vo.QcInspectionMainVo;
import org.dromara.qms.domain.vo.QcInspectionItemDetailVo;
import org.dromara.qms.service.IQcUnqualifiedReviewService;
import org.dromara.qms.utils.QcInspectionResultCalculator;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
*
*
*
* @author zch
* @date 2025-07-18
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class QcUnqualifiedGeneratorService {
private final IQcUnqualifiedReviewService qcUnqualifiedReviewService;
/**
*
*
*
* @param inspectionVo
* @param inspectionItems
* @return
*/
public Boolean autoGenerateUnqualifiedReview(QcInspectionMainVo inspectionVo, List<QcInspectionItemDetailVo> inspectionItems) {
if (inspectionVo == null) {
log.error("质检主表数据为空,无法生成不合格品评审任务");
return false;
}
// 检查是否存在不合格项
List<QcInspectionItemDetailVo> unqualifiedItems = getUnqualifiedItems(inspectionItems);
if (unqualifiedItems.isEmpty()) {
log.info("质检任务全部合格,无需生成不合格品评审任务: {}", inspectionVo.getInspectionNo());
return true;
}
try {
// 生成不合格品评审任务
QcUnqualifiedReviewBo reviewBo = createUnqualifiedReviewBo(inspectionVo, unqualifiedItems);
// 保存不合格品评审任务
Boolean result = qcUnqualifiedReviewService.insertByBo(reviewBo);
if (result) {
log.info("成功生成不合格品评审任务: 质检单号={}, 不合格项数量={}",
inspectionVo.getInspectionNo(), unqualifiedItems.size());
} else {
log.error("生成不合格品评审任务失败: {}", inspectionVo.getInspectionNo());
}
return result;
} catch (Exception e) {
log.error("生成不合格品评审任务异常: {}", inspectionVo.getInspectionNo(), e);
return false;
}
}
/**
*
*
* @param inspectionItems
* @return
*/
private List<QcInspectionItemDetailVo> getUnqualifiedItems(List<QcInspectionItemDetailVo> inspectionItems) {
if (inspectionItems == null || inspectionItems.isEmpty()) {
return List.of();
}
return inspectionItems.stream()
.filter(item -> {
Long resultStatus = QcInspectionResultCalculator.calculateItemResultStatus(item);
return QcInspectionResultCalculator.RESULT_STATUS_UNQUALIFIED.equals(resultStatus);
})
.collect(Collectors.toList());
}
/**
*
*
* @param inspectionVo
* @param unqualifiedItems
* @return
*/
private QcUnqualifiedReviewBo createUnqualifiedReviewBo(QcInspectionMainVo inspectionVo, List<QcInspectionItemDetailVo> unqualifiedItems) {
QcUnqualifiedReviewBo reviewBo = new QcUnqualifiedReviewBo();
// 生成不合格检测单号
String unqualifiedNo = generateUnqualifiedNo(inspectionVo.getInspectionNo());
reviewBo.setUnqualifiedNo(unqualifiedNo);
// 设置关联的质检主表ID
reviewBo.setInspectionId(inspectionVo.getInspectionId());
// 设置检测类型
reviewBo.setTypeId(inspectionVo.getTypeId());
// 复制质检主表的基本信息
// reviewBo.setWorkOrder(inspectionVo.getWorkOrder());
// reviewBo.setProcessCode(inspectionVo.getProcessCode());
reviewBo.setProcessName(inspectionVo.getProcessName());
reviewBo.setBatchNo(inspectionVo.getBatchNo());
reviewBo.setMaterialName(inspectionVo.getMaterialName());
reviewBo.setMaterialCode(inspectionVo.getMaterialCode());
// 设置质检员检测结果描述
String inspectorResult = buildInspectorResultDescription(unqualifiedItems);
reviewBo.setInspectorResult(inspectorResult);
// 初始状态待评审reviewResult为空
reviewBo.setReviewResult(null);
reviewBo.setReviewer(null);
reviewBo.setReviewTime(null);
return reviewBo;
}
/**
*
* UQ + + 4
*
* @param inspectionNo
* @return
*/
private String generateUnqualifiedNo(String inspectionNo) {
String timestamp = String.valueOf(System.currentTimeMillis());
String suffix = timestamp.substring(timestamp.length() - 4);
if (StringUtils.isNotBlank(inspectionNo)) {
return "UQ" + inspectionNo + suffix;
} else {
return "UQ" + System.currentTimeMillis();
}
}
/**
*
*
* @param unqualifiedItems
* @return
*/
private String buildInspectorResultDescription(List<QcInspectionItemDetailVo> unqualifiedItems) {
if (unqualifiedItems == null || unqualifiedItems.isEmpty()) {
return "无不合格项";
}
StringBuilder description = new StringBuilder();
description.append("不合格项目:");
for (int i = 0; i < unqualifiedItems.size(); i++) {
QcInspectionItemDetailVo item = unqualifiedItems.get(i);
if (i > 0) {
description.append("");
}
description.append(item.getItemName());
// 添加具体的不合格原因
if (QcInspectionResultCalculator.DETECT_TYPE_QUANTITATIVE.equals(item.getDetectType())) {
// 定量检测:显示检测值和限值
if (item.getValue() != null) {
description.append("(检测值:").append(item.getValue());
if (Boolean.TRUE.equals(item.getIsOutOfControlLimit())) {
description.append(", 超出控制限");
if (item.getUpperLimit() != null) {
description.append(", 上限:").append(item.getUpperLimit());
}
if (item.getLowerLimit() != null) {
description.append(", 下限:").append(item.getLowerLimit());
}
}
description.append(")");
}
} else {
// 定性检测:显示检测结果
if (StringUtils.isNotBlank(item.getResult())) {
description.append("(结果:").append(item.getResult()).append(")");
}
}
}
// 限制描述长度,避免过长
String result = description.toString();
if (result.length() > 500) {
result = result.substring(0, 497) + "...";
}
return result;
}
/**
*
*
* @param inspectionVo
* @param overallResult
* @return
*/
public Boolean shouldGenerateUnqualifiedReview(QcInspectionMainVo inspectionVo, Long overallResult) {
// 如果整体结果合格,不需要生成
if (QcInspectionResultCalculator.RESULT_STATUS_QUALIFIED.equals(overallResult)) {
return false;
}
// 检查是否已经存在不合格品评审任务
if (hasExistingUnqualifiedReview(inspectionVo.getInspectionId())) {
log.info("质检任务已存在不合格品评审任务,跳过生成: {}", inspectionVo.getInspectionNo());
return false;
}
return true;
}
/**
*
*
* @param inspectionId ID
* @return
*/
private Boolean hasExistingUnqualifiedReview(Long inspectionId) {
try {
// 查询是否已存在该质检任务的不合格品评审记录
QcUnqualifiedReviewBo queryBo = new QcUnqualifiedReviewBo();
queryBo.setInspectionId(inspectionId);
return !qcUnqualifiedReviewService.queryList(queryBo).isEmpty();
} catch (Exception e) {
log.error("检查不合格品评审任务是否存在时发生异常: inspectionId={}", inspectionId, e);
return false;
}
}
/**
*
*
* @param inspectionList
* @return
*/
public Integer batchGenerateUnqualifiedReviews(List<QcInspectionMainVo> inspectionList) {
if (inspectionList == null || inspectionList.isEmpty()) {
return 0;
}
int successCount = 0;
for (QcInspectionMainVo inspection : inspectionList) {
try {
// 这里需要获取检测项数据,实际实现中可能需要调用其他服务
// List<QcInspectionItemDetailVo> items = getInspectionItems(inspection.getInspectionId());
// Boolean result = autoGenerateUnqualifiedReview(inspection, items);
// if (Boolean.TRUE.equals(result)) {
// successCount++;
// }
} catch (Exception e) {
log.error("批量生成不合格品评审任务失败: {}", inspection.getInspectionNo(), e);
}
}
log.info("批量生成不合格品评审任务完成,总数: {}, 成功: {}", inspectionList.size(), successCount);
return successCount;
}
}

@ -0,0 +1,148 @@
package org.dromara.qms.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.dromara.qms.domain.bo.QcUnqualifiedRecordBo;
import org.dromara.qms.domain.vo.QcUnqualifiedRecordVo;
import org.dromara.qms.domain.QcUnqualifiedRecord;
import org.dromara.qms.mapper.QcUnqualifiedRecordMapper;
import org.dromara.qms.service.IQcUnqualifiedRecordService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
* Service
*
* @author zch
* @date 2025-07-18
*/
@RequiredArgsConstructor
@Service
public class QcUnqualifiedRecordServiceImpl implements IQcUnqualifiedRecordService {
private final QcUnqualifiedRecordMapper baseMapper;
/**
*
*
* @param recordId
* @return
*/
@Override
public QcUnqualifiedRecordVo queryById(Long recordId){
return baseMapper.selectVoById(recordId);
}
/**
*
*
* @param bo
* @param pageQuery
* @return
*/
@Override
public TableDataInfo<QcUnqualifiedRecordVo> queryPageList(QcUnqualifiedRecordBo bo, PageQuery pageQuery) {
MPJLambdaWrapper<QcUnqualifiedRecord> lqw = buildQueryWrapper(bo);
Page<QcUnqualifiedRecordVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
*
*
* @param bo
* @return
*/
@Override
public List<QcUnqualifiedRecordVo> queryList(QcUnqualifiedRecordBo bo) {
MPJLambdaWrapper<QcUnqualifiedRecord> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private MPJLambdaWrapper<QcUnqualifiedRecord> buildQueryWrapper(QcUnqualifiedRecordBo bo) {
Map<String, Object> params = bo.getParams();
MPJLambdaWrapper<QcUnqualifiedRecord> lqw = JoinWrappers.lambda(QcUnqualifiedRecord.class)
.selectAll(QcUnqualifiedRecord.class)
.eq(bo.getRecordId() != null, QcUnqualifiedRecord::getRecordId, bo.getRecordId())
.eq(bo.getReviewId() != null, QcUnqualifiedRecord::getReviewId, bo.getReviewId())
.orderByDesc(QcUnqualifiedRecord::getCreateTime);
return lqw;
}
/**
*
*
* @param bo
* @return
*/
@Override
public Boolean insertByBo(QcUnqualifiedRecordBo bo) {
QcUnqualifiedRecord add = MapstructUtils.convert(bo, QcUnqualifiedRecord.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setRecordId(add.getRecordId());
}
return flag;
}
/**
*
*
* @param bo
* @return
*/
@Override
public Boolean updateByBo(QcUnqualifiedRecordBo bo) {
QcUnqualifiedRecord update = MapstructUtils.convert(bo, QcUnqualifiedRecord.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
*
*/
private void validEntityBeforeSave(QcUnqualifiedRecord entity){
//TODO 做一些数据校验,如唯一约束
}
/**
*
*
* @param ids
* @param isValid
* @return
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
@Override
public TableDataInfo<QcUnqualifiedRecordVo> queryPageListWithDetails(QcUnqualifiedRecordBo bo, PageQuery pageQuery) {
return null;
}
@Override
public TableDataInfo<QcUnqualifiedRecordVo> queryPageUserRecords(String reviewer, PageQuery pageQuery) {
return null;
}
@Override
public TableDataInfo<QcUnqualifiedRecordVo> queryPageRecordsByDateRange(QcUnqualifiedRecordBo bo, PageQuery pageQuery) {
return null;
}
}

@ -0,0 +1,693 @@
package org.dromara.qms.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.qms.domain.QcInspectionMain;
import org.dromara.qms.domain.QcInspectionType;
import org.dromara.qms.domain.bo.QcInspectionMainBo;
import org.dromara.qms.domain.bo.QcInspectionResultBo;
import org.dromara.qms.domain.vo.QcInspectionResultVo;
import org.dromara.qms.service.IQcInspectionResultService;
import org.springframework.stereotype.Service;
import org.dromara.qms.domain.bo.QcUnqualifiedReviewBo;
import org.dromara.qms.domain.vo.QcUnqualifiedReviewVo;
import org.dromara.qms.domain.QcUnqualifiedReview;
import org.dromara.qms.mapper.QcUnqualifiedReviewMapper;
import org.dromara.qms.service.IQcUnqualifiedReviewService;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
* Service
*
* @author zch
* @date 2025-07-18
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class QcUnqualifiedReviewServiceImpl implements IQcUnqualifiedReviewService {
private final QcUnqualifiedReviewMapper baseMapper;
private final IQcInspectionResultService qcInspectionResultService;
/**
*
*
* @param reviewId
* @return
*/
@Override
public QcUnqualifiedReviewVo queryById(Long reviewId){
return baseMapper.selectVoById(reviewId);
}
/**
*
*
* @param bo
* @param pageQuery
* @return
*/
@Override
public TableDataInfo<QcUnqualifiedReviewVo> queryPageList(QcUnqualifiedReviewBo bo, PageQuery pageQuery) {
MPJLambdaWrapper<QcUnqualifiedReview> lqw = buildQueryWrapper(bo);
Page<QcUnqualifiedReviewVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
*
*
* @param bo
* @return
*/
@Override
public List<QcUnqualifiedReviewVo> queryList(QcUnqualifiedReviewBo bo) {
MPJLambdaWrapper<QcUnqualifiedReview> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
/**
* (for PDA)
* reviewResult
*
* @param bo
* @param pageQuery
* @return
*/
@Override
public TableDataInfo<QcUnqualifiedReviewVo> queryPagePendingReviews(QcUnqualifiedReviewBo bo, PageQuery pageQuery) {
// 设置查询条件只查询待评审的记录reviewResult为空
QcUnqualifiedReviewBo pendingBo = new QcUnqualifiedReviewBo();
// 复制原有查询条件
if (bo != null) {
pendingBo.setUnqualifiedNo(bo.getUnqualifiedNo());
pendingBo.setInspectionId(bo.getInspectionId());
pendingBo.setTypeId(bo.getTypeId());
pendingBo.setWorkOrder(bo.getWorkOrder());
pendingBo.setProcessCode(bo.getProcessCode());
pendingBo.setProcessName(bo.getProcessName());
pendingBo.setBatchNo(bo.getBatchNo());
pendingBo.setMaterialName(bo.getMaterialName());
pendingBo.setMaterialCode(bo.getMaterialCode());
pendingBo.setInspectorResult(bo.getInspectorResult());
pendingBo.setReviewer(bo.getReviewer());
pendingBo.setParams(bo.getParams());
}
// 强制设置reviewResult为null查询待评审记录
pendingBo.setReviewResult(null);
MPJLambdaWrapper<QcUnqualifiedReview> lqw = buildQueryWrapper(pendingBo);
// 添加条件reviewResult为空或null
lqw.and(wrapper -> wrapper.isNull(QcUnqualifiedReview::getReviewResult)
.or().eq(QcUnqualifiedReview::getReviewResult, ""));
Page<QcUnqualifiedReviewVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* (for PDA)
*
*
* @param reviewId
* @return
*/
@Override
public QcUnqualifiedReviewVo queryByIdWithItems(Long reviewId) {
QcUnqualifiedReviewVo reviewVo = queryById(reviewId);
if (reviewVo != null && reviewVo.getInspectionId() != null) {
// 查询关联的检测项结果明细
QcInspectionResultBo resultBo = new QcInspectionResultBo();
resultBo.setInspectionId(reviewVo.getInspectionId());
List<QcInspectionResultVo> inspectionResults = qcInspectionResultService.queryList(resultBo);
// 可以将检测项结果添加到reviewVo中但由于QcUnqualifiedReviewVo没有相应字段
// 这里暂时通过日志记录或者扩展VO类来处理
// 实际项目中可能需要扩展QcUnqualifiedReviewVo类添加inspectionResults字段
}
return reviewVo;
}
/**
* (for PDA)
*
*
* @param bo
* @return
*/
@Override
public Boolean submitReview(QcUnqualifiedReviewBo bo) {
// 设置评审时间
bo.setReviewTime(new Date());
// 更新评审结果
Boolean updated = updateByBo(bo);
if (updated) {
// 根据评审结果触发后续流程
triggerWorkflowProcess(bo);
}
return updated;
}
/**
* (for PDA)
*
* @param dateRange "2025-01-01,2025-01-31"
* @return
*/
@Override
public Map<String, Object> getUnqualifiedSummary(String dateRange) {
Map<String, Object> summary = new HashMap<>();
// 解析日期范围
LocalDate startDate = null;
LocalDate endDate = null;
if (StringUtils.isNotBlank(dateRange)) {
String[] dates = dateRange.split(",");
if (dates.length == 2) {
try {
startDate = LocalDate.parse(dates[0].trim(), DateTimeFormatter.ISO_LOCAL_DATE);
endDate = LocalDate.parse(dates[1].trim(), DateTimeFormatter.ISO_LOCAL_DATE);
} catch (Exception e) {
// 日期解析失败,使用默认范围(当月)
startDate = LocalDate.now().withDayOfMonth(1);
endDate = LocalDate.now();
}
}
} else {
// 默认查询当月数据
startDate = LocalDate.now().withDayOfMonth(1);
endDate = LocalDate.now();
}
// 构建查询条件
QcUnqualifiedReviewBo bo = new QcUnqualifiedReviewBo();
Map<String, Object> params = new HashMap<>();
params.put("beginTime", startDate.toString());
params.put("endTime", endDate.toString());
bo.setParams(params);
// 查询所有不合格品记录
List<QcUnqualifiedReviewVo> allRecords = queryList(bo);
// 统计总数
summary.put("totalCount", allRecords.size());
// 统计待评审数量
long pendingCount = allRecords.stream()
.filter(record -> StringUtils.isBlank(record.getReviewResult()))
.count();
summary.put("pendingCount", pendingCount);
// 统计已评审数量
long reviewedCount = allRecords.size() - pendingCount;
summary.put("reviewedCount", reviewedCount);
// 按评审结果分组统计
Map<String, Long> reviewResultStats = allRecords.stream()
.filter(record -> StringUtils.isNotBlank(record.getReviewResult()))
.collect(Collectors.groupingBy(
QcUnqualifiedReviewVo::getReviewResult,
Collectors.counting()
));
summary.put("scrapCount", reviewResultStats.getOrDefault("0", 0L)); // 报废
summary.put("reworkCount", reviewResultStats.getOrDefault("1", 0L)); // 返工
summary.put("returnCount", reviewResultStats.getOrDefault("2", 0L)); // 退货
summary.put("acceptCount", reviewResultStats.getOrDefault("3", 0L)); // 让步接收
summary.put("transferCount", reviewResultStats.getOrDefault("4", 0L)); // 流转
// 按物料分组统计
Map<String, Long> materialStats = allRecords.stream()
.filter(record -> StringUtils.isNotBlank(record.getMaterialName()))
.collect(Collectors.groupingBy(
QcUnqualifiedReviewVo::getMaterialName,
Collectors.counting()
));
summary.put("materialStats", materialStats);
// 按工序分组统计
Map<String, Long> processStats = allRecords.stream()
.filter(record -> StringUtils.isNotBlank(record.getProcessName()))
.collect(Collectors.groupingBy(
QcUnqualifiedReviewVo::getProcessName,
Collectors.counting()
));
summary.put("processStats", processStats);
return summary;
}
/**
* (for PDA)
*
*
* @param bo
* @return
*/
@Override
public Boolean triggerWorkflowProcess(QcUnqualifiedReviewBo bo) {
if (bo == null || StringUtils.isBlank(bo.getReviewResult())) {
log.error("评审结果为空,无法触发工作流程");
return false;
}
try {
log.info("开始触发工作流程: 评审ID={}, 评审结果={}", bo.getReviewId(), bo.getReviewResult());
// 根据评审结果触发不同的后续流程
switch (bo.getReviewResult()) {
case "0": // 报废
return handleScrapProcess(bo);
case "1": // 返工
return handleReworkProcess(bo);
case "2": // 退货
return handleReturnProcess(bo);
case "3": // 让步接收
return handleAcceptProcess(bo);
case "4": // 流转
return handleTransferProcess(bo);
default:
log.warn("未知的评审结果: {}", bo.getReviewResult());
return false;
}
} catch (Exception e) {
log.error("触发工作流程异常: 评审ID={}", bo.getReviewId(), e);
return false;
}
}
/**
*
*
*/
private Boolean handleScrapProcess(QcUnqualifiedReviewBo bo) {
try {
log.info("执行报废流程: 评审ID={}", bo.getReviewId());
// 1. 更新库存状态为报废
updateInventoryStatus(bo, "SCRAPPED");
// 2. 生成报废单据
generateScrapDocument(bo);
// 3. 更新质检主表状态
updateInspectionMainStatus(bo, "SCRAPPED");
// 4. 记录处理日志
recordProcessLog(bo, "报废流程执行完成");
log.info("报废流程执行成功: 评审ID={}", bo.getReviewId());
return true;
} catch (Exception e) {
log.error("报废流程执行失败: 评审ID={}", bo.getReviewId(), e);
return false;
}
}
/**
*
*
*/
private Boolean handleReworkProcess(QcUnqualifiedReviewBo bo) {
try {
log.info("执行返工流程: 评审ID={}", bo.getReviewId());
// 1. 生成返工工单
generateReworkOrder(bo);
// 2. 分派返工任务给相关人员
assignReworkTask(bo);
// 3. 更新质检主表状态为返工中
updateInspectionMainStatus(bo, "REWORKING");
// 4. 更新库存状态
updateInventoryStatus(bo, "REWORKING");
// 5. 记录处理日志
recordProcessLog(bo, "返工流程执行完成,已生成返工工单");
log.info("返工流程执行成功: 评审ID={}", bo.getReviewId());
return true;
} catch (Exception e) {
log.error("返工流程执行失败: 评审ID={}", bo.getReviewId(), e);
return false;
}
}
/**
* 退
* 退
*/
private Boolean handleReturnProcess(QcUnqualifiedReviewBo bo) {
try {
log.info("执行退货流程: 评审ID={}", bo.getReviewId());
// 1. 生成退货单据
generateReturnDocument(bo);
// 2. 通知供应商
notifySupplier(bo);
// 3. 更新库存状态为待退货
updateInventoryStatus(bo, "RETURNING");
// 4. 更新质检主表状态
updateInspectionMainStatus(bo, "RETURNED");
// 5. 记录处理日志
recordProcessLog(bo, "退货流程执行完成,已通知供应商");
log.info("退货流程执行成功: 评审ID={}", bo.getReviewId());
return true;
} catch (Exception e) {
log.error("退货流程执行失败: 评审ID={}", bo.getReviewId(), e);
return false;
}
}
/**
*
*
*/
private Boolean handleAcceptProcess(QcUnqualifiedReviewBo bo) {
try {
log.info("执行让步接收流程: 评审ID={}", bo.getReviewId());
// 1. 更新质检状态为让步合格
updateInspectionMainStatus(bo, "CONDITIONALLY_ACCEPTED");
// 2. 更新库存状态为可用
updateInventoryStatus(bo, "AVAILABLE");
// 3. 生成让步接收单据
generateAcceptanceDocument(bo);
// 4. 触发入库流程
triggerInboundProcess(bo);
// 5. 记录处理日志
recordProcessLog(bo, "让步接收流程执行完成,产品已入库");
log.info("让步接收流程执行成功: 评审ID={}", bo.getReviewId());
return true;
} catch (Exception e) {
log.error("让步接收流程执行失败: 评审ID={}", bo.getReviewId(), e);
return false;
}
}
/**
*
*
*/
private Boolean handleTransferProcess(QcUnqualifiedReviewBo bo) {
try {
log.info("执行流转流程: 评审ID={}", bo.getReviewId());
// 1. 确定流转目标部门或工序
String transferTarget = determineTransferTarget(bo);
// 2. 生成流转单据
generateTransferDocument(bo, transferTarget);
// 3. 通知目标部门
notifyTargetDepartment(bo, transferTarget);
// 4. 更新质检主表状态
updateInspectionMainStatus(bo, "TRANSFERRED");
// 5. 更新库存状态
updateInventoryStatus(bo, "TRANSFERRED");
// 6. 记录处理日志
recordProcessLog(bo, "流转流程执行完成,已转移至: " + transferTarget);
log.info("流转流程执行成功: 评审ID={}, 流转目标={}", bo.getReviewId(), transferTarget);
return true;
} catch (Exception e) {
log.error("流转流程执行失败: 评审ID={}", bo.getReviewId(), e);
return false;
}
}
// 以下是辅助方法的实现
/**
*
*/
private void updateInventoryStatus(QcUnqualifiedReviewBo bo, String status) {
try {
// TODO: 实现库存状态更新逻辑
// 这里需要调用库存管理模块的接口
log.info("更新库存状态: 评审ID={}, 状态={}", bo.getReviewId(), status);
} catch (Exception e) {
log.error("更新库存状态失败: 评审ID={}, 状态={}", bo.getReviewId(), status, e);
}
}
/**
*
*/
private void updateInspectionMainStatus(QcUnqualifiedReviewBo bo, String status) {
try {
// TODO: 实现质检主表状态更新逻辑
// 这里需要调用质检主表服务的更新方法
log.info("更新质检主表状态: 质检ID={}, 状态={}", bo.getInspectionId(), status);
} catch (Exception e) {
log.error("更新质检主表状态失败: 质检ID={}, 状态={}", bo.getInspectionId(), status, e);
}
}
/**
*
*/
private void generateScrapDocument(QcUnqualifiedReviewBo bo) {
try {
// TODO: 实现报废单据生成逻辑
log.info("生成报废单据: 评审ID={}", bo.getReviewId());
} catch (Exception e) {
log.error("生成报废单据失败: 评审ID={}", bo.getReviewId(), e);
}
}
/**
*
*/
private void generateReworkOrder(QcUnqualifiedReviewBo bo) {
try {
// TODO: 实现返工工单生成逻辑
log.info("生成返工工单: 评审ID={}", bo.getReviewId());
} catch (Exception e) {
log.error("生成返工工单失败: 评审ID={}", bo.getReviewId(), e);
}
}
/**
*
*/
private void assignReworkTask(QcUnqualifiedReviewBo bo) {
try {
// TODO: 实现返工任务分派逻辑
log.info("分派返工任务: 评审ID={}", bo.getReviewId());
} catch (Exception e) {
log.error("分派返工任务失败: 评审ID={}", bo.getReviewId(), e);
}
}
/**
* 退
*/
private void generateReturnDocument(QcUnqualifiedReviewBo bo) {
try {
// TODO: 实现退货单据生成逻辑
log.info("生成退货单据: 评审ID={}", bo.getReviewId());
} catch (Exception e) {
log.error("生成退货单据失败: 评审ID={}", bo.getReviewId(), e);
}
}
/**
*
*/
private void notifySupplier(QcUnqualifiedReviewBo bo) {
try {
// TODO: 实现供应商通知逻辑
log.info("通知供应商: 评审ID={}", bo.getReviewId());
} catch (Exception e) {
log.error("通知供应商失败: 评审ID={}", bo.getReviewId(), e);
}
}
/**
*
*/
private void generateAcceptanceDocument(QcUnqualifiedReviewBo bo) {
try {
// TODO: 实现让步接收单据生成逻辑
log.info("生成让步接收单据: 评审ID={}", bo.getReviewId());
} catch (Exception e) {
log.error("生成让步接收单据失败: 评审ID={}", bo.getReviewId(), e);
}
}
/**
*
*/
private void triggerInboundProcess(QcUnqualifiedReviewBo bo) {
try {
// TODO: 实现入库流程触发逻辑
log.info("触发入库流程: 评审ID={}", bo.getReviewId());
} catch (Exception e) {
log.error("触发入库流程失败: 评审ID={}", bo.getReviewId(), e);
}
}
/**
*
*/
private String determineTransferTarget(QcUnqualifiedReviewBo bo) {
try {
// TODO: 实现流转目标确定逻辑
// 这里可以根据业务规则或配置来确定流转目标
return "质量管理部"; // 默认流转目标
} catch (Exception e) {
log.error("确定流转目标失败: 评审ID={}", bo.getReviewId(), e);
return "质量管理部";
}
}
/**
*
*/
private void generateTransferDocument(QcUnqualifiedReviewBo bo, String transferTarget) {
try {
// TODO: 实现流转单据生成逻辑
log.info("生成流转单据: 评审ID={}, 目标={}", bo.getReviewId(), transferTarget);
} catch (Exception e) {
log.error("生成流转单据失败: 评审ID={}, 目标={}", bo.getReviewId(), transferTarget, e);
}
}
/**
*
*/
private void notifyTargetDepartment(QcUnqualifiedReviewBo bo, String transferTarget) {
try {
// TODO: 实现目标部门通知逻辑
log.info("通知目标部门: 评审ID={}, 目标={}", bo.getReviewId(), transferTarget);
} catch (Exception e) {
log.error("通知目标部门失败: 评审ID={}, 目标={}", bo.getReviewId(), transferTarget, e);
}
}
/**
*
*/
private void recordProcessLog(QcUnqualifiedReviewBo bo, String message) {
try {
// TODO: 实现处理日志记录逻辑
log.info("记录处理日志: 评审ID={}, 消息={}", bo.getReviewId(), message);
} catch (Exception e) {
log.error("记录处理日志失败: 评审ID={}, 消息={}", bo.getReviewId(), message, e);
}
}
private MPJLambdaWrapper<QcUnqualifiedReview> buildQueryWrapper(QcUnqualifiedReviewBo bo) {
Map<String, Object> params = bo.getParams();
MPJLambdaWrapper<QcUnqualifiedReview> lqw = JoinWrappers.lambda(QcUnqualifiedReview.class)
.selectAll(QcUnqualifiedReview.class)
//关联质检主表
.select(QcInspectionMain::getInspectionNo)
.leftJoin(QcInspectionMain.class, QcInspectionMain::getInspectionId, QcUnqualifiedReview::getInspectionId)
//关联检测类型
.select(QcInspectionType::getTypeName, QcInspectionType::getQcInspectionType, QcInspectionType::getTypeCode, QcInspectionType::getQcInspectionType)
.leftJoin(QcInspectionType.class, QcInspectionType::getTypeId, QcInspectionMain::getTypeId)
.eq(bo.getReviewId() != null, QcUnqualifiedReview::getReviewId, bo.getReviewId())
.eq(StringUtils.isNotBlank(bo.getUnqualifiedNo()), QcUnqualifiedReview::getUnqualifiedNo, bo.getUnqualifiedNo())
.eq(bo.getInspectionId() != null, QcUnqualifiedReview::getInspectionId, bo.getInspectionId())
.eq(bo.getTypeId() != null, QcUnqualifiedReview::getTypeId, bo.getTypeId())
.eq(StringUtils.isNotBlank(bo.getWorkOrder()), QcUnqualifiedReview::getWorkOrder, bo.getWorkOrder())
.eq(StringUtils.isNotBlank(bo.getProcessCode()), QcUnqualifiedReview::getProcessCode, bo.getProcessCode())
.like(StringUtils.isNotBlank(bo.getProcessName()), QcUnqualifiedReview::getProcessName, bo.getProcessName())
.eq(StringUtils.isNotBlank(bo.getBatchNo()), QcUnqualifiedReview::getBatchNo, bo.getBatchNo())
.like(StringUtils.isNotBlank(bo.getMaterialName()), QcUnqualifiedReview::getMaterialName, bo.getMaterialName())
.eq(StringUtils.isNotBlank(bo.getMaterialCode()), QcUnqualifiedReview::getMaterialCode, bo.getMaterialCode())
.eq(StringUtils.isNotBlank(bo.getInspectorResult()), QcUnqualifiedReview::getInspectorResult, bo.getInspectorResult())
.eq(StringUtils.isNotBlank(bo.getReviewResult()), QcUnqualifiedReview::getReviewResult, bo.getReviewResult())
.eq(StringUtils.isNotBlank(bo.getReviewer()), QcUnqualifiedReview::getReviewer, bo.getReviewer())
.eq(bo.getReviewTime() != null, QcUnqualifiedReview::getReviewTime, bo.getReviewTime())
.orderByDesc(QcUnqualifiedReview::getCreateTime);
return lqw;
}
/**
*
*
* @param bo
* @return
*/
@Override
public Boolean insertByBo(QcUnqualifiedReviewBo bo) {
QcUnqualifiedReview add = MapstructUtils.convert(bo, QcUnqualifiedReview.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setReviewId(add.getReviewId());
}
return flag;
}
/**
*
*
* @param bo
* @return
*/
@Override
public Boolean updateByBo(QcUnqualifiedReviewBo bo) {
QcUnqualifiedReview update = MapstructUtils.convert(bo, QcUnqualifiedReview.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
*
*/
private void validEntityBeforeSave(QcUnqualifiedReview entity){
//TODO 做一些数据校验,如唯一约束
}
/**
*
*
* @param ids
* @param isValid
* @return
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
//TODO 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteByIds(ids) > 0;
}
}

@ -0,0 +1,368 @@
package org.dromara.qms.utils;
import org.dromara.qms.domain.vo.QcInspectionItemDetailVo;
import org.dromara.qms.domain.bo.QcInspectionMainBo;
import org.dromara.common.core.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
/**
*
*
*
* @author zch
* @date 2025-07-18
*/
@Slf4j
public class QcInspectionResultCalculator {
/**
*
*/
public static final Long DETECT_TYPE_QUALITATIVE = 0L;
/**
*
*/
public static final Long DETECT_TYPE_QUANTITATIVE = 1L;
/**
*
*/
public static final Long RESULT_STATUS_QUALIFIED = 0L;
/**
*
*/
public static final Long RESULT_STATUS_UNQUALIFIED = 1L;
/**
*
* /
*
* @param itemDetail
* @return 0/1
*/
public static Long calculateItemResultStatus(QcInspectionItemDetailVo itemDetail) {
if (itemDetail == null) {
log.warn("检测项明细为空,无法计算结果状态");
return RESULT_STATUS_UNQUALIFIED;
}
// 定性检测:需要手动选择结果,验证是否已选择
if (DETECT_TYPE_QUALITATIVE.equals(itemDetail.getDetectType())) {
return calculateQualitativeResult(itemDetail);
}
// 定量检测:根据控制上下限自动判定
if (DETECT_TYPE_QUANTITATIVE.equals(itemDetail.getDetectType())) {
return calculateQuantitativeResult(itemDetail);
}
log.warn("未知的检测方式: {}, 检测项: {}", itemDetail.getDetectType(), itemDetail.getItemName());
return RESULT_STATUS_UNQUALIFIED;
}
/**
*
* /
*
* @param itemDetail
* @return
*/
private static Long calculateQualitativeResult(QcInspectionItemDetailVo itemDetail) {
// 检查是否已手动选择结果
if (itemDetail.getResultStatus() != null) {
return itemDetail.getResultStatus();
}
// 如果有检测结果字符串,尝试解析
if (StringUtils.isNotBlank(itemDetail.getResult())) {
String result = itemDetail.getResult().trim().toLowerCase();
if ("合格".equals(result) || "qualified".equals(result) || "pass".equals(result) || "0".equals(result)) {
return RESULT_STATUS_QUALIFIED;
}
if ("不合格".equals(result) || "unqualified".equals(result) || "fail".equals(result) || "1".equals(result)) {
return RESULT_STATUS_UNQUALIFIED;
}
}
log.warn("定性检测项未选择结果状态: {}", itemDetail.getItemName());
return RESULT_STATUS_UNQUALIFIED;
}
/**
*
* /
*
* @param itemDetail
* @return
*/
private static Long calculateQuantitativeResult(QcInspectionItemDetailVo itemDetail) {
BigDecimal value = itemDetail.getValue();
BigDecimal upperLimit = itemDetail.getUpperLimit();
BigDecimal lowerLimit = itemDetail.getLowerLimit();
// 检查检测值是否存在
if (value == null) {
log.warn("定量检测项缺少检测值: {}", itemDetail.getItemName());
return RESULT_STATUS_UNQUALIFIED;
}
// 检查控制限是否设置
if (upperLimit == null && lowerLimit == null) {
log.warn("定量检测项未设置控制限: {}", itemDetail.getItemName());
// 如果没有设置控制限,默认为合格
return RESULT_STATUS_QUALIFIED;
}
// 检查是否超出控制上限
if (upperLimit != null && value.compareTo(upperLimit) > 0) {
log.info("检测值超出控制上限: {} > {}, 检测项: {}", value, upperLimit, itemDetail.getItemName());
itemDetail.setIsOutOfControlLimit(true);
return RESULT_STATUS_UNQUALIFIED;
}
// 检查是否低于控制下限
if (lowerLimit != null && value.compareTo(lowerLimit) < 0) {
log.info("检测值低于控制下限: {} < {}, 检测项: {}", value, lowerLimit, itemDetail.getItemName());
itemDetail.setIsOutOfControlLimit(true);
return RESULT_STATUS_UNQUALIFIED;
}
// 检查规格限(如果设置了规格限)
if (isOutOfSpecLimit(itemDetail)) {
itemDetail.setIsOutOfSpecLimit(true);
log.info("检测值超出规格限,但在控制限内: {}, 检测项: {}", value, itemDetail.getItemName());
}
itemDetail.setIsOutOfControlLimit(false);
return RESULT_STATUS_QUALIFIED;
}
/**
*
*
* @param itemDetail
* @return
*/
private static boolean isOutOfSpecLimit(QcInspectionItemDetailVo itemDetail) {
BigDecimal value = itemDetail.getValue();
BigDecimal specUpperLimit = itemDetail.getSpecUpperLimit();
BigDecimal specLowerLimit = itemDetail.getSpecLowerLimit();
if (value == null) {
return false;
}
// 检查规格上限
if (specUpperLimit != null && value.compareTo(specUpperLimit) > 0) {
return true;
}
// 检查规格下限
if (specLowerLimit != null && value.compareTo(specLowerLimit) < 0) {
return true;
}
return false;
}
/**
*
*
*
* @param inspectionItems
* @return 0/1
*/
public static Long calculateOverallResult(List<QcInspectionItemDetailVo> inspectionItems) {
if (inspectionItems == null || inspectionItems.isEmpty()) {
log.warn("检测项列表为空,整体结果判定为不合格");
return RESULT_STATUS_UNQUALIFIED;
}
// 检查是否所有必检项都已完成
boolean hasUncompletedRequiredItems = inspectionItems.stream()
.filter(item -> Boolean.TRUE.equals(item.getIsRequired()))
.anyMatch(item -> !Boolean.TRUE.equals(item.getIsCompleted()));
if (hasUncompletedRequiredItems) {
log.warn("存在未完成的必检项,整体结果判定为不合格");
return RESULT_STATUS_UNQUALIFIED;
}
// 计算每个检测项的结果状态
for (QcInspectionItemDetailVo item : inspectionItems) {
Long itemResult = calculateItemResultStatus(item);
item.setResultStatus(itemResult);
// 如果任何一个检测项不合格,整体结果就是不合格
if (RESULT_STATUS_UNQUALIFIED.equals(itemResult)) {
log.info("检测项不合格,整体结果判定为不合格: {}", item.getItemName());
return RESULT_STATUS_UNQUALIFIED;
}
}
log.info("所有检测项都合格,整体结果判定为合格");
return RESULT_STATUS_QUALIFIED;
}
/**
*
*
*
* @param bo
* @return
*/
public static ValidationResult validateInspectionData(QcInspectionMainBo bo) {
ValidationResult result = new ValidationResult();
if (bo == null) {
result.setValid(false);
result.addError("质检数据不能为空");
return result;
}
// 验证基本信息
if (bo.getInspectionId() == null) {
result.addError("质检任务ID不能为空");
}
if (StringUtils.isBlank(bo.getInspector())) {
result.addError("检测人员不能为空");
}
// 验证检测项数据这里假设检测项数据在bo中实际可能需要从其他地方获取
// 实际实现中可能需要根据inspectionId查询检测项数据
return result;
}
/**
*
*
* @param inspectionItems
* @return
*/
public static ValidationResult validateInspectionItems(List<QcInspectionItemDetailVo> inspectionItems) {
ValidationResult result = new ValidationResult();
if (inspectionItems == null || inspectionItems.isEmpty()) {
result.setValid(false);
result.addError("检测项列表不能为空");
return result;
}
for (QcInspectionItemDetailVo item : inspectionItems) {
validateSingleInspectionItem(item, result);
}
return result;
}
/**
*
*
* @param item
* @param result
*/
private static void validateSingleInspectionItem(QcInspectionItemDetailVo item, ValidationResult result) {
if (item == null) {
result.addError("检测项不能为空");
return;
}
// 验证基本信息
if (StringUtils.isBlank(item.getItemName())) {
result.addError("检测项名称不能为空");
}
if (item.getDetectType() == null) {
result.addError("检测方式不能为空: " + item.getItemName());
}
// 验证定量检测数据
if (DETECT_TYPE_QUANTITATIVE.equals(item.getDetectType())) {
validateQuantitativeItem(item, result);
}
// 验证定性检测数据
if (DETECT_TYPE_QUALITATIVE.equals(item.getDetectType())) {
validateQualitativeItem(item, result);
}
// 验证必检项是否完成
if (Boolean.TRUE.equals(item.getIsRequired()) && !Boolean.TRUE.equals(item.getIsCompleted())) {
result.addError("必检项未完成: " + item.getItemName());
}
}
/**
*
*/
private static void validateQuantitativeItem(QcInspectionItemDetailVo item, ValidationResult result) {
if (item.getValue() == null) {
result.addError("定量检测项缺少检测值: " + item.getItemName());
return;
}
// 验证检测值的合理性
BigDecimal value = item.getValue();
if (value.compareTo(BigDecimal.ZERO) < 0) {
// 根据实际业务需求,某些检测项可能允许负值
log.warn("检测值为负数: {}, 检测项: {}", value, item.getItemName());
}
// 验证检测值是否在合理范围内(可以根据业务需求设置极值检查)
BigDecimal maxReasonableValue = new BigDecimal("999999999");
BigDecimal minReasonableValue = new BigDecimal("-999999999");
if (value.compareTo(maxReasonableValue) > 0 || value.compareTo(minReasonableValue) < 0) {
result.addError("检测值超出合理范围: " + value + ", 检测项: " + item.getItemName());
}
}
/**
*
*/
private static void validateQualitativeItem(QcInspectionItemDetailVo item, ValidationResult result) {
if (item.getResultStatus() == null && StringUtils.isBlank(item.getResult())) {
result.addError("定性检测项未选择结果: " + item.getItemName());
}
}
/**
*
*/
public static class ValidationResult {
private boolean valid = true;
private StringBuilder errors = new StringBuilder();
public boolean isValid() {
return valid;
}
public void setValid(boolean valid) {
this.valid = valid;
}
public String getErrors() {
return errors.toString();
}
public void addError(String error) {
this.valid = false;
if (errors.length() > 0) {
errors.append("; ");
}
errors.append(error);
}
public boolean hasErrors() {
return !valid;
}
}
}

@ -0,0 +1,38 @@
<?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="org.dromara.qms.mapper.QcUnqualifiedRecordMapper">
<resultMap type="QcUnqualifiedRecord" id="QcUnqualifiedRecordResult">
<result property="recordId" column="record_id" />
<result property="tenantId" column="tenant_id" />
<result property="reviewId" column="review_id" />
<result property="remark" column="remark" />
<result property="createDept" column="create_dept" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="delFlag" column="del_flag" />
</resultMap>
<sql id="selectQcUnqualifiedRecordVo">
select record_id, tenant_id, review_id, remark, create_dept, create_by, create_time, update_by, update_time, del_flag
from qc_unqualified_record
</sql>
<select id="selectQcUnqualifiedRecordList" parameterType="QcUnqualifiedRecord" resultMap="QcUnqualifiedRecordResult">
<include refid="selectQcUnqualifiedRecordVo"/>
<where>
<if test="recordId != null "> and record_id = #{recordId}</if>
<if test="reviewId != null "> and review_id = #{reviewId}</if>
</where>
</select>
<select id="selectQcUnqualifiedRecordByRecordId" parameterType="Long" resultMap="QcUnqualifiedRecordResult">
<include refid="selectQcUnqualifiedRecordVo"/>
where record_id = #{recordId}
</select>
</mapper>

@ -0,0 +1,61 @@
<?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="org.dromara.qms.mapper.QcUnqualifiedReviewMapper">
<resultMap type="QcUnqualifiedReview" id="QcUnqualifiedReviewResult">
<result property="reviewId" column="review_id" />
<result property="tenantId" column="tenant_id" />
<result property="unqualifiedNo" column="unqualified_no" />
<result property="inspectionId" column="inspection_id" />
<result property="typeId" column="type_id" />
<result property="workOrder" column="work_order" />
<result property="processCode" column="process_code" />
<result property="processName" column="process_name" />
<result property="batchNo" column="batch_no" />
<result property="materialName" column="material_name" />
<result property="materialCode" column="material_code" />
<result property="inspectorResult" column="inspector_result" />
<result property="reviewResult" column="review_result" />
<result property="reviewer" column="reviewer" />
<result property="reviewTime" column="review_time" />
<result property="createDept" column="create_dept" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="delFlag" column="del_flag" />
</resultMap>
<sql id="selectQcUnqualifiedReviewVo">
select review_id, tenant_id, unqualified_no, inspection_id, type_id, work_order, process_code, process_name, batch_no, material_name, material_code, inspector_result, review_result, reviewer, review_time, create_dept, create_by, create_time, update_by, update_time, del_flag
from qc_unqualified_review
</sql>
<select id="selectQcUnqualifiedReviewList" parameterType="QcUnqualifiedReview" resultMap="QcUnqualifiedReviewResult">
<include refid="selectQcUnqualifiedReviewVo"/>
<where>
<if test="reviewId != null "> and review_id = #{reviewId}</if>
<if test="unqualifiedNo != null and unqualifiedNo != ''"> and unqualified_no = #{unqualifiedNo}</if>
<if test="inspectionId != null "> and inspection_id = #{inspectionId}</if>
<if test="typeId != null "> and type_id = #{typeId}</if>
<if test="workOrder != null and workOrder != ''"> and work_order = #{workOrder}</if>
<if test="processCode != null and processCode != ''"> and process_code = #{processCode}</if>
<if test="processName != null and processName != ''"> and process_name like concat('%', #{processName}, '%')</if>
<if test="batchNo != null and batchNo != ''"> and batch_no = #{batchNo}</if>
<if test="materialName != null and materialName != ''"> and material_name like concat('%', #{materialName}, '%')</if>
<if test="materialCode != null and materialCode != ''"> and material_code = #{materialCode}</if>
<if test="inspectorResult != null and inspectorResult != ''"> and inspector_result = #{inspectorResult}</if>
<if test="reviewResult != null and reviewResult != ''"> and review_result = #{reviewResult}</if>
<if test="reviewer != null and reviewer != ''"> and reviewer = #{reviewer}</if>
<if test="reviewTime != null "> and review_time = #{reviewTime}</if>
</where>
</select>
<select id="selectQcUnqualifiedReviewByReviewId" parameterType="Long" resultMap="QcUnqualifiedReviewResult">
<include refid="selectQcUnqualifiedReviewVo"/>
where review_id = #{reviewId}
</select>
</mapper>
Loading…
Cancel
Save