Merge branch 'uat-temp-wj-chongqingdaqu-prod-temp-rfid' into uat-temp-wj-chongqingdaqu-dev

uat-temp-wj-chongqingdaqu-dev
王杰 3 months ago
commit ae9582d18d

@ -1,8 +1,6 @@
package cn.estsh.i3plus.ext.mes.pcn.api.busi;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesCellEquipContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProdShiftContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionAssemblyContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.*;
import cn.estsh.i3plus.pojo.mes.model.StationKvBean;
import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
@ -103,6 +101,15 @@ public interface IMesProductionCustomContextStepService {
@ApiOperation(value = "删除打包数据")
void removePackageDataContext(StationRequestBean reqBean);
@ApiOperation(value = "获取选择/扫描零件发运组信息上下文")
List<StationKvBean> getFunctionChooseShippingGroupContext(StationRequestBean reqBean);
@ApiOperation(value = "保存选择/扫描零件发运组信息上下文", notes = "[StationKvBean(key=shippingGroupCode, name=零件发运组代码, value=xxx, seq=0), StationKvBean(key=cellMessageSource, name=工位信息来源, value=10, seq=1)]")
Boolean dispatchFunctionChooseShippingGroupContext(StationRequestBean reqBean, List<StationKvBean> resultList);
@ApiOperation(value = "删除选择/扫描零件发运组信息上下文")
void removeFunctionChooseShippingGroupContext(StationRequestBean reqBean);
@ApiOperation(value = "获取排序线工单队列推送锁数据, 返回的值是工位代码")
String getSortQueuePushLockContext(StationRequestBean reqBean, String queuePushId);
@ -115,4 +122,13 @@ public interface IMesProductionCustomContextStepService {
@ApiOperation(value = "删除排序线工单队列推送锁数据")
void removeSortQueuePushLockContext(StationRequestBean reqBean, String queuePushId);
@ApiOperation(value = "获取生产线维度的工单完成数上下文[查询]")
MesWorkOrderCompleteQtyContext getWorkOrderCompleteQtyContext(StationRequestBean reqBean, MesProductionPartContext productionPartContext);
@ApiOperation(value = "根据noCalcOrderQty判断维度处理工单完成数上下文[查询]")
MesWorkOrderCompleteQtyContext dispatchWorkOrderCompleteQtyContext(StationRequestBean reqBean, Boolean noCalcOrderQty, MesProductionPartContext productionPartContext);
@ApiOperation(value = "根据noCalcOrderQty判断维度处理处理工单完成数上下文[保存]")
MesWorkOrderCompleteQtyContext dispatchWorkOrderCompleteQtyContext(StationRequestBean reqBean, Boolean noCalcOrderQty, String workOrderNo, Double calcCompleteQty);
}

@ -28,6 +28,9 @@ public interface IMesProductionDispatchContextStepService {
@ApiOperation(value = "获取上下文加工结果")
String getProductResultContext(StationRequestBean reqBean);
@ApiOperation(value = "获取上下文加工结果")
Integer getProductResultQcContext(StationRequestBean reqBean);
@ApiOperation(value = "保存上下文加工结果", notes = "加工结果:成功/报废/可疑 【写入的值是变量类别代码对应的条码质量状态】【报废/可疑: 在保存逻辑条码时有特殊业务处理】")
Boolean dispatchProductResultContext(StationRequestBean reqBean, String productResult);

@ -167,15 +167,6 @@ public interface IMesProductionProcessContextStepService {
@ApiOperation(value = "获取设备点检上下文对象")
MesEquipSpotCheckContext dispatchEquipSpotCheckContext(StationRequestBean reqBean, String equipmentCode);
@ApiOperation(value = "获取选择/扫描零件发运组信息上下文")
List<StationKvBean> getFunctionChooseShippingGroupContext(StationRequestBean reqBean);
@ApiOperation(value = "保存选择/扫描零件发运组信息上下文", notes = "[StationKvBean(key=shippingGroupCode, name=零件发运组代码, value=xxx, seq=0), StationKvBean(key=cellMessageSource, name=工位信息来源, value=10, seq=1)]")
Boolean dispatchFunctionChooseShippingGroupContext(StationRequestBean reqBean, List<StationKvBean> resultList);
@ApiOperation(value = "删除选择/扫描零件发运组信息上下文")
void removeFunctionChooseShippingGroupContext(StationRequestBean reqBean);
@ApiOperation(value = "处理加工不可用规则")
MesProductionProcessContext dispatchProdRuleIgnoreCfgContext(StationRequestBean reqBean);
@ -194,4 +185,13 @@ public interface IMesProductionProcessContextStepService {
@ApiOperation(value = "处理工位零件打印机配置")
List<MesWorkCellPartPrinterCfg> disPatchWorkCellPartPrinterCfg(StationRequestBean reqBean, Boolean pcNosortPrinterCfg);
@ApiOperation(value = "获取发运RFID生产模式")
String getShippingRfidRouteModeContext(StationRequestBean reqBean);
@ApiOperation(value = "处理发运RFID生产模式")
String disPatchShippingRfidRouteModeContext(StationRequestBean reqBean);
@ApiOperation(value = "处理切换发运RFID生产模式的标志")
Boolean disPatchChooseShippingRfidRouteMode(StationRequestBean reqBean);
}

@ -1,18 +1,36 @@
package cn.estsh.i3plus.ext.mes.pcn.api.busi;
import cn.estsh.i3plus.pojo.mes.bean.MesProdRouteOptParam;
import cn.estsh.i3plus.pojo.mes.bean.seres.MesCimSeresJisRfid;
import cn.estsh.i3plus.pojo.mes.bean.shipping.MesShippingOrderManagement;
import cn.estsh.i3plus.pojo.mes.bean.shipping.MesShippingOrderManagementDetail;
import cn.estsh.i3plus.pojo.mes.bean.shipping.MesShippingQueue;
import io.swagger.annotations.ApiOperation;
import java.util.Map;
import java.util.Optional;
public interface IMesShippingQueueService {
@ApiOperation("根据零件发运组代码查询创建时间正序创建状态的一条发运队列")
MesShippingQueue getShippingQueue(String organizeCode, String shippingGroupCode);
@ApiOperation("根据发运代码查询创建时间正序创建状态的一条发运队列")
MesShippingQueue getShippingQueueByCode(String organizeCode, String shippingCode);
@ApiOperation("根据ID修改发运队列")
void saveShippingQueue(String organizeCode, Long id, String[] propertyName, Object[] propertyValue);
@ApiOperation("根据VIN查询赛力斯RFID信息")
MesCimSeresJisRfid getCimSeresJisRfid(String organizeCode, String vin);
@ApiOperation("根据发运代码查询发运主表")
MesShippingOrderManagement getShipping(String organizeCode, String shippingCode);
@ApiOperation("根据发运主表ID查询发运明细表")
MesShippingOrderManagementDetail getShippingDetail(String organizeCode, Long pid);
@ApiOperation("解析rfidSn")
String getRfidSn(Optional<Map<String, MesProdRouteOptParam>> stepParamMap, String rfid);
}

@ -0,0 +1,28 @@
package cn.estsh.i3plus.ext.mes.pcn.api.job;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrder;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrderCalcQtyRecord;
import cn.estsh.impp.framework.boot.exception.ImppBusiException;
import io.swagger.annotations.ApiOperation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
public interface IMesWorkOrderCalcQtyRestoreDispatchService {
@ApiOperation(value = "查询生产工单计数记录表")
List<MesWorkOrderCalcQtyRecord> getWorkOrderCalcQtyRecordList(String organizeCode, Integer qty);
@ApiOperation(value = "查询工单")
@Transactional(propagation = Propagation.NOT_SUPPORTED)
MesWorkOrder getWorkOrderDb(String organizeCode, Long workOrderId);
@ApiOperation(value = "补录生产工单计数JOB修改数据")
@Transactional(propagation = Propagation.REQUIRES_NEW, noRollbackFor = {ImppBusiException.class, Exception.class})
void doRestoreWorkOrderCalcQty(String organizeCode, MesWorkOrder workOrder, List<MesWorkOrderCalcQtyRecord> value);
@ApiOperation(value = "修改记录状态")
void saveWorkOrderCalcQtyRecord(String organizeCode, List<Long> idList, Integer dealStatus, String remark);
}

@ -0,0 +1,12 @@
package cn.estsh.i3plus.ext.mes.pcn.api.job;
import io.swagger.annotations.ApiOperation;
import java.util.Map;
public interface IMesWorkOrderCalcQtyRestoreService {
@ApiOperation(value = "补录离线生产工单数据JOB")
void doRestoreWorkOrderCalcQty(Map<String, String> paramMap);
}

@ -0,0 +1,77 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.schedulejob;
import cn.estsh.i3plus.ext.mes.pcn.api.job.IMesWorkOrderCalcQtyRestoreService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.impp.framework.boot.init.ApplicationProperties;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;
import java.util.Map;
/**
* @author wangjie
* @Description JOB
* @version 1.0
* @date 2021/2/2 16:44
**/
@Slf4j
@DisallowConcurrentExecution
@Component
@ApiOperation("补录生产工单计数JOB")
public class MesWorkOrderCalcQtyRestoreJob extends BaseMesScheduleJob {
public MesWorkOrderCalcQtyRestoreJob() {
super(MesWorkOrderCalcQtyRestoreJob.class, "补录生产工单计数JOB");
}
@Autowired
private IMesWorkOrderCalcQtyRestoreService workOrderCalcQtyRestoreService;
@Override
public void executeMesJob(JobExecutionContext context, ApplicationProperties applicationProperties) {
String jobParam = this.getJobParam();
if (StringUtils.isEmpty(jobParam)) {
log.info("--- 异常 --- 补录生产工单计数JOB --- 参数为空 ---");
return;
}
Map<String, String> paramMap = JSONObject.parseObject(jobParam, Map.class);
if (CollectionUtils.isEmpty(paramMap) || !paramMap.containsKey(MesPcnExtConstWords.ORGANIZE_CODE)) {
log.info("--- 异常 --- 补录生产工单计数JOB --- 参数未配置:工厂代码[organizeCode] ---");
return;
}
StopWatch stopWatch = new StopWatch();
try {
stopWatch.start();
workOrderCalcQtyRestoreService.doRestoreWorkOrderCalcQty(paramMap);
} catch (Exception e) {
log.info("--- 异常 --- 补录生产工单计数JOB --- ERROR --- {} ---", e.toString());
} finally {
stopWatch.stop();
log.info("补录生产工单计数JOB --- END --- 耗时: {} ms ---", stopWatch.getTotalTimeMillis());
}
}
}

@ -76,7 +76,7 @@ public class ButtonDynamicExtService extends ButtonDynamicService {
MesConfig apiCfg = configService.getMesConfigByCfgCode(MesPcnExtConstWords.AUTO_INIT_WORK_CELL_MODULE_URL, organizeCode);
if (null == configGateWay || StringUtils.isEmpty(configGateWay.getCfgValue())) return false;
if (null == apiCfg || StringUtils.isEmpty(apiCfg.getCfgValue())) return false;
log.info("工厂{}生产线{}工位{}: --- 初始化工位按钮 --- START --- 执行结果:{}", organizeCode, workCenterCode, workCellCode);
log.info("工厂{}生产线{}工位{}: --- 初始化工位按钮 --- START", organizeCode, workCenterCode, workCellCode);
Map<String, String> paramsMap = new HashMap<>();
paramsMap.put(MesPcnExtConstWords.ORGANIZE_CODE, organizeCode);
paramsMap.put(MesPcnExtConstWords.ID, id.toString());

@ -5,8 +5,13 @@ import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.mes.bean.MesProdRouteOptParam;
import cn.estsh.i3plus.pojo.mes.bean.seres.MesCimSeresJisRfid;
import cn.estsh.i3plus.pojo.mes.bean.shipping.MesShippingOrderManagement;
import cn.estsh.i3plus.pojo.mes.bean.shipping.MesShippingOrderManagementDetail;
import cn.estsh.i3plus.pojo.mes.bean.shipping.MesShippingQueue;
import cn.estsh.i3plus.pojo.mes.repository.MesShippingOrderManagementDetailRepository;
import cn.estsh.i3plus.pojo.mes.repository.MesShippingOrderManagementRepository;
import cn.estsh.i3plus.pojo.mes.repository.MesShippingQueueRepository;
import cn.estsh.i3plus.pojo.mes.repository.seres.IMesCimSeresJisRfidRepository;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
@ -15,6 +20,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.Map;
import java.util.Optional;
@Service
@Slf4j
public class MesShippingQueueService implements IMesShippingQueueService {
@ -25,6 +33,12 @@ public class MesShippingQueueService implements IMesShippingQueueService {
@Autowired
private IMesCimSeresJisRfidRepository cimSeresJisRfidRepository;
@Autowired
private MesShippingOrderManagementRepository shippingOrderManagementRepository;
@Autowired
private MesShippingOrderManagementDetailRepository shippingOrderManagementDetailRepository;
@Override
public MesShippingQueue getShippingQueue(String organizeCode, String shippingGroupCode) {
if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(shippingGroupCode)) return null;
@ -36,6 +50,16 @@ public class MesShippingQueueService implements IMesShippingQueueService {
}
@Override
public MesShippingQueue getShippingQueueByCode(String organizeCode, String shippingCode) {
if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(shippingCode)) return null;
DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
DdlPreparedPack.getStringEqualPack(shippingCode, MesPcnExtConstWords.SHIPPING_CODE, packBean);
DdlPreparedPack.getNumEqualPack(MesExtEnumUtil.QUEUE_ORDER_STATUS.CREATE.getValue(), MesPcnExtConstWords.QUEUE_STATUS, packBean);
DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.ASC.getValue()}, new String[]{MesPcnExtConstWords.CREATE_DATE_TIME}, packBean);
return shippingQueueRepository.getByProperty(packBean);
}
@Override
public void saveShippingQueue(String organizeCode, Long id, String[] propertyName, Object[] propertyValue) {
if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(id)) return;
shippingQueueRepository.updateByPropertiesNoSync(new String[]{MesPcnExtConstWords.ID, MesPcnExtConstWords.ORGANIZE_CODE}, new Object[]{id, organizeCode}, propertyName, propertyValue);
@ -48,4 +72,46 @@ public class MesShippingQueueService implements IMesShippingQueueService {
new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.VIN, MesPcnExtConstWords.STATUS},
new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), vin, CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()});
}
@Override
public MesShippingOrderManagement getShipping(String organizeCode, String shippingCode) {
if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(shippingCode)) return null;
return shippingOrderManagementRepository.getByProperty(
new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.SHIPPING_CODE},
new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), shippingCode});
}
@Override
public MesShippingOrderManagementDetail getShippingDetail(String organizeCode, Long pid) {
if (StringUtils.isEmpty(organizeCode) || StringUtils.isEmpty(pid)) return null;
return shippingOrderManagementDetailRepository.getByProperty(
new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.PID},
new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), pid});
}
/**
* ################## 18
* 3263 4
* 1 -VIN 1
* 2 ,0,1;2 1
* JSG1DJ05 LMS 8
* : 9632
*/
//解析rfidSn
@Override
public String getRfidSn(Optional<Map<String, MesProdRouteOptParam>> stepParamMap, String rfid) {
//replaceIndex=替换起始位置; replaceLength=替换长度; replaceInfo=替换信息
String replaceIndex = (null != stepParamMap && stepParamMap.isPresent() && stepParamMap.get().containsKey(MesPcnExtConstWords.REPLACE_INDEX)) ? stepParamMap.get().get(MesPcnExtConstWords.REPLACE_INDEX).getParamValue() : null;
String replaceLength = (null != stepParamMap && stepParamMap.isPresent() && stepParamMap.get().containsKey(MesPcnExtConstWords.REPLACE_LENGTH)) ? stepParamMap.get().get(MesPcnExtConstWords.REPLACE_LENGTH).getParamValue() : null;
String replaceInfo = (null != stepParamMap && stepParamMap.isPresent() && stepParamMap.get().containsKey(MesPcnExtConstWords.REPLACE_INFO)) ? stepParamMap.get().get(MesPcnExtConstWords.REPLACE_INFO).getParamValue() : null;
if (StringUtils.isEmpty(replaceIndex)) replaceIndex = "96";
if (StringUtils.isEmpty(replaceLength)) replaceLength = "32";
if (StringUtils.isEmpty(replaceInfo)) replaceInfo = "##################326312JSG1DJ05";
try {
return new StringBuilder().append(rfid, MesPcnExtConstWords.ZERO, Integer.parseInt(replaceIndex)).append(replaceInfo).append(rfid, Integer.parseInt(replaceIndex) + Integer.parseInt(replaceLength), rfid.length()).toString();
} catch (Exception e) {
return null;
}
}
}

