yangys
2025-08-23 f13fcaa8c4b0f413d8ee100adcb67669db183c68
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
package org.springblade.mdm.flow.excution.cure;
 
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springblade.core.log.exception.ServiceException;
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.core.tool.utils.Func;
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.constants.FlowContants;
import org.springblade.mdm.flow.entity.ApproveRecord;
import org.springblade.mdm.flow.entity.FlowProgramFile;
import org.springblade.mdm.flow.excution.dispatch.FinishDataHandler;
import org.springblade.mdm.flow.service.ApproveRecordService;
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.entity.NcProgramApproved;
import org.springblade.mdm.program.service.NcNodeAutoCreateService;
import org.springblade.mdm.program.service.NcNodeService;
import org.springblade.mdm.program.service.NcProgramApprovedService;
import org.springblade.mdm.program.service.ProgramAnnotationService;
import org.springblade.mdm.utils.EntityUtil;
import org.springblade.system.feign.ISysClient;
import org.springblade.system.pojo.entity.DictBiz;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
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;
import java.util.Optional;
 
/**
 * 普通派工完成数据处理器,功能:插入审批表数据,DispatchFinishListener调用
 */
@Slf4j
@Component("normalCureFinishDataHandler")
public class NormalCureFinishDataHandler implements FinishDataHandler {
    @Autowired
    private NcProgramApprovedService approvedService;
    @Autowired
    private ApproveRecordService approveRecordService;
    @Autowired
    private FlowProgramFileService flowProgramFileService;
    @Autowired
    private NcNodeService nodeService;
    @Autowired
    private NcNodeAutoCreateService ncNodeAutoCreateService;
    @Autowired
    private MachineService machineService;
    @Autowired
    private OssTemplate ossTemplate;
    @Autowired
    private ISysClient sysClient;
    @Autowired
    private ProgramAnnotationService programAnnotationService;
    /**
     * 默认有效期间(月数),2年
     */
    private static final int DEFAULT_VALID_MONTH = 24;
 
    /**
     * DispatchFinishListener中调用
     * @param flowProps 流程属性
     */
    public void handleData(FlowProgramProperties flowProps) {
        // 执行业务逻辑
 
        //需要固化的节点
        NcNode pkgNode = nodeService.lambdaQuery().eq(NcNode::getProcessInstanceId,  flowProps.getProcessInstanceId()).one();
 
        //pkgNode.setIsLastEdition(0);
        //nodeService.updateById(pkgNode);
 
        List<NcNode> historyProgramPackageNodes = nodeService.getNodeHistory(pkgNode);
        try {
            moveNodeToCuredTree(pkgNode, historyProgramPackageNodes, flowProps);
        }catch(Exception e) {
            log.error("固化流程完成异常",e);
            throw new ServiceException("普通固化执行异常"+e.getMessage());
        }
        addApproveTable(pkgNode,flowProps);
        updateApproveRecordNodeId(flowProps.getProcessInstanceId(), pkgNode.getId());
    }
 
 
    /**
     * 将节点和历史节点挪动到固化的同级节点下
     * @param pkgNode 要固化的节点
     * @param historyProgramPackageNodes 程序包名 历史节点
     */
    void moveNodeToCuredTree(NcNode pkgNode1,List<NcNode> historyProgramPackageNodes, FlowProgramProperties programProperties) throws IOException {
 
        //创建节点到机床级别.(固化树)
        NcNode machineNode = ncNodeAutoCreateService.createNodeTreeToMachine(programProperties);
 
        pkgNode1.setParentId(machineNode.getParentId());
        pkgNode1.setParentIds(machineNode.getParentIds());//更新上级节点,下面还要用应为在historyProgramPackageNodes中的和这个不是一个实例
 
        //新建一个节点,作为固化节点,老节点保留不动,置为老版本
 
 
        //机床下现在没有文件了,程序包名升级与机床同级了,改为找到机床同级程序包名更新了
        //TODO 这个parentIds是不是不够?,不够,一个机床下多个程序包的情况不行吧,但是按照树,多个程序包不太现实
        this.nodeService.lambdaUpdate().likeRight(NcNode::getParentIds, machineNode.getParentIds())
            .in(NcNode::getNodeType, Arrays.asList(NcNode.TYPE_PROGRAM_PACKAGE,NcNode.TYPE_PROGRAM_FILE))
            //.ne(NcNode::getId,cureNode.getId())//不要更新新固化的节点
            .set(NcNode::getIsLastEdition,0).set(NcNode::getIsLocked,1).update();
 
        NcNode cureNode = createNewCureNodeByTargetNode(pkgNode1);
        for(NcNode hisPackageNode : historyProgramPackageNodes){
            //if(!hisPackageNode.getId().equals(pkgNode.getId())){
                hisPackageNode.setIsLastEdition(0);
            //}
            hisPackageNode.setParentId(machineNode.getParentId());
            hisPackageNode.setParentIds(machineNode.getParentIds());//程序包与机床节点同级
 
            //处理程序包下层的程序节点,这里:老的程序节点不用更新为历史版本,因为会建立新节点。只修改parentId 和 parentIds
            List<NcNode> oriProgramNodes = nodeService.lambdaQuery().eq(NcNode::getParentId,hisPackageNode.getId()).list();
            FlowProgramFile pfile;
            for(NcNode oldProgramNode : oriProgramNodes){
                oldProgramNode.setParentIds(hisPackageNode.getParentIds()+","+hisPackageNode.getId());
                //oldProgramNode.setIsLastEdition(0);
 
                pfile = flowProgramFileService.getById(oldProgramNode.getFlowProgramFileId());
                if(oldProgramNode.getParentId().equals(pkgNode1.getId()) && !pfile.isProgram()){
                    //当前固化程序包名下的“其他文件”非程序文件。不设置为老版本,直接挪到固化树下,两个网络之间只交换程序文件,其他文件只能保留
                    //oldProgramNode.setIsLastEdition(1);
                    //其他文件,需要复制到新建的固化节点下
                    NcNode newOtherFileNode = new NcNode();
                    BeanUtils.copyProperties(oldProgramNode,newOtherFileNode);
                    EntityUtil.clearBaseProperties(newOtherFileNode);
                    newOtherFileNode.setParentId(cureNode.getId());
                    newOtherFileNode.setParentIds(cureNode.getParentIds()+","+cureNode.getId());
                    newOtherFileNode.setIsLastEdition(1);
                    nodeService.save(newOtherFileNode);
                }
 
            }
            nodeService.updateBatchById(oriProgramNodes);
        }
        nodeService.updateBatchById(historyProgramPackageNodes);
 
        Machine machine = machineService.getByCode(cureNode.getMachineCode());
        List<DictBiz> annoDicts = programAnnotationService.getAnnotionList();
        //新的流程文件,需要在包节点下新建,不能用老的
        List<FlowProgramFile> files = flowProgramFileService.lambdaQuery().eq(FlowProgramFile::getProcessInstanceId,pkgNode1.getProcessInstanceId()).list();
        for(FlowProgramFile flowProgramFile : files){
            NcNode newProgNode = new NcNode();
 
            BeanUtils.copyProperties(cureNode,newProgNode);
            EntityUtil.clearBaseProperties(newProgNode);
 
            newProgNode.setName(flowProgramFile.getName());
            newProgNode.setNodeType(NcNode.TYPE_PROGRAM_FILE);
            newProgNode.setParentId(cureNode.getId());
            newProgNode.setParentIds(cureNode.getParentIds()+","+cureNode.getId());
            newProgNode.setIsLastEdition(1);
            newProgNode.setFlowProgramFileId(flowProgramFile.getId());
            newProgNode.setIsCured(1);
 
            setGhAnnotation(flowProgramFile,machine.getMachineGroupCode(),annoDicts);
 
            nodeService.save(newProgNode);
        }
 
 
    }
 
