diff --git a/modules/i3plus-ext-mes-pcn-api/src/main/java/cn/estsh/i3plus/ext/mes/pcn/api/busi/IMesWorkOrderCutService.java b/modules/i3plus-ext-mes-pcn-api/src/main/java/cn/estsh/i3plus/ext/mes/pcn/api/busi/IMesWorkOrderCutService.java index 6cdcb50..eefb7f8 100644 --- a/modules/i3plus-ext-mes-pcn-api/src/main/java/cn/estsh/i3plus/ext/mes/pcn/api/busi/IMesWorkOrderCutService.java +++ b/modules/i3plus-ext-mes-pcn-api/src/main/java/cn/estsh/i3plus/ext/mes/pcn/api/busi/IMesWorkOrderCutService.java @@ -22,7 +22,10 @@ public interface IMesWorkOrderCutService { @ApiOperation(value = "查询裁片工单明细") List queryMesWorkOrderCutDetailList(String cutWorkOrderNo, String organizeCode); - @ApiOperation(value = "查询裁片工单明细") + @ApiOperation(value = "查询裁片方案") MesCutScheme getCutScheme(String cutCode, String organizeCode); + @ApiOperation(value = "查询裁片方案成品配置") + List queryCutSchemeFgList(String cutCode, String organizeCode); + } diff --git a/modules/i3plus-ext-mes-pcn-apiservice/src/main/java/cn/estsh/i3plus/ext/mes/pcn/apiservice/serviceimpl/busi/MesWorkOrderCutService.java b/modules/i3plus-ext-mes-pcn-apiservice/src/main/java/cn/estsh/i3plus/ext/mes/pcn/apiservice/serviceimpl/busi/MesWorkOrderCutService.java index 473e8c2..77ef28e 100644 --- a/modules/i3plus-ext-mes-pcn-apiservice/src/main/java/cn/estsh/i3plus/ext/mes/pcn/apiservice/serviceimpl/busi/MesWorkOrderCutService.java +++ b/modules/i3plus-ext-mes-pcn-apiservice/src/main/java/cn/estsh/i3plus/ext/mes/pcn/apiservice/serviceimpl/busi/MesWorkOrderCutService.java @@ -4,15 +4,17 @@ import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesWorkOrderCutService; import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords; import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil; import cn.estsh.i3plus.pojo.mes.bean.MesCutScheme; +import cn.estsh.i3plus.pojo.mes.bean.MesCutSchemeFg; import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrderCut; import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrderCutDetail; +import cn.estsh.i3plus.pojo.mes.repository.MesCutSchemeFgRepository; import cn.estsh.i3plus.pojo.mes.repository.MesCutSchemeRepository; import cn.estsh.i3plus.pojo.mes.repository.MesWorkOrderCutDetailRepository; import cn.estsh.i3plus.pojo.mes.repository.MesWorkOrderCutRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; -import javax.xml.ws.Action; import java.util.List; /** @@ -33,6 +35,9 @@ public class MesWorkOrderCutService implements IMesWorkOrderCutService { @Autowired private MesCutSchemeRepository cutSchemeRepository; + @Autowired + private MesCutSchemeFgRepository cutSchemeFgRepository; + @Override public MesWorkOrderCut getMesWorkOrderCut(String cutWorkOrderNo, String organizeCode) { return workOrderCutRepository.getByProperty( @@ -53,4 +58,14 @@ public class MesWorkOrderCutService implements IMesWorkOrderCutService { new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.CUT_CODE}, new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), cutCode}); } + + @Override + public List queryCutSchemeFgList(String cutCode, String organizeCode) { + + if (StringUtils.isEmpty(organizeCode)) return null; + + return cutSchemeFgRepository.findByProperty( + new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.CUT_CODE}, + new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), cutCode}); + } } diff --git a/modules/i3plus-ext-mes-pcn-apiservice/src/main/java/cn/estsh/i3plus/ext/mes/pcn/apiservice/serviceimpl/step/MesWorkOrderCutCheckStepService.java b/modules/i3plus-ext-mes-pcn-apiservice/src/main/java/cn/estsh/i3plus/ext/mes/pcn/apiservice/serviceimpl/step/MesWorkOrderCutCheckStepService.java index 9d58f57..8892c88 100644 --- a/modules/i3plus-ext-mes-pcn-apiservice/src/main/java/cn/estsh/i3plus/ext/mes/pcn/apiservice/serviceimpl/step/MesWorkOrderCutCheckStepService.java +++ b/modules/i3plus-ext-mes-pcn-apiservice/src/main/java/cn/estsh/i3plus/ext/mes/pcn/apiservice/serviceimpl/step/MesWorkOrderCutCheckStepService.java @@ -1,21 +1,15 @@ package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step; -import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionDispatchContextStepService; -import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionProcessContextStepService; -import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesWorkOrderExtService; -import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesEquipVariableCollectContext; -import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionPartContext; -import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionProcessContext; -import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionPsInContext; +import cn.estsh.i3plus.ext.mes.pcn.api.busi.*; +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.mes.pcn.serviceimpl.fsm.IStepService; +import cn.estsh.i3plus.mes.pcn.util.StationKvBeanUtil; import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil; import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil; -import cn.estsh.i3plus.pojo.mes.bean.MesProduceSn; -import cn.estsh.i3plus.pojo.mes.bean.MesQueueOrder; -import cn.estsh.i3plus.pojo.mes.bean.MesWorkCenter; -import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrder; +import cn.estsh.i3plus.pojo.mes.bean.*; +import cn.estsh.i3plus.pojo.mes.model.StationKvBean; import cn.estsh.i3plus.pojo.mes.model.StationRequestBean; import cn.estsh.i3plus.pojo.mes.model.StationResultBean; import cn.estsh.i3plus.pojo.mes.model.StepResult; @@ -27,10 +21,9 @@ import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -50,6 +43,15 @@ public class MesWorkOrderCutCheckStepService extends BaseStepService { @Autowired private IMesWorkOrderExtService workOrderExtService; + @Autowired + private IMesWorkOrderCutService workOrderCutService; + + @Autowired + private MesFirstMouldNoReadStepService firstMouldNoReadStepService; + + @Autowired + private IMesProduceSnExtService produceSnExtService; + @Override public StepResult execute(StationRequestBean reqBean) { @@ -66,12 +68,12 @@ public class MesWorkOrderCutCheckStepService extends BaseStepService { //存储生产过程上下文对象 productionProcessContextStepService.dispatchProductionProcessContext(reqBean, productionProcessContext); - //清除本次已获取得到的加工单信息 - productionDispatchContextStepService.removeScanWorkOrderNoContext(reqBean); - //获取上下文生产扫/读信息:加工单 List equipVariableCollectContextList = productionDispatchContextStepService.getScanWorkOrderNoContext(reqBean); - if (CollectionUtils.isEmpty(equipVariableCollectContextList)) return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, "当前缺失待验证的加工单信息!"); + if (CollectionUtils.isEmpty(equipVariableCollectContextList)) return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, "当前缺失待验证的裁片工单信息!"); + + //清除本次已获取得到的裁片工单信息 + //productionDispatchContextStepService.removeScanWorkOrderNoContext(reqBean); //从上下文中取出生产线对象 MesWorkCenter workCenter = productionProcessContext.getWorkCenter(); @@ -90,7 +92,7 @@ public class MesWorkOrderCutCheckStepService extends BaseStepService { //当前不允许跳过 if (isCraftJumpCode && !isAllowJump) return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.SCAN.getValue()). - scanInfo(equipVariableCollectContextList.get(0).getEquipVariableValue()), stepResult, String.format("当前扫描信息工艺强过码[%s],当前没有可以跳过的加工单信息!", equipVariableCollectContextList.get(0).getEquipVariableValue())); + scanInfo(equipVariableCollectContextList.get(0).getEquipVariableValue()), stepResult, String.format("当前扫描信息工艺强过码[%s],当前没有可以跳过的裁片工单信息!", equipVariableCollectContextList.get(0).getEquipVariableValue())); //允许跳过,先更新数据 if (isCraftJumpCode && isAllowJump) { @@ -102,65 +104,153 @@ public class MesWorkOrderCutCheckStepService extends BaseStepService { //验证工单的有效性 List productionPartContextList = new ArrayList<>(); List productionPsInContextList = new ArrayList<>(); - if (!checkWorkOrderValid(reqBean, resultBean, stepResult, productionProcessContext, workCenter, - equipVariableCollectContextList, productionPartContextList, productionPsInContextList).isCompleted()) return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, stepResult.getMsg()); + List productionPsOutContextList = new ArrayList<>(); + if (!checkWorkOrderValid(reqBean, stepResult, productionProcessContext, workCenter, + equipVariableCollectContextList, productionPartContextList, productionPsInContextList, + productionPsOutContextList).isCompleted()) return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, stepResult.getMsg()); + //保存零件数据信息 + if (!firstMouldNoReadStepService.savePartDataMap(reqBean, resultBean, stepResult, productionProcessContext, productionPartContextList, true).isCompleted()) return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, stepResult.getMsg()); + + //保存上下文产出零件信息 + productionDispatchContextStepService.dispatchProductionPartContext(reqBean, productionPartContextList); + + //存储展示组件MODULE_CONTENT内容 + productionDispatchContextStepService.dispatchModuleContentContext(reqBean, getModuleContextData(reqBean, productionPartContextList)); + + //保存扫描的工单信息上下文 + if (MesExtEnumUtil.CELL_MESSAGE_SOURCE.SCAN.getValue() == equipVariableCollectContextList.get(0).getMessageSource()) { + productionProcessContextStepService.dispatchFunctionChooseCavityOrderContext(reqBean, StationKvBeanUtil.addStationKvBeanList(new ArrayList<>(), + new StationKvBean(MesPcnExtConstWords.CAVITY, "腔数", String.valueOf(productionPartContextList.size())), + new StationKvBean(MesPcnExtConstWords.CELL_MESSAGE_SOURCE, "工位信息来源", MesExtEnumUtil.CELL_MESSAGE_SOURCE.READ.getValueStr()), + new StationKvBean(MesPcnExtConstWords.CRAFT_JUMP_CODE, "是否已验证顺序防错", CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValueStr()), + new StationKvBean(MesPcnExtConstWords.WORK_ORDER_NO, "裁片工单", productionPartContextList.stream().filter(o -> null != o).map(MesProductionPartContext::getWorkOrderNo).collect(Collectors.joining(MesPcnExtConstWords.SEMICOLON))))); + } + + String workOrderStr = equipVariableCollectContextList.stream().filter(o -> null != o).map(MesEquipVariableCollectContext::getEquipVariableValue).collect(Collectors.toList()).toString(); + + //执行匹配加工规则工步 + ((IStepService) SpringContextsUtil.getBean("mesWorkOrderCutMatchingProdRuleStepService")).executeInState(reqBean); + + return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog().scanInfo(workOrderStr), stepResult, String.format("当前%s裁片工单%s验证工单状态成功%s!", + MesExtEnumUtil.CELL_MESSAGE_SOURCE.valueOfDescription(equipVariableCollectContextList.get(0).getMessageSource()), workOrderStr, MesPcnExtConstWords.EMPTY)); - return null; + } + + //封装展示组件MODULE_CONTENT内容 + private List> getModuleContextData(StationRequestBean reqBean, List productionPartContextList) { + + List> dataList = new ArrayList<>(); + + List orderList = filterProductionPartContext(productionPartContextList, true); + List finishCodeList = filterProductionPartContext(productionPartContextList, false); + + AtomicReference index = new AtomicReference<>(0); + + if (!CollectionUtils.isEmpty(orderList)) { + orderList.forEach(o -> StationKvBeanUtil.addStationKvBeanList(dataList, new ArrayList<>(), + new StationKvBean(MesPcnExtConstWords.WORK_ORDER_NO, "裁片工单号", o.getWorkOrderNo()), + new StationKvBean(MesPcnExtConstWords.PART_NO, "零件编码", new StringJoiner(MesPcnExtConstWords.SLANT_R).add(o.getPartNo()).toString()), + new StationKvBean(MesPcnExtConstWords.QTY, "完成数/工单数", new StringJoiner(MesPcnExtConstWords.SLANT_R).add(String.valueOf(o.getCompleteQty().intValue())).add(String.valueOf(o.getQty().intValue())).toString()), + new StationKvBean(MesPcnExtConstWords.CAVITY, "腔数", new StringJoiner(MesPcnExtConstWords.SLANT_R).add(String.valueOf(index.updateAndGet(v -> v + 1))).add(String.valueOf(productionPartContextList.size())).toString()))); + } + + if (!CollectionUtils.isEmpty(finishCodeList)) { + StationKvBeanUtil.addStationKvBeanList(dataList, new ArrayList<>(), new StationKvBean(MesPcnExtConstWords.CAVITY_FINISH_CODE, "空腔数", String.valueOf(finishCodeList.size()))); + } + + return dataList; } //验证工单的有效性 - private StepResult checkWorkOrderValid(StationRequestBean reqBean, StationResultBean resultBean, StepResult stepResult, MesProductionProcessContext productionProcessContext, MesWorkCenter workCenter, - List equipVariableCollectContextList, List productionPartContextList, List productionPsInContextList) { + private StepResult checkWorkOrderValid(StationRequestBean reqBean, StepResult stepResult, + MesProductionProcessContext productionProcessContext, MesWorkCenter workCenter, + List equipVariableCollectContextList, + List productionPartContextList, + List productionPsInContextList, + List productionPsOutContextList) { //搜集生产工单号 List filterList = equipVariableCollectContextList.stream().filter(o -> (null != o)).map(MesEquipVariableCollectContext::getEquipVariableValue).collect(Collectors.toList()); - List workOrderNoList = filterList.stream().filter(o -> (!StringUtils.isEmpty(o) && !o.equals(productionProcessContext.getFinishCode()))).distinct().collect(Collectors.toList()); + List workOrderCutNoList = filterList.stream().filter(o -> (!StringUtils.isEmpty(o) && !o.equals(productionProcessContext.getFinishCode()))).distinct().collect(Collectors.toList()); + + //Map> workOrderMap = workOrderExtService.getWorkOrderMapSort(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), workOrderNoList); + + String cutWorkOrderNo = workOrderCutNoList.stream().findFirst().get(); + + MesWorkOrderCut workOrderCut = workOrderCutService.getMesWorkOrderCut(reqBean.getOrganizeCode(), cutWorkOrderNo); - Map> workOrderMap = workOrderExtService.getWorkOrderMapSort(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), workOrderNoList); + if (workOrderCut == null) + return stepResult.isCompleted(false).msg(String.format("请检查裁片工单信息,裁片工单[%s]无效!", cutWorkOrderNo)); - for (String workOrderNo : workOrderNoList) { + MesCutScheme cutScheme = workOrderCutService.getCutScheme(workOrderCut.getCutCode(), reqBean.getOrganizeCode()); - if (StringUtils.isEmpty(workOrderNo)) continue; + if (cutScheme == null) + return stepResult.isCompleted(false).msg(String.format("请检查裁片工单信息,裁片工单[%s]所属裁片配置无效!", cutWorkOrderNo)); - Map itemMap = CollectionUtils.isEmpty(workOrderMap) ? null : workOrderMap.get(workOrderNo); - if (CollectionUtils.isEmpty(itemMap)) - return stepResult.isCompleted(false).msg(String.format("请检查工单信息,加工单号[%s]无效!", workOrderNo)); - if (itemMap.containsKey(MesPcnExtConstWords.MESSAGE)) - return stepResult.isCompleted(false).msg((String) itemMap.get(MesPcnExtConstWords.MESSAGE)); + if (CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue() == cutScheme.getIsCheckMaterial() && workOrderCut.getWorkOrderStatus() != MesExtEnumUtil.CUT_ORDER_STATUS.CHECKED_RAW.getValue()) + return stepResult.isCompleted(false).msg(String.format("裁片工单[%s]未进行裁片原材料防错!", cutWorkOrderNo)); + else if (workOrderCut.getWorkOrderStatus() != MesExtEnumUtil.CUT_ORDER_STATUS.RELEASED.getValue() || workOrderCut.getWorkOrderStatus() != MesExtEnumUtil.CUT_ORDER_STATUS.PROCESS.getValue()) + return stepResult.isCompleted(false).msg(String.format("裁片工单[%s]当前状态[%s]无需加工或无法加工!", cutWorkOrderNo, MesExtEnumUtil.CUT_ORDER_STATUS.valueOfDescription(workOrderCut.getWorkOrderStatus()))); - MesWorkOrder workOrder = (MesWorkOrder) itemMap.get(MesWorkOrder.class.getSimpleName()); + List mesWorkOrderCutDetailList = workOrderCutService.queryMesWorkOrderCutDetailList(reqBean.getOrganizeCode(), cutWorkOrderNo); + + if (CollectionUtils.isEmpty(mesWorkOrderCutDetailList)) + return stepResult.isCompleted(false).msg(String.format("请检查裁片工单信息,裁片工单[%s]明细不存在!", cutWorkOrderNo)); + + List workOrderNoList = mesWorkOrderCutDetailList.stream().map(MesWorkOrderCutDetail::getWorkOrderNo).distinct().collect(Collectors.toList()); + + List workOrderList = workOrderExtService.getWorkOrderList(reqBean.getOrganizeCode(), workOrderNoList); + + if (CollectionUtils.isEmpty(workOrderList)) + return stepResult.isCompleted(false).msg(String.format("请检查工单信息,裁片工单[%s]信息绑定工单信息无效!", cutWorkOrderNo)); + + for (MesWorkOrder workOrder : workOrderList) { if (!MesExtEnumUtil.ORDER_STATUS.checkAllowStatus(workCenter.getCenterType(), workOrder.getWorkOrderStatus())) - return stepResult.isCompleted(false).msg(String.format("请检查工单信息,加工单[%s]信息工单状态[%s]!", workOrderNo, MesExtEnumUtil.ORDER_STATUS.valueOfDescription(workOrder.getWorkOrderStatus()))); + return stepResult.isCompleted(false).msg(String.format("请检查工单信息,裁片工单[%s]信息绑定工单信息工单状态[%s]!", cutWorkOrderNo, MesExtEnumUtil.ORDER_STATUS.valueOfDescription(workOrder.getWorkOrderStatus()))); + if (!workOrder.getWorkCenterCode().equals(reqBean.getWorkCenterCode())) - return stepResult.isCompleted(false).msg(String.format("请检查工单信息,加工单[%s]信息所属生产线[%s]与当前生产线[%s]不一致!", workOrderNo, workOrder.getWorkCenterCode(), reqBean.getWorkCenterCode())); - if (StringUtils.isEmpty(workOrder.getPartProdGroupCode())) - return stepResult.isCompleted(false).msg(String.format("请检查工单信息,加工单[%s]信息未关联零件生产组!", workOrderNo)); - - MesProduceSn produceSn = (MesProduceSn) itemMap.get(MesProduceSn.class.getSimpleName()); - if (MesExtEnumUtil.PRODUCE_QC_STATUS.QUALIFIED.getValue() != produceSn.getQcStatus()) - return stepResult.isCompleted(false).msg(String.format("请检查产品条码信息,产品条码[%s]质量状态[%s]", produceSn.getProductSn(), MesExtEnumUtil.PRODUCE_QC_STATUS.valueOfDescription(produceSn.getQcStatus()))); - if (MesExtEnumUtil.PRODUCE_SN_STATUS.OFFLINE.getValue() <= produceSn.getSnStatus() || MesExtEnumUtil.PRODUCE_SN_STATUS.UNKNOW.getValue() == produceSn.getSnStatus()) - return stepResult.isCompleted(false).msg(String.format("请检查产品条码信息,产品条码[%s]条码状态[%s]", produceSn.getProductSn(), MesExtEnumUtil.PRODUCE_SN_STATUS.valueOfDescription(produceSn.getSnStatus()))); - - MesQueueOrder queueOrder = (MesQueueOrder) itemMap.get(MesQueueOrder.class.getSimpleName()); - if (MesExtEnumUtil.QUEUE_ORDER_STATUS.FINISH.getValue() == queueOrder.getStatus()) - return stepResult.isCompleted(false).msg(String.format("请检查产品条码工位队列信息,产品条码[%s]工位队列状态[%s]", queueOrder.getProductSn(), MesExtEnumUtil.QUEUE_ORDER_STATUS.valueOfDescription(queueOrder.getStatus()))); - - //封装产成零件 - MesProductionPartContext productionPartContext = new MesProductionPartContext().copyPartNo(workOrder, equipVariableCollectContextList.get(0).getMessageSource()).isCheck(productionProcessContext.getWorkCell()); - productionPartContextList.add(productionPartContext); + return stepResult.isCompleted(false).msg(String.format("请检查工单信息,裁片工单[%s]信息绑定工单[%s]信息所属生产线[%s]与当前生产线[%s]不一致!", cutWorkOrderNo, workOrder.getWorkOrderNo(), workOrder.getWorkCenterCode(), reqBean.getWorkCenterCode())); + } - //封装产品条码 - productionPsInContextList.add(new MesProductionPsInContext(productionProcessContext.getWorkCell(), produceSn).messageSource(equipVariableCollectContextList.get(0).getMessageSource()).relateId(queueOrder.getId())); + // 裁片方案成品配置 + List mesCutSchemeFgList = workOrderCutService.queryCutSchemeFgList(cutScheme.getCutCode(), reqBean.getOrganizeCode()); - } + if (CollectionUtils.isEmpty(mesCutSchemeFgList)) + return stepResult.isCompleted(false).msg(String.format("请检查裁片方案成品信息,裁片工单[%s]关联裁片方案[%s]无成品配置!", cutWorkOrderNo, cutScheme.getCutCode())); + + List fgPartNoList = mesCutSchemeFgList.stream().map(MesCutSchemeFg::getPartNo).distinct().collect(Collectors.toList()); + + List worKOrderPartNoList = workOrderList.stream().map(MesWorkOrder::getWorkOrderNo).distinct().collect(Collectors.toList()); + + worKOrderPartNoList.removeAll(fgPartNoList); - //封装空腔 - equipVariableCollectContextList.stream().filter(o -> (null != o && o.getEquipVariableValue().equals(productionProcessContext.getFinishCode()))).forEach(o -> { - productionPartContextList.add(new MesProductionPartContext().isFinishCode()); - productionPsInContextList.add(new MesProductionPsInContext().isFinishCode()); + if (!CollectionUtils.isEmpty(worKOrderPartNoList)) + return stepResult.isCompleted(false).msg(String.format("请检查裁片方案成品信息,零件号[%s]未在裁片方案[%]成品配置信息中维护!", worKOrderPartNoList, cutScheme.getCutCode())); + + Map workOrderCutDetailMap = mesWorkOrderCutDetailList.stream().collect(Collectors.toMap(MesWorkOrderCutDetail::getWorkOrderNo, Function.identity(), (x, y) -> y)); + + List produceSnList = produceSnExtService.getProduceSnList(reqBean.getOrganizeCode(), cutWorkOrderNo); + + //获取上下文的工位 + MesWorkCell workCell = productionProcessContext.getWorkCell(); + + // 获取上道工艺生产的条码并封装到进料上下文中 + if (!CollectionUtils.isEmpty(produceSnList)) + produceSnList.stream().filter(o -> null != o).forEach(o -> { + productionPsInContextList.add(new MesProductionPsInContext(workCell, o).cutCode(cutScheme.getCutCode())); + productionPsOutContextList.add(new MesProductionPsOutContext().copy(o)); + }); + + //封装产出零件信息 + workOrderList.stream().filter(o -> null != o).forEach( o -> { + MesProductionPartContext productionPartContext = new MesProductionPartContext() + .copyPartNo(o, workOrderCutDetailMap.get(o.getWorkOrderNo()).getQty(), equipVariableCollectContextList.get(0).getMessageSource()) + .isCheck(productionProcessContext.getWorkCell()); + //if (equipVariableCollectContextList.get(0).getIsConsume().compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0) productionPartContext.checkSeqResult(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()); + productionPartContext.setCutCode(cutScheme.getCutCode()); + productionPartContextList.add(productionPartContext); }); return stepResult; diff --git a/modules/i3plus-ext-mes-pcn-apiservice/src/main/java/cn/estsh/i3plus/ext/mes/pcn/apiservice/serviceimpl/step/MesWorkOrderCutMatchingProdRuleStepService.java b/modules/i3plus-ext-mes-pcn-apiservice/src/main/java/cn/estsh/i3plus/ext/mes/pcn/apiservice/serviceimpl/step/MesWorkOrderCutMatchingProdRuleStepService.java new file mode 100644 index 0000000..f2eb609 --- /dev/null +++ b/modules/i3plus-ext-mes-pcn-apiservice/src/main/java/cn/estsh/i3plus/ext/mes/pcn/apiservice/serviceimpl/step/MesWorkOrderCutMatchingProdRuleStepService.java @@ -0,0 +1,538 @@ +package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step; + +import cn.estsh.i3plus.ext.mes.pcn.api.busi.*; +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.mes.pcn.util.PojoAttrUtil; +import cn.estsh.i3plus.mes.pcn.util.StringUtil; +import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil; +import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil; +import cn.estsh.i3plus.pojo.mes.bean.MesProdRuleNosortCfg; +import cn.estsh.i3plus.pojo.mes.bean.MesWorkCenter; +import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrder; +import cn.estsh.i3plus.pojo.mes.model.AttrBean; +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 com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +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.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; + +/** + * @Description : 裁片工单匹配加工规则工步【非排序】 + * @Author : xinwang.yi + **/ +@Slf4j +@Service("mesWorkOrderCutMatchingProdRuleStepService") +public class MesWorkOrderCutMatchingProdRuleStepService extends BaseStepService { + + @Autowired + private IMesProductionProcessContextStepService productionProcessContextStepService; + + @Autowired + private IMesProductionDispatchContextStepService productionDispatchContextStepService; + + @Autowired + private IMesProdRuleCfgExtService prodRuleCfgExtService; + + @Autowired + private IMesNumberRuleMatchDispatchService numberRuleMatchDispatchService; + + @Autowired + private IMesTimeEfficientCfgMatchService timeEfficientCfgMatchService; + + @Autowired + private IMesWorkOrderExtService workOrderExtService; + + @Override + public StepResult execute(StationRequestBean reqBean) { + + StationResultBean resultBean = new StationResultBean(); + + StepResult stepResult = StepResult.getSuccessComplete(); + + //获取上下文信息 + MesProductionProcessContext productionProcessContext = productionProcessContextStepService.dispatchCurCellEquipment(reqBean); + + //配置错误 抛出异常 + if (!productionProcessContext.getSuccess()) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), productionProcessContext.getMessage()); + + //存储生产过程上下文对象 + productionProcessContextStepService.dispatchProductionProcessContext(reqBean, productionProcessContext); + + //从上下文中取出生产线对象 + MesWorkCenter workCenter = productionProcessContext.getWorkCenter(); + + //从上下文中取出生产线对象 + MesCellEquipContext cellEquipContext = productionProcessContext.getCurCellEquip(); + + //获取上下文加工规则数据信息集合 + List prodRuleContextList = productionDispatchContextStepService.getProdRuleDataContext(reqBean); + + //获取上下文产出零件数据信息集合 + List productionPartContextList = productionDispatchContextStepService.getProductionPartContext(reqBean); + + //获取上下文进料零件条码信息集合 + //List productionPsInContextList = productionDispatchContextStepService.getProductionPsInContext(reqBean); + + //根据现有数据【产出零件数据】【进料零件条码信息】比对上下文中已经存在的加工规则数据信息集合, 没有加工规则的数据进行查询 + if (CollectionUtils.isEmpty(prodRuleContextList)) prodRuleContextList = new ArrayList<>(); + Integer initSize = prodRuleContextList.size(); + + //封装非排序加工规则 + doHandleProdRuleData(reqBean, resultBean, stepResult, workCenter, productionProcessContext, cellEquipContext, + prodRuleContextList, productionPartContextList); + + //匹配失败需要清除本次扫描/读取信息 + //if (!stepResult.isCompleted() && doBusiCheckToDelete(reqBean, stepResult, productionPartContextList, productionPsInContextList)) + // return stepResult.nextTriggerEvent(CollectionUtils.isEmpty(productionPsInContextList) ? + // MesPcnExtConstWords.NEXT_TRIGGER_EVENT_PART_NO : + // (!StringUtils.isEmpty(stepResult.getObj()) ? MesPcnExtConstWords.NEXT_TRIGGER_EVENT_PART_NO : MesPcnExtConstWords.NEXT_TRIGGER_EVENT_PRODUCT_SN)); + + if (prodRuleContextList.size() != initSize) { + //保存上下文产品加工规则信息集合 + productionDispatchContextStepService.dispatchProdRuleDataContext(reqBean, prodRuleContextList); + //保存上下文产出零件信息 + //if (!CollectionUtils.isEmpty(productionPartContextList)) productionDispatchContextStepService.dispatchProductionPartContext(reqBean, productionPartContextList); + } + + return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), stepResult, "匹配完成!"); + } + + private StepResult doHandleProdRuleData(StationRequestBean reqBean, StationResultBean resultBean, StepResult stepResult, + MesWorkCenter workCenter, MesProductionProcessContext productionProcessContext, + MesCellEquipContext cellEquipContext, List prodRuleContextList, + List productionPartContextList) { + + //根据是否存在【产出零件数据】获取剩余待匹配的加工规则数据 (只能查询到一条,否则报错) + return doHandleProdRuleDataByProductionPart(reqBean, resultBean, stepResult, workCenter, productionProcessContext, + cellEquipContext, prodRuleContextList, productionPartContextList); + + } + + //根据是否存在【产出零件数据】获取剩余待匹配的加工规则数据 (只能查询到一条,否则报错) + private StepResult doHandleProdRuleDataByProductionPart(StationRequestBean reqBean, StationResultBean resultBean, + StepResult stepResult, MesWorkCenter workCenter, + MesProductionProcessContext productionProcessContext, + MesCellEquipContext cellEquipContext, + List prodRuleContextList, + List productionPartContextList) { + + //加工规则的数据已与产出零件的数量一致 + //if (!CollectionUtils.isEmpty(prodRuleContextList) && prodRuleContextList.size() == productionPartContextList.size()) return stepResult; + + //拿到当前最大的foreignKey + Optional maxForeignKeyOptional = productionPartContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getForeignKey()))).max(Comparator.comparing(MesProductionPartContext::getForeignKey)); + Integer foreignKey = (null != maxForeignKeyOptional && maxForeignKeyOptional.isPresent()) ? maxForeignKeyOptional.get().getForeignKey() : MesPcnExtConstWords.ZERO; + + //搜集未匹配规则的产出零件 + List outPartNoList = productionPartContextList.stream() + .filter(o -> (null != o && StringUtils.isEmpty(o.getForeignKey()) && !StringUtils.isEmpty(o.getPartNo()))) + .map(MesProductionPartContext::getPartNo).collect(Collectors.toList()); + + //没有【进料零件条码信息】信息, 根据进料[NULL]条件获取匹配当前产出零件的加工规则数据(只能查询到一条,否则报错) + return doHandleProdRuleDataByProductionPartAndEmptyProductSn(reqBean, resultBean, stepResult, productionProcessContext, + cellEquipContext, prodRuleContextList, productionPartContextList, outPartNoList, foreignKey); + //存在【产出零件数据】信息, 存在【进料零件条码信息】 获取匹配当前产出零件的加工规则数据 (只能查询到一条,否则报错) + //else return doHandleProdRuleDataByProductionPartAndProductSn(reqBean, resultBean, stepResult, workCenter, productionProcessContext, cellEquipContext, prodRuleContextList, productionPartContextList, productionPsInContextList, outPartNoList, foreignKey); + + } + + //没有【进料零件条码信息】信息, 根据进料[NULL]条件获取匹配当前产出零件的加工规则数据(只能查询到一条,否则报错) + private StepResult doHandleProdRuleDataByProductionPartAndEmptyProductSn(StationRequestBean reqBean, StationResultBean resultBean, StepResult stepResult, MesProductionProcessContext productionProcessContext, + MesCellEquipContext cellEquipContext, List prodRuleContextList, List productionPartContextList, List outPartNoList, Integer foreignKey) { + + //【非排序线】获取产品加工规则 ; 条件进料[NULL] + List prodRuleNosortCfgList = prodRuleCfgExtService.getProdRuleNosortCfgList(new MesProdRuleContext(reqBean.getOrganizeCode()).equipmentCode(cellEquipContext.getEquipmentCode()).outPartNos(outPartNoList).inPartIsEmpty(true)); + + //根据产出零件分组数据 + Map> prodRuleNosortCfgMap = groupProdRuleNosortCfgList(prodRuleNosortCfgList); + + for (MesProductionPartContext productionPartContext : productionPartContextList) { + + //foreignKey有值代表已经匹配过产品加工规则 + if (null == productionPartContext || productionPartContext.getIsFinishCode().compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0 || !StringUtils.isEmpty(productionPartContext.getForeignKey())) continue; + + List filterList = !CollectionUtils.isEmpty(prodRuleNosortCfgMap) ? prodRuleNosortCfgMap.get(productionPartContext.getPartNo()) : null; + + if (CollectionUtils.isEmpty(filterList) || filterList.size() > 1) { + productionPartContextList.forEach(o -> o.busiCheckToDelete()); + return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, String.format( + "设备[%s]产出零件[%s]进料零件[空]%s加工规则配置信息!", cellEquipContext.getEquipmentName(), productionPartContext.getPartNo(), CollectionUtils.isEmpty(filterList) ? "未匹配到" : String.format("匹配到[%s]条", filterList.size()))); + } + //【非排序线】获取产品加工规则对应的装配件信息 + MesProdRuleContext prodRuleContext = prodRuleCfgExtService.getProdRuleNosortContext( + new MesProdRuleContext(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), reqBean.getProcessCode(), productionProcessContext.getCraftCode()) + .copy(filterList.get(0)).workOrderNo(productionPartContext.getWorkOrderNo()).foreignKey(productionPartContext.foreignKey(foreignKey += 1).getForeignKey())); + prodRuleContextList.add(prodRuleContext); + + log.info("工厂{}生产线{}工位{}:FSM STATE DISPATCHER --- DO STEP --- {} EXEC --- 设备:{} 产出零件信息:{} 产品加工规则:{} ---", reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), + StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()), cellEquipContext.getEquipmentCode(), JSONObject.toJSONString(productionPartContext), JSONObject.toJSONString(prodRuleContext)); + + } + // 默认头道才有超工单 + //validSuperWorkOrder(reqBean, productionPartContextList, null, workCenter, stepResult, resultBean); + + return stepResult; + } + + /** + * 1 遍历 MesProductionPartContext 对工单号分组 + * 2 不同的单号,查询对应的工单数量和完成数量,进行对比 + * 3 是否超报工和报工比例, + * @param reqBean + * @param productionPartContextList + * @param workCenter + * @param stepResult + * @param resultBean + * @return + */ + private StepResult validSuperWorkOrder(StationRequestBean reqBean, List productionPartContextList, List productionPsInContextList, MesWorkCenter workCenter, StepResult stepResult, StationResultBean resultBean) { + // 验证超工单 + log.info("验证是否超工单begin ->"); + + //判断是否还存在待匹配的主条码信息, 内部循环匹配成功会标记 foreignKey + Optional optional = productionPartContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getWorkOrderNo()))).findFirst(); + if (null == optional || !optional.isPresent()) return stepResult; + + // 对MesProductionPartContext中的工单号经行分组,每个工单可能对应多条数据,筛选掉foreignkey为空的数据 + Map> productionPartContextMap = productionPartContextList.stream().filter(productionPartContext -> !StringUtils.isEmpty(productionPartContext.getForeignKey())) + .collect(Collectors.groupingBy(MesProductionPartContext::getWorkOrderNo)); + // 获取涉及到的所有工单列表 + List workOrderList = workOrderExtService.getWorkOrderList(reqBean.getOrganizeCode(), new ArrayList<>(productionPartContextMap.keySet())); + + // 对工单经行分组 + Map> orderListMap = workOrderList.stream().collect(Collectors.groupingBy(MesWorkOrder::getWorkOrderNo)); + + for (Map.Entry> entry : productionPartContextMap.entrySet()) { + String workOrder = entry.getKey(); + List 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), String.format("请检查工单数量,工单号[%s],工单数量[%s]预完成数量[%s],且未配置超工单!", workOrder, mesWorkOrder.getQty().intValue(), complateQty.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(), complateQty.intValue(), workCenter.getOrderRate())); + } + log.info("验证超工单,工单号【{}】,qty=【{}】,complateQty =【{}】,isCheckOrderQty=【{}】, rate = 【{}】end ->", mesWorkOrder.getWorkOrderNo(), qty, complateQty,workCenter.getIsCheckOrderQty(),rate); + } + log.info("验证是否超工单end ->"); + return stepResult; + } + + //没有【产出零件数据】信息 , 根据进料条件获取匹配加工规则数据(只能查询到一条,否则报错) + private StepResult doHandleProdRuleDataByProductSn(StationRequestBean reqBean, StationResultBean resultBean, StepResult stepResult, MesWorkCenter workCenter, MesProductionProcessContext productionProcessContext, + MesCellEquipContext cellEquipContext, List prodRuleContextList, List productionPsInContextList) { + + //【非排序线】获取产品加工规则 ; 分别根据 进料零件有值 与 进料规则不为空 查询 再合并数据返回 + List prodRuleNosortCfgList = getProdRuleNosortCfgList(reqBean, cellEquipContext, productionPsInContextList, null); + + //拿到当前最大的foreignKey + Optional maxForeignKeyOptional = productionPsInContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getForeignKey()))).max(Comparator.comparing(MesProductionPsInContext::getForeignKey)); + Integer foreignKey = (null != maxForeignKeyOptional && maxForeignKeyOptional.isPresent()) ? maxForeignKeyOptional.get().getForeignKey() : MesPcnExtConstWords.ZERO; + + for (MesProductionPsInContext productionPsInContext : productionPsInContextList) { + + //foreignKey有值代表已经匹配过产品加工规则 + if (null == productionPsInContext || productionPsInContext.getIsFinishCode().compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0 || !StringUtils.isEmpty(productionPsInContext.getForeignKey())) continue; + + List filterList; + //搜集进料零件号匹配的产品加工规则 + if (!StringUtils.isEmpty(productionPsInContext.getPartNo())) filterList = filterProdRuleNosortCfgList(prodRuleNosortCfgList, productionPsInContext.getPartNo()); + //进料零件条码匹配进料零件规则 + else filterList = (List) numberRuleMatchDispatchService.matchNumberRule(reqBean.getOrganizeCode(), productionPsInContext.getProductSn(), filterProdRuleNosortCfgList(prodRuleNosortCfgList)); + + if (CollectionUtils.isEmpty(filterList) || filterList.size() > 1) { + if (productionPsInContext.getMessageSource().compareTo(MesExtEnumUtil.CELL_MESSAGE_SOURCE.SCAN.getValue()) == 0) productionPsInContext.busiCheckToDelete(); + else productionPsInContextList.forEach(o -> o.busiCheckToDelete()); + return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, String.format("设备[%s]与进料零件条码%s加工规则配置信息! 进料零件条码[%s]%s", + cellEquipContext.getEquipmentName(), CollectionUtils.isEmpty(filterList) ? "未匹配到" : String.format("匹配到[%s]条", filterList.size()), productionPsInContext.getProductSn(), + StringUtils.isEmpty(productionPsInContext.getPartNo()) ? "为外协件" : String.format("当前零件号[%s]", productionPsInContext.getPartNo()))); + } + + //时效性验证 + if (!StringUtils.isEmpty(productionPsInContext.getPartNo())) { + Map result = timeEfficientCfgMatchService.checkSnTimeliness(reqBean.getOrganizeCode(), productionPsInContext.getProductSn(), filterList.get(0).getId(), MesExtEnumUtil.TIME_DATA_SOURCE.DATA_SOURCE20.getValue()); + + if (!(Boolean) result.get(MesPcnExtConstWords.RESULT)) { + if (productionPsInContext.getMessageSource().compareTo(MesExtEnumUtil.CELL_MESSAGE_SOURCE.SCAN.getValue()) == 0) productionPsInContext.busiCheckToDelete(); + else productionPsInContextList.forEach(o -> o.busiCheckToDelete()); + return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog().scanInfo(productionPsInContext.getProductSn()), stepResult, (String) result.get(MesPcnExtConstWords.MESSAGE)); + } + } + + //【非排序线】获取产品加工规则对应的装配件信息 + MesProdRuleContext prodRuleContext = prodRuleCfgExtService.getProdRuleNosortContext( + new MesProdRuleContext(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), reqBean.getProcessCode(), productionProcessContext.getCraftCode()) + .copy(filterList.get(0)).productSn(productionPsInContext.getProductSn()).foreignKey(productionPsInContext.foreignKey(foreignKey += 1).getForeignKey())); + prodRuleContextList.add(prodRuleContext); + + log.info("工厂{}生产线{}工位{}:FSM STATE DISPATCHER --- DO STEP --- {} EXEC --- 设备:{} 进料零件条码:{} 产品加工规则:{} ---", reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), + StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()), cellEquipContext.getEquipmentCode(), JSONObject.toJSONString(productionPsInContext), JSONObject.toJSONString(prodRuleContext)); + + } + + return stepResult; + + } + + private List getProdRuleNosortCfgList(StationRequestBean reqBean, MesCellEquipContext cellEquipContext, List productionPsInContextList, List outPartNoList) { + //【非排序线】获取产品加工规则 ; 分别根据 进料零件有值 与 进料规则不为空 查询 再合并数据返回, 条件可能携带产出零件 + List inPartNoList = productionPsInContextList.stream().filter(o -> (null != o && StringUtils.isEmpty(o.getForeignKey()) && !StringUtils.isEmpty(o.getPartNo()))).map(MesProductionPsInContext::getPartNo).collect(Collectors.toList()); + Optional optional = productionPsInContextList.stream().filter(o -> (null != o && StringUtils.isEmpty(o.getForeignKey()) && o.getIsFinishCode().compareTo(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) == 0 && StringUtils.isEmpty(o.getPartNo()))).findFirst(); + List prodRuleNosortCfgList = prodRuleCfgExtService.getProdRuleNosortCfgList( + !CollectionUtils.isEmpty(inPartNoList) ? new MesProdRuleContext(reqBean.getOrganizeCode()).equipmentCode(cellEquipContext.getEquipmentCode()).inPartNos(inPartNoList).outPartNos(outPartNoList) : null, + (null != optional && optional.isPresent()) ? new MesProdRuleContext(reqBean.getOrganizeCode()).equipmentCode(cellEquipContext.getEquipmentCode()).inPartIsEmpty(true).inPartRuleIsEmpty(false).outPartNos(outPartNoList) : null); + return prodRuleNosortCfgList; + } + + //存在【产出零件数据】信息, 存在【进料零件条码信息】 获取匹配当前产出零件的加工规则数据 (只能查询到一条,否则报错) + private StepResult doHandleProdRuleDataByProductionPartAndProductSn(StationRequestBean reqBean, StationResultBean resultBean, StepResult stepResult, MesWorkCenter workCenter, MesProductionProcessContext productionProcessContext, MesCellEquipContext cellEquipContext, + List prodRuleContextList, List productionPartContextList, List productionPsInContextList, List outPartNoList, Integer foreignKey) { + + //【非排序线】获取产品加工规则 ; 分别根据 进料零件有值 与 进料规则不为空 查询 再合并数据返回, 条件携带产出零件 + List prodRuleNosortCfgList = getProdRuleNosortCfgList(reqBean, cellEquipContext, productionPsInContextList, outPartNoList); + + //TODO 提示优化 直接根除产出零件去查询,判断产出零件对应的加工规则是不是仅仅维护了一个 + //List prodRuleNosortCfgList = prodRuleCfgExtService.getProdRuleNosortCfgList(new MesProdRuleContext(reqBean.getOrganizeCode()).equipmentCode(cellEquipContext.getEquipmentCode()).outPartNos(outPartNoList)); + + //根据产出零件分组数据 + Map> prodRuleNosortCfgMap = groupProdRuleNosortCfgList(prodRuleNosortCfgList); + + for (MesProductionPartContext productionPartContext : productionPartContextList) { + + //foreignKey有值代表已经匹配过产品加工规则 + if (null == productionPartContext || productionPartContext.getIsFinishCode() + .compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0 || !StringUtils.isEmpty(productionPartContext.getForeignKey())) continue; + + //获取匹配产出零件的所有加工规则 + List outPartNoProdRuleList = !CollectionUtils.isEmpty(prodRuleNosortCfgMap) ? prodRuleNosortCfgMap.get(productionPartContext.getPartNo()) : null; + + MesProductionPsInContext productSn = null; + + //判断是否还存在待匹配的主条码信息, 内部循环匹配成功会标记 foreignKey + Optional optional = productionPsInContextList.stream().filter(o -> (null != o && StringUtils.isEmpty(o.getForeignKey()) && o.getIsFinishCode().compareTo(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) == 0)).findFirst(); + if (null == optional || !optional.isPresent()) break; + + List innerfilterList = null; + for (MesProductionPsInContext productionPsInContext : productionPsInContextList) { + + //foreignKey有值代表已经匹配过产品加工规则 + if (null == productionPsInContext || productionPartContext.getIsFinishCode().compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0 || !StringUtils.isEmpty(productionPsInContext.getForeignKey())) continue; + + //搜集进料零件号匹配的产品加工规则 + if (!StringUtils.isEmpty(productionPsInContext.getPartNo())) innerfilterList = filterProdRuleNosortCfgList(outPartNoProdRuleList, productionPsInContext.getPartNo()); + //进料零件条码匹配进料零件规则 + else innerfilterList = (List) numberRuleMatchDispatchService.matchNumberRule(reqBean.getOrganizeCode(), productionPsInContext.getProductSn(), filterProdRuleNosortCfgList(outPartNoProdRuleList)); + + if (CollectionUtils.isEmpty(innerfilterList) || innerfilterList.size() > 1) continue; + + //验证进出一致 + if (!StringUtils.isEmpty(productionPsInContext.getPartNo()) && productionPsInContext.getPartNo().equals(productionPartContext.getPartNo())) { + + //进料工单必须与产出工单一致 + if (!StringUtils.isEmpty(productionPartContext.getWorkOrderNo()) && !StringUtils.isEmpty(productionPsInContext.getWorkOrderNo()) && !productionPsInContext.getWorkOrderNo().equals(productionPartContext.getWorkOrderNo())) { + if (productionPsInContext.getMessageSource().compareTo(MesExtEnumUtil.CELL_MESSAGE_SOURCE.SCAN.getValue()) == 0) productionPsInContext.busiCheckToDelete(); + else productionPsInContextList.forEach(o -> o.busiCheckToDelete()); + return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog().scanInfo(productionPsInContext.getProductSn()), stepResult, String.format("主条码[%s]零件号[%s]关联的加工单[%s]与产出零件[%s]关联的加工单[%s]不一致!", + productionPsInContext.getProductSn(), productionPsInContext.getPartNo(), productionPsInContext.getWorkOrderNo(), productionPartContext.getPartNo(), productionPartContext.getWorkOrderNo())); + } + + //进料存在工单且已经过某工序生产, 不能匹配无工单的产出零件 + if (StringUtils.isEmpty(productionPartContext.getWorkOrderNo()) && !StringUtils.isEmpty(productionPsInContext.getWorkOrderNo()) && !StringUtils.isEmpty(productionPsInContext.getProcessCode())) { + if (productionPsInContext.getMessageSource().compareTo(MesExtEnumUtil.CELL_MESSAGE_SOURCE.SCAN.getValue()) == 0) productionPsInContext.busiCheckToDelete(); + else productionPsInContextList.forEach(o -> o.busiCheckToDelete()); + return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog().scanInfo(productionPsInContext.getProductSn()), stepResult, String.format("主条码[%s]零件号[%s]已关联加工单[%s]且已经过工序[%s]工艺[%s],不支持匹配当前未关联加工单的产出零件[%s]", + productionPsInContext.getProductSn(), productionPsInContext.getPartNo(), productionPsInContext.getWorkOrderNo(), productionPsInContext.getProcessCode(), productionPsInContext.getCraftCode(), productionPartContext.getPartNo())); + } + + } + + //时效性验证 + //if (!StringUtils.isEmpty(productionPsInContext.getPartNo())) { + // Map result = timeEfficientCfgMatchService.checkSnTimeliness(reqBean.getOrganizeCode(), productionPsInContext.getProductSn(), innerfilterList.get(0).getId(), MesExtEnumUtil.TIME_DATA_SOURCE.DATA_SOURCE20.getValue()); + // + // if (!(Boolean)result.get(MesPcnExtConstWords.RESULT)) { + // if (productionPsInContext.getMessageSource().compareTo(MesExtEnumUtil.CELL_MESSAGE_SOURCE.SCAN.getValue()) == 0) productionPsInContext.busiCheckToDelete(); + // else productionPsInContextList.forEach(o -> o.busiCheckToDelete()); + // return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog().scanInfo(productionPsInContext.getProductSn()), stepResult, (String) result.get(MesPcnExtConstWords.MESSAGE)); + // } + //} + + productionPartContext.foreignKey(productionPsInContext.foreignKey(foreignKey += 1).getForeignKey()); + productSn = productionPsInContext; + + break; + } + + //【非排序线】获取产品加工规则对应的装配件信息 + if (!CollectionUtils.isEmpty(innerfilterList) && innerfilterList.size() == 1) { + + MesProdRuleContext prodRuleContext = prodRuleCfgExtService.getProdRuleNosortContext(new MesProdRuleContext( + reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), + reqBean.getProcessCode(), productionProcessContext.getCraftCode()). + copy(innerfilterList.get(0)).workOrderNo(productionPartContext.getWorkOrderNo()).productSn(productSn.getProductSn())) + .foreignKey(productionPartContext.getForeignKey()); + prodRuleContextList.add(prodRuleContext); + + log.info("工厂{}生产线{}工位{}:FSM STATE DISPATCHER --- DO STEP --- {} EXEC --- 设备:{} 产出零件信息:{} 进料零件条码:{} 产品加工规则:{} ---", reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), + StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()), cellEquipContext.getEquipmentCode(), JSONObject.toJSONString(productionPartContext), JSONObject.toJSONString(productSn), JSONObject.toJSONString(prodRuleContext)); + + } + + } + + ////判断是否还存在待匹配的主条码信息 + //Optional optional = productionPsInContextList.stream().filter(o -> + // (null != o && StringUtils.isEmpty(o.getForeignKey()) && o.getIsFinishCode().compareTo(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) == 0)).findFirst(); + //if (null != optional && optional.isPresent()) { + // if (optional.get().getMessageSource().compareTo(MesExtEnumUtil.CELL_MESSAGE_SOURCE.SCAN.getValue()) == 0) optional.get().busiCheckToDelete(); + // else productionPsInContextList.forEach(o -> o.busiCheckToDelete()); + // String productSnStr = productionPsInContextList.stream().filter(o -> (null != o && StringUtils.isEmpty(o.getForeignKey()) && o.getIsFinishCode().compareTo(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) == 0)) + // .map(o -> String.format(" 进料零件条码[%s]%s", o.getProductSn(), StringUtils.isEmpty(o.getPartNo()) ? "为外协件" : String.format("当前零件号[%s]", o.getPartNo()))).collect(Collectors.joining(MesPcnExtConstWords.SEMICOLON)); + // return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog().scanInfo(productSnStr), stepResult, String.format("设备[%s]产出零件%s与进料零件条码未匹配到唯一的加工规则配置信息!%s", cellEquipContext.getEquipmentName(), + // productionPartContextList.stream().filter(o -> (null != o && StringUtils.isEmpty(o.getForeignKey()) && o.getIsFinishCode().compareTo(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) == 0)).map(MesProductionPartContext::getPartNo).collect(Collectors.toList()).toString(), + // productSnStr)); + //} + + // 默认头道才有超工单 + //validSuperWorkOrder(reqBean, productionPartContextList,productionPsInContextList,workCenter, stepResult, resultBean); + return stepResult; + + } + + //搜集进料零件号匹配的产品加工规则 + private List filterProdRuleNosortCfgList(List prodRuleNosortCfgList, String partNo) { + return CollectionUtils.isEmpty(prodRuleNosortCfgList) ? null : prodRuleNosortCfgList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getInPartNo()) && o.getInPartNo().equals(partNo))).collect(Collectors.toList()); + } + + //搜集进料零件规则有值的产品加工规则 + private List filterProdRuleNosortCfgList(List prodRuleNosortCfgList) { + return CollectionUtils.isEmpty(prodRuleNosortCfgList) ? null : prodRuleNosortCfgList.stream().filter(o -> (null != o && StringUtils.isEmpty(o.getInPartNo()) && !StringUtils.isEmpty(o.getInPartNoRule()))).collect(Collectors.toList()); + } + + //根据产出零件分组数据 + private Map> groupProdRuleNosortCfgList(List prodRuleNosortCfgList) { + return CollectionUtils.isEmpty(prodRuleNosortCfgList) ? null : + prodRuleNosortCfgList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesProdRuleNosortCfg::getOutPartNo)); + } + + //显示装配件信息 + public Boolean showProductionAssembly(StationRequestBean reqBean, StationResultBean resultBean, MesWorkCenter workCenter, MesCellEquipContext cellEquipContext, List prodRuleContextList) { + + for (MesProdRuleContext prodRuleContext : prodRuleContextList) { + + if (null == prodRuleContext || StringUtils.isEmpty(prodRuleContext.getAssemblyDataJson())) continue; + + //封装匹配当前设备的装配件信息 + List assemblyShowContextList = getAssemblyShowContextList(cellEquipContext, prodRuleContext.getAssemblyDataContext(workCenter)); + if (CollectionUtils.isEmpty(assemblyShowContextList)) continue; + + //装配件清单列表标题 + List attrBeanList = dataAttrList(prodRuleContext.getWorkOrderNo()); + + //封装多表格 + resultBean.addStationResultBeans(new StationResultBean().dataType(MesPcnEnumUtil.STATION_DATA_TYPE.TABLE.getValue()).dataAttrList(attrBeanList).resultList(assemblyShowContextList)); + + } + + if (CollectionUtils.isEmpty(resultBean.getStationResultBeans())) return false; + + resultBean.busiType(MesPcnEnumUtil.STATION_BUSI_TYPE.STEP_CUSTOM_CONTENT.getValue()).dataType(MesPcnEnumUtil.STATION_DATA_TYPE.TABLES.getValue()); + this.sendMessage(reqBean, resultBean); + + return true; + + } + + private String getWorkOrderNo(Map productionPartMap, Integer foreignKey) { + return (!CollectionUtils.isEmpty(productionPartMap) && productionPartMap.containsKey(foreignKey)) ? productionPartMap.get(foreignKey).getWorkOrderNo() : null; + } + + //封装匹配当前设备的装配件信息 + private List getAssemblyShowContextList(MesCellEquipContext cellEquipContext, List productionAssemblyContextList) { + if (CollectionUtils.isEmpty(productionAssemblyContextList)) return null; + List assemblyShowContextList = new ArrayList<>(); + for (MesProductionAssemblyContext item : productionAssemblyContextList) { + //不显示且不扫描/仅目视的不显示出来 + if (null == item || MesExtEnumUtil.ASSEMBLY_MATCH_TYPE.checkIsNoShow(item.getMatchType())) continue; + assemblyShowContextList.add(assemblyShowContext(item)); + } + + assemblyShowContextList = assemblyShowContextList.stream().filter(o -> null != o).sorted(Comparator.comparing(MesAssemblyShowContext::getRouteSeq)).collect(Collectors.toList()); + + AtomicReference index = new AtomicReference<>(0); + assemblyShowContextList.forEach(o -> o.index(index.updateAndGet(v -> v + 1))); + + return assemblyShowContextList; + } + + //封装装配件信息 + private MesAssemblyShowContext assemblyShowContext(MesProductionAssemblyContext o) { + MesAssemblyShowContext assemblyShowContext = new MesAssemblyShowContext(); + BeanUtils.copyProperties(o, assemblyShowContext); + assemblyShowContext.setMatchTypeName(MesExtEnumUtil.ASSEMBLY_MATCH_TYPE.valueOfDescription(assemblyShowContext.getMatchType())); + assemblyShowContext.setAssemblyStatusName(MesExtEnumUtil.ASSEMBLY_STATUS.valueOfDescription(assemblyShowContext.getAssemblyStatus())); + if (MesExtEnumUtil.ASSEMBLY_STATUS.ASSEMBLY_STATUS_30.getValue() != assemblyShowContext.getAssemblyStatus()) + assemblyShowContext.setColor(StringUtils.isEmpty(assemblyShowContext.getShowColor()) ? MesExtEnumUtil.COLOR.GREEN.getValue() : assemblyShowContext.getShowColor()); + return assemblyShowContext; + } + + //装配件清单列表标题 + private List dataAttrList(String workOrderNo) { + List attrBeanList = new ArrayList<>(); + PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.INDEX, "序号"); + PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.MATCH_TYPE_NAME, "装配方式"); + if (!StringUtils.isEmpty(workOrderNo)) PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.WORK_ORDER_NO, "生产工单编号"); + PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.PART_NO, "零件编码"); + PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.ASSEMBLY_PART_NO, "原料编码"); + PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.ASSEMBLY_PART_NAME, "原料名称"); + PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.ASSEMBLY_SN, "原料条码"); + PojoAttrUtil.loadPojoAttrs(attrBeanList, MesPcnExtConstWords.ASSEMBLY_STATUS_NAME, "装配状态"); + return attrBeanList; + } + + //清除本次扫描/读取信息 有进料【只】需要清除进料,否则存在产出零件需要清除产出零件 【只需要清除被标记的数据】 + private Boolean doBusiCheckToDelete(StationRequestBean reqBean, StepResult stepResult, List productionPartContextList, List productionPsInContextList) { + if (!CollectionUtils.isEmpty(productionPsInContextList) && StringUtils.isEmpty(stepResult.getObj())) { + productionDispatchContextStepService.dispatchProductionPsInContext(reqBean, productionPsInContextList.stream().filter(o -> (null != o && o.getBusiCheckToDelete().compareTo(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) == 0)).collect(Collectors.toList())); + } else if (!CollectionUtils.isEmpty(productionPartContextList)) { + if (!StringUtils.isEmpty(stepResult.getObj())) productionDispatchContextStepService.removeProductionPsInContext(reqBean); + productionDispatchContextStepService.removeProductionPartContext(reqBean); + productionDispatchContextStepService.removeProdRuleDataContext(reqBean); + productionProcessContextStepService.removeFunctionChooseCavityOrderContext(reqBean); + if (productionDispatchContextStepService.checkFirstMouldNoIsExistContext(reqBean)) { + //存在头道模具号场景下 必须抛出异常 因为头道模具号的接口逻辑会配置非常变值,也就是每次返回回去都会拿到头道模具号 就会出现死循环线程 + productionDispatchContextStepService.removeFirstMouldNoContext(reqBean); + foundExThrowNoShowMsg(); + } + } + return true; + } + +} diff --git a/modules/i3plus-ext-mes-pcn-apiservice/src/main/java/cn/estsh/i3plus/ext/mes/pcn/apiservice/serviceimpl/step/MesWorkOrderCutSaveStepService.java b/modules/i3plus-ext-mes-pcn-apiservice/src/main/java/cn/estsh/i3plus/ext/mes/pcn/apiservice/serviceimpl/step/MesWorkOrderCutSaveStepService.java new file mode 100644 index 0000000..1bf13ca --- /dev/null +++ b/modules/i3plus-ext-mes-pcn-apiservice/src/main/java/cn/estsh/i3plus/ext/mes/pcn/apiservice/serviceimpl/step/MesWorkOrderCutSaveStepService.java @@ -0,0 +1,323 @@ +package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step; + +import cn.estsh.i3plus.ext.mes.pcn.api.busi.*; +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.actor.shipping.dispatch.IFsmCommonService; +import cn.estsh.i3plus.mes.pcn.actor.shipping.dispatch.IFsmRouteDataService; +import cn.estsh.i3plus.mes.pcn.api.iservice.busi.ISyncFuncService; +import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseStepService; +import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.IStepService; +import cn.estsh.i3plus.mes.pcn.util.StringUtil; +import cn.estsh.i3plus.platform.common.convert.ConvertBean; +import cn.estsh.i3plus.platform.common.tool.TimeTool; +import cn.estsh.i3plus.pojo.base.bean.DdlPackBean; +import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil; +import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil; +import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack; +import cn.estsh.i3plus.pojo.mes.bean.*; +import cn.estsh.i3plus.pojo.mes.model.GenSerialNoModel; +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.repository.MesProductionAssemblyRepository; +import cn.estsh.i3plus.pojo.mes.repository.MesWorkOrderCutRepository; +import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil; +import cn.estsh.impp.framework.boot.exception.ImppBusiException; +import cn.estsh.impp.framework.boot.util.SpringContextsUtil; +import com.alibaba.fastjson.JSONObject; +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.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @Description : 保存加工结果工步 + * @Author : wangjie + **/ +@Slf4j +@Service("mesWorkOrderCutSaveStepService") +public class MesWorkOrderCutSaveStepService extends BaseStepService { + + @Autowired + private IMesProductionProcessContextStepService productionProcessContextStepService; + + @Autowired + private IMesProductionDispatchContextStepService productionDispatchContextStepService; + + @Autowired + private IMesProductionCustomContextStepService productionCustomContextStepService; + + @Autowired + private IMesWorkOrderCutService workOrderCutService; + + @Autowired + private MesWorkOrderCutRepository workOrderCutRepository; + + @Autowired + private IFsmCommonService fsmCommonService; + + @Autowired + private MesFirstMouldNoReadStepService firstMouldNoReadStepService; + + @Autowired + private IMesProduceSnExtService produceSnExtService; + + @Autowired + private ISyncFuncService syncFuncService; + + @Autowired + private IFsmRouteDataService fsmRouteDataService; + + @Autowired + private MesProductionAssemblyRepository productionAssemblyRepository; + + @Override + public StepResult execute(StationRequestBean reqBean) { + + StationResultBean resultBean = new StationResultBean(); + + //获取上下文信息 + MesProductionProcessContext productionProcessContext = productionProcessContextStepService.dispatchCurCellEquipment(reqBean); + + //配置错误 抛出异常 + if (!productionProcessContext.getSuccess()) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), productionProcessContext.getMessage()); + + //存储生产过程上下文对象 + productionProcessContextStepService.dispatchProductionProcessContext(reqBean, productionProcessContext); + + //获取上下文生产扫/读信息:加工单 + List equipVariableCollectContextList = productionDispatchContextStepService.getScanWorkOrderNoContext(reqBean); + + String cutWorkOrderNo = equipVariableCollectContextList.get(0).getEquipVariableValue(); + + //从上下文中取出工位当前要使用的设备 + MesCellEquipContext cellEquipContext = productionProcessContext.getCurCellEquip(); + + // 看是否修改裁片工单状态 + //获取工位参数 + Map wcpcMap = fsmCommonService.handleFsmWcpcMapDataForDoScan(reqBean); + + //获取上下文进料零件条码信息集合 + List productionPsInContextList = productionDispatchContextStepService.getProductionPsInContext(reqBean); + + //获取上下文产成零件条码信息集合 + List productionPsOutContextList = productionDispatchContextStepService.getProductionPsOutContext(reqBean); + + //获取上下文产出零件数据信息集合 + List productionPartContextList = productionDispatchContextStepService.getProductionPartContext(reqBean); + + //获取上下文产品加工规则数据信息集合 + List prodRuleContextList = productionDispatchContextStepService.getProdRuleDataContext(reqBean); + + if (CollectionUtils.isEmpty(prodRuleContextList)) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), "当前不存在加工规则信息,请重置工序解决!"); + + // 根据产出零件号分组加工规则 + Map prodRuleContextMapByOutPartNo = prodRuleContextList.stream().collect(Collectors.toMap(MesProdRuleContext::getOutPartNo, Function.identity(), (x, y) -> y)); + + // 获取产成零件信息 + Map partDataContext = productionDispatchContextStepService.getPartDataContext(reqBean); + + // 无进料条码则生成条码 + if (CollectionUtils.isEmpty(productionPsInContextList)) { + + productionPsOutContextList = new ArrayList<>(); + + //获取生产线的当前班组班次信息 + MesProdShiftContext prodShiftContext = productionCustomContextStepService.getMesProdShiftKvBean(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode()); + + if (null == prodShiftContext) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), "当前不存在生产开班记录,请重新开班!"); + + //从上下文中取出工位对象 + MesWorkCell workCell = productionProcessContext.getWorkCell(); + + for (MesProductionPartContext mesProductionPartContext : productionPartContextList) { + + MesPart part = partDataContext.get(mesProductionPartContext.getPartNo()); + + MesProdRuleContext mesProdRuleContext = prodRuleContextMapByOutPartNo.get(part.getPartNo()); + + MesProduceSn produceSn = new MesProduceSn(); + ConvertBean.serviceModelInitialize(produceSn, reqBean.getUserInfo()); + produceSn.setOrganizeCode(reqBean.getOrganizeCode()); + produceSn.setProductSn(cutWorkOrderNo); + //produceSn.set + produceSn.setCustSn(produceSn.getCustSn()); + produceSn.setSerialNumber(doGenerateSerialNo(reqBean, resultBean, MesPcnExtConstWords.DEFAULT_SERIAL_NUMBER_RULE, part)); + produceSn.setQty(mesProductionPartContext.getQty()); + + produceSn.setWorkOrderNo(mesProductionPartContext.getWorkOrderNo()); + produceSn.setCustCode(mesProductionPartContext.getCustCode()); + produceSn.setCustPartNo(mesProductionPartContext.getCustPartNo()); + + produceSn.setAreaCode(workCell.getAreaCode()); + produceSn.setWorkCenterCode(workCell.getWorkCenterCode()); + produceSn.setWorkCellCode(workCell.getWorkCellCode()); + + produceSn.setPartNo(mesProductionPartContext.getPartNo()); + produceSn.setPartName(mesProductionPartContext.getPartName()); + produceSn.setProcessLabelTemplate(part.getProcessLabelTemplate()); + produceSn.setProdLabelTemplate(part.getProductLabelTemplate()); + produceSn.setCustLabelTemplate(part.getCustLabelTemplate()); + + produceSn.setSnType(MesExtEnumUtil.PRODUCE_SN_TYPE.STANDARD.getValue()); + produceSn.setSnStatus(MesExtEnumUtil.PRODUCE_SN_STATUS.OFFLINE.getValue()); + produceSn.setQcStatus(MesExtEnumUtil.PRODUCE_QC_STATUS.QUALIFIED.getValue()); + + produceSn.setShiftCode(prodShiftContext.getShiftCode()); + produceSn.setShiftGroup(prodShiftContext.getShiftGroup()); + + produceSn.setPrintCount(MesPcnExtConstWords.ZERO); + produceSn.setPrintStatus(MesExtEnumUtil.PRINT_STATUS.UNPRINT.getValue()); + + if (StringUtils.isEmpty(produceSn.getInWorkCenterTime())) produceSn.setInWorkCenterTime(produceSn.getModifyDatetime()); + produceSn.setLotNo(produceSn.getModifyDatetime().substring(0, 10)); + + produceSn.setFid(UUID.randomUUID().toString()); + produceSn = produceSnExtService.insert(produceSn); + + MesProductionPsOutContext productionPsOutContext = new MesProductionPsOutContext().copy(produceSn, mesProdRuleContext.getForeignKey()); + + log.info("工厂{}生产线{}工位{}:FSM STATE DISPATCHER --- DO STEP --- {} EXEC --- MesProduceSn:{} --- MesProductionPsOutContext:{}", + reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), + StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()), JSONObject.toJSONString(produceSn), JSONObject.toJSONString(productionPsOutContext)); + + productionPsOutContextList.add(productionPsOutContext); + + saveProductionAssembly(reqBean, productionProcessContext, cellEquipContext, mesProdRuleContext, productionPsOutContext); + + } + + //保存上下文产出条码数据信息集合 + productionDispatchContextStepService.dispatchProductionPsOutContext(reqBean, productionPsOutContextList); + + } else { + + if (CollectionUtils.isEmpty(prodRuleContextList)) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), "当前不存在加工规则信息,请重置工序解决!"); + + //保存零件条码信息工步 + ((IStepService) SpringContextsUtil.getBean("mesProductSnSaveStepService")).executeInState(reqBean); + for (MesProductionPartContext mesProductionPartContext : productionPartContextList) { + + Map productionPsOutContextMap = productionPsOutContextList.stream().collect(Collectors.toMap(MesProductionPsOutContext::getPartNo, Function.identity(), (x, y) -> y)); + + MesPart part = partDataContext.get(mesProductionPartContext.getPartNo()); + + if (part == null) + stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), String.format("产出零件号[%s]不存在,请重置工序解决!", part.getPartNo())); + + MesProductionPsOutContext productionPsOutContext = productionPsOutContextMap.get(part.getPartNo()); + + if (productionPsOutContext == null) + stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), String.format("产出零件号[%s]不存在,请重置工序解决!", part.getPartNo())); + + MesProdRuleContext mesProdRuleContext = prodRuleContextMapByOutPartNo.get(part.getPartNo()); + + saveProductionAssembly(reqBean, productionProcessContext, cellEquipContext, mesProdRuleContext, productionPsOutContext); + } + + } + + //生成加工记录工步 + ((IStepService) SpringContextsUtil.getBean("mesProductionRecordGenerateStepService")).executeInState(reqBean); + + // 是否修改工单状态为完成 + String cutOrderOrderIsComplete = wcpcMap.containsKey(MesPcnExtConstWords.CUT_ORDER_ORDER_IS_COMPLETE) ? wcpcMap.get(MesPcnExtConstWords.CUT_ORDER_ORDER_IS_COMPLETE) : null; + + if (!StringUtils.isEmpty(cutOrderOrderIsComplete)) { + + updateWorkOrderCutStatus(reqBean, cutWorkOrderNo, MesExtEnumUtil.CUT_ORDER_STATUS.COMPLETE.getValue()); + + } else { + + updateWorkOrderCutStatus(reqBean, cutWorkOrderNo, MesExtEnumUtil.CUT_ORDER_STATUS.PROCESS.getValue()); + + } + + //保存装配记录工步 + //((IStepService) SpringContextsUtil.getBean("mesAssemblySaveStepService")).executeInState(reqBean); + + //保存工单信息工步 + ((IStepService) SpringContextsUtil.getBean("mesWorkOrderSaveStepService")).executeInState(reqBean); + + return stepSuccessCompleteAndSendMsgReturn(reqBean, new StationResultBean().writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), "保存加工结果成功!"); + + } + + private void saveProductionAssembly(StationRequestBean reqBean, MesProductionProcessContext productionProcessContext, + MesCellEquipContext cellEquipContext, MesProdRuleContext mesProdRuleContext, + MesProductionPsOutContext productionPsOutContext) { + + MesProductionAssembly productionAssembly = new MesProductionAssembly(); + + productionAssembly.setAssemblySn(""); + productionAssembly.setDataSource(MesExtEnumUtil.PRODUCTION_ASSEMBLY_DATA_SOURCE.NOSORT.getValue()); + productionAssembly.setIsOrigSn(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()); + productionAssembly.setIsSkip(CommonEnumUtil.FALSE); + + productionAssembly.setAreaCode(reqBean.getWorkCenterCode()); + productionAssembly.setWorkCenterCode(reqBean.getWorkCenterCode()); + productionAssembly.setWorkCellCode(reqBean.getWorkCellCode()); + productionAssembly.setProcessCode(reqBean.getProcessCode()); + + productionAssembly.setProcessName(productionProcessContext.getProcessName()); + productionAssembly.setCraftCode(productionProcessContext.getCraftCode()); + productionAssembly.setCraftName(productionProcessContext.getCraftName()); + + productionAssembly.setEquipmentCode(cellEquipContext.getEquipmentCode()); + + productionAssembly.setProductionRecordId(mesProdRuleContext.getProductionRecordId()); + productionAssembly.setMouldNo(mesProdRuleContext.getMouldNo()); + + if (null != productionPsOutContext) { + productionAssembly.setPartNo(productionPsOutContext.getPartNo()); + productionAssembly.setPartName(productionPsOutContext.getPartName()); + productionAssembly.setSerialNumber(productionPsOutContext.getSerialNumber()); + productionAssembly.setProductSn(productionPsOutContext.getProductSn()); + productionAssembly.setCustSn(productionPsOutContext.getCustSn()); + } + + MesScanMonitorContext scanMonitorContext = productionProcessContextStepService.dispatchScanMonitorContext(reqBean, true); + if (null != scanMonitorContext) productionAssembly.setMouldRecordId(scanMonitorContext.getMouldRecordId()); + + productionAssembly.setOrganizeCode(reqBean.getOrganizeCode()); + ConvertBean.serviceModelInitialize(productionAssembly, reqBean.getUserInfo()); + + productionAssembly.setFid(UUID.randomUUID().toString()); + + productionAssemblyRepository.insert(productionAssembly); + } + + private void updateWorkOrderCutStatus(StationRequestBean reqBean, String cutWorkOrderNo, Integer status) { + DdlPackBean packBean = DdlPackBean.getDdlPackBean(reqBean.getOrganizeCode()); + DdlPreparedPack.getStringEqualPack(cutWorkOrderNo, MesPcnExtConstWords.CUT_WORK_ORDER_NO, packBean); + workOrderCutRepository.updateByProperties(new String[]{MesPcnExtConstWords.MODIFY_USER, MesPcnExtConstWords.MODIFY_DATE_TIME, MesPcnExtConstWords.WORK_ORDER_STATUS}, + new Object[]{reqBean.getUserInfo(), TimeTool.getNowTime(true), status}, + packBean); + } + + private String doGenerateSerialNo(StationRequestBean reqBean, StationResultBean resultBean, String ruleCode, MesPart part) { + try { + return syncFuncService.syncSerialNo( + new GenSerialNoModel(ruleCode).prodLocation(reqBean.getWorkCenterCode()).partNo(part.getPartNo()).putDataMap(MesPart.class.getSimpleName(), part).organizeCode(reqBean.getOrganizeCode()), + reqBean.getUserInfo(), reqBean.getOrganizeCode(), 1).getResultList().get(0).toString(); + } catch (ImppBusiException e) { + stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), e.getErrorDetail()); + } catch (Exception e) { + String webMsg = String.format("零件编码[%s]编码规则代码[%s]生成零件条码%s", part.getPartNo(), ruleCode, fsmRouteDataService.handleFsmCfgOrDefault(reqBean, MesPcnEnumUtil.FSM_CFG.FSM_EXCEPTION_MSG.getCode())); + this.sendMessage(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.ERROR.getValue()), webMsg, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT); + this.cacheException(reqBean, reqBean.getStepName(), webMsg, e, true); + foundExThrowNoShowMsg(); + } + return null; + } + +} diff --git a/modules/i3plus-ext-mes-pcn-apiservice/src/main/java/cn/estsh/i3plus/ext/mes/pcn/apiservice/serviceimpl/step/MesWorkOrderCutScanStepService.java b/modules/i3plus-ext-mes-pcn-apiservice/src/main/java/cn/estsh/i3plus/ext/mes/pcn/apiservice/serviceimpl/step/MesWorkOrderCutScanStepService.java index f4bdb76..9ec90fc 100644 --- a/modules/i3plus-ext-mes-pcn-apiservice/src/main/java/cn/estsh/i3plus/ext/mes/pcn/apiservice/serviceimpl/step/MesWorkOrderCutScanStepService.java +++ b/modules/i3plus-ext-mes-pcn-apiservice/src/main/java/cn/estsh/i3plus/ext/mes/pcn/apiservice/serviceimpl/step/MesWorkOrderCutScanStepService.java @@ -70,15 +70,10 @@ public class MesWorkOrderCutScanStepService extends BaseStepService { //存储生产过程上下文对象 productionProcessContextStepService.dispatchProductionProcessContext(reqBean, productionProcessContext); - //从上下文中取出生产线对象 - MesWorkCenter workCenter = productionProcessContext.getWorkCenter(); - //如果没有扫描信息, 取手选工单信息, 封装扫/读信息:裁片工单信息 - List equipVariableCollectContextList; + List equipVariableCollectContextList = new ArrayList<>(); //优先验证扫描裁片工单 if (!StringUtils.isEmpty(scanInfo)) equipVariableCollectContextList = doHandleScanWorkOrderNoContext(reqBean, stepResult, scanInfo); - //选择裁片工单 - else equipVariableCollectContextList = doHandleScanWorkOrderNoContext(reqBean, stepResult, workCenter); //扫描信息为空 if (CollectionUtils.isEmpty(equipVariableCollectContextList)) stepSendGuideAndThrowEx(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), "请扫描裁片工单!"); diff --git a/modules/i3plus-ext-mes-pcn-pojo/src/main/java/cn/estsh/i3plus/ext/mes/pcn/pojo/context/MesProductionPartContext.java b/modules/i3plus-ext-mes-pcn-pojo/src/main/java/cn/estsh/i3plus/ext/mes/pcn/pojo/context/MesProductionPartContext.java index 1de0a86..2df798f 100644 --- a/modules/i3plus-ext-mes-pcn-pojo/src/main/java/cn/estsh/i3plus/ext/mes/pcn/pojo/context/MesProductionPartContext.java +++ b/modules/i3plus-ext-mes-pcn-pojo/src/main/java/cn/estsh/i3plus/ext/mes/pcn/pojo/context/MesProductionPartContext.java @@ -111,6 +111,17 @@ public class MesProductionPartContext implements Serializable { @ApiParam("业务验证之后需要清除的数据标志") private Integer busiCheckToDelete = CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(); + // 裁片功能 + @ApiParam("裁片方案代码") + private String cutCode; + + @ApiParam("标包数量") + private Double packageQty; + + @ApiParam("包装条码规则") + private String packageSnRule; + // 裁片功能 + //根据一模多腔赋值 public MesProductionPartContext copyMouldMultiCavity(MesMouldMultiCavity mouldMultiCavity) { BeanUtils.copyProperties(mouldMultiCavity, this, MesPcnExtConstWords.ID); diff --git a/modules/i3plus-ext-mes-pcn-pojo/src/main/java/cn/estsh/i3plus/ext/mes/pcn/pojo/context/MesProductionPsInContext.java b/modules/i3plus-ext-mes-pcn-pojo/src/main/java/cn/estsh/i3plus/ext/mes/pcn/pojo/context/MesProductionPsInContext.java index e88b4d2..7772033 100644 --- a/modules/i3plus-ext-mes-pcn-pojo/src/main/java/cn/estsh/i3plus/ext/mes/pcn/pojo/context/MesProductionPsInContext.java +++ b/modules/i3plus-ext-mes-pcn-pojo/src/main/java/cn/estsh/i3plus/ext/mes/pcn/pojo/context/MesProductionPsInContext.java @@ -86,6 +86,9 @@ public class MesProductionPsInContext implements Serializable { @ApiParam("业务验证之后需要清除的数据标志") private Integer busiCheckToDelete = CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(); + @ApiParam("裁片方案代码") + private String cutCode; + public MesProductionPsInContext() {} public MesProductionPsInContext foreignKey(Integer foreignKey) { @@ -133,4 +136,9 @@ public class MesProductionPsInContext implements Serializable { return this; } + public MesProductionPsInContext cutCode(String cutCode) { + this.cutCode = cutCode; + return this; + } + } diff --git a/modules/i3plus-ext-mes-pcn-pojo/src/main/java/cn/estsh/i3plus/ext/mes/pcn/pojo/model/MesWorkOrderCutDetailModel.java b/modules/i3plus-ext-mes-pcn-pojo/src/main/java/cn/estsh/i3plus/ext/mes/pcn/pojo/model/MesWorkOrderCutDetailModel.java new file mode 100644 index 0000000..a746109 --- /dev/null +++ b/modules/i3plus-ext-mes-pcn-pojo/src/main/java/cn/estsh/i3plus/ext/mes/pcn/pojo/model/MesWorkOrderCutDetailModel.java @@ -0,0 +1,38 @@ +package cn.estsh.i3plus.ext.mes.pcn.pojo.model; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiParam; +import lombok.Data; + +/** + * @Description :裁片工单明细 + * @Reference : + * @Author : jack.jia + * @CreateDate : 2019-04-02 + * @Modify: + **/ +@Data +@Api("裁片工单明细MODEL") +public class MesWorkOrderCutDetailModel { + + @ApiParam("裁片工单号") + private String cutWorkOrderNo; + + @ApiParam("工单号") + private String workOrderNo; + + @ApiParam("物料号") + private String partNo; + + @ApiParam("物料名称") + private String partName; + + @ApiParam("产成数量") + private Double qty; + + @ApiParam("标包数量") + private Double packageQty; + + @ApiParam("包装条码规则") + private String packageSnRule; +} diff --git a/modules/i3plus-ext-mes-pcn-pojo/src/main/java/cn/estsh/i3plus/ext/mes/pcn/pojo/util/MesPcnExtConstWords.java b/modules/i3plus-ext-mes-pcn-pojo/src/main/java/cn/estsh/i3plus/ext/mes/pcn/pojo/util/MesPcnExtConstWords.java index b6bbba7..82515fc 100644 --- a/modules/i3plus-ext-mes-pcn-pojo/src/main/java/cn/estsh/i3plus/ext/mes/pcn/pojo/util/MesPcnExtConstWords.java +++ b/modules/i3plus-ext-mes-pcn-pojo/src/main/java/cn/estsh/i3plus/ext/mes/pcn/pojo/util/MesPcnExtConstWords.java @@ -442,4 +442,7 @@ public class MesPcnExtConstWords { // 裁片方案代码 public static final String CUT_CODE = "cutCode"; + + // 裁片成品列表弹框打印 + public static final String FUNCITON_CUT_ORDER_DIALOG_PRINT = "FUNCTION_CUT_ORDER_DIALOG_PRINT"; }