feat(component): 新增零部件打包管理和外协领料功能

- 实现零部件打包管理控制器,支持打包单的增删改查
- 添加零部件订单信息查询和装箱单详情查看功能
- 实现零部件打包信息的保存、更新和删除操作
- 添加装箱单PDF导出功能
- 实现外协领料控制器,支持SAP领料订单数据查询
- 添加外协领料订单的保存、搜索和详情查看功能
- 实现PDA端外协领料功能和物料扫码提交功能
- 添加出库单审核和库存管理功能
- 实现二维码扫描和批次管理功能
This commit is contained in:
曹鹏飞 2026-04-02 18:33:35 +08:00
parent 2a8d96a14a
commit 461775b5db
8 changed files with 162 additions and 127 deletions

View File

@ -113,9 +113,7 @@ public class ComponentPackingController {
/**
* 添加零部件的打包信息
*
* @param request
* @return
* @return {@link InventoryLockVO}
*/
@PostMapping("add")
public ApiResult<Void> savePacking(@Valid @RequestBody ComponentPackingInputQO request) {

View File

@ -11,7 +11,6 @@ import com.nflg.wms.admin.repository.InventoryForOutRepository;
import com.nflg.wms.admin.repository.OutMaterialScanRecordRespository;
import com.nflg.wms.admin.service.BasdeSerialNumberControllerService;
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;
@ -105,6 +104,7 @@ public class OutAssistanceController extends BaseController {
/**
* 保存
* @return {@link InventoryLockVO}
*/
@Transactional
@PostMapping("save")
@ -119,6 +119,7 @@ public class OutAssistanceController extends BaseController {
VUtil.trueThrowBusinessError(CollectionUtil.isNotEmpty(materialNos))
.throwMessage("以下物料的申请数量超出限制:" + StrUtil.join(",", materialNos));
Map<String, List<SubcontractedOrderDTO>> maps = datas.stream().collect(Collectors.groupingBy(SubcontractedOrderDTO::getKey));
List<InventoryLockVO> lockVOS = new ArrayList<>();
maps.forEach((key, items) -> {
WmsOutAssistance order = Convert.convert(WmsOutAssistance.class, items.get(0));
order.setNo(serialNumberControllerService.generateSerialNumber(16));
@ -127,11 +128,35 @@ public class OutAssistanceController extends BaseController {
outAssistanceService.save(order);
items.forEach(item -> {
WmsOutAssistanceItem data = Convert.convert(WmsOutAssistanceItem.class, item);
data.setLeft(data.getNum());
data.setOrderId(order.getId());
outAssistanceItemService.save(data);
RLock lock = redissonClient.getLock(StrUtil.format("lock:inventory:{}:{}:{}", order.getWerks(), order.getLgort1(), item.getMatnr1()));
try {
// 等待5秒获取锁10秒后自动释放
if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {
if (inventoryService.getNumOne(order.getWerks(), order.getLgort1(), item.getMatnr1()).compareTo(data.getNum()) < 0) {
List<InventoryLockVO> itemLocks = inventoryService.getLockList(order.getWerks(), order.getLgort1(), item.getMatnr1());
VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(itemLocks)).throwMessage("库存不足:" + item.getMatnr1());
lockVOS.addAll(itemLocks);
}else {
data.setLeft(data.getNum());
data.setOrderId(order.getId());
outAssistanceItemService.save(data);
}
} else {
throw new NflgException(STATE.BusinessError, "获取锁失败");
}
} catch (Exception e) {
log.error("保存单据出错", e);
throw new NflgException(STATE.BusinessError, e.getMessage());
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
});
});
if (CollectionUtil.isNotEmpty(lockVOS)) {
throw new DataAlertException(STATE.OutOfStock, lockVOS);
}
return ApiResult.success();
}
@ -230,10 +255,10 @@ public class OutAssistanceController extends BaseController {
public ApiResult<Void> submit(@Valid @RequestBody OutProduceSubmitQO request) {
WmsOutAssistance order = outAssistanceService.lambdaQuery().eq(WmsOutAssistance::getNo, request.getNo()).one();
VUtil.trueThrowBusinessError(Objects.isNull(order)).throwMessage("订单不存在");
Set<String> matnrs = request.getItems().stream().map(OutProduceSubmitItemQO::getMaterialNo).collect(Collectors.toSet());
matnrs.removeAll(request.getRecommendBatch().stream().map(InventoryForOutVO::getMaterialNo).collect(Collectors.toSet()));
VUtil.trueThrowBusinessError(CollectionUtil.isNotEmpty(matnrs))
.throwMessage("以下物料无库存,不能出库:" + StrUtil.join(",", matnrs));
// Set<String> matnrs = request.getItems().stream().map(OutProduceSubmitItemQO::getMaterialNo).collect(Collectors.toSet());
// matnrs.removeAll(request.getRecommendBatch().stream().map(InventoryForOutVO::getMaterialNo).collect(Collectors.toSet()));
// VUtil.trueThrowBusinessError(CollectionUtil.isNotEmpty(matnrs))
// .throwMessage("以下物料无库存,不能出库:" + StrUtil.join(",", matnrs));
WmsOutAssistanceTicket ticket = new WmsOutAssistanceTicket()
.setId(IdUtil.getSnowflakeNextId())
.setNo(serialNumberControllerService.generateSerialNumber(17))
@ -354,36 +379,6 @@ public class OutAssistanceController extends BaseController {
});
}
});
List<InventoryLockVO> lockVOS = new ArrayList<>();
records.stream()
.collect(Collectors.groupingBy(OutMaterialScanRecord::getKey10))
.forEach((key, vs) -> {
OutMaterialScanRecord info = vs.get(0);
BigDecimal lockNum = vs.stream().map(OutMaterialScanRecord::getNum).reduce(BigDecimal.ZERO, BigDecimal::add);
RLock lock = redissonClient.getLock(StrUtil.format("lock:inventory:{}:{}:{}", info.getFactoryNo(), info.getWarehouseNo(), info.getMaterialNo()));
try {
// 等待5秒获取锁10秒后自动释放
if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {
if (inventoryService.getNumOne(info.getFactoryNo(), info.getWarehouseNo(), info.getMaterialNo()).compareTo(lockNum) < 0) {
List<InventoryLockVO> itemLocks = inventoryService.getLockList(info.getFactoryNo(), info.getWarehouseNo(), info.getMaterialNo());
VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(itemLocks)).throwMessage("库存不足:" + info.getMaterialNo());
lockVOS.addAll(itemLocks);
}
} else {
throw new NflgException(STATE.BusinessError, "获取锁失败");
}
} catch (Exception e) {
log.error("保存生产领料单出错", e);
throw new NflgException(STATE.BusinessError, e.getMessage());
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
});
if (CollectionUtil.isNotEmpty(lockVOS)) {
throw new DataAlertException(STATE.OutOfStock, lockVOS);
}
outAssistanceItemService.updateBatchById(datas);
outAssistanceTicketItemService.saveBatch(ticketItems);
outAssistanceTicketService.save(ticket);

View File

@ -11,7 +11,6 @@ import com.nflg.wms.admin.repository.InventoryForOutRepository;
import com.nflg.wms.admin.repository.OutMaterialScanRecordRespository;
import com.nflg.wms.admin.service.BasdeSerialNumberControllerService;
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;
@ -108,6 +107,7 @@ public class OutCostCenterController extends BaseController {
/**
* 保存
* @return {@link InventoryLockVO}
*/
@Transactional
@PostMapping("save")
@ -121,6 +121,7 @@ public class OutCostCenterController extends BaseController {
});
VUtil.trueThrowBusinessError(CollectionUtil.isNotEmpty(materialNos))
.throwMessage("以下物料的申请数量超出限制:" + StrUtil.join(",", materialNos));
List<InventoryLockVO> lockVOS = new ArrayList<>();
Map<String, List<DepartmentMaterialRequisitionDTO>> maps = datas.stream().collect(Collectors.groupingBy(DepartmentMaterialRequisitionDTO::getKey1));
maps.forEach((key, items) -> {
WmsOutCostcenter order = Convert.convert(WmsOutCostcenter.class, items.get(0));
@ -130,11 +131,35 @@ public class OutCostCenterController extends BaseController {
outCostcenterService.save(order);
items.forEach(item -> {
WmsOutCostcenterItem data = Convert.convert(WmsOutCostcenterItem.class, item);
data.setLeft(data.getNum());
data.setOrderId(order.getId());
outCostcenterItemService.save(data);
RLock lock = redissonClient.getLock(StrUtil.format("lock:inventory:{}:{}:{}", order.getWerks(), data.getLgort(), data.getMatnr()));
try {
// 等待5秒获取锁10秒后自动释放
if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {
if (inventoryService.getNumOne(order.getWerks(), data.getLgort(), data.getMatnr()).compareTo(data.getNum()) < 0) {
List<InventoryLockVO> itemLocks = inventoryService.getLockList(order.getWerks(), data.getLgort(), data.getMatnr());
VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(itemLocks)).throwMessage("库存不足:" + data.getMatnr());
lockVOS.addAll(itemLocks);
} else {
data.setLeft(data.getNum());
data.setOrderId(order.getId());
outCostcenterItemService.save(data);
}
} else {
throw new NflgException(STATE.BusinessError, "获取锁失败");
}
} catch (Exception e) {
log.error("保存单据出错", e);
throw new NflgException(STATE.BusinessError, e.getMessage());
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
});
});
if (CollectionUtil.isNotEmpty(lockVOS)) {
throw new DataAlertException(STATE.OutOfStock, lockVOS);
}
return ApiResult.success();
}
@ -232,10 +257,10 @@ public class OutCostCenterController extends BaseController {
public ApiResult<Void> submit(@Valid @RequestBody OutProduceSubmitQO request) {
WmsOutCostcenter order = outCostcenterService.lambdaQuery().eq(WmsOutCostcenter::getNo, request.getNo()).one();
VUtil.trueThrowBusinessError(Objects.isNull(order)).throwMessage("订单不存在");
Set<String> matnrs = request.getItems().stream().map(OutProduceSubmitItemQO::getMaterialNo).collect(Collectors.toSet());
matnrs.removeAll(request.getRecommendBatch().stream().map(InventoryForOutVO::getMaterialNo).collect(Collectors.toSet()));
VUtil.trueThrowBusinessError(CollectionUtil.isNotEmpty(matnrs))
.throwMessage("以下物料无库存,不能出库:" + StrUtil.join(",", matnrs));
// Set<String> matnrs = request.getItems().stream().map(OutProduceSubmitItemQO::getMaterialNo).collect(Collectors.toSet());
// matnrs.removeAll(request.getRecommendBatch().stream().map(InventoryForOutVO::getMaterialNo).collect(Collectors.toSet()));
// VUtil.trueThrowBusinessError(CollectionUtil.isNotEmpty(matnrs))
// .throwMessage("以下物料无库存,不能出库:" + StrUtil.join(",", matnrs));
WmsOutCostcenterTicket ticket = new WmsOutCostcenterTicket()
.setId(IdUtil.getSnowflakeNextId())
.setNo(serialNumberControllerService.generateSerialNumber(15))
@ -253,7 +278,9 @@ public class OutCostCenterController extends BaseController {
.flatMap(Collection::stream)
.map(QRCodeQO::getContent)
.collect(Collectors.toSet());
List<WmsQrCodeMaster> qrCodeMasters = CollectionUtil.isEmpty(allQrCodes) ? Collections.emptyList() : qrCodeMasterService.lambdaQuery()
List<WmsQrCodeMaster> qrCodeMasters = CollectionUtil.isEmpty(allQrCodes)
? Collections.emptyList() :
qrCodeMasterService.lambdaQuery()
.eq(WmsQrCodeMaster::getProcessStage, BarCodeProcessStage.InBound.getState())
.in(WmsQrCodeMaster::getBarcodeCode, allQrCodes)
.list();
@ -348,36 +375,6 @@ public class OutCostCenterController extends BaseController {
});
}
});
List<InventoryLockVO> lockVOS = new ArrayList<>();
records.stream()
.collect(Collectors.groupingBy(OutMaterialScanRecord::getKey10))
.forEach((key, vs) -> {
OutMaterialScanRecord info = vs.get(0);
BigDecimal lockNum = vs.stream().map(OutMaterialScanRecord::getNum).reduce(BigDecimal.ZERO, BigDecimal::add);
RLock lock = redissonClient.getLock(StrUtil.format("lock:inventory:{}:{}:{}", info.getFactoryNo(), info.getWarehouseNo(), info.getMaterialNo()));
try {
// 等待5秒获取锁10秒后自动释放
if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {
if (inventoryService.getNumOne(info.getFactoryNo(), info.getWarehouseNo(), info.getMaterialNo()).compareTo(lockNum) < 0) {
List<InventoryLockVO> itemLocks = inventoryService.getLockList(info.getFactoryNo(), info.getWarehouseNo(), info.getMaterialNo());
VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(itemLocks)).throwMessage("库存不足:" + info.getMaterialNo());
lockVOS.addAll(itemLocks);
}
} else {
throw new NflgException(STATE.BusinessError, "获取锁失败");
}
} catch (Exception e) {
log.error("保存生产领料单出错", e);
throw new NflgException(STATE.BusinessError, e.getMessage());
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
});
if (CollectionUtil.isNotEmpty(lockVOS)) {
throw new DataAlertException(STATE.OutOfStock, lockVOS);
}
outCostcenterItemService.updateBatchById(datas);
outCostcenterTicketItemService.saveBatch(ticketItems);
outCostcenterTicketService.save(ticket);
@ -433,17 +430,17 @@ public class OutCostCenterController extends BaseController {
.setFactoryNo(list.get(0).getFactoryNo())
.setWarehouseNo(list.get(0).getWarehouseNo())
.setBinLocation(list.get(0).isQiTao() ? list.get(0).getBinNo() : qrCodeMasters.stream()
.filter(qr -> StrUtil.equals(qr.getBarcodeCode(), list.get(0).getUniqNo()))
.findFirst()
.map(WmsQrCodeMaster::getBinLocation)
.orElse("")
.filter(qr -> StrUtil.equals(qr.getBarcodeCode(), list.get(0).getUniqNo()))
.findFirst()
.map(WmsQrCodeMaster::getBinLocation)
.orElse("")
)
.setNum(list.stream().map(OutMaterialScanRecord::getNum).reduce(BigDecimal.ZERO, BigDecimal::add))
).toList()
);
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);
C_MaterialOutboundDTO vo = sapService.ZWM00_MB115(new C_MaterialOutboundQO()

View File

@ -21,7 +21,10 @@ import com.nflg.wms.common.exception.NflgException;
import com.nflg.wms.common.pojo.ApiResult;
import com.nflg.wms.common.pojo.PageData;
import com.nflg.wms.common.pojo.document.OutMaterialScanRecord;
import com.nflg.wms.common.pojo.dto.*;
import com.nflg.wms.common.pojo.dto.InventoryForOutDTO;
import com.nflg.wms.common.pojo.dto.InventoryInDTO;
import com.nflg.wms.common.pojo.dto.InventoryOutDTO;
import com.nflg.wms.common.pojo.dto.OptRecordDTO;
import com.nflg.wms.common.pojo.qo.*;
import com.nflg.wms.common.pojo.vo.*;
import com.nflg.wms.common.util.EecExcelUtil;
@ -46,7 +49,6 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@ -384,10 +386,10 @@ public class OutProduceController extends BaseController {
public ApiResult<Void> submit(@Valid @RequestBody OutProduceSubmitQO request) {
WmsOutProduce order = outProduceService.lambdaQuery().eq(WmsOutProduce::getNo, request.getNo()).one();
VUtil.trueThrowBusinessError(Objects.isNull(order)).throwMessage("订单不存在");
Set<String> matnrs = request.getItems().stream().map(OutProduceSubmitItemQO::getMaterialNo).collect(Collectors.toSet());
matnrs.removeAll(request.getRecommendBatch().stream().map(InventoryForOutVO::getMaterialNo).collect(Collectors.toSet()));
VUtil.trueThrowBusinessError(CollectionUtil.isNotEmpty(matnrs))
.throwMessage("以下物料无库存,不能出库:" + StrUtil.join(",", matnrs));
// Set<String> matnrs = request.getItems().stream().map(OutProduceSubmitItemQO::getMaterialNo).collect(Collectors.toSet());
// matnrs.removeAll(request.getRecommendBatch().stream().map(InventoryForOutVO::getMaterialNo).collect(Collectors.toSet()));
// VUtil.trueThrowBusinessError(CollectionUtil.isNotEmpty(matnrs))
// .throwMessage("以下物料无库存,不能出库:" + StrUtil.join(",", matnrs));
WmsOutProduceTicket ticket = new WmsOutProduceTicket()
.setId(IdUtil.getSnowflakeNextId())
.setNo(serialNumberControllerService.generateSerialNumber(21))

View File

@ -162,7 +162,7 @@ public class TransferCompanyController extends BaseController {
throw new NflgException(STATE.BusinessError, "获取锁失败");
}
} catch (Exception e) {
log.error("保存生产领料单出错", e);
log.error("保存出错", e);
throw new NflgException(STATE.BusinessError, e.getMessage());
} finally {
if (lock.isHeldByCurrentThread()) {
@ -288,10 +288,10 @@ public class TransferCompanyController extends BaseController {
public ApiResult<Void> submitForOut(@Valid @RequestBody OutProduceSubmitQO request) {
WmsTransferCompany order = transferCompanyService.lambdaQuery().eq(WmsTransferCompany::getNo, request.getNo()).one();
VUtil.trueThrowBusinessError(Objects.isNull(order)).throwMessage("转储单不存在");
Set<String> matnrs = request.getItems().stream().map(OutProduceSubmitItemQO::getMaterialNo).collect(Collectors.toSet());
matnrs.removeAll(request.getRecommendBatch().stream().map(InventoryForOutVO::getMaterialNo).collect(Collectors.toSet()));
VUtil.trueThrowBusinessError(CollectionUtil.isNotEmpty(matnrs))
.throwMessage("以下物料无库存,不能出库:" + StrUtil.join(",", matnrs));
// Set<String> matnrs = request.getItems().stream().map(OutProduceSubmitItemQO::getMaterialNo).collect(Collectors.toSet());
// matnrs.removeAll(request.getRecommendBatch().stream().map(InventoryForOutVO::getMaterialNo).collect(Collectors.toSet()));
// VUtil.trueThrowBusinessError(CollectionUtil.isNotEmpty(matnrs))
// .throwMessage("以下物料无库存,不能出库:" + StrUtil.join(",", matnrs));
List<WmsTransferCompanyItem> datas = transferCompanyItemService.getList(order.getId());
List<OutMaterialScanRecord> records = new ArrayList<>();
List<WmsTransferCompanyTicketItem> ticketItems = new ArrayList<>();

View File

@ -160,7 +160,7 @@ public class TransferFactoryController extends BaseController {
throw new NflgException(STATE.BusinessError, "获取锁失败");
}
} catch (Exception e) {
log.error("保存生产领料单出错", e);
log.error("保存出错", e);
throw new NflgException(STATE.BusinessError, e.getMessage());
} finally {
if (lock.isHeldByCurrentThread()) {
@ -287,10 +287,10 @@ public class TransferFactoryController extends BaseController {
public ApiResult<Void> submitForOut(@Valid @RequestBody OutProduceSubmitQO request) {
WmsTransferFactory order = transferFactoryService.lambdaQuery().eq(WmsTransferFactory::getNo, request.getNo()).one();
VUtil.trueThrowBusinessError(Objects.isNull(order)).throwMessage("调拨单不存在");
Set<String> matnrs = request.getItems().stream().map(OutProduceSubmitItemQO::getMaterialNo).collect(Collectors.toSet());
matnrs.removeAll(request.getRecommendBatch().stream().map(InventoryForOutVO::getMaterialNo).collect(Collectors.toSet()));
VUtil.trueThrowBusinessError(CollectionUtil.isNotEmpty(matnrs))
.throwMessage("以下物料无库存,不能出库:" + StrUtil.join(",", matnrs));
// Set<String> matnrs = request.getItems().stream().map(OutProduceSubmitItemQO::getMaterialNo).collect(Collectors.toSet());
// matnrs.removeAll(request.getRecommendBatch().stream().map(InventoryForOutVO::getMaterialNo).collect(Collectors.toSet()));
// VUtil.trueThrowBusinessError(CollectionUtil.isNotEmpty(matnrs))
// .throwMessage("以下物料无库存,不能出库:" + StrUtil.join(",", matnrs));
List<WmsTransferFactoryItem> datas = transferFactoryItemService.getList(order.getId());
List<OutMaterialScanRecord> records = new ArrayList<>();
WmsTransferFactoryTicket ticket = new WmsTransferFactoryTicket()

View File

@ -2,27 +2,38 @@ package com.nflg.wms.admin.service;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nflg.wms.common.constant.STATE;
import com.nflg.wms.common.exception.DataAlertException;
import com.nflg.wms.common.exception.NflgException;
import com.nflg.wms.common.pojo.qo.ComponentPackingEditInputQO;
import com.nflg.wms.common.pojo.qo.ComponentPackingInputQO;
import com.nflg.wms.common.pojo.qo.ComponentPackingItemEditInputQO;
import com.nflg.wms.common.pojo.vo.InventoryLockVO;
import com.nflg.wms.common.util.UserUtil;
import com.nflg.wms.common.util.VUtil;
import com.nflg.wms.repository.entity.WmsComponentPacking;
import com.nflg.wms.repository.entity.WmsComponentPackingItem;
import com.nflg.wms.repository.service.IWmsComponentPackingItemService;
import com.nflg.wms.repository.service.IWmsComponentPackingService;
import com.nflg.wms.repository.service.IWmsInventoryService;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.cloud.commons.util.IdUtils;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@Slf4j
@Component
public class ComponentPackingControllerService {
@Resource
@ -34,6 +45,12 @@ public class ComponentPackingControllerService {
@Resource
private BasdeSerialNumberControllerService basdeSerialNumberControllerService;
@Resource
private RedissonClient redissonClient;
@Resource
private IWmsInventoryService inventoryService;
@Transactional
public void savePacking(@Valid ComponentPackingInputQO request) {
WmsComponentPacking wmsComponentPacking = new WmsComponentPacking();
@ -65,32 +82,57 @@ public class ComponentPackingControllerService {
wmsComponentPacking.setCreateId(UserUtil.getUserId());
wmsComponentPacking.setCreateTime(LocalDateTime.now());
wmsComponentPacking.setFactoryNo(request.getFactoryNo());
List<WmsComponentPackingItem> wmsComponentPackingItems = request.getItems().stream()
.map(item -> new WmsComponentPackingItem()
.setId(IdUtil.getSnowflakeNextId())
.setItemIndex(item.getIndex())
.setVbeln(item.getVbeln())
.setPosnr(item.getPosnr())
.setIdnrk(item.getIdnrk())
.setOjtxb(item.getOjtxb())
.setMeins(item.getMeins())
.setMenge(item.getMenge())
.setAtwrt(item.getAtwrt())
.setZatwrt(item.getZatwrt())
.setZxiah(item.getZxiah())
.setZtext(item.getZtext())
.setPotx2(item.getPotx2())
.setPmenge(item.getPmenge())
.setLgpbe(item.getLgpbe())
.setLgort(item.getLgort())
.setLgobe(item.getLgobe())
.setOutQty(new BigDecimal(0))
.setPackingId(wmsComponentPacking.getId())
).toList();
List<InventoryLockVO> lockVOS = new ArrayList<>();
request.getItems().forEach(item -> {
RLock lock = redissonClient.getLock(StrUtil.format("lock:inventory:{}:{}:{}", wmsComponentPacking.getFactoryNo(), item.getLgort(), item.getIdnrk()));
try {
// 等待5秒获取锁10秒后自动释放
if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {
if (inventoryService.getNumOne(wmsComponentPacking.getFactoryNo(), item.getLgort(), item.getIdnrk()).compareTo(item.getMenge()) < 0) {
List<InventoryLockVO> itemLocks = inventoryService.getLockList(wmsComponentPacking.getFactoryNo(), item.getLgort(), item.getIdnrk());
VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(itemLocks)).throwMessage("库存不足:" + item.getIdnrk());
lockVOS.addAll(itemLocks);
} else {
wmsComponentPackingItemService.save(
new WmsComponentPackingItem()
.setId(IdUtil.getSnowflakeNextId())
.setItemIndex(item.getIndex())
.setVbeln(item.getVbeln())
.setPosnr(item.getPosnr())
.setIdnrk(item.getIdnrk())
.setOjtxb(item.getOjtxb())
.setMeins(item.getMeins())
.setMenge(item.getMenge())
.setAtwrt(item.getAtwrt())
.setZatwrt(item.getZatwrt())
.setZxiah(item.getZxiah())
.setZtext(item.getZtext())
.setPotx2(item.getPotx2())
.setPmenge(item.getPmenge())
.setLgpbe(item.getLgpbe())
.setLgort(item.getLgort())
.setLgobe(item.getLgobe())
.setOutQty(new BigDecimal(0))
.setPackingId(wmsComponentPacking.getId())
);
}
} else {
throw new NflgException(STATE.BusinessError, "获取锁失败");
}
} catch (Exception e) {
log.error("保存单据出错", e);
throw new NflgException(STATE.BusinessError, e.getMessage());
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
});
if (CollectionUtil.isNotEmpty(lockVOS)) {
throw new DataAlertException(STATE.OutOfStock, lockVOS);
}
// 直接保存
wmscomponentPackingService.save(wmsComponentPacking);
wmsComponentPackingItemService.saveBatch(wmsComponentPackingItems);
}
@Transactional

View File

@ -3,13 +3,13 @@ package com.nflg.wms.repository.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
@ -157,6 +157,7 @@ public class WmsComponentPacking implements Serializable {
/**
* 所属工厂
*/
@NotBlank
private String factoryNo;
/**