feat(inventory): 添加库存锁定检查功能
- 在 ApiResult 中新增 errorWithExtras 方法用于返回额外信息 - 新增 InventoryLockVO 数据传输对象 - 在 IWmsInventoryService 中添加 getLockList 方法查询锁定库存列表 - 修改 IWmsReturnRequestService 的 addPurchaseReturns 方法返回库存锁定信息 - 在多个控制器中添加 Redisson 分布式锁确保库存操作一致性 - 实现库存不足时返回锁定详情的功能 - 在数据库映射中添加 getLockList 查询方法 - 更新 STATE 枚举添加 OutOfStock 状态码 120 - 在多个出库和调拨流程中集成库存锁定检查逻辑
This commit is contained in:
parent
a021013ef2
commit
78dad56dbe
|
|
@ -15,6 +15,8 @@ import com.nflg.wms.admin.util.PdfGeneratorUtil;
|
|||
import com.nflg.wms.admin.util.QRCodeUtil;
|
||||
import com.nflg.wms.admin.util.ThymeleafUtil;
|
||||
import com.nflg.wms.common.constant.BarCodeProcessStage;
|
||||
import com.nflg.wms.common.constant.STATE;
|
||||
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;
|
||||
|
|
@ -32,6 +34,8 @@ import jakarta.validation.Valid;
|
|||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
|
@ -39,6 +43,7 @@ import java.math.BigDecimal;
|
|||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
|
@ -76,15 +81,15 @@ public class OutAssistanceController extends BaseController {
|
|||
@Resource
|
||||
private InventoryForOutRepository inventoryForOutRepository;
|
||||
|
||||
@Resource
|
||||
private IParamConfigService paramConfigService;
|
||||
|
||||
@Resource
|
||||
private IWmsBomService bomService;
|
||||
|
||||
@Resource
|
||||
private IWmsQrCodeMasterService qrCodeMasterService;
|
||||
|
||||
@Resource
|
||||
private RedissonClient redissonClient;
|
||||
|
||||
/**
|
||||
* 查询SAP领料订单数据
|
||||
*/
|
||||
|
|
@ -328,6 +333,34 @@ 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) {
|
||||
lockVOS.addAll(inventoryService.getLockList(info.getFactoryNo(), info.getWarehouseNo(), info.getMaterialNo()));
|
||||
}
|
||||
} 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)) {
|
||||
return ApiResult.errorWithExtras(STATE.OutOfStock, lockVOS);
|
||||
}
|
||||
outAssistanceItemService.updateBatchById(datas);
|
||||
outAssistanceTicketItemService.saveBatch(ticketItems);
|
||||
outAssistanceTicketService.save(ticket);
|
||||
|
|
@ -468,38 +501,37 @@ public class OutAssistanceController extends BaseController {
|
|||
.in(WmsQrCodeMaster::getBarcodeCode, records.stream().map(OutMaterialScanRecord::getUniqNo).toList())
|
||||
.list();
|
||||
qrCodeMasters.forEach(p -> {
|
||||
OutMaterialScanRecord record = records.stream()
|
||||
.filter(r -> r.getUniqNo().equals(p.getBarcodeCode()))
|
||||
.findFirst()
|
||||
.get();
|
||||
p.setFactoryCode(record.getFactoryNo());
|
||||
p.setStorageLocation(record.getWarehouseNo());
|
||||
p.setBinLocation(record.getBinNo());
|
||||
p.setProcessStage(BarCodeProcessStage.OutBound.getState());
|
||||
p.setLastScanBy(UserUtil.getUserId());
|
||||
p.setLastScanByname(UserUtil.getUserName());
|
||||
p.setLastScanTime(LocalDateTime.now());
|
||||
if (p.getPackagingType() == 1) {
|
||||
List<WmsQrCodeMaster> children = qrCodeMasterService.lambdaQuery()
|
||||
.eq(WmsQrCodeMaster::getParentBarcodeId, p.getId())
|
||||
.list();
|
||||
if (CollectionUtil.isNotEmpty(children)) {
|
||||
children.forEach(c -> {
|
||||
c.setProcessStage(p.getProcessStage());
|
||||
c.setFactoryCode(p.getFactoryCode());
|
||||
c.setStorageLocation(p.getStorageLocation());
|
||||
c.setBinLocation(p.getBinLocation());
|
||||
c.setProcessStage(p.getProcessStage());
|
||||
c.setLastScanBy(p.getLastScanBy());
|
||||
c.setLastScanByname(p.getLastScanByname());
|
||||
c.setLastScanTime(p.getLastScanTime());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
OutMaterialScanRecord record = records.stream()
|
||||
.filter(r -> r.getUniqNo().equals(p.getBarcodeCode()))
|
||||
.findFirst()
|
||||
.get();
|
||||
p.setFactoryCode(record.getFactoryNo());
|
||||
p.setStorageLocation(record.getWarehouseNo());
|
||||
p.setBinLocation(record.getBinNo());
|
||||
p.setProcessStage(BarCodeProcessStage.OutBound.getState());
|
||||
p.setLastScanBy(UserUtil.getUserId());
|
||||
p.setLastScanByname(UserUtil.getUserName());
|
||||
p.setLastScanTime(LocalDateTime.now());
|
||||
if (p.getPackagingType() == 1) {
|
||||
List<WmsQrCodeMaster> children = qrCodeMasterService.lambdaQuery()
|
||||
.eq(WmsQrCodeMaster::getParentBarcodeId, p.getId())
|
||||
.list();
|
||||
if (CollectionUtil.isNotEmpty(children)) {
|
||||
children.forEach(c -> {
|
||||
c.setProcessStage(p.getProcessStage());
|
||||
c.setFactoryCode(p.getFactoryCode());
|
||||
c.setStorageLocation(p.getStorageLocation());
|
||||
c.setBinLocation(p.getBinLocation());
|
||||
c.setProcessStage(p.getProcessStage());
|
||||
c.setLastScanBy(p.getLastScanBy());
|
||||
c.setLastScanByname(p.getLastScanByname());
|
||||
c.setLastScanTime(p.getLastScanTime());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
qrCodeMasterService.updateBarCode(qrCodeMasters);
|
||||
submitSap(order, ticket, records, outAssistanceItemService.getList(order.getId()), qrCodeMasters
|
||||
);
|
||||
submitSap(order, ticket, records, outAssistanceItemService.getList(order.getId()), qrCodeMasters);
|
||||
} else {
|
||||
List<OutAssistanceItemVO> items = outAssistanceTicketItemService.getList(qo.getId());
|
||||
items.forEach(it -> {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ import com.nflg.wms.admin.util.PdfGeneratorUtil;
|
|||
import com.nflg.wms.admin.util.QRCodeUtil;
|
||||
import com.nflg.wms.admin.util.ThymeleafUtil;
|
||||
import com.nflg.wms.common.constant.BarCodeProcessStage;
|
||||
import com.nflg.wms.common.constant.STATE;
|
||||
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;
|
||||
|
|
@ -32,6 +34,8 @@ import jakarta.validation.Valid;
|
|||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
|
@ -39,6 +43,7 @@ import java.math.BigDecimal;
|
|||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
|
@ -85,6 +90,9 @@ public class OutCostCenterController extends BaseController {
|
|||
@Resource
|
||||
private IWmsQrCodeMasterService qrCodeMasterService;
|
||||
|
||||
@Resource
|
||||
private RedissonClient redissonClient;
|
||||
|
||||
/**
|
||||
* 查询SAP领料订单数据
|
||||
*/
|
||||
|
|
@ -319,6 +327,34 @@ 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) {
|
||||
lockVOS.addAll(inventoryService.getLockList(info.getFactoryNo(), info.getWarehouseNo(), info.getMaterialNo()));
|
||||
}
|
||||
} 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)) {
|
||||
return ApiResult.errorWithExtras(STATE.OutOfStock, lockVOS);
|
||||
}
|
||||
outCostcenterItemService.updateBatchById(datas);
|
||||
outCostcenterTicketItemService.saveBatch(ticketItems);
|
||||
outCostcenterTicketService.save(ticket);
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ public class OutProduceController extends BaseController {
|
|||
VUtil.trueThrowBusinessError(CollectionUtil.isNotEmpty(materialNos))
|
||||
.throwMessage("以下物料的申请数量超出限制:" + StrUtil.join(",", materialNos));
|
||||
Map<String, List<Zwm3a07VO>> maps = datas.stream().collect(Collectors.groupingBy(Zwm3a07VO::getKey2));
|
||||
List<InventoryLockVO> lockVOS = new ArrayList<>();
|
||||
maps.forEach((key, items) -> {
|
||||
WmsOutProduce order = Convert.convert(WmsOutProduce.class, items.get(0));
|
||||
order.setNo(serialNumberControllerService.generateSerialNumber(9));
|
||||
|
|
@ -155,10 +156,16 @@ public class OutProduceController extends BaseController {
|
|||
try {
|
||||
// 等待5秒获取锁,10秒后自动释放
|
||||
if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {
|
||||
WmsOutProduceItem data = Convert.convert(WmsOutProduceItem.class, item);
|
||||
data.setLockNum(item.getSqsl());
|
||||
data.setOrderId(order.getId());
|
||||
outProduceItemService.save(data);
|
||||
if (inventoryService.getNumOne(item.getDwerk(), item.getLgort2(), item.getMatnr())
|
||||
.compareTo(item.getSqsl()) < 0
|
||||
) {
|
||||
lockVOS.addAll(inventoryService.getLockList(item.getDwerk(), item.getLgort2(), item.getMatnr()));
|
||||
} else {
|
||||
WmsOutProduceItem data = Convert.convert(WmsOutProduceItem.class, item);
|
||||
data.setLockNum(item.getSqsl());
|
||||
data.setOrderId(order.getId());
|
||||
outProduceItemService.save(data);
|
||||
}
|
||||
} else {
|
||||
throw new NflgException(STATE.BusinessError, "获取锁失败");
|
||||
}
|
||||
|
|
@ -166,14 +173,17 @@ public class OutProduceController extends BaseController {
|
|||
log.error("保存生产领料单出错", e);
|
||||
throw new NflgException(STATE.BusinessError, e.getMessage());
|
||||
} finally {
|
||||
// 确保只释放自己持有的锁
|
||||
if (lock.isHeldByCurrentThread()) {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
return ApiResult.success();
|
||||
if (CollectionUtil.isEmpty(lockVOS)) {
|
||||
return ApiResult.success();
|
||||
} else {
|
||||
return ApiResult.errorWithExtras(STATE.OutOfStock, lockVOS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -192,6 +202,7 @@ public class OutProduceController extends BaseController {
|
|||
// VUtil.trueThrowBusinessError(CollectionUtil.isNotEmpty(materialNos))
|
||||
// .throwMessage("以下物料的申请数量超出限制:" + StrUtil.join(",", materialNos));
|
||||
Map<String, List<Zwm3a07VO>> maps = datas.stream().collect(Collectors.groupingBy(Zwm3a07VO::getKey2));
|
||||
List<InventoryLockVO> lockVOS = new ArrayList<>();
|
||||
maps.forEach((key, items) -> {
|
||||
WmsOutProduce order = Convert.convert(WmsOutProduce.class, items.get(0));
|
||||
order.setNo(serialNumberControllerService.generateSerialNumber(9));
|
||||
|
|
@ -200,13 +211,39 @@ public class OutProduceController extends BaseController {
|
|||
order.setCreateTime(LocalDateTime.now());
|
||||
outProduceService.save(order);
|
||||
items.forEach(item -> {
|
||||
WmsOutProduceItem data = Convert.convert(WmsOutProduceItem.class, item);
|
||||
data.setLockNum(BigDecimal.ZERO);
|
||||
data.setOrderId(order.getId());
|
||||
outProduceItemService.save(data);
|
||||
RLock lock = redissonClient.getLock(StrUtil.format("lock:inventory:{}:{}:{}", item.getDwerk(), item.getLgort2(), item.getMatnr()));
|
||||
try {
|
||||
// 等待5秒获取锁,10秒后自动释放
|
||||
if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {
|
||||
if (inventoryService.getNumOne(item.getDwerk(), item.getLgort2(), item.getMatnr())
|
||||
.compareTo(item.getSqsl()) < 0
|
||||
) {
|
||||
lockVOS.addAll(inventoryService.getLockList(item.getDwerk(), item.getLgort2(), item.getMatnr()));
|
||||
} else {
|
||||
WmsOutProduceItem data = Convert.convert(WmsOutProduceItem.class, item);
|
||||
data.setLockNum(data.getSqsl());
|
||||
data.setOrderId(order.getId());
|
||||
outProduceItemService.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();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
return ApiResult.success();
|
||||
if (CollectionUtil.isEmpty(lockVOS)) {
|
||||
return ApiResult.success();
|
||||
} else {
|
||||
return ApiResult.errorWithExtras(STATE.OutOfStock, lockVOS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import com.nflg.wms.admin.util.PdfGeneratorUtil;
|
|||
import com.nflg.wms.admin.util.QRCodeUtil;
|
||||
import com.nflg.wms.admin.util.ThymeleafUtil;
|
||||
import com.nflg.wms.common.constant.BarCodeProcessStage;
|
||||
import com.nflg.wms.common.constant.STATE;
|
||||
import com.nflg.wms.common.constant.UserType;
|
||||
import com.nflg.wms.common.pojo.ApiResult;
|
||||
import com.nflg.wms.common.pojo.PageData;
|
||||
|
|
@ -127,8 +128,12 @@ public class PurchaseReturnController extends BaseController {
|
|||
VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(request))
|
||||
.throwMessage("申请数据不可以为空");
|
||||
List<PurchaseReturnDTO> purchaseReturnDTOList = Convert.toList(PurchaseReturnDTO.class, request);
|
||||
SaveApply(purchaseReturnDTOList, Short.valueOf("0"));
|
||||
return ApiResult.success();
|
||||
List<InventoryLockVO> inventoryLockVOS = SaveApply(purchaseReturnDTOList, Short.valueOf("0"));
|
||||
if (CollectionUtil.isEmpty(inventoryLockVOS)) {
|
||||
return ApiResult.success();
|
||||
} else {
|
||||
return ApiResult.errorWithExtras(STATE.OutOfStock, inventoryLockVOS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -171,7 +176,7 @@ public class PurchaseReturnController extends BaseController {
|
|||
.throwMessage("无效申请单");
|
||||
User user = userService.getById(UserUtil.getUserId());
|
||||
VUtil.trueThrowBusinessError(StrUtil.equals(user.getPurchasingGroup(), returnRequest.getPurchaseGroup()))
|
||||
.throwMessage("无权限审核此单");
|
||||
.throwMessage("无权限审核此单");
|
||||
// VUtil.trueThrowBusinessError(returnRequest.getApprovalStatus() == 1)
|
||||
// .throwMessage("此单已审核通过,不可以再此审核");
|
||||
|
||||
|
|
@ -285,7 +290,7 @@ public class PurchaseReturnController extends BaseController {
|
|||
* 保存申请单
|
||||
* @return
|
||||
*/
|
||||
private void SaveApply(List<PurchaseReturnDTO> purchaseReturnDTOList, Short dataSource) {
|
||||
private List<InventoryLockVO> SaveApply(List<PurchaseReturnDTO> purchaseReturnDTOList, Short dataSource) {
|
||||
//根据采购组编号、采购单编号、供应商id进行去除
|
||||
List<String> disGroupCode = purchaseReturnDTOList.stream()
|
||||
.map(PurchaseReturnDTO::getGroupCode)
|
||||
|
|
@ -334,7 +339,7 @@ public class PurchaseReturnController extends BaseController {
|
|||
returnRequestItems.add(returnRequestItem);
|
||||
}
|
||||
}
|
||||
returnRequestService.addPurchaseReturns(returnRequests, returnRequestItems);
|
||||
return returnRequestService.addPurchaseReturns(returnRequests, returnRequestItems);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -372,6 +377,7 @@ public class PurchaseReturnController extends BaseController {
|
|||
for (WmsQrCodeMaster qrCodeMaster : qrCodeMasters) {
|
||||
qrCodeVOS.add(BarcodeValidation(qrCodeMaster));
|
||||
}
|
||||
List<InventoryLockVO> inventoryLockVOS = null;
|
||||
if (CollectionUtil.isNotEmpty(qrCodeVOS)) {
|
||||
List<PurchaseReturnDTO> purchaseReturnDTOList = new ArrayList<>();
|
||||
for (QrCodeVO qrCodeVO : qrCodeVOS) {
|
||||
|
|
@ -430,10 +436,14 @@ public class PurchaseReturnController extends BaseController {
|
|||
);
|
||||
purchaseReturnDTO.setGroupCode(groupCode);
|
||||
}
|
||||
SaveApply(purchaseReturnDTOList, Short.valueOf("1"));
|
||||
inventoryLockVOS = SaveApply(purchaseReturnDTOList, Short.valueOf("1"));
|
||||
}
|
||||
}
|
||||
return ApiResult.success();
|
||||
if (CollectionUtil.isEmpty(inventoryLockVOS)) {
|
||||
return ApiResult.success();
|
||||
} else {
|
||||
return ApiResult.errorWithExtras(STATE.OutOfStock, inventoryLockVOS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -463,8 +473,8 @@ public class PurchaseReturnController extends BaseController {
|
|||
public void exportTicket(HttpServletResponse response, @Valid @RequestParam @NotNull Long id) throws Exception {
|
||||
WmsReturnRequest order = returnRequestService.getById(id);
|
||||
VUtil.trueThrowBusinessError(Objects.isNull(order)).throwMessage("申请单不存在");
|
||||
VUtil.trueThrowBusinessError(order.getApprovalStatus()!=1).throwMessage("申请单未审核通过");
|
||||
UserSupplier supplier=userSupplierService.getByCode(order.getSupplierCode());
|
||||
VUtil.trueThrowBusinessError(order.getApprovalStatus() != 1).throwMessage("申请单未审核通过");
|
||||
UserSupplier supplier = userSupplierService.getByCode(order.getSupplierCode());
|
||||
List<WmsReturnRequestItem> list = returnRequestItemService.lambdaQuery()
|
||||
.eq(WmsReturnRequestItem::getApplicationId, id)
|
||||
.list();
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ import com.nflg.wms.admin.service.BasdeSerialNumberControllerService;
|
|||
import com.nflg.wms.admin.service.SapService;
|
||||
import com.nflg.wms.admin.util.*;
|
||||
import com.nflg.wms.common.constant.BarCodeProcessStage;
|
||||
import com.nflg.wms.common.constant.STATE;
|
||||
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.InMaterialScanRecord;
|
||||
|
|
@ -37,6 +39,8 @@ import jakarta.validation.constraints.NotBlank;
|
|||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
|
@ -44,6 +48,7 @@ import java.math.BigDecimal;
|
|||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
|
@ -87,9 +92,6 @@ public class TransferCompanyController extends BaseController {
|
|||
@Resource
|
||||
private InventoryForOutRepository inventoryForOutRepository;
|
||||
|
||||
@Resource
|
||||
private IParamConfigService paramConfigService;
|
||||
|
||||
@Resource
|
||||
private IWmsWarehouseService warehouseService;
|
||||
|
||||
|
|
@ -99,6 +101,9 @@ public class TransferCompanyController extends BaseController {
|
|||
@Resource
|
||||
private IWmsQrCodeMasterService qrCodeMasterService;
|
||||
|
||||
@Resource
|
||||
private RedissonClient redissonClient;
|
||||
|
||||
/**
|
||||
* 查询SAP订单数据
|
||||
*/
|
||||
|
|
@ -124,6 +129,7 @@ public class TransferCompanyController extends BaseController {
|
|||
VUtil.trueThrowBusinessError(CollectionUtil.isNotEmpty(materialNos))
|
||||
.throwMessage("以下物料的申请数量超出限制:" + StrUtil.join(",", materialNos));
|
||||
Map<String, List<AllocationOrderDTO>> maps = datas.stream().collect(Collectors.groupingBy(AllocationOrderDTO::getGroup1));
|
||||
List<InventoryLockVO> lockVOS = new ArrayList<>();
|
||||
maps.forEach((key, items) -> {
|
||||
WmsTransferCompany order = Convert.convert(WmsTransferCompany.class, items.get(0));
|
||||
order.setNo(serialNumberControllerService.generateSerialNumber(22));
|
||||
|
|
@ -131,16 +137,38 @@ public class TransferCompanyController extends BaseController {
|
|||
order.setCreateTime(LocalDateTime.now());
|
||||
transferCompanyService.save(order);
|
||||
items.forEach(item -> {
|
||||
BigDecimal max = inventoryService.getNumOne(item.getReswk(), item.getLgfsb1(), item.getMatnr());
|
||||
VUtil.trueThrowBusinessError(item.getNum().compareTo(max) > 0)
|
||||
.throwMessage("物料" + item.getMatnr() + "的申请数量超出库存限制");
|
||||
WmsTransferCompanyItem data = Convert.convert(WmsTransferCompanyItem.class, item);
|
||||
data.setOrderId(order.getId());
|
||||
data.setLeft(data.getNum());
|
||||
transferCompanyItemService.save(data);
|
||||
RLock lock = redissonClient.getLock(StrUtil.format("lock:inventory:{}:{}:{}", item.getReswk(), item.getLgfsb1(), item.getMatnr()));
|
||||
try {
|
||||
// 等待5秒获取锁,10秒后自动释放
|
||||
if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {
|
||||
if (inventoryService.getNumOne(item.getReswk(), item.getLgfsb1(), item.getMatnr())
|
||||
.compareTo(item.getNum()) < 0
|
||||
) {
|
||||
lockVOS.addAll(inventoryService.getLockList(item.getReswk(), item.getLgfsb1(), item.getMatnr()));
|
||||
} else {
|
||||
WmsTransferCompanyItem data = Convert.convert(WmsTransferCompanyItem.class, item);
|
||||
data.setOrderId(order.getId());
|
||||
data.setLeft(data.getNum());
|
||||
transferCompanyItemService.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();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
return ApiResult.success();
|
||||
if (CollectionUtil.isEmpty(lockVOS)) {
|
||||
return ApiResult.success();
|
||||
} else {
|
||||
return ApiResult.errorWithExtras(STATE.OutOfStock, lockVOS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ import com.nflg.wms.admin.util.PdfGeneratorUtil;
|
|||
import com.nflg.wms.admin.util.QRCodeUtil;
|
||||
import com.nflg.wms.admin.util.ThymeleafUtil;
|
||||
import com.nflg.wms.common.constant.BarCodeProcessStage;
|
||||
import com.nflg.wms.common.constant.STATE;
|
||||
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.InMaterialScanRecord;
|
||||
|
|
@ -35,6 +37,8 @@ import jakarta.validation.constraints.NotBlank;
|
|||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
|
@ -42,6 +46,7 @@ import java.math.BigDecimal;
|
|||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
|
@ -85,9 +90,6 @@ public class TransferFactoryController extends BaseController {
|
|||
@Resource
|
||||
private InventoryForOutRepository inventoryForOutRepository;
|
||||
|
||||
@Resource
|
||||
private IParamConfigService paramConfigService;
|
||||
|
||||
@Resource
|
||||
private IWmsBomService bomService;
|
||||
|
||||
|
|
@ -97,6 +99,9 @@ public class TransferFactoryController extends BaseController {
|
|||
@Resource
|
||||
private IWmsQrCodeMasterService qrCodeMasterService;
|
||||
|
||||
@Resource
|
||||
private RedissonClient redissonClient;
|
||||
|
||||
/**
|
||||
* 查询SAP领料订单数据
|
||||
*/
|
||||
|
|
@ -122,6 +127,7 @@ public class TransferFactoryController extends BaseController {
|
|||
VUtil.trueThrowBusinessError(CollectionUtil.isNotEmpty(materialNos))
|
||||
.throwMessage("以下物料的申请数量超出限制:" + StrUtil.join(",", materialNos));
|
||||
Map<String, List<TransferOrderDTO>> maps = datas.stream().collect(Collectors.groupingBy(TransferOrderDTO::getGroup1));
|
||||
List<InventoryLockVO> lockVOS = new ArrayList<>();
|
||||
maps.forEach((key, items) -> {
|
||||
WmsTransferFactory order = Convert.convert(WmsTransferFactory.class, items.get(0));
|
||||
order.setNo(serialNumberControllerService.generateSerialNumber(18));
|
||||
|
|
@ -129,16 +135,38 @@ public class TransferFactoryController extends BaseController {
|
|||
order.setCreateTime(LocalDateTime.now());
|
||||
transferFactoryService.save(order);
|
||||
items.forEach(item -> {
|
||||
BigDecimal max = inventoryService.getNumOne(item.getWerks(), item.getLgort(), item.getMatnr());
|
||||
VUtil.trueThrowBusinessError(item.getNum().compareTo(max) > 0)
|
||||
.throwMessage("物料" + item.getMatnr() + "的申请数量超出库存限制");
|
||||
WmsTransferFactoryItem data = Convert.convert(WmsTransferFactoryItem.class, item);
|
||||
data.setOrderId(order.getId());
|
||||
data.setLeft(data.getNum());
|
||||
transferFactoryItemService.save(data);
|
||||
RLock lock = redissonClient.getLock(StrUtil.format("lock:inventory:{}:{}:{}", item.getWerks(), item.getLgort(), item.getMatnr()));
|
||||
try {
|
||||
// 等待5秒获取锁,10秒后自动释放
|
||||
if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {
|
||||
if (inventoryService.getNumOne(item.getWerks(), item.getLgort(), item.getMatnr())
|
||||
.compareTo(item.getNum()) < 0
|
||||
) {
|
||||
lockVOS.addAll(inventoryService.getLockList(item.getWerks(), item.getLgort(), item.getMatnr()));
|
||||
} else {
|
||||
WmsTransferFactoryItem data = Convert.convert(WmsTransferFactoryItem.class, item);
|
||||
data.setOrderId(order.getId());
|
||||
data.setLeft(data.getNum());
|
||||
transferFactoryItemService.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();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
return ApiResult.success();
|
||||
if (CollectionUtil.isEmpty(lockVOS)) {
|
||||
return ApiResult.success();
|
||||
} else {
|
||||
return ApiResult.errorWithExtras(STATE.OutOfStock, lockVOS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ public enum STATE {
|
|||
RequestMethodError(116, "请求方式错误"),
|
||||
InconsistentDataError(117, "需要用户确认"),
|
||||
NoOrderData(118, "订单不存在"),
|
||||
SAPErr(119, "SAP错误");
|
||||
SAPErr(119, "SAP错误"),
|
||||
OutOfStock(120, "库存不足");
|
||||
|
||||
@Getter
|
||||
private final Integer state;
|
||||
|
|
|
|||
|
|
@ -27,16 +27,16 @@ public class ApiResult<T> implements Serializable {
|
|||
ApiResult<T> vo = new ApiResult<>();
|
||||
vo.result = value;
|
||||
vo.code = STATE.Success.getState();
|
||||
vo.type=STATE.Success.getType();
|
||||
vo.type = STATE.Success.getType();
|
||||
return vo;
|
||||
}
|
||||
|
||||
public static <T> ApiResult<T> error(int state,String msg,T value) {
|
||||
public static <T> ApiResult<T> error(int state, String msg, T value) {
|
||||
ApiResult<T> vo = new ApiResult<>();
|
||||
vo.result = value;
|
||||
vo.code = state;
|
||||
vo.type = msg;
|
||||
vo.message=msg;
|
||||
vo.message = msg;
|
||||
return vo;
|
||||
}
|
||||
|
||||
|
|
@ -49,7 +49,15 @@ public class ApiResult<T> implements Serializable {
|
|||
return vo;
|
||||
}
|
||||
|
||||
public static <T> ApiResult<T> error(int state, String type,String msg) {
|
||||
public static <T> ApiResult<T> errorWithExtras(STATE state,Object extras) {
|
||||
ApiResult<T> vo = new ApiResult<>();
|
||||
vo.extras = extras;
|
||||
vo.code = state.getState();
|
||||
vo.type = state.getType();
|
||||
return vo;
|
||||
}
|
||||
|
||||
public static <T> ApiResult<T> error(int state, String type, String msg) {
|
||||
ApiResult<T> vo = new ApiResult<T>();
|
||||
vo.code = state;
|
||||
vo.type = type;
|
||||
|
|
@ -63,12 +71,13 @@ public class ApiResult<T> implements Serializable {
|
|||
vo.type = STATE.Success.getType();
|
||||
return vo;
|
||||
}
|
||||
|
||||
public static <T> ApiResult<T> error(STATE code, String msg) {
|
||||
return error(code.getState(),code.getType(), msg);
|
||||
return error(code.getState(), code.getType(), msg);
|
||||
}
|
||||
|
||||
public static <T> ApiResult<T> error(String msg) {
|
||||
return error(STATE.Error.getState(),STATE.Error.getType(), msg);
|
||||
return error(STATE.Error.getState(), STATE.Error.getType(), msg);
|
||||
}
|
||||
|
||||
public static <T> ApiResult<T> error(STATE code) {
|
||||
|
|
@ -92,7 +101,7 @@ public class ApiResult<T> implements Serializable {
|
|||
return vo;
|
||||
}
|
||||
|
||||
public static <T,D> ApiResult<PageData<D>> success(IPage<T> page, Function<T, D> converter) {
|
||||
public static <T, D> ApiResult<PageData<D>> success(IPage<T> page, Function<T, D> converter) {
|
||||
ApiResult<PageData<D>> vo = new ApiResult<>();
|
||||
PageData<D> pageData = new PageData<>();
|
||||
pageData.setPage((int) page.getCurrent());
|
||||
|
|
|
|||
|
|
@ -201,4 +201,11 @@ public class OutMaterialScanRecord {
|
|||
public String getKey9() {
|
||||
return materialNo + "|" + getBatchNo() + "|" + this.getSerialNo() + "|" + this.getBinNo();
|
||||
}
|
||||
|
||||
@Transient
|
||||
private String key10;
|
||||
|
||||
public String getKey10() {
|
||||
return materialNo + "|" + getFactoryNo() + "|" + this.getWarehouseNo();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
package com.nflg.wms.common.pojo.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class InventoryLockVO {
|
||||
|
||||
/**
|
||||
* 订单类型
|
||||
*/
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 订单编号
|
||||
*/
|
||||
private String no;
|
||||
|
||||
/**
|
||||
* 工厂编号
|
||||
*/
|
||||
private String factoryNo;
|
||||
|
||||
/**
|
||||
* 仓库编号
|
||||
*/
|
||||
private String warehouseNo;
|
||||
|
||||
/**
|
||||
* 物料编号
|
||||
*/
|
||||
private String materialNo;
|
||||
|
||||
/**
|
||||
* 锁定数量
|
||||
*/
|
||||
private BigDecimal lockNum;
|
||||
}
|
||||
|
|
@ -56,6 +56,12 @@
|
|||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-crypto</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.redisson</groupId>
|
||||
<artifactId>redisson</artifactId>
|
||||
<version>3.52.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.nflg.wms.common.pojo.dto.InventoryInDTO;
|
||||
import com.nflg.wms.common.pojo.qo.InventorySearchQO;
|
||||
import com.nflg.wms.common.pojo.vo.InventoryLockVO;
|
||||
import com.nflg.wms.common.pojo.vo.InventoryVO;
|
||||
import com.nflg.wms.repository.entity.WmsInventory;
|
||||
|
||||
|
|
@ -30,4 +31,6 @@ public interface WmsInventoryMapper extends BaseMapper<WmsInventory> {
|
|||
BigDecimal getNumOne(String factoryNo, String warehouseNo, String materialNo);
|
||||
|
||||
BigDecimal getLockedNumOne(String factoryNo, String warehouseNo, String materialNo);
|
||||
|
||||
List<InventoryLockVO> getLockList(String factoryNo, String warehouseNo, String materialNo);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
|||
import com.nflg.wms.common.pojo.dto.InventoryInDTO;
|
||||
import com.nflg.wms.common.pojo.dto.InventoryOutDTO;
|
||||
import com.nflg.wms.common.pojo.qo.InventorySearchQO;
|
||||
import com.nflg.wms.common.pojo.vo.InventoryLockVO;
|
||||
import com.nflg.wms.common.pojo.vo.InventoryVO;
|
||||
import com.nflg.wms.repository.entity.WmsInventory;
|
||||
import jakarta.validation.Valid;
|
||||
|
|
@ -48,4 +49,6 @@ public interface IWmsInventoryService extends IService<WmsInventory> {
|
|||
BigDecimal getNumOne(String factoryNo, String warehouseNo, String materialNo);
|
||||
|
||||
List<WmsInventory> getForOutFIFO(String factoryNo, String warehouseNo, Collection<String> materialNos);
|
||||
|
||||
List<InventoryLockVO> getLockList(String factoryNo, String warehouseNo, String materialNo);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.nflg.wms.common.pojo.qo.ApplyReturnRequestSearchQO;
|
|||
import com.nflg.wms.common.pojo.qo.GoodsReceiptSearchQO;
|
||||
import com.nflg.wms.common.pojo.vo.ApplyReturnRequestVO;
|
||||
import com.nflg.wms.common.pojo.vo.GoodsReceiptVO;
|
||||
import com.nflg.wms.common.pojo.vo.InventoryLockVO;
|
||||
import com.nflg.wms.repository.entity.WmsReturnRequest;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.nflg.wms.repository.entity.WmsReturnRequestItem;
|
||||
|
|
@ -25,7 +26,7 @@ import java.util.List;
|
|||
*/
|
||||
public interface IWmsReturnRequestService extends IService<WmsReturnRequest> {
|
||||
|
||||
void addPurchaseReturns(List<WmsReturnRequest> returnRequests, List<WmsReturnRequestItem> returnRequestItems);
|
||||
List<InventoryLockVO> addPurchaseReturns(List<WmsReturnRequest> returnRequests, List<WmsReturnRequestItem> returnRequestItems);
|
||||
|
||||
IPage<GoodsReceiptVO> getGoodsReceipts(@Valid GoodsReceiptSearchQO request);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.nflg.wms.common.exception.NflgException;
|
|||
import com.nflg.wms.common.pojo.dto.InventoryInDTO;
|
||||
import com.nflg.wms.common.pojo.dto.InventoryOutDTO;
|
||||
import com.nflg.wms.common.pojo.qo.InventorySearchQO;
|
||||
import com.nflg.wms.common.pojo.vo.InventoryLockVO;
|
||||
import com.nflg.wms.common.pojo.vo.InventoryVO;
|
||||
import com.nflg.wms.common.util.UserUtil;
|
||||
import com.nflg.wms.common.util.VUtil;
|
||||
|
|
@ -194,4 +195,9 @@ public class WmsInventoryServiceImpl extends ServiceImpl<WmsInventoryMapper, Wms
|
|||
.orderByAsc(WmsInventory::getId)
|
||||
.list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<InventoryLockVO> getLockList(String factoryNo, String warehouseNo, String materialNo) {
|
||||
return baseMapper.getLockList(factoryNo, warehouseNo, materialNo);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,39 @@
|
|||
package com.nflg.wms.repository.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.nflg.wms.common.constant.STATE;
|
||||
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.qo.ApplyReturnRequestSearchQO;
|
||||
import com.nflg.wms.common.pojo.qo.GoodsReceiptSearchQO;
|
||||
import com.nflg.wms.common.pojo.vo.ApplyReturnRequestVO;
|
||||
import com.nflg.wms.common.pojo.vo.GoodsReceiptVO;
|
||||
import com.nflg.wms.common.pojo.vo.InventoryLockVO;
|
||||
import com.nflg.wms.repository.entity.WmsOutProduceItem;
|
||||
import com.nflg.wms.repository.entity.WmsReturnRequest;
|
||||
import com.nflg.wms.repository.entity.WmsReturnRequestItem;
|
||||
import com.nflg.wms.repository.mapper.WmsReturnRequestMapper;
|
||||
import com.nflg.wms.repository.service.IWmsInventoryService;
|
||||
import com.nflg.wms.repository.service.IWmsReturnRequestItemService;
|
||||
import com.nflg.wms.repository.service.IWmsReturnRequestService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
|
@ -38,15 +49,49 @@ public class WmsReturnRequestServiceImpl extends ServiceImpl<WmsReturnRequestMap
|
|||
@Resource
|
||||
private IWmsReturnRequestItemService itemService;
|
||||
|
||||
@Resource
|
||||
private RedissonClient redissonClient;
|
||||
|
||||
@Resource
|
||||
private IWmsInventoryService inventoryService;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void addPurchaseReturns(List<WmsReturnRequest> returnRequests, List<WmsReturnRequestItem> returnRequestItems) {
|
||||
public List<InventoryLockVO> addPurchaseReturns(List<WmsReturnRequest> returnRequests, List<WmsReturnRequestItem> returnRequestItems) {
|
||||
if (CollectionUtil.isNotEmpty(returnRequests)) {
|
||||
this.saveBatch(returnRequests);
|
||||
}
|
||||
if (CollectionUtil.isNotEmpty(returnRequestItems)) {
|
||||
itemService.saveBatch(returnRequestItems);
|
||||
List<InventoryLockVO> lockVOS = new ArrayList<>();
|
||||
returnRequestItems.forEach(item->{
|
||||
RLock lock = redissonClient.getLock(StrUtil.format("lock:inventory:{}:{}:{}", item.getFactoryCode(), item.getStorageLocation(), item.getMaterialCode()));
|
||||
try {
|
||||
// 等待5秒获取锁,10秒后自动释放
|
||||
if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {
|
||||
if (inventoryService.getNumOne(item.getFactoryCode(), item.getStorageLocation(), item.getMaterialCode())
|
||||
.compareTo(item.getLeft()) < 0
|
||||
) {
|
||||
lockVOS.addAll(inventoryService.getLockList(item.getFactoryCode(), item.getStorageLocation(), item.getMaterialCode()));
|
||||
} else {
|
||||
itemService.save(item);
|
||||
}
|
||||
} 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)) {
|
||||
return lockVOS;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
</select>
|
||||
|
||||
<select id="getLockedNum" resultType="com.nflg.wms.common.pojo.dto.InventoryInDTO">
|
||||
SELECT material_no,num
|
||||
SELECT material_no,sum(lock_num) as num
|
||||
FROM v_inventory_lock
|
||||
WHERE factory_no=#{factoryNo} AND warehouse_no=#{warehouseNo}
|
||||
<if test="materialNos != null and materialNos.size() > 0">
|
||||
|
|
@ -48,18 +48,26 @@
|
|||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
group by material_no
|
||||
</select>
|
||||
|
||||
<select id="getNumOne" resultType="java.math.BigDecimal">
|
||||
SELECT SUM(num) num
|
||||
SELECT SUM(num) as num
|
||||
FROM wms_inventory
|
||||
WHERE factory_no=#{factoryNo} AND warehouse_no=#{warehouseNo} AND material_no=#{materialNo}
|
||||
GROUP BY factory_no,warehouse_no,material_no
|
||||
</select>
|
||||
|
||||
<select id="getLockedNumOne" resultType="java.math.BigDecimal">
|
||||
SELECT num
|
||||
SELECT SUM(lock_num) as num
|
||||
FROM v_inventory_lock
|
||||
WHERE factory_no=#{factoryNo} AND warehouse_no=#{warehouseNo} AND material_no=#{materialNo}
|
||||
</select>
|
||||
|
||||
<select id="getLockList" resultType="com.nflg.wms.common.pojo.vo.InventoryLockVO">
|
||||
SELECT *
|
||||
FROM v_inventory_lock
|
||||
WHERE factory_no=#{factoryNo} AND warehouse_no=#{warehouseNo} AND material_no=#{materialNo}
|
||||
ORDER BY id DESC
|
||||
</select>
|
||||
</mapper>
|
||||
|
|
|
|||
Loading…
Reference in New Issue