盘点模块修改

This commit is contained in:
2025-09-16 15:23:04 +08:00
parent 29226c104f
commit 2e32af8fbe
9 changed files with 105 additions and 32 deletions

View File

@@ -66,8 +66,9 @@ public class InventoryMatchScanServiceImpl implements InventoryMatchScanService
}
// 状态=1查询指定仓库下未被扫描的库位
else if ("1".equals(param.getStatus())) {
String wh = taskMapper.getWhByTaskId(param.getTaskId()); // 根据任务ID获取仓库ID
return rkInfoMapper.getUnscannedPcodeByWh(wh, param.getTaskId());
// 根据任务ID取 sceneId再按 scene 查询“未被扫描”的库位
String sceneId = taskMapper.getSceneByTaskId(param.getTaskId());
return rkInfoMapper.getUnscannedPcodeByScene(sceneId, param.getTaskId());
}
// 其它情况:返回扫描表和库存表的关联数据
else {

View File

@@ -74,6 +74,13 @@ public interface InventoryTaskMapper
*/
String getWhByTaskId(String taskId);
/**
* 根据任务ID查询场景ID
* @param taskId
* @return
*/
String getSceneByTaskId(@Param("taskId") String taskId);
/**
* 更新任务状态
* @param taskId

View File

@@ -2,6 +2,7 @@ package com.zg.project.information.mapper;
import java.util.List;
import com.zg.project.information.domain.PcdeDetail;
import org.apache.ibatis.annotations.Param;
/**
* 库位明细Mapper接口
@@ -66,4 +67,11 @@ public interface PcdeDetailMapper
* @return
*/
PcdeDetail selectByPcode(String pcode);
/**
* 根据仓库编码查询库位编码
* @param pcode
* @return
*/
String selectEncodedIdByPcode(@Param("pcode") String pcode);;
}

View File

