Merge remote-tracking branch 'origin/dev' into dev

tags/yfai-pcn-ext-v1.0
jun 11 months ago
commit d42bba00d2

@ -0,0 +1,17 @@
package cn.estsh.i3plus.ext.mes.pcn.api.base;
/**
* @Description :
* @Reference :
* @Author : Castle
* @CreateDate : 2024/6/13 17:54
* @Modify:
**/
public interface IMesMaximoService {
/**
*
* @param organizeCode
* @param url
*/
void doMeterReading(String organizeCode,String url);
}

@ -28,5 +28,12 @@ public interface IMesWorkOrderService {
public ListPager<MesWorkOrder> queryMesWorkOrderListByPager(MesWorkOrder workOrder, Pager pager);
void doProductReport(List<MesProduceSn> mesProduceSnList, String organizeCode, String userName);
void doProductReport(List<MesProduceSn> mesProduceSns, String organizeCode, String userName);
/**
*
* @param organizeCode
* @return
*/
List<MesProduceSn> getUnReportMesProduceSn(String organizeCode);
}

@ -0,0 +1,120 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.schedulejob;
import cn.estsh.i3plus.platform.common.util.CommonConstWords;
import cn.estsh.i3plus.platform.common.util.MesConstWords;
import cn.estsh.impp.framework.base.schedule.BaseImppScheduleJob;
import cn.estsh.impp.framework.boot.init.ApplicationProperties;
import cn.estsh.impp.framework.boot.util.ImppRedis;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.quartz.JobExecutionContext;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.DigestUtils;
import javax.annotation.Resource;
/**
* @author ns
* @create 2021/11/15 0015 17:04
* xxljob
* 使xxljobBaseMesScheduleJob
*/
public abstract class BaseMesScheduleJob extends BaseImppScheduleJob {
public static final Logger LOGGER = LoggerFactory.getLogger(BaseMesScheduleJob.class);
@Resource(name = CommonConstWords.IMPP_REDIS_MES)
@Getter
@Setter
private ImppRedis redisMes;
@Resource(name = CommonConstWords.IMPP_REDIS_RES)
private ImppRedis redisRes;
private Class childClass;
private String childDesc;
@Getter
@Setter
private String wmsJobParams;
/**
* Redis 30
*/
@Getter
@Setter
private Integer redisLockTime = 1800;
// 当一个 job class 需要同时运行多个 job 实例时把此属性设置为 true默认为 false
@Getter
@Setter
private boolean isMultiInstance = true;
public BaseMesScheduleJob(Class cls, String jobDesc) {
super(cls, jobDesc);
this.childClass = cls;
this.childDesc = jobDesc;
}
@Override
public void executeImppJob(JobExecutionContext context, ApplicationProperties applicationProperties) {
// 保存 job 参数
this.wmsJobParams = super.getJobParam();
String redisKey = MesConstWords.MES_JOB_REDIS_PREFIX + this.childClass.getName();
if (isMultiInstance) {
// 把 Job 参数也作为 key 的一部分,确保相同的 job class 配置多个 job instance 时可以各自运行
redisKey = redisKey + ":" + getMd5String(this.getJobParam());
}
LOGGER.info("JOB REDIS KEY: " + redisKey);
//添加redis锁半小时失效
// if (redisMes.getObject(redisKey) != null) {
// LOGGER.error("JOB REDIS KEY: " + redisKey+ " - "+this.childDesc + " 数据正在处理中,不能并发执行!");
// // 直接返回
// return;
// }
RLock rLock = (RLock) redisRes.getLock(redisKey);
try {
LOGGER.info("JOB REDIS KEY PUT: " + redisKey);
//使用tryLock拿不到锁直接返回
//rlock的leaseTime为-1会每隔WatchdogTimeout秒去续约
if (rLock.tryLock()){
this.executeMesJob(context, applicationProperties);
}else{
LOGGER.error("JOB REDIS KEY: " + redisKey+ " - "+this.childDesc + " 数据正在处理中,不能并发执行!");
}
// 直接返回
return;
// redisMes.putObject(redisKey, redisKey, getRedisLockTime());
} catch (Exception e) {
LOGGER.error(ExceptionUtils.getStackTrace(e));
} finally {
LOGGER.info("JOB REDIS KEY DELETE: " + redisKey);
//解除REDIS执行锁
// redisMes.deleteKey(redisKey);
if (rLock.isHeldByCurrentThread()) {
rLock.unlock();
}
}
}
public abstract void executeMesJob(JobExecutionContext context, ApplicationProperties applicationProperties);
/**
* MD5
* @param context
* @return MD5
*/
private String getMd5String(String context) {
if (context == null || context.isEmpty()) {
return "";
}
return DigestUtils.md5DigestAsHex(context.getBytes());
}
}

@ -0,0 +1,48 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.schedulejob;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesWorkOrderService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.base.MesMaximoServiceImpl;
import cn.estsh.i3plus.pojo.mes.bean.MesProduceSn;
import cn.estsh.impp.framework.boot.init.ApplicationProperties;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
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 java.util.List;
/**
* @author castle,
* @version 1.0
* @date 2021/2/2 16:44
**/
@Slf4j
@DisallowConcurrentExecution
@Component
@ApiOperation("仪表读数job")
public class MesMeterReadingJob extends BaseMesScheduleJob {
@Autowired
private MesMaximoServiceImpl maximoService;
public MesMeterReadingJob() {
super(MesMeterReadingJob.class, "仪表读数job");
}
@Override
public void executeMesJob(JobExecutionContext context, ApplicationProperties applicationProperties) {
String jobParam = this.getJobParam();
JSONObject jsonObject= JSONUtil.parseObj(jobParam);
String organizeCode = jsonObject.getStr("organizeCode");
String url = jsonObject.getStr("url");
if (null == organizeCode){
log.error("请添加需要报工的工厂代码!");
return;
}
maximoService.doMeterReading(organizeCode,url);
}
}

@ -0,0 +1,51 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.schedulejob;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesWorkOrderService;
import cn.estsh.i3plus.pojo.mes.bean.MesProduceSn;
import cn.estsh.impp.framework.boot.init.ApplicationProperties;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
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 java.util.List;
/**
* @author castle,
* @version 1.0
* @date 2021/2/2 16:44
**/
@Slf4j
@DisallowConcurrentExecution
@Component
@ApiOperation("非排序报工job")
public class MesReportNoSortJob extends BaseMesScheduleJob {
@Autowired
private IMesWorkOrderService workOrderService;
public MesReportNoSortJob() {
super(MesReportNoSortJob.class, "非排序报工JOB");
}
@Override
public void executeMesJob(JobExecutionContext context, ApplicationProperties applicationProperties) {
String jobParam = this.getJobParam();
JSONObject jsonObject= JSONUtil.parseObj(jobParam);
String organizeCode = jsonObject.getStr("organizeCode");
String userName = jsonObject.getStr("userName");
if (null == organizeCode){
log.error("请添加需要报工的工厂代码!");
return;
}
if (null == userName){
userName = "JOB";
}
List<MesProduceSn> unReportMesProduceSn = workOrderService.getUnReportMesProduceSn(organizeCode);
workOrderService.doProductReport(unReportMesProduceSn,organizeCode,userName);
}
}

