|
@@ -1,11 +1,17 @@
|
|
|
package com.ruoyi.ams.xuankuang.service;
|
|
|
|
|
|
import cn.hutool.core.collection.CollectionUtil;
|
|
|
+import cn.hutool.core.collection.ListUtil;
|
|
|
+import cn.hutool.core.comparator.CompareUtil;
|
|
|
+import cn.hutool.core.util.NumberUtil;
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
|
|
+import com.google.common.collect.Lists;
|
|
|
import com.ruoyi.ams.asn.domain.WmsDocAsnDetails;
|
|
|
import com.ruoyi.ams.asn.service.IWmsDocAsnHeaderService;
|
|
|
import com.ruoyi.ams.config.domain.dto.LotattDTO;
|
|
|
+import com.ruoyi.ams.inv.domain.InvLotLocId;
|
|
|
import com.ruoyi.ams.inv.service.IInvLotLocIdService;
|
|
|
import com.ruoyi.ams.order.domain.WmsDocOrderDetails;
|
|
|
import com.ruoyi.ams.order.domain.WmsDocOrderHeader;
|
|
@@ -15,13 +21,19 @@ import com.ruoyi.ams.order.service.IWmsDocOrderHeaderService;
|
|
|
import com.ruoyi.ams.xuankuang.domain.form.OutTaskForm;
|
|
|
import com.ruoyi.ams.xuankuang.domain.vo.WcsResponseVo;
|
|
|
import com.ruoyi.base.constant.Constant;
|
|
|
+import com.ruoyi.base.domain.BaseLocationInfo;
|
|
|
import com.ruoyi.base.domain.BaseSku;
|
|
|
import com.ruoyi.base.domain.vo.BaseLocationLotattDTO;
|
|
|
import com.ruoyi.base.service.IBaseLocationInfoService;
|
|
|
import com.ruoyi.base.service.IBaseSkuService;
|
|
|
import com.ruoyi.base.utils.IdSequenceUtils;
|
|
|
+import com.ruoyi.common.constant.Constants;
|
|
|
+import com.ruoyi.common.constant.SceneConstants;
|
|
|
import com.ruoyi.common.core.domain.AjaxResult;
|
|
|
+import com.ruoyi.common.core.redis.RedisCache;
|
|
|
import com.ruoyi.common.utils.StringUtils;
|
|
|
+import com.ruoyi.system.service.ISysConfigService;
|
|
|
+import com.sun.xml.internal.ws.api.model.CheckedException;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
@@ -30,9 +42,8 @@ import org.springframework.util.Assert;
|
|
|
import org.springframework.web.bind.annotation.PathVariable;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.Date;
|
|
|
-import java.util.List;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
import static com.ruoyi.ams.xuankuang.service.BaseLocationInfoSubService.OUT_ZONES;
|
|
|
|
|
@@ -69,39 +80,44 @@ public class WmsDocOrderSubService {
|
|
|
private WmsToWcsApiService wmsToWcsApiService;
|
|
|
@Autowired
|
|
|
private IInvLotLocIdService invLotLocIdService;
|
|
|
+ @Autowired
|
|
|
+ private RedisCache redisCache;
|
|
|
+ @Autowired
|
|
|
+ private ISysConfigService sysConfigService;
|
|
|
+
|
|
|
+
|
|
|
|
|
|
|
|
|
@Transactional
|
|
|
public AjaxResult initOrderDetails(@PathVariable("orderNo") String orderNo) {
|
|
|
-
|
|
|
// 根据单号,和创建状态为00
|
|
|
WmsDocOrderDetails wmsDocOrderDetails = new WmsDocOrderDetails();
|
|
|
wmsDocOrderDetails.setOrderNo(orderNo);
|
|
|
wmsDocOrderDetails.setLineStatus(Constant.ORDER_STS.STS00.getValue());
|
|
|
List<WmsDocOrderDetails> list = iWmsDocOrderDetailsService.selectWmsDocOrderDetailsList(wmsDocOrderDetails);
|
|
|
-
|
|
|
+ //IllegalArgumentException NPE RuntimeException;
|
|
|
// 查询出库单头
|
|
|
WmsDocOrderHeader wmsDocOrderHeader = iWmsDocOrderHeaderService.selectWmsDocOrderHeaderByOrderNo(orderNo);
|
|
|
|
|
|
// 匹配库存(先进先出)
|
|
|
- List<BaseLocationLotattDTO> baseLocationLotattVOS = addConfirmAllocationAuto(orderNo);
|
|
|
-
|
|
|
- //筛选库存
|
|
|
- List<BaseLocationLotattDTO> baseLocationLotattVOS1 = filterInv(baseLocationLotattVOS, orderNo);
|
|
|
+ List<BaseLocationLotattDTO> baseLocationLotattList = addConfirmAllocationAuto(orderNo);
|
|
|
|
|
|
+ //筛选库存 由于选矿项目出库单头只对应一个
|
|
|
+ List<BaseLocationLotattDTO> filteredLocationLotattList = selectInventoriesByLocation(baseLocationLotattList, list.get(0));
|
|
|
// 匹配库存(撇开先进先出)
|
|
|
// baseLocationLotattVOS = addConfirmAllocationAuto(orderNo);
|
|
|
|
|
|
//重新筛选库存
|
|
|
// baseLocationLotattVOS1 = filterInv(baseLocationLotattVOS, orderNo);
|
|
|
-
|
|
|
+ //TODO 张馨
|
|
|
+ if(0==0) throw new RuntimeException("test");
|
|
|
|
|
|
boolean con = true;
|
|
|
//机械手应拆袋数
|
|
|
int allocateQuantities = 0;
|
|
|
//出库单对应袋数
|
|
|
int orderNum = list.get(0).getQtyOrderedEach().intValue();
|
|
|
- for (BaseLocationLotattDTO baseLocationLotatt : baseLocationLotattVOS1) {
|
|
|
+ for (BaseLocationLotattDTO baseLocationLotatt : filteredLocationLotattList) {
|
|
|
|
|
|
|
|
|
BaseSku baseSku = iBaseSkuService.selectBaseSkuByCustomerId(Constant.CUSTOMER_ID, list.get(0).getSku());
|
|
@@ -175,9 +191,158 @@ public class WmsDocOrderSubService {
|
|
|
wmsDocOrderHeader.setOrderStatus(Constant.ORDER_STS.STS10.getValue());
|
|
|
iWmsDocOrderHeaderService.updateWmsDocOrderHeader(wmsDocOrderHeader);
|
|
|
}
|
|
|
- return AjaxResult.success("", baseLocationLotattVOS1);
|
|
|
+ return AjaxResult.success("", filteredLocationLotattList);
|
|
|
}
|
|
|
|
|
|
+ public List<BaseLocationLotattDTO> selectInventoriesByLocation(List<BaseLocationLotattDTO> baseLocationLotattList, WmsDocOrderDetails docOrderDetail) {
|
|
|
+ if( CollectionUtil.isEmpty(baseLocationLotattList) || ObjectUtil.isNull(docOrderDetail)) return Lists.newArrayList();
|
|
|
+
|
|
|
+ List<String> locationIdList = baseLocationLotattList.stream()
|
|
|
+ .filter(ObjectUtil::isNotNull).map(item -> NumberUtil.toStr(item.getId())).collect(Collectors.toList());
|
|
|
+
|
|
|
+ List<InvLotLocId> sourceInvLotLocIdList = invLotLocIdService.selectInvLotLocIdList(locationIdList);
|
|
|
+ BigDecimal quantity = docOrderDetail.getQtyOrdered();
|
|
|
+ //从最老的库存开始,计算库存所在的列是否符合要求
|
|
|
+ List<Long> selectedLocationIdList = Lists.newArrayList();
|
|
|
+ for (InvLotLocId invLotLocId : sourceInvLotLocIdList){
|
|
|
+ BaseLocationInfo locationInfo = baseLocationLotattList.stream()
|
|
|
+ .filter(item -> StringUtils.equals(NumberUtil.toStr(item.getId()), invLotLocId.getLocationId())).findFirst().orElse(null);
|
|
|
+ if(ObjectUtil.isNull(locationInfo)) continue;
|
|
|
+
|
|
|
+ String floorAppendRowKey = locationInfo.getShiftNo() + "_" + locationInfo.getRowIndex();
|
|
|
+ Map<String, List<Long>> partitionRowNoListMapper = redisCache.getCacheObject(floorAppendRowKey);
|
|
|
+ Map<String, Object> warehouseAttrMapper = getWarehouseAttrConfig();
|
|
|
+ List<Integer> wayRowNoList = (List<Integer>) warehouseAttrMapper.get(Constants.WAY_ROW_NO_LIST);
|
|
|
+ //获取到这个库位命中的子列在两边还是中间
|
|
|
+ Integer firstWayNo = CollectionUtil.getFirst(wayRowNoList);
|
|
|
+ Integer lastWayNo = CollectionUtil.getLast(wayRowNoList);
|
|
|
+ String partitionRowKey = getPartitionRowKey(firstWayNo, lastWayNo, locationInfo.getRowIndex());
|
|
|
+ List<Long> partitionLocationIdList = partitionRowNoListMapper.get(partitionRowKey);
|
|
|
+ int locationIndex = partitionLocationIdList.indexOf(locationInfo.getId());
|
|
|
+ if(StringUtils.equals(partitionRowKey, Constants.FIRST)) {
|
|
|
+ //TODO 张馨
|
|
|
+ List<Long> firstRightSubList = ListUtil.sub(partitionLocationIdList, locationIndex, partitionLocationIdList.size());
|
|
|
+ List<Long> resultLocationIdList = checkLocationIdList(locationInfo.getId(), sourceInvLotLocIdList, firstRightSubList,
|
|
|
+ baseLocationLotattList, quantity);
|
|
|
+ if(CollectionUtil.isEmpty(resultLocationIdList)) continue;
|
|
|
+ BigDecimal firstRightCount = sourceInvLotLocIdList.stream()
|
|
|
+ .filter(item -> CollectionUtil.contains(resultLocationIdList, Long.parseLong(item.getLocationId()))
|
|
|
+ && ObjectUtil.isNotNull(item.getQty()))
|
|
|
+ .map(item -> item.getQty()).reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+ quantity = NumberUtil.sub(quantity, firstRightCount);
|
|
|
+ baseLocationLotattList = baseLocationLotattList.stream()
|
|
|
+ .filter(item -> !CollectionUtil.contains(resultLocationIdList, item.getId())).collect(Collectors.toList());
|
|
|
+ selectedLocationIdList.addAll(resultLocationIdList);
|
|
|
+ if(CompareUtil.compare(quantity, BigDecimal.ZERO) <= 0) break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(StringUtils.equals(partitionRowKey, Constants.MIDDLE)){
|
|
|
+ //TODO 张馨
|
|
|
+ List<Long> middleLeftSubList = ListUtil.sub(partitionLocationIdList, Constants.START_VALUE, locationIndex + 1);
|
|
|
+ List<Long> middleLeftLocationIdList = checkLocationIdList(locationInfo.getId(), sourceInvLotLocIdList, middleLeftSubList,
|
|
|
+ baseLocationLotattList, quantity);
|
|
|
+ if(CollectionUtil.isEmpty(middleLeftLocationIdList)) continue;
|
|
|
+ BigDecimal middleLeftCount = sourceInvLotLocIdList.stream()
|
|
|
+ .filter(item -> CollectionUtil.contains(middleLeftLocationIdList, Long.parseLong(item.getLocationId()))
|
|
|
+ && ObjectUtil.isNotNull(item.getQty()))
|
|
|
+ .map(item -> item.getQty()).reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+
|
|
|
+ List<Long> middleRightSubList = ListUtil.sub(partitionLocationIdList, locationIndex, partitionLocationIdList.size());
|
|
|
+ List<Long> middleRightLocationIdList = checkLocationIdList(locationInfo.getId(), sourceInvLotLocIdList, middleRightSubList,
|
|
|
+ baseLocationLotattList, quantity);
|
|
|
+ if(CollectionUtil.isEmpty(middleRightLocationIdList)) continue;
|
|
|
+ BigDecimal middleRightCount = sourceInvLotLocIdList.stream()
|
|
|
+ .filter(item -> CollectionUtil.contains(middleRightLocationIdList, Long.parseLong(item.getLocationId()))
|
|
|
+ && ObjectUtil.isNotNull(item.getQty()))
|
|
|
+ .map(item -> item.getQty()).reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+
|
|
|
+ BigDecimal singleRowInvCount = CompareUtil.compare(middleLeftCount, middleRightCount) > 0 ? middleLeftCount : middleRightCount;
|
|
|
+ quantity = NumberUtil.sub(quantity, singleRowInvCount);
|
|
|
+
|
|
|
+ selectedLocationIdList.addAll(CompareUtil.compare(middleLeftCount, middleRightCount) > 0
|
|
|
+ ? middleLeftLocationIdList : middleRightLocationIdList);
|
|
|
+ if(CompareUtil.compare(quantity, BigDecimal.ZERO) <= 0) break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(StringUtils.equals(partitionRowKey, Constants.LAST)) {
|
|
|
+ //TODO 张馨
|
|
|
+ List<Long> lastLeftSubList = ListUtil.sub(partitionLocationIdList, Constants.START_VALUE, locationIndex + 1);
|
|
|
+ List<Long> lastLeftLocationIdList = checkLocationIdList(locationInfo.getId(), sourceInvLotLocIdList, lastLeftSubList,
|
|
|
+ baseLocationLotattList, quantity);
|
|
|
+ if(CollectionUtil.isEmpty(lastLeftLocationIdList)) continue;
|
|
|
+ BigDecimal lastLeftCount = sourceInvLotLocIdList.stream()
|
|
|
+ .filter(item -> CollectionUtil.contains(lastLeftLocationIdList, Long.parseLong(item.getLocationId()))
|
|
|
+ && ObjectUtil.isNotNull(item.getQty()))
|
|
|
+ .map(item -> item.getQty()).reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+
|
|
|
+ quantity = NumberUtil.sub(quantity, lastLeftCount);
|
|
|
+ baseLocationLotattList = baseLocationLotattList.stream()
|
|
|
+ .filter(item -> !CollectionUtil.contains(lastLeftLocationIdList, item.getId())).collect(Collectors.toList());
|
|
|
+ selectedLocationIdList.addAll(lastLeftLocationIdList);
|
|
|
+ if(CompareUtil.compare(quantity, BigDecimal.ZERO) <= 0) break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //TODO 张馨 加过滤 删掉注释
|
|
|
+ System.err.println(JSONObject.toJSONString(selectedLocationIdList));
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private List<Long> checkLocationIdList(Long locationId, List<InvLotLocId> sourceInvLotLocIdList, List<Long> subList,
|
|
|
+ List<BaseLocationLotattDTO> baseLocationLotattList, BigDecimal quantity) {
|
|
|
+ //要过滤掉已经推荐的库存
|
|
|
+ List<Long> locationIdList = baseLocationLotattList.stream().map(item -> item.getId()).collect(Collectors.toList());
|
|
|
+ //证明这一列只有这一个
|
|
|
+ List<Long> filteredList = subList.stream()
|
|
|
+ .filter(item -> !ObjectUtil.equal(item, locationId)
|
|
|
+ && CollectionUtil.contains(locationIdList, item)).collect(Collectors.toList());
|
|
|
+ if(CollectionUtil.isEmpty(filteredList)) return Lists.newArrayList(locationId);
|
|
|
+
|
|
|
+ //查有没有入库任务,存在入库任务,此列不能出库
|
|
|
+ List<BaseLocationInfo> locationInfoList = baseLocationInfoService.selectLocationInfoList(filteredList);
|
|
|
+ List<BaseLocationInfo> asnTaskCheckList = locationInfoList.stream()
|
|
|
+ .filter(item -> StringUtils.equals(item.getStockStatus(), Constant.STOCK_STATUS.STOCK10.getValue())
|
|
|
+ && StringUtils.equals(item.getIsEmpty(), Constants.YES)).collect(Collectors.toList());
|
|
|
+ if(CollectionUtil.isNotEmpty(asnTaskCheckList)) return Lists.newArrayList();
|
|
|
+
|
|
|
+ //证明外侧都是空的
|
|
|
+ List<BaseLocationLotattDTO> locationLotattList = baseLocationLotattList.stream()
|
|
|
+ .filter(item -> CollectionUtil.contains(filteredList, item.getId())
|
|
|
+ && CollectionUtil.contains(locationIdList, item.getId())).collect(Collectors.toList());
|
|
|
+ if(CollectionUtil.isEmpty(locationLotattList)) return Lists.newArrayList(locationId);
|
|
|
+
|
|
|
+ //要过滤掉已经推荐的库存
|
|
|
+ List<InvLotLocId> invLocIdList = sourceInvLotLocIdList.stream()
|
|
|
+ .filter(item -> CollectionUtil.contains(locationIdList, Long.parseLong(item.getLocationId())))
|
|
|
+ .filter(item -> CollectionUtil.contains(subList, Long.parseLong(item.getLocationId()))).collect(Collectors.toList());
|
|
|
+ BigDecimal singleRowInvCount = invLocIdList.stream().filter(item -> ObjectUtil.isNotNull(item.getQty()))
|
|
|
+ .map(item -> item.getQty()).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
|
|
|
+ return CompareUtil.compare(singleRowInvCount, quantity) < 0
|
|
|
+ ? invLocIdList.stream().map(item -> Long.parseLong(item.getLocationId())).collect(Collectors.toList())
|
|
|
+ : Lists.newArrayList();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private String getPartitionRowKey(Integer first, Integer last, String rowIndex) {
|
|
|
+ if(CompareUtil.compare(Integer.parseInt(rowIndex), first) < 0) return Constants.FIRST;
|
|
|
+ if(CompareUtil.compare(Integer.parseInt(rowIndex), first) > 0
|
|
|
+ && CompareUtil.compare(Integer.parseInt(rowIndex), last) < 0) return Constants.MIDDLE;
|
|
|
+ if(CompareUtil.compare(Integer.parseInt(rowIndex), last) > 0) return Constants.LAST;
|
|
|
+ return StringUtils.EMPTY;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取库位的配置
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Map<String, Object> getWarehouseAttrConfig() {
|
|
|
+ String warehouseAttrInfo = sysConfigService.selectConfigByKey(SceneConstants.WAREHOUSE_ATTRIBUTE_SCENE_CONFIG);
|
|
|
+ Assert.isTrue(com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(warehouseAttrInfo), "baseLocationInfoList is empty");
|
|
|
+ return JSONObject.parseObject(warehouseAttrInfo);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* 匹配库存
|
|
|
*
|
|
@@ -197,11 +362,11 @@ public class WmsDocOrderSubService {
|
|
|
//List<String> skuList = detailslist.stream().map(item -> item.getSku()).collect(Collectors.toList());
|
|
|
String sku = detailslist.get(0).getSku();
|
|
|
Assert.isTrue(StringUtils.isNotNull(sku),"存在无物料号的出库单");
|
|
|
- List<BaseLocationLotattDTO> baseLocationLotattVOS
|
|
|
+ List<BaseLocationLotattDTO> baseLocationLotattList
|
|
|
= baseLocationInfoSubService.selectAllocatingInventoryAccordingConditionsOrderBy(OUT_ZONES, new LotattDTO(), sku, null);
|
|
|
- Assert.isTrue(CollectionUtil.isNotEmpty(baseLocationLotattVOS),"仓库中无库存");
|
|
|
+ Assert.isTrue(CollectionUtil.isNotEmpty(baseLocationLotattList),"仓库中无库存");
|
|
|
|
|
|
- return baseLocationLotattVOS;
|
|
|
+ return baseLocationLotattList;
|
|
|
}
|
|
|
|
|
|
/**
|