Compare commits

...

8 Commits

Author SHA1 Message Date
曹鹏飞 fbb1e90ae4 fix(repository): 处理来料检验任务检查数量为空问题
- 修改SQL查询,使用COALESCE确保返回值不为null
- 避免inspection_qty为空时返回null导致的异常
- 提升后台数据查询的稳定性和准确性
2026-04-29 11:40:19 +08:00
曹鹏飞 998cbbb074 Merge remote-tracking branch '惠信/qms/develop' into qms/develop 2026-04-29 11:26:54 +08:00
曹鹏飞 61fa709345 refactor(qms-admin): 优化来料检验任务回调处理逻辑
- 将submit方法添加事务注解,确保操作原子性
- 移除控制器层多余的@Transactional注解,精简代码结构
- 修改回调调用方式,去除多余参数,简化接口调用
- 在WmsIncomingInspectionTaskCallbackService中增强回调处理逻辑
- 根据检验结果动态处理回调,避免重复回调
- 新增基于工单状态自动获取处理结果的处理路径
- 修正任务查询SQL,增加detection_qty字段数据支持
- 初始化QmsIncomingInspectionTaskVO已检数量字段防止空指针
2026-04-29 11:26:48 +08:00
funny e60b389ffc Merge branch 'qms/yf' into qms/develop 2026-04-29 11:18:38 +08:00
曹鹏飞 b17e1fcec8 feat(inspection): 优化送检及检测数量管理
- 调整送检数量字段注释和校验信息的描述
- 在入库检验任务服务逻辑中根据检测方法设置检测数量
- 实体及VO中新增检测数量与已检数量属性,并计算未检数量
- Mapper接口及XML新增获取已检数量的数据库查询方法
- 在获取任务详情时设置已检数量以供前端显示使用
2026-04-29 10:30:28 +08:00
曹鹏飞 66e5407cbf feat(exempt-material): 实现批量判断免检物料功能
- 在IQmsExemptMaterialService接口添加batchCheckExempt方法定义
- QmsExemptMaterialMapper新增batchCheckExempt数据库查询方法及对应XML实现
- 在QmsExemptMaterialServiceImpl中实现batchCheckExempt业务逻辑
- 新增ExemptMaterialCheckQO请求对象用于传递供应商编号和物料编号
- 新增ExemptMaterialCheckVO响应对象用于返回免检判断结果
- 新增MaterialController对外提供批量免检判断接口
- 接口仅返回审核通过、启用且有效期内的免检物料组合
2026-04-29 09:59:00 +08:00
曹鹏飞 3b5e6b4ef2 Merge remote-tracking branch '惠信/qms/develop' into qms/develop 2026-04-29 09:35:20 +08:00
曹鹏飞 5ca36762ca fix(repository): 修复入库检验任务映射增加存储位置字段
- 在QmsIncomingInspectionTaskMapper.xml中添加storage_location字段
- 更新SQL查询,保证storage_location正确关联与查询
- 保留原storage_days字段,新增存储位置支持详细库位管理
- 优化入库检验任务数据完整性与可追溯性
2026-04-29 09:35:10 +08:00
17 changed files with 316 additions and 49 deletions

View File