@ -0,0 +1,94 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.base;
import cn.estsh.i3plus.ext.mes.pcn.api.base.IMesMaximoService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.platform.common.tool.TimeTool;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.mes.bean.MesMouldMappingCfg;
import cn.estsh.i3plus.pojo.mes.repository.IMesMouldMappingCfgRepository;
import cn.estsh.i3plus.pojo.mes.repository.MesProdMouldRecordRepository;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
* @Description :Maximo
* @Reference :
* @Author : Castle
* @CreateDate : 2024/6/13 17:55
* @Modify:
**/
@Service
@Slf4j
public class MesMaximoServiceImpl implements IMesMaximoService {
@Autowired
private MesProdMouldRecordRepository prodMouldRecordRao;
@Autowired
private IMesMouldMappingCfgRepository mesMouldMappingCfgRao;
@Override
public void doMeterReading(String organizeCode,String url) {
//1.查询表磨具映射关系维护表,查询出当前工厂需要统计的模具信息
//1.按天、按照meter_name 和 asset_num 汇总
DdlPackBean modulePackBean = DdlPackBean.getDdlPackBean(organizeCode);
List<MesMouldMappingCfg> mappingCfgList = mesMouldMappingCfgRao.findByHqlWhere(modulePackBean);
if (mappingCfgList.isEmpty()){
log.info("当前工厂:{} 模具映射关系没有数据",organizeCode);
return;
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.DAY_OF_MONTH, -1);
Date date = calendar.getTime();
String createDateTimeStart = TimeTool.getToday(date) + MesPcnExtConstWords.APPEND_ZERO_HMS;
String createDateTimeEnd = TimeTool.getToday(date) + MesPcnExtConstWords.APPEND_24_HMS;
for (MesMouldMappingCfg cfg : mappingCfgList) {
//循环模具映射关系维护
DdlPackBean recordPackBean = DdlPackBean.getDdlPackBean(organizeCode);
DdlPreparedPack.getStringEqualPack(cfg.getMeterName(),"meterName",recordPackBean);
DdlPreparedPack.getStringEqualPack(cfg.getAssetNum(),"assetNum",recordPackBean);
DdlPreparedPack.timeBuilder(createDateTimeStart,createDateTimeEnd,"createDatetime",recordPackBean,true);
int count = prodMouldRecordRao.findByHqlWhereCount(recordPackBean);
call(cfg.getMeterName(),cfg.getAssetNum(),organizeCode,count,url);
}
}
private void call(String meterName,String assetNum,String organizeCode,int count , String url){
String xml = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:max=\"http://www.ibm.com/maximo\">\n" +
" <soapenv:Header/>\n" +
" <soapenv:Body>\n" +
" <max:CreateCUR_METERREADING creationDateTime=\"EN\" baseLanguage=\"EN\">\n" +
" <max:CUR_METERREADINGSet>\n" +
" <max:METERDATA action=\"Change\">\n" +
" <max:MAXINTERRORMSG>?</max:MAXINTERRORMSG>\n" +
" <max:ASSETNUM changed=\"?\">%s</max:ASSETNUM>\n" +
" <max:METERNAME changed=\"?\">%s</max:METERNAME>\n" +
" <max:NEWREADING changed=\"?\">%s</max:NEWREADING>\n" +
" <max:NEWREADINGDATE changed=\"?\">%s</max:NEWREADINGDATE>\n" +
" <max:SITEID changed=\"?\">%s</max:SITEID>\n" +
" </max:METERDATA>\n" +
" </max:CUR_METERREADINGSet>\n" +
" </max:CreateCUR_METERREADING>\n" +
" </soapenv:Body>\n" +
"</soapenv:Envelope>";
//2024-05-30T11:10:00
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter isoDateTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
String today = now.format(isoDateTime);
String xmlString = String.format(xml, assetNum, meterName, count, today, organizeCode);
log.info("当前工厂:{},报文:{}",organizeCode,xmlString);
HttpRequest.post(url).header("Content-Type","text/xml").body(xmlString).execute().body();
}
}

