Commit 098c4760 zshaohui

odn出库 必须满足数量 才能出库

1 个父辈 b05b1c45
......@@ -23,6 +23,7 @@ import com.neotel.smfcore.core.order.service.manager.ILiteOrderItemManager;
import com.neotel.smfcore.core.order.service.manager.ILiteOrderManager;
import com.neotel.smfcore.core.order.service.po.LiteOrder;
import com.neotel.smfcore.core.order.service.po.LiteOrderItem;
import com.neotel.smfcore.core.order.util.CombinationUtil;
import com.neotel.smfcore.core.storage.bean.InventoryItem;
import com.neotel.smfcore.core.storage.enums.CHECKOUT_TYPE;
import com.neotel.smfcore.core.storage.service.manager.IStoragePosManager;
......@@ -1381,72 +1382,88 @@ public class LiteOrderCache {
for (LiteOrderItem orderItem : cacheOrder.getOrderItems()) {
String partNumber = orderItem.getPn();
int taskNum = 0;
int remainNum = orderItem.getNeedNum() - orderItem.getTotalOutNum();
//1.查找所有符合条件的pn
if (remainNum <= 0) {
continue;
}
Collection<String> excludePosIds = excludeOutPosIds();
//找到hold的
List<String> holdPosIdList = getHoldPosIdList(cacheOrder);
if (holdPosIdList != null && !holdPosIdList.isEmpty()) {
excludePosIds.addAll(holdPosIdList);
}
if (dataLogList != null && !dataLogList.isEmpty()) {
for (DataLog dataLog : dataLogList) {
excludePosIds.add(dataLog.getPosId());
}
}
while (taskNum < remainNum) {
log.info(orderNo + "已分配数量为:"+taskNum+",剩余数量为:"+remainNum);
String pn = orderItem.getPn();
String warehouseCode = orderItem.getWarehouseCode();
Collection<String> excludePosIds = excludeOutPosIds();
if (dataLogList != null && !dataLogList.isEmpty()){
for (DataLog dataLog : dataLogList) {
excludePosIds.add(dataLog.getPosId());
}
}
Criteria c = Criteria.where("barcode.partNumber").is(pn)
.and("id").nin(excludePosIds)
.and("enabled").is(true)
.and("storageId").in(storageIdList)
.and("barcode.warehouseCode").is(warehouseCode);
//1.先从执行的料箱中出库
StoragePos pos = null;
if (storagePosList != null && !storagePosList.isEmpty()) {
for (StoragePos storagePos : storagePosList) {
if (excludePosIds.contains(storagePos.getId())) {
continue;
}
if (partNumber.equals(storagePos.getBarcode().getPartNumber())) {
pos = storagePos;
break;
}
}
}
List<StoragePos> posList = storagePosManager.findByQuery(new Query(c));
if (posList == null || posList.isEmpty()) {
finishedOrderTasks(cacheOrder);
throw new ValidateException("", orderItem.getPn() + "库存不足,odn:" + cacheOrder.getOrderNo() + "无法进行出库");
}
if (pos == null) {
pos = storagePosManager.findPartNumberInStorages(storageIdList, partNumber, excludePosIds, checkoutType, orderItem.getBrand(),orderItem.getWarehouseCode());
}
if (pos == null) {
break;
} else {
Barcode barcode = pos.getBarcode();
log.info(barcode.getBarcode() + "需要生成出库任务,工单号为:" + orderNo+",数量为:"+barcode.getQty());
taskNum = taskNum + barcode.getQty();
taskReelCount = taskReelCount + 1;
DataLog task = newTask(pos);
task.setSourceId(cacheOrder.getId());
task.setSourceName(cacheOrder.getOrderNo());
task.setSubSourceId(orderItem.getId());
task.setSubSourceInfo(orderItem.getFeederInfo());
task.setType(OP.CHECKOUT);
task.setStatus(OP_STATUS.WAIT.name());
task.setLoc(TaskLocUtil.OUT);
if (StringUtils.isNotEmpty(barcode.getCartonId())){
task.setCartonId(barcode.getCartonId());
}
task.setOdn(true);
dataLogList.add(task);
}
//开始寻找组合数量为needOutNum的库存
List<Integer> amountList = new ArrayList<>();
for (StoragePos storagePos : posList) {
Barcode barcode = storagePos.getBarcode();
amountList.add(barcode.getQty());
}
//如果数量不满足,则提示出来
if (taskNum < remainNum){
//寻找到组合
List<List<Integer>> combinations = CombinationUtil.findCombinationsWithoutDuplicates(amountList, remainNum);
Collections.sort(combinations, Comparator.comparingInt(List::size));
if (combinations.isEmpty()) {
finishedOrderTasks(cacheOrder);
throw new ValidateException("", orderItem.getPn()+"库存不足,odn:"+cacheOrder.getOrderNo()+"无法进行出库");
throw new ValidateException("", orderItem.getPn() + "需要出库的数量为:" + remainNum + ",未找到符合条件的组合");
}
}
for (DataLog dataLog : dataLogList) {
taskService.addTaskToExecute(dataLog);
//开始出库
List<Integer> needOutNumList = combinations.get(0);
while (needOutNumList.size() > 0) {
Integer qty = needOutNumList.get(0);
for (StoragePos pos : posList) {
if (excludePosIds.contains(pos.getId())) {
continue;
}
Barcode barcode = pos.getBarcode();
if (barcode.getQty() == qty) {
log.info(barcode.getBarcode() + "需要生成出库任务,工单号为:" + orderNo + ",数量为:" + barcode.getQty());
taskReelCount = taskReelCount + 1;
DataLog task = newTask(pos);
task.setSourceId(cacheOrder.getId());
task.setSourceName(cacheOrder.getOrderNo());
task.setSubSourceId(orderItem.getId());
task.setSubSourceInfo(orderItem.getFeederInfo());
task.setType(OP.CHECKOUT);
task.setStatus(OP_STATUS.WAIT.name());
task.setLoc(TaskLocUtil.OUT);
if (StringUtils.isNotEmpty(barcode.getCartonId())) {
task.setCartonId(barcode.getCartonId());
}
task.setOdn(true);
dataLogList.add(task);
excludePosIds.add(pos.getId());
break;
}
}
needOutNumList.remove(0);
}
}
if (taskReelCount <= 0) {
......@@ -1455,6 +1472,9 @@ public class LiteOrderCache {
throw new ValidateException("smfcore.order.out.noTask", "工单无可执行的任务");
}
for (DataLog dataLog : dataLogList) {
taskService.addTaskToExecute(dataLog);
}
cacheOrder.setTaskReelCount(taskReelCount);
......@@ -1463,4 +1483,28 @@ public class LiteOrderCache {
log.info("生成工单" + orderNo + "任务结束,数量为:" + taskReelCount);
}
private List<String> getHoldPosIdList(LiteOrder cacheOrder) {
//如果是hold的,判断有没有符合的条件
List<String> holdPosIdList = new ArrayList<>();
for (LiteOrderItem orderItem : cacheOrder.getOrderItems()) {
List<FetchHoldInfoResult> resultList = LuxsanApi.fetchHoldInfo(new FetchHoldInfoRequest(CommonUtil.plantCode, orderItem.getSrcWarehouse(), orderItem.getPn()));
if (resultList != null && !resultList.isEmpty()) {
List<String> palletIdList = resultList.stream().map(FetchHoldInfoResult::getPALLET_ID).collect(Collectors.toList());
List<Criteria> orCriterialList = Lists.newArrayList();
orCriterialList.add(Criteria.where("barcode.barcode").in(palletIdList));
orCriterialList.add(Criteria.where("barcode.palletId").in(palletIdList));
Criteria c = new Criteria().orOperator(orCriterialList);
List<StoragePos> posList = storagePosManager.findByQuery(new Query(c));
if (posList != null && !posList.isEmpty()) {
for (StoragePos pos : posList) {
holdPosIdList.add(pos.getId());
}
}
}
}
return holdPosIdList;
}
}
package com.neotel.smfcore.core.order.util;
import java.util.ArrayList;
import java.util.List;
public class CombinationUtil {
private static void backtrack(List<Integer> numbers, int targetSum, int start, List<Integer> current, List<List<Integer>> combinations, boolean used[]) {
if (targetSum == 0) {
combinations.add(new ArrayList<>(current));
return;
}
if (targetSum < 0 || start >= numbers.size()) {
return;
}
for (int i = start; i < numbers.size(); i++) {
// 如果不允许重复使用数字,并且当前数字已经被使用过,则跳过
if (used != null && used[i]) {
continue;
}
// 选择当前数字
current.add(numbers.get(i));
// 如果不允许重复使用数字,则标记当前数字为已使用
if (used != null) {
used[i] = true;
}
// 递归调用,继续查找剩余的数字
backtrack(numbers, targetSum - numbers.get(i), i + 1, current, combinations, used);
// 回溯,移除当前选择的数字
current.remove(current.size() - 1);
// 如果不允许重复使用数字,则取消标记
if (used != null) {
used[i] = false;
}
}
}
// 如果不允许重复使用数字,可以使用以下版本的findCombinations方法
public static List<List<Integer>> findCombinationsWithoutDuplicates(List<Integer> numbers, int targetSum) {
boolean[] used = new boolean[numbers.size()];
return findCombinations(numbers, targetSum, used);
}
// 带有used数组的findCombinations方法
private static List<List<Integer>> findCombinations(List<Integer> numbers, int targetSum, boolean[] used) {
List<List<Integer>> combinations = new ArrayList<>();
backtrack(numbers, targetSum, 0, new ArrayList<>(), combinations, used);
return combinations;
}
}
......@@ -726,7 +726,8 @@ public class LuxsanApi extends DefaultSmfApiListener {
LuxsanApiResult apiResult = JSONObject.parseObject(resultStr, LuxsanApiResult.class);
if (LuxsanApiEnum.ERROR.equals(apiResult.getMSGTY())) {
throw new ValidateException("smfcore.api.error", "接口请求失败[{0}]", new String[]{apiResult.getMSGTX()});
//throw new ValidateException("smfcore.api.error", "接口请求失败[{0}]", new String[]{apiResult.getMSGTX()});
return new ArrayList<>();
}
List<FetchHoldInfoResult> resultList = JSONObject.parseArray(apiResult.getDATA(), FetchHoldInfoResult.class);
......@@ -736,9 +737,10 @@ public class LuxsanApi extends DefaultSmfApiListener {
} catch (ApiException e) {
log.error("fetchHoldInfo请求失败:" + e.getMessage());
throw new ValidateException("smfcore.api.error", "接口请求失败[{0}]", new String[]{e.getMessage()});
//throw new ValidateException("smfcore.api.error", "接口请求失败[{0}]", new String[]{e.getMessage()});
return new ArrayList<>();
}
throw new ValidateException("smfcore.api.error", "接口请求失败[{0}]", new String[]{"未找到对应的获取不可用(HOLD)库存信息"});
return new ArrayList<>();
}
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!