@ -0,0 +1,188 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.job;
import cn.estsh.i3plus.ext.mes.pcn.api.job.IMesWorkOrderCalcQtyRestoreDispatchService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrder;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrderCalcQtyRecord;
import cn.estsh.i3plus.pojo.mes.repository.MesWorkOrderCalcQtyRecordRepository;
import cn.estsh.i3plus.pojo.mes.repository.MesWorkOrderRepository;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
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.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@Service
public class MesWorkOrderCalcQtyRestoreDispatchService implements IMesWorkOrderCalcQtyRestoreDispatchService {
@Autowired
private MesWorkOrderCalcQtyRecordRepository workOrderCalcQtyRecordRepository;
@Autowired
private MesWorkOrderRepository workOrderRepository;
@Override
public List<MesWorkOrderCalcQtyRecord> getWorkOrderCalcQtyRecordList(String organizeCode, Integer qty) {
DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
DdlPreparedPack.getNumEqualPack(MesExtEnumUtil.MES_LOG_DEAL_STATUS.UNDEAL.getValue(), MesPcnExtConstWords.DEAL_STATUS, packBean);
DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.ASC.getValue()}, new String[]{MesPcnExtConstWords.CREATE_DATE_TIME}, packBean);
return workOrderCalcQtyRecordRepository.findByHqlTopWhere(packBean, qty);
}
@Override
public MesWorkOrder getWorkOrderDb(String organizeCode, Long workOrderId) {
return workOrderRepository.getByProperty(
new String[]{MesPcnExtConstWords.ORGANIZE_CODE, MesPcnExtConstWords.IS_DELETED, MesPcnExtConstWords.IS_VALID, MesPcnExtConstWords.ID},
new Object[]{organizeCode, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), CommonEnumUtil.IS_VAILD.VAILD.getValue(), workOrderId});
}
@Override
public void doRestoreWorkOrderCalcQty(String organizeCode, MesWorkOrder workOrder, List<MesWorkOrderCalcQtyRecord> workOrderCalcQtyRecordList) {
//搜集记录ID集合
List<Long> idList = workOrderCalcQtyRecordList.stream().filter(o -> null != o).map(MesWorkOrderCalcQtyRecord::getId).collect(Collectors.toList());
if (null == workOrder) {
//修改记录状态
saveWorkOrderCalcQtyRecord(organizeCode, idList, MesExtEnumUtil.MES_LOG_DEAL_STATUS.DEAL_FAILURE.getValue(), "工单信息不存在");
log.info("补录生产工单计数JOB --- 补录: {} --- ID: {} --- END --- {} {} --- MesWorkOrderCalcQtyRecord: {} ---",
workOrderCalcQtyRecordList.get(0).getWorkOrderNo(), workOrderCalcQtyRecordList.get(0).getId(), MesExtEnumUtil.MES_LOG_DEAL_STATUS.DEAL_FAILURE.getDescription(), "工单信息不存在", idList.toString());
return;
}
//计数
Double completeQty = !StringUtils.isEmpty(workOrder.getCompleteQty()) ? workOrder.getCompleteQty() : new Double(MesPcnExtConstWords.ZERO);
Double suspiciousPartQty = !StringUtils.isEmpty(workOrder.getSuspiciousPartQty()) ? workOrder.getSuspiciousPartQty() : new Double(MesPcnExtConstWords.ZERO);
Double scrapPartQty = !StringUtils.isEmpty(workOrder.getScrapPartQty()) ? workOrder.getScrapPartQty() : new Double(MesPcnExtConstWords.ZERO);
for (MesWorkOrderCalcQtyRecord workOrderCalcQtyRecord : workOrderCalcQtyRecordList) {
if (null == workOrderCalcQtyRecord) continue;
if (!StringUtils.isEmpty(workOrderCalcQtyRecord.getCompleteQty())) completeQty = MathOperation.add(completeQty, workOrderCalcQtyRecord.getCompleteQty());
if (!StringUtils.isEmpty(workOrderCalcQtyRecord.getSuspiciousPartQty())) suspiciousPartQty = MathOperation.add(suspiciousPartQty, workOrderCalcQtyRecord.getSuspiciousPartQty());
if (!StringUtils.isEmpty(workOrderCalcQtyRecord.getScrapPartQty())) scrapPartQty = MathOperation.add(scrapPartQty, workOrderCalcQtyRecord.getScrapPartQty());
}
//未完成数
Double unCompleteQty = !StringUtils.isEmpty(workOrder.getUnCompleteQty()) ? workOrder.getUnCompleteQty() : workOrder.getQty();
unCompleteQty = MathOperation.compareTo(unCompleteQty, new Double(MesPcnExtConstWords.ZERO)) <= MesPcnExtConstWords.ZERO ? new Double(MesPcnExtConstWords.ZERO) : MathOperation.sub(workOrder.getQty(), completeQty);
if (MathOperation.compareTo(unCompleteQty, new Double(MesPcnExtConstWords.ZERO)) < MesPcnExtConstWords.ZERO) unCompleteQty = new Double(MesPcnExtConstWords.ZERO);
//状态
Integer workOrderStatus = workOrder.getWorkOrderStatus();
if (workOrderStatus.compareTo(MesExtEnumUtil.ORDER_STATUS.RELEASE.getValue()) == MesPcnExtConstWords.ZERO || workOrderStatus.compareTo(MesExtEnumUtil.ORDER_STATUS.PROCESS.getValue()) == MesPcnExtConstWords.ZERO) {
if (MathOperation.compareTo(completeQty, workOrder.getQty()) >= MesPcnExtConstWords.ZERO) workOrderStatus = MesExtEnumUtil.ORDER_STATUS.COMPLETE.getValue();
else workOrderStatus = MesExtEnumUtil.ORDER_STATUS.PROCESS.getValue();
}
//添加修改属性
Map<String, Object> propertyMap = new HashMap<>();
Map<String, Object> conditionMap = new HashMap<>();
conditionMap.put(MesPcnExtConstWords.ID, workOrder.getId());
conditionMap.put(MesPcnExtConstWords.ORGANIZE_CODE, organizeCode);
conditionMap.put(MesPcnExtConstWords.IS_DELETED, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
conditionMap.put(MesPcnExtConstWords.IS_VALID, CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue());
if (MathOperation.compareTo(workOrder.getCompleteQty(), completeQty) != MesPcnExtConstWords.ZERO) {
propertyMap.put(MesPcnExtConstWords.COMPLETE_QTY, completeQty);
conditionMap.put(MesPcnExtConstWords.COMPLETE_QTY, workOrder.getCompleteQty());
}
if (MathOperation.compareTo(workOrder.getSuspiciousPartQty(), suspiciousPartQty) != MesPcnExtConstWords.ZERO) {
propertyMap.put(MesPcnExtConstWords.SUSPICIOUS_PART_QTY, suspiciousPartQty);
conditionMap.put(MesPcnExtConstWords.SUSPICIOUS_PART_QTY, workOrder.getSuspiciousPartQty());
}
if (MathOperation.compareTo(workOrder.getScrapPartQty(), scrapPartQty) != MesPcnExtConstWords.ZERO) {
propertyMap.put(MesPcnExtConstWords.SCRAP_PART_QTY, scrapPartQty);
conditionMap.put(MesPcnExtConstWords.SCRAP_PART_QTY, workOrder.getScrapPartQty());
}
if (MathOperation.compareTo(workOrder.getUnCompleteQty(), unCompleteQty) != MesPcnExtConstWords.ZERO) {
propertyMap.put(MesPcnExtConstWords.UN_COMPLETE_QTY, unCompleteQty);
conditionMap.put(MesPcnExtConstWords.UN_COMPLETE_QTY, workOrder.getUnCompleteQty());
}
if (workOrder.getWorkOrderStatus().compareTo(workOrderStatus) != MesPcnExtConstWords.ZERO) {
propertyMap.put(MesPcnExtConstWords.WORK_ORDER_STATUS, workOrderStatus);
conditionMap.put(MesPcnExtConstWords.WORK_ORDER_STATUS, workOrder.getWorkOrderStatus());
}
//当前没有任何修改
if (CollectionUtils.isEmpty(propertyMap)) {
//修改记录状态
saveWorkOrderCalcQtyRecord(organizeCode, idList, MesExtEnumUtil.MES_LOG_DEAL_STATUS.DEAL_SUCCESS.getValue(), "工单信息无变更");
log.info("补录生产工单计数JOB --- 补录: {} --- ID: {} --- END --- {} {} --- MesWorkOrderCalcQtyRecord: {} ---",
workOrder.getWorkOrderNo(), workOrder.getId(), MesExtEnumUtil.MES_LOG_DEAL_STATUS.DEAL_SUCCESS.getDescription(), "工单信息无变更", idList.toString());
return;
}
//添加常规字段判断是否需要修改
if (workOrder.getSystemSyncStatus().compareTo(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) != 0) {
propertyMap.put(MesPcnExtConstWords.SYSTEM_SYNC_STATUS, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
conditionMap.put(MesPcnExtConstWords.SYSTEM_SYNC_STATUS, workOrder.getSystemSyncStatus());
}
if (!workOrder.getSystemSyncDatetime().equals(MesPcnExtConstWords.EMPTY)) propertyMap.put(MesPcnExtConstWords.SYSTEM_SYNC_DATE_TIME, MesPcnExtConstWords.EMPTY);
String userInfo = workOrderCalcQtyRecordList.get(workOrderCalcQtyRecordList.size() - MesPcnExtConstWords.ONE).getCreateUser();
if (!workOrder.getModifyUser().equals(userInfo)) propertyMap.put(MesPcnExtConstWords.MODIFY_USER, userInfo);
propertyMap.put(MesPcnExtConstWords.MODIFY_DATE_TIME, (new SimpleDateFormat(MesPcnExtConstWords.DATE_FORMAT_SSS)).format(new Date()));
conditionMap.put(MesPcnExtConstWords.MODIFY_DATE_TIME, workOrder.getModifyDatetime());
//修改值
String[] propertyName = new String[propertyMap.size()];
Object[] propertyValue = new Object[propertyMap.size()];
Integer index = 0;
for (Map.Entry<String, Object> innerEntry : propertyMap.entrySet()) {
if (null == innerEntry) continue;
propertyName[index] = innerEntry.getKey();
propertyValue[index] = innerEntry.getValue();
index ++;
}
//修改条件
String[] conditionName = new String[conditionMap.size()];
Object[] conditionValue = new Object[conditionMap.size()];
index = 0;
for (Map.Entry<String, Object> innerEntry : conditionMap.entrySet()) {
if (null == innerEntry) continue;
conditionName[index] = innerEntry.getKey();
conditionValue[index] = innerEntry.getValue();
index ++;
}
//当工单修改成功后, 再修改记录状态
if (workOrderRepository.updateByPropertiesNoSync(conditionName, conditionValue, propertyName, propertyValue) == 1) {
//修改记录状态
saveWorkOrderCalcQtyRecord(organizeCode, idList, MesExtEnumUtil.MES_LOG_DEAL_STATUS.DEAL_SUCCESS.getValue(), "工单信息已变更成功");
log.info("补录生产工单计数JOB --- 补录: {} --- ID: {} --- END --- conditionMap: {} --- propertyMap: {} --- {} {} --- MesWorkOrderCalcQtyRecord: {} ---",
workOrder.getWorkOrderNo(), workOrder.getId(), JSONObject.toJSONString(conditionMap), JSONObject.toJSONString(propertyMap),
MesExtEnumUtil.MES_LOG_DEAL_STATUS.DEAL_SUCCESS.getDescription(), "工单信息已变更成功", idList.toString());
}
}
//修改记录状态
@Override
public void saveWorkOrderCalcQtyRecord(String organizeCode, List<Long> idList, Integer dealStatus, String remark) {
String[] propertyName = new String[]{MesPcnExtConstWords.DEAL_STATUS, MesPcnExtConstWords.MODIFY_USER,
MesPcnExtConstWords.MODIFY_DATE_TIME, MesPcnExtConstWords.SYSTEM_SYNC_STATUS, MesPcnExtConstWords.REMARK};
Object[] propertyValue = new Object[]{dealStatus, MesPcnExtConstWords.JOB,
(new SimpleDateFormat(MesPcnExtConstWords.DATE_FORMAT_SSS)).format(new Date()), CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue(), remark};
DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
DdlPreparedPack.getInPackList(idList, MesPcnExtConstWords.ID, packBean);
workOrderCalcQtyRecordRepository.updateByPropertiesNoSync(propertyName, propertyValue, packBean);
}
}

@ -0,0 +1,65 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.job;
import cn.estsh.i3plus.ext.mes.pcn.api.job.IMesWorkOrderCalcQtyRestoreDispatchService;
import cn.estsh.i3plus.ext.mes.pcn.api.job.IMesWorkOrderCalcQtyRestoreService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrder;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrderCalcQtyRecord;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@Service
public class MesWorkOrderCalcQtyRestoreService implements IMesWorkOrderCalcQtyRestoreService {
@Autowired
private IMesWorkOrderCalcQtyRestoreDispatchService workOrderCalcQtyRestoreDispatchService;
@Override
public void doRestoreWorkOrderCalcQty(Map<String, String> paramMap) {
//参数 工厂
String organizeCode = paramMap.get(MesPcnExtConstWords.ORGANIZE_CODE);
//参数 处理数据量
Integer qty = paramMap.containsKey(MesPcnExtConstWords.QTY) ? Integer.valueOf(paramMap.get(MesPcnExtConstWords.QTY)) : MesPcnExtConstWords.ONE_HUNDRED;
//生产工单计数记录表
List<MesWorkOrderCalcQtyRecord> workOrderCalcQtyRecordList = workOrderCalcQtyRestoreDispatchService.getWorkOrderCalcQtyRecordList(organizeCode, qty);
Map<String, List<MesWorkOrderCalcQtyRecord>> workOrderNoMap = CollectionUtils.isEmpty(workOrderCalcQtyRecordList) ? null :
workOrderCalcQtyRecordList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesWorkOrderCalcQtyRecord::getWorkOrderNo));
log.info("补录生产工单计数JOB --- 查询到未补录完成的记录 {} 条 --- 生产工单包含: {} ---",
CollectionUtils.isEmpty(workOrderCalcQtyRecordList) ? "[]" : workOrderCalcQtyRecordList.size(),
CollectionUtils.isEmpty(workOrderNoMap) ? "[]" : workOrderNoMap.keySet().toString());
if (CollectionUtils.isEmpty(workOrderNoMap)) return;
for (Map.Entry<String, List<MesWorkOrderCalcQtyRecord>> entry : workOrderNoMap.entrySet()) {
if (null == entry) continue;
//查询工单, 无事务查询
MesWorkOrder workOrder = workOrderCalcQtyRestoreDispatchService.getWorkOrderDb(organizeCode, entry.getValue().get(0).getPid());
if (null == workOrder) log.info("补录生产工单计数JOB --- 补录: {} --- ID: {} --- START --- 信息不存在 ---", entry.getKey(), entry.getValue().get(0).getPid());
else log.info("补录生产工单计数JOB --- 补录: {} --- ID: {} --- START ---", entry.getKey(), entry.getValue().get(0).getPid());
try {
workOrderCalcQtyRestoreDispatchService.doRestoreWorkOrderCalcQty(organizeCode, workOrder, entry.getValue());
} catch (Exception e) {
log.info("补录生产工单计数JOB --- 补录: {} --- ID: {} --- EXCEPTION: {} ---", entry.getKey(), entry.getValue().get(0).getPid(), e.toString());
}
}
}
}