@ -51,6 +51,12 @@ public class MesWorkOrderService implements IMesWorkOrderService {
@Autowired
private MesProductOffLineRepository mesProductOffLineRDao;
@Autowired
private MesProductionRecordRepository productionRecordRao;
@Autowired
private MesProduceSnRepository mesProduceSnRao;
@Override
public MesWorkOrder queryMesWorkOrder(MesWorkOrder workOrder) {
@ -109,7 +115,7 @@ public class MesWorkOrderService implements IMesWorkOrderService {
//新增初始化 todo
Map<String, List<MesProduceSn>> mesWorkOrderMap = mesProduceSnList.stream().collect(Collectors.groupingBy(MesProduceSn::getPartNo));
Map<String,MesPart> mesPartMap = new HashMap<>();
MesPart mesPart = null;
MesPart mesPart;
//查询工单状态
Integer[] orderStatus =new Integer[]{MesExtEnumUtil.ORDER_STATUS.RELEASE.getValue(),MesExtEnumUtil.ORDER_STATUS.PROCESS.getValue()};
for (Map.Entry<String, List<MesProduceSn>> mesProduceSn : mesWorkOrderMap.entrySet()) {
@ -212,6 +218,26 @@ public class MesWorkOrderService implements IMesWorkOrderService {
}
}
@Override
public List<MesProduceSn> getUnReportMesProduceSn(String organizeCode) {
List<MesProduceSn> mesProduceSnList = new ArrayList<>();
//1.获取生产加工记录production_record表中report_status为待汇报状态的工单
DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
DdlPreparedPack.getNumEqualPack( MesExtEnumUtil.REPORT_STATUS.REPORT_STATUS_10.getValue(),"reportStatus",ddlPackBean);
List<MesProductionRecord> mesProductionRecordList = productionRecordRao.findByHqlTopWhere(ddlPackBean, 1);
if (mesProductionRecordList.isEmpty()){
return mesProduceSnList;
}
//2.根据工单查询工单下的mesProduceSn
MesProductionRecord mesProductionRecord = mesProductionRecordList.get(0);
//工单号
String workOrderNo = mesProductionRecord.getWorkOrderNo();
DdlPackBean snPackBean = DdlPackBean.getDdlPackBean(organizeCode);
DdlPreparedPack.getStringEqualPack(workOrderNo,"workOrderNo",snPackBean);
return mesProduceSnRao.findByHqlWhere(snPackBean);
}
private void saveMesProductPlan(MesWorkOrder bean, boolean isInsert, boolean isReport) {
if (StringUtil.isEmpty(bean.getPlanOrderNo())) {
DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(bean.getOrganizeCode());

@ -0,0 +1,22 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.print;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionPsOutContext;
import java.util.List;
/**
* @Description : , content dataList
* @Reference :
* @Author : Castle
* @CreateDate : 2024/6/6 16:39
* @Modify:
**/
public interface IPrintTemplateStrategyService {
/**
* dataList
*
* @param sn
* @return
*/
List<Object> execute(MesProductionPsOutContext sn , String organizeCode);
}

@ -0,0 +1,29 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.print.strategy;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.print.IPrintTemplateStrategyService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionPsOutContext;
import cn.estsh.i3plus.pojo.mes.repository.MesLabelTemplateRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Description : 广使
* @Reference :
* @Author : Castle
* @CreateDate : 2024/6/6 17:03
* @Modify:
**/
@Service
@Slf4j
public class GzPrintSnStrategy implements IPrintTemplateStrategyService {
@Autowired
private MesLabelTemplateRepository labelTemplateRao;
@Override
public List<Object> execute(MesProductionPsOutContext sn, String organizeCode) {
//1.根据 templateCode
return null;
}
}

@ -0,0 +1,108 @@
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.print.IPrintTemplateStrategyService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionPsOutContext;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseStepService;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.mes.bean.MesLabelTemplate;
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.MesLabelTemplateRepository;
import cn.estsh.impp.framework.boot.util.SpringContextsUtil;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Description :
* @Reference :
* @Author : Castle
* @CreateDate : 2024/6/6 13:39
* @Modify:
**/
@Service
public class MesProductSnPrintStepService extends BaseStepService {
@Autowired
private IMesProductionProcessContextStepService productionProcessContextStepService;
@Autowired
private IMesProductionDispatchContextStepService mesProductionDispatchContextStepService;
@Autowired
private MesLabelTemplateRepository labelTemplateRao;
@Override
public StepResult execute(StationRequestBean reqBean) {
String organizeCode = reqBean.getOrganizeCode();
StationResultBean resultBean = new StationResultBean();
StepResult stepResult = StepResult.getSuccessComplete();
//需要打印的数据
Map<String,List<Object>> resultData = new HashMap<>();
//用于保存客户模板代码 和 模板信息关系
Map<String,MesLabelTemplate> labelTemplateMap = new HashMap<>();
//返回打印标识 给前端
//1. 获取上下文中生成的主条码
List<MesProductionPsOutContext> productionPsOutContextList = mesProductionDispatchContextStepService.getProductionPsOutContext(reqBean);
//2. 获取条码需要模板、模板代码、打印机 --- 循环遍历条码 封装数据
for (MesProductionPsOutContext sn : productionPsOutContextList) {
String custLabelTemplate = sn.getCustLabelTemplate();
MesLabelTemplate labelTemplate;
// 查模板代码
if (!labelTemplateMap.containsKey(custLabelTemplate)) {
labelTemplate = getLabelTemplate(custLabelTemplate, organizeCode);
//模板信息丢失抛出异常
if (labelTemplate == null) {
execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("零件号[%s]的模板代码[%s]的模板信息丢失,请配置!", sn.getPartNo(),custLabelTemplate));
}
labelTemplateMap.put(custLabelTemplate, labelTemplate);
}else {
labelTemplate = labelTemplateMap.get(custLabelTemplate);
}
//根据反射获取策略类--封装打印数据
String methodCode = labelTemplate.getMethodCode();
//模板信息丢失抛出异常
if (methodCode == null) {
execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("零件号[%s]的模板代码[%s]的反射类丢失,请配置!", sn.getPartNo(),custLabelTemplate));
}
IPrintTemplateStrategyService strategyService = (IPrintTemplateStrategyService) SpringContextsUtil.getBean(methodCode);
List<Object> snData = strategyService.execute(sn, organizeCode);
if (resultData.containsKey(labelTemplate.getTemplateCode())){
List<Object> printData = resultData.get(labelTemplate.getTemplateCode());
printData.addAll(snData);
}else {
resultData.put(labelTemplate.getTemplateCode(),snData);
}
}
//前端接收到busiTyep是customComponent并且 dataType是file类型的消息就需要打印后续消息里的数据一个模板对应多个打印数据
resultBean.setBusiType(MesPcnEnumUtil.STATION_BUSI_TYPE.CUSTOM_COMPONENT.getValue());
resultBean.setDataType(MesPcnEnumUtil.STATION_DATA_TYPE.FILE.getValue());
resultBean.setResultObj(resultData);
//3. 发送数据给到前端
this.sendMessage(reqBean,resultBean);
return stepResult;
}
/**
* templateCode
* @param templateCode
* @param organizeCode
* @return
*/
private MesLabelTemplate getLabelTemplate(String templateCode,String organizeCode) {
DdlPackBean templatePackBean = DdlPackBean.getDdlPackBean(organizeCode);
DdlPreparedPack.getStringEqualPack(templateCode,"templateCode",templatePackBean);
List<MesLabelTemplate> mesLabelTemplateList = labelTemplateRao.findByHqlWhere(templatePackBean);
return mesLabelTemplateList.isEmpty() ? null : mesLabelTemplateList.get(0);
}
}

@ -5,48 +5,86 @@ import akka.actor.ActorSystem;
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.IMesWorkOrderService;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProdRuleContext;
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.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.platform.common.tool.MathOperation;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.codemaker.SnowflakeIdMaker;
import cn.estsh.i3plus.pojo.mes.bean.MesProduceSn;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.base.util.StringUtil;
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.*;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import cn.estsh.impp.framework.boot.exception.ImppBusiException;
import cn.estsh.impp.framework.boot.util.SpringContextsUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* @Description :
* @Author : zxw
* @Author : zxw --castle update
* @Date: 2024/06/07
**/
@Slf4j
@Service
public class MesReportGenerateStepService extends BaseStepService {
@Autowired
private IMesProductionProcessContextStepService productionProcessContextStepService;
@Autowired
private IMesProductionDispatchContextStepService mesProductionDispatchContextStepService;
private MesReportNoSortStepService reportNoSortStepService;
@Autowired
private IMesWorkOrderService mesWorkOrderService;
private MesReportSortStepService reportSortStepService;
@Override
public StepResult execute(StationRequestBean reqBean) {
StationResultBean resultBean = new StationResultBean();
StepResult stepResult = StepResult.getSuccessComplete();
// todo 根据产线判断是排序还是非排序,然后调用排序或者非排序的报工工步
// //产品加工规则
// List<MesProdRuleContext> prodRuleDataContext = mesProductionDispatchContextStepService.getProdRuleDataContext(reqBean);
// //获取产成零件信息
// List<MesProductionPartContext> productionPartContext = mesProductionDispatchContextStepService.getProductionPartContext(reqBean);
//1. 校验当前有没有工单---只有有工单才能报工
//如果产品加工规则中的foreignKey 和 产成零件信息 一一对应的,查询MesProductionPartContext的工单号
// List<MesProductionPsOutContext> mesProduceSns = mesProductionDispatchContextStepService.getProductionPsOutContext(reqBean);
//获取上下文信息
MesProductionProcessContext productionProcessContext = productionProcessContextStepService.getCurCellEquipment(reqBean);
public static final String ORDER_NO_JIS_SORT = "ORDER_NO_JIS_SORT";
//配置错误 抛出异常
if (!productionProcessContext.getSuccess())
execExpSendMsgAndThrowEx(reqBean, resultBean.writeDbLog(), productionProcessContext.getMessage());
private static final Map<String, ActorRef> refMap = new ConcurrentHashMap<>(200);
//存储生产过程上下文对象
productionProcessContextStepService.saveProductionProcessContext(reqBean, productionProcessContext);
@Override
public StepResult execute(StationRequestBean reqBean) {
StationResultBean resultBean = new StationResultBean();
//从上下文中取出生产线对象
MesWorkCenter workCenter = productionProcessContext.getWorkCenter();
StepResult stepResult = StepResult.getSuccessComplete();
List<MesProduceSn> mesProduceSns = mesProductionDispatchContextStepService.getOutProduceSnDataContext(reqBean);
//排序线报工
if (MesExtEnumUtil.WORK_CENTER_TYPE.SORT.getValue() == workCenter.getCenterType()) {
return reportSortStepService.execute(reqBean);
} else {
//非排序线报工
return reportNoSortStepService.execute(reqBean);
}
mesWorkOrderService.doProductReport(mesProduceSns, reqBean.getOrganizeCode(), reqBean.getUserInfo());
return execSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, "保存加工结果成功");
}
}
}

@ -0,0 +1,240 @@
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.pojo.context.MesProductionPsOutContext;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseStepService;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.base.util.StringUtil;
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.*;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
* @Description :
*
* @Author : zxw --castle update
* @Date: 2024/06/07
**/
@Slf4j
@Service
public class MesReportNoSortStepService extends BaseStepService {
@Autowired
private IMesProductionDispatchContextStepService mesProductionDispatchContextStepService;
@Autowired
private MesPartRepository mesPartRDao;
@Autowired
private MesWorkOrderRepository workOrderRepository;
@Autowired
private MesWorkCenterRepository mesWorkCenterRDao;
@Autowired
private MesProductVersionRepository mesProductVersionRDao;
@Autowired
private MesBomRepository mesBomRDao;
@Autowired
private MesProductOffLineRepository mesProductOffLineRDao;
@Autowired
private MesProductPlanRepository mesProductPlanRDao;
@Override
public StepResult execute(StationRequestBean reqBean) {
StationResultBean resultBean = new StationResultBean();
StepResult stepResult = StepResult.getSuccessComplete();
// todo 先不使用缓存中的数据
//1. 校验当前有没有工单---只有有工单才能报工
//如果产品加工规则中的foreignKey 和 产成零件信息 一一对应的,查询MesProductionPartContext的工单号
List<MesProductionPsOutContext> mesProduceSns = mesProductionDispatchContextStepService.getProductionPsOutContext(reqBean);
this.doProductReport(mesProduceSns, reqBean.getOrganizeCode(), reqBean.getUserInfo(),reqBean,resultBean);
return execSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, "报工成功");
}
public void doProductReport(List<MesProductionPsOutContext> mesProduceSnList, String organizeCode, String userName, StationRequestBean reqBean, StationResultBean resultBean) {
//新增初始化
Map<String, List<MesProduceSn>> mesWorkOrderMap = mesProduceSnList.stream().collect(Collectors.groupingBy(MesProduceSn::getPartNo));
Map<String, MesPart> mesPartMap = new HashMap<>();
MesPart mesPart;
//查询工单状态
Integer[] orderStatus =new Integer[]{MesExtEnumUtil.ORDER_STATUS.RELEASE.getValue(),MesExtEnumUtil.ORDER_STATUS.PROCESS.getValue()};
for (Map.Entry<String, List<MesProduceSn>> mesProduceSn : mesWorkOrderMap.entrySet()) {
List<MesProduceSn> mesWorkOrderList = mesProduceSn.getValue();
//获取物料信息
if(mesPartMap.containsKey(mesProduceSn.getKey())){
mesPart = mesPartMap.get(mesProduceSn.getKey());
}else{
//查询物料信息
DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
DdlPreparedPack.getStringEqualPack(mesProduceSn.getKey(), "partNo", ddlPackBean);
mesPart = mesPartRDao.getByProperty(ddlPackBean);
if(Objects.isNull(mesPart)){
execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("物料【%s】信息不存在", mesProduceSn.getKey()));
}
mesPartMap.put(mesProduceSn.getKey(),mesPart);
}
//根据物料获取已发布的工单
DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
DdlPreparedPack.getStringEqualPack(mesPart.getPartNo(), "partNo", ddlPackBean);
DdlPreparedPack.getInPackArray(orderStatus, "workOrderStatus", ddlPackBean);
MesWorkOrder oldMesWorkOrder = workOrderRepository.getByProperty(ddlPackBean);
if(Objects.isNull(oldMesWorkOrder)){
execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("物料【%s】状态未已发布的工单信息不存在", mesPart.getPartNo()));
}
//查询工作中心
ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
DdlPreparedPack.getStringEqualPack(oldMesWorkOrder.getWorkCenterCode(), "workCenterCode", ddlPackBean);
MesWorkCenter mesWorkCenter = mesWorkCenterRDao.getByProperty(ddlPackBean);
if (Objects.isNull(mesWorkCenter)) {
execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("产线【%s】不存在", oldMesWorkOrder.getWorkCenterCode()));
}
//获取生产版本
ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
DdlPreparedPack.getStringEqualPack(mesPart.getPartNo(), "partNo", ddlPackBean);
DdlPreparedPack.getStringEqualPack(mesWorkCenter.getErpWorkCenter(), "workCenterCode", ddlPackBean);
DdlPreparedPack.getStringEqualPack(oldMesWorkOrder.getProductVersion(), "productVersion", ddlPackBean);
MesProductVersion mesProductVersion = mesProductVersionRDao.getByProperty(ddlPackBean);
if (null == mesProductVersion) {
execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("物料【%s】生产版本信息不存在", mesPart.getPartNo()));
}
//物料+生产版本获取bom信息
ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
DdlPreparedPack.getStringEqualPack(mesPart.getPartNo(), "partNo", ddlPackBean);
DdlPreparedPack.getStringEqualPack(mesProductVersion.getAlternativePartList(), "bomVersion", ddlPackBean);
List<MesBom> mesBoms = mesBomRDao.findByHqlWhere(ddlPackBean);
if (CollectionUtils.isEmpty(mesBoms)) {
execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("物料【%s】生产版本【%s】对应bom信息不存在", mesPart.getPartNo(), mesProductVersion.getProductVersion()));
}
oldMesWorkOrder.setNum(mesWorkOrderList.size());
oldMesWorkOrder.setReportedQty(MathOperation.add(oldMesWorkOrder.getNum(), oldMesWorkOrder.getReportedQty()));
//更新SAP计划完成数量
saveMesProductPlan(oldMesWorkOrder, false, true, reqBean, resultBean);
//更新工单状态
double unCompleteQty = MathOperation.sub(oldMesWorkOrder.getQty(), oldMesWorkOrder.getReportedQty());
oldMesWorkOrder.setUnCompleteQty(unCompleteQty > 0 ? unCompleteQty : 0);
if (oldMesWorkOrder.getReportedQty() > oldMesWorkOrder.getQty()) {
execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("工单报工数量【%s】大于工单数量【%s】,不允许报工", oldMesWorkOrder.getReportedQty(), oldMesWorkOrder.getQty()));
} else if (Objects.equals(oldMesWorkOrder.getReportedQty(), oldMesWorkOrder.getQty())) {
oldMesWorkOrder.setWorkOrderStatus(MesExtEnumUtil.ORDER_STATUS.COMPLETE.getValue());
} else {
oldMesWorkOrder.setWorkOrderStatus(MesExtEnumUtil.ORDER_STATUS.PROCESS.getValue());
}
ConvertBean.serviceModelUpdate(oldMesWorkOrder,userName);
workOrderRepository.update(oldMesWorkOrder);
//保存数据
List<MesProductOffLine> mesProductOffLineList = new ArrayList<>();
MesProductOffLine newMesProductOffLine;
for (MesProduceSn produceSn : mesWorkOrderList) {
for (MesBom mesBom : mesBoms) {
newMesProductOffLine = new MesProductOffLine();
newMesProductOffLine.setReportPartNo(oldMesWorkOrder.getPartNo());
newMesProductOffLine.setReportPartNameRdd(oldMesWorkOrder.getPartName());
newMesProductOffLine.setItemPartNo(mesBom.getItemPartNo());
newMesProductOffLine.setItemPartName(mesBom.getItemPartName());
newMesProductOffLine.setItemQty(mesBom.getItemQty());
newMesProductOffLine.setAlort(mesProductVersion.getReceiveInventoryPoint());
newMesProductOffLine.setStgeLoc(mesProductVersion.getShipInventoryPoint());
newMesProductOffLine.setQty(1d);
newMesProductOffLine.setReportSn(produceSn.getProductSn());
newMesProductOffLine.setBomVersion(oldMesWorkOrder.getProductVersion());
newMesProductOffLine.setSerialNumber(produceSn.getProductSn());
newMesProductOffLine.setUnit(mesBom.getUnit());
newMesProductOffLine.setItemUnit(mesBom.getItemUnit());
newMesProductOffLine.setWorkOrderNo(oldMesWorkOrder.getWorkOrderNo());
newMesProductOffLine.setWorkCenterCode(oldMesWorkOrder.getWorkCenterCode());
newMesProductOffLine.setWorkCellCode(oldMesWorkOrder.getWorkCellCode());
newMesProductOffLine.setReportType(oldMesWorkOrder.getReportType());
newMesProductOffLine.setSapWorkCenter(oldMesWorkOrder.getErpWorkCenter());
newMesProductOffLine.setOrganizeCode(oldMesWorkOrder.getOrganizeCode());
ConvertBean.serviceModelInitialize(newMesProductOffLine, userName);
mesProductOffLineList.add(newMesProductOffLine);
}
}
mesProductOffLineRDao.saveAll(mesProductOffLineList);
}
}
private void saveMesProductPlan(MesWorkOrder bean, boolean isInsert, boolean isReport,StationRequestBean reqBean, StationResultBean resultBean) {
if (StringUtil.isEmpty(bean.getPlanOrderNo())) {
DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(bean.getOrganizeCode());
DdlPreparedPack.getStringEqualPack(bean.getPartNo(), "planPartNo", ddlPackBean);
DdlPreparedPack.getStringEqualPack(bean.getPlanStartTime(), "planStartDate", ddlPackBean);
DdlPreparedPack.getStringEqualPack(bean.getPlanEndTime(), "planEndDate", ddlPackBean);
MesProductPlan mesProductPlan = mesProductPlanRDao.getByProperty(ddlPackBean);
if (null == mesProductPlan) {
MesProductPlan mesPlanOrder = new MesProductPlan();
mesPlanOrder.setPlanOrderNo("");
mesPlanOrder.setPlanQty(bean.getQty());
mesPlanOrder.setPlanPartNo(bean.getPartNo());
mesPlanOrder.setCompleteQty(0d);
mesPlanOrder.setUncompleteQty(bean.getQty());
mesPlanOrder.setUnit(bean.getUnit());
mesPlanOrder.setPlanStartDate(bean.getPlanStartTime());
mesPlanOrder.setPlanEndDate(bean.getPlanEndTime());
mesPlanOrder.setPartMappingWorkCenterCode(bean.getErpWorkCenter());
mesPlanOrder.setPlanOrganizeCode(bean.getOrganizeCode());
mesPlanOrder.setOrganizeCode(bean.getOrganizeCode());
ConvertBean.serviceModelInitialize(mesPlanOrder, bean.getCreateUser());
mesProductPlanRDao.insert(mesPlanOrder);
} else {
if (isInsert) {
mesProductPlan.setPlanQty(MathOperation.add(mesProductPlan.getPlanQty(), bean.getQty()));
} else {
//报工
if (isReport) {
mesProductPlan.setCompleteQty(MathOperation.add(mesProductPlan.getCompleteQty(), bean.getNum()));
//报工调整
} else {
mesProductPlan.setCompleteQty(MathOperation.sub(mesProductPlan.getCompleteQty(), bean.getNum()));
}
}
mesProductPlan.setUncompleteQty(MathOperation.sub(mesProductPlan.getPlanQty(), mesProductPlan.getCompleteQty()));
ConvertBean.serviceModelUpdate(mesProductPlan, bean.getCreateUser());
mesProductPlanRDao.update(mesProductPlan);
}
} else {
DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(bean.getOrganizeCode());
DdlPreparedPack.getStringEqualPack(bean.getPlanOrderNo(), "planOrderNo", ddlPackBean);
DdlPreparedPack.getStringEqualPack(bean.getPartNo(), "planPartNo", ddlPackBean);
MesProductPlan mesProductPlan = mesProductPlanRDao.getByProperty(ddlPackBean);
if (null == mesProductPlan) {
execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("SAP计划单号【%s】物料【%s】,不存在", bean.getPlanOrderNo(), bean.getPartNo()));
}
if (!isInsert) {
if (Objects.isNull(mesProductPlan.getCompleteQty())) {
mesProductPlan.setCompleteQty(0d);
}
//报工
if (isReport) {
mesProductPlan.setCompleteQty(MathOperation.add(mesProductPlan.getCompleteQty(), bean.getNum()));
//报工调整
} else {
mesProductPlan.setCompleteQty(MathOperation.sub(mesProductPlan.getCompleteQty(), bean.getNum()));
}
mesProductPlan.setUncompleteQty(MathOperation.sub(mesProductPlan.getPlanQty(), mesProductPlan.getCompleteQty()));
ConvertBean.serviceModelUpdate(mesProductPlan, bean.getCreateUser());
mesProductPlanRDao.update(mesProductPlan);
}
}
}
}

