Browse Source

2025-10-31

pda调整扫描、查询、确认逻辑(生产入库)
master
fengyuan_yang 11 months ago
parent
commit
c06bf66f50
  1. 77
      src/main/java/com/gaotao/modules/productionInbound/controller/ProductionInboundController.java
  2. 9
      src/main/java/com/gaotao/modules/productionInbound/dao/ProductionInboundMapper.java
  3. 41
      src/main/java/com/gaotao/modules/productionInbound/service/ProductionInboundService.java
  4. 163
      src/main/java/com/gaotao/modules/productionInbound/service/impl/ProductionInboundServiceImpl.java
  5. 16
      src/main/resources/mapper/productionInbound/ProductionInboundMapper.xml

77
src/main/java/com/gaotao/modules/productionInbound/controller/ProductionInboundController.java

@ -86,19 +86,17 @@ public class ProductionInboundController extends AbstractController {
}
/**
* 验证生产标签与入库单是否匹配
* 从SFDC_ROLLS表验证标签
* 返回多条子标签记录
* 验证生产标签通过存储过程
*/
@PostMapping("validateLabelWithInbound")
public R validateLabelWithInbound(@RequestBody Map<String, Object> params) {
try {
String labelCode = (String) params.get("labelCode");
String inboundNo = (String) params.get("inboundNo");
String partNo = (String) params.get("partNo");
String site = (String) params.get("site");
String buNo = (String) params.get("buNo");
String relatedOrderNo = (String) params.get("relatedOrderNo");
String operationType = (String) params.get("operationType");
if (labelCode == null || labelCode.trim().isEmpty()) {
return R.error("标签条码不能为空");
@ -106,10 +104,17 @@ public class ProductionInboundController extends AbstractController {
if (inboundNo == null || inboundNo.trim().isEmpty()) {
return R.error("入库单号不能为空");
}
if (operationType == null || operationType.trim().isEmpty()) {
operationType = "I"; // 默认为添加
}
// 返回子标签列表
List<Map<String, Object>> resultList = productionInboundService.validateLabelWithInbound(labelCode, inboundNo, partNo, site, buNo, relatedOrderNo);
return R.ok().put("data", resultList);
// 获取当前登录用户
String userName = getUser().getUsername();
// 调用存储过程验证标签
Map<String, Object> result = productionInboundService.validateLabelWithInbound(
site, buNo, relatedOrderNo, inboundNo, labelCode, operationType, userName);
return R.ok().put("data", result);
} catch (Exception e) {
logger.error("生产标签验证失败", e);
return R.error(e.getMessage());
@ -117,13 +122,7 @@ public class ProductionInboundController extends AbstractController {
}
/**
* 确认生产入库上架
* 系统逻辑
* 1. 更新SFDC_ROLLS表中的标签状态为"已入库"
* 2. 更改inbound_notification_head表中的单据状态入库状态为"已入库"
* 3. 在WMS库存表中插入标签数据状态为"在库"
* 4. 生成WMS入库记录Transheader...
* 5. 异步调用ERP接口回传数据
* 确认生产入库上架通过存储过程
*/
@PostMapping("confirmInboundStorage")
public R confirmInboundStorage(@RequestBody Map<String, Object> params) {
@ -133,7 +132,6 @@ public class ProductionInboundController extends AbstractController {
String site = (String) params.get("site");
String buNo = (String) params.get("buNo");
String relatedOrderNo = (String) params.get("relatedOrderNo");
List<Map<String, Object>> labels = (List<Map<String, Object>>) params.get("labels");
if (inboundNo == null || inboundNo.trim().isEmpty()) {
return R.error("入库单号不能为空");
@ -141,18 +139,15 @@ public class ProductionInboundController extends AbstractController {
if (locationCode == null || locationCode.trim().isEmpty()) {
return R.error("库位号不能为空");
}
if (labels == null || labels.isEmpty()) {
return R.error("标签列表不能为空");
if (relatedOrderNo == null || relatedOrderNo.trim().isEmpty()) {
return R.error("关联单号不能为空");
}
// 验证标签数据完整性
for (Map<String, Object> label : labels) {
String labelCode = (String) label.get("labelCode");
if (labelCode == null || labelCode.trim().isEmpty()) {
return R.error("标签条码不能为空");
}
}
boolean success = productionInboundService.confirmInboundStorage(inboundNo, locationCode, labels, site, buNo, relatedOrderNo);
// 获取当前登录用户
String userName = getUser().getUsername();
boolean success = productionInboundService.confirmInboundStorage(
site, buNo, relatedOrderNo, inboundNo, locationCode, userName);
if (success) {
return R.ok("上架成功");
} else {
@ -251,4 +246,36 @@ public class ProductionInboundController extends AbstractController {
return R.error("获取明细列表失败: " + e.getMessage());
}
}
/**
* 获取已扫描标签列表从缓存表
*/
@PostMapping("getScannedLabelList")
public R getScannedLabelList(@RequestBody Map<String, Object> params) {
try {
String site = (String) params.get("site");
String buNo = (String) params.get("buNo");
String relatedOrderNo = (String) params.get("relatedOrderNo");
String inboundNo = (String) params.get("inboundNo");
if (site == null || site.trim().isEmpty()) {
return R.error("站点不能为空");
}
if (buNo == null || buNo.trim().isEmpty()) {
return R.error("业务单元不能为空");
}
if (inboundNo == null || inboundNo.trim().isEmpty()) {
return R.error("入库单号不能为空");
}
List<Map<String, Object>> labelList = productionInboundService.getScannedLabelList(site, buNo, relatedOrderNo, inboundNo);
return R.ok().put("data", labelList);
} catch (Exception e) {
logger.error("获取已扫描标签列表失败", e);
return R.error("获取已扫描标签列表失败: " + e.getMessage());
}
}
}

9
src/main/java/com/gaotao/modules/productionInbound/dao/ProductionInboundMapper.java

@ -80,4 +80,13 @@ public interface ProductionInboundMapper {
List<Map<String, Object>> getInboundNotificationDetails(@Param("site") String site,
@Param("buNo") String buNo,
@Param("orderNo") String orderNo);
/**
* 获取已扫描标签列表从缓存表
* 数据来源ScannedRollTempTable
*/
List<Map<String, Object>> getScannedLabelList(@Param("site") String site,
@Param("buNo") String buNo,
@Param("relatedOrderNo") String relatedOrderNo,
@Param("inboundNo") String inboundNo);
}

41
src/main/java/com/gaotao/modules/productionInbound/service/ProductionInboundService.java

@ -28,34 +28,29 @@ public interface ProductionInboundService {
Map<String, Object> getInboundDetails(String orderNo, String warehouseId, String site, String buNo, String relatedOrderNo);
/**
* 验证生产标签与入库单是否匹配
* 从SFDC_ROLLS表验证标签信息
* @param labelCode 标签条码父标签
* @param orderNo 入库单号
* @param partNo 物料编码
* 验证生产标签通过存储过程
* @param site 站点
* @param buNo 业务单元
* @param relatedOrderNo 关联单号
* @return 标签信息列表多条子标签记录
* @param inboundNo 入库单号
* @param labelCode 标签条码
* @param operationType 操作类型 I-添加 D-移除
* @param userName 当前登录人
* @return 标签信息
*/
List<Map<String, Object>> validateLabelWithInbound(String labelCode, String orderNo, String partNo, String site, String buNo, String relatedOrderNo);
Map<String, Object> validateLabelWithInbound(String site, String buNo, String relatedOrderNo, String inboundNo, String labelCode, String operationType, String userName);
/**
* 确认生产入库上架
* 1. 更新SFDC_ROLLS表中的标签状态
* 2. 更新inbound_notification_head表状态
* 3. 插入库存数据
* 4. 生成事务记录
* @param orderNo 入库单号
* @param partNo 物料编码
* @param warehouseId 仓库ID
* @param locationCode 库位号
* @param labels 标签列表
* 确认生产入库上架通过存储过程
* @param site 站点
* @param buNo 业务单元
* @param relatedOrderNo 关联单号
* @param inboundNo 入库单号
* @param locationCode 库位号
* @param userName 当前登录人
* @return 处理结果
*/
boolean confirmInboundStorage(String orderNo, String locationCode, List<Map<String, Object>> labels, String site, String buNo, String relatedOrderNo);
boolean confirmInboundStorage(String site, String buNo, String relatedOrderNo, String inboundNo, String locationCode, String userName);
/**
* 获取生产物料清单
@ -76,4 +71,14 @@ public interface ProductionInboundService {
* @return 明细列表
*/
List<Map<String, Object>> getInboundNotificationDetails(String site, String buNo, String orderNo);
/**
* 获取已扫描标签列表从缓存表
* @param site 站点
* @param buNo 业务单元
* @param relatedOrderNo 关联单号
* @param inboundNo 入库单号
* @return 已扫描标签列表
*/
List<Map<String, Object>> getScannedLabelList(String site, String buNo, String relatedOrderNo, String inboundNo);
}

163
src/main/java/com/gaotao/modules/productionInbound/service/impl/ProductionInboundServiceImpl.java

@ -1,6 +1,5 @@
package com.gaotao.modules.productionInbound.service.impl;
import com.gaotao.common.exception.XJException;
import com.gaotao.modules.inventoryStock.dao.InventoryStockMapper;
import com.gaotao.modules.pms.entity.vo.PartLabelTemplateVo;
import com.gaotao.modules.productionInbound.dao.ProductionInboundMapper;
@ -25,7 +24,6 @@ import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class ProductionInboundServiceImpl implements ProductionInboundService {
@ -67,101 +65,89 @@ public class ProductionInboundServiceImpl implements ProductionInboundService {
}
@Override
public List<Map<String, Object>> validateLabelWithInbound(String labelCode, String orderNo, String partNo, String site, String buNo, String relatedOrderNo) {
logger.info("验证标签与入库单匹配,标签: {}, 入库单: {}, 关联单号: {}", labelCode, orderNo, relatedOrderNo);
public Map<String, Object> validateLabelWithInbound(String site, String buNo, String relatedOrderNo, String inboundNo, String labelCode, String operationType, String userName) {
logger.info("验证生产入库标签,site: {}, buNo: {}, 关联单号: {}, 入库单号: {}, 标签: {}, 操作类型: {}",
site, buNo, relatedOrderNo, inboundNo, labelCode, operationType);
// 从SFDC_ROLLS表验证标签信息返回多条子标签记录
List<Map<String, Object>> resultList = productionInboundMapper.validateLabelWithInbound(labelCode, orderNo, partNo, site, buNo, relatedOrderNo);
try {
// 调用存储过程 GetScanLabelVerification
List<Object> params = new ArrayList<>();
params.add(site); // 参数1: site
params.add(buNo); // 参数2: buNo
params.add(relatedOrderNo); // 参数3: 关联单号
params.add(inboundNo); // 参数4: 入库单号
params.add(""); // 参数5: 空字符串
params.add(""); // 参数6: 空字符串
params.add(""); // 参数7: 空字符串
params.add(labelCode); // 参数8: 扫描的标签条码
params.add(""); // 参数9: 空字符串
params.add("生产入库"); // 参数10: 生产入库
params.add(operationType); // 参数11: 操作类型 I或D
params.add(userName); // 参数12: 当前登陆人
List<Map<String, Object>> resultList = procedureMapper.getProcedureData("GetScanLabelVerification", params);
// 判断返回结果
if (resultList == null || resultList.isEmpty()) {
throw new RuntimeException("存储过程调用失败");
}
if (resultList == null || resultList.isEmpty()) {
logger.warn("该标签与入库单不符,标签: {}, 入库单: {}", labelCode, orderNo);
throw new RuntimeException("该标签与入库单不符,请检查");
}
Map<String, Object> result = resultList.get(0);
String code = String.valueOf(result.get("code"));
// 验证所有标签的状态
for (Map<String, Object> result : resultList) {
String status = (String) result.get("status");
if (!"待入库".equals(status)) {
String subLabelCode = (String) result.get("labelCode");
logger.warn("子标签状态不允许入库,子标签: {}, 状态: {}", subLabelCode, status);
throw new RuntimeException("标签 " + subLabelCode + " 的状态不允许入库");
if (!"200".equals(code)) {
String msg = String.valueOf(result.get("message"));
throw new RuntimeException(msg);
}
}
logger.info("标签验证成功,父标签: {}, 共找到 {} 条子标签记录", labelCode, resultList.size());
return resultList;
logger.info("标签验证成功,标签: {}, 操作类型: {}", labelCode, operationType);
return result;
} catch (Exception e) {
logger.error("标签验证失败,标签: {}, 错误: {}", labelCode, e.getMessage(), e);
throw new RuntimeException(e.getMessage(), e);
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean confirmInboundStorage(String orderNo, String locationCode, List<Map<String, Object>> labels, String site, String buNo, String relatedOrderNo) {
SysUserEntity sysUserEntity = (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
String userName = sysUserEntity.getUsername();
public boolean confirmInboundStorage(String site, String buNo, String relatedOrderNo, String inboundNo, String locationCode, String userName) {
logger.info("开始确认生产入库上架,site: {}, buNo: {}, 关联单号: {}, 入库单号: {}, 库位号: {}",
site, buNo, relatedOrderNo, inboundNo, locationCode);
logger.info("开始确认生产入库上架,入库单号: {}, 库位号: {}, 标签数量: {}", orderNo, locationCode, labels.size());
try {
// 1. 验证库位是否存在且可用
Map<String, Object> locationInfo = productionInboundMapper.validateLocation(locationCode, site);
if (locationInfo == null || locationInfo.isEmpty()) {
throw new RuntimeException("该库位不存在,请检查");
// 调用存储过程 GetSaveLabelVerification
List<Object> params = new ArrayList<>();
params.add(site); // 参数1: site
params.add(buNo); // 参数2: buNo
params.add(relatedOrderNo); // 参数3: 关联单号
params.add(inboundNo); // 参数4: 入库单号
params.add(""); // 参数5: 空字符串
params.add(""); // 参数6: 空字符串
params.add(""); // 参数7: 空字符串
params.add(locationCode); // 参数8: 库位
params.add("生产入库"); // 参数9: 生产入库
params.add(userName); // 参数10: 当前登陆人
List<Map<String, Object>> resultList = procedureMapper.getProcedureData("GetSaveLabelVerification", params);
// 判断返回结果
if (resultList == null || resultList.isEmpty()) {
throw new RuntimeException("存储过程调用失败");
}
String locationStatus = (String) locationInfo.get("status");
if (!"Y".equals(locationStatus)) {
throw new RuntimeException("该库位已停用,请检查");
}
// 根据库位获取实际的仓库ID
String warehouseId = (String) locationInfo.get("warehouseId");
if (warehouseId == null && warehouseId.trim().isEmpty()) {
throw new RuntimeException("该库位未绑定仓库,请检查");
}
// 2. 提取标签条码列表
List<String> labelCodes = labels.stream()
.map(label -> (String) label.get("labelCode"))
.collect(Collectors.toList());
Map<String, Object> result = resultList.get(0);
String code = String.valueOf(result.get("code"));
// 3. 更新SFDC_ROLLS表中标签状态为"已入库"
int updatedLabels = productionInboundMapper.updateSfdcRollsStatus(labelCodes, "已入库", site, buNo);
if (updatedLabels != labelCodes.size()) {
throw new RuntimeException("部分标签状态更新失败");
if (!"200".equals(code)) {
String msg = String.valueOf(result.get("message"));
throw new RuntimeException(msg);
}
// 5. 插入库存数据
insertInventoryStock(orderNo, warehouseId, locationCode, labels, site, buNo, relatedOrderNo);
// 6. 生成入库事务记录
String transNo = generateInboundTransaction(orderNo, warehouseId, locationCode, labels, site, buNo);
// 7. 计算所有标签的数量总和
BigDecimal inQty = BigDecimal.ZERO;
for (Map<String, Object> label : labels) {
Object quantityObj = label.get("quantity");
BigDecimal quantity = convertToDecimal(quantityObj);
inQty = inQty.add(quantity);
}
logger.info("标签总数量: {}, 用于倒冲的数量: {}", inQty, inQty);
// 8. 基于工单BOM生成入库倒冲数据
// 调用存储过程使用计算出的总数量
Map<String, Object> resultMap = this.UspBackflushMaterialByOrder(site, buNo, transNo, orderNo, inQty, userName);
//判断是否检验成功
String resultCode = String.valueOf(resultMap.get("resultCode"));
if ("400".equalsIgnoreCase(resultCode)) {
String msg = String.valueOf(resultMap.get("resultMsg"));
String objectId = String.valueOf(resultMap.get("objectId"));
throw new XJException(msg,objectId);
}
// 7. 异步调用ERP接口这里可以发送消息到队列
//asyncCallErpInterface(orderNo, partNo, labels);
logger.info("生产入库上架确认完成,入库单号: {}", orderNo);
logger.info("生产入库上架成功,入库单号: {}", inboundNo);
return true;
} catch (Exception e) {
logger.error("生产入库确认失败,入库单号: {}, 错误信息: {}", orderNo, e.getMessage(), e);
throw new RuntimeException("入库确认失败: " + e.getMessage(), e);
logger.error("生产入库确认失败,入库单号: {}, 错误: {}", inboundNo, e.getMessage(), e);
throw new RuntimeException(e.getMessage(), e);
}
}
@ -391,6 +377,25 @@ public class ProductionInboundServiceImpl implements ProductionInboundService {
}
}
@Override
public List<Map<String, Object>> getScannedLabelList(String site, String buNo, String relatedOrderNo, String inboundNo) {
logger.info("获取已扫描标签列表,site: {}, buNo: {}, 关联单号: {}, 入库单号: {}", site, buNo, relatedOrderNo, inboundNo);
try {
List<Map<String, Object>> labelList = productionInboundMapper.getScannedLabelList(site, buNo, relatedOrderNo, inboundNo);
if (labelList == null) {
labelList = new ArrayList<>();
}
logger.info("获取已扫描标签列表成功,共 {} 条记录", labelList.size());
return labelList;
} catch (Exception e) {
logger.error("获取已扫描标签列表失败,错误: {}", e.getMessage(), e);
throw new RuntimeException("获取已扫描标签列表失败: " + e.getMessage(), e);
}
}
/**
* 生成事务明细记录
*/

16
src/main/resources/mapper/productionInbound/ProductionInboundMapper.xml

@ -161,4 +161,20 @@
AND a.order_status = '待入库'
</select>
<!-- 获取已扫描标签列表(从缓存表) -->
<select id="getScannedLabelList" resultType="java.util.Map">
SELECT
site,
bu_no as buNo,
part_no as partNo,
RollNo as labelCode,
RollQty as quantity
FROM ScannedRollTempTable
WHERE site = #{site}
AND bu_no = #{buNo}
AND NotifyNo = #{relatedOrderNo}
AND OrderNo = #{inboundNo}
ORDER BY RollNo DESC
</select>
</mapper>
Loading…
Cancel
Save