@ -14,6 +14,7 @@ import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
@ -165,4 +166,41 @@ public class MesTimeEfficientCfgMatchService implements IMesTimeEfficientCfgMatc
return true;
}
public static void main(String[] args) {
try {
Double minValue = 1d;
Double maxValue = 240d;
SimpleDateFormat sdf = new SimpleDateFormat(MesPcnExtConstWords.DATE_FORMAT);
// Date now = new Date();
Date now = sdf.parse("2025-03-21 11:19:06");
Date productDateTime = sdf.parse("2025-03-21 11:15:06");
int minDiff = (int) ((now.getTime() - productDateTime.getTime())/(60 * 1000));
Integer matchRule = 40;
if (MesExtEnumUtil.MATCH_RULE.MATCH_RULE_20.getValue().equals(matchRule)) {
//差值 小于最小时差有效
if (minDiff >= minValue){
System.out.println(false);
}
} else if (MesExtEnumUtil.MATCH_RULE.MATCH_RULE_30.getValue().equals(matchRule)) {
// 差值 大于最大时差有效
if (minDiff <= maxValue){
System.out.println(false);
}
} else if (MesExtEnumUtil.MATCH_RULE.MATCH_RULE_40.getValue().equals(matchRule)) {
// 差值 最大最小时差有效 在 最大值 最小值之间
if (minDiff <= minValue || minDiff >= maxValue){
System.out.println(false);
}
} else if (MesExtEnumUtil.MATCH_RULE.MATCH_RULE_50.getValue().equals(matchRule)) {
// 差值 最大外或最小内有效
if (minDiff >= minValue && minDiff <= maxValue){
System.out.println(false);
}
}
System.out.println("执行完成");
} catch (ParseException e) {
e.printStackTrace();
}
}
}

@ -1,6 +1,7 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.station.function;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesPartShippingGroupService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionCustomContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionProcessContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseSwsService;
@ -28,7 +29,7 @@ import java.util.List;
public class MesFunctionChooseShippingGroupService extends BaseSwsService implements IFsmModuleFunctionService {
@Autowired
private IMesProductionProcessContextStepService productionProcessContextStepService;
private IMesProductionCustomContextStepService productionCustomContextStepService;
@Autowired
private IShippingDispatchService shippingDispatchService;
@ -49,7 +50,7 @@ public class MesFunctionChooseShippingGroupService extends BaseSwsService implem
}
//保存选择的零件发运组信息上下文
productionProcessContextStepService.dispatchFunctionChooseShippingGroupContext(reqBean, resultList);
productionCustomContextStepService.dispatchFunctionChooseShippingGroupContext(reqBean, resultList);
this.sendMessage(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PICK.getValue()).scanInfo(buttonDynamicModel.getFunctionValue()),
String.format("生产线[%s]工位[%s]%s成功,请等待验证!提交信息[%s]", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), buttonDynamicModel.getButtonName(), buttonDynamicModel.getFunctionValue()),

@ -0,0 +1,55 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.station.function;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionProcessContextStepService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseSwsService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.IShippingDispatchService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.function.IFsmModuleFunctionService;
import cn.estsh.i3plus.platform.common.util.MesPcnConstWords;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.model.ButtonDynamicModel;
import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
import cn.estsh.i3plus.pojo.mes.model.StationResultBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
/**
* @Description : RFID
**/
@Service
public class MesFunctionChooseShippingRfidRouteModeService extends BaseSwsService implements IFsmModuleFunctionService {
@Autowired
private IMesProductionProcessContextStepService productionProcessContextStepService;
@Autowired
private IShippingDispatchService shippingDispatchService;
@Override
public Boolean doFunction(StationRequestBean reqBean, StationResultBean resultBean, ButtonDynamicModel buttonDynamicModel) {
//获取发运RFID生产模式
String routeMode = productionProcessContextStepService.getShippingRfidRouteModeContext(reqBean);
//判断是否人工模式
Boolean isManualMode = !StringUtils.isEmpty(routeMode) && routeMode.equals(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValueStr());
//处理切换发运RFID生产模式的标志
productionProcessContextStepService.disPatchChooseShippingRfidRouteMode(reqBean);
this.sendMessage(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PICK.getValue()).scanInfo(buttonDynamicModel.getFunctionValue()),
String.format("生产线[%s]工位[%s]%s:[%s],请等待验证!", reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), buttonDynamicModel.getButtonName(), isManualMode ? "人工 -> 自动" : "自动 -> 人工"),
MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
reqBean.setClientInfo(shippingDispatchService.getActorClientInfo(reqBean));
reqBean.setInterfaceType(MesPcnConstWords.SHIPPING);
reqBean.setBusiType(MesPcnEnumUtil.ACTOR_RECEIVE_STRATEGY.WS_CMD_DO_SCAN.getCode());
reqBean.setForceJumpProcess(true);
shippingDispatchService.sendScanQueueNextExec(reqBean);
return true;
}
}

@ -196,7 +196,7 @@ public class MesAssemblyReadStepService extends BaseStepService {
this.sendMessage(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.READ.getValue()),
String.format("读取到设备[%s]装配件条码的详细JSON内容: %s", cellEquipContext.getEquipmentName(), JSONObject.toJSONString(equipLogDispatchContext)), MesPcnEnumUtil.STATION_BUSI_TYPE.RUNNING_INFO, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT);
return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.READ.getValue()).scanInfo(scanInfo), stepResult, String.format("当前已读取到设备[%s]装配件条码信息[%s]!", cellEquipContext.getEquipmentName(), scanInfo));
return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.READ.getValue()).checkRepeat().scanInfo(scanInfo), stepResult, String.format("当前已读取到设备[%s]装配件条码信息[%s]!", cellEquipContext.getEquipmentName(), scanInfo));
}

@ -86,6 +86,7 @@ public class MesAssemblySaveStepService extends BaseStepService {
if (CollectionUtils.isEmpty(productionPsOutContextList)) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), "当前不存在产出零件条码信息,请重置工序解决!");
//获取上下文工位扫描监控信息
MesScanMonitorContext scanMonitorContext = productionProcessContextStepService.dispatchScanMonitorContext(reqBean, true);
//从上下文中取出工位当前要使用的设备

@ -1,19 +1,18 @@
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.apiservice.serviceimpl.step.method.MesWorkOrderCheckCompleteQtyStepService;
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.serviceimpl.fsm.BaseStepService;
import cn.estsh.i3plus.mes.pcn.util.PojoAttrUtil;
import cn.estsh.i3plus.mes.pcn.util.StringUtil;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesProdRuleIgnoreCfg;
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;
@ -60,6 +59,9 @@ public class MesAssemblyShowNosortStepService extends BaseStepService {
@Autowired
private IFsmCommonService fsmCommonService;
@Autowired
private MesWorkOrderCheckCompleteQtyStepService workOrderCheckCompleteQtyStepService;
@Override
public StepResult execute(StationRequestBean reqBean) {
@ -102,8 +104,12 @@ public class MesAssemblyShowNosortStepService extends BaseStepService {
//封装非排序加工规则
doHandleProdRuleData(reqBean, resultBean, stepResult, workCenter, productionProcessContext, cellEquipContext, prodRuleContextList, productionPartContextList, productionPsInContextList);
//验证加工单完成数量, 验证的前提条件: 每腔均已匹配到加工规则
workOrderCheckCompleteQtyStepService.dispatchWorkOrderCompleteQtyContext(
reqBean, resultBean, stepResult, productionProcessContext, productionPartContextList, productionPsInContextList);
//匹配失败需要清除本次扫描/读取信息
if (!stepResult.isCompleted() && doBusiCheckToDelete(reqBean, stepResult, productionPartContextList, productionPsInContextList))
if (!stepResult.isCompleted() && workOrderCheckCompleteQtyStepService.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) {
@ -193,72 +199,7 @@ public class MesAssemblyShowNosortStepService extends BaseStepService {
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<MesProductionPartContext> productionPartContextList, List<MesProductionPsInContext> productionPsInContextList, MesWorkCenter workCenter, StepResult stepResult, StationResultBean resultBean) {
// 验证超工单
log.info("验证是否超工单begin ->");
//判断是否还存在待匹配的主条码信息, 内部循环匹配成功会标记 foreignKey
Optional<MesProductionPartContext> optional = productionPartContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getWorkOrderNo()))).findFirst();
if (null == optional || !optional.isPresent()) return stepResult;
// 对MesProductionPartContext中的工单号经行分组每个工单可能对应多条数据,筛选掉foreignkey为空的数据
Map<String, List<MesProductionPartContext>> productionPartContextMap = productionPartContextList.stream().filter(productionPartContext -> !StringUtils.isEmpty(productionPartContext.getForeignKey()))
.collect(Collectors.groupingBy(MesProductionPartContext::getWorkOrderNo));
// 获取涉及到的所有工单列表
List<MesWorkOrder> workOrderList = workOrderExtService.getWorkOrderList(reqBean.getOrganizeCode(), new ArrayList<>(productionPartContextMap.keySet()));
// 对工单经行分组
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;
}
@ -452,8 +393,6 @@ public class MesAssemblyShowNosortStepService extends BaseStepService {
productSnStr));
}
// 默认头道才有超工单
validSuperWorkOrder(reqBean, productionPartContextList,productionPsInContextList,workCenter, stepResult, resultBean);
return stepResult;
}
@ -591,22 +530,6 @@ public class MesAssemblyShowNosortStepService extends BaseStepService {
return attrBeanList;
}
//清除本次扫描/读取信息 有进料【只】需要清除进料,否则存在产出零件需要清除产出零件 【只需要清除被标记的数据】
private Boolean doBusiCheckToDelete(StationRequestBean reqBean, StepResult stepResult, List<MesProductionPartContext> productionPartContextList, List<MesProductionPsInContext> 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;
}
}

@ -177,7 +177,7 @@ public class MesProductSnCheckStepService extends BaseStepService {
}
//未知条码, 工序为空, 条码数量等于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()));

@ -5,6 +5,7 @@ import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProduceSnExtService;
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.apiservice.serviceimpl.step.method.MesPartDataMapSaveStepService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step.method.MesWorkOrderCheckCompleteQtyStepService;
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.IFsmRouteDataService;
@ -74,6 +75,9 @@ public class MesProductSnGenerateStepService extends BaseStepService {
@Autowired
private IMesProdShiftRecordService prodShiftRecordService;
@Autowired
private MesWorkOrderCheckCompleteQtyStepService workOrderCheckCompleteQtyStepService;
@Override
public StepResult execute(StationRequestBean reqBean) {
@ -154,9 +158,9 @@ public class MesProductSnGenerateStepService extends BaseStepService {
MesPart part = partDataMap.get(prodRuleContext.getOutPartNo());
//验证进料零件与产出零件是否一致
Boolean isSamePart = isSamePart(productionPsInContext, productionPartContext, prodRuleContext);
//工位是否不累计工单完成
Boolean isCellNoCalcQty = isCellNoCalcQty(workCell.getNoCalcOrderQty());
Boolean isSamePart = workOrderCheckCompleteQtyStepService.isSamePart(productionPsInContext, productionPartContext, prodRuleContext);
//验证是否计
Boolean isCalcCompleteQty = workOrderCheckCompleteQtyStepService.isCalcCompleteQty(isSamePart, productionPsInContext, productionPartContext);
MesProduceSn produceSn;
//进出一致, 不累计工单完成数量 在显示装配件工步中已经验证了 进出一致 进出存在工单则必须一致
@ -222,7 +226,9 @@ public class MesProductSnGenerateStepService extends BaseStepService {
produceSn = produceSnExtService.insert(produceSn);
} else produceSnExtService.updateNoSync(produceSn);
MesProductionPsOutContext productionPsOutContext = new MesProductionPsOutContext().copy(produceSn, prodRuleContext.getForeignKey()).isCalcCompleteQty(isCalcCompleteQty(isCellNoCalcQty, isSamePart, productionPartContext));
//isCalcCompleteQty=true的情况下【工位是否不累计工单完成数noCalcOrderQty=true最终不会实际累加到工单上】【noCalcOrderQty=false代表生产线维度的统计,才会实际累加到工单上】
MesProductionPsOutContext productionPsOutContext = new MesProductionPsOutContext()
.copy(produceSn, prodRuleContext.getForeignKey()).isCalcCompleteQty(isCalcCompleteQty, isSamePart, workCell.getNoCalcOrderQty());
log.info("工厂{}生产线{}工位{}:FSM STATE DISPATCHER --- DO STEP --- {} EXEC --- MesProduceSn:{} --- MesProductionPsOutContext:{}",
reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(),
@ -256,31 +262,4 @@ public class MesProductSnGenerateStepService extends BaseStepService {
return part.getProductMatchRule();
}
//验证进料零件与产出零件是否一致
private Boolean isSamePart(MesProductionPsInContext productionPsInContext, MesProductionPartContext productionPartContext, MesProdRuleContext prodRuleContext) {
if (null == productionPsInContext) return false;
if (StringUtils.isEmpty(productionPsInContext.getPartNo())) return false;
if (null != productionPartContext) {
if (!productionPsInContext.getPartNo().equals(productionPartContext.getPartNo())) return false;
else return true;
} else {
if (!productionPsInContext.getPartNo().equals(prodRuleContext.getOutPartNo())) return false;
else return true;
}
}
//工位是否不累计工单完成数
private Boolean isCellNoCalcQty(Integer noCalcOrderQty) {
return (!StringUtils.isEmpty(noCalcOrderQty) && noCalcOrderQty.compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0) ? true : false;
}
//判断是否累计工单完成数
private Boolean isCalcCompleteQty(Boolean isCellNoCalcQty, Boolean isSamePart, MesProductionPartContext productionPartContext) {
//工位不消耗工单完成数
if (isCellNoCalcQty) return false;
//未选工单场景
if (null == productionPartContext || StringUtils.isEmpty(productionPartContext.getWorkOrderNo())) return false;
return isSamePart ? false : true;
}
}

@ -180,7 +180,7 @@ public class MesProductSnReadStepService extends BaseStepService {
String scanInfo = equipVariableCollectContextList.stream().filter(o -> null != o).map(MesEquipVariableCollectContext::getEquipVariableValue).collect(Collectors.joining(MesPcnExtConstWords.SEMICOLON));
productionCustomContextStepService.sendStepContextMessage(reqBean, scanInfo, MesExtEnumUtil.CELL_MESSAGE_SOURCE.READ);
return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.READ.getValue()).scanInfo(scanInfo), stepResult, String.format("当前已读取到设备[%s]主条码信息[%s]!", cellEquipContext.getEquipmentName(), scanInfo));
return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.READ.getValue()).checkRepeat().scanInfo(scanInfo), stepResult, String.format("当前已读取到设备[%s]主条码信息[%s]!", cellEquipContext.getEquipmentName(), scanInfo));
}