    /**
     * 复制待固化节点数据,创建一个新的固化节点
     * @param waitingCureNode 待固化节点
     * @return 固化节点
     */
    NcNode createNewCureNodeByTargetNode(NcNode waitingCureNode){
        //新建一个节点,作为固化节点,老节点保留不动
        NcNode cureNode = new NcNode();
        BeanUtils.copyProperties(waitingCureNode, cureNode);
        EntityUtil.clearBaseProperties(cureNode);
        cureNode.setIsCured(1);
        cureNode.setIsLocked(NcNode.UNLOCK);
        cureNode.setIsLastEdition(1);
        cureNode.setExpireDate(calculateExpireDate());//设置过期日期
 
        Optional<NcNode> optOldCuredPackageNode = nodeService.lambdaQuery().eq(NcNode::getName,waitingCureNode.getName())
            .eq(NcNode::getProcessNo,waitingCureNode.getProcessNo())
            .eq(NcNode::getProcessEdition,waitingCureNode.getProcessEdition())
            .eq(NcNode::getIsLastEdition,1).eq(NcNode::getIsCured,1).oneOpt();
 
        if(optOldCuredPackageNode.isEmpty()){
            //之前 没有已固化的程序包名,则直接更新版本号,如果有,那就使用node现在的版本号,因为不可用转为试切,审批完成已经升级version
            cureNode.upgradeVersionNumber();
        }
 
        nodeService.save(cureNode);
 
        return cureNode;
    }
    /**
     * 设置固化注释,实现方式,获取文件字节下,修改后替换文件
     * @param flowProgramFile oss 文件
     *
     */
    void setGhAnnotation(FlowProgramFile flowProgramFile,String machineGroup,List<DictBiz> annoDicts) throws IOException {
        String ossName = flowProgramFile.getOssName();
        //
        try(InputStream ins = ossTemplate.statFileStream(ossName);){
            byte[] bytes = IOUtils.toByteArray(ins);
            ByteArrayInputStream byteInputStream =  new ByteArrayInputStream(bytes);
 
            InputStream finishedStream = programAnnotationService.setGHAnnotation(byteInputStream,machineGroup,annoDicts);
 
            try(finishedStream) {
                finishedStream.reset();
                BladeFile bfile = ossTemplate.putFile(flowProgramFile.getName(), finishedStream);
                //替换原有的文件地址
                flowProgramFile.setOssName(bfile.getName());
 
                flowProgramFileService.updateById(flowProgramFile);
            }
        }
    }
 
    /**
     * 计算有效期
     * @return
     */
    private Date calculateExpireDate() {
        R<String> 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));
    }
 
    /**
     * 保存审批完成的记录
     * @param packageNode
     * @param props
     */
    void addApproveTable(NcNode packageNode,FlowProgramProperties props){
        NcProgramApproved approved = new NcProgramApproved();
 
        approved.setProgramName(packageNode.getName());
        approved.setNcNodeId(packageNode.getId());//程序包节点id
        approved.setTitle(props.getTitle());
        approved.setProgrammerId(props.getProgrammerId());
        approvedService.save(approved);
 
    }
 
 
    void updateApproveRecordNodeId(String processInstanceId,Long nodeId){
        //更新审批记录的ncNodeId
        approveRecordService.lambdaUpdate()
            .eq(ApproveRecord::getProcessInstanceId, processInstanceId)
            .set(ApproveRecord::getNcNodeId,nodeId).update();
    }
}