OEE添加镀锌接口

This commit is contained in:
2026-03-20 13:36:42 +08:00
parent 7e1e4b7b62
commit 017961e3b2
6 changed files with 433 additions and 22 deletions

View File

@@ -0,0 +1,22 @@
package com.klp.pocket.galvanize1.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.klp.pocket.acid.domain.vo.AcidOeeCoilInfoByDateVo;
import com.klp.pocket.acid.domain.vo.AcidOeeDailySummaryVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
@DS("master")
public interface GalvanizeOeeMasterMapper {
List<AcidOeeDailySummaryVo> selectDailySummary(@Param("startDate") String startDate,
@Param("endDate") String endDate,
@Param("createBy") String createBy);
List<AcidOeeCoilInfoByDateVo> selectCoilInfoByDate(@Param("startDate") String startDate,
@Param("endDate") String endDate,
@Param("createBy") String createBy);
}

View File

@@ -0,0 +1,19 @@
package com.klp.pocket.galvanize1.service;
import com.klp.pocket.acid.domain.vo.AcidOeeDailySummaryVo;
import com.klp.pocket.acid.domain.vo.AcidOeeIdealCycleVo;
import com.klp.pocket.acid.domain.vo.AcidOeeLoss7Vo;
import com.klp.pocket.acid.domain.vo.Klptcm1ProStoppageVo;
import java.util.List;
public interface IGalvanizeOeeService {
List<AcidOeeDailySummaryVo> getDailySummary(String startDate, String endDate);
List<Klptcm1ProStoppageVo> getStoppageEvents(String startDate, String endDate);
List<AcidOeeLoss7Vo> getLoss7Summary(String startDate, String endDate);
AcidOeeIdealCycleVo getIdealCycle(String startDate, String endDate);
}

View File