@ -0,0 +1,89 @@
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.apiservice.serviceimpl.step.method.MesWorkOrderCheckCompleteQtyStepService;
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.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.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;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.StringJoiner;
/**
* @Description :
* @Author : wangjie
**/
@Slf4j
@Service("mesProductionDataSaveBeforeLockOrderStepService")
public class MesProductionDataSaveBeforeLockOrderStepService extends BaseStepService {
@Autowired
private IMesProductionProcessContextStepService productionProcessContextStepService;
@Autowired
private IMesProductionDispatchContextStepService productionDispatchContextStepService;
@Autowired
private MesWorkOrderCheckCompleteQtyStepService workOrderCheckCompleteQtyStepService;
@Override
public StepResult execute(StationRequestBean reqBean) {
StationResultBean resultBean = new StationResultBean();
StepResult stepResult = StepResult.getSuccessComplete();
//获取上下文信息: 处理加工不可用规则
MesProductionProcessContext productionProcessContext = productionProcessContextStepService.dispatchProdRuleIgnoreCfgContext(reqBean);
//配置错误 抛出异常
if (!productionProcessContext.getSuccess()) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), productionProcessContext.getMessage());
//存储生产过程上下文对象
productionProcessContextStepService.dispatchProductionProcessContext(reqBean, productionProcessContext);
//获取上下文产出零件数据信息集合
List<MesProductionPartContext> productionPartContextList = productionDispatchContextStepService.getProductionPartContext(reqBean);
//获取上下文进料零件条码信息集合
List<MesProductionPsInContext> productionPsInContextList = productionDispatchContextStepService.getProductionPsInContext(reqBean);
synchronized (new StringJoiner(MesPcnExtConstWords.COLON).add(reqBean.getOrganizeCode()).add(reqBean.getWorkCenterCode()).add(MesPcnExtConstWords.WORK_ORDER_COMPLETE_CONTEXT).toString().intern()) {
//验证加工单完成数量
workOrderCheckCompleteQtyStepService.dispatchWorkOrderCompleteQtyContext(
reqBean, resultBean, stepResult, productionProcessContext, productionPartContextList, productionPsInContextList);
//匹配失败需要清除本次扫描/读取信息
if (!stepResult.isCompleted() && workOrderCheckCompleteQtyStepService.doBusiCheckToDelete(reqBean, stepResult, productionPartContextList, productionPsInContextList))
return stepResult.nextTriggerEvent(MesPcnExtConstWords.NEXT_TRIGGER_EVENT_PART_NO);
//非排序线 保存加工结果工步 execute 方法 使用的是 新事务
stepResult = ((IStepService) SpringContextsUtil.getBean("mesProductionDataSaveStepService")).execute(reqBean);
//保存加工结果事务提交之后, 保存工单计数
if (stepResult.isCompleted() && !StringUtils.isEmpty(stepResult.getStepAfterState())) {
IStepService stepService = ((IStepService) SpringContextsUtil.getBean(stepResult.getStepAfterState()));
stepResult.stepAfterState(null);
stepService.executeStepAfterExecute(reqBean, stepResult);
}
}
return stepResult;
}
}

@ -1,8 +1,10 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionProcessContextStepService;
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.StringUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
import cn.estsh.i3plus.pojo.mes.model.StationResultBean;
@ -53,7 +55,7 @@ public class MesProductionDataSaveStepService extends BaseStepService {
LinkedList<String> stepList = !isSort ? noSortStepList : sortStepList;
for (String stepService : stepList) {
if (StringUtils.isEmpty(stepResult)) continue;
if (StringUtils.isEmpty(stepService)) continue;
StepResult innerStepResult = ((IStepService) SpringContextsUtil.getBean(stepService)).executeInState(reqBean);
if (!StringUtils.isEmpty(innerStepResult.getNextTriggerEvent())) stepResult.nextTriggerEvent(innerStepResult.getNextTriggerEvent());
if (!StringUtils.isEmpty(innerStepResult.getStepAfterState())) stepResult.stepAfterState(innerStepResult.getStepAfterState());
@ -63,5 +65,4 @@ public class MesProductionDataSaveStepService extends BaseStepService {
return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), stepResult, "保存加工结果成功!");
}
}

@ -102,8 +102,13 @@ public class MesProductionRecordGenerateStepService extends BaseStepService {
//获取上下文(头道)模具号
String mouldNo = getMouldNo(reqBean, workCenter, prodRuleContextList);
//获取上下文工位扫描监控信息
MesScanMonitorContext scanMonitorContext = productionProcessContextStepService.dispatchScanMonitorContext(reqBean, true);
//生成加工记录
productionPsOutContextList.stream().filter(o -> null != o).forEach(o -> saveProductionRecordData(reqBean, workCenter, mouldNo, prodRuleContextList, productionProcessContext, o, prMap, cellEquipContext, CollectionUtils.isEmpty(psiMap) ? null : psiMap.get(o.getForeignKey())));
productionPsOutContextList.stream().filter(o -> null != o).forEach(o ->
saveProductionRecordData(reqBean, workCenter, scanMonitorContext, mouldNo, prodRuleContextList, productionProcessContext, o, prMap, cellEquipContext, CollectionUtils.isEmpty(psiMap) ? null : psiMap.get(o.getForeignKey()))
);
//保存上下文产品加工规则信息集合
productionDispatchContextStepService.dispatchProdRuleDataContext(reqBean, prodRuleContextList);
@ -119,8 +124,9 @@ public class MesProductionRecordGenerateStepService extends BaseStepService {
}
private void saveProductionRecordData(StationRequestBean reqBean, MesWorkCenter workCenter, String mouldNo, List<MesProdRuleContext> prodRuleContextList, MesProductionProcessContext productionProcessContext,
MesProductionPsOutContext productionPsOutContext, Map<Integer, MesProdRuleContext> prMap, MesCellEquipContext cellEquipContext, MesProductionPsInContext productionPsInContext) {
private void saveProductionRecordData(StationRequestBean reqBean, MesWorkCenter workCenter, MesScanMonitorContext scanMonitorContext, String mouldNo,
List<MesProdRuleContext> prodRuleContextList, MesProductionProcessContext productionProcessContext, MesProductionPsOutContext productionPsOutContext,
Map<Integer, MesProdRuleContext> prMap, MesCellEquipContext cellEquipContext, MesProductionPsInContext productionPsInContext) {
MesProdRuleContext prodRuleContext = CollectionUtils.isEmpty(prMap) ? null : prMap.get(productionPsOutContext.getForeignKey());
@ -163,7 +169,6 @@ public class MesProductionRecordGenerateStepService extends BaseStepService {
productionRecord.setProcessCode(reqBean.getProcessCode());
productionRecord.setCraftCode(productionProcessContext.getCraftCode());
MesScanMonitorContext scanMonitorContext = productionProcessContextStepService.dispatchScanMonitorContext(reqBean, true);
if (null != scanMonitorContext) {
productionRecord.setMouldRecordId(scanMonitorContext.getMouldRecordId());
productionRecord.setStartDateTime(scanMonitorContext.getStartDateTime());

@ -0,0 +1,135 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionCustomContextStepService;
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.IMesShippingQueueService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesEquipVariableCollectContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionProcessContext;
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.bean.MesProdRouteOptParam;
import cn.estsh.i3plus.pojo.mes.bean.seres.MesCimSeresJisRfid;
import cn.estsh.i3plus.pojo.mes.bean.shipping.MesShippingOrderManagement;
import cn.estsh.i3plus.pojo.mes.bean.shipping.MesShippingOrderManagementDetail;
import cn.estsh.i3plus.pojo.mes.bean.shipping.MesShippingQueue;
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;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
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;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* @Description :
* @Author : wangjie
**/
@Slf4j
@Service("mesShippingCodeScanStepService")
public class MesShippingCodeScanStepService extends BaseStepService {
@Autowired
private IMesProductionProcessContextStepService productionProcessContextStepService;
@Autowired
private IMesProductionDispatchContextStepService productionDispatchContextStepService;
@Autowired
private IMesProductionCustomContextStepService productionCustomContextStepService;
@Autowired
private IMesShippingQueueService shippingQueueService;
@Override
public StepResult execute(StationRequestBean reqBean) {
StationResultBean resultBean = new StationResultBean();
StepResult stepResult;
//获取上下文信息
MesProductionProcessContext productionProcessContext = productionProcessContextStepService.dispatchCurCellEquipment(reqBean);
//配置错误 抛出异常
if (!productionProcessContext.getSuccess()) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), productionProcessContext.getMessage());
//存储生产过程上下文对象
productionProcessContextStepService.dispatchProductionProcessContext(reqBean, productionProcessContext);
//扫描信息置空
String scanInfo = reqBean.resetScanInfo(reqBean.getScanInfo());
//验证发运组信息是否有效
List<StationKvBean> resultList = null;
if (StringUtils.isEmpty(scanInfo)) stepSendGuideAndThrowEx(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), "[人工模式]请扫描发运单号!");
//发送工步内容
productionCustomContextStepService.sendStepContextMessage(reqBean, scanInfo, MesExtEnumUtil.CELL_MESSAGE_SOURCE.SCAN);
//根据发运代码查询创建时间正序创建状态的一条发运队列
MesShippingQueue shippingQueue = shippingQueueService.getShippingQueueByCode(reqBean.getOrganizeCode(), scanInfo);
String vinCode = (null == shippingQueue || StringUtils.isEmpty(shippingQueue.getVin())) ? null : shippingQueue.getVin();
if (StringUtils.isEmpty(vinCode)) {
MesShippingOrderManagement shipping = shippingQueueService.getShipping(reqBean.getOrganizeCode(), scanInfo);
MesShippingOrderManagementDetail shippingDetail = null == shipping ? null : shippingQueueService.getShippingDetail(reqBean.getOrganizeCode(), shipping.getId());
vinCode = null == shippingDetail ? null : shippingDetail.getVin();
}
if (StringUtils.isEmpty(vinCode)) {
this.sendMessage(reqBean, new StationResultBean().writeDbLog().scanInfo(scanInfo), String.format("当前扫描信息发运单号[%s]信息无效!", scanInfo), MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
stepSendGuideAndThrowEx(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), "[人工模式]请扫描发运单号!");
}
//根据VIN查询赛力斯RFID信息
MesCimSeresJisRfid cimSeresJisRfid = shippingQueueService.getCimSeresJisRfid(reqBean.getOrganizeCode(), vinCode);
if (null == cimSeresJisRfid || StringUtils.isEmpty(cimSeresJisRfid.getRfid())) {
this.sendMessage(reqBean, new StationResultBean().writeDbLog().scanInfo(scanInfo), String.format("当前扫描信息发运单号[%s]信息关联的VIN[%s]未查询到有效的赛力斯RFID信息!", scanInfo, vinCode), MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
stepSendGuideAndThrowEx(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), "[人工模式]请扫描发运单号!");
}
//获取工步参数
Optional<Map<String, MesProdRouteOptParam>> stepParamMap = getStepParams(reqBean);
//解析rfidSn
String rfidSn = shippingQueueService.getRfidSn(stepParamMap, cimSeresJisRfid.getRfid());
if (StringUtils.isEmpty(rfidSn)) {
this.sendMessage(reqBean, new StationResultBean().writeDbLog().scanInfo(scanInfo), String.format("当前扫描信息发运单号[%s]信息关联的VIN[%s]查询到的赛力斯RFID[%s]解析错误!", scanInfo, vinCode, cimSeresJisRfid.getRfid()), MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
stepSendGuideAndThrowEx(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), "[人工模式]请扫描发运单号!");
}
List<MesEquipVariableCollectContext> equipVariableCollectContextList = new ArrayList<>();
equipVariableCollectContextList.add(new MesEquipVariableCollectContext(reqBean.getOrganizeCode(), rfidSn, MesExtEnumUtil.CELL_MESSAGE_SOURCE.READ.getValue()));
//保存上下文扫/读信息:主条码
productionDispatchContextStepService.dispatchScanProductSnContext(reqBean, equipVariableCollectContextList);
//主条码验证工步 【非排序】
stepResult = ((IStepService) SpringContextsUtil.getBean("mesProductSnCheckStepService")).executeInState(reqBean);
if (!stepResult.isCompleted()) {
this.sendMessage(reqBean, new StationResultBean().writeDbLog().scanInfo(scanInfo), String.format("当前扫描信息发运单号[%s]信息关联的VIN[%s]查询到的赛力斯RFID[%s]验证错误!", scanInfo, vinCode, cimSeresJisRfid.getRfid()), MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT);
stepSendGuideAndThrowEx(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), "[人工模式]请扫描发运单号!");
}
//保存上下文发运队列信息
if (null != shippingQueue) {
//保存上下文发运队列信息
shippingQueue.setPidStr(cimSeresJisRfid.getId().toString());
shippingQueue.setRfidSn(rfidSn);
productionDispatchContextStepService.dispatchShippingQueueContext(reqBean, shippingQueue);
}
return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, String.format("当前扫描信息发运单号[%s]VIN[%s]已匹配到赛力斯RFID信息[%s]!", scanInfo, vinCode, cimSeresJisRfid.getRfid()));
}
}

