Commit 9b58acb3 zshaohui

增加出库数量计算

1 个父辈 64843be9
...@@ -255,6 +255,8 @@ public class DataInitManager { ...@@ -255,6 +255,8 @@ public class DataInitManager {
addNewFunctionMenu(10, wip, "restoreRebox", "ODN还原补箱", "restoreRebox", "SemiFinishProducts/restoreRebox/index", "restoreRebox", functionMenuMap); addNewFunctionMenu(10, wip, "restoreRebox", "ODN还原补箱", "restoreRebox", "SemiFinishProducts/restoreRebox/index", "restoreRebox", functionMenuMap);
addNewFunctionMenu(11, wip, "manualTransfer", "手动储位转移", "manualTransfer", "manualTransfer/index", "manualTransfer", functionMenuMap); addNewFunctionMenu(11, wip, "manualTransfer", "手动储位转移", "manualTransfer", "manualTransfer/index", "manualTransfer", functionMenuMap);
addNewFunctionMenu(12, wip, "pickBox", "出货计算", "pickBox", "SemiFinishProducts/pickBox/index", "", functionMenuMap);
//MSD管理:MSD库存.MSD追溯性.MSD设置 //MSD管理:MSD库存.MSD追溯性.MSD设置
Menu msd = Menu.CreatePMenu("MSD管理", 2, "msd", 2, "MSD",null); Menu msd = Menu.CreatePMenu("MSD管理", 2, "msd", 2, "MSD",null);
......
...@@ -100,4 +100,6 @@ public interface IStoragePosManager extends IBaseManager<StoragePos> { ...@@ -100,4 +100,6 @@ public interface IStoragePosManager extends IBaseManager<StoragePos> {
void batchUpdatePosEnabled(List<String> idList, boolean enabled); void batchUpdatePosEnabled(List<String> idList, boolean enabled);
List<StoragePos> findPosByIdList(List<String> idList); List<StoragePos> findPosByIdList(List<String> idList);
List<StoragePos> findOdnCalculatePos(String pn, String warehouseCode,Collection<String> excludeOutPosIds);
} }
...@@ -19,6 +19,10 @@ import com.neotel.smfcore.core.storage.service.dao.IStoragePosDao; ...@@ -19,6 +19,10 @@ import com.neotel.smfcore.core.storage.service.dao.IStoragePosDao;
import com.neotel.smfcore.core.storage.service.manager.IStoragePosManager; import com.neotel.smfcore.core.storage.service.manager.IStoragePosManager;
import com.neotel.smfcore.core.storage.service.po.Storage; import com.neotel.smfcore.core.storage.service.po.Storage;
import com.neotel.smfcore.core.storage.service.po.StoragePos; import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.custom.luxsan.api.LuxsanApi;
import com.neotel.smfcore.custom.luxsan.api.bean.request.FetchHoldInfoRequest;
import com.neotel.smfcore.custom.luxsan.api.bean.result.FetchHoldInfoResult;
import com.neotel.smfcore.custom.luxsan.factory_c.common.util.CommonUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -907,4 +911,29 @@ public class StoragePosManagerImpl implements IStoragePosManager { ...@@ -907,4 +911,29 @@ public class StoragePosManagerImpl implements IStoragePosManager {
Query query = new Query(Criteria.where("id").in(idList)); Query query = new Query(Criteria.where("id").in(idList));
return storagePosDao.findByQuery(query); return storagePosDao.findByQuery(query);
} }
@Override
public List<StoragePos> findOdnCalculatePos(String pn, String warehouseCode,Collection<String> excludeOutPosIds) {
//排除hold的料箱
List<String> holdPalletIdList = new ArrayList<>();
List<FetchHoldInfoResult> holdList = LuxsanApi.fetchHoldInfo(new FetchHoldInfoRequest(CommonUtil.plantCode, warehouseCode, pn));
//List<FetchHoldInfoResult> holdList = new ArrayList<>();
if (holdList != null && !holdList.isEmpty()){
for (FetchHoldInfoResult hold : holdList) {
holdPalletIdList.add(hold.getPALLET_ID());
}
}
Criteria c = Criteria.where("barcode.partNumber").is(pn).and("enabled").is(true).and("barcode.warehouseCode").is(warehouseCode);;
if (excludeOutPosIds != null && !excludeOutPosIds.isEmpty()){
c.and("id").nin(excludeOutPosIds);
}
if (holdPalletIdList != null && !holdPalletIdList.isEmpty()){
c.and("barcode.palletId").nin(holdPalletIdList);
}
Query q = new Query(c);
q.fields().include("barcode.amount","barcode.partNumber","barcode.warehouseCode","posName","barcode.barcode","barcode.palletId");
return storagePosDao.findByQuery(q);
}
} }
package com.neotel.smfcore.custom.luxsan.factory_c.wipstor.controller;
import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.common.utils.StringUtils;
import com.neotel.smfcore.core.order.LiteOrderCache;
import com.neotel.smfcore.core.storage.service.manager.IStoragePosManager;
import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.custom.luxsan.api.LuxsanApi;
import com.neotel.smfcore.custom.luxsan.api.bean.request.FetchHoldInfoRequest;
import com.neotel.smfcore.custom.luxsan.api.bean.result.FetchHoldInfoResult;
import com.neotel.smfcore.custom.luxsan.factory_c.common.util.CommonUtil;
import com.neotel.smfcore.custom.luxsan.factory_c.wipstor.util.CalculateUtil;
import com.neotel.smfcore.security.annotation.AnonymousAccess;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
@Slf4j
@RestController
@RequestMapping("/odnCalculateQty")
public class OdnCalculateQty {
@Autowired
private LiteOrderCache liteOrderCache;
@Autowired
private IStoragePosManager storagePosManager;
private static boolean calculate = false;
@ApiOperation("计算数量")
@RequestMapping("/calculate")
@AnonymousAccess
public ResultBean calculate(@RequestBody Map<String, String> paramMap) {
if (calculate) {
return ResultBean.newErrorResult(-1, "", "有正在计算的任务,等结束后再重新计算");
}
calculate = true;
String pn = paramMap.get("pn");
String targetNumStr = paramMap.get("targetNum");
String warehouseCode = paramMap.get("warehouseCode");
log.info("收到odn出货计算数量,料号为:" + pn + ",目标数量为:" + targetNumStr + "库别为:" + warehouseCode);
//检验参数
if (StringUtils.isEmpty(pn) || StringUtils.isEmpty(warehouseCode) || StringUtils.isEmpty(targetNumStr)) {
calculate = false;
return ResultBean.newErrorResult(-1, "", "料号,库别,目标数量信息不能为空");
}
int targetNum = 0;
try {
targetNum = Integer.parseInt(targetNumStr);
} catch (NumberFormatException e) {
log.info("解析数量:" + targetNumStr + "报错:", e);
calculate = false;
return ResultBean.newErrorResult(-1, "", targetNumStr + "格式不正确");
}
//查找所有符合条件的库位
Collection<String> excludeOutPosIds = liteOrderCache.excludeOutPosIds();
List<StoragePos> storagePosList = storagePosManager.findOdnCalculatePos(pn,warehouseCode,excludeOutPosIds);
if (storagePosList == null || storagePosList.isEmpty()){
calculate = false;
return ResultBean.newErrorResult(-1,"","料号:" + pn +"库别:"+warehouseCode+"库存中未找到料箱");
}
List<StoragePos> combinationsPosList = CalculateUtil.findCombinationsByPos(storagePosList, targetNum);
if (combinationsPosList == null || combinationsPosList.isEmpty()){
calculate = false;
return ResultBean.newErrorResult(-1,"","料号:" + pn +"库别:"+warehouseCode+"库存中未找到对应的组合数据");
}
List<Map<String,Object>> resultList = new ArrayList<>();
for (StoragePos pos : combinationsPosList) {
Map<String,Object> resultMap = new HashMap<>();
resultMap.put("qty",pos.getBarcode().getAmount());
resultMap.put("barcode",pos.getBarcode().getBarcode());
resultMap.put("pos",pos.getPosName());
resultMap.put("warehouseCode",pos.getBarcode().getWarehouseCode());
resultMap.put("pn",pos.getBarcode().getPartNumber());
resultMap.put("palletId",pos.getBarcode().getPalletId());
resultList.add(resultMap);
}
calculate = false;
return ResultBean.newOkResult(resultList);
}
}
package com.neotel.smfcore.custom.luxsan.factory_c.wipstor.util;
import com.neotel.smfcore.core.storage.service.po.StoragePos;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Component
public class CalculateUtil {
public static List<StoragePos> findCombinationsByPos(List<StoragePos> storagePosList, int target) {
// 使用HashMap来存储和值及其对应的组合次数
Map<Integer, List<StoragePos>> sumCounts = new HashMap<>();
sumCounts.put(0, new ArrayList<>()); // 初始化,和为0的组合有1种(即不选任何数)
long now = System.currentTimeMillis();
for (StoragePos pos : storagePosList) {
Map<Integer, List<StoragePos>> temp = new HashMap<>(sumCounts); // 复制当前的和值映射,避免在迭代过程中修改
for (Map.Entry<Integer, List<StoragePos>> entry : temp.entrySet()) {
if (System.currentTimeMillis() - now >= 1000 * 60) {
log.info(target+"计算超过一分钟,退出");
return new ArrayList<>();
}
int amount = pos.getBarcode().getAmount();
int sum = entry.getKey();
Integer newSum = sum + amount;
if (newSum <= target) { // 只考虑不超过target的和
List<StoragePos> oldValue = new ArrayList<>(entry.getValue());
if (!sumCounts.containsKey(newSum)) {
oldValue.add(pos);
sumCounts.put(newSum, oldValue);
if (newSum == target) {
log.info("找到和为 " + target + " 的组合为 " + oldValue + " 共:" + oldValue.size());
return oldValue;
}
}
}
}
}
return new ArrayList<>();
}
}
...@@ -36,42 +36,4 @@ public class ManualWorkUtil { ...@@ -36,42 +36,4 @@ public class ManualWorkUtil {
} }
return cacheMap.containsKey(boxStr); return cacheMap.containsKey(boxStr);
} }
public static void findCombinations(List<Integer> numbers, int target) {
// 使用HashMap来存储和值及其对应的组合次数
Map<Integer, List<Integer>> sumCounts = new HashMap<>();
sumCounts.put(0, new ArrayList<>()); // 初始化,和为0的组合有1种(即不选任何数)
for (int num : numbers) {
Map<Integer, List<Integer>> temp = new HashMap<>(sumCounts); // 复制当前的和值映射,避免在迭代过程中修改
for (Map.Entry<Integer, List<Integer>> entry : temp.entrySet()) {
int sum = entry.getKey();
Integer newSum = sum + num;
if (newSum <= target) { // 只考虑不超过target的和
List<Integer> oldValue = new ArrayList<>(entry.getValue());
if(!sumCounts.containsKey(newSum)){
oldValue.add(num);
sumCounts.put(newSum,oldValue);
if(newSum == target){
System.out.println("找到和为 " + target + " 的组合为 " + oldValue +" 共:" + oldValue.size());
return;
}
}
}
}
}
System.out.println(sumCounts.size());
}
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>();
for (int i = 0; i < 100; i++) {
numbers.add(1);
}
int target = 101;
findCombinations(numbers, target);
}
} }
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!