Commit c6b20dfa LN

工单调料规则修改。

1 个父辈 ad402fe0
......@@ -230,7 +230,7 @@ public class LiteOrderCache implements ITaskListener {
}
}
if (closed) {
order.setClosed(closed);
order.finishedTasks();
//工单出库完成,调用7.11订单发料完成通知接口
boolean result = HikApi.orderEndApi(order.getOperateUser(), order.getJobNo());
}
......@@ -239,9 +239,11 @@ public class LiteOrderCache implements ITaskListener {
log.error("工单[" + orderNo + "]的任务[" + task.getBarcode() + "]完成时,状态为:" + task.getStatus());
}
if (order.getFinishedReelCount() >= order.getTaskReelCount()) {
log.info("工单[" + orderNo + "]的出库任务已完成,共出库:" + order.getFinishedReelCount() + " 盘");
order.finishedTasks();
if(!order.isClosed()){
if (order.getFinishedReelCount() >= order.getTaskReelCount()) {
log.info("工单[" + orderNo + "]的出库任务已完成,共出库:" + order.getFinishedReelCount() + " 盘");
order.finishedTasks();
}
}
liteOrderManager.save(order);
liteOrderMap.put(orderNo, order);
......@@ -442,8 +444,6 @@ public class LiteOrderCache implements ITaskListener {
boolean needJieliao =false;
List<StoragePos> itemPosList = new ArrayList<>();
List<String> itemPosNameList = new ArrayList<>();
//查找PN的所有库存,PN=pn,未锁定,qty 从大到小,入库时间正序
List<StoragePos> posList = storagePosManager.findOrderItemInStorage(availableStorageIds, pn, taskService.excludePosIds());
......@@ -493,39 +493,41 @@ public class LiteOrderCache implements ITaskListener {
}
}
List<StoragePos> itemPosList = new ArrayList<>();
List<String> itemPosNameList = new ArrayList<>();
//此PN未完成
int targetNum = needNum;
StoragePos tempPos = null;
for (StoragePos pos :
posList) {
//已经在出库列表
if (itemPosNameList.contains(pos.getPosName())) {
continue;
for (int i=0;i<posList.size();i++
) {
StoragePos tempPos = null;
List<StoragePos> forPosList=new ArrayList<>();
for (StoragePos pos :
posList) {
if(!needOutPosMap.containsKey(pos.getPosName())){
forPosList.add(pos);
}
}
if (isGuizhong || needJieliao) {
//一盘是否满足
if (pos.getBarcode().getAmount() > targetNum) {
tempPos = pos;
} else if (pos.getBarcode().getAmount() == targetNum) {
//一盘刚好满足
targetNum = 0;
itemPosList.add(pos);
itemPosNameList.add(pos.getPosName());
break;
} else {
//循环剩余的库位,查找
int forIndex=-1;
for (StoragePos pos :
forPosList) {
forIndex++;
boolean isLast=(forIndex==(forPosList.size()-1));
//已经在出库列表
if (itemPosNameList.contains(pos.getPosName())) {
continue;
}
//数量不满足,如果暂存有料,使用暂存物料,一盘料满足
if (tempPos != null) {
itemPosList.add(tempPos);
itemPosNameList.add(tempPos.getPosName());
targetNum -= tempPos.getBarcode().getAmount();
//截料的数量
if (targetNum < 0) {
jieliaoPosMap.put(tempPos.getPosName(), targetNum);
}
} else {
//截料料规则
if (isGuizhong || needJieliao) {
if (pos.getBarcode().getAmount() >= targetNum) {
//一盘刚好满足
targetNum = 0;
itemPosList.add(pos);
itemPosNameList.add(pos.getPosName());
break;
} else if (isLast) {
//一盘料不足,直接加入
itemPosList.add(pos);
itemPosNameList.add(pos.getPosName());
......@@ -533,77 +535,52 @@ public class LiteOrderCache implements ITaskListener {
if (targetNum < 0) {
jieliaoPosMap.put(tempPos.getPosName(), targetNum);
}
break;
}
}
} else if (wholeReelCount > 0) {
boolean isWholeReel = pos.getBarcode().getAmount() >= component.getAmount();
if (needWholeReelCount > 0) {
//判断数量,先出整盘料
if (pos.getBarcode().getAmount() >= targetNum) {
if (isWholeReel) {
needWholeReelCount--;
} else if (wholeReelCount > 0) {
boolean isWholeReel = pos.getBarcode().getAmount() >= component.getAmount();
if (needWholeReelCount > 0) {
//判断数量,先出整盘料
if (pos.getBarcode().getAmount() >= targetNum) {
if (isWholeReel) {
needWholeReelCount--;
}
itemPosList.add(pos);
itemPosNameList.add(pos.getPosName());
targetNum -= pos.getBarcode().getAmount();
}
} else {
//整盘已出完,按照数量满足或最后一盘来出
if (!isWholeReel) {
if (pos.getBarcode().getAmount() >= targetNum || isLast) {
itemPosList.add(pos);
itemPosNameList.add(pos.getPosName());
targetNum -= pos.getBarcode().getAmount();
break;
}
}
itemPosList.add(pos);
itemPosNameList.add(pos.getPosName());
targetNum -= pos.getBarcode().getAmount();
}
} else {
//整盘已出完
if (!isWholeReel) {
//不需要截料,也不按照整盘比,按照数量满足或最后一盘来出
if (pos.getBarcode().getAmount() >= targetNum || isLast) {
itemPosList.add(pos);
itemPosNameList.add(pos.getPosName());
targetNum -= pos.getBarcode().getAmount();
break;
}
}
} else {
//不需要截料,也不按照整盘比,直接数量最大的发料
itemPosList.add(pos);
itemPosNameList.add(pos.getPosName());
targetNum -= pos.getBarcode().getAmount();
}
if (targetNum <= 0) {
break;
}
}
if(targetNum>0&&isGuizhong || needJieliao) {
if (tempPos != null) {
if (!itemPosNameList.contains(tempPos.getPosName())) {
itemPosList.add(tempPos);
itemPosNameList.add(tempPos.getPosName());
targetNum -= tempPos.getBarcode().getAmount();
//截料的数量
if (targetNum < 0) {
jieliaoPosMap.put(tempPos.getPosName(), targetNum);
}
}
}
}
//第一轮循环完,判断是否需要再次循环
if (targetNum > 0 && wholeReelCount > 0) {
//如果是散盘料不足,需要再次循环
for (StoragePos pos :
posList) {
//已经在出库列表
if (itemPosNameList.contains(pos.getPosName())) {
continue;
}
itemPosList.add(pos);
itemPosNameList.add(pos.getPosName());
targetNum -= pos.getBarcode().getAmount();
if (targetNum <= 0) {
break;
}
}
if (targetNum <= 0) {
break;
}
}
//判断数量是否满足
if (targetNum > 0) {
int outNum = needNum - targetNum;
......@@ -713,6 +690,372 @@ public class LiteOrderCache implements ITaskListener {
return "";
}
// /**
// * 工单出库
// * @param userName 操作人
// * @param orderNo 工单号
// * @param isShortageOut 是否缺料继续出库
// * @param addOutbound 是否补料出库
// * @return
// */
// public synchronized String checkOutLiteOrder(String userName, String orderNo,boolean isShortageOut,boolean addOutbound) {
// LiteOrder cacheOrder = findOrderByNo(orderNo);
//
// if (cacheOrder == null) {
// return "smfcore.order.out.notFound";
// }
// if(!addOutbound) {
// if (cacheOrder.isExecuting()) {
// log.info("工单[" + orderNo + "]正在执行");
// return "smfcore.order.out.executing";
// }
// }
//
// if(cacheOrder.isClosed()) {
// log.info("工单[" + orderNo + "]已关闭,无法出库");
// return "smfcore.order.hasClose";
// }
//
// updateOrderFromApi(userName,cacheOrder);
// //如果更新完工单已关闭,直接提示
// if(cacheOrder.isClosed()) {
// log.info("工单[" + orderNo + "]已关闭,无法出库");
// return "smfcore.order.hasClose";
// }
//
// ORDER_COLOR nextColor = getNextColor();
// if (nextColor == null) {
// log.info("执行工单[" + orderNo + "] 时, 已达最大可执行工单数");
// return "smfcore.order.out.maxOrder";
// }
//
//// //先查找是否已经锁定过库位,如果已经锁定过,出锁定的库位
//// List<StoragePos> lockPosList = storagePosManager.findLockPos(cacheOrder.getOrderNo());
//// if(lockPosList!=null&& lockPosList.size()>0){
//// return checkOutOrder(cacheOrder).getMsgKey();
//// }
//
//// 出库策略(系统判断逻辑由上到下依次满足):
////①湿敏超期物料所在仓位锁定,不允许备料;
////②贵重物料,不允许超发,按实际需求发料;
////③截料:库存物料的盘数≤设定值,SMF仓位分配
//// 锁定时要标识需要截料并按工单实际需求发料,料
//// 盘相同要先进先出
////④发料盘分配逻辑:
//// 1、散盘与整盘如何分配;
//// 2、订单发料:
//// 2.1、订单数量>200;
//// 2.1.1 散盘:整盘=3:7(比例可调,物料数量)
//// 2.1.2 整盘数量=需求数量*整盘占比/最小包装(四
//// 舍五入)
//// 2.1.3 剩余发散盘,优先取散盘(由多到少发送),
//// 散盘不满足情况下补充整盘
//// 2.2、订单数量≤200;(料盘最少原则)
//// 2.2.1 优先发单盘
//// 2.2.1 单盘不满足,发最大量+补充盘
//// 3 MES传输实际需求+超发需求
//// 3.1 优先满足实际需求+超发需求
//// 3.2 只满足实际需求,不满足超发需求,发出
//// 3.3 不满足实际需求,不发,报缺料
//// 料盘相同要先进先出(物料配置小单标准不需要再
//// 单独写逻辑考虑)
////⑤ 锁定仓位要指定首件所在的仓位,首件取经过①
////②③④筛选锁定料盘中的最大料盘
//
// log.info("开始为工单[" + orderNo + "]挑选出库物料 ");
// boolean shortage=false;
//
// List<String> availableStorageIds = dataCache.getAvailableStorageIds();
//
// Map<String ,List<StoragePos>> needOutPosMap=new HashMap<>();//挑出的需要出库的料列表,key=pn,value=库位
// Map<String,Integer> jieliaoPosMap=new HashMap<>();//需要截料的物料列表,key=PosName,value=此工单使用数量
// //获取此工单出库的所有物料
// for (LiteOrderItem orderItem : cacheOrder.getOrderItems()) {
//
//
// String pn = orderItem.getMaterialNo();
//
// //需求数量
// int needNum = orderItem.getQty() + orderItem.getIncrement()-orderItem.getOutNum();
// if (needNum <= 0) {
// continue;
// }
// ////②贵重物料,不允许超发,按实际需求发料;
// boolean isGuizhong = orderItem.getOverFlag()==1;
// //判断是否需要截料
// boolean needJieliao =false;
//
//
// List<StoragePos> itemPosList = new ArrayList<>();
// List<String> itemPosNameList = new ArrayList<>();
// //查找PN的所有库存,PN=pn,未锁定,qty 从大到小,入库时间正序
// List<StoragePos> posList = storagePosManager.findOrderItemInStorage(availableStorageIds, pn, taskService.excludePosIds());
//
// int storageNum=0;
// int reelNum=posList.size();
// for (StoragePos pos :posList
// ) {
// storageNum+=pos.getBarcode().getAmount();
// }
//
// Component component = componentManager.findOneByPN(pn);
// if(component==null){
// if(isShortageOut) {
// log.info("工单[" + cacheOrder.getOrderNo() + "]缺料出库: 物料号[" + pn + "] ,需求数量[" + orderItem.getWemng() + "], 未找到元器件信息 ");
// shortage = true;
// }else {
// log.info("工单[" + cacheOrder.getOrderNo() + "] 物料号[" + pn + "] ,需求数量[" + orderItem.getWemng() + "], 未找到元器件信息, 缺料 ");
// return materialShortPro(userName, cacheOrder);
// }
// }
// //判断库存 使用最小库存盘数:当前盘数<=最小库存盘数时,需要截料
// if(reelNum<=component.getMinStoreNum()){
// needJieliao=true;
// }
// //判断库存数量是否小于需求数量,小于直接返回缺料
// if(storageNum<orderItem.getQty()){
// if(isShortageOut){
// shortage=true;
// log.info("工单[" + cacheOrder.getOrderNo() + "]缺料出库: 物料号[" + pn + "] ,需求数量[" + orderItem.getWemng() + "], 库存总数量[" + storageNum + "] ");
// }
// else {
// //不满足实际需求,不发,报缺料
// log.info("工单[" + cacheOrder.getOrderNo() + "] 物料号[" + pn + "] ,需求数量[" + orderItem.getWemng() + "], 库存总数量[" + storageNum + "], 不满足实际需求,缺料 ");
// return materialShortPro(userName, cacheOrder);
// }
// }
//
// int wholeReelCount = 0;
// int needWholeReelCount = 0;
// //判断整盘散盘比
// if (orderItem.getWemng() > 200) {
//
// if (component.getWholeReel() >= 0) {
// wholeReelCount = needNum * (component.getWholeReel() / (component.getWholeReel() + component.getHalfReel())) / component.getAmount();
// needWholeReelCount = wholeReelCount;
// log.info("工单[" + cacheOrder.getOrderNo() + "] 物料号[" + pn + "] ,订单数量[" + orderItem.getWemng() + "],计算的整盘数量:" + wholeReelCount);
// }
// }
//
//
// //此PN未完成
// int targetNum = needNum;
// StoragePos tempPos = null;
// for (StoragePos pos :
// posList) {
// //已经在出库列表
// if (itemPosNameList.contains(pos.getPosName())) {
// continue;
// }
//
// if (isGuizhong || needJieliao) {
// //一盘是否满足
// if (pos.getBarcode().getAmount() > targetNum) {
// tempPos = pos;
// } else if (pos.getBarcode().getAmount() == targetNum) {
// //一盘刚好满足
// targetNum = 0;
// itemPosList.add(pos);
// itemPosNameList.add(pos.getPosName());
// break;
// } else {
//
// //数量不满足,如果暂存有料,使用暂存物料,一盘料满足
// if (tempPos != null) {
// itemPosList.add(tempPos);
// itemPosNameList.add(tempPos.getPosName());
// targetNum -= tempPos.getBarcode().getAmount();
// //截料的数量
// if (targetNum < 0) {
// jieliaoPosMap.put(tempPos.getPosName(), targetNum);
// }
// } else {
// //一盘料不足,直接加入
// itemPosList.add(pos);
// itemPosNameList.add(pos.getPosName());
// targetNum -= pos.getBarcode().getAmount();
// if (targetNum < 0) {
// jieliaoPosMap.put(tempPos.getPosName(), targetNum);
// }
// }
//
// }
// } else if (wholeReelCount > 0) {
//
// boolean isWholeReel = pos.getBarcode().getAmount() >= component.getAmount();
// if (needWholeReelCount > 0) {
// //判断数量,先出整盘料
// if (pos.getBarcode().getAmount() >= targetNum) {
// if (isWholeReel) {
// needWholeReelCount--;
// }
// itemPosList.add(pos);
// itemPosNameList.add(pos.getPosName());
// targetNum -= pos.getBarcode().getAmount();
// }
// } else {
// //整盘已出完
// if (!isWholeReel) {
// itemPosList.add(pos);
// itemPosNameList.add(pos.getPosName());
// targetNum -= pos.getBarcode().getAmount();
// }
// }
//
//
// } else {
// //不需要截料,也不按照整盘比,直接数量最大的发料
// itemPosList.add(pos);
// itemPosNameList.add(pos.getPosName());
// targetNum -= pos.getBarcode().getAmount();
// }
//
// if (targetNum <= 0) {
// break;
// }
// }
//
// if(targetNum>0&&isGuizhong || needJieliao) {
// if (tempPos != null) {
// if (!itemPosNameList.contains(tempPos.getPosName())) {
// itemPosList.add(tempPos);
// itemPosNameList.add(tempPos.getPosName());
// targetNum -= tempPos.getBarcode().getAmount();
// //截料的数量
// if (targetNum < 0) {
// jieliaoPosMap.put(tempPos.getPosName(), targetNum);
// }
// }
// }
// }
//
// //第一轮循环完,判断是否需要再次循环
// if (targetNum > 0 && wholeReelCount > 0) {
//
// //如果是散盘料不足,需要再次循环
// for (StoragePos pos :
// posList) {
// //已经在出库列表
// if (itemPosNameList.contains(pos.getPosName())) {
// continue;
// }
// itemPosList.add(pos);
// itemPosNameList.add(pos.getPosName());
// targetNum -= pos.getBarcode().getAmount();
// if (targetNum <= 0) {
// break;
// }
// }
// }
//
// //判断数量是否满足
// if (targetNum > 0) {
// int outNum = needNum - targetNum;
// if (outNum < orderItem.getQty()) {
// if(isShortageOut){
// shortage=true;
// log.info("工单[" + cacheOrder.getOrderNo() + "]缺料出库: 物料号[" + pn + "] ,需求数量[" + orderItem.getWemng() + "], 库存可发数量[" + outNum + "], 不满足实际需求 ");
// }
// else {
// //不满足实际需求,不发,报缺料
// log.info("工单[" + cacheOrder.getOrderNo() + "] 物料号[" + pn + "] ,需求数量[" + orderItem.getWemng() + "], 库存可发数量[" + outNum + "], 不满足实际需求,缺料 ");
// return materialShortPro(userName, cacheOrder);
// }
// }
// }
// //可以出库
// needOutPosMap.put(pn, itemPosList);
// }
//
// log.info("开始执行工单[" + orderNo + "] ");
// if(!addOutbound){
// cacheOrder.setTaskReelCount(0);
// cacheOrder.setTaskFinishedTime(-1);
// cacheOrder.setFinishedReelCount(0);
// }
// cacheOrder.setStatus(LITEORDER_STATUS.EXECUTING);
// //设置出库操作人
// cacheOrder.setOperateUser(userName);
// cacheOrder.setStartDate(new Date());
//
//
// int taskReelCount = 0;
// //物料筛选完成,开始生成出库任务
// for (LiteOrderItem orderItem : cacheOrder.getOrderItems()) {
// int itemReelCount=0;
// int itemOutCount=0;
// List<StoragePos> posList=needOutPosMap.get(orderItem.getMaterialNo());
// for (StoragePos pos :
// posList) {
// DataLog task = taskService.newTask(pos) ;
//
// task.setSourceId(cacheOrder.getId());
// task.setSourceName(cacheOrder.getOrderNo());
// task.setSubSourceId(orderItem.getId());
// task.setSubSourceInfo(orderItem.getStation());
// task.setType(OP.CHECKOUT);
// task.setLightColor(nextColor.getRgb());
// task.setStatus(OP_STATUS.WAIT.name());
// task.setOperator(userName);
//
// task.setOutType(10);//工单出库类型为10
// if(jieliaoPosMap.containsKey(pos.getPosName())){
// //需要截料
// int count=jieliaoPosMap.get(pos.getPosName());
// task.setNeedSplitting(true);
// task.setNeedQty(count);
// task.setLightColor(ORDER_COLOR.PURPLE.getRgb());//截料料 颜色:PURPLE
// }
// else if(itemReelCount==0){
// task.setFirstReel(true);
// task.setLightColor(ORDER_COLOR.CYAN.getRgb());//首盘料 颜色:CYAN
// } else{
// task.setLightColor(ORDER_COLOR.SKYBLUE.getRgb());//普通工单 颜色:SKYBLUE
// }
// if(addOutbound){
// task.setAddOutbound(true);
// task.setLightColor(ORDER_COLOR.PINK.getRgb());//补料出库 颜色:PINK
// }
// taskService.addTaskToExecute(task);
// log.info("工单[" + orderNo + "],任务数[" + taskReelCount + "]仓位【" + pos.getPosName() + "】RI=[" + pos.getBarcode().getBarcode() + "] PN=[" + orderItem.getMaterialNo() + "] Amount[" + pos.getBarcode().getAmount()+
// "] 首盘["+task.isFirstReel()+"] 截料["+task.isNeedSplitting()+"]["+task.getNeedQty()+"] 补料出库["+task.isAddOutbound()+"]");
//
// taskReelCount++;
// itemReelCount++;
// itemOutCount+=pos.getBarcode().getAmount();
//
// }
//// orderItem.setTotalOutReelCount(orderItem.getTotalOutReelCount()+itemReelCount);
//// orderItem.setTotalOutNum(orderItem.getTotalOutNum()+itemOutCount);
// orderItem.setOutReelCount(itemReelCount);
// orderItem.setOutNum(itemOutCount);
// liteOrderItemManager.save(orderItem);
//
// }
//
// cacheOrder.setTaskReelCount(taskReelCount);
// cacheOrder.setTotalFinishedReelCount(0);
// cacheOrder.setTotalTaskReelCount(cacheOrder.getTotalTaskReelCount()+taskReelCount);
// if(addOutbound){
//
// }
// else if(shortage) {
// cacheOrder.setShortageOut(true);
// }
// log.info("工单[" + orderNo + "]任务分配结束,任务数[" + taskReelCount + "]");
// //有需要出库的
// if (taskReelCount <= 0) {
// cacheOrder.finishedTasks();
// }
//
// liteOrderManager.save(cacheOrder);
// liteOrderMap.put(cacheOrder.getOrderNo(), cacheOrder);
// if (taskReelCount <= 0) {
// //return "工单无可执行的任务";
// return "smfcore.order.out.noTask";
// }
// return "";
// }
public String materialShortPro(String userName, LiteOrder liteOrder){
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!