@ -8,8 +8,10 @@ import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.station.function.MesFu
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionProcessContext;
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.api.iservice.base.IConfigService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseStepService;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesConfig;
import cn.estsh.i3plus.pojo.mes.bean.shipping.MesShippingQueue;
import cn.estsh.i3plus.pojo.mes.model.StationKvBean;
import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
@ -23,6 +25,7 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.StringJoiner;
import java.util.stream.Collectors;
/**
@ -51,6 +54,9 @@ public class MesShippingQueueFindStepService extends BaseStepService {
@Autowired
private IFsmCommonService fsmCommonService;
@Autowired
private IConfigService configService;
@Override
public StepResult init(StationRequestBean reqBean) {
@ -101,9 +107,21 @@ public class MesShippingQueueFindStepService extends BaseStepService {
}
//扫描的发运组信息无效,获取缓存中的发运组信息
if (CollectionUtils.isEmpty(resultList)) resultList = productionProcessContextStepService.getFunctionChooseShippingGroupContext(reqBean);
if (CollectionUtils.isEmpty(resultList)) {
resultList = productionCustomContextStepService.getFunctionChooseShippingGroupContext(reqBean);
}
//缓存中无发运组信息,获取默认配置的发运组代码
if (CollectionUtils.isEmpty(resultList)) {
scanInfo = getDefaultShippingGroupCodeCfg(reqBean);
//验证扫描的发运组信息是否有效
resultList = functionChooseShippingGroupService.checkShippingGroupIsValid(reqBean.getOrganizeCode(), scanInfo);
}
//扫描的发运组信息有效,保存到上下文
else productionProcessContextStepService.dispatchFunctionChooseShippingGroupContext(reqBean, resultList);
if (!StringUtils.isEmpty(scanInfo) && !CollectionUtils.isEmpty(resultList)) {
productionCustomContextStepService.dispatchFunctionChooseShippingGroupContext(reqBean, resultList);
}
//验证是否存在发运组代码
if (CollectionUtils.isEmpty(resultList)) {
@ -116,6 +134,7 @@ public class MesShippingQueueFindStepService extends BaseStepService {
productionCustomContextStepService.sendStepContextMessage(reqBean, scanInfo, MesExtEnumUtil.CELL_MESSAGE_SOURCE.SCAN);
scanInfo = resultList.stream().filter(o -> (null != o && o.getKey().equals(MesPcnExtConstWords.SHIPPING_GROUP_CODE))).findFirst().get().getValue();
//根据零件发运组代码查询创建时间正序创建状态的一条发运队列
MesShippingQueue shippingQueue = shippingQueueService.getShippingQueue(reqBean.getOrganizeCode(), scanInfo);
if (null == shippingQueue) {
@ -137,4 +156,10 @@ public class MesShippingQueueFindStepService extends BaseStepService {
}
private String getDefaultShippingGroupCodeCfg(StationRequestBean reqBean) {
MesConfig config = configService.getMesConfigByCfgCodeKeyOrg(MesPcnExtConstWords.FUNCTION_CHOOSE_SHIPPING_GROUP,
new StringJoiner(MesPcnExtConstWords.AND).add(reqBean.getWorkCenterCode()).add(reqBean.getWorkCellCode()).toString(), reqBean.getOrganizeCode());
return (null != config && !StringUtils.isEmpty(config.getCfgValue())) ? config.getCfgValue() : null;
}
}

@ -0,0 +1,40 @@
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.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
import cn.estsh.i3plus.pojo.mes.model.StepResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
/**
* @Description :
* @Author : wangjie
**/
@Slf4j
@Service("mesShippingRfidRouteModeCheckStepService")
public class MesShippingRfidRouteModeCheckStepService extends BaseStepService {
@Autowired
private IMesProductionProcessContextStepService productionProcessContextStepService;
@Override
public StepResult execute(StationRequestBean reqBean) {
StepResult stepResult = StepResult.getSuccessComplete();
//获取发运RFID生产模式
String routeMode = productionProcessContextStepService.getShippingRfidRouteModeContext(reqBean);
//判断是否人工模式
Boolean isManualMode = !StringUtils.isEmpty(routeMode) && routeMode.equals(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValueStr());
if (isManualMode) stepResult.isCompleted(false);
return stepResult;
}
}

@ -0,0 +1,55 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionProcessContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionProcessContext;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseStepService;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
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 lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
/**
* @Description :
* @Author : wangjie
**/
@Slf4j
@Service("mesShippingRfidRouteModeLoadStepService")
public class MesShippingRfidRouteModeLoadStepService extends BaseStepService {
@Autowired
private IMesProductionProcessContextStepService productionProcessContextStepService;
@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);
//处理发运RFID生产模式
String routeMode = productionProcessContextStepService.disPatchShippingRfidRouteModeContext(reqBean);
//判断是否人工模式
Boolean isManualMode = !StringUtils.isEmpty(routeMode) && routeMode.equals(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValueStr());
if (isManualMode) resultBean.writeDbLog();
return stepDynamicsCompleteAndSendMsgReturn(reqBean, resultBean, stepResult, isManualMode ? false : true,
MesPcnEnumUtil.STATION_BUSI_TYPE.RUNNING_INFO, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT, String.format("当前生产模式是否人工模式[%s]!", isManualMode));
}
}

@ -67,7 +67,7 @@ public class MesShippingRfidSeresFindStepService extends BaseStepService {
}
//解析rfidSn
String rfidSn = getRfidSn(stepParamMap, cimSeresJisRfid.getRfid());
String rfidSn = shippingQueueService.getRfidSn(stepParamMap, cimSeresJisRfid.getRfid());
if (StringUtils.isEmpty(rfidSn)) {
return stepDynamicsCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog().checkRepeat(), stepResult,
false, MesPcnEnumUtil.STATION_BUSI_TYPE.MESSAGE, MesPcnEnumUtil.STATION_DATA_TYPE.EXP_TEXT,
@ -100,30 +100,6 @@ public class MesShippingRfidSeresFindStepService extends BaseStepService {
}
/**
* ################## 18
* 3263 4
* 1 -VIN 1
* 2 ,0,1;2 1
* JSG1DJ05 LMS 8
* : 9632
*/
//解析rfidSn
private String getRfidSn(Optional<Map<String, MesProdRouteOptParam>> stepParamMap, String rfid) {
//replaceIndex=替换起始位置; replaceLength=替换长度; replaceInfo=替换信息
String replaceIndex = (null != stepParamMap && stepParamMap.isPresent() && stepParamMap.get().containsKey(MesPcnExtConstWords.REPLACE_INDEX)) ? stepParamMap.get().get(MesPcnExtConstWords.REPLACE_INDEX).getParamValue() : null;
String replaceLength = (null != stepParamMap && stepParamMap.isPresent() && stepParamMap.get().containsKey(MesPcnExtConstWords.REPLACE_LENGTH)) ? stepParamMap.get().get(MesPcnExtConstWords.REPLACE_LENGTH).getParamValue() : null;
String replaceInfo = (null != stepParamMap && stepParamMap.isPresent() && stepParamMap.get().containsKey(MesPcnExtConstWords.REPLACE_INFO)) ? stepParamMap.get().get(MesPcnExtConstWords.REPLACE_INFO).getParamValue() : null;
if (StringUtils.isEmpty(replaceIndex)) replaceIndex = "96";
if (StringUtils.isEmpty(replaceLength)) replaceLength = "32";
if (StringUtils.isEmpty(replaceInfo)) replaceInfo = "##################326312JSG1DJ05";
try {
return new StringBuilder().append(rfid, MesPcnExtConstWords.ZERO, Integer.parseInt(replaceIndex)).append(replaceInfo).append(rfid, Integer.parseInt(replaceIndex) + Integer.parseInt(replaceLength), rfid.length()).toString();
} catch (Exception e) {
return null;
}
}
// public static void main(String[] args) {
// String rfid = "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567";
// System.out.println(rfid.length());

@ -1,5 +1,7 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionCustomContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionDispatchContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesCellEquipContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesEquipVariableCollectContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionPartContext;
@ -37,6 +39,9 @@ public class MesWorkOrderCheckNosortStepService extends MesWorkOrderCheckStepSer
@Autowired
private IFsmCommonService fsmCommonService;
@Autowired
private IMesProductionCustomContextStepService productionCustomContextStepService;
@Override
public StepResult execute(StationRequestBean reqBean) {
@ -232,7 +237,7 @@ public class MesWorkOrderCheckNosortStepService extends MesWorkOrderCheckStepSer
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, "零件编码", o.getPartNo()),
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.QTY, "完成数/工单数", new StringJoiner(MesPcnExtConstWords.SLANT_R).add(String.valueOf(productionCustomContextStepService.getWorkOrderCompleteQtyContext(reqBean, 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())));
}

@ -219,7 +219,9 @@ public class MesWorkOrderCheckSortStepService extends MesWorkOrderCheckStepServi
MesProduceSn produceSn = (MesProduceSn) itemMap.get(MesProduceSn.class.getSimpleName());
if ((StringUtils.isEmpty(workCenter.getIsIgnoreQc()) || workCenter.getIsIgnoreQc().compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) != 0) && produceSn.getQcStatus().compareTo(MesExtEnumUtil.PRODUCE_QC_STATUS.SUSPICIOUS.getValue()) >= 0)
return stepResult.isCompleted(false).msg(String.format("请检查工单信息,加工单[%s]质量状态[%s]", workOrderNo, MesExtEnumUtil.PRODUCE_QC_STATUS.valueOfDescription(produceSn.getQcStatus())));
if (MesExtEnumUtil.PRODUCE_SN_STATUS.OFFLINE.getValue() <= produceSn.getSnStatus() || MesExtEnumUtil.PRODUCE_SN_STATUS.UNKNOW.getValue() == produceSn.getSnStatus())
if (StringUtils.isEmpty(cfg) && MesExtEnumUtil.PRODUCE_SN_STATUS.OFFLINE.getValue() <= produceSn.getSnStatus())
return stepResult.isCompleted(false).msg(String.format("请检查工单产品条码信息,产品条码[%s]条码状态[%s]", produceSn.getProductSn(), MesExtEnumUtil.PRODUCE_SN_STATUS.valueOfDescription(produceSn.getSnStatus())));
if (!StringUtils.isEmpty(cfg) && MesExtEnumUtil.PRODUCE_SN_STATUS.OFFLINE.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());