@ -0,0 +1,411 @@
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.pojo.context.MesProductionPsOutContext;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseStepService;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.platform.common.tool.MathOperation;
import cn.estsh.i3plus.platform.common.tool.TimeTool;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.base.util.StringUtil;
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.*;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import cn.estsh.impp.framework.boot.auth.AuthUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
* @Description :
*
* @Author : zxw --castle update
* @Date: 2024/06/07
**/
@Slf4j
@Service
public class MesReportSortStepService extends BaseStepService {
@Autowired
private IMesProductionDispatchContextStepService mesProductionDispatchContextStepService;
@Autowired
private MesPartRepository mesPartRDao;
@Autowired
private MesWorkOrderRepository workOrderRepository;
@Autowired
private MesWorkCenterRepository mesWorkCenterRDao;
@Autowired
private MesProductVersionRepository mesProductVersionRDao;
@Autowired
private MesBomRepository mesBomRDao;
@Autowired
private MesProductOffLineRepository mesProductOffLineRDao;
@Autowired
private MesProductPlanRepository mesProductPlanRDao;
@Autowired
private MesProdRuleSortCfgRepository mesProdRuleSortCfgRDao;
@Autowired
private IMesMoveRuleRepository moveRuleRao;
@Autowired
private MesPartSapRepository mesPartSapRao;
@Autowired
private MesPartRepository partRao;
@Autowired
private MesMoveRepository mesMoveRDao;
@Override
public StepResult execute(StationRequestBean reqBean) {
StationResultBean resultBean = new StationResultBean();
StepResult stepResult = StepResult.getSuccessComplete();
//如果产品加工规则中的foreignKey 和 产成零件信息 一一对应的,查询MesProductionPartContext的工单号
List<MesProductionPsOutContext> mesProduceSns = mesProductionDispatchContextStepService.getProductionPsOutContext(reqBean);
this.doProductReport(mesProduceSns, reqBean.getOrganizeCode(), reqBean.getUserInfo(),reqBean,resultBean);
return execSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, "报工成功");
}
public void doProductReport(List<MesProductionPsOutContext> mesProduceSnList, String organizeCode, String userName, StationRequestBean reqBean, StationResultBean resultBean) {
//新增初始化
Map<String, List<MesProduceSn>> mesWorkOrderMap = mesProduceSnList.stream().collect(Collectors.groupingBy(MesProduceSn::getPartNo));
Map<String, MesPart> mesPartMap = new HashMap<>();
MesPart mesPart;
//查询工单状态
Integer[] orderStatus =new Integer[]{MesExtEnumUtil.ORDER_STATUS.RELEASE.getValue(),MesExtEnumUtil.ORDER_STATUS.PROCESS.getValue()};
for (Map.Entry<String, List<MesProduceSn>> mesProduceSn : mesWorkOrderMap.entrySet()) {
List<MesProduceSn> mesWorkOrderList = mesProduceSn.getValue();
//获取物料信息
if(mesPartMap.containsKey(mesProduceSn.getKey())){
mesPart = mesPartMap.get(mesProduceSn.getKey());
}else{
//查询物料信息
DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
DdlPreparedPack.getStringEqualPack(mesProduceSn.getKey(), "partNo", ddlPackBean);
mesPart = mesPartRDao.getByProperty(ddlPackBean);
if(Objects.isNull(mesPart)){
execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("物料【%s】信息不存在", mesProduceSn.getKey()));
}
mesPartMap.put(mesProduceSn.getKey(),mesPart);
}
//根据物料获取已发布的工单
DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
DdlPreparedPack.getStringEqualPack(mesPart.getPartNo(), "partNo", ddlPackBean);
DdlPreparedPack.getInPackArray(orderStatus, "workOrderStatus", ddlPackBean);
MesWorkOrder oldMesWorkOrder = workOrderRepository.getByProperty(ddlPackBean);
if(Objects.isNull(oldMesWorkOrder)){
execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("物料【%s】状态未已发布的工单信息不存在", mesPart.getPartNo()));
}
//查询工作中心
ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
DdlPreparedPack.getStringEqualPack(oldMesWorkOrder.getWorkCenterCode(), "workCenterCode", ddlPackBean);
MesWorkCenter mesWorkCenter = mesWorkCenterRDao.getByProperty(ddlPackBean);
if (Objects.isNull(mesWorkCenter)) {
execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("产线【%s】不存在", oldMesWorkOrder.getWorkCenterCode()));
}
//获取生产版本
ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
DdlPreparedPack.getStringEqualPack(mesPart.getPartNo(), "partNo", ddlPackBean);
DdlPreparedPack.getStringEqualPack(mesWorkCenter.getErpWorkCenter(), "workCenterCode", ddlPackBean);
DdlPreparedPack.getStringEqualPack(oldMesWorkOrder.getProductVersion(), "productVersion", ddlPackBean);
MesProductVersion mesProductVersion = mesProductVersionRDao.getByProperty(ddlPackBean);
if (null == mesProductVersion) {
execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("物料【%s】生产版本信息不存在", mesPart.getPartNo()));
}
//物料+生产版本获取bom信息
ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
DdlPreparedPack.getStringEqualPack(mesPart.getPartNo(), "partNo", ddlPackBean);
DdlPreparedPack.getStringEqualPack(mesProductVersion.getAlternativePartList(), "bomVersion", ddlPackBean);
List<MesBom> mesBoms = mesBomRDao.findByHqlWhere(ddlPackBean);
if (CollectionUtils.isEmpty(mesBoms)) {
execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("物料【%s】生产版本【%s】对应bom信息不存在", mesPart.getPartNo(), mesProductVersion.getProductVersion()));
}
oldMesWorkOrder.setNum(mesWorkOrderList.size());
oldMesWorkOrder.setReportedQty(MathOperation.add(oldMesWorkOrder.getNum(), oldMesWorkOrder.getReportedQty()));
//更新SAP计划完成数量
saveMesProductPlan(oldMesWorkOrder, false, true, reqBean, resultBean);
//更新工单状态
double unCompleteQty = MathOperation.sub(oldMesWorkOrder.getQty(), oldMesWorkOrder.getReportedQty());
oldMesWorkOrder.setUnCompleteQty(unCompleteQty > 0 ? unCompleteQty : 0);
if (oldMesWorkOrder.getReportedQty() > oldMesWorkOrder.getQty()) {
execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("工单报工数量【%s】大于工单数量【%s】,不允许报工", oldMesWorkOrder.getReportedQty(), oldMesWorkOrder.getQty()));
} else if (Objects.equals(oldMesWorkOrder.getReportedQty(), oldMesWorkOrder.getQty())) {
oldMesWorkOrder.setWorkOrderStatus(MesExtEnumUtil.ORDER_STATUS.COMPLETE.getValue());
} else {
oldMesWorkOrder.setWorkOrderStatus(MesExtEnumUtil.ORDER_STATUS.PROCESS.getValue());
}
ConvertBean.serviceModelUpdate(oldMesWorkOrder,userName);
workOrderRepository.update(oldMesWorkOrder);
//保存数据
List<MesProductOffLine> mesProductOffLineList = new ArrayList<>();
List<MesMove> mesMoveList = new ArrayList<>();
//条码
List<String> snList = mesProduceSnList.stream().map(MesProduceSn::getProductSn).collect(Collectors.toList());
//物料信息
Map<String, List<MesPartSap>> partSapMap = new HashMap<>();
boolean isReport = false;
boolean isMove = false;
//排序加工规则
MesProdRuleSortCfg mesProdRuleSortCfg = getMesProdRuleSortCfg(oldMesWorkOrder);
if (Objects.isNull(mesProdRuleSortCfg)){
execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("产线【%s】物料【%s】排序加工规则未维护", oldMesWorkOrder.getWorkCenterCode(), oldMesWorkOrder.getPartNo()));
}
if(MesExtEnumUtil.MES_REPORT_TYPE.REPORT.getValue() == mesProdRuleSortCfg.getReportType()){
isReport = true;
} else if (MesExtEnumUtil.MES_REPORT_TYPE.MOVE.getValue() == mesProdRuleSortCfg.getReportType()) {
isMove = true;
}else if (MesExtEnumUtil.MES_REPORT_TYPE.REPORT_MOVE.getValue() == mesProdRuleSortCfg.getReportType()) {
isReport = true;
isMove = true;
}else if (MesExtEnumUtil.MES_REPORT_TYPE.CUSTOMER_SUPPLY_MOVE.getValue() == mesProdRuleSortCfg.getReportType()) {
partSapMap = customerSupplyMove(oldMesWorkOrder, mesProductVersion, mesBoms, snList, mesProductOffLineList, mesMoveList);
}else{
log.info("工单{}排序加工规则报工类型未维护",oldMesWorkOrder.getWorkOrderNo());
return;
}
//查询SAP物料信息
List<MesPartSap> mesPartSaps = partSapMap.get(oldMesWorkOrder.getPartNo());
if (mesPartSaps.isEmpty()){
execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("产线【%s】物料【%s】物料信息不存在", oldMesWorkOrder.getWorkCenterCode(), oldMesWorkOrder.getPartNo()));
}
MesPartSap mesPartSap = mesPartSaps.get(0);
for (String sn : snList) {
//成品汇报
if(isReport){
for (MesBom mesBom : mesBoms) {
mesProductOffLineList.add(creatMesProductOffLine(oldMesWorkOrder, mesProductVersion, sn, mesBom,false));
}
}
//成品移库
if(isMove){
MesMove move = createMove(mesPartSap, mesProdRuleSortCfg.getSrcErpLocation(), mesProdRuleSortCfg.getDestErpLocation(), oldMesWorkOrder.getOrganizeCode(), 1d,sn,MesExtEnumUtil.MOVE_TYPE.FINISH_PRODUCTS_MOVE.getValue());
move.setMatnr(oldMesWorkOrder.getPartNo());
mesMoveList.add(move);
}
}
//保存报工记录
mesProductOffLineRDao.saveAll(mesProductOffLineList);
//保存移库记录
mesMoveRDao.saveAll(mesMoveList);
}
}
private void saveMesProductPlan(MesWorkOrder bean, boolean isInsert, boolean isReport,StationRequestBean reqBean, StationResultBean resultBean) {
if (StringUtil.isEmpty(bean.getPlanOrderNo())) {
DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(bean.getOrganizeCode());
DdlPreparedPack.getStringEqualPack(bean.getPartNo(), "planPartNo", ddlPackBean);
DdlPreparedPack.getStringEqualPack(bean.getPlanStartTime(), "planStartDate", ddlPackBean);
DdlPreparedPack.getStringEqualPack(bean.getPlanEndTime(), "planEndDate", ddlPackBean);
MesProductPlan mesProductPlan = mesProductPlanRDao.getByProperty(ddlPackBean);
if (null == mesProductPlan) {
MesProductPlan mesPlanOrder = new MesProductPlan();
mesPlanOrder.setPlanOrderNo("");
mesPlanOrder.setPlanQty(bean.getQty());
mesPlanOrder.setPlanPartNo(bean.getPartNo());
mesPlanOrder.setCompleteQty(0d);
mesPlanOrder.setUncompleteQty(bean.getQty());
mesPlanOrder.setUnit(bean.getUnit());
mesPlanOrder.setPlanStartDate(bean.getPlanStartTime());
mesPlanOrder.setPlanEndDate(bean.getPlanEndTime());
mesPlanOrder.setPartMappingWorkCenterCode(bean.getErpWorkCenter());
mesPlanOrder.setPlanOrganizeCode(bean.getOrganizeCode());
mesPlanOrder.setOrganizeCode(bean.getOrganizeCode());
ConvertBean.serviceModelInitialize(mesPlanOrder, bean.getCreateUser());
mesProductPlanRDao.insert(mesPlanOrder);
} else {
if (isInsert) {
mesProductPlan.setPlanQty(MathOperation.add(mesProductPlan.getPlanQty(), bean.getQty()));
} else {
//报工
if (isReport) {
mesProductPlan.setCompleteQty(MathOperation.add(mesProductPlan.getCompleteQty(), bean.getNum()));
//报工调整
} else {
mesProductPlan.setCompleteQty(MathOperation.sub(mesProductPlan.getCompleteQty(), bean.getNum()));
}
}
mesProductPlan.setUncompleteQty(MathOperation.sub(mesProductPlan.getPlanQty(), mesProductPlan.getCompleteQty()));
ConvertBean.serviceModelUpdate(mesProductPlan, bean.getCreateUser());
mesProductPlanRDao.update(mesProductPlan);
}
} else {
DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(bean.getOrganizeCode());
DdlPreparedPack.getStringEqualPack(bean.getPlanOrderNo(), "planOrderNo", ddlPackBean);
DdlPreparedPack.getStringEqualPack(bean.getPartNo(), "planPartNo", ddlPackBean);
MesProductPlan mesProductPlan = mesProductPlanRDao.getByProperty(ddlPackBean);
if (null == mesProductPlan) {
execExpSendMsgAndThrowEx(reqBean, resultBean, String.format("SAP计划单号【%s】物料【%s】,不存在", bean.getPlanOrderNo(), bean.getPartNo()));
}
if (!isInsert) {
if (Objects.isNull(mesProductPlan.getCompleteQty())) {
mesProductPlan.setCompleteQty(0d);
}
//报工
if (isReport) {
mesProductPlan.setCompleteQty(MathOperation.add(mesProductPlan.getCompleteQty(), bean.getNum()));
//报工调整
} else {
mesProductPlan.setCompleteQty(MathOperation.sub(mesProductPlan.getCompleteQty(), bean.getNum()));
}
mesProductPlan.setUncompleteQty(MathOperation.sub(mesProductPlan.getPlanQty(), mesProductPlan.getCompleteQty()));
ConvertBean.serviceModelUpdate(mesProductPlan, bean.getCreateUser());
mesProductPlanRDao.update(mesProductPlan);
}
}
}
private MesProdRuleSortCfg getMesProdRuleSortCfg(MesWorkOrder mesWorkOrder) {
DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(mesWorkOrder.getOrganizeCode());
DdlPreparedPack.getStringEqualPack(mesWorkOrder.getPartNo(),"reportPartNo",ddlPackBean);
DdlPreparedPack.getStringEqualPack(mesWorkOrder.getWorkCenterCode(),"workCenterCode",ddlPackBean);
MesProdRuleSortCfg mesProdRuleSortCfg = mesProdRuleSortCfgRDao.getByProperty(ddlPackBean);
return mesProdRuleSortCfg;
}
private Map<String, List<MesPartSap>> customerSupplyMove(MesWorkOrder mesWorkOrder, MesProductVersion mesProductVersion, List<MesBom> mesBoms, List<String> resultList, List<MesProductOffLine> mesProductOffLineList, List<MesMove> mesMoveList) {
boolean isItemMove;
boolean isItemReport;
MesMoveRule moveRule;
//查询零件生产组的移库规则
List<MesMoveRule> moveRules = this.findMesMoveRuleByPartProdGroupCode(mesWorkOrder.getPartProdGroupCode(), mesWorkOrder.getOrganizeCode());
Map<String, List<MesMoveRule>> mesMoveRuleMap = moveRules.stream().filter(t -> Objects.nonNull(t.getSrcType())).collect(Collectors.groupingBy(MesMoveRule::getSrcType));
List<String> itemPartNoList = mesBoms.stream().map(MesBom::getItemPartNo).collect(Collectors.toList());
//子物料SAP下发信息
Map<String, List<MesPartSap>> mesPartSapMap = getPartSapMap(mesWorkOrder, itemPartNoList);
//获取物料信息
Map<String, List<MesPart>> itemPartMap = getItemPartMap(mesWorkOrder, itemPartNoList);
for (String sn : resultList) {
for (MesBom mesBom : mesBoms) {
isItemReport = false;
isItemMove = false;
moveRule = null;
if(itemPartMap.containsKey(mesBom.getItemPartNo())){
MesPart itemPart = itemPartMap.get(mesBom.getItemPartNo()).iterator().next();
if(!StringUtil.isEmpty(itemPart.getEsd()) && mesMoveRuleMap.containsKey(itemPart.getEsd())){
moveRule = mesMoveRuleMap.get(itemPart.getEsd()).iterator().next();
if (MesExtEnumUtil.MOVE_TYPE_REPORT_TYPE.REPORT_MOVE.getValue() == moveRule.getReportType()) {
isItemMove = true;
isItemReport = true;
} else if (MesExtEnumUtil.MOVE_TYPE_REPORT_TYPE.REPORT.getValue() == moveRule.getReportType()) {
isItemReport = true;
} else if (MesExtEnumUtil.MOVE_TYPE_REPORT_TYPE.MOVE.getValue() == moveRule.getReportType()) {
isItemMove = true;
}
}
}
//汇报
if(isItemReport){
mesProductOffLineList.add(creatMesProductOffLine(mesWorkOrder, mesProductVersion, sn, mesBom,true));
}
//移库
if(isItemMove){
MesPartSap mesPartSap = null;
if(mesPartSapMap.containsKey(mesBom.getItemPartNo())){
mesPartSap = mesPartSapMap.get(mesBom.getItemPartNo()).iterator().next();
}
MesMove move = createMove(mesPartSap, moveRule.getErpSrcLocateNo(), moveRule.getErpDestLocateNo(), mesBom.getOrganizeCode(), mesBom.getItemQty(),"",MesExtEnumUtil.MOVE_TYPE.RAW_MATERIAL_MOVE.getValue());
move.setMatnr(mesBom.getItemPartNo());
mesMoveList.add(move);
}
}
}
//子物料SAP下发信息
return mesPartSapMap ;
}
private List<MesMoveRule> findMesMoveRuleByPartProdGroupCode(String partProdGroupCode, String organizeCode) {
DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(organizeCode);
DdlPreparedPack.getStringEqualPack(partProdGroupCode, "partProdGroupCode", ddlPackBean);
List<MesMoveRule> moveRules = moveRuleRao.findByHqlWhere(ddlPackBean);
return moveRules;
}
private Map<String, List<MesPartSap>> getPartSapMap(MesWorkOrder mesWorkOrder, List<String> itemPartNoList) {
DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(mesWorkOrder.getOrganizeCode());
DdlPreparedPack.getInPackList(itemPartNoList, "partNo", ddlPackBean);
List<MesPartSap> mesPartSapList = mesPartSapRao.findByHqlWhere(ddlPackBean);
Map<String, List<MesPartSap>> mesPartSapMap = mesPartSapList.stream().filter(t -> Objects.nonNull(t.getPartNo())).collect(Collectors.groupingBy(MesPartSap::getPartNo));
return mesPartSapMap;
}
private Map<String, List<MesPart>> getItemPartMap(MesWorkOrder mesWorkOrder, List<String> itemPartNoList) {
DdlPackBean ddlPackBean = DdlPackBean.getDdlPackBean(mesWorkOrder.getOrganizeCode());
DdlPreparedPack.getInPackList(itemPartNoList, "partNo", ddlPackBean);
List<MesPart> mesPartList = partRao.findByHqlWhere(ddlPackBean);
Map<String, List<MesPart>> itemPartMap = mesPartList.stream().filter(t -> Objects.nonNull(t.getPartNo())).collect(Collectors.groupingBy(MesPart::getPartNo));
return itemPartMap;
}
private MesProductOffLine creatMesProductOffLine(MesWorkOrder mesWorkOrder, MesProductVersion mesProductVersion,
String sn, MesBom mesBom,boolean isItemReport) {
MesProductOffLine newMesProductOffLine;
newMesProductOffLine = new MesProductOffLine();
if(!isItemReport){
newMesProductOffLine.setReportPartNo(mesWorkOrder.getPartNo());
newMesProductOffLine.setReportPartNameRdd(mesWorkOrder.getPartName());
}
newMesProductOffLine.setReportSn(sn);
newMesProductOffLine.setItemPartNo(mesBom.getItemPartNo());
newMesProductOffLine.setItemPartName(mesBom.getItemPartName());
newMesProductOffLine.setItemQty(mesBom.getItemQty());
newMesProductOffLine.setAlort(mesProductVersion.getReceiveInventoryPoint());
newMesProductOffLine.setStgeLoc(mesProductVersion.getShipInventoryPoint());
newMesProductOffLine.setQty(1d);
newMesProductOffLine.setBomVersion(mesWorkOrder.getProductVersion());
newMesProductOffLine.setSerialNumber(sn);
newMesProductOffLine.setUnit(mesBom.getUnit());
newMesProductOffLine.setItemUnit(mesBom.getItemUnit());
newMesProductOffLine.setWorkOrderNo(mesWorkOrder.getWorkOrderNo());
newMesProductOffLine.setWorkCenterCode(mesWorkOrder.getWorkCenterCode());
newMesProductOffLine.setWorkCellCode(mesWorkOrder.getWorkCellCode());
newMesProductOffLine.setReportType(mesWorkOrder.getReportType());
newMesProductOffLine.setSapWorkCenter(mesWorkOrder.getErpWorkCenter());
newMesProductOffLine.setOrganizeCode(mesWorkOrder.getOrganizeCode());
ConvertBean.serviceModelInitialize(newMesProductOffLine, mesWorkOrder.getCreateUser());
return newMesProductOffLine;
}
private MesMove createMove(MesPartSap mesPart , String source, String target, String org,double qty,String sn,Integer moveType) {
MesMove move = new MesMove();
if(!Objects.isNull(mesPart)){
move.setMeins(mesPart.getUnit());
}
move.setOrganizeCode(org);
move.setFactoryCode(org);
move.setLgort(source);
move.setUmlgo(target);
move.setMenge(qty);
move.setPostDate(TimeTool.getToday());
move.setProductSn(sn);
move.setMoveType(moveType);
move.setPostTime(TimeTool.getTimeShortWithColon());
ConvertBean.serviceModelInitialize(move, AuthUtil.getSessionUser().getUserName());
return move;
}
}

