feat(controller): 优化物料扫码出库逻辑并增加批次号序列号处理

- 修改ComponentOutboundController处理无扫码记录的情况
- 移除各控制器中的扫码检查条件并在VO中新增mustScan字段
- 在NoScanItemVO中添加batchNo和mustScan属性
- 修复NoScanningBaseControllerService中cannotOutNoScanning方法逻辑
- 为NoScanningItemDataRequest添加batchNo、serialNo和binNo的空值处理
- 重构OutAssistanceController和OutCostCenterController中的库存出库逻辑
- 优化OutProduceController中的PDI检测任务和库存处理逻辑
- 更新OutPurchaseController中的退货请求处理
- 新增QrCodeMasterController的getInfo接口获取二维码信息
- 扩展StrappingVO数据传输对象添加条码相关属性
This commit is contained in:
曹鹏飞 2026-06-12 08:54:52 +08:00
parent 759b1172ec
commit c9899887a6
15 changed files with 152 additions and 44 deletions

View File

@ -15,6 +15,7 @@ import com.nflg.wms.admin.repository.OutMaterialScanRecordRespository;
import com.nflg.wms.admin.service.ComponentOutboundControllerService;
import com.nflg.wms.admin.service.NoScanningBaseControllerService;
import com.nflg.wms.admin.service.SapService;
import com.nflg.wms.admin.util.NoUtil;
import com.nflg.wms.common.constant.BarCodeProcessStage;
import com.nflg.wms.common.pojo.ApiResult;
import com.nflg.wms.common.pojo.PageData;
@ -160,9 +161,13 @@ public class ComponentOutboundController extends BaseController {
List<InventoryInDTO> inventoryDTOS = new ArrayList<>();
for (WmsComponentOutboundItem item : outboundItems) {
List<OutMaterialScanRecord> records = outMaterialScanRecordRespository.findByTicketItemId(item.getId());
VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(records)).throwMessage("无有效的扫码记录");
for (OutMaterialScanRecord code : records) {
setInventoryInDTO(inventoryDTOS, item.getIdnrk(), outbound.getFactoryNo(), item.getLgort(), code.getBatchNo(), code.getSerialNo(), code.getNum());
if(CollectionUtil.isEmpty(records)) {
setInventoryInDTO(inventoryDTOS, item.getIdnrk(), outbound.getFactoryNo(), item.getLgort(), "", "", item.getOutQty());
}
else {
for (OutMaterialScanRecord code : records) {
setInventoryInDTO(inventoryDTOS, item.getIdnrk(), outbound.getFactoryNo(), item.getLgort(), code.getBatchNo(), code.getSerialNo(), code.getNum());
}
}
}
OptRecordDTO optRecordDTO = new OptRecordDTO();
@ -420,8 +425,7 @@ public class ComponentOutboundController extends BaseController {
List<WmsComponentPackingItem> items = wmsComponentPackingItemService.lambdaQuery()
.eq(WmsComponentPackingItem::getPackingId, order.getId())
.list();
items.removeIf(item -> getNoScanOutQty(item).compareTo(BigDecimal.ZERO) <= 0
|| noScanningBaseControllerService.cannotOutNoScanning(item.getIdnrk(),order.getFactoryNo(),item.getLgort()));
items.removeIf(item -> getNoScanOutQty(item).compareTo(BigDecimal.ZERO) <= 0);
return ApiResult.success(
items.stream()
.map(item -> new NoScanItemVO()
@ -432,6 +436,8 @@ public class ComponentOutboundController extends BaseController {
.setFactoryNo(order.getFactoryNo())
.setWarehouseNo(item.getLgort())
.setNum(getNoScanOutQty(item))
.setBatchNo("")
.setMustScan(noScanningBaseControllerService.cannotOutNoScanning(item.getIdnrk(),order.getFactoryNo(),item.getLgort()))
)
.toList()
);

View File

@ -13,6 +13,7 @@ import com.nflg.wms.admin.repository.InMaterialScanRecordRespository;
import com.nflg.wms.admin.service.BasdeSerialNumberControllerService;
import com.nflg.wms.admin.service.NoScanningBaseControllerService;
import com.nflg.wms.admin.service.SapService;
import com.nflg.wms.admin.util.NoUtil;
import com.nflg.wms.admin.util.PdfGeneratorUtil;
import com.nflg.wms.admin.util.QRCodeUtil;
import com.nflg.wms.admin.util.ThymeleafUtil;
@ -219,8 +220,7 @@ public class InCostCenterBackController extends BaseController {
List<WmsInCostcenterBackItem> items = inCostcenterBackItemService.lambdaQuery()
.eq(WmsInCostcenterBackItem::getOrderId, order.getId())
.list();
items.removeIf(item -> item.getLeft().compareTo(BigDecimal.ZERO) <= 0
|| noScanningBaseControllerService.existsQrCode(item.getMatnr()));
items.removeIf(item -> item.getLeft().compareTo(BigDecimal.ZERO) <= 0);
return ApiResult.success(
items.stream()
.map(item -> new NoScanItemVO()
@ -230,7 +230,10 @@ public class InCostCenterBackController extends BaseController {
.setMaterialDesc(item.getMaktx())
.setFactoryNo(order.getWerks())
.setWarehouseNo(order.getLgort())
.setNum(item.getLeft()))
.setNum(item.getLeft())
.setBatchNo("")
.setMustScan(noScanningBaseControllerService.existsQrCode(item.getMatnr()))
)
.toList()
);
}

View File

@ -228,8 +228,7 @@ public class InProduceBackController extends BaseController {
List<WmsInProduceBackItem> items = inProduceBackItemService.lambdaQuery()
.eq(WmsInProduceBackItem::getOrderId, order.getId())
.list();
items.removeIf(item -> item.getSqsl().subtract(item.getNum()).compareTo(BigDecimal.ZERO) <= 0
|| noScanningBaseControllerService.existsQrCode(item.getMatnr()));
items.removeIf(item -> item.getSqsl().subtract(item.getNum()).compareTo(BigDecimal.ZERO) <= 0);
return ApiResult.success(
items.stream()
.map(item -> new NoScanItemVO()
@ -239,7 +238,10 @@ public class InProduceBackController extends BaseController {
.setMaterialDesc(item.getMaktx2())
.setFactoryNo(order.getDwerk())
.setWarehouseNo(order.getLgort2())
.setNum(item.getSqsl().subtract(item.getNum())))
.setNum(item.getSqsl().subtract(item.getNum()))
.setBatchNo("")
.setMustScan(noScanningBaseControllerService.existsQrCode(item.getMatnr()))
)
.toList()
);
}

View File

@ -430,10 +430,7 @@ public class InProduceOrderController extends BaseController {
List<WmsInProduceOrderItem> items = produceOrderItemService.lambdaQuery()
.eq(WmsInProduceOrderItem::getOrderId, order.getId())
.list();
items.removeIf(item -> item.getInspectionStatus() == 0
|| item.getInspectionStatus() == 2
|| noScanningBaseControllerService.existsQrCode(item.getMaterialNo())
);
items.removeIf(item -> Objects.equals(0, item.getInspectionStatus()) || Objects.equals(item.getInspectionStatus(), 2));
return ApiResult.success(
items.stream()
.map(item -> new NoScanItemVO()
@ -444,6 +441,8 @@ public class InProduceOrderController extends BaseController {
.setFactoryNo(item.getFactoryNo())
.setWarehouseNo(item.getWarehouseNo())
.setNum(item.getNum())
.setBatchNo(NoUtil.getBatchNo(item.getBatchNo()))
.setMustScan(noScanningBaseControllerService.existsQrCode(item.getMaterialNo()))
)
.toList()
);

View File

@ -414,8 +414,7 @@ public class InProduceOrderSurplusController extends BaseController {
List<WmsInProduceOrderSurplusItem> items = inProduceOrderSurplusItemService.lambdaQuery()
.eq(WmsInProduceOrderSurplusItem::getOrderId, order.getId())
.list();
items.removeIf(item -> item.getLeftNum().compareTo(BigDecimal.ZERO) <= 0
|| noScanningBaseControllerService.existsQrCode(item.getMatnr()));
items.removeIf(item -> item.getLeftNum().compareTo(BigDecimal.ZERO) <= 0);
return ApiResult.success(
items.stream()
.map(item -> new NoScanItemVO()
@ -426,6 +425,8 @@ public class InProduceOrderSurplusController extends BaseController {
.setFactoryNo(order.getDwerk())
.setWarehouseNo(order.getLgort2())
.setNum(item.getLeftNum())
.setBatchNo("")
.setMustScan(noScanningBaseControllerService.existsQrCode(item.getMatnr()))
)
.toList()
);

View File

@ -202,8 +202,7 @@ public class NormalPGIController extends BaseController {
List<WmsSrmOrderItem> items = wmsSrmOrderItemService.lambdaQuery()
.eq(WmsSrmOrderItem::getOrderId, order.getId())
.list();
items.removeIf(item -> item.getDeliveryQty().compareTo(item.getReceiptQty()) <= 0
|| noScanningBaseControllerService.existsQrCode(item.getItemCode()));
items.removeIf(item -> item.getDeliveryQty().compareTo(item.getReceiptQty()) <= 0);
return ApiResult.success(
items.stream()
.map(item -> {
@ -216,7 +215,9 @@ public class NormalPGIController extends BaseController {
.setMaterialDesc(item.getItemName())
.setFactoryNo(order.getIuCode())
.setWarehouseNo(syncParamsDTO.getWarehouseNo())
.setNum(item.getDeliveryQty().subtract(item.getReceiptQty()));
.setNum(item.getDeliveryQty().subtract(item.getReceiptQty()))
.setBatchNo(order.getSupplierNum())
.setMustScan(noScanningBaseControllerService.existsQrCode(item.getItemCode()));
})
.toList()
);

View File

@ -297,8 +297,7 @@ public class OutAssistanceController extends BaseController {
List<WmsOutAssistanceItem> items = outAssistanceItemService.lambdaQuery()
.eq(WmsOutAssistanceItem::getOrderId, order.getId())
.list();
items.removeIf(item -> item.getLeft().compareTo(BigDecimal.ZERO) <= 0
|| noScanningBaseControllerService.cannotOutNoScanning(item.getMatnr1(),order.getWerks(),order.getLgort1()));
items.removeIf(item -> item.getLeft().compareTo(BigDecimal.ZERO) <= 0);
return ApiResult.success(
items.stream()
.map(item -> new NoScanItemVO()
@ -309,6 +308,7 @@ public class OutAssistanceController extends BaseController {
.setFactoryNo(order.getWerks())
.setWarehouseNo(order.getLgort1())
.setNum(item.getLeft())
.setMustScan(noScanningBaseControllerService.cannotOutNoScanning(item.getMatnr1(), order.getWerks(), order.getLgort1()))
)
.toList()
);
@ -327,7 +327,7 @@ public class OutAssistanceController extends BaseController {
VUtil.trueThrowBusinessError(Objects.isNull(order)).throwMessage("订单不存在");
request.getItems()
.forEach(data ->
VUtil.trueThrowBusinessError(noScanningBaseControllerService.cannotOutNoScanning(data.getMaterialNo(),order.getWerks(),data.getWarehouseNo()))
VUtil.trueThrowBusinessError(noScanningBaseControllerService.cannotOutNoScanning(data.getMaterialNo(), order.getWerks(), data.getWarehouseNo()))
.throwMessage("物料" + data.getMaterialNo() + "不支持无码出库")
);
WmsOutAssistanceTicket ticket = new WmsOutAssistanceTicket()
@ -364,7 +364,8 @@ public class OutAssistanceController extends BaseController {
.setNum(num);
ticketItems.add(ti);
ri.getDatas().forEach(data -> {
String key = item.getMatnr1() + "|" + data.getBatchNo() + "|" + data.getSerialNo() + "|" + order.getWerks() + "|" + ri.getWarehouseNo();
String key = item.getMatnr1() + "|" + data.getBatchNo() + "|" + data.getSerialNo() + "|"
+ order.getWerks() + "|" + ri.getWarehouseNo() + "|" + data.getBinNo();
inventoryOutMap.merge(key, new InventoryOutDTO()
.setMaterialNo(item.getMatnr1())
.setBatchNo(data.getBatchNo())
@ -388,7 +389,10 @@ public class OutAssistanceController extends BaseController {
.setMeins(item.getMeins())
.setMenge(data.getNum())
.setName1(order.getName1())
.setEnmng(item.getEnmng()), (e, i) -> { e.setMenge(e.getMenge().add(i.getMenge())); return e; });
.setEnmng(item.getEnmng()), (e, i) -> {
e.setMenge(e.getMenge().add(i.getMenge()));
return e;
});
});
});
outAssistanceItemService.updateBatchById(datas);

View File

@ -298,8 +298,7 @@ public class OutCostCenterController extends BaseController {
List<WmsOutCostcenterItem> items = outCostcenterItemService.lambdaQuery()
.eq(WmsOutCostcenterItem::getOrderId, order.getId())
.list();
items.removeIf(item -> item.getLeft().compareTo(BigDecimal.ZERO) <= 0
|| noScanningBaseControllerService.cannotOutNoScanning(item.getMatnr(), order.getWerks(), item.getLgort()));
items.removeIf(item -> item.getLeft().compareTo(BigDecimal.ZERO) <= 0);
return ApiResult.success(
items.stream()
.map(item -> new NoScanItemVO()
@ -310,6 +309,7 @@ public class OutCostCenterController extends BaseController {
.setFactoryNo(order.getWerks())
.setWarehouseNo(item.getLgort())
.setNum(item.getLeft())
.setMustScan(noScanningBaseControllerService.cannotOutNoScanning(item.getMatnr(), order.getWerks(), item.getLgort()))
)
.toList()
);
@ -365,7 +365,8 @@ public class OutCostCenterController extends BaseController {
.setNum(num);
ticketItems.add(ti);
ri.getDatas().forEach(data -> {
String key = item.getMatnr() + "|" + data.getBatchNo() + "|" + data.getSerialNo() + "|" + order.getWerks() + "|" + ri.getWarehouseNo();
String key = item.getMatnr() + "|" + data.getBatchNo() + "|" + data.getSerialNo() + "|"
+ order.getWerks() + "|" + ri.getWarehouseNo() + "|" + data.getBinNo();
inventoryOutMap.merge(key, new InventoryOutDTO()
.setMaterialNo(item.getMatnr())
.setBatchNo(data.getBatchNo())

View File

@ -284,7 +284,6 @@ public class OutProduceController extends BaseController {
/**
* 发起PDI检测任务
*
* @param id 成品发货单ID
*/
@PostMapping("pdi/apply")
@ -440,8 +439,7 @@ public class OutProduceController extends BaseController {
List<WmsOutProduceItem> items = outProduceItemService.lambdaQuery()
.eq(WmsOutProduceItem::getOrderId, order.getId())
.list();
items.removeIf(item -> item.getSqsl().subtract(item.getNum()).compareTo(BigDecimal.ZERO) <= 0
|| noScanningBaseControllerService.cannotOutNoScanning(item.getMatnr(),order.getDwerk(),order.getLgort2()));
items.removeIf(item -> item.getSqsl().subtract(item.getNum()).compareTo(BigDecimal.ZERO) <= 0);
return ApiResult.success(
items.stream()
.map(item -> new NoScanItemVO()
@ -452,6 +450,7 @@ public class OutProduceController extends BaseController {
.setFactoryNo(order.getDwerk())
.setWarehouseNo(order.getLgort2())
.setNum(item.getSqsl().subtract(item.getNum()))
.setMustScan(noScanningBaseControllerService.cannotOutNoScanning(item.getMatnr(), order.getDwerk(), order.getLgort2()))
)
.toList()
);
@ -470,7 +469,7 @@ public class OutProduceController extends BaseController {
VUtil.trueThrowBusinessError(Objects.isNull(order)).throwMessage("订单不存在");
request.getItems()
.forEach(data ->
VUtil.trueThrowBusinessError(noScanningBaseControllerService.cannotOutNoScanning(data.getMaterialNo(),order.getDwerk(),data.getWarehouseNo()))
VUtil.trueThrowBusinessError(noScanningBaseControllerService.cannotOutNoScanning(data.getMaterialNo(), order.getDwerk(), data.getWarehouseNo()))
.throwMessage("物料" + data.getMaterialNo() + "不支持无码出库")
);
WmsOutProduceTicket ticket = new WmsOutProduceTicket()
@ -511,7 +510,8 @@ public class OutProduceController extends BaseController {
.setNum(num);
ticketItems.add(ti);
ri.getDatas().forEach(data -> {
String key = item.getMatnr() + "|" + data.getBatchNo() + "|" + data.getSerialNo() + "|" + order.getDwerk() + "|" + ri.getWarehouseNo();
String key = item.getMatnr() + "|" + data.getBatchNo() + "|" + data.getSerialNo() + "|"
+ order.getDwerk() + "|" + ri.getWarehouseNo() + "|" + data.getBinNo();
inventoryOutMap.merge(key, new InventoryOutDTO()
.setMaterialNo(item.getMatnr())
.setBatchNo(data.getBatchNo())
@ -530,7 +530,10 @@ public class OutProduceController extends BaseController {
.setLgort(ri.getWarehouseNo())
.setMenge(data.getNum())
.setMenge_t(BigDecimal.ZERO)
.setMeins(item.getMeins()), (e, i) -> { e.setMenge(e.getMenge().add(i.getMenge())); return e; });
.setMeins(item.getMeins()), (e, i) -> {
e.setMenge(e.getMenge().add(i.getMenge()));
return e;
});
});
});
outProduceItemService.updateBatchById(datas);
@ -769,7 +772,7 @@ public class OutProduceController extends BaseController {
);
Map<String, List<OutMaterialScanRecord>> dmaps = records.stream().collect(Collectors.groupingBy(OutMaterialScanRecord::getKey7));
OptRecordDTO optRecordDTO = new OptRecordDTO();
optRecordDTO.setOperationType((short)1)
optRecordDTO.setOperationType((short) 1)
.setOrderId(order.getNo());
optRecordService.add(optRecordDTO);
Zwm3a10VO vo = sapService.zwm3A10(new Zwm3a10QO()

View File

@ -156,8 +156,7 @@ public class OutPurchaseController extends BaseController {
List<WmsReturnRequestItem> items = returnRequestItemService.lambdaQuery()
.eq(WmsReturnRequestItem::getApplicationId, order.getId())
.list();
items.removeIf(item -> item.getLeft().compareTo(BigDecimal.ZERO) <= 0
|| noScanningBaseControllerService.cannotOutNoScanning(item.getMaterialCode(),item.getFactoryCode(),item.getStorageLocation()));
items.removeIf(item -> item.getLeft().compareTo(BigDecimal.ZERO) <= 0);
return ApiResult.success(
items.stream()
.map(item -> new NoScanItemVO()
@ -168,6 +167,7 @@ public class OutPurchaseController extends BaseController {
.setFactoryNo(item.getFactoryCode())
.setWarehouseNo(item.getStorageLocation())
.setNum(item.getLeft())
.setMustScan(noScanningBaseControllerService.cannotOutNoScanning(item.getMaterialCode(),item.getFactoryCode(),item.getStorageLocation()))
)
.toList()
);
@ -227,7 +227,8 @@ public class OutPurchaseController extends BaseController {
.setLgort(rrItem.getStorageLocation())
);
ri.getDatas().forEach(data -> {
String key = rrItem.getMaterialCode() + "|" + data.getBatchNo() + "|" + data.getSerialNo() + "|" + rrItem.getFactoryCode() + "|" + rrItem.getStorageLocation();
String key = rrItem.getMaterialCode() + "|" + data.getBatchNo() + "|" + data.getSerialNo() + "|"
+ rrItem.getFactoryCode() + "|" + rrItem.getStorageLocation()+ "|" + data.getBinNo();
inventoryOutMap.merge(key, new InventoryOutDTO()
.setMaterialNo(rrItem.getMaterialCode())
.setBatchNo(data.getBatchNo())

View File

@ -38,10 +38,7 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
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 org.springframework.web.bind.annotation.*;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
@ -518,4 +515,26 @@ public class QrCodeMasterController extends BaseController {
URL baseUrl = new ClassPathResource("template/qrcode/").getURL();
PdfGeneratorUtil.generatePdf("箱码标签图片", html, baseUrl.toString(), response);
}
/**
* 获取二维码信息
* @param barcodeCode 二维码编号
*/
@PostMapping("getInfo")
public ApiResult<StrappingVO> getInfo(@RequestParam String barcodeCode) {
WmsQrCodeMaster qrCodeMaster = qrCodeMasterService.lambdaQuery()
.eq(WmsQrCodeMaster::getBarcodeCode, barcodeCode)
.one();
VUtil.trueThrowBusinessError(ObjectUtil.isNull(qrCodeMaster)).throwMessage("无效码");
StrappingVO vo = Convert.convert(StrappingVO.class, qrCodeMaster);
vo.setItems(
qrCodeMasterService.lambdaQuery()
.eq(WmsQrCodeMaster::getParentBarcodeId, qrCodeMaster.getId())
.list()
.stream()
.map(it -> Convert.convert(StrappingVO.class, it))
.toList()
);
return ApiResult.success(vo);
}
}

View File

@ -1,5 +1,6 @@
package com.nflg.wms.admin.pojo.request;
import cn.hutool.core.util.StrUtil;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.experimental.Accessors;
@ -21,13 +22,34 @@ public class NoScanningItemDataRequest {
*/
private String batchNo;
public String getBatchNo(){
if (StrUtil.isBlank(batchNo)){
return "";
}
return batchNo;
}
/**
* 序列号
*/
private String serialNo;
public String getSerialNo(){
if (StrUtil.isBlank(serialNo)){
return "";
}
return serialNo;
}
/**
* 库位
*/
private String binNo;
public String getBinNo(){
if (StrUtil.isBlank(binNo)){
return "";
}
return binNo;
}
}

View File

@ -52,8 +52,8 @@ public class NoScanningBaseControllerService {
}
public boolean cannotOutNoScanning(String materialNo, String factoryNo, String warehouseNo) {
if (existsQrCode(materialNo)) {
return true;
if (!existsQrCode(materialNo)) {
return false;
}
return !quantityConsistencyCheck(materialNo, factoryNo, warehouseNo);
}

View File

@ -43,4 +43,14 @@ public class NoScanItemVO {
* 数量
*/
private BigDecimal num;
/**
* 批次号
*/
private String batchNo;
/**
* 是否需要扫码
*/
private boolean mustScan;
}

View File

@ -14,6 +14,7 @@ public class StrappingVO {
* 物料二维码Id
*/
private Long id;
/**
* 二维码编号
*/
@ -29,6 +30,41 @@ public class StrappingVO {
*/
private BigDecimal quantity;
/**
* 条码类型(物料码箱码) 0 物料码1 箱码
*/
private Short packagingType;
/**
* 条码流程位置
*/
private Short processStage;
/**
* 批次号
*/
private String batchNo;
/**
* 序列号
*/
private String serialNo;
/**
* 所属工厂
*/
private String factoryCode;
/**
* 库存地点
*/
private String storageLocation;
/**
* 储位
*/
private String binLocation;
/**
* 子物料信息
*/