Lius
2024-01-15 cca0e9fe9d471799538ddc277baa6e79778c3adb
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
274
275
276
277
package org.jeecg.modules.mdc.service.impl;
 
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.modules.mdc.constant.MdcConstant;
import org.jeecg.modules.mdc.entity.MdcEquipment;
import org.jeecg.modules.mdc.entity.MdcOverallEquipmentEfficiency;
import org.jeecg.modules.mdc.entity.MdcStandardProcessDuration;
import org.jeecg.modules.mdc.mapper.MdcOverallEquipmentEfficiencyMapper;
import org.jeecg.modules.mdc.service.*;
import org.jeecg.modules.mdc.util.DateUtils;
import org.jeecg.modules.mdc.vo.MdcOverallEquipmentEfficiencyVo;
import org.springframework.stereotype.Service;
 
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.YearMonth;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
/**
 * @author: LiuS
 * @create: 2023-10-18 09:25
 */
@Service
public class MdcOverallEquipmentEfficiencyServiceImpl extends ServiceImpl<MdcOverallEquipmentEfficiencyMapper, MdcOverallEquipmentEfficiency> implements IMdcOverallEquipmentEfficiencyService {
 
    @Resource
    private IMdcEquipmentService mdcEquipmentService;
 
    @Resource
    private IMdcEquipmentOvertimeService mdcEquipmentOvertimeService;
 
    @Resource
    private IMdcDeviceCalendarService mdcDeviceCalendarService;
 
    @Resource
    private IMdcNoplanCloseService mdcNoplanCloseService;
 
    @Resource
    private IMdcPlanCloseService mdcPlanCloseService;
 
    @Resource
    private IMdcPassRateService mdcPassRateService;
 
    @Resource
    private IMdcStandardProcessDurationService mdcStandardProcessDurationService;
 
    @Resource
    private IMdcEquipmentStatisticalShiftInfoService mdcEquipmentStatisticalShiftInfoService;
 
    @Resource
    private IProcessCountService processCountService;
 