@ -108,7 +108,6 @@ public class QmsIncomingInspectionTaskController extends BaseController {
/**
* 提交检测项
*/
@Transactional
@PostMapping("pad/add-check-item")
public ApiResult<Void> addCheckItem(@Valid @RequestBody QmsIncomingInspectionTaskTodoCheckSubmitQO request){
incomingInspectionTaskControllerService.submitCheckItem(request);
@ -118,7 +117,6 @@ public class QmsIncomingInspectionTaskController extends BaseController {
/**
* 暂存检验结果
*/
@Transactional
@PostMapping("pad/staging")
public ApiResult<Void> staging(@Valid @RequestBody QmsIncomingInspectionTaskSubmitQO request){
incomingInspectionTaskControllerService.staging(request);
@ -128,7 +126,6 @@ public class QmsIncomingInspectionTaskController extends BaseController {
/**
* 提交检验结果
*/
@Transactional
@PostMapping("pad/submit")
public ApiResult<Void> submit(@Valid @RequestBody QmsIncomingInspectionTaskSubmitQO request){
incomingInspectionTaskControllerService.submit(request);
@ -140,7 +137,7 @@ public class QmsIncomingInspectionTaskController extends BaseController {
*/
@PostMapping("callback")
public ApiResult<Void> callback(@RequestParam Long taskId){
wmsIncomingInspectionTaskCallbackService.process(taskId, (short) 0);
wmsIncomingInspectionTaskCallbackService.process(taskId);
return ApiResult.success();
}
}

View File

@ -0,0 +1,42 @@
package com.nflg.qms.admin.controller.external;
import com.nflg.wms.common.pojo.ApiResult;
import com.nflg.wms.common.pojo.qo.ExemptMaterialCheckQO;
import com.nflg.wms.common.pojo.vo.ExemptMaterialCheckVO;
import com.nflg.wms.repository.service.IQmsExemptMaterialService;
import com.nflg.wms.starter.BaseController;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import org.springframework.validation.annotation.Validated;
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;
/**
* 对外接口-物料信息
* @folder 对外接口/物料信息
*/
@Validated
@RestController
@RequestMapping("/external/material")
public class MaterialController extends BaseController {
@Resource
private IQmsExemptMaterialService exemptMaterialService;
/**
* 批量判断物料是否免检
* - 参数为供应商编号和物料编号的组合列表
* - 根据系统中已审核已启用且在有效期内的免检设置判断
* - 返回每个组合的免检标志exempt=true 表示免检
*/
@PostMapping("batchCheckExempt")
public ApiResult<List<ExemptMaterialCheckVO>> batchCheckExempt(
@Valid @RequestBody @NotEmpty List<ExemptMaterialCheckQO> request) {
return ApiResult.success(exemptMaterialService.batchCheckExempt(request));
}
}

View File

@ -224,6 +224,18 @@ public class IncomingInspectionTaskControllerService {
.setTriggerTime(LocalDateTime.now())
);
}
// 9. 设置检测数量
Integer total;
if (Objects.equals(standard.getTestingMethodDictItemId(), dictionaryItemService.getIdByCode("InspectionStandardTestingMethod", "Full"))) {
total = task.getInspectionQty();
} else {
total = getCountOfSampling(task.getId(), task.getInspectionQty(), standard);
}
incomingInspectionTaskService.lambdaUpdate()
.set(QmsIncomingInspectionTask::getDetectionQty, total)
.eq(QmsIncomingInspectionTask::getId, task.getId())
.update();
}
/**
@ -333,6 +345,18 @@ public class IncomingInspectionTaskControllerService {
.setTriggerTime(LocalDateTime.now())
);
}
// 9. 设置检测数量
Integer total;
if (Objects.equals(standard.getTestingMethodDictItemId(), dictionaryItemService.getIdByCode("InspectionStandardTestingMethod", "Full"))) {
total = task.getInspectionQty();
} else {
total = getCountOfSampling(task.getId(), task.getInspectionQty(), standard);
}
incomingInspectionTaskService.lambdaUpdate()
.set(QmsIncomingInspectionTask::getDetectionQty, total)
.eq(QmsIncomingInspectionTask::getId, task.getId())
.update();
}
private DictionaryItem getAql(Long id, List<DictionaryItem> aqls) {
@ -521,6 +545,7 @@ public class IncomingInspectionTaskControllerService {
public QmsIncomingInspectionTaskVO getDetail(Long id) {
QmsIncomingInspectionTaskVO detail = incomingInspectionTaskService.getDetail(id);
VUtil.trueThrowBusinessError(Objects.isNull(detail)).throwMessage("任务不存在");
detail.setInspectedQty(incomingInspectionTaskService.getInspectedQty(id));
return detail;
}
@ -918,6 +943,7 @@ public class IncomingInspectionTaskControllerService {
updateWrapper.update();
}
@Transactional
public void submit(@Valid QmsIncomingInspectionTaskSubmitQO request) {
QmsIncomingInspectionTask task = incomingInspectionTaskService.getById(request.getTaskId());
VUtil.trueThrowBusinessError(Objects.isNull(task)).throwMessage("任务不存在");
@ -960,7 +986,7 @@ public class IncomingInspectionTaskControllerService {
updateWrapper.update();
if (task.getInspectionResult()) {
wmsIncomingInspectionTaskCallbackService.process(task.getId(), (short) 0);
wmsIncomingInspectionTaskCallbackService.process(task.getId());
} else {
issueTicketControllerService.initiate(task.getId());
}

View File

@ -8,8 +8,10 @@ import com.nflg.wms.common.pojo.vo.QmsIncomingInspectionTaskVO;
import com.nflg.wms.common.util.VUtil;
import com.nflg.wms.repository.entity.QmsIncomingInspectionTask;
import com.nflg.wms.repository.entity.QmsIncomingInspectionTaskRecord;
import com.nflg.wms.repository.entity.QmsIssueTicket;
import com.nflg.wms.repository.service.IQmsIncomingInspectionTaskRecordService;
import com.nflg.wms.repository.service.IQmsIncomingInspectionTaskService;
import com.nflg.wms.repository.service.IQmsIssueTicketService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
@ -17,6 +19,7 @@ import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Objects;
/**
* Wms来料检验任务回调服务
@ -40,6 +43,9 @@ public class WmsIncomingInspectionTaskCallbackService {
@Resource
private WmsApiService wmsApiService;
@Resource
private IQmsIssueTicketService issueTicketService;
/**
* 向WMS系统发送来料检验任务回调
*/
@ -152,11 +158,31 @@ public class WmsIncomingInspectionTaskCallbackService {
/**
* WMS系统来料检验任务回调
* @param taskId 来料检验任务ID
*/
public void process(Long taskId) {
QmsIncomingInspectionTaskVO taskVO = incomingInspectionTaskService.getDetail(taskId);
VUtil.trueThrowBusinessError(Objects.equals(taskVO.getCallbackResult(), true)).throwMessage("请勿重复回调");
VUtil.trueThrowBusinessError(taskVO.getInspectionStatus() != 2).throwMessage("来料检验任务状态不允许回调");
if (taskVO.getInspectionResult()) {
process(taskVO, (short) 0);
} else {
QmsIssueTicket issueTicket = issueTicketService.lambdaQuery()
.eq(QmsIssueTicket::getSourceId, taskId)
.eq(QmsIssueTicket::getStatus, 2)
.orderByDesc(QmsIssueTicket::getId)
.last("limit 1")
.one();
VUtil.trueThrowBusinessError(Objects.isNull(issueTicket)).throwMessage("未找到符合条件的工单");
process(taskVO, issueTicket.getApprovalStatus());
}
}
/**
* WMS系统来料检验任务回调
* @param taskVO 来料检验任务VO
* @param processingResult 处理结果0=通过3=报废4=维修5=挑选使用6=让渡使用
*/
public void process(Long taskId, Short processingResult) {
QmsIncomingInspectionTaskVO taskVO = incomingInspectionTaskService.getDetail(taskId);
VUtil.trueThrowBusinessError(taskVO.getCallbackResult()).throwMessage("请勿重复回调");
private void process(QmsIncomingInspectionTaskVO taskVO, Short processingResult) {
switch (taskVO.getInspectionType()) {
case 1:
incoming(taskVO,processingResult);
@ -169,4 +195,15 @@ public class WmsIncomingInspectionTaskCallbackService {
break;
}
}
/**
* WMS系统来料检验任务回调
* @param taskId 来料检验任务ID
* @param processingResult 处理结果0=通过3=报废4=维修5=挑选使用6=让渡使用
*/
private void process(Long taskId, Short processingResult) {
QmsIncomingInspectionTaskVO taskVO = incomingInspectionTaskService.getDetail(taskId);
VUtil.trueThrowBusinessError(Objects.equals(taskVO.getCallbackResult(),true)).throwMessage("请勿重复回调");
process(taskVO, processingResult);
}
}

View File

@ -0,0 +1,23 @@
package com.nflg.wms.common.pojo.qo;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
/**
* 免检物料判断 单条请求对象
*/
@Data
public class ExemptMaterialCheckQO {
/**
* 供应商编号
*/
@NotBlank(message = "供应商编号不能为空")
private String supplierCode;
/**
* 物料编号
*/
@NotBlank(message = "物料编号不能为空")
private String materialNo;
}

View File

@ -66,10 +66,10 @@ public class ExternalIncomingInspectionApplyQO {
private String factory;
/**
* 数量必填即送检数量
* 检数量必填
*/
@NotNull(message = "数量不能为空")
@Min(value = 1, message = "数量必须大于0")
@NotNull(message = "检数量不能为空")
@Min(value = 1, message = "检数量必须大于0")
private Integer inspectionQty;
/**

View File

@ -0,0 +1,25 @@
package com.nflg.wms.common.pojo.vo;
import lombok.Data;
/**
* 免检物料判断 结果VO
*/
@Data
public class ExemptMaterialCheckVO {
/**
* 供应商编号
*/
private String supplierCode;
/**
* 物料编号
*/
private String materialNo;
/**
* 是否免检true=免检false=非免检
*/
private Boolean exempt;
}

View File

@ -103,7 +103,7 @@ public class QmsIncomingInspectionTaskVO {
private Integer inspectionType;
/**
* 数量
* 检数量
*/
private Integer inspectionQty;
@ -117,6 +117,25 @@ public class QmsIncomingInspectionTaskVO {
*/
private Integer unqualifiedQty;
/**
* 检测数量
*/
private Integer detectionQty;
/**
* 已检数量
*/
private Integer inspectedQty = 0;
/**
* 未检数量
*/
private Integer uninspectedQty;
public Integer getUninspectedQty() {
return detectionQty - inspectedQty;
}
/**
* 检验状态0=待检1=已检
*/

View File

@ -88,7 +88,7 @@ public class QmsIncomingInspectionTask implements Serializable {
private Integer inspectionType;
/**
* 检验数量送检数量
* 送检数量
*/
private Integer inspectionQty;
@ -102,6 +102,11 @@ public class QmsIncomingInspectionTask implements Serializable {
*/
private Integer unqualifiedQty;
/**
* 检测数量
*/
private Integer detectionQty;
/**
* 检验状态0=待检1=检验中2=已检
*/

View File

@ -4,6 +4,7 @@ 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.QmsExemptMaterialSearchQO;
import com.nflg.wms.common.pojo.vo.ExemptMaterialCheckVO;
import com.nflg.wms.common.pojo.vo.QmsExemptMaterialVO;
import com.nflg.wms.repository.entity.QmsExemptMaterial;
import org.apache.ibatis.annotations.Param;
@ -29,4 +30,11 @@ public interface QmsExemptMaterialMapper extends BaseMapper<QmsExemptMaterial> {
* 按物料编号查询关联的供应商免检明细
*/
List<QmsExemptMaterialVO> detailByMaterial(@Param("materialNo") String materialNo);
/**
* 批量查询有效免检物料供应商编号+物料编号组合
* 仅返回审核通过启用且在有效期内的记录
*/
List<ExemptMaterialCheckVO> batchCheckExempt(@Param("supplierCodes") List<String> supplierCodes,
@Param("materialNos") List<String> materialNos);
}

View File

@ -21,4 +21,6 @@ public interface QmsIncomingInspectionTaskMapper extends BaseMapper<QmsIncomingI
* 根据id查询任务详情
*/
QmsIncomingInspectionTaskVO getDetail(Long id);
Integer getInspectedQty(Long id);
}

View File

@ -2,9 +2,11 @@ package com.nflg.wms.repository.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.nflg.wms.common.pojo.qo.ExemptMaterialCheckQO;
import com.nflg.wms.common.pojo.qo.QmsExemptMaterialAuditQO;
import com.nflg.wms.common.pojo.qo.QmsExemptMaterialSaveQO;
import com.nflg.wms.common.pojo.qo.QmsExemptMaterialSearchQO;
import com.nflg.wms.common.pojo.vo.ExemptMaterialCheckVO;
import com.nflg.wms.common.pojo.vo.QmsExemptMaterialVO;
import com.nflg.wms.repository.entity.QmsExemptMaterial;
@ -44,4 +46,10 @@ public interface IQmsExemptMaterialService extends IService<QmsExemptMaterial> {
* 审核免检物料
*/
void audit(QmsExemptMaterialAuditQO request);
/**
* 批量判断物料是否免检
* 根据供应商编号和物料编号判断返回每个组合的免检标志
*/
List<ExemptMaterialCheckVO> batchCheckExempt(List<ExemptMaterialCheckQO> items);
}

View File

@ -48,4 +48,6 @@ public interface IQmsIncomingInspectionTaskService extends IService<QmsIncomingI
* @return 任务详情
*/
QmsIncomingInspectionTaskVO getDetail(Long id);
Integer getInspectedQty(Long id);
}

View File

@ -6,9 +6,11 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nflg.wms.common.constant.STATE;
import com.nflg.wms.common.exception.NflgException;
import com.nflg.wms.common.pojo.qo.ExemptMaterialCheckQO;
import com.nflg.wms.common.pojo.qo.QmsExemptMaterialAuditQO;
import com.nflg.wms.common.pojo.qo.QmsExemptMaterialSaveQO;
import com.nflg.wms.common.pojo.qo.QmsExemptMaterialSearchQO;
import com.nflg.wms.common.pojo.vo.ExemptMaterialCheckVO;
import com.nflg.wms.common.pojo.vo.QmsExemptMaterialVO;
import com.nflg.wms.common.util.StringUtil;
import com.nflg.wms.common.util.UserUtil;
@ -21,7 +23,10 @@ import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 免检物料 服务实现类
@ -166,4 +171,36 @@ public class QmsExemptMaterialServiceImpl extends ServiceImpl<QmsExemptMaterialM
}
return LocalDateTime.parse(dateStr, DATE_FMT);
}
@Override
public List<ExemptMaterialCheckVO> batchCheckExempt(List<ExemptMaterialCheckQO> items) {
// 提取所有供应商编号和物料编号
List<String> supplierCodes = items.stream()
.map(ExemptMaterialCheckQO::getSupplierCode)
.distinct()
.collect(Collectors.toList());
List<String> materialNos = items.stream()
.map(ExemptMaterialCheckQO::getMaterialNo)
.distinct()
.collect(Collectors.toList());
// 一次性查询所有有效免检组合
List<ExemptMaterialCheckVO> exemptList = baseMapper.batchCheckExempt(supplierCodes, materialNos);
// 构建免检组合的快速查询集合格式supplierCode:materialNo
Set<String> exemptSet = exemptList.stream()
.map(v -> v.getSupplierCode() + ":" + v.getMaterialNo())
.collect(Collectors.toCollection(HashSet::new));
// 构建返回结果
List<ExemptMaterialCheckVO> result = new ArrayList<>(items.size());
for (ExemptMaterialCheckQO item : items) {
ExemptMaterialCheckVO vo = new ExemptMaterialCheckVO();
vo.setSupplierCode(item.getSupplierCode());
vo.setMaterialNo(item.getMaterialNo());
vo.setExempt(exemptSet.contains(item.getSupplierCode() + ":" + item.getMaterialNo()));
result.add(vo);
}
return result;
}
}

View File

@ -64,4 +64,9 @@ public class QmsIncomingInspectionTaskServiceImpl extends ServiceImpl<QmsIncomin
public QmsIncomingInspectionTaskVO getDetail(Long id) {
return baseMapper.getDetail(id);
}
@Override
public Integer getInspectedQty(Long id) {
return baseMapper.getInspectedQty(id);
}
}

View File

@ -134,4 +134,27 @@
ORDER BY em.create_time DESC
</select>
<!-- 批量查询有效免检物料(供应商编号+物料编号组合),仅返回审核通过、启用且在有效期内的记录 -->
<select id="batchCheckExempt" resultType="com.nflg.wms.common.pojo.vo.ExemptMaterialCheckVO">
SELECT
us.supplier_code AS supplierCode,
em.material_no AS materialNo
FROM qms_exempt_material em
INNER JOIN user_supplier us ON us.id = em.supplier_id
WHERE em.audit_status = 1
AND em.enable = true
AND (
em.exempt_mode = 0
OR (em.exempt_mode = 1 AND em.valid_end_date IS NOT NULL AND em.valid_end_date &gt;= NOW())
)
AND us.supplier_code IN
<foreach collection="supplierCodes" item="code" open="(" separator="," close=")">
#{code}
</foreach>
AND em.material_no IN
<foreach collection="materialNos" item="no" open="(" separator="," close=")">
#{no}
</foreach>
</select>
</mapper>

View File

@ -41,7 +41,8 @@
t.purchase_group,
t.callback_result,
t.warehouse,
t.storage_days
t.storage_days,
t.storage_location
FROM qms_incoming_inspection_task t
LEFT JOIN qms_qc_material m ON t.material_id = m.id
LEFT JOIN qms_inspection_standard s ON t.inspection_standard_id = s.id
@ -137,7 +138,8 @@
t2.task_no as related_task_no,
t.update_user_id,
t.update_user_name,
t.update_time
t.update_time,
t.detection_qty
FROM qms_incoming_inspection_task t
LEFT JOIN qms_qc_material m ON t.material_id = m.id
LEFT JOIN qms_inspection_standard s ON t.inspection_standard_id = s.id
@ -214,7 +216,8 @@
t.warehouse,
t.storage_location,
t.storage_days,
t.callback_result
t.callback_result,
t.detection_qty
FROM qms_incoming_inspection_task t
LEFT JOIN qms_qc_material m ON t.material_id = m.id
LEFT JOIN qms_inspection_standard s ON t.inspection_standard_id = s.id
@ -222,4 +225,9 @@
WHERE t.id = #{id}
</select>
<select id="getInspectedQty" resultType="java.lang.Integer">
SELECT COALESCE(SUM(inspection_qty),0)
FROM qms_incoming_inspection_task_record
WHERE task_id=#{id}
</select>
</mapper>