|
@@ -10,15 +10,18 @@ import com.ruoyi.base.domain.BaseLocationInfo;
|
|
|
import com.ruoyi.base.domain.vo.BaseLocationLotattListVO;
|
|
|
import com.ruoyi.base.domain.vo.BaseLocationLotattVO;
|
|
|
import com.ruoyi.base.domain.vo.LotattInfo;
|
|
|
+import com.ruoyi.base.mapper.BaseLocationInfoMapper;
|
|
|
import com.ruoyi.base.service.IBaseLocationInfoService;
|
|
|
import com.ruoyi.common.core.redis.RedisCache;
|
|
|
import com.ruoyi.common.core.redis.RedisKey;
|
|
|
+import com.ruoyi.common.exception.ServiceException;
|
|
|
import com.ruoyi.common.utils.StringUtils;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.BeanUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.data.redis.core.RedisTemplate;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
import java.util.*;
|
|
|
|
|
@@ -35,6 +38,8 @@ public class LocationAllocationStrategy {
|
|
|
private RedisCache redisCache;
|
|
|
@Autowired
|
|
|
private IBaseLocationInfoService baseLocationInfoService;
|
|
|
+ @Autowired
|
|
|
+ private BaseLocationInfoMapper baseLocationInfoMapper;
|
|
|
|
|
|
/**
|
|
|
* 过滤锁定库位
|
|
@@ -342,19 +347,6 @@ public class LocationAllocationStrategy {
|
|
|
return currentLocation;
|
|
|
}
|
|
|
|
|
|
- private Double checkOutedInvQty(OutWarehouseDTO ow, Map<String, List<LotattInfo>> lockInvList) {
|
|
|
- Double qty = 0d;
|
|
|
- for (Map.Entry<String, List<LotattInfo>> entry : lockInvList.entrySet()) {
|
|
|
- List<LotattInfo> list = entry.getValue();
|
|
|
- for (LotattInfo info : list) {
|
|
|
- if (info.getSku().equals(ow.getSku())) {
|
|
|
- qty += info.getQty();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return qty;
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* 过滤库存信息
|
|
|
*
|
|
@@ -364,126 +356,279 @@ public class LocationAllocationStrategy {
|
|
|
* @param token 唯一token用来解锁加锁
|
|
|
* @return
|
|
|
*/
|
|
|
+ @Transactional
|
|
|
public List<BaseLocationInfo> filterLockInv(List<Long> locationIdList, List<OutWarehouseDTO> outWarehouseDTOs, AsnSoStrategy asnSoStrategy, Long token) {
|
|
|
//取出范围内所有的库存
|
|
|
List<BaseLocationLotattListVO> locationLotattVOList = baseLocationInfoService.selectSortedLocatinListByZoneId(locationIdList, 1L, null, null);
|
|
|
List<BaseLocationInfo> result = new ArrayList<>(); //返回的结果
|
|
|
- Map<String, List<LotattInfo>> lockInv = new HashMap<>(); //已锁定的库存列表(key:列名,value:库位库存)
|
|
|
+ Map<String, List<BaseLocationLotattListVO>> lockInv = new HashMap<>(); //已锁定的库存列表(key:列名,value:库位库存)
|
|
|
//将同一列的库位排序好====================================================>
|
|
|
LinkedHashMap<String, Boolean> taskingFlag = new LinkedHashMap<>(); //任务中的列
|
|
|
LinkedHashMap<String, List<BaseLocationLotattListVO>> mapFloor = new LinkedHashMap<>(); //同一列的库存(key:列名,value:库位库存)地堆
|
|
|
- LinkedHashMap<String, List<BaseLocationLotattListVO>> shelvesFloor = new LinkedHashMap<>(); //同一列的库存(key:列名,value:库位库存)货架
|
|
|
- LinkedHashMap<String, String> skuTagMap = new LinkedHashMap<>(); //每列存放的物料分类(key:列名,value:sku)
|
|
|
- List<LocationSortDTO> list = new ArrayList<>();//全部
|
|
|
- List<LocationSortDTO> sameLotattList = new ArrayList<>(); //同批号
|
|
|
+ LinkedHashMap<String, List<BaseLocationLotattListVO>> mapShelves = new LinkedHashMap<>(); //同一列的库存(key:列名,value:库位库存)货架
|
|
|
+ LinkedHashMap<String, String> skuTagMapFloor = new LinkedHashMap<>(); //每列存放的物料分类(key:列名,value:sku)
|
|
|
+ LinkedHashMap<String, String> skuTagMapShelves = new LinkedHashMap<>(); //每列存放的物料分类(key:列名,value:sku)
|
|
|
for (BaseLocationLotattListVO info : locationLotattVOList) {
|
|
|
List<BaseLocationLotattListVO> infoList;
|
|
|
- if (info.getLocationType().equals("1")) {
|
|
|
- if (shelvesFloor.containsKey(info.getColNo())) {
|
|
|
- infoList = shelvesFloor.get(info.getColNo());
|
|
|
+ if (info.getLocationType().equals("1")) { //货架
|
|
|
+ if (mapShelves.containsKey(info.getColNo())) {
|
|
|
+ infoList = mapShelves.get(info.getColNo());
|
|
|
} else {
|
|
|
infoList = new ArrayList<>();
|
|
|
}
|
|
|
- } else {
|
|
|
+ } else { //地堆
|
|
|
if (mapFloor.containsKey(info.getColNo())) {
|
|
|
infoList = mapFloor.get(info.getColNo());
|
|
|
} else {
|
|
|
infoList = new ArrayList<>();
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+ //将查询出来的baslocation按照列存放到map中
|
|
|
if (info.getColNo() != null) {
|
|
|
- if (skuTagMap.containsKey(info.getColNo())) {
|
|
|
- String tmp = skuTagMap.get(info.getColNo());
|
|
|
- StringBuffer sb = new StringBuffer(tmp);
|
|
|
- List<LotattInfo> lotattInfoList = info.getLotattInfoList();
|
|
|
- if (info.getLotattInfoList() != null && info.getLotattInfoList().size() > 0) {
|
|
|
- for (LotattInfo lot : lotattInfoList) {
|
|
|
- if (lot.getSku() == null || tmp.contains(lot.getSku())) {
|
|
|
- continue;
|
|
|
+ if (info.getLocationType().equals("1")) { //货架
|
|
|
+ //重复代码不用看来逻辑一样的存放的map不一样
|
|
|
+ if (skuTagMapShelves.containsKey(info.getColNo())) {
|
|
|
+ String tmp = skuTagMapShelves.get(info.getColNo());
|
|
|
+ StringBuffer sb = new StringBuffer(tmp);
|
|
|
+ List<LotattInfo> lotattInfoList = info.getLotattInfoList();
|
|
|
+ if (info.getLotattInfoList() != null && info.getLotattInfoList().size() > 0) {
|
|
|
+ for (LotattInfo lot : lotattInfoList) {
|
|
|
+ if (lot.getSku() == null || tmp.contains(lot.getSku())) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ sb.append(",");
|
|
|
+ sb.append(lot.getSku());
|
|
|
+ }
|
|
|
+ if (sb.length() > 0) {
|
|
|
+ skuTagMapShelves.put(info.getColNo(), sb.toString());
|
|
|
}
|
|
|
- sb.append(",");
|
|
|
- sb.append(lot.getSku());
|
|
|
}
|
|
|
- if (sb.length() > 0) {
|
|
|
- skuTagMap.put(info.getColNo(), sb.toString());
|
|
|
+ } else {
|
|
|
+ StringBuffer sb = new StringBuffer("");
|
|
|
+ List<LotattInfo> lotattInfoList = info.getLotattInfoList();
|
|
|
+ if (info.getLotattInfoList() != null && info.getLotattInfoList().size() > 0) {
|
|
|
+ for (LotattInfo lot : lotattInfoList) {
|
|
|
+ if (lot.getSku() == null || sb.toString().contains(lot.getSku())) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ sb.append(",");
|
|
|
+ sb.append(lot.getSku());
|
|
|
+ }
|
|
|
+ if (sb.length() > 0) {
|
|
|
+ skuTagMapShelves.put(info.getColNo(), sb.toString());
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
- StringBuffer sb = new StringBuffer("");
|
|
|
- List<LotattInfo> lotattInfoList = info.getLotattInfoList();
|
|
|
- if (info.getLotattInfoList() != null && info.getLotattInfoList().size() > 0) {
|
|
|
- for (LotattInfo lot : lotattInfoList) {
|
|
|
- if (lot.getSku() == null || sb.toString().contains(lot.getSku())) {
|
|
|
- continue;
|
|
|
+ if (skuTagMapFloor.containsKey(info.getColNo())) {
|
|
|
+ String tmp = skuTagMapFloor.get(info.getColNo());
|
|
|
+ StringBuffer sb = new StringBuffer(tmp);
|
|
|
+ List<LotattInfo> lotattInfoList = info.getLotattInfoList();
|
|
|
+ if (info.getLotattInfoList() != null && info.getLotattInfoList().size() > 0) {
|
|
|
+ for (LotattInfo lot : lotattInfoList) {
|
|
|
+ if (lot.getSku() == null || tmp.contains(lot.getSku())) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ sb.append(",");
|
|
|
+ sb.append(lot.getSku());
|
|
|
+ }
|
|
|
+ if (sb.length() > 0) {
|
|
|
+ skuTagMapFloor.put(info.getColNo(), sb.toString());
|
|
|
}
|
|
|
- sb.append(",");
|
|
|
- sb.append(lot.getSku());
|
|
|
}
|
|
|
- if (sb.length() > 0) {
|
|
|
- skuTagMap.put(info.getColNo(), sb.toString());
|
|
|
+ } else {
|
|
|
+ StringBuffer sb = new StringBuffer("");
|
|
|
+ List<LotattInfo> lotattInfoList = info.getLotattInfoList();
|
|
|
+ if (info.getLotattInfoList() != null && info.getLotattInfoList().size() > 0) {
|
|
|
+ for (LotattInfo lot : lotattInfoList) {
|
|
|
+ if (lot.getSku() == null || sb.toString().contains(lot.getSku())) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ sb.append(",");
|
|
|
+ sb.append(lot.getSku());
|
|
|
+ }
|
|
|
+ if (sb.length() > 0) {
|
|
|
+ skuTagMapFloor.put(info.getColNo(), sb.toString());
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- if (info.getStockStatus().equals("10") || redisCache.checkIsLock(RedisKey.LOCK_LOCATION + info.getId())) {
|
|
|
- taskingFlag.put(info.getColNo(), true);
|
|
|
- lockInv.put(info.getId().toString(), info.getLotattInfoList());
|
|
|
- //如果在任务中跳过该库存
|
|
|
- } else {
|
|
|
- if (taskingFlag.get(info.getColNo()) == null || taskingFlag.get(info.getColNo()).booleanValue() == false) {
|
|
|
- taskingFlag.put(info.getColNo(), false);
|
|
|
- }
|
|
|
- }
|
|
|
infoList.add(info);
|
|
|
- if (info.getLocationType().equals("1")) {
|
|
|
- mapFloor.put(info.getColNo(), infoList);
|
|
|
+ if (info.getLocationType().equals("1")) { //把货架和地堆存放到不同的map方便查找
|
|
|
+ mapShelves.put(info.getColNo(), infoList);
|
|
|
} else {
|
|
|
- shelvesFloor.put(info.getColNo(), infoList);
|
|
|
- }
|
|
|
-
|
|
|
- String period = "";
|
|
|
- if (asnSoStrategy.getSoPeriodFlag().equals("optimization") || asnSoStrategy.getSoPeriodFlag().equals("force")) {
|
|
|
- info.getLotattInfoList().get(0).initLotatt();
|
|
|
- period = info.getLotattInfoList().get(0).getAttMap().get(asnSoStrategy.getSoPeriodLotatt());
|
|
|
- }
|
|
|
- LocationSortDTO sortDTO = new LocationSortDTO(info.getColNo(), period);
|
|
|
- list.add(sortDTO);
|
|
|
-
|
|
|
- if (asnSoStrategy.getSoSameLotatt1Flag().equals("optimization")) {
|
|
|
- String lotattValue = redisCache.getCacheObject(asnSoStrategy.getAsnSameLotatt1Value());
|
|
|
- if (!StringUtils.isEmpty(lotattValue)) {
|
|
|
- if (!StringUtils.isEmpty(info.getLotattInfoList().get(0).getAttMap().get(asnSoStrategy.getSoSameLotatt1Value())) && info.getLotattInfoList().get(0).getAttMap().get(asnSoStrategy.getSoSameLotatt1Value()).equals(lotattValue)) {
|
|
|
- sameLotattList.add(sortDTO);
|
|
|
- }
|
|
|
- }
|
|
|
+ mapFloor.put(info.getColNo(), infoList);
|
|
|
}
|
|
|
}
|
|
|
- //=========================================================>
|
|
|
- log.info("检索的库存范围:" + JSON.toJSONString(locationLotattVOList));
|
|
|
+ //===========================库存数据排序完成==============================>
|
|
|
+
|
|
|
+ log.info("检索的库存范围====================================================>");
|
|
|
+ log.info("地堆:" + JSON.toJSONString(mapFloor));
|
|
|
+ log.info("货架:" + JSON.toJSONString(mapShelves));
|
|
|
log.info("列的任务状态:" + JSON.toJSONString(taskingFlag));
|
|
|
- log.info("每列存放的物料分类:" + JSON.toJSONString(skuTagMap));
|
|
|
+ log.info("货架每列存放的物料分类:" + JSON.toJSONString(skuTagMapShelves));
|
|
|
+ log.info("地堆每列存放的物料分类:" + JSON.toJSONString(skuTagMapFloor));
|
|
|
|
|
|
for (OutWarehouseDTO ow : outWarehouseDTOs) {
|
|
|
- //先去已锁定的库存中查询是否有可以扣减的库存
|
|
|
+ //先查询已锁定的库存中查询是否有可以扣减的库存,如果已经扣除了那么久不用继续分配
|
|
|
Double qty = checkOutedInvQty(ow, lockInv);
|
|
|
if (qty >= ow.getQty()) {
|
|
|
continue;
|
|
|
}
|
|
|
//过滤出每列可以用的库位并进行分配
|
|
|
- BaseLocationInfo currentLocation = null;
|
|
|
- BaseLocationLotattListVO currentLocationLotatt = null;
|
|
|
+ BaseLocationInfo currentLocation;
|
|
|
+ boolean isEnd = false;
|
|
|
//地堆
|
|
|
- for (Map.Entry<String, List<BaseLocationLotattListVO>> invList : mapFloor.entrySet()) {
|
|
|
-
|
|
|
+ List<String> colNosFloor = getColNoBySku(skuTagMapFloor, ow.getSku());
|
|
|
+ for (String s : colNosFloor) {
|
|
|
+ if (isEnd) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ List<BaseLocationLotattListVO> bls = mapFloor.get(s);
|
|
|
+ for (BaseLocationLotattListVO v : bls) {
|
|
|
+ if (v.getIsEmpty().equals("N") && v.getStockStatus().equals("00")) {
|
|
|
+ if (redisCache.lockCacheObject(RedisKey.LOCK_LOCATION + v.getId(), v.getId().toString(), token)) {
|
|
|
+ //判断是否有阻挡
|
|
|
+ currentLocation = new BaseLocationInfo();
|
|
|
+ BeanUtils.copyProperties(v, currentLocation);
|
|
|
+ if (checkCanOut(currentLocation)) {
|
|
|
+ result.add(currentLocation);
|
|
|
+ lockInv = addLockInv(lockInv, v.getColNo(), v);
|
|
|
+ Double currentQty = checkOutedInvQty(ow, lockInv);
|
|
|
+ if (currentQty >= ow.getQty()) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ //如果不能出去去除锁定
|
|
|
+ redisCache.deleteObject(RedisKey.LOCK_LOCATION + v.getId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
//货架
|
|
|
- for (Map.Entry<String, List<BaseLocationLotattListVO>> invList : shelvesFloor.entrySet()) {
|
|
|
+ isEnd = false;
|
|
|
+ List<String> colNosShelves = getColNoBySku(skuTagMapShelves, ow.getSku());
|
|
|
+ for (String s : colNosShelves) {
|
|
|
+ if (isEnd) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ List<BaseLocationLotattListVO> bls = mapShelves.get(s);
|
|
|
+ for (BaseLocationLotattListVO v : bls) {
|
|
|
+ if (v.getIsEmpty().equals("N") && v.getStockStatus().equals("00")) {
|
|
|
+ if (redisCache.lockCacheObject(RedisKey.LOCK_LOCATION + v.getId(), v.getId().toString(), token)) {
|
|
|
+ //判断是否有阻挡
|
|
|
+ currentLocation = new BaseLocationInfo();
|
|
|
+ BeanUtils.copyProperties(v, currentLocation);
|
|
|
+ result.add(currentLocation);
|
|
|
+ lockInv = addLockInv(lockInv, v.getColNo(), v);
|
|
|
+ Double currentQty = checkOutedInvQty(ow, lockInv);
|
|
|
+ if (currentQty >= ow.getQty()) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 添加已锁定库存
|
|
|
+ *
|
|
|
+ * @param lockInv 锁定库存列
|
|
|
+ * @param colNo 列
|
|
|
+ * @param vo 库存对象
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public Map<String, List<BaseLocationLotattListVO>> addLockInv(Map<String, List<BaseLocationLotattListVO>> lockInv, String colNo, BaseLocationLotattListVO vo) {
|
|
|
+ List<BaseLocationLotattListVO> result;
|
|
|
+ if (lockInv.containsKey(colNo)) {
|
|
|
+ result = lockInv.get(colNo);
|
|
|
+ } else {
|
|
|
+ result = new ArrayList<>();
|
|
|
+ }
|
|
|
+ result.add(vo);
|
|
|
+ lockInv.put(colNo, result);
|
|
|
+ return lockInv;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检索出物料所属的列号
|
|
|
+ *
|
|
|
+ * @param skuTagMap
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private List<String> getColNoBySku(LinkedHashMap<String, String> skuTagMap, String sku) {
|
|
|
+ List<String> colNos = new ArrayList<>();
|
|
|
+ for (Map.Entry<String, String> skuTag : skuTagMap.entrySet()) {
|
|
|
+ if (!colNos.contains(skuTag.getKey())) {
|
|
|
+ if (skuTag.getValue().indexOf(sku) != -1) {
|
|
|
+ colNos.add(skuTag.getKey());
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return colNos;
|
|
|
+ }
|
|
|
|
|
|
+ /**
|
|
|
+ * 检查需要出库的库存是否满足
|
|
|
+ *
|
|
|
+ * @param ow
|
|
|
+ * @param lockInvList
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Double checkOutedInvQty(OutWarehouseDTO ow, Map<String, List<BaseLocationLotattListVO>> lockInvList) {
|
|
|
+ Double qty = 0d;
|
|
|
+ for (Map.Entry<String, List<BaseLocationLotattListVO>> entry : lockInvList.entrySet()) {
|
|
|
+ List<BaseLocationLotattListVO> list = entry.getValue();
|
|
|
+ for (BaseLocationLotattListVO bv : list) {
|
|
|
+ List<LotattInfo> lotattInfoList = bv.getLotattInfoList();
|
|
|
+ for (LotattInfo info : lotattInfoList) {
|
|
|
+ if (info.getSku().equals(ow.getSku())) {
|
|
|
+ qty += info.getQty();
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
+ return qty;
|
|
|
+ }
|
|
|
|
|
|
- return result;
|
|
|
+ /**
|
|
|
+ * 检查同列库位是否有阻挡
|
|
|
+ *
|
|
|
+ * @param b
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private boolean checkCanOut(BaseLocationInfo b) {
|
|
|
+ if (b.getLocationType().equals("1")) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ //查询同列的排序库位
|
|
|
+ List<BaseLocationInfo> locationInfoList = baseLocationInfoMapper.selectLocationByColNo(b.getColNo());
|
|
|
+ for (BaseLocationInfo bef : locationInfoList) {
|
|
|
+ if (bef.getId().equals(b.getId())) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (bef.getStockStatus().equals("00") && bef.getIsEmpty().equals("Y") && redisCache.checkIsLock(bef.getId().toString()) == false) {
|
|
|
+ return true;
|
|
|
+ } else if (bef.getStockStatus().equals("00") && bef.getIsEmpty().equals("N")) {
|
|
|
+ //判断是否在任务中
|
|
|
+ int count = baseLocationInfoMapper.selectLocationIsTasking(bef.getLocationType(), bef.getId());
|
|
|
+ if (count > 0 && redisCache.checkIsLock(bef.getId().toString())) {
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
}
|
|
|
}
|