@ -1,24 +1,14 @@
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.mes.pcn.serviceimpl.fsm.BaseStepService;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.IStepService;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.*;
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.util.MesExtEnumUtil;
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;
import java.util.*;
/**
* @Description :
* @Author : wangjie
@ -27,12 +17,6 @@ import java.util.*;
@Service("mesWorkOrderCutSaveStepService")
public class MesWorkOrderCutSaveStepService extends BaseStepService {
@Autowired
private IMesProductionProcessContextStepService productionProcessContextStepService;
@Autowired
private MesProductionAssemblyRepository productionAssemblyRepository;
@Override
public StepResult execute(StationRequestBean reqBean) {
@ -54,48 +38,5 @@ public class MesWorkOrderCutSaveStepService extends BaseStepService {
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.getAreaCode());
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);
}
}

@ -177,7 +177,7 @@ public class MesWorkOrderReadStepService extends BaseStepService {
String scanInfo = equipVariableCollectContextList.stream().filter(o -> null != o).map(MesEquipVariableCollectContext::getEquipVariableValue).collect(Collectors.joining(MesPcnExtConstWords.SEMICOLON));
productionCustomContextStepService.sendStepContextMessage(reqBean, scanInfo, MesExtEnumUtil.CELL_MESSAGE_SOURCE.READ);
return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.READ.getValue()).scanInfo(scanInfo), stepResult, String.format("当前已读取到设备[%s]加工单信息[%s]!", cellEquipContext.getEquipmentName(), scanInfo));
return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.READ.getValue()).checkRepeat().scanInfo(scanInfo), stepResult, String.format("当前已读取到设备[%s]加工单信息[%s]!", cellEquipContext.getEquipmentName(), scanInfo));
}

@ -1,22 +1,21 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionCustomContextStepService;
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.MesProductionPartContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionProcessContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionPsOutContext;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step.method.MesWorkOrderCheckCompleteQtyStepService;
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.StringUtil;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrder;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrderCalcQtyRecord;
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.MesWorkOrderRepository;
import cn.estsh.i3plus.pojo.mes.repository.MesWorkOrderCalcQtyRecordRepository;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
@ -25,9 +24,10 @@ import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import javax.persistence.EntityManager;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
@ -48,13 +48,13 @@ public class MesWorkOrderSaveNosortStepService extends BaseStepService {
private IMesProductionDispatchContextStepService productionDispatchContextStepService;
@Autowired
private IMesWorkOrderExtService workOrderExtService;
private MesWorkOrderCheckCompleteQtyStepService workOrderCheckCompleteQtyStepService;
@Autowired
private MesWorkOrderRepository workOrderRepository;
private MesWorkOrderCalcQtyRecordRepository workOrderCalcQtyRecordRepository;
@Autowired
private EntityManager entityManager;
private IMesProductionCustomContextStepService productionCustomContextStepService;
@Override
public StepResult execute(StationRequestBean reqBean) {
@ -83,22 +83,31 @@ public class MesWorkOrderSaveNosortStepService extends BaseStepService {
List<MesProductionPsOutContext> productionPsOutContextList = productionDispatchContextStepService.getProductionPsOutContext(reqBean);
//保存生产工单数据
doHandleWorkOrderData(reqBean, resultBean, productionPartContextList, productionPsOutContextList);
doHandleWorkOrderData(reqBean, resultBean, stepResult, productionProcessContext, productionPartContextList, productionPsOutContextList);
return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), stepResult, "保存加工单信息成功!");
}
//保存生产工单数据
private void doHandleWorkOrderData(StationRequestBean reqBean, StationResultBean resultBean, List<MesProductionPartContext> productionPartContextList, List<MesProductionPsOutContext> productionPsOutContextList) {
private void doHandleWorkOrderData(StationRequestBean reqBean, StationResultBean resultBean,
StepResult stepResult, MesProductionProcessContext productionProcessContext,
List<MesProductionPartContext> productionPartContextList, List<MesProductionPsOutContext> productionPsOutContextList) {
//工位是否不累计工单完成数
Boolean noCalcOrderQty = workOrderCheckCompleteQtyStepService.noCalcOrderQty(productionProcessContext.getWorkCell().getNoCalcOrderQty());
//获取上下文工位扫描监控信息
MesScanMonitorContext scanMonitorContext = productionProcessContextStepService.dispatchScanMonitorContext(reqBean, true);
//产出零件信息根据生产工单分组
Map<String, List<MesProductionPartContext>> ppMap = productionPartContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getForeignKey()))).collect(Collectors.groupingBy(MesProductionPartContext::getWorkOrderNo));
//产出条码 根据生产工单分组
Map<String, List<MesProductionPsOutContext>> proMap = productionPsOutContextList.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(MesProductionPsOutContext::getWorkOrderNo));
Map<String, List<MesProductionPsOutContext>> proMap = productionPsOutContextList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesProductionPsOutContext::getWorkOrderNo));
String productResult = productionDispatchContextStepService.getProductResultContext(reqBean);
//获取上下文加工结果
Integer productResult = productionDispatchContextStepService.getProductResultQcContext(reqBean);
//遍历产出零件信息
for(Map.Entry<String, List<MesProductionPartContext>> entry : ppMap.entrySet()) {
@ -107,87 +116,101 @@ public class MesWorkOrderSaveNosortStepService extends BaseStepService {
//获取对应的加工规则
List<MesProductionPsOutContext> produceSnContextList = proMap.get(entry.getKey());
//生产数量
Integer calcCompleteQty = 0;
Double calcCompleteQty = new Double(MesPcnExtConstWords.ZERO);
//遍历产出物料
for (MesProductionPsOutContext productionPsOutContext : produceSnContextList) {
if (null == productionPsOutContext) continue;
//产出零件是否是
if (productionPsOutContext.getIsCalcCompleteQty() == CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) calcCompleteQty += 1;
//产出零件需要计算工单完成数量
if (productionPsOutContext.getIsCalcCompleteQty() == CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) calcCompleteQty = MathOperation.add(calcCompleteQty, new Double(MesPcnExtConstWords.ONE));
}
if (calcCompleteQty.compareTo(MesPcnExtConstWords.ZERO) == 0) continue;
if (MathOperation.compareTo(calcCompleteQty, new Double(MesPcnExtConstWords.ZERO)) == 0) continue;
MesWorkOrder workOrder = workOrderExtService.getWorkOrder(reqBean.getOrganizeCode(), entry.getValue().get(0).getId());
// 赋值 stepAfterState, 当前工步集执行结束后会执行当前工步重写的executeStepAfterState方法
if (StringUtils.isEmpty(stepResult.getStepAfterState())) stepResult.stepAfterState(StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()));
if (null == workOrder) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), String.format("请检查工单信息,加工单[%s]信息不存在!", entry.getKey()));
//TODO 排序考虑多工位扫描可疑码; 非排序考虑自进自出可疑或报废; 可疑数/报废数是否需要增加的问题[条码+零件+质量状态 增加履历]
//工单状态分 排序工单 和非排序工单; 现在必须是非排序工单
if (!MesExtEnumUtil.ORDER_STATUS.checkNosortAllowStatus(workOrder.getWorkOrderStatus()))
stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), String.format("请检查工单信息,加工单[%s]信息工单状态[%s]!", entry.getKey(), MesExtEnumUtil.ORDER_STATUS.valueOfDescription(workOrder.getWorkOrderStatus())));
//工单产线要和当前产线一致
if (!workOrder.getWorkCenterCode().equals(reqBean.getWorkCenterCode()))
stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), String.format("请检查工单信息,加工单[%s]信息所属生产线[%s]与当前生产线[%s]不一致!", entry.getKey(), workOrder.getWorkCenterCode(), reqBean.getWorkCenterCode()));
//工位不累计工单完成数
if (noCalcOrderQty) continue;
Map<String, Object> propertyMap = new HashMap<>();
MesWorkOrderCalcQtyRecord workOrderCalcQtyRecord = new MesWorkOrderCalcQtyRecord();
workOrderCalcQtyRecord.setOrganizeCode(reqBean.getOrganizeCode());
workOrderCalcQtyRecord.setWorkCenterCode(reqBean.getWorkCenterCode());
workOrderCalcQtyRecord.setWorkCellCode(reqBean.getWorkCellCode());
workOrderCalcQtyRecord.setWorkOrderNo(entry.getKey());
workOrderCalcQtyRecord.setPid(entry.getValue().get(0).getId());
workOrderCalcQtyRecord.setCompleteQty(calcCompleteQty);
//可疑数量
if (!StringUtils.isEmpty(productResult) && productResult.compareTo(MesExtEnumUtil.PRODUCE_QC_STATUS.SUSPICIOUS.getValue()) == 0) {
workOrderCalcQtyRecord.setSuspiciousPartQty(calcCompleteQty);
}
//报废数量
if (!StringUtils.isEmpty(productResult) && productResult.compareTo(MesExtEnumUtil.PRODUCE_QC_STATUS.SCRAP.getValue()) == 0) {
workOrderCalcQtyRecord.setScrapPartQty(calcCompleteQty);
}
//修改完成数量
propertyMap.put(MesPcnExtConstWords.COMPLETE_QTY, MathOperation.add(workOrder.getCompleteQty(), calcCompleteQty));
if (null != scanMonitorContext) workOrderCalcQtyRecord.setMouldRecordId(scanMonitorContext.getMouldRecordId());
//修改未完成数量
if (workOrder.getUnCompleteQty().compareTo(new Double(0)) > 0 && MathOperation.compareTo(MathOperation.sub(workOrder.getUnCompleteQty(), new Double(calcCompleteQty)), new Double(0)) >= 0) {
propertyMap.put(MesPcnExtConstWords.UN_COMPLETE_QTY, MathOperation.sub(workOrder.getUnCompleteQty(), new Double(calcCompleteQty)));
}
workOrderCalcQtyRecord.setDealStatus(MesExtEnumUtil.MES_LOG_DEAL_STATUS.UNDEAL.getValue());
workOrderCalcQtyRecord.setCreateUser(reqBean.getUserInfo());
workOrderCalcQtyRecord.setModifyUser(reqBean.getUserInfo());
workOrderCalcQtyRecord.setCreateDatetime((new SimpleDateFormat(MesPcnExtConstWords.DATE_FORMAT_SSS)).format(new Date()));
workOrderCalcQtyRecord.setModifyDatetime(workOrderCalcQtyRecord.getCreateDatetime());
workOrderCalcQtyRecord.setIsValid(CommonEnumUtil.IS_VAILD.VAILD.getValue());
workOrderCalcQtyRecord.setIsDeleted(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
/**
* 线
* sql
* busiprodResult
*
*/
if (!StringUtils.isEmpty(productResult)) {
//可疑品
if (Integer.valueOf(productResult).compareTo(MesExtEnumUtil.PRODUCE_QC_STATUS.SUSPICIOUS.getValue()) == 0 && !CollectionUtils.isEmpty(productionPsOutContextList)){
propertyMap.put(MesPcnExtConstWords.SUSPICIOUS_PART_QTY, MathOperation.add(workOrder.getSuspiciousPartQty(), new Double(productionPsOutContextList.size())));
}
//报废数量
if (Integer.valueOf(productResult).compareTo(MesExtEnumUtil.PRODUCE_QC_STATUS.SCRAP.getValue()) == 0 && !CollectionUtils.isEmpty(productionPsOutContextList)){
propertyMap.put(MesPcnExtConstWords.SCRAP_PART_QTY, MathOperation.add(workOrder.getScrapPartQty(), new Double(productionPsOutContextList.size())));
}
}
workOrderCalcQtyRecord = workOrderCalcQtyRecordRepository.insert(workOrderCalcQtyRecord);
if (MathOperation.compareTo(MathOperation.add(workOrder.getCompleteQty(), calcCompleteQty), workOrder.getQty()) >= 0 && workOrder.getWorkOrderStatus().compareTo(MesExtEnumUtil.ORDER_STATUS.COMPLETE.getValue()) != 0) {
propertyMap.put(MesPcnExtConstWords.WORK_ORDER_STATUS, MesExtEnumUtil.ORDER_STATUS.COMPLETE.getValue());
} else if (workOrder.getCompleteQty() >= 0 && workOrder.getWorkOrderStatus() == MesExtEnumUtil.ORDER_STATUS.RELEASE.getValue()) {
propertyMap.put(MesPcnExtConstWords.WORK_ORDER_STATUS, MesExtEnumUtil.ORDER_STATUS.PROCESS.getValue());
}
log.info("工厂{}生产线{}工位{}:FSM STATE DISPATCHER --- DO STEP --- {} EXEC --- ORDER:{} --- productResult:{} --- MesWorkOrderCalcQtyRecord:{}",
reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(),
StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()), entry.getKey(), productResult, JSONObject.toJSONString(workOrderCalcQtyRecord));
}
}
if (CollectionUtils.isEmpty(propertyMap)) continue;
//当前工步集完成之后执行当前方法
@Override
public void executeStepAfterState(StationRequestBean reqBean, StepResult stepResult) {
if (!stepResult.isCompleted()) return;
//获取上下文产出零件数据信息集合
List<MesProductionPsOutContext> productionPsOutContextList = productionDispatchContextStepService.getProductionPsOutContext(reqBean);
if (CollectionUtils.isEmpty(productionPsOutContextList)) return;
propertyMap.put(MesPcnExtConstWords.MODIFY_DATE_TIME, (new SimpleDateFormat(MesPcnExtConstWords.DATE_FORMAT_SSS)).format(new Date()));
propertyMap.put(MesPcnExtConstWords.MODIFY_USER, reqBean.getUserInfo());
propertyMap.put(MesPcnExtConstWords.SYSTEM_SYNC_STATUS, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
propertyMap.put(MesPcnExtConstWords.SYSTEM_SYNC_DATE_TIME, MesPcnExtConstWords.EMPTY);
//工位是否不累计工单完成数
Boolean noCalcOrderQty = workOrderCheckCompleteQtyStepService.noCalcOrderQty(productionPsOutContextList.get(0).getNoCalcOrderQty());
String[] propertyName = new String[propertyMap.size()];
Object[] propertyValue = new Object[propertyMap.size()];
//产出条码 根据生产工单分组
Map<String, List<MesProductionPsOutContext>> proMap = productionPsOutContextList.stream().filter(o -> null != o).collect(Collectors.groupingBy(MesProductionPsOutContext::getWorkOrderNo));
Integer index = 0;
for (Map.Entry<String, Object> innerEntry : propertyMap.entrySet()) {
if (null == innerEntry) continue;
propertyName[index] = innerEntry.getKey();
propertyValue[index] = innerEntry.getValue();
index ++;
//遍历产出物料
for (Map.Entry<String, List<MesProductionPsOutContext>> entry : proMap.entrySet()) {
if (null == entry) continue;
//生产数量
Double calcCompleteQty = new Double(MesPcnExtConstWords.ZERO);
for (MesProductionPsOutContext productionPsOutContext : entry.getValue()) {
if (null == productionPsOutContext) continue;
//产出零件需要计算工单完成数量
if (productionPsOutContext.getIsCalcCompleteQty() == CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) calcCompleteQty = MathOperation.add(calcCompleteQty, new Double(MesPcnExtConstWords.ONE));
}
if (MathOperation.compareTo(calcCompleteQty, new Double(MesPcnExtConstWords.ZERO)) == 0) continue;
workOrderRepository.updateByPropertiesNoSync(new String[]{MesPcnExtConstWords.ID, MesPcnExtConstWords.ORGANIZE_CODE}, new Object[]{workOrder.getId(), reqBean.getOrganizeCode()}, propertyName, propertyValue);
//根据noCalcOrderQty判断维度处理处理工单完成数上下文[保存]
MesWorkOrderCompleteQtyContext workOrderCompleteQtyContext = productionCustomContextStepService.dispatchWorkOrderCompleteQtyContext(reqBean, noCalcOrderQty, entry.getKey(), calcCompleteQty);
log.info("工厂{}生产线{}工位{}:FSM STATE DISPATCHER --- DO STEP --- {} EXEC --- ORDER:{} --- QUERY:{} --- calcCompleteQty:{} --- productResult:{} --- UPDATE:{}",
log.info("工厂{}生产线{}工位{}:FSM STATE DISPATCHER --- DO STEP --- {} EXEC --- ORDER:{} --- noCalcOrderQty:{} --- calcCompleteQty:{} --- MesWorkOrderCompleteQtyContext:{}",
reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(),
StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()), workOrder.getWorkOrderNo(), JSONObject.toJSONString(workOrder), calcCompleteQty, productResult, JSONObject.toJSONString(propertyMap));
StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()), entry.getKey(), noCalcOrderQty, calcCompleteQty, JSONObject.toJSONString(workOrderCompleteQtyContext));
}
}
//执行execute之后根据条件判断是否执行
@Override
public void executeStepAfterExecute(StationRequestBean reqBean, StepResult stepResult) {
executeStepAfterState(reqBean, stepResult);
}
}