@@ -153,10 +153,11 @@ public interface RkInfoMapper
/**
* 根据所属仓库查询所有的库位号和库位对应的货物数量
* @param wh
* @param
* @return
*/
List<RkInfoMatchVO> getUnscannedPcodeByWh(@Param("wh") String wh, @Param("taskId") String taskId);
List<RkInfoMatchVO> getUnscannedPcodeByScene(@Param("sceneId") String sceneId,
@Param("taskId") String taskId);
/**
* 图表统计:每个库位有多少个货物

View File

@@ -18,6 +18,7 @@ import com.zg.project.Inventory.domain.dto.QueryDTO;
import com.zg.project.Inventory.domain.entity.InventoryMatchScan;
import com.zg.project.Inventory.domain.vo.ChartDataVO;
import com.zg.project.Inventory.domain.vo.PcdeCntVO;
import com.zg.project.information.mapper.PcdeDetailMapper;
import com.zg.project.system.service.ISysConfigService;
import com.zg.project.wisdom.domain.AuditSignature;
import com.zg.project.wisdom.domain.GysJh;
@@ -63,6 +64,10 @@ public class RkInfoServiceImpl implements IRkInfoService
@Autowired
private ISysConfigService configService;
@Autowired
private PcdeDetailMapper pcdeDetailMapper;
/**
* 查询库存单据主
*
@@ -326,6 +331,8 @@ public class RkInfoServiceImpl implements IRkInfoService
for (PcRkInfoItemDTO item : list) {
RkInfo rk = new RkInfo();
BeanUtils.copyProperties(item, rk);
String encodedId = pcdeDetailMapper.selectEncodedIdByPcode(item.getPcode());
rk.setPcodeId(encodedId);
rk.setBillNo(billNo);
rk.setRkType(dto.getRkType());
rk.setWlType(dto.getWlType());
@@ -738,37 +745,44 @@ public class RkInfoServiceImpl implements IRkInfoService
}
@Override
@Transactional(rollbackFor = Exception.class)
@Transactional(rollbackFor = Exception.class) // 开启事务,异常时回滚
public void matchWithStatus(QueryDTO dto) {
// 从 DTO 获取待比对的库位 ID 列表
List<String> pcdeIds = dto.getIds();
if (pcdeIds == null || pcdeIds.isEmpty()) return;
if (pcdeIds == null || pcdeIds.isEmpty()) return; // 如果为空,直接返回
// 场景ID优先取 DTO;没有就通过任务查
// 通过任务 ID 获取场景 ID优先取 DTO 中的,若无则从任务表查)
String sceneId = taskMapper.selectSceneIdById(dto.getTaskId());
if (sceneId == null || sceneId.trim().isEmpty()) {
throw new ServiceException("匹配失败缺少场景ID");
}
// 自动盘点必须设备ID
// 自动盘点必须设备 ID
String deviceId = dto.getDeviceId();
int scanType = dto.getScanType() != null ? dto.getScanType() : 0;
int scanType = dto.getScanType() != null ? dto.getScanType() : 0; // 扫描类型0=手动盘点1=自动盘点
String taskId = dto.getTaskId();
// 校验若是自动盘点scanType=1但未传设备 ID则报错
if (scanType == 1 && (deviceId == null || deviceId.trim().isEmpty())) {
throw new ServiceException("自动盘点必须传递设备ID");
}
// 三类数据(限定在 sceneId 内)
// ====================== 分类匹配三类数据 ======================
// 1. 正常匹配的数据(库位 ID 存在于库存表中,且属于当前场景 sceneId
List<RkInfo> matchedAll = rkInfoMapper.getByPcodeIdList(pcdeIds, sceneId);
matchedAll.forEach(r -> r.setStatus("0"));
matchedAll.forEach(r -> r.setStatus("0")); // 标记状态 0匹配成功
// 2. 未盘点的数据(存在于库存表,但未出现在传入的 pcdeIds 中)
List<RkInfo> missedAll = rkInfoMapper.getMissedPcodeIds(pcdeIds, sceneId);
missedAll.forEach(r -> r.setStatus("1"));
missedAll.forEach(r -> r.setStatus("1")); // 标记状态 1未盘点
// 3. 异常数据(传入的库位 ID 在库存中不存在)
List<String> errorIds = pcdeIds.stream()
.filter(id -> rkInfoMapper.existsByPcodeId(id, sceneId) == 0)
.filter(id -> rkInfoMapper.existsByPcodeId(id, sceneId) == 0) // 判断库位是否存在
.collect(Collectors.toList());
// 将异常库位 ID 封装成 RkInfo 对象,状态设为 2错误
List<RkInfo> errorAll = errorIds.stream().map(id -> {
RkInfo r = new RkInfo();
r.setPcodeId(id);
@@ -776,29 +790,47 @@ public class RkInfoServiceImpl implements IRkInfoService
return r;
}).collect(Collectors.toList());
// 统一落表
// ====================== 扫描结果落库 ======================
// 当前时间字符串
String tmeStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
List<InventoryMatchScan> toSave = new ArrayList<>();
// 将匹配成功的数据封装成扫描记录
for (RkInfo r : matchedAll) {
toSave.add(buildScanRecord(taskId, r.getPcodeId(), "0", deviceId, tmeStr, scanType));
toSave.add(buildScanRecord(taskId, r.getPcode(), "0", deviceId, tmeStr, scanType));
}
// 将未盘点的数据封装成扫描记录
for (RkInfo r : missedAll) {
toSave.add(buildScanRecord(taskId, r.getPcodeId(), "1", deviceId, tmeStr, scanType));
toSave.add(buildScanRecord(taskId, r.getPcode(), "1", deviceId, tmeStr, scanType));
}
// 将异常数据封装成扫描记录
for (RkInfo r : errorAll) {
toSave.add(buildScanRecord(taskId, r.getPcodeId(), "2", deviceId, tmeStr, scanType));
}
// 批量插入数据库
if (!toSave.isEmpty()) {
matchScanMapper.insertBatch(toSave);
}
// 更新任务状态为“已完成”(状态=1
if (taskId != null && !taskId.trim().isEmpty()) {
taskMapper.updateStatus(taskId, "1"); // 已完成
taskMapper.updateStatus(taskId, "1");
}
}
/**
* 封装一个盘点扫描记录
*
* @param taskId 任务 ID
* @param pcode 库位编码 ID
* @param status 盘点状态0=匹配成功1=未盘点2=错误)
* @param deviceId 设备 ID自动盘点时才有
* @param tme 扫描时间
* @param scanType 扫描类型0=手动盘点1=自动盘点)
* @return 封装好的 InventoryMatchScan 对象
*/
private InventoryMatchScan buildScanRecord(String taskId, String pcode, String status,
String deviceId, String tme, int scanType) {
InventoryMatchScan record = new InventoryMatchScan();
@@ -806,6 +838,7 @@ public class RkInfoServiceImpl implements IRkInfoService
record.setTaskId(taskId);
record.setStatus(status);
// 自动盘点时才保存设备 ID
if (scanType == 1 && deviceId != null) {
record.setDeviceId(deviceId);
}

View File

@@ -196,10 +196,10 @@
parameterType="InventoryMatchScan"
resultType="com.zg.project.Inventory.domain.vo.RkInfoMatchVO">
SELECT
r.pcode AS rkPcode,
COALESCE(SUM(r.real_qty), 0) AS realQty
r.pcode AS rkPcode,
COALESCE(SUM(r.real_qty), 0) AS realQty
FROM rk_info r
WHERE r.pcode_id IN (
WHERE r.pcode IN (
SELECT DISTINCT i.pcode
FROM inventory_match_scan i
<where>

View File

@@ -85,6 +85,13 @@
where id = #{taskId}
</select>
<select id="getSceneByTaskId"
resultType="java.lang.String" parameterType="java.lang.String">
SELECT scene_id
FROM inventory_task
WHERE id = #{taskId}
</select>
<select id="selectSceneIdById" parameterType="string" resultType="java.lang.String">
SELECT scene_id
FROM inventory_task

View File

@@ -76,6 +76,13 @@
AND is_delete = '0'
</select>
<select id="selectEncodedIdByPcode" resultType="java.lang.String" parameterType="java.lang.String">
select encoded_id
from pcde_detail
where pcode = #{pcode}
AND is_delete = '0'
</select>
<insert id="insertPcdeDetail" parameterType="PcdeDetail" useGeneratedKeys="true" keyProperty="id">
insert into pcde_detail
<trim prefix="(" suffix=")" suffixOverrides=",">
@@ -134,4 +141,5 @@
#{id}
</foreach>
</delete>
</mapper>

View File

@@ -653,19 +653,27 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND is_chuku = '0'
</select>
<select id="getUnscannedPcodeByWh" resultType="com.zg.project.Inventory.domain.vo.RkInfoMatchVO">
<select id="getUnscannedPcodeByScene"
resultType="com.zg.project.Inventory.domain.vo.RkInfoMatchVO">
SELECT
r.pcode AS rkPcode,
r.real_qty AS realQty
FROM rk_info r
WHERE r.cangku = #{wh}
AND r.pcode_id NOT IN (
SELECT i.pcode
FROM inventory_match_scan i
WHERE i.task_id = #{taskId}
AND i.status = '0' <!-- 过滤掉扫描成功的 -->
)
ORDER BY r.create_time DESC
r.pcode AS rkPcode,
COALESCE(SUM(r.real_qty), 0) AS realQty
FROM pcde_detail d
JOIN rk_info r
ON r.pcode = d.pcode
LEFT JOIN (
SELECT DISTINCT pcode
FROM inventory_match_scan
WHERE task_id = #{taskId}
AND status = '0'
) s
ON s.pcode = r.pcode
WHERE (d.is_delete IS NULL OR d.is_delete = '0')
AND d.scene = #{sceneId}
AND r.is_chuku = '0'
AND s.pcode IS NULL
GROUP BY r.pcode
ORDER BY MAX(r.create_time) DESC
</select>
<select id="selectPcdeCntFromRkInfo" resultType="com.zg.project.Inventory.domain.vo.PcdeCntVO">