Commit ef273b8b zshaohui

1.工单统计优化

1 个父辈 0a63b907
package com.neotel.smfcore.core.order;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.google.common.base.Strings;
......@@ -70,7 +71,7 @@ public class LiteOrderCache implements ITaskListener {
*/
public static Map<String, LiteOrder> liteOrderMap = new ConcurrentHashMap<>();
public static Collection<LiteOrder> getAllCachedOrders(){
public static Collection<LiteOrder> getAllCachedOrders() {
return liteOrderMap.values();
}
......@@ -83,7 +84,7 @@ public class LiteOrderCache implements ITaskListener {
for (LiteOrder needResolveOrder : needResolveOrders) {
needResolveOrder.setCurrBoxNum(needResolveOrder.getCurrBoxNum());
needResolveOrder = liteOrderManager.save(needResolveOrder);
log.info("更新工单["+needResolveOrder.getOrderNo()+"]剩余箱子数为: "+needResolveOrder.getRemainBoxNum() + " " + needResolveOrder.getUpdateDate());
log.info("更新工单[" + needResolveOrder.getOrderNo() + "]剩余箱子数为: " + needResolveOrder.getRemainBoxNum() + " " + needResolveOrder.getUpdateDate());
}
log.info("开始加载未完成的需求单");
......@@ -96,57 +97,57 @@ public class LiteOrderCache implements ITaskListener {
// closeOrder(order.getOrderNo());
//
// } else {
addOrderToMap(order);
addOrderToMap(order);
// }
}
log.info("加载到["+unEndOutInfoList.size()+"]个未完成的需求单");
log.info("加载到[" + unEndOutInfoList.size() + "]个未完成的需求单");
}
public void addOrderToMap(LiteOrder order ){
if(order==null|| order.getOrderNo()==null){
public void addOrderToMap(LiteOrder order) {
if (order == null || order.getOrderNo() == null) {
return;
}
if(liteOrderMap.containsKey(order.getOrderNo())){
if (liteOrderMap.containsKey(order.getOrderNo())) {
liteOrderMap.remove(order.getOrderNo());
}
liteOrderMap.put(order.getOrderNo(), order);
updateOrderProgress(order,false);
updateOrderProgress(order, false);
}
public void removeOrder(LiteOrder order){
public void removeOrder(LiteOrder order) {
log.info("从缓存中清除工单:" + order.getOrderNo());
liteOrderMap.remove(order.getOrderNo());
}
public synchronized void updateOrder(LiteOrder order){
public synchronized void updateOrder(LiteOrder order) {
order = liteOrderManager.save(order);
liteOrderMap.put(order.getOrderNo(), order);
updateOrderProgress(order,false);
updateOrderProgress(order, false);
}
public LiteOrder findOrderById(String orderId){
public LiteOrder findOrderById(String orderId) {
for (LiteOrder order : liteOrderMap.values()) {
if(order.getId().equals(orderId)){
if (order.getId().equals(orderId)) {
return order;
}
}
LiteOrder order=liteOrderManager.get(orderId);
if(order!=null){
LiteOrder order = liteOrderManager.get(orderId);
if (order != null) {
addOrderToMap(order);
return order;
}
return null;
}
public LiteOrder findOrderByNo(String orderNo){
public LiteOrder findOrderByNo(String orderNo) {
if(liteOrderMap.containsKey(orderNo)){
if (liteOrderMap.containsKey(orderNo)) {
return liteOrderMap.get(orderNo);
}
else{
LiteOrder order=liteOrderManager.findByOrderNo(orderNo);
if(order!=null){
addOrderToMap(order);;
} else {
LiteOrder order = liteOrderManager.findByOrderNo(orderNo);
if (order != null) {
addOrderToMap(order);
;
return order;
}
}
......@@ -156,19 +157,19 @@ public class LiteOrderCache implements ITaskListener {
private boolean isProcessTimer = false;
public void runTimer(){
if(!isProcessTimer){
public void runTimer() {
if (!isProcessTimer) {
isProcessTimer = true;
try {
boolean startJob = dataCache.getCache(Constants.CACHE_StartJob);
if(startJob){
if (startJob) {
//定时执行工单任务
executeOrderTask();
}
}catch (Exception e){
log.error("需求单定时器执行出错:",e);
}finally {
} catch (Exception e) {
log.error("需求单定时器执行出错:", e);
} finally {
isProcessTimer = false;
}
}
......@@ -180,7 +181,7 @@ public class LiteOrderCache implements ITaskListener {
//只有任务完成或取消时才处理,任务未完成直接返回
if (task.isFinished() || task.isCancel()) {
//判断是否是工单任务
if(task.isOrderTask()){
if (task.isOrderTask()) {
finishedOrderTask(task);
}
}
......@@ -189,20 +190,20 @@ public class LiteOrderCache implements ITaskListener {
}
}
public void executeOrderTask(){
public void executeOrderTask() {
for (LiteOrder order : liteOrderMap.values()) {
if(order.isNew() ){
if (order.isNew()) {
// if(order.isNew()||order.isTaskFinished()){
//判断是否到达时间
Date curr=new Date();
if(order.getStartDate().before(curr)){
//判断是否到达时间
Date curr = new Date();
if (order.getStartDate().before(curr)) {
//开始自动出库
String result= checkOutLiteOrder("system",order.getOrderNo() );
if(!ObjectUtil.isEmpty(result)){
String msg= MessageUtils.getText(result,MessageUtils.getDefaultLocal(),"");
log.info("自动执行工单 【"+order.getOrderNo()+"】 失败:"+msg);
}else{
log.info("自动执行工单 【"+order.getOrderNo()+"】 成功");
String result = checkOutLiteOrder("system", order.getOrderNo());
if (!ObjectUtil.isEmpty(result)) {
String msg = MessageUtils.getText(result, MessageUtils.getDefaultLocal(), "");
log.info("自动执行工单 【" + order.getOrderNo() + "】 失败:" + msg);
} else {
log.info("自动执行工单 【" + order.getOrderNo() + "】 成功");
}
break;
......@@ -221,7 +222,7 @@ public class LiteOrderCache implements ITaskListener {
if (!Strings.isNullOrEmpty(task.getSourceId())) {
LiteOrder order = findOrderById(task.getSourceId());
if (order == null) {
log.info("缓存中未找到"+sourceName+"[" + task.getSourceId() + "],从数据库中重新加载");
log.info("缓存中未找到" + sourceName + "[" + task.getSourceId() + "],从数据库中重新加载");
order = liteOrderManager.get(task.getSourceId());
if (order != null) {
List<LiteOrderItem> items = liteOrderItemManager.findOrderItems(sourceName);
......@@ -268,7 +269,7 @@ public class LiteOrderCache implements ITaskListener {
log.error("工单[" + orderNo + "]的任务[" + task.getBarcode() + "]完成时,状态为:" + task.getStatus());
}
if(!order.isClosed()){
if (!order.isClosed()) {
if (order.getFinishedReelCount() >= order.getTaskReelCount()) {
log.info("工单[" + orderNo + "]的出库任务已完成,共出库:" + order.getFinishedReelCount() + " 盘");
order.finishedTasks();
......@@ -276,7 +277,7 @@ public class LiteOrderCache implements ITaskListener {
}
updateOrder(order);
} else {
log.error("完成任务时,未找到工单"+sourceName+"[" + task.getSourceId() + "]信息");
log.error("完成任务时,未找到工单" + sourceName + "[" + task.getSourceId() + "]信息");
}
}
......@@ -285,7 +286,7 @@ public class LiteOrderCache implements ITaskListener {
public ORDER_COLOR getNextColor() {
//设置颜色
Set<String> currentColors = new HashSet<>();
for (DataLog dataLog :taskService. getQueueTasks()) {
for (DataLog dataLog : taskService.getQueueTasks()) {
currentColors.add(dataLog.getLightColor());
}
ORDER_COLOR nextColor = ORDER_COLOR.nextColor(currentColors);
......@@ -294,10 +295,11 @@ public class LiteOrderCache implements ITaskListener {
/**
* 工单出库前,如果是new工单,需要从API重新获取工单详情
*
* @param liteOrder
* @return
*/
public LiteOrder updateOrderFromApi(String userName,LiteOrder liteOrder) {
public LiteOrder updateOrderFromApi(String userName, LiteOrder liteOrder) {
if ((!liteOrder.isNew()) /**&&(!liteOrder.isShortage())*/) {
return liteOrder;
}
......@@ -313,7 +315,7 @@ public class LiteOrderCache implements ITaskListener {
apiResult = HikApi.updateOrderApi(userName, liteOrder.getOrderNo());
}
if (apiResult != null ) {
if (apiResult != null) {
if (apiResult.getCode() == 33) {
liteOrder.setClosed(true);
......@@ -337,7 +339,7 @@ public class LiteOrderCache implements ITaskListener {
//删除旧的Items
long deleteCount = liteOrderItemManager.deleteByOrderNo(liteOrder.getOrderNo());
log.info("删除工单["+liteOrder.getOrderNo()+"]的旧item,原有"+liteOrder.getOrderItems().size()+"条, 删除"+ deleteCount+"条,新增 " + newItems.size()+"条");
log.info("删除工单[" + liteOrder.getOrderNo() + "]的旧item,原有" + liteOrder.getOrderItems().size() + "条, 删除" + deleteCount + "条,新增 " + newItems.size() + "条");
List<LiteOrderItem> newOrderItems = Lists.newArrayList();
HikOrderInfo outInfo = null;
......@@ -345,11 +347,11 @@ public class LiteOrderCache implements ITaskListener {
LiteOrderItem newItem = apiItem.crateOrderItem(liteOrder.getOrderNo());
// liteOrder = updateOrderItem(liteOrder, newItem);
newOrderItems.add(newItem);
if(outInfo == null){
if (outInfo == null) {
outInfo = apiItem;
}
}
if(outInfo != null){
if (outInfo != null) {
liteOrder.UpdateOutInfo(outInfo);
}
liteOrder.setOrderItems(newOrderItems);
......@@ -362,15 +364,16 @@ public class LiteOrderCache implements ITaskListener {
/**
* 更新工单指定的物料信息
*
* @param order
* @param item
* @return
*/
public LiteOrder updateOrderItem(LiteOrder order,LiteOrderItem item) {
public LiteOrder updateOrderItem(LiteOrder order, LiteOrderItem item) {
List<LiteOrderItem> items = order.getOrderItems();
if(items==null){
items=new ArrayList<>();
if (items == null) {
items = new ArrayList<>();
}
boolean find = false;
......@@ -390,44 +393,46 @@ public class LiteOrderCache implements ITaskListener {
}
return order;
}
@Autowired
private IComponentManager componentManager;
@Autowired
private SafetyInventoryMapper safetyInventoryMapper;
public synchronized String checkOutLiteOrder(String userName, String orderNo) {
return checkOutLiteOrder(userName,orderNo,false,false);
return checkOutLiteOrder(userName, orderNo, false, false);
}
/**
* 工单出库
* @param userName 操作人
* @param orderNo 工单号
*
* @param userName 操作人
* @param orderNo 工单号
* @param isShortageOut 是否缺料继续出库
* @param addOutbound 是否补料出库
* @param addOutbound 是否补料出库
* @return
*/
public synchronized String checkOutLiteOrder(String userName, String orderNo,boolean isShortageOut,boolean addOutbound) {
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 (!addOutbound) {
if (cacheOrder.isExecuting()) {
log.info("工单[" + orderNo + "]正在执行");
return "smfcore.order.out.executing";
}
}
if(cacheOrder.isClosed()) {
if (cacheOrder.isClosed()) {
log.info("工单[" + orderNo + "]已关闭,无法出库");
return "smfcore.order.hasClose";
}
updateOrderFromApi(userName,cacheOrder);
updateOrderFromApi(userName, cacheOrder);
//如果更新完工单已关闭,直接提示
if(cacheOrder.isClosed()) {
if (cacheOrder.isClosed()) {
log.info("工单[" + orderNo + "]已关闭,无法出库");
return "smfcore.order.hasClose";
}
......@@ -466,13 +471,13 @@ public class LiteOrderCache implements ITaskListener {
//②③④筛选锁定料盘中的最大料盘
log.info("开始为工单[" + orderNo + "]挑选出库物料 ");
boolean shortage=false;
boolean shortage = false;
boolean hasReel = false;
List<String> availableStorageIds = dataCache.getAvailableStorageIds();
Map<String ,List<StoragePos>> itemOutPosMap=new HashMap<>();//挑出的需要出库的料列表,key=itemId,value=库位
Map<String,Integer> jieliaoPosMap=new HashMap<>();//需要截料的物料列表,key=PosName,value=此工单使用数量
Map<String, List<StoragePos>> itemOutPosMap = new HashMap<>();//挑出的需要出库的料列表,key=itemId,value=库位
Map<String, Integer> jieliaoPosMap = new HashMap<>();//需要截料的物料列表,key=PosName,value=此工单使用数量
List<String> excludePosIds = Lists.newArrayList();
excludePosIds.addAll(taskService.excludePosIds());
......@@ -498,7 +503,7 @@ public class LiteOrderCache implements ITaskListener {
String pn = orderItem.getMaterialNo();
//需求数量
int needNum = orderItem.getQty() + orderItem.getIncrement()-orderItem.getTotalOutNum();
int needNum = orderItem.getQty() + orderItem.getIncrement() - orderItem.getTotalOutNum();
if (needNum <= 0) {
continue;
}
......@@ -506,29 +511,28 @@ public class LiteOrderCache implements ITaskListener {
//查找PN的所有库存,PN=pn,未锁定,qty 从大到小,批次正序, 入库时间正序
List<StoragePos> posList = new ArrayList<>();
for (StoragePos storagePos : allAvailblePosList) {
if(storagePos.getBarcode().getPartNumber().equals(pn)){
if (storagePos.getBarcode().getPartNumber().equals(pn)) {
posList.add(storagePos);
}
}
log.info("开始挑选["+orderItem.getStation()+"]物料["+pn+"] 可用库存数量:" + posList.size());
log.info("开始挑选[" + orderItem.getStation() + "]物料[" + pn + "] 可用库存数量:" + posList.size());
int targetNum = needNum;
List<StoragePos> outPosList = new ArrayList<>();
if(cacheOrder.isRepleOrder()){
if (cacheOrder.isRepleOrder()) {
//产线补料出库,补料逻辑:单盘最大5000 需求补料1000,按照满足需求最少料盘补料,补料需求6000时首发最大盘第二盘发满足需求最小盘
outPosList = pickRepleReels(outPosNameList, posList, targetNum);
}else{
if (orderItem.getWemng() > 200){
// 2.1、订单数量>200;
} else {
if (orderItem.getWemng() > 200) {
// 2.1、订单数量>200;
// 2.1.1 散盘:整盘=3:7(比例可调,物料数量)
// 2.1.2 整盘数量=需求数量*整盘占比/最小包装(四舍五入)
// 2.1.3 剩余发散盘,优先取散盘(由多到少发送),
// 散盘不满足情况下补充整盘
outPosList =pickBigOrderReels(pn,outPosNameList,posList,targetNum);
outPosList = pickBigOrderReels(pn, outPosNameList, posList, targetNum);
}
else{
} else {
//2.2、订单数量≤200;(料盘最少原则)
// 2.2.1 优先发单盘
// 2.2.1 单盘不满足,发最大量+补充盘
......@@ -547,61 +551,61 @@ public class LiteOrderCache implements ITaskListener {
outNum = outNum + reelAmount;
}
//判断数量是否满足
if(outNum > 0){
if (outNum > 0) {
hasReel = true;
}
int excessNum = outNum - needNum;//超发的数量
if (excessNum < 0) {
shortage=true;
}else if(excessNum > 0){
shortage = true;
} else if (excessNum > 0) {
////②贵重物料,不允许超发,按实际需求发料;
boolean isGuizhong = orderItem.getOverFlag()==1;
boolean isGuizhong = orderItem.getOverFlag() == 1;
//判断是否需要截料
boolean needJieliao =false;
boolean needJieliao = false;
//判断库存 使用最小库存盘数:当前盘数<=最小库存盘数时,需要截料
Component component = null;
for (Component c : componentList) {
if(c.getPartNumber().equals(pn)){
if (c.getPartNumber().equals(pn)) {
component = c;
break;
}
}
if(component != null){
if(component.getMinStoreNum()>0&& posList.size() <=component.getMinStoreNum()){
needJieliao=true;
if (component != null) {
if (component.getMinStoreNum() > 0 && posList.size() <= component.getMinStoreNum()) {
needJieliao = true;
}
log.info("物料["+pn+"]贵重["+isGuizhong+"]可用库存数量:" + posList.size() + " 截料设置数量:" + component.getMinStoreNum() + " 是否需要截料:" + needJieliao);
log.info("物料[" + pn + "]贵重[" + isGuizhong + "]可用库存数量:" + posList.size() + " 截料设置数量:" + component.getMinStoreNum() + " 是否需要截料:" + needJieliao);
}
if(isGuizhong || needJieliao){
if (isGuizhong || needJieliao) {
StoragePos minAmountReelPos = null;
//找大于超出数量的最小的一盘进行截料
for (StoragePos storagePos : outPosList) {
int reelAmount = storagePos.getBarcode().getAmount();
if(reelAmount > excessNum){
if(minAmountReelPos == null || reelAmount <= minAmountReelPos.getBarcode().getAmount()){
if (reelAmount > excessNum) {
if (minAmountReelPos == null || reelAmount <= minAmountReelPos.getBarcode().getAmount()) {
minAmountReelPos = storagePos;
}
}
}
//如果需要截料,找最小的一盘
if(minAmountReelPos != null){
if (minAmountReelPos != null) {
int reelNeedNum = minAmountReelPos.getBarcode().getAmount() - excessNum;
log.info("需要对料盘["+minAmountReelPos.getBarcode().getBarcode()+"]进行截料,需求数量:" + reelNeedNum);
jieliaoPosMap.put(minAmountReelPos.getPosName(),reelNeedNum);
log.info("需要对料盘[" + minAmountReelPos.getBarcode().getBarcode() + "]进行截料,需求数量:" + reelNeedNum);
jieliaoPosMap.put(minAmountReelPos.getPosName(), reelNeedNum);
}
}
}
}
if(!isShortageOut){
if (!isShortageOut) {
//不是强制出库,缺料需要进行提示
if(shortage){
changeOrderToShortage(userName,cacheOrder);
if(hasReel){
if (shortage) {
changeOrderToShortage(userName, cacheOrder);
if (hasReel) {
//有可以出库的料
return "smfcore.order.out.shortReel";
}else{
} else {
//一盘料都没有
return "smfcore.order.out.noReel";
}
......@@ -609,7 +613,7 @@ public class LiteOrderCache implements ITaskListener {
}
log.info("开始执行工单[" + orderNo + "] ");
if(!addOutbound){
if (!addOutbound) {
cacheOrder.setTaskReelCount(0);
cacheOrder.setTaskFinishedTime(-1);
cacheOrder.setFinishedReelCount(0);
......@@ -624,16 +628,16 @@ public class LiteOrderCache implements ITaskListener {
//物料筛选完成,开始生成出库任务
for (LiteOrderItem orderItem : cacheOrder.getOrderItems()) {
int itemReelCount=0;
int itemOutCount=0;
int itemReelCount = 0;
int itemOutCount = 0;
boolean hasFirst = false;//是否已设定首盘
List<StoragePos> posList=itemOutPosMap.get(orderItem.getId());
if(posList == null){
List<StoragePos> posList = itemOutPosMap.get(orderItem.getId());
if (posList == null) {
posList = new ArrayList<>();
}
for (StoragePos pos : posList) {
DataLog task = taskService.newTask(pos) ;
DataLog task = taskService.newTask(pos);
task.setSourceId(cacheOrder.getId());
task.setSubSourceId(orderItem.getId());
......@@ -645,46 +649,45 @@ public class LiteOrderCache implements ITaskListener {
task.setOutType(IN_OUT_TYPE.OUT_ORDER);//工单出库类型为10
task.setSourceName(cacheOrder.getJobNo());
if(cacheOrder.isRepleOrder()){
if (cacheOrder.isRepleOrder()) {
//task.setSourceName(cacheOrder.getReplenishmentNo());
task.setOutType(IN_OUT_TYPE.OUT_REPLE);//补料出库类型为11
}
if(jieliaoPosMap.containsKey(pos.getPosName())){
if (jieliaoPosMap.containsKey(pos.getPosName())) {
//需要截料
int count=jieliaoPosMap.get(pos.getPosName());
int count = jieliaoPosMap.get(pos.getPosName());
task.setNeedSplitting(true);
task.setNeedQty(count);
task.setLightColor(ORDER_COLOR.PINK.getRgb());//截料料 颜色:PINK
}
else if(!hasFirst){
} else if (!hasFirst) {
hasFirst = true;
task.setFirstReel(true);
task.setLightColor(ORDER_COLOR.GREEN.getRgb());//首盘料 颜色:GREEN
} else{
} else {
task.setLightColor(ORDER_COLOR.BLUE.getRgb());//普通工单 颜色:BLUE
}
if(addOutbound){
if (addOutbound) {
task.setInOperate(true);
task.setAddOutbound(true);
task.setLightColor(ORDER_COLOR.ORANGE.getRgb());//缺料出库 颜色:orange
}
if(cacheOrder.isRepleOrder()){
if (cacheOrder.isRepleOrder()) {
//产线补料
task.setLightColor(ORDER_COLOR.CYAN.getRgb());//产线补料出库 颜色:CYAN
}
try{
try {
taskService.addTaskToExecute(task);
}catch (Exception e){
log.info("添加入库列表出错:"+e.getMessage());
} catch (Exception e) {
log.info("添加入库列表出错:" + e.getMessage());
}
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()+"]");
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();
itemOutCount += pos.getBarcode().getAmount();
}
// orderItem.setTotalOutReelCount(orderItem.getTotalOutReelCount()+itemReelCount);
......@@ -698,8 +701,8 @@ public class LiteOrderCache implements ITaskListener {
cacheOrder.setTaskReelCount(taskReelCount);
cacheOrder.setFinishedReelCount(0);
//cacheOrder.setTotalFinishedReelCount(0);
cacheOrder.setTotalTaskReelCount(cacheOrder.getTotalTaskReelCount()+taskReelCount);
if(shortage) {
cacheOrder.setTotalTaskReelCount(cacheOrder.getTotalTaskReelCount() + taskReelCount);
if (shortage) {
cacheOrder.setShortageOut(true);
}
log.info("工单[" + orderNo + "]任务分配结束,任务数[" + taskReelCount + "]");
......@@ -720,10 +723,10 @@ public class LiteOrderCache implements ITaskListener {
/**
* 更改工单状态为缺料状态
*/
public void changeOrderToShortage(String userName, LiteOrder liteOrder){
public void changeOrderToShortage(String userName, LiteOrder liteOrder) {
//挑料时缺料,直接 关闭工单
log.info("工单["+liteOrder.getOrderNo()+"]缺料,更改工单为缺料状态");
log.info("工单[" + liteOrder.getOrderNo() + "]缺料,更改工单为缺料状态");
liteOrder.setOperateUser(userName);
liteOrder.setStatus(LITEORDER_STATUS.SHORTAGE);
liteOrder.setClosed(false);
......@@ -731,25 +734,25 @@ public class LiteOrderCache implements ITaskListener {
}
/**
* 关闭工单
*
* @param orderNo
*/
public String closeOrder(String orderNo) {
LiteOrder liteOrder = findOrderByNo(orderNo);
if(liteOrder==null){
if (liteOrder == null) {
return "smfcore.order.out.notFound";
}
//有任务的工单不能关闭
List<DataLog> allTask=taskService.getAllTasks();
for (DataLog task:allTask
) {
if (OP.CHECKOUT == task.getType()&&(!task.isEnd())) {
List<DataLog> allTask = taskService.getAllTasks();
for (DataLog task : allTask
) {
if (OP.CHECKOUT == task.getType() && (!task.isEnd())) {
//更新工单状态
String taskSourceName = task.getSourceName();
if (!Strings.isNullOrEmpty(taskSourceName) && orderNo.equals(taskSourceName)) {
log.info("关闭工单[" + orderNo + "]失败,有未完成的出库任务:"+task.getPosName());
log.info("关闭工单[" + orderNo + "]失败,有未完成的出库任务:" + task.getPosName());
return "smfcore.order.close.taskNotEnd";
}
}
......@@ -760,7 +763,7 @@ public class LiteOrderCache implements ITaskListener {
log.info("关闭工单[" + orderNo + "]成功");
liteOrder.setClosed(true);
updateOrder(liteOrder);
return "smfcore.order.close.success";
return "smfcore.order.close.success";
}
......@@ -778,24 +781,25 @@ public class LiteOrderCache implements ITaskListener {
/**
* // 2.1、订单数量>200;
* // 2.1.1 散盘:整盘=3:7(比例可调,物料数量)
* // 2.1.2 整盘数量=需求数量*整盘占比/最小包装(四舍五入)
* // 2.1.3 剩余发散盘,优先取散盘(由多到少发送),
* // 散盘不满足情况下补充整盘
* // 2.1.1 散盘:整盘=3:7(比例可调,物料数量)
* // 2.1.2 整盘数量=需求数量*整盘占比/最小包装(四舍五入)
* // 2.1.3 剩余发散盘,优先取散盘(由多到少发送),
* // 散盘不满足情况下补充整盘
*
* @param pn
* @param outPosNameList
* @param posList
* @param targetNum
* @return
*/
private List<StoragePos> pickBigOrderReels(String pn, Set<String> outPosNameList, List<StoragePos> posList, int targetNum){
private List<StoragePos> pickBigOrderReels(String pn, Set<String> outPosNameList, List<StoragePos> posList, int targetNum) {
List<String> excludePosNameList = new ArrayList<>(outPosNameList);
List<StoragePos> outPosList = new ArrayList<>();
int needWholeReelCount = 0;
Component component = componentManager.findOneByPN(pn);
if(component==null){
if (component == null) {
//缺料
return outPosList;
}
......@@ -803,61 +807,61 @@ public class LiteOrderCache implements ITaskListener {
if (component.getWholeReel() >= 0) {
Float wholeReelCount = 1.0f * targetNum * component.getWholeReel() / (component.getWholeReel() + component.getHalfReel()) / component.getAmount();
needWholeReelCount = wholeReelCount.intValue();
if(wholeReelCount - needWholeReelCount > 0.5){
if (wholeReelCount - needWholeReelCount > 0.5) {
needWholeReelCount = needWholeReelCount + 1;
}
}
int oneReelNum = component.getAmount();
//挑选整盘
log.info("开始挑选整盘料,共需要"+needWholeReelCount+"盘");
log.info("开始挑选整盘料,共需要" + needWholeReelCount + "盘");
for (int i = 0; i < needWholeReelCount; i++) {
//先取整盘
StoragePos outPos = pickWholeReel(excludePosNameList,posList,targetNum,oneReelNum);
if(outPos == null){
StoragePos outPos = pickWholeReel(excludePosNameList, posList, targetNum, oneReelNum);
if (outPos == null) {
break;
}else{
log.info("挑选批次["+outPos.getBarcode().getBatch()+"]的整盘物料:" + outPos.getBarcode().getBarcode() + " 数量:" + outPos.getBarcode().getAmount());
} else {
log.info("挑选批次[" + outPos.getBarcode().getBatch() + "]的整盘物料:" + outPos.getBarcode().getBarcode() + " 数量:" + outPos.getBarcode().getAmount());
outPosList.add(outPos);
excludePosNameList.add(outPos.getPosName());
targetNum = targetNum - outPos.getBarcode().getAmount();
}
}
//挑选散盘
log.info("开始挑选散盘料,剩余需求"+targetNum);
log.info("开始挑选散盘料,剩余需求" + targetNum);
//已挑选的散盘数量
int notWholeReelCount = 0;
while (true){
while (true) {
//取散盘
StoragePos outPos = pickNotWholeReel(excludePosNameList,posList,targetNum,oneReelNum);
if(outPos == null){
StoragePos outPos = pickNotWholeReel(excludePosNameList, posList, targetNum, oneReelNum);
if (outPos == null) {
break;
}else{
log.info("挑选到批次["+outPos.getBarcode().getBatch()+"]的散盘物料:" + outPos.getBarcode().getBarcode() + " 数量:" + outPos.getBarcode().getAmount());
} else {
log.info("挑选到批次[" + outPos.getBarcode().getBatch() + "]的散盘物料:" + outPos.getBarcode().getBarcode() + " 数量:" + outPos.getBarcode().getAmount());
outPosList.add(outPos);
excludePosNameList.add(outPos.getPosName());
targetNum = targetNum - outPos.getBarcode().getAmount();
if(targetNum <=0){
if (targetNum <= 0) {
break;
}
notWholeReelCount = notWholeReelCount + 1;
if(notWholeReelCount >= 5){
if (notWholeReelCount >= 5) {
log.info(pn + "的散盘已挑选5盘,跳出");
break;
}
}
}
if(targetNum > 0){
log.info("剩余需求"+targetNum+"开始补充最合适的盘");
while(true){
StoragePos outPos = pickFitWholeReel(excludePosNameList,posList,targetNum);
if(outPos == null){
if (targetNum > 0) {
log.info("剩余需求" + targetNum + "开始补充最合适的盘");
while (true) {
StoragePos outPos = pickFitWholeReel(excludePosNameList, posList, targetNum);
if (outPos == null) {
break;
}else{
log.info("挑选到批次["+outPos.getBarcode().getBatch()+"]的物料:" + outPos.getBarcode().getBarcode() + " 数量:" + outPos.getBarcode().getAmount());
} else {
log.info("挑选到批次[" + outPos.getBarcode().getBatch() + "]的物料:" + outPos.getBarcode().getBarcode() + " 数量:" + outPos.getBarcode().getAmount());
outPosList.add(outPos);
excludePosNameList.add(outPos.getPosName());
targetNum = targetNum - outPos.getBarcode().getAmount();
if(targetNum <=0){
if (targetNum <= 0) {
break;
}
}
......@@ -868,98 +872,98 @@ public class LiteOrderCache implements ITaskListener {
/**
* 按照满足需求最少料盘补料,最大盘第二盘发满足需求最小盘
*
* @param outPosNameList
* @param posList
* @param targetNum
* @return
*/
private List<StoragePos> pickRepleReels(Set<String> outPosNameList, List<StoragePos> posList, int targetNum){
private List<StoragePos> pickRepleReels(Set<String> outPosNameList, List<StoragePos> posList, int targetNum) {
List<String> excludePosNameList = new ArrayList<>(outPosNameList);
List<StoragePos> itemPickPosList = new ArrayList<>();
boolean pickMaxQtyReel = false;
do {
//取满足的
StoragePos outPos = pickOneReel(true, excludePosNameList,posList,targetNum, pickMaxQtyReel, -1);
if(outPos == null){
StoragePos outPos = pickOneReel(true, excludePosNameList, posList, targetNum, pickMaxQtyReel, -1);
if (outPos == null) {
break;
}else{
log.info("挑选到批次["+outPos.getBarcode().getBatch()+"]物料:" + outPos.getBarcode().getBarcode() + " 数量:" + outPos.getBarcode().getAmount());
} else {
log.info("挑选到批次[" + outPos.getBarcode().getBatch() + "]物料:" + outPos.getBarcode().getBarcode() + " 数量:" + outPos.getBarcode().getAmount());
itemPickPosList.add(outPos);
excludePosNameList.add(outPos.getPosName());
targetNum = targetNum - outPos.getBarcode().getAmount();
if(targetNum <=0){
if (targetNum <= 0) {
break;
}
}
} while(true);
} while (true);
return itemPickPosList;
}
/**
* 取整盘
*/
private StoragePos pickWholeReel(List<String> excluedPosNameList, List<StoragePos> posList, int targetNum, int oneReelNum){
StoragePos outPos = pickOneReel(true,excluedPosNameList,posList,targetNum,true,oneReelNum);
private StoragePos pickWholeReel(List<String> excluedPosNameList, List<StoragePos> posList, int targetNum, int oneReelNum) {
StoragePos outPos = pickOneReel(true, excluedPosNameList, posList, targetNum, true, oneReelNum);
return outPos;
}
/**
* 取散盘,从大到小取
*/
private StoragePos pickNotWholeReel(List<String> excluedPosNameList, List<StoragePos> posList, int targetNum, int oneReelNum){
StoragePos outPos = pickOneReel(false,excluedPosNameList,posList,targetNum,true,oneReelNum);
private StoragePos pickNotWholeReel(List<String> excluedPosNameList, List<StoragePos> posList, int targetNum, int oneReelNum) {
StoragePos outPos = pickOneReel(false, excluedPosNameList, posList, targetNum, true, oneReelNum);
return outPos;
}
/**
* 取最小满足数量的盘
*/
private StoragePos pickFitWholeReel(List<String> excluedPosNameList, List<StoragePos> posList, int targetNum){
StoragePos outPos = pickOneReel(true,excluedPosNameList,posList,targetNum,false,-1);
private StoragePos pickFitWholeReel(List<String> excluedPosNameList, List<StoragePos> posList, int targetNum) {
StoragePos outPos = pickOneReel(true, excluedPosNameList, posList, targetNum, false, -1);
return outPos;
}
/**
*
* @param takeWholeReel 是否取整盘, 如果整盘数量小于0,此参数无效, 取整盘时,整盘料数量要大于0
* @param takeWholeReel 是否取整盘, 如果整盘数量小于0,此参数无效, 取整盘时,整盘料数量要大于0
* @param excluedPosNameList
* @param posList
* @param targetNum
* @param pickMaxQtyReel
* @param oneReelNum 整盘料的数量, 挑盘散盘时要小于此值
* @param oneReelNum 整盘料的数量, 挑盘散盘时要小于此值
* @return
*/
private StoragePos pickOneReel(boolean takeWholeReel, List<String> excluedPosNameList, List<StoragePos> posList, int targetNum, boolean pickMaxQtyReel, int oneReelNum){
private StoragePos pickOneReel(boolean takeWholeReel, List<String> excluedPosNameList, List<StoragePos> posList, int targetNum, boolean pickMaxQtyReel, int oneReelNum) {
StoragePos outPos = null;
if(targetNum > 0){
if (targetNum > 0) {
for (StoragePos pos : posList) {
if(!excluedPosNameList.contains(pos.getPosName())){
if (!excluedPosNameList.contains(pos.getPosName())) {
int qty = pos.getBarcode().getAmount();
if(oneReelNum > 0){
if(takeWholeReel){
if (oneReelNum > 0) {
if (takeWholeReel) {
//需要取整盘,即小于此值的盘无效
if(qty < oneReelNum){
if (qty < oneReelNum) {
continue;
}
}else{
} else {
//需要取散盘,即大于此值的盘无效
if(qty >= oneReelNum){
if (qty >= oneReelNum) {
continue;
}
}
}
if(outPos == null){
if (outPos == null) {
//先取第一盘(数量最大的盘)
outPos = pos;
if(pickMaxQtyReel){
if (pickMaxQtyReel) {
return outPos;
}
}
if(qty < outPos.getBarcode().getAmount() && qty >= targetNum){
if (qty < outPos.getBarcode().getAmount() && qty >= targetNum) {
//如果当前盘小于已挑料盘并且这盘料出库后可以满足需求,那么替换已挑料盘
outPos = pos;
}
if(qty < targetNum){
if (qty < targetNum) {
//当前料盘挑完还不满足需求
return outPos;
}
......@@ -970,7 +974,7 @@ public class LiteOrderCache implements ITaskListener {
}
public void updateOrderProgress(LiteOrder order,boolean flag) {
public void updateOrderProgress(LiteOrder order, boolean flag) {
try {
if (!flag) {
if (!order.isClosed()) {
......@@ -988,24 +992,31 @@ public class LiteOrderCache implements ITaskListener {
OrderProgress progress = dataCache.getCache(Constants.CACHE_OrderProgress);
if (progress == null) {
progress = new OrderProgress();
progress = initProgress(order.getOrderNo());
} else {
//判断创建时间,是否在当前时间范围内
Date createDate = progress.getCreateDate();
Date startDate = ShiftUtil.getShiftAStartDate();
DateTime endDate = DateUtil.offsetDay(startDate, 1);
//如果当前时间大于等于当天的白班开始日期,再判断工单记录的创建时间是否在今天范围内
if (System.currentTimeMillis() >= startDate.getTime()){
if (createDate.getTime() >= startDate.getTime() && createDate.getTime() < endDate.getTime()) {
} else {
progress = initProgress(order.getOrderNo());
}
}
}
Date orderStartDate = order.getStartDate();
String orderStartDateStr = DateUtil.format(orderStartDate, "yyyy-MM-dd");
Date createDate = progress.getCreateDate();
String createDateStr = DateUtil.format(createDate, "yyyy-MM-dd");
log.info("工单:" + order.getOrderNo() + "开工时间为:" + orderStartDateStr + "状态为:" + order.getStatus());
log.info("工单:" + order.getOrderNo() + "开工时间为:" + order.getStartDate() + "状态为:" + order.getStatus());
//判断工单创建时间是否小于当前时间
if (DateUtil.parse(orderStartDateStr, "yyyy-MM-dd").getTime() < DateUtil.parse(createDateStr, "yyyy-MM-dd").getTime()) {
return;
}
if (ShiftUtil.isA(orderStartDate)) {
if (!orderStartDateStr.equals(createDateStr)) {
log.info("工单:"+order.getOrderNo()+"开工时间为:"+order.getStartDate()+"与缓存中时间:"+progress.getCreateDate()+"不一致");
progress = new OrderProgress();
}
if (order.isNew()) {
log.info("工单:" + order.getOrderNo() + "属于白班新建,数量加1");
progress.setShiftAOrderCount(progress.getShiftAOrderCount() + 1);
......@@ -1013,13 +1024,7 @@ public class LiteOrderCache implements ITaskListener {
log.info("工单:" + order.getOrderNo() + "属于白班关闭,数量加1");
progress.setShiftAOrderFinishedCount(progress.getShiftAOrderFinishedCount() + 1);
}
} else {
Date startDate = ShiftUtil.getShiftBSelectDate(orderStartDate);
String startDateStr = DateUtil.format(startDate, "yyyy-MM-dd");
if (!startDateStr.equals(createDateStr)) {
log.info("工单:"+order.getOrderNo()+"开工时间为:"+order.getStartDate()+"与缓存中时间:"+progress.getCreateDate()+"不一致");
progress = new OrderProgress();
}
} else if (ShiftUtil.isB(orderStartDate)) {
if (order.isNew()) {
log.info("工单:" + order.getOrderNo() + "属于夜班新建,数量加1");
progress.setShiftBOrderCount(progress.getShiftBOrderCount() + 1);
......@@ -1034,4 +1039,53 @@ public class LiteOrderCache implements ITaskListener {
e.printStackTrace();
}
}
private OrderProgress initProgress(String orderNo) {
OrderProgress process = new OrderProgress();
Date startDate = ShiftUtil.getShiftAStartDate();
DateTime endDate = DateUtil.offsetDay(startDate, 1);
Query query = new Query(Criteria.where("startDate").gte(startDate).lt(endDate));
List<LiteOrder> liteOrderList = liteOrderManager.findByQuery(query);
//A班工单数量
int shiftAOrderCount = 0;
//B班工单数量
int shiftBOrderCount = 0;
//A班工单完成数量
int shiftAOrderFinishedCount = 0;
//B班工单完成数量
int shiftBOrderFinishedCount = 0;
for (LiteOrder order : liteOrderList) {
if (orderNo.equals(order.getOrderNo())) {
continue;
}
if (StringUtils.isNotBlank(order.getReplenishmentNo())){
continue;
}
if (ShiftUtil.isA(order.getStartDate())) {
if (order.isClosed()) {
shiftAOrderFinishedCount = shiftAOrderFinishedCount + 1;
}
shiftAOrderCount = shiftAOrderCount + 1;
} else {
if (order.isClosed()) {
shiftBOrderFinishedCount = shiftBOrderFinishedCount + 1;
}
shiftBOrderCount = shiftBOrderCount + 1;
}
}
process.setShiftAOrderCount(shiftAOrderCount);
process.setShiftBOrderCount(shiftBOrderCount);
process.setShiftAOrderFinishedCount(shiftAOrderFinishedCount);
process.setShiftBOrderFinishedCount(shiftBOrderFinishedCount);
return process;
}
}
......@@ -284,7 +284,8 @@ public class OrderController {
@ApiOperation("关闭工单")
@PostMapping(value = "/closeOrder")
@PreAuthorize("@el.check('workOrder')")
//@PreAuthorize("@el.check('workOrder')")
@AnonymousAccess
public ResultBean closeOrder(@RequestBody Map<String, String> mapValues) {
String orderNo = mapValues.get("orderNo");
if (orderNo == null) {
......
......@@ -50,6 +50,12 @@ public class ShiftUtil {
return date.getTime() >= getShiftAStartDate().getTime() && date.getTime() < getShiftAEndDate().getTime();
}
public static boolean isB(Date date) {
Date startDate = getShiftAEndDate();
DateTime endDate = DateUtil.offsetDay(getShiftAStartDate(), 1);
return date.getTime() >= startDate.getTime() && date.getTime() < endDate.getTime();
}
public static Date getShiftASelectDate() {
String currentDateStr = DateUtil.format(new Date(), "yyyy-MM-dd");
return DateUtil.parse(currentDateStr + " " + START, "yyyy-MM-dd 00:00:00");
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!