@ -0,0 +1,193 @@
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.MesProductionPartContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionProcessContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionPsOutContext;
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.StringUtil;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
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.repository.MesWorkOrderRepository;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
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 javax.persistence.EntityManager;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
/**
* @Description :
* @Reference :
* @Author : wangjie
* @CreateDate : 2024/6/11 18:50
* @Modify:
**/
@Slf4j
@Service("mesWorkOrderSaveNosortStepServiceBak")
public class MesWorkOrderSaveNosortStepServiceBak extends BaseStepService {
@Autowired
private IMesProductionProcessContextStepService productionProcessContextStepService;
@Autowired
private IMesProductionDispatchContextStepService productionDispatchContextStepService;
@Autowired
private IMesWorkOrderExtService workOrderExtService;
@Autowired
private MesWorkOrderRepository workOrderRepository;
@Autowired
private EntityManager entityManager;
@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);
//获取上下文产出零件数据信息集合
List<MesProductionPartContext> productionPartContextList = productionDispatchContextStepService.getProductionPartContext(reqBean);
//没有产出零件或者没有工单
if (CollectionUtils.isEmpty(productionPartContextList) || StringUtils.isEmpty(
productionPartContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getForeignKey()))).findFirst().get().getWorkOrderNo())) return stepResult;
//获取上下文产出零件数据信息集合
List<MesProductionPsOutContext> productionPsOutContextList = productionDispatchContextStepService.getProductionPsOutContext(reqBean);
//保存生产工单数据
doHandleWorkOrderData(reqBean, resultBean, productionPartContextList, productionPsOutContextList);
return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), stepResult, "保存加工单信息成功!");
}
//保存生产工单数据
private void doHandleWorkOrderData(StationRequestBean reqBean, StationResultBean resultBean, List<MesProductionPartContext> productionPartContextList, List<MesProductionPsOutContext> productionPsOutContextList) {
//产出零件信息根据生产工单分组
Map<String, List<MesProductionPartContext>> ppMap = productionPartContextList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getForeignKey()))).collect(Collectors.groupingBy(MesProductionPartContext::getWorkOrderNo));
//产出条码 根据生产工单分组
Map<String, List<MesProductionPsOutContext>> proMap = productionPsOutContextList.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(MesProductionPsOutContext::getWorkOrderNo));
String productResult = productionDispatchContextStepService.getProductResultContext(reqBean);
//遍历产出零件信息
for(Map.Entry<String, List<MesProductionPartContext>> entry : ppMap.entrySet()) {
if (null == entry) continue;
//获取对应的加工规则
List<MesProductionPsOutContext> produceSnContextList = proMap.get(entry.getKey());
//生产数量
Integer calcCompleteQty = 0;
//遍历产出物料
for (MesProductionPsOutContext productionPsOutContext : produceSnContextList) {
if (null == productionPsOutContext) continue;
//产出零件是否是
if (productionPsOutContext.getIsCalcCompleteQty() == CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) calcCompleteQty += 1;
}
if (calcCompleteQty.compareTo(MesPcnExtConstWords.ZERO) == 0) continue;
MesWorkOrder workOrder = workOrderExtService.getWorkOrder(reqBean.getOrganizeCode(), entry.getValue().get(0).getId());
if (null == workOrder) stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), String.format("请检查工单信息,加工单[%s]信息不存在!", entry.getKey()));
//工单状态分 排序工单 和非排序工单; 现在必须是非排序工单
if (!MesExtEnumUtil.ORDER_STATUS.checkNosortAllowStatus(workOrder.getWorkOrderStatus()))
stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), String.format("请检查工单信息,加工单[%s]信息工单状态[%s]!", entry.getKey(), MesExtEnumUtil.ORDER_STATUS.valueOfDescription(workOrder.getWorkOrderStatus())));
//工单产线要和当前产线一致
if (!workOrder.getWorkCenterCode().equals(reqBean.getWorkCenterCode()))
stepExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), String.format("请检查工单信息,加工单[%s]信息所属生产线[%s]与当前生产线[%s]不一致!", entry.getKey(), workOrder.getWorkCenterCode(), reqBean.getWorkCenterCode()));
Map<String, Object> propertyMap = new HashMap<>();
//修改完成数量
propertyMap.put(MesPcnExtConstWords.COMPLETE_QTY, MathOperation.add(workOrder.getCompleteQty(), calcCompleteQty));
//修改未完成数量
if (workOrder.getUnCompleteQty().compareTo(new Double(0)) > 0 && MathOperation.compareTo(MathOperation.sub(workOrder.getUnCompleteQty(), new Double(calcCompleteQty)), new Double(0)) >= 0) {
propertyMap.put(MesPcnExtConstWords.UN_COMPLETE_QTY, MathOperation.sub(workOrder.getUnCompleteQty(), new Double(calcCompleteQty)));
}
/**
* 线
* sql
* busiprodResult
*
*/
if (!StringUtils.isEmpty(productResult)) {
//可疑品
if (Integer.valueOf(productResult).compareTo(MesExtEnumUtil.PRODUCE_QC_STATUS.SUSPICIOUS.getValue()) == 0 && !CollectionUtils.isEmpty(productionPsOutContextList)){
propertyMap.put(MesPcnExtConstWords.SUSPICIOUS_PART_QTY, MathOperation.add(workOrder.getSuspiciousPartQty(), new Double(productionPsOutContextList.size())));
}
//报废数量
if (Integer.valueOf(productResult).compareTo(MesExtEnumUtil.PRODUCE_QC_STATUS.SCRAP.getValue()) == 0 && !CollectionUtils.isEmpty(productionPsOutContextList)){
propertyMap.put(MesPcnExtConstWords.SCRAP_PART_QTY, MathOperation.add(workOrder.getScrapPartQty(), new Double(productionPsOutContextList.size())));
}
}
if (MathOperation.compareTo(MathOperation.add(workOrder.getCompleteQty(), calcCompleteQty), workOrder.getQty()) >= 0 && workOrder.getWorkOrderStatus().compareTo(MesExtEnumUtil.ORDER_STATUS.COMPLETE.getValue()) != 0) {
propertyMap.put(MesPcnExtConstWords.WORK_ORDER_STATUS, MesExtEnumUtil.ORDER_STATUS.COMPLETE.getValue());
} else if (workOrder.getCompleteQty() >= 0 && workOrder.getWorkOrderStatus() == MesExtEnumUtil.ORDER_STATUS.RELEASE.getValue()) {
propertyMap.put(MesPcnExtConstWords.WORK_ORDER_STATUS, MesExtEnumUtil.ORDER_STATUS.PROCESS.getValue());
}
if (CollectionUtils.isEmpty(propertyMap)) continue;
propertyMap.put(MesPcnExtConstWords.MODIFY_DATE_TIME, (new SimpleDateFormat(MesPcnExtConstWords.DATE_FORMAT_SSS)).format(new Date()));
propertyMap.put(MesPcnExtConstWords.MODIFY_USER, reqBean.getUserInfo());
propertyMap.put(MesPcnExtConstWords.SYSTEM_SYNC_STATUS, CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
propertyMap.put(MesPcnExtConstWords.SYSTEM_SYNC_DATE_TIME, MesPcnExtConstWords.EMPTY);
String[] propertyName = new String[propertyMap.size()];
Object[] propertyValue = new Object[propertyMap.size()];
Integer index = 0;
for (Map.Entry<String, Object> innerEntry : propertyMap.entrySet()) {
if (null == innerEntry) continue;
propertyName[index] = innerEntry.getKey();
propertyValue[index] = innerEntry.getValue();
index ++;
}
workOrderRepository.updateByPropertiesNoSync(new String[]{MesPcnExtConstWords.ID, MesPcnExtConstWords.ORGANIZE_CODE}, new Object[]{workOrder.getId(), reqBean.getOrganizeCode()}, propertyName, propertyValue);
log.info("工厂{}生产线{}工位{}:FSM STATE DISPATCHER --- DO STEP --- {} EXEC --- ORDER:{} --- QUERY:{} --- calcCompleteQty:{} --- productResult:{} --- UPDATE:{}",
reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(),
StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()), workOrder.getWorkOrderNo(), JSONObject.toJSONString(workOrder), calcCompleteQty, productResult, JSONObject.toJSONString(propertyMap));
}
}
}

@ -1,12 +1,11 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step.context;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionCustomContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesCellEquipContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProdShiftContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionAssemblyContext;
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.StationKvBeanUtil;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.mes.model.StationKvBean;
@ -295,6 +294,29 @@ public class MesProductionCustomContextStepService extends BaseStepService imple
removeFsmBusiData(reqBean.getOrganizeCode(), getPackageDataContextKey(reqBean));
}
//上个扫描/读取信息KEY
private String getShippingGroupContextKey(StationRequestBean reqBean) { return getFsmBusikey(reqBean, new StringJoiner(MesPcnExtConstWords.COLON).add(MesPcnExtConstWords.PRODUCTION_PROCESS_CONTEXT).add(MesPcnExtConstWords.FUNCTION_CHOOSE_SHIPPING_GROUP).toString()); }
//获取选择/扫描零件发运组信息上下文
@Override
public List<StationKvBean> getFunctionChooseShippingGroupContext(StationRequestBean reqBean) {
String chooseCavityOrderJson = getFsmBusiData(reqBean.getOrganizeCode(), getShippingGroupContextKey(reqBean));
return !StringUtils.isEmpty(chooseCavityOrderJson) ? JSONObject.parseArray(chooseCavityOrderJson, StationKvBean.class) : null;
}
//保存选择/扫描零件发运组信息上下文 腔数=工单个数 数据格式: [StationKvBean(key=shippingGroupCode, name=零件发运组代码, value=xxx, seq=0), StationKvBean(key=cellMessageSource, name=工位信息来源, value=10, seq=1)]
@Override
public Boolean dispatchFunctionChooseShippingGroupContext(StationRequestBean reqBean, List<StationKvBean> resultList) {
if (CollectionUtils.isEmpty(resultList)) return false;
return dispatchFsmBusiData(reqBean.getOrganizeCode(), getShippingGroupContextKey(reqBean), JSONObject.toJSONString(resultList));
}
//删除选择/扫描零件发运组信息上下文
@Override
public void removeFunctionChooseShippingGroupContext(StationRequestBean reqBean) {
removeFsmBusiData(reqBean.getOrganizeCode(), getShippingGroupContextKey(reqBean));
}
//排序线工单队列推送锁数据KEY 【PS:生产线级别】
private String getSortQueuePushLockContextKey(StationRequestBean reqBean) { return new StringJoiner(MesPcnExtConstWords.COLON).add(reqBean.getOrganizeCode()).add(reqBean.getWorkCenterCode()).add(MesPcnExtConstWords.QUEUE_PUSH_LOCK_CONTEXT).toString(); }
@ -327,4 +349,51 @@ public class MesProductionCustomContextStepService extends BaseStepService imple
removeFsmBusiData(reqBean.getOrganizeCode(), getSortQueuePushLockContextKey(reqBean), queuePushId);
}
//工单完成数KEY【noCalcOrderQty=true代表工位维度的统计,最终不一定会实际累加到工单上】【noCalcOrderQty=false代表生产线维度的统计】
private String getWorkOrderCompleteQtyContextCellKey(StationRequestBean reqBean, Boolean noCalcOrderQty, String workOrderNo) {
StringJoiner sj = new StringJoiner(MesPcnExtConstWords.COLON).add(reqBean.getOrganizeCode()).add(reqBean.getWorkCenterCode());
if (noCalcOrderQty) sj.add(reqBean.getWorkCellCode());
return sj.add(MesPcnExtConstWords.WORK_ORDER_COMPLETE_CONTEXT).add(workOrderNo).toString();
}
//获取生产线维度的工单完成数上下文[查询]
@Override
public MesWorkOrderCompleteQtyContext getWorkOrderCompleteQtyContext(StationRequestBean reqBean, MesProductionPartContext productionPartContext) {
String key = getWorkOrderCompleteQtyContextCellKey(reqBean, false, productionPartContext.getWorkOrderNo());
String context = getFsmBusiData(reqBean.getOrganizeCode(), key);
MesWorkOrderCompleteQtyContext workOrderCompleteQtyContext = !StringUtils.isEmpty(context)
? JSONObject.parseObject(context, MesWorkOrderCompleteQtyContext.class)
: new MesWorkOrderCompleteQtyContext(productionPartContext.getWorkOrderNo(), productionPartContext.getQty(), productionPartContext.getCompleteQty());
return workOrderCompleteQtyContext;
}
//根据noCalcOrderQty判断维度处理处理工单完成数上下文[查询], 有效期三天
@Override
public MesWorkOrderCompleteQtyContext dispatchWorkOrderCompleteQtyContext(StationRequestBean reqBean, Boolean noCalcOrderQty, MesProductionPartContext productionPartContext) {
String key = getWorkOrderCompleteQtyContextCellKey(reqBean, noCalcOrderQty, productionPartContext.getWorkOrderNo());
String context = getFsmBusiData(reqBean.getOrganizeCode(), key);
MesWorkOrderCompleteQtyContext workOrderCompleteQtyContext = !StringUtils.isEmpty(context)
? JSONObject.parseObject(context, MesWorkOrderCompleteQtyContext.class)
: new MesWorkOrderCompleteQtyContext(productionPartContext.getWorkOrderNo(), productionPartContext.getQty(), productionPartContext.getCompleteQty());
//假如缓存中的完成数小于当前传参工单的完成数,则覆盖
Boolean isNeedSave = !StringUtils.isEmpty(context) && MathOperation.compareTo(productionPartContext.getCompleteQty(), workOrderCompleteQtyContext.getCompleteQty()) > 0;
if (isNeedSave) workOrderCompleteQtyContext.overrideCompleteQty(productionPartContext.getCompleteQty());
//判断是否需要存储
if (StringUtils.isEmpty(context) || isNeedSave) dispatchFsmBusiData(reqBean.getOrganizeCode(), key, JSONObject.toJSONString(workOrderCompleteQtyContext), MesPcnEnumUtil.EXPIRE_TIME.THREE_DAY.getValue());
return workOrderCompleteQtyContext;
}
//根据noCalcOrderQty判断维度处理处理工单完成数上下文[保存], 有效期三天
//【noCalcOrderQty=true代表工位维度的统计,最终不一定会实际累加到工单上】【noCalcOrderQty=false代表生产线维度的统计】
@Override
public MesWorkOrderCompleteQtyContext dispatchWorkOrderCompleteQtyContext(StationRequestBean reqBean, Boolean noCalcOrderQty, String workOrderNo, Double calcCompleteQty) {
String key = getWorkOrderCompleteQtyContextCellKey(reqBean, noCalcOrderQty, workOrderNo);
String context = getFsmBusiData(reqBean.getOrganizeCode(), key);
MesWorkOrderCompleteQtyContext workOrderCompleteQtyContext = !StringUtils.isEmpty(context) ? JSONObject.parseObject(context, MesWorkOrderCompleteQtyContext.class) : null;
if (null == workOrderCompleteQtyContext) return null;
workOrderCompleteQtyContext.overrideCompleteQty(MathOperation.add(workOrderCompleteQtyContext.getCompleteQty(), calcCompleteQty));
dispatchFsmBusiData(reqBean.getOrganizeCode(), key, JSONObject.toJSONString(workOrderCompleteQtyContext), MesPcnEnumUtil.EXPIRE_TIME.THREE_DAY.getValue());
return workOrderCompleteQtyContext;
}
}

@ -11,6 +11,7 @@ import cn.estsh.i3plus.pojo.mes.bean.MesRawPartCharging;
import cn.estsh.i3plus.pojo.mes.bean.shipping.MesShippingQueue;
import cn.estsh.i3plus.pojo.mes.model.StationKvBean;
import cn.estsh.i3plus.pojo.mes.model.StationRequestBean;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import lombok.extern.slf4j.Slf4j;
@ -63,6 +64,18 @@ public class MesProductionDispatchContextStepService extends BaseStepService imp
return getFsmBusiData(reqBean.getOrganizeCode(), getContextKey(reqBean), MesPcnExtConstWords.PRODUCT_RESULT_CONTEXT);
}
//获取上下文加工结果
@Override
public Integer getProductResultQcContext(StationRequestBean reqBean) {
String productResult = getProductResultContext(reqBean);
if (StringUtils.isEmpty(productResult)) return MesExtEnumUtil.PRODUCE_QC_STATUS.QUALIFIED.getValue();
try {
return Integer.valueOf(productResult);
} catch (NumberFormatException e) {
return MesExtEnumUtil.PRODUCE_QC_STATUS.QUALIFIED.getValue();
}
}
//保存上下文加工结果 加工结果:成功/报废/可疑 【写入的值是变量类别代码对应的条码质量状态】【报废/可疑: 在保存逻辑条码时有特殊业务处理】
@Override
public Boolean dispatchProductResultContext(StationRequestBean reqBean, String productResult) {

@ -589,26 +589,6 @@ public class MesProductionProcessContextStepService extends BaseStepService impl
return equipSpotCheckContext;
}
//获取选择/扫描零件发运组信息上下文
@Override
public List<StationKvBean> getFunctionChooseShippingGroupContext(StationRequestBean reqBean) {
String chooseCavityOrderJson = getFsmBusiData(reqBean.getOrganizeCode(), getContextKey(reqBean), MesPcnExtConstWords.FUNCTION_CHOOSE_SHIPPING_GROUP);
return !StringUtils.isEmpty(chooseCavityOrderJson) ? JSONObject.parseArray(chooseCavityOrderJson, StationKvBean.class) : null;
}
//保存选择/扫描零件发运组信息上下文 腔数=工单个数 数据格式: [StationKvBean(key=shippingGroupCode, name=零件发运组代码, value=xxx, seq=0), StationKvBean(key=cellMessageSource, name=工位信息来源, value=10, seq=1)]
@Override
public Boolean dispatchFunctionChooseShippingGroupContext(StationRequestBean reqBean, List<StationKvBean> resultList) {
if (CollectionUtils.isEmpty(resultList)) return false;
return dispatchFsmBusiData(reqBean.getOrganizeCode(), getContextKey(reqBean), MesPcnExtConstWords.FUNCTION_CHOOSE_SHIPPING_GROUP, JSONObject.toJSONString(resultList));
}
//删除选择/扫描零件发运组信息上下文
@Override
public void removeFunctionChooseShippingGroupContext(StationRequestBean reqBean) {
removeFsmBusiData(reqBean.getOrganizeCode(), getContextKey(reqBean), MesPcnExtConstWords.FUNCTION_CHOOSE_SHIPPING_GROUP);
}
//处理加工不可用规则
@Override
public MesProductionProcessContext dispatchProdRuleIgnoreCfgContext(StationRequestBean reqBean) {
@ -698,6 +678,7 @@ public class MesProductionProcessContextStepService extends BaseStepService impl
return filterList;
}
//处理工位零件打印机配置
@Override
public List<MesWorkCellPartPrinterCfg> disPatchWorkCellPartPrinterCfg(StationRequestBean reqBean, Boolean pcNosortPrinterCfg) {
if (!pcNosortPrinterCfg) return null;
@ -709,4 +690,36 @@ public class MesProductionProcessContextStepService extends BaseStepService impl
return workCellPartPrinterCfgList;
}
//获取发运RFID生产模式
@Override
public String getShippingRfidRouteModeContext(StationRequestBean reqBean) {
return getFsmBusiData(reqBean.getOrganizeCode(), getContextKey(reqBean), MesPcnExtConstWords.SHIPPING_RFID_ROUTE_MODE_CONTEXT);
}
//处理发运RFID生产模式
@Override
public String disPatchShippingRfidRouteModeContext(StationRequestBean reqBean) {
//当前生产模式
String routeMode = getShippingRfidRouteModeContext(reqBean);
//选择的生产模式
String chooseRouteMode = getFsmBusiData(reqBean.getOrganizeCode(), getContextKey(reqBean), MesPcnExtConstWords.CHOOSE_SHIPPING_RFID_ROUTE_MODE);
//生产模式默认自动
if (StringUtils.isEmpty(routeMode)) routeMode = CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr();
if (StringUtils.isEmpty(chooseRouteMode)) return routeMode;
//删除切换发运RFID生产模式的标志
removeFsmBusiData(reqBean.getOrganizeCode(), getContextKey(reqBean), MesPcnExtConstWords.CHOOSE_SHIPPING_RFID_ROUTE_MODE);
//切换发运RFID生产模式
if (routeMode.equals(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr())) routeMode = CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValueStr();
else routeMode = CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr();
//保存发运RFID生产模式
dispatchFsmBusiData(reqBean.getOrganizeCode(), getContextKey(reqBean), MesPcnExtConstWords.SHIPPING_RFID_ROUTE_MODE_CONTEXT, routeMode);
return routeMode;
}
//处理切换发运RFID生产模式的标志
@Override
public Boolean disPatchChooseShippingRfidRouteMode(StationRequestBean reqBean) {
return dispatchFsmBusiData(reqBean.getOrganizeCode(), getContextKey(reqBean), MesPcnExtConstWords.CHOOSE_SHIPPING_RFID_ROUTE_MODE, CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr());
}
}

