深汕工单验证

uat-temp-wj-2502060000-chongqing-step
王杰 2 months ago
parent af973db0c1
commit de0d2f188e

@ -114,6 +114,6 @@ public interface IMesProductionCustomContextStepService {
void removeSortQueuePushLockContext(StationRequestBean reqBean, String queuePushId);
@ApiOperation(value = "处理工位维度的工单完成数上下文")
MesWorkOrderCompleteQtyContext dispatchWorkOrderCompleteQtyCellContext(Integer flag, StationRequestBean reqBean, MesProductionPartContext productionPartContext, Double calcCompleteQty);
MesWorkOrderCompleteQtyContext dispatchWorkOrderCompleteQtyCellContext(Integer flag, Boolean isCellNoCalcQty, StationRequestBean reqBean, MesProductionPartContext productionPartContext, Double calcCompleteQty);
}

@ -176,9 +176,8 @@ public class MesProductSnCheckStepService extends BaseStepService {
return stepResult;
}
//TODO 问题点 自进自出 会导致不计数
//未知条码, 工序为空, 条码数量等于1, 已打印 【打印件, 首工位自进自出未加工完成】
if (produceSn.getPrintStatus().compareTo(MesExtEnumUtil.PRINT_STATUS.PRINTED.getValue()) == 0) {
if (!StringUtils.isEmpty(produceSn.getPrintStatus()) && produceSn.getPrintStatus().compareTo(MesExtEnumUtil.PRINT_STATUS.PRINTED.getValue()) == 0) {
productionPsInContextList.add(new MesProductionPsInContext(produceSn).isCheck(workCell).messageSource(equipVariableCollectContext.getMessageSource()).relateId(produceSn.getId()));

@ -273,6 +273,6 @@ public class MesProductSnGenerateStepService extends BaseStepService {
//TODO 问题点 未知 自进自出 会导致不计数 【再上面未知的地方判断 工序空,已打印状态, 并且自进自出 直接标记需要计数】--- 可以跟下面的合并逻辑进行修改
//TODO 打印件 已经是产成, 当时实际需要计数, 但是实际不会被计算上去 【再上面判断是否存在ID 工序空,已打印状态, 并且自进自出 直接标记需要计数】
//TODO 自进自出, 此前没有被计数, 这个时候也再会被计数 【目前无解, 业务上进行规避】
//TODO 自进自出, 此前没有被计数, 这个时候也再会被计数 【目前无解, 业务上进行规避】
}

@ -0,0 +1,46 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionProcessContextStepService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseStepService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.IStepService;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
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 cn.estsh.impp.framework.boot.util.SpringContextsUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @Description :
* @Author : wangjie
**/
@Slf4j
@Service("mesProductionDataSaveBeforeLockOrderStepService")
public class MesProductionDataSaveBeforeLockOrderStepService extends BaseStepService {
@Autowired
public IMesProductionProcessContextStepService productionProcessContextStepService;
@Override
public StepResult execute(StationRequestBean reqBean) {
StationResultBean resultBean = new StationResultBean();
StepResult stepResult = StepResult.getSuccessComplete();
synchronized ()
//非排序线 保存加工结果工步 execute 方法 使用的是 新事务
((IStepService) SpringContextsUtil.getBean("mesProductionDataSaveStepService")).execute(reqBean);
return stepResult;
}
}

@ -326,15 +326,17 @@ public class MesProductionCustomContextStepService extends BaseStepService imple
removeFsmBusiData(reqBean.getOrganizeCode(), getSortQueuePushLockContextKey(reqBean), queuePushId);
}
//工单完成数工位维度KEY
private String getWorkOrderCompleteQtyContextCellKey(StationRequestBean reqBean, String workOrderNo) {
return new StringJoiner(MesPcnExtConstWords.COLON).add(reqBean.getOrganizeCode()).add(reqBean.getWorkCenterCode()).add(reqBean.getWorkCellCode()).add(MesPcnExtConstWords.WORK_ORDER_COMPLETE_CONTEXT).add(workOrderNo).toString();
//工单完成数KEY【isCellNoCalcQty=true代表工位维度的统计,最终不一定会实际累加到工单上】【isCellNoCalcQty=false代表生产线维度的统计】
private String getWorkOrderCompleteQtyContextCellKey(StationRequestBean reqBean, Boolean isCellNoCalcQty, String workOrderNo) {
StringJoiner sj = new StringJoiner(MesPcnExtConstWords.COLON).add(reqBean.getOrganizeCode()).add(reqBean.getWorkCenterCode());
if (isCellNoCalcQty) sj.add(reqBean.getWorkCellCode());
return sj.add(MesPcnExtConstWords.WORK_ORDER_COMPLETE_CONTEXT).add(workOrderNo).toString();
}
//处理工位维度的工单完成数上下文
//处理工位维度的工单完成数上下文, 有效期三天
@Override
public MesWorkOrderCompleteQtyContext dispatchWorkOrderCompleteQtyCellContext(Integer flag, StationRequestBean reqBean, MesProductionPartContext productionPartContext, Double calcCompleteQty) {
String key = getWorkOrderCompleteQtyContextCellKey(reqBean, productionPartContext.getWorkOrderNo());
public MesWorkOrderCompleteQtyContext dispatchWorkOrderCompleteQtyCellContext(Integer flag, Boolean isCellNoCalcQty, StationRequestBean reqBean, MesProductionPartContext productionPartContext, Double calcCompleteQty) {
String key = getWorkOrderCompleteQtyContextCellKey(reqBean, isCellNoCalcQty, productionPartContext.getWorkOrderNo());
String context = getFsmBusiData(reqBean.getOrganizeCode(), key);
MesWorkOrderCompleteQtyContext workOrderCompleteQtyContext = !StringUtils.isEmpty(context)
? JSONObject.parseObject(context, MesWorkOrderCompleteQtyContext.class)
@ -344,7 +346,7 @@ public class MesProductionCustomContextStepService extends BaseStepService imple
//判断标志当前是否是累计上下文的完成数
if (flag == CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) workOrderCompleteQtyContext.overrideCompleteQty(MathOperation.add(workOrderCompleteQtyContext.getCompleteQty(), calcCompleteQty));
//判断是否需要存储
if (StringUtils.isEmpty(context) || flag == CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) dispatchFsmBusiData(reqBean.getOrganizeCode(), key, JSONObject.toJSONString(workOrderCompleteQtyContext));
if (StringUtils.isEmpty(context) || flag == CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) dispatchFsmBusiData(reqBean.getOrganizeCode(), key, JSONObject.toJSONString(workOrderCompleteQtyContext), MesPcnEnumUtil.EXPIRE_TIME.THREE_DAY.getValue());
return workOrderCompleteQtyContext;
}

@ -8,17 +8,18 @@ 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 cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
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.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
@ -32,7 +33,7 @@ public class MesWorkOrderCheckCompleteQtyStepService extends BaseStepService {
@Autowired
private IMesProductionCustomContextStepService productionCustomContextStepService;
//flag=1【验证+临时存储】; flag=2【累加完成数+删除临时存储
//flag=1【验证】; flag=2【累加完成数】
//验证加工单完成数量, 验证的前提条件: 每腔均已匹配到加工规则;存在工单;
public void dispatchWorkOrderCompleteQtyContext(Integer flag, StationRequestBean reqBean, StationResultBean resultBean,
StepResult stepResult, MesProductionProcessContext productionProcessContext,
@ -61,9 +62,19 @@ public class MesWorkOrderCheckCompleteQtyStepService extends BaseStepService {
//工位是否不累计工单完成数
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);
//验证失败直接退出
if (!stepResult.isCompleted()) break;
}
//验证失败标记删除标志
if (!stepResult.isCompleted()) {
productionPartContextList.forEach(o -> o.busiCheckToDelete());
if (!CollectionUtils.isEmpty(productionPsInContextList)) productionPsInContextList.forEach(o -> o.busiCheckToDelete());
}
}
@ -74,25 +85,32 @@ public class MesWorkOrderCheckCompleteQtyStepService extends BaseStepService {
List<MesProductionPartContext> productionPartContextList, Map<Integer, MesProductionPsInContext> productionPsInContextMap) {
Double calcCompleteQty = new Double(MesPcnExtConstWords.ZERO);
for (MesProductionPartContext productionPartContext : productionPartContextList) {
MesProductionPsInContext productionPsInContext = getProductionPsInContext(productionPsInContextMap, productionPartContext.getForeignKey());
//验证进料零件与产出零件是否一致
Boolean isSamePart = isSamePart(getProductionPsInContext(productionPsInContextMap, productionPartContext.getForeignKey()), productionPartContext, null);
//如果进出不一致,则累加完成数
if (!isSamePart) calcCompleteQty = MathOperation.add(calcCompleteQty, new Double(MesPcnExtConstWords.ONE));
Boolean isSamePart = isSamePart(productionPsInContext, productionPartContext, null);
//验证是否计数
Boolean isCalcCompleteQty = isCalcCompleteQty(isSamePart, productionPsInContext, productionPartContext);
if (isCalcCompleteQty) calcCompleteQty = MathOperation.add(calcCompleteQty, new Double(MesPcnExtConstWords.ONE));
}
//当前工单无须计算工单完成数
if (MathOperation.compareTo(calcCompleteQty, new Double(MesPcnExtConstWords.ZERO)) == 0) return;
MesWorkOrderCompleteQtyContext workOrderCompleteQtyContext;
//处理工位维度的工单完成数上下文
workOrderCompleteQtyContext = productionCustomContextStepService.dispatchWorkOrderCompleteQtyCellContext(flag, reqBean, productionPartContextList.get(0), calcCompleteQty);
//已经在上下文中累加当前工序的工单完成数
MesWorkOrderCompleteQtyContext workOrderCompleteQtyContext = productionCustomContextStepService.dispatchWorkOrderCompleteQtyCellContext(flag, isCellNoCalcQty, reqBean, productionPartContextList.get(0), calcCompleteQty);
//flag=2【累加完成数】
if (flag == CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) return;
//验证工单完成数
checkWorkOrderCompleteQty(reqBean, resultBean, stepResult, workCenter, workOrderCompleteQtyContext, calcCompleteQty);
}
//工位是否不累计工单完成数
public Boolean isCellNoCalcQty(Integer noCalcOrderQty) {
return (!StringUtils.isEmpty(noCalcOrderQty) && noCalcOrderQty.compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0) ? true : false;
}
//根据数据关联键获取进料零件信息
private MesProductionPsInContext getProductionPsInContext(Map<Integer, MesProductionPsInContext> productionPsInContextMap, Integer foreignKey) {
if (CollectionUtils.isEmpty(productionPsInContextMap) || StringUtils.isEmpty(foreignKey)) return null;
@ -112,9 +130,19 @@ public class MesWorkOrderCheckCompleteQtyStepService extends BaseStepService {
}
}
//工位是否不累计工单完成数
public Boolean isCellNoCalcQty(Integer noCalcOrderQty) {
return (!StringUtils.isEmpty(noCalcOrderQty) && noCalcOrderQty.compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0) ? true : false;
//验证是否计数
private Boolean isCalcCompleteQty(Boolean isSamePart, MesProductionPsInContext productionPsInContext, MesProductionPartContext productionPartContext) {
//未选工单场景
if (null == productionPartContext || StringUtils.isEmpty(productionPartContext.getWorkOrderNo())) return false;
//进出不一致
if (!isSamePart) return true;
//进出一致的情况下: 【打印件已经是产成的情况下也需要计数】
if (!StringUtils.isEmpty(productionPsInContext.getId()) && StringUtils.isEmpty(productionPsInContext.getProcessCode()) &&
!StringUtils.isEmpty(productionPsInContext.getPrintStatus()) && productionPsInContext.getPrintStatus().compareTo(MesExtEnumUtil.PRINT_STATUS.PRINTED.getValue()) == 0) {
return true;
}
//进出一致
return false;
}
//验证工单完成数
@ -125,53 +153,22 @@ public class MesWorkOrderCheckCompleteQtyStepService extends BaseStepService {
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()));
//stepResult.obj(false)目的是在工步最后可以判断是否需要清除进料
stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult.obj(false), String.format("请检查工单数量,工单[%s]计划数量[%s]已完成数量[%s]!",
workOrderCompleteQtyContext.getWorkOrderNo(), workOrderCompleteQtyContext.getQty().intValue(), workOrderCompleteQtyContext.getCompleteQty().intValue(),
MathOperation.compareTo(workOrderCompleteQtyContext.getQty(), workOrderCompleteQtyContext.getCompleteQty()) == 0 ? "当前已完成!" : "当前不支持超工单!"));
return;
}
//支持超工单生产情况下判断超出比例
Double rate = MathOperation.div((MathOperation.sub(complateQty, workOrderCompleteQtyContext.getQty())), workOrderCompleteQtyContext.getQty());
if (MathOperation.compareTo(rate, MathOperation.div(workCenter.getOrderRate(), new Double(MesPcnExtConstWords.ONE_HUNDRED))) > 0) {
stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult.obj(false),
String.format("请检查工单数量,工单[%s]计划数量[%s]已完成数量[%s],当前超出超工单比例[%s]!",
workOrderCompleteQtyContext.getWorkOrderNo(), workOrderCompleteQtyContext.getQty().intValue(), workOrderCompleteQtyContext.getCompleteQty().intValue(), workCenter.getOrderRate()));
return;
}
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;
}
}

@ -49,6 +49,9 @@ public class MesProductionPsInContext implements Serializable {
@ApiParam("零件条码状态【用于发送设备加工参数】")
private Integer snStatus;
@ApiParam("打印状态")
private Integer printStatus;
@ApiParam("零件号")
private String partNo;

Loading…
Cancel
Save