oee修复,提交app同步以及质保书

This commit is contained in:
2026-05-13 17:09:00 +08:00
parent f0b68382e3
commit 7a4f8a4a29
2 changed files with 83 additions and 27 deletions

View File

@@ -63,8 +63,9 @@ public class AcidOeeServiceImpl implements IAcidOeeService {
if (summaries == null || summaries.isEmpty()) { if (summaries == null || summaries.isEmpty()) {
return Collections.emptyList(); return Collections.emptyList();
} }
// 2. 查询停机事件,按日聚合停机时间 // 2. 按日聚合:计划停机、非计划停机(一次拉取,按 stopType 分流)
Map<String, Long> downtimeByDate = aggregateDowntimeByDate(startDate, endDate); Map<String, Long> plannedDowntimeByDate = new HashMap<>();
Map<String, Long> downtimeByDate = aggregateDowntimeByDate(startDate, endDate, plannedDowntimeByDate);
// 3. 查询产量明细,用于良品/次品判定 // 3. 查询产量明细,用于良品/次品判定
Map<String, List<CoilInfo>> coilInfoByDate = getCoilNosByDate(startDate, endDate); Map<String, List<CoilInfo>> coilInfoByDate = getCoilNosByDate(startDate, endDate);
@@ -76,10 +77,14 @@ public class AcidOeeServiceImpl implements IAcidOeeService {
summary.setLineId("SY"); summary.setLineId("SY");
summary.setLineName("酸轧线"); summary.setLineName("酸轧线");
Long plannedDowntime = plannedDowntimeByDate.getOrDefault(statDate, 0L);
Long loadingTime = Math.max(0, 1440 - plannedDowntime);
summary.setPlannedDowntimeMin(plannedDowntime);
summary.setLoadingTimeMin(loadingTime);
Long downtime = downtimeByDate.getOrDefault(statDate, 0L); Long downtime = downtimeByDate.getOrDefault(statDate, 0L);
summary.setDowntimeMin(downtime); summary.setDowntimeMin(downtime);
Long loadingTime = summary.getLoadingTimeMin() != null ? summary.getLoadingTimeMin() : 0L;
Long runTime = Math.max(0, loadingTime - downtime); Long runTime = Math.max(0, loadingTime - downtime);
summary.setRunTimeMin(runTime); summary.setRunTimeMin(runTime);
@@ -168,12 +173,16 @@ public class AcidOeeServiceImpl implements IAcidOeeService {
return rsp; return rsp;
} }
// 2) 聚合停机,补齐 runTime // 2) 聚合停机,补齐 loadingTime / runTime
Map<String, Long> downtimeByDate = aggregateDowntimeByDate(startDate, endDate); Map<String, Long> plannedDowntimeByDate2 = new HashMap<>();
Map<String, Long> downtimeByDate = aggregateDowntimeByDate(startDate, endDate, plannedDowntimeByDate2);
for (AcidOeeDailySummaryVo d : daily) { for (AcidOeeDailySummaryVo d : daily) {
Long plannedDowntime = plannedDowntimeByDate2.getOrDefault(d.getStatDate(), 0L);
Long loading = Math.max(0, 1440 - plannedDowntime);
d.setPlannedDowntimeMin(plannedDowntime);
d.setLoadingTimeMin(loading);
Long downtime = downtimeByDate.getOrDefault(d.getStatDate(), 0L); Long downtime = downtimeByDate.getOrDefault(d.getStatDate(), 0L);
d.setDowntimeMin(downtime); d.setDowntimeMin(downtime);
Long loading = d.getLoadingTimeMin() != null ? d.getLoadingTimeMin() : 0L;
d.setRunTimeMin(Math.max(0, loading - downtime)); d.setRunTimeMin(Math.max(0, loading - downtime));
} }
@@ -294,11 +303,12 @@ public class AcidOeeServiceImpl implements IAcidOeeService {
} }
/** /**
* 按日期聚合停机时间 * 按日期聚合停机时间,同时将计划停机单独写入 plannedDowntimeOut。
* 修复:如果停机事件跨天,需要按实际跨天的分钟数分配到对应的日期 * - "计划停机" stopType 不计入 OEE 停机时间,也不计入负荷时间。
* - 跨天事件按实际分钟数拆分到各天。
*/ */
private Map<String, Long> aggregateDowntimeByDate(String startDate, String endDate) { private Map<String, Long> aggregateDowntimeByDate(String startDate, String endDate,
// 性能稼动率/运转时间口径:停机时间需要包含短停机(<5min否则 runTime 被高估 Map<String, Long> plannedDowntimeOut) {
List<Klptcm1ProStoppageVo> events = getStoppageEvents(startDate, endDate, true); List<Klptcm1ProStoppageVo> events = getStoppageEvents(startDate, endDate, true);
Map<String, Long> downtimeMap = new HashMap<>(); Map<String, Long> downtimeMap = new HashMap<>();
@@ -310,45 +320,40 @@ public class AcidOeeServiceImpl implements IAcidOeeService {
continue; continue;
} }
boolean isPlanned = "计划停机".equals(event.getStopType());
Map<String, Long> targetMap = isPlanned ? plannedDowntimeOut : downtimeMap;
Date eventStart = event.getStartDate(); Date eventStart = event.getStartDate();
long durationSec = event.getDuration(); long durationSec = event.getDuration();
long durationMin = (durationSec + 59) / 60; // 向上取整,避免丢失秒数 long durationMin = (durationSec + 59) / 60;
// 计算停机结束时间
cal.setTime(eventStart); cal.setTime(eventStart);
cal.add(Calendar.SECOND, (int) durationSec); cal.add(Calendar.SECOND, (int) durationSec);
Date eventEnd = cal.getTime(); Date eventEnd = cal.getTime();
// 如果停机事件在同一天,直接累加
String startDateStr = dateFormat.format(eventStart); String startDateStr = dateFormat.format(eventStart);
String endDateStr = dateFormat.format(eventEnd); String endDateStr = dateFormat.format(eventEnd);
if (startDateStr.equals(endDateStr)) { if (startDateStr.equals(endDateStr)) {
// 同一天,直接累加 targetMap.merge(startDateStr, durationMin, Long::sum);
downtimeMap.merge(startDateStr, durationMin, Long::sum);
} else { } else {
// 跨天:按实际跨天的分钟数分配到对应的日期
cal.setTime(eventStart); cal.setTime(eventStart);
cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0); cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0); cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0); cal.set(Calendar.MILLISECOND, 0);
Date dayStart = cal.getTime(); Date currentDayStart = cal.getTime();
Date currentDayStart = dayStart;
while (currentDayStart.before(eventEnd)) { while (currentDayStart.before(eventEnd)) {
cal.setTime(currentDayStart); cal.setTime(currentDayStart);
cal.add(Calendar.DAY_OF_MONTH, 1); cal.add(Calendar.DAY_OF_MONTH, 1);
Date nextDayStart = cal.getTime(); Date nextDayStart = cal.getTime();
// 计算当前天的停机分钟数
Date dayEnd = nextDayStart.before(eventEnd) ? nextDayStart : eventEnd; Date dayEnd = nextDayStart.before(eventEnd) ? nextDayStart : eventEnd;
long dayMinutes = Math.max(0, (dayEnd.getTime() - Math.max(currentDayStart.getTime(), eventStart.getTime())) / (1000 * 60)); long dayMinutes = Math.max(0, (dayEnd.getTime() - Math.max(currentDayStart.getTime(), eventStart.getTime())) / (1000 * 60));
if (dayMinutes > 0) { if (dayMinutes > 0) {
String dateKey = dateFormat.format(currentDayStart); targetMap.merge(dateFormat.format(currentDayStart), dayMinutes, Long::sum);
downtimeMap.merge(dateKey, dayMinutes, Long::sum);
} }
currentDayStart = nextDayStart; currentDayStart = nextDayStart;

View File

@@ -39,16 +39,20 @@ public class GalvanizeOeeServiceImpl implements IGalvanizeOeeService {
List<AcidOeeDailySummaryVo> summaries = galvanizeOeeMasterMapper.selectDailySummary(startDate, endDate, galvanizeCreateBy); List<AcidOeeDailySummaryVo> summaries = galvanizeOeeMasterMapper.selectDailySummary(startDate, endDate, galvanizeCreateBy);
if (summaries == null || summaries.isEmpty()) return Collections.emptyList(); if (summaries == null || summaries.isEmpty()) return Collections.emptyList();
Map<String, Long> downtimeByDate = aggregateDowntimeByDate(startDate, endDate); Map<String, Long> plannedDowntimeByDate = new HashMap<>();
Map<String, Long> downtimeByDate = aggregateDowntimeByDate(startDate, endDate, plannedDowntimeByDate);
Map<String, List<CoilInfo>> coilInfoByDate = getCoilNosByDate(startDate, endDate); Map<String, List<CoilInfo>> coilInfoByDate = getCoilNosByDate(startDate, endDate);
List<BigDecimal> dailyCycles = new ArrayList<>(); List<BigDecimal> dailyCycles = new ArrayList<>();
for (AcidOeeDailySummaryVo s : summaries) { for (AcidOeeDailySummaryVo s : summaries) {
s.setLineId("DX1"); s.setLineId("DX1");
s.setLineName("镀锌一线"); s.setLineName("镀锌一线");
Long plannedDowntime = plannedDowntimeByDate.getOrDefault(s.getStatDate(), 0L);
Long loading = Math.max(0, 1440 - plannedDowntime);
s.setPlannedDowntimeMin(plannedDowntime);
s.setLoadingTimeMin(loading);
Long downtime = downtimeByDate.getOrDefault(s.getStatDate(), 0L); Long downtime = downtimeByDate.getOrDefault(s.getStatDate(), 0L);
s.setDowntimeMin(downtime); s.setDowntimeMin(downtime);
Long loading = s.getLoadingTimeMin() == null ? 0L : s.getLoadingTimeMin();
Long run = Math.max(0, loading - downtime); Long run = Math.max(0, loading - downtime);
s.setRunTimeMin(run); s.setRunTimeMin(run);
BigDecimal ton = s.getTotalOutputTon(); BigDecimal ton = s.getTotalOutputTon();
@@ -230,15 +234,62 @@ public class GalvanizeOeeServiceImpl implements IGalvanizeOeeService {
} }
} }
private Map<String, Long> aggregateDowntimeByDate(String startDate, String endDate) { /**
* 按日期聚合停机时间,同时将计划停机写入 plannedDowntimeOut。
* - "计划停机" stopType 不计入 OEE 停机时间,也不计入负荷时间。
* - 跨天事件按实际分钟数拆分到各天。
*/
private Map<String, Long> aggregateDowntimeByDate(String startDate, String endDate,
Map<String, Long> plannedDowntimeOut) {
List<Klptcm1ProStoppageVo> events = getStoppageEvents(startDate, endDate); List<Klptcm1ProStoppageVo> events = getStoppageEvents(startDate, endDate);
Map<String, Long> map = new HashMap<>(); Map<String, Long> map = new HashMap<>();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Calendar cal = Calendar.getInstance();
for (Klptcm1ProStoppageVo e : events) { for (Klptcm1ProStoppageVo e : events) {
if (e.getStartDate() == null || e.getDuration() == null || e.getDuration() <= 0) continue; if (e.getStartDate() == null || e.getDuration() == null || e.getDuration() <= 0) continue;
long min = Math.max(1, (e.getDuration() + 59) / 60);
map.merge(df.format(e.getStartDate()), min, Long::sum); boolean isPlanned = "计划停机".equals(e.getStopType());
Map<String, Long> targetMap = isPlanned ? plannedDowntimeOut : map;
Date eventStart = e.getStartDate();
long durationSec = e.getDuration();
long durationMin = (durationSec + 59) / 60;
cal.setTime(eventStart);
cal.add(Calendar.SECOND, (int) durationSec);
Date eventEnd = cal.getTime();
String startDateStr = df.format(eventStart);
String endDateStr = df.format(eventEnd);
if (startDateStr.equals(endDateStr)) {
targetMap.merge(startDateStr, durationMin, Long::sum);
} else {
cal.setTime(eventStart);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Date currentDayStart = cal.getTime();
while (currentDayStart.before(eventEnd)) {
cal.setTime(currentDayStart);
cal.add(Calendar.DAY_OF_MONTH, 1);
Date nextDayStart = cal.getTime();
Date dayEnd = nextDayStart.before(eventEnd) ? nextDayStart : eventEnd;
long dayMinutes = Math.max(0, (dayEnd.getTime() - Math.max(currentDayStart.getTime(), eventStart.getTime())) / (1000 * 60));
if (dayMinutes > 0) {
targetMap.merge(df.format(currentDayStart), dayMinutes, Long::sum);
}
currentDayStart = nextDayStart;
}
}
} }
return map; return map;
} }