|
|
|
|
@ -1,15 +1,19 @@
|
|
|
|
|
package com.aucma.production.service.impl;
|
|
|
|
|
|
|
|
|
|
import com.aucma.base.domain.BaseDeviceLedger;
|
|
|
|
|
import com.aucma.base.domain.BaseDeviceParamVal;
|
|
|
|
|
import com.aucma.base.mapper.BaseDeviceLedgerMapper;
|
|
|
|
|
import com.aucma.base.mapper.BaseDeviceParamValMapper;
|
|
|
|
|
import com.aucma.common.constant.AnDonConstants;
|
|
|
|
|
import com.aucma.common.utils.DateUtils;
|
|
|
|
|
import com.aucma.common.utils.StringUtils;
|
|
|
|
|
import com.aucma.production.domain.AndonEvent;
|
|
|
|
|
import com.aucma.production.domain.ProductPlanInfo;
|
|
|
|
|
import com.aucma.production.domain.ProductionReportQualityInspection;
|
|
|
|
|
import com.aucma.production.domain.dto.AndonDashboardDTO;
|
|
|
|
|
import com.aucma.production.mapper.AndonEventMapper;
|
|
|
|
|
import com.aucma.production.mapper.ProductPlanInfoMapper;
|
|
|
|
|
import com.aucma.production.mapper.ProductionReportQualityInspectionMapper;
|
|
|
|
|
import com.aucma.production.service.IAndonDashboardService;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
@ -31,12 +35,18 @@ public class AndonDashboardServiceImpl implements IAndonDashboardService {
|
|
|
|
|
@Autowired
|
|
|
|
|
private BaseDeviceLedgerMapper baseDeviceLedgerMapper;
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private BaseDeviceParamValMapper baseDeviceParamValMapper;
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private ProductPlanInfoMapper productPlanInfoMapper;
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private AndonEventMapper andonEventMapper;
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private ProductionReportQualityInspectionMapper reportQualityInspectionMapper;
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public AndonDashboardDTO getDashboardData(String productLineCode) {
|
|
|
|
|
AndonDashboardDTO dto = new AndonDashboardDTO();
|
|
|
|
|
@ -53,15 +63,10 @@ public class AndonDashboardServiceImpl implements IAndonDashboardService {
|
|
|
|
|
public AndonDashboardDTO.DeviceStatusSummary getDeviceStatusSummary(String productLineCode) {
|
|
|
|
|
AndonDashboardDTO.DeviceStatusSummary summary = new AndonDashboardDTO.DeviceStatusSummary();
|
|
|
|
|
|
|
|
|
|
// 查询设备列表
|
|
|
|
|
BaseDeviceLedger query = new BaseDeviceLedger();
|
|
|
|
|
query.setIsFlag(1L); // 有效设备
|
|
|
|
|
if (StringUtils.isNotEmpty(productLineCode)) {
|
|
|
|
|
query.setProductLineCode(productLineCode);
|
|
|
|
|
}
|
|
|
|
|
List<BaseDeviceLedger> devices = baseDeviceLedgerMapper.selectBaseDeviceLedgerList(query);
|
|
|
|
|
// 直接调用BaseDeviceParamValMapper获取真实设备状态统计
|
|
|
|
|
Map<String, Object> stats = baseDeviceParamValMapper.selectDeviceStatusStatistics();
|
|
|
|
|
|
|
|
|
|
if (devices == null || devices.isEmpty()) {
|
|
|
|
|
if (stats == null || stats.isEmpty()) {
|
|
|
|
|
summary.setTotalDevices(0);
|
|
|
|
|
summary.setRunningDevices(0);
|
|
|
|
|
summary.setStoppedDevices(0);
|
|
|
|
|
@ -70,35 +75,46 @@ public class AndonDashboardServiceImpl implements IAndonDashboardService {
|
|
|
|
|
summary.setDeviceDetails(new ArrayList<>());
|
|
|
|
|
return summary;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置统计数据
|
|
|
|
|
Number totalCount = (Number) stats.get("totalCount");
|
|
|
|
|
Number runningCount = (Number) stats.get("runningCount");
|
|
|
|
|
Number stoppedCount = (Number) stats.get("stoppedCount");
|
|
|
|
|
Number standbyCount = (Number) stats.get("standbyCount");
|
|
|
|
|
|
|
|
|
|
summary.setTotalDevices(totalCount != null ? totalCount.intValue() : 0);
|
|
|
|
|
summary.setRunningDevices(runningCount != null ? runningCount.intValue() : 0);
|
|
|
|
|
summary.setStoppedDevices(stoppedCount != null ? stoppedCount.intValue() : 0);
|
|
|
|
|
summary.setIdleDevices(standbyCount != null ? standbyCount.intValue() : 0);
|
|
|
|
|
summary.setFaultDevices(0); // 三色灯没有故障状态,使用报警代替
|
|
|
|
|
|
|
|
|
|
int running = 0, stopped = 0, fault = 0, idle = 0;
|
|
|
|
|
// 获取设备状态详情
|
|
|
|
|
List<Map<String, Object>> deviceStatusList = baseDeviceParamValMapper.selectDeviceStatusList();
|
|
|
|
|
List<AndonDashboardDTO.DeviceStatusDetail> details = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
for (BaseDeviceLedger device : devices) {
|
|
|
|
|
Long status = device.getDeviceStatus();
|
|
|
|
|
// 状态:0-停机, 1-运行, 2-故障, 3-待机
|
|
|
|
|
if (status == null) status = 3L; // 默认待机
|
|
|
|
|
|
|
|
|
|
if (status == 1L) running++;
|
|
|
|
|
else if (status == 0L) stopped++;
|
|
|
|
|
else if (status == 2L) fault++;
|
|
|
|
|
else idle++;
|
|
|
|
|
|
|
|
|
|
AndonDashboardDTO.DeviceStatusDetail detail = new AndonDashboardDTO.DeviceStatusDetail();
|
|
|
|
|
detail.setDeviceCode(device.getDeviceCode());
|
|
|
|
|
detail.setDeviceName(device.getDeviceName());
|
|
|
|
|
detail.setProductLineCode(device.getProductLineCode());
|
|
|
|
|
detail.setProductLineName(device.getProductLineName());
|
|
|
|
|
detail.setStatus(status.intValue());
|
|
|
|
|
detail.setStatusName(getStatusName(status.intValue()));
|
|
|
|
|
details.add(detail);
|
|
|
|
|
|
|
|
|
|
if (deviceStatusList != null) {
|
|
|
|
|
for (Map<String, Object> device : deviceStatusList) {
|
|
|
|
|
// 如果指定了产线编码,过滤设备
|
|
|
|
|
if (StringUtils.isNotEmpty(productLineCode)) {
|
|
|
|
|
String lineCode = (String) device.get("productLineCode");
|
|
|
|
|
if (!productLineCode.equals(lineCode)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AndonDashboardDTO.DeviceStatusDetail detail = new AndonDashboardDTO.DeviceStatusDetail();
|
|
|
|
|
detail.setDeviceCode((String) device.get("deviceCode"));
|
|
|
|
|
detail.setDeviceName((String) device.get("deviceName"));
|
|
|
|
|
detail.setProductLineCode((String) device.get("productLineCode"));
|
|
|
|
|
detail.setProductLineName((String) device.get("productLineName"));
|
|
|
|
|
|
|
|
|
|
Number statusCode = (Number) device.get("statusCode");
|
|
|
|
|
detail.setStatus(statusCode != null ? statusCode.intValue() : 0);
|
|
|
|
|
detail.setStatusName((String) device.get("deviceStatus"));
|
|
|
|
|
details.add(detail);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
summary.setTotalDevices(devices.size());
|
|
|
|
|
summary.setRunningDevices(running);
|
|
|
|
|
summary.setStoppedDevices(stopped);
|
|
|
|
|
summary.setFaultDevices(fault);
|
|
|
|
|
summary.setIdleDevices(idle);
|
|
|
|
|
|
|
|
|
|
summary.setDeviceDetails(details);
|
|
|
|
|
|
|
|
|
|
return summary;
|
|
|
|
|
@ -216,70 +232,85 @@ public class AndonDashboardServiceImpl implements IAndonDashboardService {
|
|
|
|
|
return summary;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 基于设备状态模拟计算OEE(实际应从设备运行数据表获取)
|
|
|
|
|
// OEE = 可用率 × 性能稼动率 × 良品率
|
|
|
|
|
long totalPlannedMinutes = devices.size() * 480L; // 假设每台设备每天计划8小时
|
|
|
|
|
long totalDowntimeMinutes = 0;
|
|
|
|
|
|
|
|
|
|
List<AndonDashboardDTO.DeviceOeeDetail> details = new ArrayList<>();
|
|
|
|
|
double totalAvailability = 0, totalPerformance = 0, totalQuality = 0;
|
|
|
|
|
long totalPlannedTime = 0, totalDowntime = 0;
|
|
|
|
|
|
|
|
|
|
for (BaseDeviceLedger device : devices) {
|
|
|
|
|
Long status = device.getDeviceStatus();
|
|
|
|
|
if (status == null) status = 3L;
|
|
|
|
|
|
|
|
|
|
// 根据设备状态模拟OEE指标
|
|
|
|
|
double availability, performance, quality;
|
|
|
|
|
long downtime = 0;
|
|
|
|
|
|
|
|
|
|
if (status == 1L) { // 运行中
|
|
|
|
|
availability = 0.92 + Math.random() * 0.06; // 92%-98%
|
|
|
|
|
performance = 0.88 + Math.random() * 0.10; // 88%-98%
|
|
|
|
|
quality = 0.95 + Math.random() * 0.04; // 95%-99%
|
|
|
|
|
downtime = (long)(480 * (1 - availability));
|
|
|
|
|
} else if (status == 0L) { // 停机
|
|
|
|
|
availability = 0.0;
|
|
|
|
|
performance = 0.0;
|
|
|
|
|
quality = 0.0;
|
|
|
|
|
downtime = 480;
|
|
|
|
|
} else if (status == 2L) { // 故障
|
|
|
|
|
availability = 0.3 + Math.random() * 0.2; // 30%-50%
|
|
|
|
|
performance = 0.5 + Math.random() * 0.2; // 50%-70%
|
|
|
|
|
quality = 0.8 + Math.random() * 0.1; // 80%-90%
|
|
|
|
|
downtime = (long)(480 * (1 - availability));
|
|
|
|
|
} else { // 待机
|
|
|
|
|
availability = 0.6 + Math.random() * 0.2; // 60%-80%
|
|
|
|
|
performance = 0.7 + Math.random() * 0.15; // 70%-85%
|
|
|
|
|
quality = 0.92 + Math.random() * 0.05; // 92%-97%
|
|
|
|
|
downtime = (long)(480 * (1 - availability));
|
|
|
|
|
// 查询该设备的总计划生产时间
|
|
|
|
|
BaseDeviceParamVal plannedQuery = new BaseDeviceParamVal();
|
|
|
|
|
plannedQuery.setDeviceCode(device.getDeviceCode());
|
|
|
|
|
plannedQuery.setParamName("机台状态-总计划生产时间");
|
|
|
|
|
List<BaseDeviceParamVal> plannedList = baseDeviceParamValMapper.selectLatestBaseDeviceParamValList(plannedQuery);
|
|
|
|
|
double plannedTime = 0;
|
|
|
|
|
if (plannedList != null && !plannedList.isEmpty()) {
|
|
|
|
|
plannedTime = parseDouble(plannedList.get(0).getParamValue());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
totalDowntimeMinutes += downtime;
|
|
|
|
|
|
|
|
|
|
// 查询该设备的实际生产时间
|
|
|
|
|
BaseDeviceParamVal actualQuery = new BaseDeviceParamVal();
|
|
|
|
|
actualQuery.setDeviceCode(device.getDeviceCode());
|
|
|
|
|
actualQuery.setParamName("机台状态-实际生产时间");
|
|
|
|
|
List<BaseDeviceParamVal> actualList = baseDeviceParamValMapper.selectLatestBaseDeviceParamValList(actualQuery);
|
|
|
|
|
double actualTime = 0;
|
|
|
|
|
if (actualList != null && !actualList.isEmpty()) {
|
|
|
|
|
actualTime = parseDouble(actualList.get(0).getParamValue());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 查询该设备的设定产出数量
|
|
|
|
|
BaseDeviceParamVal targetQuery = new BaseDeviceParamVal();
|
|
|
|
|
targetQuery.setDeviceCode(device.getDeviceCode());
|
|
|
|
|
targetQuery.setParamName("机台状态-设定产出数量");
|
|
|
|
|
List<BaseDeviceParamVal> targetList = baseDeviceParamValMapper.selectLatestBaseDeviceParamValList(targetQuery);
|
|
|
|
|
long targetOutput = 0;
|
|
|
|
|
if (targetList != null && !targetList.isEmpty()) {
|
|
|
|
|
targetOutput = parseLong(targetList.get(0).getParamValue());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 查询该设备的实际产出数量
|
|
|
|
|
BaseDeviceParamVal actualOutputQuery = new BaseDeviceParamVal();
|
|
|
|
|
actualOutputQuery.setDeviceCode(device.getDeviceCode());
|
|
|
|
|
actualOutputQuery.setParamName("机台状态-实际产出数量");
|
|
|
|
|
List<BaseDeviceParamVal> actualOutputList = baseDeviceParamValMapper.selectLatestBaseDeviceParamValList(actualOutputQuery);
|
|
|
|
|
long actualOutput = 0;
|
|
|
|
|
if (actualOutputList != null && !actualOutputList.isEmpty()) {
|
|
|
|
|
actualOutput = parseLong(actualOutputList.get(0).getParamValue());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 计算OEE三个指标
|
|
|
|
|
double availability = plannedTime > 0 ? (actualTime / plannedTime) : 0;
|
|
|
|
|
double performance = targetOutput > 0 ? (actualOutput / targetOutput) : 0;
|
|
|
|
|
double quality = 0.95;
|
|
|
|
|
|
|
|
|
|
double oee = availability * performance * quality;
|
|
|
|
|
|
|
|
|
|
totalPlannedTime += (long) plannedTime;
|
|
|
|
|
totalDowntime += (long)(plannedTime - actualTime);
|
|
|
|
|
totalAvailability += availability;
|
|
|
|
|
totalPerformance += performance;
|
|
|
|
|
totalQuality += quality;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AndonDashboardDTO.DeviceOeeDetail detail = new AndonDashboardDTO.DeviceOeeDetail();
|
|
|
|
|
detail.setDeviceCode(device.getDeviceCode());
|
|
|
|
|
detail.setDeviceName(device.getDeviceName());
|
|
|
|
|
detail.setAvailability(round(availability * 100, 2));
|
|
|
|
|
detail.setPerformance(round(performance * 100, 2));
|
|
|
|
|
detail.setQuality(round(quality * 100, 2));
|
|
|
|
|
detail.setOee(round(availability * performance * quality * 100, 2));
|
|
|
|
|
detail.setOee(round(oee * 100, 2));
|
|
|
|
|
details.add(detail);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int count = devices.size();
|
|
|
|
|
double avgAvailability = totalAvailability / count;
|
|
|
|
|
double avgPerformance = totalPerformance / count;
|
|
|
|
|
double avgQuality = totalQuality / count;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
summary.setAvailability(round(avgAvailability * 100, 2));
|
|
|
|
|
summary.setPerformance(round(avgPerformance * 100, 2));
|
|
|
|
|
summary.setQuality(round(avgQuality * 100, 2));
|
|
|
|
|
summary.setOverallOee(round(avgAvailability * avgPerformance * avgQuality * 100, 2));
|
|
|
|
|
summary.setPlannedTimeMinutes(totalPlannedMinutes);
|
|
|
|
|
summary.setDowntimeMinutes(totalDowntimeMinutes);
|
|
|
|
|
summary.setPlannedTimeMinutes(totalPlannedTime);
|
|
|
|
|
summary.setDowntimeMinutes(totalDowntime);
|
|
|
|
|
summary.setDeviceOeeDetails(details);
|
|
|
|
|
|
|
|
|
|
return summary;
|
|
|
|
|
@ -303,7 +334,7 @@ public class AndonDashboardServiceImpl implements IAndonDashboardService {
|
|
|
|
|
return summary;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 按产线分组计算利用率
|
|
|
|
|
// 按产线分组
|
|
|
|
|
Map<String, List<BaseDeviceLedger>> lineDevices = devices.stream()
|
|
|
|
|
.filter(d -> StringUtils.isNotEmpty(d.getProductLineCode()))
|
|
|
|
|
.collect(Collectors.groupingBy(BaseDeviceLedger::getProductLineCode));
|
|
|
|
|
@ -313,23 +344,31 @@ public class AndonDashboardServiceImpl implements IAndonDashboardService {
|
|
|
|
|
|
|
|
|
|
for (Map.Entry<String, List<BaseDeviceLedger>> entry : lineDevices.entrySet()) {
|
|
|
|
|
List<BaseDeviceLedger> lineDeviceList = entry.getValue();
|
|
|
|
|
long linePlanned = lineDeviceList.size() * 480L; // 假设8小时
|
|
|
|
|
long linePlanned = 0;
|
|
|
|
|
long lineRunning = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (BaseDeviceLedger device : lineDeviceList) {
|
|
|
|
|
Long status = device.getDeviceStatus();
|
|
|
|
|
if (status == null) status = 3L;
|
|
|
|
|
// 查询该设备的总计划生产时间
|
|
|
|
|
BaseDeviceParamVal plannedQuery = new BaseDeviceParamVal();
|
|
|
|
|
plannedQuery.setDeviceCode(device.getDeviceCode());
|
|
|
|
|
plannedQuery.setParamName("机台状态-总计划生产时间");
|
|
|
|
|
List<BaseDeviceParamVal> plannedList = baseDeviceParamValMapper.selectLatestBaseDeviceParamValList(plannedQuery);
|
|
|
|
|
if (plannedList != null && !plannedList.isEmpty()) {
|
|
|
|
|
double plannedTime = parseDouble(plannedList.get(0).getParamValue());
|
|
|
|
|
linePlanned += (long) plannedTime;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 根据状态估算运行时间
|
|
|
|
|
if (status == 1L) {
|
|
|
|
|
lineRunning += (long)(480 * (0.85 + Math.random() * 0.1));
|
|
|
|
|
} else if (status == 2L) {
|
|
|
|
|
lineRunning += (long)(480 * (0.3 + Math.random() * 0.2));
|
|
|
|
|
} else if (status == 3L) {
|
|
|
|
|
lineRunning += (long)(480 * (0.5 + Math.random() * 0.2));
|
|
|
|
|
// 查询该设备的实际生产时间
|
|
|
|
|
BaseDeviceParamVal actualQuery = new BaseDeviceParamVal();
|
|
|
|
|
actualQuery.setDeviceCode(device.getDeviceCode());
|
|
|
|
|
actualQuery.setParamName("机台状态-实际生产时间");
|
|
|
|
|
List<BaseDeviceParamVal> actualList = baseDeviceParamValMapper.selectLatestBaseDeviceParamValList(actualQuery);
|
|
|
|
|
if (actualList != null && !actualList.isEmpty()) {
|
|
|
|
|
double actualTime = parseDouble(actualList.get(0).getParamValue());
|
|
|
|
|
lineRunning += (long) actualTime;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
totalRunning += lineRunning;
|
|
|
|
|
totalPlanned += linePlanned;
|
|
|
|
|
|
|
|
|
|
@ -352,84 +391,75 @@ public class AndonDashboardServiceImpl implements IAndonDashboardService {
|
|
|
|
|
public AndonDashboardDTO.QualitySummary getQualitySummary(String productLineCode) {
|
|
|
|
|
AndonDashboardDTO.QualitySummary summary = new AndonDashboardDTO.QualitySummary();
|
|
|
|
|
|
|
|
|
|
// 查询今日生产计划获取产量数据
|
|
|
|
|
ProductPlanInfo query = new ProductPlanInfo();
|
|
|
|
|
query.setIsFlag(1L);
|
|
|
|
|
if (StringUtils.isNotEmpty(productLineCode)) {
|
|
|
|
|
query.setProductLineCode(productLineCode);
|
|
|
|
|
}
|
|
|
|
|
List<ProductPlanInfo> plans = productPlanInfoMapper.selectProductPlanInfoList(query);
|
|
|
|
|
|
|
|
|
|
if (plans == null) plans = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
// 获取今日日期范围
|
|
|
|
|
Date todayStart = DateUtils.parseDate(DateUtils.getDate());
|
|
|
|
|
Date todayEnd = DateUtils.addDays(todayStart, 1);
|
|
|
|
|
|
|
|
|
|
// 获取本月日期范围
|
|
|
|
|
Calendar cal = Calendar.getInstance();
|
|
|
|
|
cal.set(Calendar.DAY_OF_MONTH, 1);
|
|
|
|
|
cal.set(Calendar.HOUR_OF_DAY, 0);
|
|
|
|
|
cal.set(Calendar.MINUTE, 0);
|
|
|
|
|
cal.set(Calendar.SECOND, 0);
|
|
|
|
|
cal.set(Calendar.MILLISECOND, 0);
|
|
|
|
|
Date monthStart = cal.getTime();
|
|
|
|
|
cal.add(Calendar.MONTH, 1);
|
|
|
|
|
Date monthEnd = cal.getTime();
|
|
|
|
|
|
|
|
|
|
long todayOutput = 0, monthOutput = 0;
|
|
|
|
|
Map<String, long[]> lineStats = new HashMap<>(); // [output, good, defect]
|
|
|
|
|
Map<String, String> lineNames = new HashMap<>();
|
|
|
|
|
|
|
|
|
|
for (ProductPlanInfo plan : plans) {
|
|
|
|
|
Long compAmt = plan.getCompleteAmount() == null ? 0L : plan.getCompleteAmount();
|
|
|
|
|
Date planDate = plan.getPlanBeginTime();
|
|
|
|
|
|
|
|
|
|
if (planDate != null && !planDate.before(todayStart) && planDate.before(todayEnd)) {
|
|
|
|
|
todayOutput += compAmt;
|
|
|
|
|
}
|
|
|
|
|
if (planDate != null && !planDate.before(monthStart) && planDate.before(monthEnd)) {
|
|
|
|
|
monthOutput += compAmt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String lineCode = plan.getProductLineCode();
|
|
|
|
|
// 查询今日质检记录
|
|
|
|
|
ProductionReportQualityInspection query = new ProductionReportQualityInspection();
|
|
|
|
|
query.setBeginBeginTime(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", todayStart));
|
|
|
|
|
query.setEndBeginTime(DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", todayEnd));
|
|
|
|
|
if (StringUtils.isNotEmpty(productLineCode)) {
|
|
|
|
|
query.setStationCode(productLineCode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<ProductionReportQualityInspection> qualityList = reportQualityInspectionMapper.selectReportQualityInspectionList(query);
|
|
|
|
|
|
|
|
|
|
if (qualityList == null) {
|
|
|
|
|
qualityList = new ArrayList<>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 按产线分组统计
|
|
|
|
|
Map<String, List<ProductionReportQualityInspection>> lineQualityMap = new HashMap<>();
|
|
|
|
|
for (ProductionReportQualityInspection inspection : qualityList) {
|
|
|
|
|
String lineCode = inspection.getStationCode();
|
|
|
|
|
if (StringUtils.isNotEmpty(lineCode)) {
|
|
|
|
|
lineStats.computeIfAbsent(lineCode, k -> new long[3]);
|
|
|
|
|
lineStats.get(lineCode)[0] += compAmt;
|
|
|
|
|
if (StringUtils.isNotEmpty(plan.getProductLineName())) {
|
|
|
|
|
lineNames.put(lineCode, plan.getProductLineName());
|
|
|
|
|
}
|
|
|
|
|
lineQualityMap.computeIfAbsent(lineCode, k -> new ArrayList<>()).add(inspection);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 模拟良品率数据(实际应从质检数据获取)
|
|
|
|
|
double yieldRate = 0.95 + Math.random() * 0.04; // 95%-99%
|
|
|
|
|
long todayGood = (long)(todayOutput * yieldRate);
|
|
|
|
|
long todayDefect = todayOutput - todayGood;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
long todayOutput = 0, todayGood = 0, todayDefect = 0;
|
|
|
|
|
List<AndonDashboardDTO.LineQuality> lineQualities = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
// 按产线统计良品和不良品
|
|
|
|
|
for (Map.Entry<String, List<ProductionReportQualityInspection>> entry : lineQualityMap.entrySet()) {
|
|
|
|
|
List<ProductionReportQualityInspection> lineInspections = entry.getValue();
|
|
|
|
|
long lineGood = 0;
|
|
|
|
|
long lineDefect = 0;
|
|
|
|
|
|
|
|
|
|
for (ProductionReportQualityInspection inspection : lineInspections) {
|
|
|
|
|
// treatmentMeasure: 3=合格(良品), 1=返修(不良品)
|
|
|
|
|
if ("3".equals(inspection.getTreatmentMeasure())) {
|
|
|
|
|
lineGood++;
|
|
|
|
|
} else if ("1".equals(inspection.getTreatmentMeasure())) {
|
|
|
|
|
lineDefect++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
long lineOutput = lineGood + lineDefect;
|
|
|
|
|
double lineYieldRate = lineOutput > 0 ? (lineGood * 100.0 / lineOutput) : 0;
|
|
|
|
|
|
|
|
|
|
todayOutput += lineOutput;
|
|
|
|
|
todayGood += lineGood;
|
|
|
|
|
todayDefect += lineDefect;
|
|
|
|
|
|
|
|
|
|
AndonDashboardDTO.LineQuality lq = new AndonDashboardDTO.LineQuality();
|
|
|
|
|
lq.setProductLineCode(entry.getKey());
|
|
|
|
|
lq.setProductLineName(lineInspections.get(0).getProductLineName());
|
|
|
|
|
lq.setOutput(lineOutput);
|
|
|
|
|
lq.setGoodCount(lineGood);
|
|
|
|
|
lq.setDefectCount(lineDefect);
|
|
|
|
|
lq.setYieldRate(round(lineYieldRate, 2));
|
|
|
|
|
lineQualities.add(lq);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double todayYieldRate = todayOutput > 0 ? (todayGood * 100.0 / todayOutput) : 0;
|
|
|
|
|
|
|
|
|
|
summary.setTodayOutput(todayOutput);
|
|
|
|
|
summary.setTodayGoodCount(todayGood);
|
|
|
|
|
summary.setTodayDefectCount(todayDefect);
|
|
|
|
|
summary.setTodayYieldRate(round(yieldRate * 100, 2));
|
|
|
|
|
summary.setMonthYieldRate(round((0.94 + Math.random() * 0.05) * 100, 2));
|
|
|
|
|
|
|
|
|
|
// 产线品质数据
|
|
|
|
|
List<AndonDashboardDTO.LineQuality> lineQualities = new ArrayList<>();
|
|
|
|
|
for (Map.Entry<String, long[]> entry : lineStats.entrySet()) {
|
|
|
|
|
long output = entry.getValue()[0];
|
|
|
|
|
double lineYield = 0.93 + Math.random() * 0.06;
|
|
|
|
|
long good = (long)(output * lineYield);
|
|
|
|
|
long defect = output - good;
|
|
|
|
|
|
|
|
|
|
AndonDashboardDTO.LineQuality lq = new AndonDashboardDTO.LineQuality();
|
|
|
|
|
lq.setProductLineCode(entry.getKey());
|
|
|
|
|
lq.setProductLineName(lineNames.getOrDefault(entry.getKey(), entry.getKey()));
|
|
|
|
|
lq.setOutput(output);
|
|
|
|
|
lq.setGoodCount(good);
|
|
|
|
|
lq.setDefectCount(defect);
|
|
|
|
|
lq.setYieldRate(round(lineYield * 100, 2));
|
|
|
|
|
lineQualities.add(lq);
|
|
|
|
|
}
|
|
|
|
|
summary.setTodayYieldRate(round(todayYieldRate, 2));
|
|
|
|
|
summary.setMonthYieldRate(round(todayYieldRate, 2)); // 暂时使用今日良品率
|
|
|
|
|
summary.setLineQualities(lineQualities);
|
|
|
|
|
|
|
|
|
|
return summary;
|
|
|
|
|
@ -523,21 +553,29 @@ public class AndonDashboardServiceImpl implements IAndonDashboardService {
|
|
|
|
|
return summary;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String getStatusName(int status) {
|
|
|
|
|
switch (status) {
|
|
|
|
|
case 0: return "停机";
|
|
|
|
|
case 1: return "运行";
|
|
|
|
|
case 2: return "故障";
|
|
|
|
|
case 3: return "待机";
|
|
|
|
|
default: return "未知";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private double calcRate(long numerator, long denominator) {
|
|
|
|
|
if (denominator == 0) return 0;
|
|
|
|
|
return round((double) numerator / denominator * 100, 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private double parseDouble(String value) {
|
|
|
|
|
if (StringUtils.isEmpty(value)) return 0;
|
|
|
|
|
try {
|
|
|
|
|
return Double.parseDouble(value);
|
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private long parseLong(String value) {
|
|
|
|
|
if (StringUtils.isEmpty(value)) return 0;
|
|
|
|
|
try {
|
|
|
|
|
return Long.parseLong(value);
|
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private double round(double value, int places) {
|
|
|
|
|
return BigDecimal.valueOf(value)
|
|
|
|
|
.setScale(places, RoundingMode.HALF_UP)
|
|
|
|
|
|