@ -0,0 +1,60 @@
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.pojo.context.MesProductionPartContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionPsOutContext;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseStepService;
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 java.util.List;
import java.util.stream.Collectors;
/**
* @Description :
* @Reference :
* @Author : Castle
* @CreateDate : 2024/6/11 18:50
* @Modify:
**/
@Slf4j
@Service("mesWorkOrderSaveStepService")
public class MesWorkOrderSaveStepService extends BaseStepService {
@Autowired
private IMesProductionProcessContextStepService productionProcessContextStepService;
@Autowired
private IMesProductionDispatchContextStepService productionDispatchContextStepService;
@Override
public StepResult execute(StationRequestBean reqBean) {
StationResultBean resultBean = new StationResultBean();
StepResult stepResult = StepResult.getSuccessComplete();
//1. 获取上下文中的MesProductionPartContext
List<MesProductionPartContext> productionPartContext = productionDispatchContextStepService.getProductionPartContext(reqBean);
if (productionPartContext.isEmpty()){
return execSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, "没有可保存的加工单信息");
}
//2. 判断是否为空,id是否为空如果没有则返回,id为工单id
List<MesProductionPartContext> collectContext = productionPartContext.stream().filter(item -> item.getId() != null).collect(Collectors.toList());
//3. 如果id不为空查询工单信息
if (collectContext.isEmpty()){
return execSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, "没有可保存的加工单信息");
}
//4. 判断当前产出的零件MesProductionPsOutContext中是否有id如果有就是新生成的
List<MesProductionPsOutContext> productionPsOutContext = productionDispatchContextStepService.getProductionPsOutContext(reqBean);
//过滤出新生成的条码没有条码id就是新生成的
List<MesProductionPsOutContext> produceSnList = productionPsOutContext.stream().filter(item -> item.getId() != null).collect(Collectors.toList());
if (produceSnList.isEmpty()){
return execSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, "没有可保存的加工单信息");
}
// productionPsOutContext.stream().collect(Collectors.groupingBy(MesProductionPsOutContext::getId))
//5. 修改完成数量,完成数量大于计划数量,就需要修改工单的状态为完成
return execSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(), stepResult, "保存加工单信息成功");
}
}

@ -66,7 +66,9 @@ public class MesProdRuleContext implements Serializable {
@ApiParam(name = "是否有装配件")
private Integer isHasBind;
/**
*
*/
@ApiParam(name = "汇报方式")
private Integer reportType;

@ -10,6 +10,11 @@ package cn.estsh.i3plus.ext.mes.pcn.pojo.util;
public class MesPcnExtConstWords {
//-----------------COMMON--------------------------
//拼接00时:00分:00秒
public static final String APPEND_ZERO_HMS = " 00:00:00";
//拼接23时:59分:59秒
public static final String APPEND_24_HMS = " 23:59:59";
public static final String REDIS_RES_PCN = "redisMesPcn";
// id常量

Loading…
Cancel
Save