@ -0,0 +1,214 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step.method;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionCustomContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionDispatchContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionProcessContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.*;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseStepService;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkCell;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkCenter;
import cn.estsh.i3plus.pojo.mes.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.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @Description :
* @Author : wangjie
**/
@Slf4j
@Service("mesWorkOrderCheckCompleteQtyStepService")
public class MesWorkOrderCheckCompleteQtyStepService extends BaseStepService {
@Autowired
private IMesProductionProcessContextStepService productionProcessContextStepService;
@Autowired
private IMesProductionDispatchContextStepService productionDispatchContextStepService;
@Autowired
private IMesProductionCustomContextStepService productionCustomContextStepService;
//验证加工单完成数量, 验证的前提条件: 每腔均已匹配到加工规则;存在工单;
public List<MesWorkOrderCompleteQtyContext> dispatchWorkOrderCompleteQtyContext(StationRequestBean reqBean, StationResultBean resultBean,
StepResult stepResult, MesProductionProcessContext productionProcessContext,
List<MesProductionPartContext> productionPartContextList, List<MesProductionPsInContext> productionPsInContextList) {
//是否存在产成零件信息
if (!stepResult.isCompleted() || CollectionUtils.isEmpty(productionPartContextList)) return null;
//根据产出零件或者腔数拿到需要的加工规则数量, 优先使用产出零件数量
Integer needQty = !CollectionUtils.isEmpty(productionPartContextList) ? productionPartContextList.size() : productionProcessContext.getCurCellEquip().getCavity();
//验证是否满足腔数
if (!CollectionUtils.isEmpty(productionPsInContextList) && productionPsInContextList.size() < needQty) return null;
//对MesProductionPartContext中的工单号经行分组每个工单可能对应多条数据, 筛选掉foreignkey为空的数据
Map<String, List<MesProductionPartContext>> productionPartContextMap = productionPartContextList.stream().filter(o ->
(!StringUtils.isEmpty(o.getWorkOrderNo()) && !StringUtils.isEmpty(o.getForeignKey()))).collect(Collectors.groupingBy(MesProductionPartContext::getWorkOrderNo));
if (CollectionUtils.isEmpty(productionPartContextMap)) return null;
//根据foreignkey分组进料零件条码
Map<Integer, MesProductionPsInContext> productionPsInContextMap = CollectionUtils.isEmpty(productionPsInContextList) ? null :
productionPsInContextList.stream().filter(o -> !StringUtils.isEmpty(o.getForeignKey())).collect(Collectors.toMap(MesProductionPsInContext::getForeignKey, o -> o));
//生产线与工位信息
MesWorkCenter workCenter = productionProcessContext.getWorkCenter();
MesWorkCell workCell = productionProcessContext.getWorkCell();
//工位是否不累计工单完成数
Boolean noCalcOrderQty = noCalcOrderQty(workCell.getNoCalcOrderQty());
//遍历验证加工单完成数量
List<MesWorkOrderCompleteQtyContext> workOrderCompleteQtyContextList = null;
for (Map.Entry<String, List<MesProductionPartContext>> entry : productionPartContextMap.entrySet()) {
if (null == entry) continue;
//验证加工单完成数量
MesWorkOrderCompleteQtyContext workOrderCompleteQtyContext = dispatchWorkOrderCompleteQty(reqBean, resultBean, stepResult, workCenter, noCalcOrderQty, entry.getValue(), productionPsInContextMap);
//验证失败直接退出
if (!stepResult.isCompleted()) break;
if (null != workOrderCompleteQtyContext) {
if (CollectionUtils.isEmpty(workOrderCompleteQtyContextList)) workOrderCompleteQtyContextList = new ArrayList<>();
workOrderCompleteQtyContextList.add(workOrderCompleteQtyContext);
}
}
//验证失败标记删除标志
if (!stepResult.isCompleted()) {
productionPartContextList.forEach(o -> o.busiCheckToDelete());
if (!CollectionUtils.isEmpty(productionPsInContextList)) productionPsInContextList.forEach(o -> o.busiCheckToDelete());
if (!CollectionUtils.isEmpty(workOrderCompleteQtyContextList)) workOrderCompleteQtyContextList.clear();
}
return workOrderCompleteQtyContextList;
}
//验证加工单完成数量
private MesWorkOrderCompleteQtyContext dispatchWorkOrderCompleteQty(StationRequestBean reqBean, StationResultBean resultBean,
StepResult stepResult, MesWorkCenter workCenter, Boolean noCalcOrderQty,
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(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 null;
//根据noCalcOrderQty判断维度处理工单完成数上下文[查询]【noCalcOrderQty=true代表工位维度的统计,最终不会实际累加到工单上】【noCalcOrderQty=false代表生产线维度的统计,才会实际累加到工单上】
MesWorkOrderCompleteQtyContext workOrderCompleteQtyContext = productionCustomContextStepService.dispatchWorkOrderCompleteQtyContext(reqBean, noCalcOrderQty, productionPartContextList.get(0));
//验证工单完成数
checkWorkOrderCompleteQty(reqBean, resultBean, stepResult, workCenter, workOrderCompleteQtyContext, calcCompleteQty, noCalcOrderQty);
if (!stepResult.isCompleted()) return null;
return workOrderCompleteQtyContext;
}
//工位是否不累计工单完成数
public Boolean noCalcOrderQty(Integer noCalcOrderQty) {
return (!StringUtils.isEmpty(noCalcOrderQty) && noCalcOrderQty.compareTo(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue()) == 0) ? true : false;
}
//验证进料零件与产出零件是否一致
public Boolean isSamePart(MesProductionPsInContext productionPsInContext, MesProductionPartContext productionPartContext, MesProdRuleContext prodRuleContext) {
if (null == productionPsInContext) return false;
if (StringUtils.isEmpty(productionPsInContext.getPartNo())) return false;
if (null != productionPartContext) {
if (!productionPsInContext.getPartNo().equals(productionPartContext.getPartNo())) return false;
else return true;
} else {
if (!productionPsInContext.getPartNo().equals(prodRuleContext.getOutPartNo())) return false;
else return true;
}
}
//验证是否计数
public Boolean 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;
}
//根据数据关联键获取进料零件信息
private MesProductionPsInContext getProductionPsInContext(Map<Integer, MesProductionPsInContext> productionPsInContextMap, Integer foreignKey) {
if (CollectionUtils.isEmpty(productionPsInContextMap) || StringUtils.isEmpty(foreignKey)) return null;
return productionPsInContextMap.get(foreignKey);
}
//验证工单完成数
private void checkWorkOrderCompleteQty(StationRequestBean reqBean, StationResultBean resultBean, StepResult stepResult, MesWorkCenter workCenter,
MesWorkOrderCompleteQtyContext workOrderCompleteQtyContext, Double calcCompleteQty, Boolean noCalcOrderQty) {
//当前工序的预计达到的完成数
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) {
//stepResult.obj(false)目的是在工步最后可以判断是否需要清除进料
stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult.obj(false), String.format("请检查工单数量,工单[%s]计划数量[%s]%s已完成数量[%s]!",
workOrderCompleteQtyContext.getWorkOrderNo(), workOrderCompleteQtyContext.getQty().intValue(),
noCalcOrderQty ? "当前工位" : MesPcnExtConstWords.EMPTY, 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]超工单比例[%s]!",
workOrderCompleteQtyContext.getWorkOrderNo(), workOrderCompleteQtyContext.getQty().intValue(),
noCalcOrderQty ? "当前工位" : MesPcnExtConstWords.EMPTY, workOrderCompleteQtyContext.getCompleteQty().intValue(), workCenter.getOrderRate()));
return;
}
}
//清除本次扫描/读取信息 有进料【只】需要清除进料,否则存在产出零件需要清除产出零件 【只需要清除被标记的数据】
public Boolean doBusiCheckToDelete(StationRequestBean reqBean, StepResult stepResult, List<MesProductionPartContext> productionPartContextList, List<MesProductionPsInContext> 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;
}
}

@ -1,6 +1,7 @@
package cn.estsh.i3plus.ext.mes.pcn.pojo.context;
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.MesEquipmentVariable;
import cn.estsh.i3plus.pojo.mes.bean.MesEquipmentVariableCfg;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkCell;
@ -171,6 +172,9 @@ public class MesProductionProcessContext implements Serializable {
//上下文赋值生产线对象
public MesProductionProcessContext workCenterJson(MesWorkCenter workCenter) {
if (StringUtils.isEmpty(workCenter.getIsCheckOrderQty())) workCenter.setIsCheckOrderQty(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
if (StringUtils.isEmpty(workCenter.getIsIgnoreQc())) workCenter.setIsCheckOrderQty(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
if (StringUtils.isEmpty(workCenter.getIsPushQueue())) workCenter.setIsPushQueue(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
this.workCenterJson = null != workCenter ? JSONObject.toJSONString(workCenter) : null;
return this.isNeedCache();
}
@ -184,6 +188,12 @@ public class MesProductionProcessContext implements Serializable {
//上下文赋值工位对象
public MesProductionProcessContext workCellJson(MesWorkCell workCell) {
if (StringUtils.isEmpty(workCell.getIsCheckSeq())) workCell.setIsCheckSeq(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
if (StringUtils.isEmpty(workCell.getIsCheckCraft())) workCell.setIsCheckCraft(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
if (StringUtils.isEmpty(workCell.getIsSeqScan())) workCell.setIsCheckSeq(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
if (StringUtils.isEmpty(workCell.getIsResetScan())) workCell.setIsResetScan(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
if (StringUtils.isEmpty(workCell.getNoCalcOrderQty())) workCell.setNoCalcOrderQty(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
if (StringUtils.isEmpty(workCell.getIsEndWorkCell())) workCell.setIsEndWorkCell(CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue());
this.workCellJson = null != workCell ? JSONObject.toJSONString(workCell) : null;
return this.isNeedCache();
}

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

@ -1,5 +1,6 @@
package cn.estsh.i3plus.ext.mes.pcn.pojo.context;
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.MesProduceSn;
import io.swagger.annotations.ApiParam;
@ -22,6 +23,12 @@ public class MesProductionPsOutContext extends MesProduceSn implements Serializa
@ApiParam(name = "是否计算工单完成数量")
private Integer isCalcCompleteQty = CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue();
@ApiParam(name = "是否进出一致")
private Integer isSamePart = CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue();
@ApiParam(name = "是否不累计工单完成数")
private Integer noCalcOrderQty = CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue();
public MesProductionPsOutContext() {}
public MesProductionPsOutContext copy(MesProduceSn produceSn, Integer foreignKey) {
@ -41,8 +48,10 @@ public class MesProductionPsOutContext extends MesProduceSn implements Serializa
return this;
}
public MesProductionPsOutContext isCalcCompleteQty(Boolean isCalcCompleteQty) {
public MesProductionPsOutContext isCalcCompleteQty(Boolean isCalcCompleteQty, Boolean isSamePart, Integer noCalcOrderQty) {
if (isCalcCompleteQty) this.isCalcCompleteQty = CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue();
if (isSamePart) this.isSamePart = CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValue();
this.noCalcOrderQty = noCalcOrderQty;
return this;
}

@ -0,0 +1,38 @@
package cn.estsh.i3plus.ext.mes.pcn.pojo.context;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import io.swagger.annotations.ApiParam;
import lombok.Data;
import org.springframework.util.StringUtils;
import java.io.Serializable;
/**
* -
*/
@Data
public class MesWorkOrderCompleteQtyContext implements Serializable {
private static final long serialVersionUID = -1602007855074296100L;
@ApiParam("生产工单号")
private String workOrderNo;
@ApiParam("工单数量")
private Double qty;
@ApiParam("完成数量")
private Double completeQty;
public MesWorkOrderCompleteQtyContext(String workOrderNo, Double qty, Double completeQty) {
this.workOrderNo = workOrderNo;
this.qty = qty;
this.completeQty = StringUtils.isEmpty(completeQty) ? new Double(MesPcnExtConstWords.ZERO) : completeQty;
}
public MesWorkOrderCompleteQtyContext overrideCompleteQty(Double completeQty) {
this.completeQty = completeQty;
return this;
}
}

@ -670,6 +670,12 @@ public class MesPcnExtConstWords {
public static final String QUEUE_PUSH_CONTEXT = "QUEUE_PUSH_CONTEXT";
// 工位零件打印机上下文
public static final String CELL_PART_PRINTER_CONTEXT = "CELL_PART_PRINTER_CONTEXT";
// 工单完成数上下文
public static final String WORK_ORDER_COMPLETE_CONTEXT = "WORK_ORDER_COMPLETE_CONTEXT";
// 发运RFID生产模式上下文
public static final String SHIPPING_RFID_ROUTE_MODE_CONTEXT = "SHIPPING_RFID_ROUTE_MODE_CONTEXT";
// 选择发运RFID生产模式
public static final String CHOOSE_SHIPPING_RFID_ROUTE_MODE = "CHOOSE_SHIPPING_RFID_ROUTE_MODE";
// 上下文: 展示组件数据
public static final String MODULE_CONTENT_CONTEXT = "MODULE_CONTENT_CONTEXT";

Loading…
Cancel
Save