package org.springblade.mdm.flow.task.cure; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; import org.checkerframework.checker.units.qual.N; import org.flowable.engine.delegate.DelegateExecution; import org.springblade.core.oss.OssTemplate; import org.springblade.core.oss.model.BladeFile; import org.springblade.core.tool.api.R; import org.springblade.core.tool.utils.DateUtil; import org.springblade.mdm.basesetting.machine.MachineService; import org.springblade.mdm.basesetting.machine.entity.Machine; import org.springblade.mdm.commons.contants.ParamConstants; import org.springblade.mdm.flow.entity.FlowProgramFile; import org.springblade.mdm.flow.service.FlowCommonService; import org.springblade.mdm.flow.service.FlowProgramFileService; import org.springblade.mdm.flow.service.FlowProgramProperties; import org.springblade.mdm.program.entity.NcNode; import org.springblade.mdm.program.service.NcNodeAutoCreateService; import org.springblade.mdm.program.service.NcNodeService; import org.springblade.mdm.program.service.ProgramAnnotationService; import org.springblade.mdm.utils.FileContentUtil; import org.springblade.system.feign.ISysClient; import org.springblade.system.pojo.entity.Dict; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.time.LocalDate; import java.util.Arrays; import java.util.Date; import java.util.List; @Slf4j @Component("cureFinishOperateTask") @AllArgsConstructor public class CureFinishOperateTask { private final NcNodeService nodeService; private final NcNodeAutoCreateService ncNodeAutoCreateService; private final FlowCommonService flowCommonService; private final FlowProgramFileService flowProgramFileService; private final ISysClient sysClient; private final OssTemplate ossTemplate; private final ProgramAnnotationService programAnnotationService; private final MachineService machineService; public static final String GH = "GH"; /** * 默认有效期间(月数),2年 */ private static final int DEFAULT_VALID_MONTH = 24; private final NcNodeService ncNodeService; /** * 固化审批通过处理任务, * @param execution 流程execution */ @Transactional public void execute(DelegateExecution execution) throws IOException { log.info("执行固化程序任务服务,流程实例id={}", execution.getProcessInstanceId()); //固化程序检查有效期, dealWithNode(execution.getProcessInstanceId()); } /** * 处理node状态。 * @param processInstanceId 流程实例id */ void dealWithNode(String processInstanceId) throws IOException { //程序包节点和下属程序节点(包括历史节点非最新版本的)从试切挪到固化下面 //程序包节点 设置未已固化 NcNode pkgNode = nodeService.lambdaQuery().eq(NcNode::getProcessInstanceId, processInstanceId).one(); if(pkgNode.isDeviationProgram()){ //偏离的程序直接锁定 pkgNode.setIsLocked(1); nodeService.updateById(pkgNode); }else { //试切的 pkgNode.setIsCured(1); //设置过期日期 pkgNode.upgradeVersionNUmber(); pkgNode.setExpireDate(calculateExpireDate()); nodeService.updateById(pkgNode); List historyProgramPackageNodes = nodeService.getNodeHistory(pkgNode); moveNodeToCuredTree(pkgNode, historyProgramPackageNodes, flowCommonService.getProgramProperties(processInstanceId)); } } /** * 将节点和历史节点挪动到固化的同级节点下 * @param pkgNode 要挪动的节点 * @param historyProgramPackageNodes 程序包名 历史节点 */ void moveNodeToCuredTree(NcNode pkgNode,List historyProgramPackageNodes, FlowProgramProperties programProperties) throws IOException { //创建节点到机床级别.(固化树) NcNode machineNode = ncNodeAutoCreateService.createNodeTreeToMachine(programProperties); //机床下现在没有文件了,程序包名升级与机床同级了,改为找到机床同级程序包名更新了 this.nodeService.lambdaUpdate().likeRight(NcNode::getParentIds, machineNode.getParentIds()) .in(NcNode::getNodeType, Arrays.asList(NcNode.TYPE_PROGRAM_PACKAGE,NcNode.TYPE_PROGRAM_FILE)) .set(NcNode::getIsLastEdition,0).set(NcNode::getIsLocked,1).update(); for(NcNode hisPackageNode : historyProgramPackageNodes){ if(!hisPackageNode.getId().equals(pkgNode.getId())){ hisPackageNode.setIsLastEdition(0); } hisPackageNode.setParentId(machineNode.getParentId()); hisPackageNode.setParentIds(machineNode.getParentIds());//程序包与机床节点同级 //处理程序包下层的程序节点 List programNodes = nodeService.lambdaQuery().eq(NcNode::getParentId,hisPackageNode.getId()).list(); for(NcNode programNode : programNodes){ programNode.setIsLastEdition(0); programNode.setParentIds(hisPackageNode.getParentIds()+","+hisPackageNode.getId()); } nodeService.updateBatchById(programNodes); } nodeService.updateBatchById(historyProgramPackageNodes); Machine machine = machineService.getByCode(pkgNode.getMachineCode()); List annoDicts = programAnnotationService.getAnnotionList(); //新的流程文件,需要在包节点下新建,不能用老的 List files = flowProgramFileService.lambdaQuery().eq(FlowProgramFile::getProcessInstanceId,pkgNode.getProcessInstanceId()).list(); for(FlowProgramFile flowProgramFile : files){ NcNode newProgNode = new NcNode(); newProgNode.setName(flowProgramFile.getName()); newProgNode.setNodeType(NcNode.TYPE_PROGRAM_FILE); newProgNode.setParentId(pkgNode.getId()); newProgNode.setParentIds(pkgNode.getParentIds()+","+pkgNode.getId()); newProgNode.setIsLastEdition(1); newProgNode.setVersionNumber(pkgNode.getVersionNumber()); newProgNode.setFlowProgramFileId(flowProgramFile.getId()); newProgNode.setIsCured(1); ncNodeService.save(newProgNode); //修改文件内容更新注释,并更新文件数据的地址 ///替换注释后总是不行啊 setGhAnnotation(flowProgramFile,machine.getMachineGroupCode(),annoDicts); flowProgramFileService.updateById(flowProgramFile); } } /** * 设置固化注释,实现方式,获取文件字节下,修改后替换文件 * @param flowProgramFile oss 文件 * */ void setGhAnnotation(FlowProgramFile flowProgramFile,String machineGroup,List annoDicts) throws IOException { String ossName = flowProgramFile.getOssName(); // try(InputStream ins = ossTemplate.statFileStream(ossName);){ byte[] bytes = IOUtils.toByteArray(ins); ByteArrayInputStream byteInputStream = new ByteArrayInputStream(bytes); String annoTxt = programAnnotationService.generateAnnotation("GH",machineGroup,annoDicts); int statusLineIndex = 2; String line2 = FileContentUtil.readLineAt(byteInputStream,statusLineIndex);//第三行应该是状态注释 byteInputStream.reset(); InputStream finishedStream; if(programAnnotationService.isAnnotation(line2,machineGroup,annoDicts)){ finishedStream = FileContentUtil.replaceAtLine(byteInputStream,statusLineIndex,annoTxt); }else{ finishedStream = FileContentUtil.insertLine(byteInputStream,statusLineIndex,annoTxt); } try(finishedStream) { finishedStream.reset(); BladeFile bfile = ossTemplate.putFile(flowProgramFile.getName(), finishedStream); //替换原有的文件地址 flowProgramFile.setOssName(bfile.getName()); } } } /** * 计算有效期 * @return */ private Date calculateExpireDate() { R validMonResult = sysClient.getParamValue(ParamConstants.CURE_VALID_MONTH_KEY); int month = DEFAULT_VALID_MONTH; if(validMonResult.isSuccess() && validMonResult.getData()!=null){ month = Integer.parseInt(validMonResult.getData()); } LocalDate now = LocalDate.now(); return DateUtil.toDate(now.plusMonths(month)); } }