|
|
|
@ -1,8 +1,25 @@
|
|
|
|
|
package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step.method;
|
|
|
|
|
|
|
|
|
|
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionCustomContextStepService;
|
|
|
|
|
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.*;
|
|
|
|
|
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
|
|
|
|
|
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseStepService;
|
|
|
|
|
import cn.estsh.i3plus.platform.common.tool.MathOperation;
|
|
|
|
|
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
|
|
|
|
|
import cn.estsh.i3plus.pojo.mes.bean.MesWorkCell;
|
|
|
|
|
import cn.estsh.i3plus.pojo.mes.bean.MesWorkCenter;
|
|
|
|
|
import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrder;
|
|
|
|
|
import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
|
|
|
|
|
import cn.estsh.i3plus.pojo.mes.model.StationResultBean;
|
|
|
|
|
import cn.estsh.i3plus.pojo.mes.model.StepResult;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
import org.springframework.util.CollectionUtils;
|
|
|
|
|
import org.springframework.util.StringUtils;
|
|
|
|
|
|
|
|
|
|
import java.util.*;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @Description : 加工单验证工单完成数量通用工步方法
|
|
|
|
@ -12,4 +29,155 @@ import org.springframework.stereotype.Service;
|
|
|
|
|
@Service("mesWorkOrderCheckCompleteQtyStepService")
|
|
|
|
|
public class MesWorkOrderCheckCompleteQtyStepService extends BaseStepService {
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private IMesProductionCustomContextStepService productionCustomContextStepService;
|
|
|
|
|
|
|
|
|
|
//flag=1【验证+临时存储】; flag=2【累加完成数+删除临时存储】
|
|
|
|
|
//验证加工单完成数量, 验证的前提条件: 每腔均已匹配到加工规则;存在工单;
|
|
|
|
|
public void dispatchWorkOrderCompleteQtyContext(Integer flag, StationRequestBean reqBean, StationResultBean resultBean,
|
|
|
|
|
StepResult stepResult, MesProductionProcessContext productionProcessContext,
|
|
|
|
|
List<MesProductionPartContext> productionPartContextList, List<MesProductionPsInContext> productionPsInContextList) {
|
|
|
|
|
//是否存在产成零件信息
|
|
|
|
|
if (!stepResult.isCompleted() || CollectionUtils.isEmpty(productionPartContextList)) return;
|
|
|
|
|
|
|
|
|
|
//根据产出零件或者腔数拿到需要的加工规则数量, 优先使用产出零件数量
|
|
|
|
|
Integer needQty = !CollectionUtils.isEmpty(productionPartContextList) ? productionPartContextList.size() : productionProcessContext.getCurCellEquip().getCavity();
|
|
|
|
|
//验证是否满足腔数
|
|
|
|
|
if (!CollectionUtils.isEmpty(productionPsInContextList) && productionPsInContextList.size() < needQty) return;
|
|
|
|
|
|
|
|
|
|
//对MesProductionPartContext中的工单号经行分组,每个工单可能对应多条数据, 筛选掉foreignkey为空的数据
|
|
|
|
|
Map<String, List<MesProductionPartContext>> productionPartContextMap = productionPartContextList.stream().filter(o ->
|
|
|
|
|
(!StringUtils.isEmpty(o.getWorkOrderNo()) && !StringUtils.isEmpty(o.getForeignKey()))).collect(Collectors.groupingBy(MesProductionPartContext::getWorkOrderNo));
|
|
|
|
|
|
|
|
|
|
if (CollectionUtils.isEmpty(productionPartContextMap)) return;
|
|
|
|
|
|
|
|
|
|
//根据foreignkey分组进料零件条码
|
|
|
|
|
Map<Integer, MesProductionPsInContext> productionPsInContextMap = CollectionUtils.isEmpty(productionPsInContextList) ? null :
|
|
|
|
|
productionPsInContextList.stream().filter(o -> !StringUtils.isEmpty(o.getForeignKey())).collect(Collectors.toMap(MesProductionPsInContext::getForeignKey, o -> o));
|
|
|
|
|
|
|
|
|
|
//生产线与工位信息
|
|
|
|
|
MesWorkCenter workCenter = productionProcessContext.getWorkCenter();
|
|
|
|
|
MesWorkCell workCell = productionProcessContext.getWorkCell();
|
|
|
|
|
//工位是否不累计工单完成数
|
|
|
|
|
Boolean isCellNoCalcQty = isCellNoCalcQty(workCell.getNoCalcOrderQty());
|
|
|
|
|
|
|
|
|
|
for (Map.Entry<String, List<MesProductionPartContext>> entry : productionPartContextMap.entrySet()) {
|
|
|
|
|
if (null == entry) continue;
|
|
|
|
|
dispatchWorkOrderCompleteQty(flag, reqBean, resultBean, stepResult, workCenter, isCellNoCalcQty, entry.getValue(), productionPsInContextMap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//验证加工单完成数量
|
|
|
|
|
private void dispatchWorkOrderCompleteQty(Integer flag, StationRequestBean reqBean, StationResultBean resultBean,
|
|
|
|
|
StepResult stepResult, MesWorkCenter workCenter, Boolean isCellNoCalcQty,
|
|
|
|
|
List<MesProductionPartContext> productionPartContextList, Map<Integer, MesProductionPsInContext> productionPsInContextMap) {
|
|
|
|
|
Double calcCompleteQty = new Double(MesPcnExtConstWords.ZERO);
|
|
|
|
|
for (MesProductionPartContext productionPartContext : productionPartContextList) {
|
|
|
|
|
//验证进料零件与产出零件是否一致
|
|
|
|
|
Boolean isSamePart = isSamePart(getProductionPsInContext(productionPsInContextMap, productionPartContext.getForeignKey()), productionPartContext, null);
|
|
|
|
|
//如果进出不一致,则累加完成数
|
|
|
|
|
if (!isSamePart) calcCompleteQty = MathOperation.add(calcCompleteQty, new Double(MesPcnExtConstWords.ONE));
|
|
|
|
|
}
|
|
|
|
|
//当前工单无须计算工单完成数
|
|
|
|
|
if (MathOperation.compareTo(calcCompleteQty, new Double(MesPcnExtConstWords.ZERO)) == 0) return;
|
|
|
|
|
|
|
|
|
|
MesWorkOrderCompleteQtyContext workOrderCompleteQtyContext;
|
|
|
|
|
|
|
|
|
|
//工位维度=true ; 生产线维度=false,需要LOCK
|
|
|
|
|
if (isCellNoCalcQty) {
|
|
|
|
|
//处理工位维度的工单完成数上下文
|
|
|
|
|
workOrderCompleteQtyContext = productionCustomContextStepService.dispatchWorkOrderCompleteQtyCellContext(flag, reqBean, productionPartContextList.get(0), calcCompleteQty);
|
|
|
|
|
//已经在上下文中累加当前工序的工单完成数
|
|
|
|
|
if (flag == CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) return;
|
|
|
|
|
//验证工单完成数
|
|
|
|
|
checkWorkOrderCompleteQty(reqBean, resultBean, stepResult, workCenter, workOrderCompleteQtyContext, calcCompleteQty);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//根据数据关联键获取进料零件信息
|
|
|
|
|
private MesProductionPsInContext getProductionPsInContext(Map<Integer, MesProductionPsInContext> productionPsInContextMap, Integer foreignKey) {
|
|
|
|
|
if (CollectionUtils.isEmpty(productionPsInContextMap) || StringUtils.isEmpty(foreignKey)) return null;
|
|
|
|
|
return productionPsInContextMap.get(foreignKey);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//验证进料零件与产出零件是否一致
|
|
|
|
|
public Boolean isSamePart(MesProductionPsInContext productionPsInContext, MesProductionPartContext productionPartContext, MesProdRuleContext prodRuleContext) {
|
|
|
|
|
if (null == productionPsInContext) return false;
|
|
|
|
|
if (StringUtils.isEmpty(productionPsInContext.getPartNo())) return false;
|
|
|
|
|
if (null != productionPartContext) {
|
|
|
|
|
if (!productionPsInContext.getPartNo().equals(productionPartContext.getPartNo())) return false;
|
|
|
|
|
else return true;
|
|
|
|
|
} else {
|
|
|
|
|
if (!productionPsInContext.getPartNo().equals(prodRuleContext.getOutPartNo())) return false;
|
|
|
|
|
else return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//工位是否不累计工单完成数
|
|
|
|
|
public Boolean isCellNoCalcQty(Integer noCalcOrderQty) {
|
|
|
|
|
return (!StringUtils.isEmpty(noCalcOrderQty) && noCalcOrderQty.compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0) ? true : false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//验证工单完成数
|
|
|
|
|
private void checkWorkOrderCompleteQty(StationRequestBean reqBean, StationResultBean resultBean, StepResult stepResult,
|
|
|
|
|
MesWorkCenter workCenter, MesWorkOrderCompleteQtyContext workOrderCompleteQtyContext, Double calcCompleteQty) {
|
|
|
|
|
|
|
|
|
|
//当前工序的预计达到的完成数
|
|
|
|
|
Double complateQty = MathOperation.add(workOrderCompleteQtyContext.getCompleteQty(), calcCompleteQty);
|
|
|
|
|
// 如果预完成数量 小于等于工单数量,则直接过
|
|
|
|
|
if (MathOperation.compareTo(workOrderCompleteQtyContext.getQty(), complateQty) >= 0) return;
|
|
|
|
|
if (StringUtils.isEmpty(workCenter.getIsCheckOrderQty()) || workCenter.getIsCheckOrderQty().compareTo(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) == 0) {
|
|
|
|
|
productionPartContextList.forEach(o -> o.busiCheckToDelete());
|
|
|
|
|
if (!CollectionUtils.isEmpty(productionPsInContextList)) productionPsInContextList.forEach(o -> o.busiCheckToDelete());
|
|
|
|
|
return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult.obj(false),
|
|
|
|
|
MathOperation.compareTo(mesWorkOrder.getQty(), mesWorkOrder.getCompleteQty()) == 0
|
|
|
|
|
? String.format("请检查工单数量,工单[%s]计划数量[%s]已完成数量[%s],当前已完成!", workOrder, mesWorkOrder.getQty().intValue(), mesWorkOrder.getCompleteQty().intValue())
|
|
|
|
|
: String.format("请检查工单数量,工单[%s]计划数量[%s]已完成数量[%s],当前不支持超工单!", workOrder, mesWorkOrder.getQty().intValue(), mesWorkOrder.getCompleteQty().intValue()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private StepResult validSuperWorkOrder(StationRequestBean reqBean, List<MesProductionPartContext> productionPartContextList, List<MesProductionPsInContext> productionPsInContextList, MesWorkCenter workCenter, StepResult stepResult, StationResultBean resultBean) {
|
|
|
|
|
|
|
|
|
|
// 对工单经行分组
|
|
|
|
|
Map<String, List<MesWorkOrder>> orderListMap = workOrderList.stream().collect(Collectors.groupingBy(MesWorkOrder::getWorkOrderNo));
|
|
|
|
|
|
|
|
|
|
for (Map.Entry<String, List<MesProductionPartContext>> entry : productionPartContextMap.entrySet()) {
|
|
|
|
|
String workOrder = entry.getKey();
|
|
|
|
|
List<MesProductionPartContext> productionPartContexts = entry.getValue();
|
|
|
|
|
MesWorkOrder mesWorkOrder = orderListMap.get(workOrder).get(0);
|
|
|
|
|
|
|
|
|
|
Double complateQty = mesWorkOrder.getCompleteQty() + productionPartContexts.size();
|
|
|
|
|
Double qty = mesWorkOrder.getQty();
|
|
|
|
|
log.info("验证超工单,工单号【{}】,qty=【{}】,complateQty =【{}】begin ->", mesWorkOrder.getWorkOrderNo(), qty, complateQty);
|
|
|
|
|
// 如果预完成数量 小于等于工单数量,则直接过
|
|
|
|
|
if (complateQty <= qty) continue;
|
|
|
|
|
|
|
|
|
|
// 以下则是超工单逻辑
|
|
|
|
|
// 如果产线中没有配置超工单,则直接阻断
|
|
|
|
|
if (!Objects.equals(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue(), workCenter.getIsCheckOrderQty())) {
|
|
|
|
|
productionPartContextList.forEach(o -> o.busiCheckToDelete());
|
|
|
|
|
if (!CollectionUtils.isEmpty(productionPsInContextList)) productionPsInContextList.forEach(o -> o.busiCheckToDelete());
|
|
|
|
|
return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult.obj(false),
|
|
|
|
|
MathOperation.compareTo(mesWorkOrder.getQty(), mesWorkOrder.getCompleteQty()) == 0
|
|
|
|
|
? String.format("请检查工单数量,工单[%s]计划数量[%s]已完成数量[%s],当前已完成!", workOrder, mesWorkOrder.getQty().intValue(), mesWorkOrder.getCompleteQty().intValue())
|
|
|
|
|
: String.format("请检查工单数量,工单[%s]计划数量[%s]已完成数量[%s],当前不支持超工单!", workOrder, mesWorkOrder.getQty().intValue(), mesWorkOrder.getCompleteQty().intValue()));
|
|
|
|
|
}
|
|
|
|
|
// 如果配置了超工单,且比例已经超过了配置的超工单比例,也需要阻断
|
|
|
|
|
Double rate = (complateQty - qty)/qty;
|
|
|
|
|
if (rate > workCenter.getOrderRate()/100) {
|
|
|
|
|
productionPartContextList.forEach(o -> o.busiCheckToDelete());
|
|
|
|
|
if (!CollectionUtils.isEmpty(productionPsInContextList)) productionPsInContextList.forEach(o -> o.busiCheckToDelete());
|
|
|
|
|
return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult.obj(false),
|
|
|
|
|
String.format("请检查工单数量,工单[%s]计划数量[%s]已完成数量[%s],当前超出超工单比例[%s]!", workOrder, mesWorkOrder.getQty().intValue(), mesWorkOrder.getCompleteQty().intValue(), workCenter.getOrderRate()));
|
|
|
|
|
}
|
|
|
|
|
log.info("验证超工单,工单号【{}】,qty=【{}】,complateQty =【{}】,isCheckOrderQty=【{}】, rate = 【{}】end ->", mesWorkOrder.getWorkOrderNo(), qty, complateQty,workCenter.getIsCheckOrderQty(),rate);
|
|
|
|
|
}
|
|
|
|
|
log.info("验证是否超工单end ->");
|
|
|
|
|
return stepResult;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|