    /**
     * 计算设备综合效率OEE
     */
    @Override
    public void runningOverallEquipmentEfficiency(String dateTime) {
        /*
            OEE = 时间开动率 × 性能开动率 × 合格品率
            时间开动率 = (负荷时间 - 非计划停机时间) / 负荷时间 × 100%
            性能开动率 = 净开动时间 / 开动时间 × 100%
            合格品率 = 加工数量 - 不合格数量 / 加工数量
            负荷时间 = 日历工作时间 - 计划停机时间
            非计划停机时间 = 负荷时间 - 主轴运转时间
            工作日历时间 = 日历时间 - 法定假日 - 双休日 + 加班时间
            净开动时间 = 标准加工时间 × 加工数量
         */
        List<MdcOverallEquipmentEfficiency> result = new ArrayList<>();
        // 获取有效日期 格式 yyyy-MM
        String validDate = YearMonth.now().minusMonths(1).toString();
        if (StringUtils.isNotBlank(dateTime)) {
            validDate = DateUtils.format(DateUtils.toDate(dateTime, "yyyyMM"), DateUtils.STR_YEAR_MONTH);
            try {
                if (validDate != null) {
                    this.remove(new LambdaQueryWrapper<MdcOverallEquipmentEfficiency>().
                            eq(MdcOverallEquipmentEfficiency::getValidDate, validDate));
                }
            } catch (Exception e) {
                log.error("参数格式不对", e);
            }
        }
        // 获取设备列表
//        List<MdcEquipment> equipmentList = mdcEquipmentService.list(new LambdaQueryWrapper<MdcEquipment>().eq(MdcEquipment::getEquipmentId, "2140198"));
        List<MdcEquipment> equipmentList = mdcEquipmentService.list();
        for (MdcEquipment mdcEquipment : equipmentList) {
            String equipmentId = mdcEquipment.getEquipmentId();
 
            MdcOverallEquipmentEfficiency mdcOverallEquipmentEfficiency = new MdcOverallEquipmentEfficiency();
            // 时间开动率计算
            mdcOverallEquipmentEfficiency.setEquipmentId(equipmentId);
            mdcOverallEquipmentEfficiency.setEquipmentName(mdcEquipment.getEquipmentName());
            mdcOverallEquipmentEfficiency.setEquipmentModel(mdcEquipment.getEquipmentModel());
            mdcOverallEquipmentEfficiency.setValidDate(validDate);
 
            // 查询班制分类
            List<String> shiftSubIdList = mdcDeviceCalendarService.findShiftSort(equipmentId, validDate);
            if (shiftSubIdList != null && !shiftSubIdList.isEmpty()) {
                String shift = String.join(",", shiftSubIdList);
                mdcOverallEquipmentEfficiency.setShift(shift);
            }
 
//            BigDecimal shiftTimeCount = mdcDeviceCalendarService.computeShiftTimeCount(equipmentId, validDate);
            mdcOverallEquipmentEfficiency.setShiftTimeCount(new BigDecimal("8"));
 
            // 计算加班时间
            BigDecimal overtime = mdcEquipmentOvertimeService.computeOvertime(equipmentId, validDate);
            mdcOverallEquipmentEfficiency.setOvertime(overtime);
 
            // 计算实际班产天数
            BigDecimal actualWorkDayCount = mdcDeviceCalendarService.computeActualWorkDayCount(equipmentId, validDate);
            mdcOverallEquipmentEfficiency.setActualWorkDayCount(actualWorkDayCount);
 
            // 月度实际班产总时间(分钟)
            mdcOverallEquipmentEfficiency.setMonthActualWorkDayTimeCount(mdcOverallEquipmentEfficiency.getShiftTimeCount().add(overtime));
 
            // 故障停机时长统计(分钟)
            BigDecimal breakdownDownDuration = mdcNoplanCloseService.findNoplanTimeDuration(equipmentId, validDate, MdcConstant.BREAKDOWN_DOWN);
            mdcOverallEquipmentEfficiency.setBreakdownDownDuration(breakdownDownDuration);
            // 换型调试时长统计(分钟)
            BigDecimal conversionDebugDuration = mdcNoplanCloseService.findNoplanTimeDuration(equipmentId, validDate, MdcConstant.CONVERSION_DEBUG);
            mdcOverallEquipmentEfficiency.setConversionDebugDuration(conversionDebugDuration);
            // 物料短缺时长统计(分钟)
            BigDecimal materialShortageDuration = mdcNoplanCloseService.findNoplanTimeDuration(equipmentId, validDate, MdcConstant.MATERIAL_SHORTAGE);
            mdcOverallEquipmentEfficiency.setMaterialShortageDuration(materialShortageDuration);
            // 计划等任务时长统计(分钟)
            BigDecimal plannedTaskDuration = mdcNoplanCloseService.findNoplanTimeDuration(equipmentId, validDate, MdcConstant.PLANNED_TASK);
            mdcOverallEquipmentEfficiency.setPlannedTaskDuration(plannedTaskDuration);
            // 检验时长统计(分钟)
            BigDecimal inspectDuration = mdcNoplanCloseService.findNoplanTimeDuration(equipmentId, validDate, MdcConstant.INSPECT);
            mdcOverallEquipmentEfficiency.setInspectDuration(inspectDuration);
            // 其他时长统计(分钟)
            BigDecimal otherDuration = mdcNoplanCloseService.findNoplanTimeDuration(equipmentId, validDate, MdcConstant.OTHER);
            mdcOverallEquipmentEfficiency.setOtherDuration(otherDuration);
            // 计划保养时长统计(分钟)
            BigDecimal plannedMaintenanceDuration = mdcPlanCloseService.findPlanTimeDuration(actualWorkDayCount, MdcConstant.PLANNED_MAINTENANCE);
            mdcOverallEquipmentEfficiency.setPlannedMaintenanceDuration(plannedMaintenanceDuration);
            // 会议/培训时长统计(分钟)
            BigDecimal conferenceTrainingDuration = mdcPlanCloseService.findPlanTimeDuration(actualWorkDayCount, MdcConstant.CONFERENCE_TRAINING);
            mdcOverallEquipmentEfficiency.setConferenceTrainingDuration(conferenceTrainingDuration);
            // 其它休息时长统计(分钟)
            BigDecimal otherRestDuration = mdcPlanCloseService.findPlanTimeDuration(actualWorkDayCount, MdcConstant.OTHER_REST);
            mdcOverallEquipmentEfficiency.setOtherRestDuration(otherRestDuration);
            /*
                负荷时间(小时) = 工作日历时间 - 计划停机时间
                工作日历时间 = 日历时间 - 法定假日 - 双休日 + 加班时间
                计划停机时间 = 计划保养时长 + 会议/培训时长 + 会议/培训时长
             */
            // mdcOverallEquipmentEfficiency.getShiftTimeCount() - plannedMaintenanceDuration - conferenceTrainingDuration - otherRestDuration
            // 负荷时间(分钟)
            BigDecimal loadTime = mdcOverallEquipmentEfficiency.getShiftTimeCount().subtract(plannedMaintenanceDuration).subtract(conferenceTrainingDuration).subtract(otherRestDuration);
            if (loadTime.compareTo(BigDecimal.ZERO) > -1) {
                loadTime = BigDecimal.ZERO;
            }
            mdcOverallEquipmentEfficiency.setLoadTime(loadTime.divide(new BigDecimal("60"), 1, RoundingMode.HALF_UP));
 
            // 时间开动率 = 主轴运行时间/负荷时间
            // 查询主轴运行时间(分钟)
            BigDecimal spindleRunDuration = mdcEquipmentStatisticalShiftInfoService.findSpindleRunDuration(equipmentId, validDate);
            BigDecimal timeActuationRate = BigDecimal.ZERO;
            if (loadTime.compareTo(BigDecimal.ZERO) == 0) {
                mdcOverallEquipmentEfficiency.setTimeActuationRate(BigDecimal.ZERO);
            } else {
                timeActuationRate = spindleRunDuration.divide(loadTime, 4, RoundingMode.HALF_UP);
                mdcOverallEquipmentEfficiency.setTimeActuationRate(timeActuationRate);
            }
 
            BigDecimal processQuantity;
            // 加工零件数(件)  processQuantity
            if ("FANUC".equals(mdcEquipment.getDriveType())) {
                processQuantity = processCountService.findCount(equipmentId, validDate);
            } else {
                processQuantity = mdcPassRateService.findProcessQuantity(equipmentId, validDate);
            }
            mdcOverallEquipmentEfficiency.setProcessQuantity(processQuantity);
 
            // 标准加工时间(分钟)
            MdcStandardProcessDuration mdcStandardProcessDuration = mdcStandardProcessDurationService.getOne(new LambdaQueryWrapper<MdcStandardProcessDuration>().eq(MdcStandardProcessDuration::getEquipmentId, equipmentId));
            if (mdcStandardProcessDuration != null) {
                mdcOverallEquipmentEfficiency.setStandardProcessDuration(new BigDecimal(mdcStandardProcessDuration.getDuration()).multiply(processQuantity));
            } else {
                mdcOverallEquipmentEfficiency.setStandardProcessDuration(BigDecimal.ZERO);
            }
 
            if ("FANUC".equals(mdcEquipment.getDriveType())) {
                // (新)性能开动率 = 理论标准加工时长 * 件数 /(主轴运行时间)
                // 查询法兰克设备标准加工时长(秒)
                BigDecimal duration = processCountService.findDuration(mdcEquipment.getEquipmentId(), validDate);
                if (spindleRunDuration.compareTo(BigDecimal.ZERO) != 0 && duration.compareTo(BigDecimal.ZERO) != 0) {
                    mdcOverallEquipmentEfficiency.setStandardProcessDuration(duration.divide(new BigDecimal("60"), 0, RoundingMode.HALF_UP));
                    BigDecimal performanceRate = duration.divide(new BigDecimal("60"), 0, RoundingMode.HALF_UP).divide(spindleRunDuration, 4, RoundingMode.HALF_UP);
                    if (performanceRate.compareTo(BigDecimal.ONE) == 1) {
                        performanceRate = new BigDecimal("0.95").add(BigDecimal.valueOf(Math.random() * 5).divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP));
                    }
                    mdcOverallEquipmentEfficiency.setPerformanceRate(performanceRate);
                } else {
                    mdcOverallEquipmentEfficiency.setPerformanceRate(BigDecimal.ZERO);
                }
            } else {
                // (旧)性能开动率 = 主轴运行时间/负荷时间
                if (loadTime.compareTo(BigDecimal.ZERO) != 0) {
                    mdcOverallEquipmentEfficiency.setPerformanceRate(spindleRunDuration.divide(loadTime, 4, RoundingMode.HALF_UP));
                } else {
                    mdcOverallEquipmentEfficiency.setPerformanceRate(BigDecimal.ZERO);
                }
            }
 
            // 废品数 unqualifiedQuantity
            BigDecimal unqualifiedQuantity = mdcPassRateService.findUnqualifiedQuantity(equipmentId, validDate);
            mdcOverallEquipmentEfficiency.setUnqualifiedQuantity(unqualifiedQuantity);
            // 合格率
            if (processQuantity.compareTo(BigDecimal.ZERO) == 0) {
                mdcOverallEquipmentEfficiency.setPassRate(BigDecimal.ONE);
            } else {
                mdcOverallEquipmentEfficiency.setPassRate((processQuantity.subtract(unqualifiedQuantity)).divide(processQuantity, 4, RoundingMode.HALF_UP));
            }
 
            // 设备综合效率 = 时间开动率 × 性能开动率 × 合格品率
            mdcOverallEquipmentEfficiency.setOverallEquipmentEfficiency(timeActuationRate.multiply(mdcOverallEquipmentEfficiency.getPerformanceRate()).multiply(mdcOverallEquipmentEfficiency.getPassRate()).setScale(4, RoundingMode.HALF_UP));
            if (mdcOverallEquipmentEfficiency.getOverallEquipmentEfficiency().compareTo(BigDecimal.ZERO) == 0) {
                mdcOverallEquipmentEfficiency.setOverallEquipmentEfficiency(BigDecimal.ZERO);
            }
            result.add(mdcOverallEquipmentEfficiency);
 
        }
        super.saveBatch(result);
    }
 
    /**
     * 分页列表查询
     *
     * @param userId
     * @param page
     * @param mdcOverallEquipmentEfficiencyVo
     * @param req
     * @return
     */
    @Override
    public IPage<MdcOverallEquipmentEfficiency> pageList(String userId, Page<MdcOverallEquipmentEfficiency> page, MdcOverallEquipmentEfficiencyVo mdcOverallEquipmentEfficiencyVo, HttpServletRequest req) {
        List<String> equipmentIds = new ArrayList<>();
        if (StringUtils.isNotEmpty(mdcOverallEquipmentEfficiencyVo.getParentId()) && StringUtils.isEmpty(mdcOverallEquipmentEfficiencyVo.getEquipmentId())) {
            if ("2".equals(mdcOverallEquipmentEfficiencyVo.getTypeTree())) {
                // 部门层级
                equipmentIds = mdcEquipmentService.getEquipmentIdsByDepart(userId, mdcOverallEquipmentEfficiencyVo.getParentId());
            } else {
                // 产线层级
                equipmentIds = mdcEquipmentService.getEquipmentIdsProduction(userId, mdcOverallEquipmentEfficiencyVo.getParentId());
            }
        } else if (StringUtils.isNotEmpty(mdcOverallEquipmentEfficiencyVo.getEquipmentId())) {
            // 单台设备信息
            mdcOverallEquipmentEfficiencyVo.setEquipmentIdList(Collections.singletonList(mdcOverallEquipmentEfficiencyVo.getEquipmentId()));
        } else {
            // 查询用户拥有的所有设备信息
            if ("2".equals(mdcOverallEquipmentEfficiencyVo.getTypeTree())) {
                // 部门层级
                equipmentIds = mdcEquipmentService.getEquipmentIdsByDepart(userId, null);
            } else {
                // 产线层级
                equipmentIds = mdcEquipmentService.getEquipmentIdsProduction(userId, null);
            }
        }
        if (mdcOverallEquipmentEfficiencyVo.getEquipmentIdList() == null || mdcOverallEquipmentEfficiencyVo.getEquipmentIdList().isEmpty()) {
            mdcOverallEquipmentEfficiencyVo.setEquipmentIdList(equipmentIds);
        }
        if (mdcOverallEquipmentEfficiencyVo.getEquipmentIdList() == null || mdcOverallEquipmentEfficiencyVo.getEquipmentIdList().isEmpty()) {
            return null;
        }
        return this.baseMapper.pageList(page, mdcOverallEquipmentEfficiencyVo);
    }
}