@@ -0,0 +1,274 @@
package com.klp.pocket.galvanize1.service.impl;
import com.klp.common.utils.StringUtils;
import com.klp.pocket.acid.domain.vo.AcidOeeCoilInfoByDateVo;
import com.klp.pocket.acid.domain.vo.AcidOeeDailySummaryVo;
import com.klp.pocket.acid.domain.vo.AcidOeeIdealCycleVo;
import com.klp.pocket.acid.domain.vo.AcidOeeLoss7Vo;
import com.klp.pocket.acid.domain.vo.Klptcm1ProStoppageVo;
import com.klp.pocket.galvanize1.domain.bo.ProStoppageBo;
import com.klp.pocket.galvanize1.domain.vo.ProStoppageVo;
import com.klp.pocket.galvanize1.mapper.GalvanizeOeeMasterMapper;
import com.klp.pocket.galvanize1.service.IGalvanizeOeeService;
import com.klp.pocket.galvanize1.service.IProStoppageService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
@Slf4j
@RequiredArgsConstructor
@Service
public class GalvanizeOeeServiceImpl implements IGalvanizeOeeService {
private static final Set<String> CD_SERIES = new HashSet<>(Arrays.asList("C+", "C", "C-", "D+", "D", "D-"));
private final GalvanizeOeeMasterMapper galvanizeOeeMasterMapper;
private final IProStoppageService proStoppageService;
@Value("${oee.galvanize1.coil-create-by:duxinkuguan}")
private String galvanizeCreateBy;
@Override
public List<AcidOeeDailySummaryVo> getDailySummary(String startDate, String endDate) {
List<AcidOeeDailySummaryVo> summaries = galvanizeOeeMasterMapper.selectDailySummary(startDate, endDate, galvanizeCreateBy);
if (summaries == null || summaries.isEmpty()) return Collections.emptyList();
Map<String, Long> downtimeByDate = aggregateDowntimeByDate(startDate, endDate);
Map<String, List<CoilInfo>> coilInfoByDate = getCoilNosByDate(startDate, endDate);
List<BigDecimal> dailyCycles = new ArrayList<>();
for (AcidOeeDailySummaryVo s : summaries) {
s.setLineId("DX1");
s.setLineName("镀锌一线");
Long downtime = downtimeByDate.getOrDefault(s.getStatDate(), 0L);
s.setDowntimeMin(downtime);
Long loading = s.getLoadingTimeMin() == null ? 0L : s.getLoadingTimeMin();
Long run = Math.max(0, loading - downtime);
s.setRunTimeMin(run);
BigDecimal ton = s.getTotalOutputTon();
if (run > 0 && ton != null && ton.compareTo(BigDecimal.ZERO) > 0) {
dailyCycles.add(BigDecimal.valueOf(run).divide(ton, 6, RoundingMode.HALF_UP));
}
}
dailyCycles.sort(BigDecimal::compareTo);
BigDecimal ideal = applyEightyPercent(median(dailyCycles));
for (AcidOeeDailySummaryVo s : summaries) {
if (ideal != null) s.setIdealCycleTimeMinPerTon(ideal);
List<CoilInfo> coilInfos = coilInfoByDate.get(s.getStatDate());
if (coilInfos != null) {
calculateQualityOutput(s, coilInfos);
} else {
s.setGoodOutputTon(BigDecimal.ZERO);
s.setGoodOutputCoil(0L);
s.setQualifiedOutputTon(BigDecimal.ZERO);
s.setQualifiedOutputCoil(0L);
s.setAbOutputTon(BigDecimal.ZERO);
s.setAbOutputCoil(0L);
s.setDefectOutputTon(BigDecimal.ZERO);
s.setDefectOutputCoil(0L);
s.setPendingOutputTon(s.getTotalOutputTon());
s.setPendingOutputCoil(s.getTotalOutputCoil());
}
calculateDerivedMetrics(s);
}
return summaries;
}
@Override
public List<Klptcm1ProStoppageVo> getStoppageEvents(String startDate, String endDate) {
ProStoppageBo bo = new ProStoppageBo();
bo.setStartDate(parseDate(startDate));
bo.setEndDate(parseDate(endDate));
List<ProStoppageVo> list = proStoppageService.queryList(bo);
List<Klptcm1ProStoppageVo> out = new ArrayList<>();
for (ProStoppageVo p : list) {
Klptcm1ProStoppageVo v = new Klptcm1ProStoppageVo();
v.setStopid(p.getStopid());
v.setShift(p.getShift());
v.setCrew(p.getCrew());
v.setArea(p.getArea());
v.setUnit(p.getUnit());
v.setSeton(p.getSeton());
v.setStartDate(p.getStartDate());
v.setEndDate(p.getEndDate());
v.setRemark(p.getRemark());
v.setStopType(p.getStopType());
long durationSec = p.getDuration() == null ? 0L : Math.round(p.getDuration());
v.setDuration(durationSec);
out.add(v);
}
return out;
}
@Override
public List<AcidOeeLoss7Vo> getLoss7Summary(String startDate, String endDate) {
List<Klptcm1ProStoppageVo> events = getStoppageEvents(startDate, endDate);
if (events.isEmpty()) return Collections.emptyList();
Map<String, long[]> m = new HashMap<>();
long total = 0L;
for (Klptcm1ProStoppageVo e : events) {
String k = StringUtils.isBlank(e.getStopType()) ? "未分类" : e.getStopType();
long min = Math.max(1, (e.getDuration() == null ? 0L : e.getDuration()) / 60);
if (min <= 0) continue;
m.computeIfAbsent(k, x -> new long[2]);
m.get(k)[0] += min;
m.get(k)[1] += 1;
total += min;
}
List<AcidOeeLoss7Vo> out = new ArrayList<>();
for (Map.Entry<String, long[]> en : m.entrySet()) {
AcidOeeLoss7Vo vo = new AcidOeeLoss7Vo();
vo.setLossCategoryCode(en.getKey());
vo.setLossCategoryName(en.getKey());
vo.setLossTimeMin(en.getValue()[0]);
vo.setCount((int) en.getValue()[1]);
vo.setAvgDurationMin(BigDecimal.valueOf(en.getValue()[0]).divide(BigDecimal.valueOf(Math.max(1, en.getValue()[1])), 2, RoundingMode.HALF_UP));
vo.setLossTimeRate(total == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(en.getValue()[0]).divide(BigDecimal.valueOf(total), 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
out.add(vo);
}
out.sort(Comparator.comparingLong(AcidOeeLoss7Vo::getLossTimeMin).reversed());
return out;
}
@Override
public AcidOeeIdealCycleVo getIdealCycle(String startDate, String endDate) {
List<AcidOeeDailySummaryVo> daily = getDailySummary(startDate, endDate);
AcidOeeIdealCycleVo rsp = new AcidOeeIdealCycleVo();
rsp.setLineId("DX1");
rsp.setLineName("镀锌一线");
rsp.setStartDate(startDate);
rsp.setEndDate(endDate);
if (daily.isEmpty()) {
rsp.setDailyComparePoints(Collections.emptyList());
rsp.setSampleDays(0);
return rsp;
}
List<BigDecimal> dailyCycles = new ArrayList<>();
List<AcidOeeIdealCycleVo.DailyComparePointVo> points = new ArrayList<>();
for (AcidOeeDailySummaryVo d : daily) {
if (d.getRunTimeMin() == null || d.getRunTimeMin() <= 0 || d.getTotalOutputTon() == null || d.getTotalOutputTon().compareTo(BigDecimal.ZERO) <= 0) continue;
BigDecimal c = BigDecimal.valueOf(d.getRunTimeMin()).divide(d.getTotalOutputTon(), 6, RoundingMode.HALF_UP);
dailyCycles.add(c);
}
dailyCycles.sort(BigDecimal::compareTo);
BigDecimal med = median(dailyCycles);
BigDecimal ideal = applyEightyPercent(med);
for (AcidOeeDailySummaryVo d : daily) {
if (ideal == null || d.getTotalOutputTon() == null || d.getRunTimeMin() == null) continue;
AcidOeeIdealCycleVo.DailyComparePointVo p = new AcidOeeIdealCycleVo.DailyComparePointVo();
p.setStatDate(d.getStatDate());
p.setActualRunTimeMin(d.getRunTimeMin());
p.setTheoreticalTimeMin(ideal.multiply(d.getTotalOutputTon()));
points.add(p);
}
rsp.setIdealCycleTimeMinPerTon(ideal);
rsp.setMedianCycleTimeMinPerTon(med);
rsp.setSampleDays(daily.size());
rsp.setDailyComparePoints(points);
return rsp;
}
private Map<String, List<CoilInfo>> getCoilNosByDate(String startDate, String endDate) {
List<AcidOeeCoilInfoByDateVo> list = galvanizeOeeMasterMapper.selectCoilInfoByDate(startDate, endDate, galvanizeCreateBy);
Map<String, List<CoilInfo>> map = new HashMap<>();
for (AcidOeeCoilInfoByDateVo i : list) {
map.computeIfAbsent(i.getStatDate(), k -> new ArrayList<>()).add(new CoilInfo(i.getWeight(), i.getQualityStatus()));
}
return map;
}
private void calculateQualityOutput(AcidOeeDailySummaryVo summary, List<CoilInfo> coilInfos) {
BigDecimal aTon = BigDecimal.ZERO, bTon = BigDecimal.ZERO, cdTon = BigDecimal.ZERO, oTon = BigDecimal.ZERO;
long a = 0, b = 0, cd = 0, o = 0;
for (CoilInfo c : coilInfos) {
BigDecimal w = c.weight == null ? BigDecimal.ZERO : c.weight;
String q = StringUtils.upperCase(StringUtils.trim(c.qualityStatus));
if (StringUtils.isBlank(q) || "O".equals(q)) {
oTon = oTon.add(w); o++; continue;
}
if (q.startsWith("A")) { aTon = aTon.add(w); a++; }
else if (q.startsWith("B")) { bTon = bTon.add(w); b++; }
else if (CD_SERIES.contains(q)) { cdTon = cdTon.add(w); cd++; }
else { oTon = oTon.add(w); o++; }
}
summary.setGoodOutputTon(aTon); summary.setGoodOutputCoil(a);
summary.setQualifiedOutputTon(bTon); summary.setQualifiedOutputCoil(b);
summary.setAbOutputTon(aTon.add(bTon)); summary.setAbOutputCoil(a + b);
summary.setDefectOutputTon(cdTon); summary.setDefectOutputCoil(cd);
summary.setPendingOutputTon(oTon); summary.setPendingOutputCoil(o);
}
private void calculateDerivedMetrics(AcidOeeDailySummaryVo s) {
long loading = s.getLoadingTimeMin() == null ? 0 : s.getLoadingTimeMin();
long downtime = s.getDowntimeMin() == null ? 0 : s.getDowntimeMin();
if (loading > 0) s.setAvailability(BigDecimal.valueOf(loading - downtime).divide(BigDecimal.valueOf(loading), 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
long run = s.getRunTimeMin() == null ? 0 : s.getRunTimeMin();
BigDecimal ideal = s.getIdealCycleTimeMinPerTon();
BigDecimal ton = s.getTotalOutputTon();
if (run > 0 && ideal != null && ideal.compareTo(BigDecimal.ZERO) > 0 && ton != null && ton.compareTo(BigDecimal.ZERO) > 0) {
s.setPerformanceTon(ideal.multiply(ton).divide(BigDecimal.valueOf(run), 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
}
if (ton != null && ton.compareTo(BigDecimal.ZERO) > 0) {
BigDecimal a = Optional.ofNullable(s.getGoodOutputTon()).orElse(BigDecimal.ZERO);
BigDecimal b = Optional.ofNullable(s.getQualifiedOutputTon()).orElse(BigDecimal.ZERO);
BigDecimal cd = Optional.ofNullable(s.getDefectOutputTon()).orElse(BigDecimal.ZERO);
BigDecimal o = Optional.ofNullable(s.getPendingOutputTon()).orElse(BigDecimal.ZERO);
s.setQuality(a.divide(ton, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
s.setQualifiedRate(a.add(b).divide(ton, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
s.setDefectRate(cd.divide(ton, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
s.setPendingRate(o.divide(ton, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
}
if (s.getAvailability() != null && s.getPerformanceTon() != null && s.getQuality() != null) {
s.setOee(s.getAvailability().multiply(s.getPerformanceTon()).multiply(s.getQuality()).divide(BigDecimal.valueOf(10000), 4, RoundingMode.HALF_UP));
}
}
private Map<String, Long> aggregateDowntimeByDate(String startDate, String endDate) {
List<Klptcm1ProStoppageVo> events = getStoppageEvents(startDate, endDate);
Map<String, Long> map = new HashMap<>();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
for (Klptcm1ProStoppageVo e : events) {
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);
}
return map;
}
private BigDecimal median(List<BigDecimal> values) {
if (values == null || values.isEmpty()) return null;
int n = values.size();
if (n % 2 == 1) return values.get(n / 2);
return values.get(n / 2 - 1).add(values.get(n / 2)).divide(BigDecimal.valueOf(2), 6, RoundingMode.HALF_UP);
}
private BigDecimal applyEightyPercent(BigDecimal v) {
return v == null ? null : v.multiply(BigDecimal.valueOf(0.7)).setScale(6, RoundingMode.HALF_UP);
}
private Date parseDate(String dateStr) {
if (StringUtils.isBlank(dateStr)) return null;
try {
return new SimpleDateFormat("yyyy-MM-dd").parse(dateStr);
} catch (Exception e) {
return null;
}
}
private static class CoilInfo {
final BigDecimal weight;
final String qualityStatus;
CoilInfo(BigDecimal weight, String qualityStatus) {
this.weight = weight;
this.qualityStatus = qualityStatus;
}
}
}