refactor(andon): 优化看板服务数据查询逻辑

- 替换设备状态统计为直接调用mapper获取真实数据
- 新增设备参数值mapper依赖注入用于实时状态获取
- 集成设备参数值表查询OEE指标的真实生产数据
- 添加生产质检记录专用实体类和映射器
- 实现基于实际质检数据的良品率统计功能
- 重构设备状态详情获取逻辑使用新的数据源
- 移除设备状态模拟计算改为真实数据查询
master
zangch@mesnac.com 1 day ago
parent 6ed1d4492a
commit 436bdf1419

@ -0,0 +1,434 @@
package com.aucma.production.domain;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.aucma.common.annotation.Excel;
import com.aucma.common.core.domain.BaseEntity;
/**
* report_quality_inspection
*
* aucma-report
* com.aucma.report.domain.ReportQualityInspection
* aucma-reportMyBatis
*
* @author Yinq
* @date 2023-11-21
*/
public class ProductionReportQualityInspection extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
*
*/
private Long objId;
/**
*
*/
@Excel(name = "产品条码")
private String barCode;
/**
*
*/
@Excel(name = "物料名称")
private String materialName;
/**
*
*/
@Excel(name = "工序编号")
private String processCode;
/**
*
*/
@Excel(name = "工序名称")
private String processName;
/**
*
*/
@Excel(name = "检测项编号")
private String testItemCode;
/**
*
*/
@Excel(name = "质量缺陷编码")
private String qualityDefectCode;
/**
*
*/
@Excel(name = "质量缺陷名称")
private String qualityDefectName;
/**
* 3=,1=
*/
@Excel(name = "处理措施")
private String treatmentMeasure;
/**
*
*/
@Excel(name = "处理结果")
private String processResult;
/**
* 线1-2-
*/
@Excel(name = "是否下静态线", readConverterExp = "1=-是2-否")
private String isLowerLine;
/**
*
*/
@Excel(name = "班组编号")
private String groupCode;
/**
*
*/
@Excel(name = "班组名称")
private String groupName;
/**
*
*/
@Excel(name = "检测人员编号")
private String inspectorCode;
/**
*
*/
@Excel(name = "检测人员名称")
private String inspectorName;
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "检测时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date inspectorTime;
/**
*
*/
@Excel(name = "返修次数")
private Long reworkNumber;
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "完成时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date finishTime;
/**
* (1=,2=)
*/
@Excel(name = "返修结果")
private Long isFlag;
/**
*
*/
@Excel(name = "更新人")
private String updatedBy;
/**
*
*/
private String stationCode;
/**
* ID
*/
private int submitQualtyId;
/**
* PDA
*/
private String productLineName;
/**
* SAP
*/
private String orderCode;
/**
* MES
*/
private String planCode;
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "更新时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date updatedTime;
/**
*
*/
private String beginBeginTime;
/**
*
*/
private String endBeginTime;
public String getBeginBeginTime() {
return beginBeginTime;
}
public void setBeginBeginTime(String beginBeginTime) {
this.beginBeginTime = beginBeginTime;
}
public String getEndBeginTime() {
return endBeginTime;
}
public void setEndBeginTime(String endBeginTime) {
this.endBeginTime = endBeginTime;
}
public String getOrderCode() {
return orderCode;
}
public void setOrderCode(String orderCode) {
this.orderCode = orderCode;
}
public String getPlanCode() {
return planCode;
}
public void setPlanCode(String planCode) {
this.planCode = planCode;
}
public String getProcessName() {
return processName;
}
public void setProcessName(String processName) {
this.processName = processName;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public String getInspectorName() {
return inspectorName;
}
public void setInspectorName(String inspectorName) {
this.inspectorName = inspectorName;
}
public void setObjId(Long objId) {
this.objId = objId;
}
public Long getObjId() {
return objId;
}
public void setBarCode(String barCode) {
this.barCode = barCode;
}
public int getSubmitQualtyId() {
return submitQualtyId;
}
public void setSubmitQualtyId(int submitQualtyId) {
this.submitQualtyId = submitQualtyId;
}
public String getBarCode() {
return barCode;
}
public void setMaterialName(String materialName) {
this.materialName = materialName;
}
public String getStationCode() {
return stationCode;
}
public void setStationCode(String stationCode) {
this.stationCode = stationCode;
}
public String getMaterialName() {
return materialName;
}
public void setProcessCode(String processCode) {
this.processCode = processCode;
}
public String getProcessCode() {
return processCode;
}
public void setTestItemCode(String testItemCode) {
this.testItemCode = testItemCode;
}
public String getTestItemCode() {
return testItemCode;
}
public void setQualityDefectCode(String qualityDefectCode) {
this.qualityDefectCode = qualityDefectCode;
}
public String getQualityDefectCode() {
return qualityDefectCode;
}
public void setQualityDefectName(String qualityDefectName) {
this.qualityDefectName = qualityDefectName;
}
public String getQualityDefectName() {
return qualityDefectName;
}
public void setTreatmentMeasure(String treatmentMeasure) {
this.treatmentMeasure = treatmentMeasure;
}
public String getTreatmentMeasure() {
return treatmentMeasure;
}
public void setProcessResult(String processResult) {
this.processResult = processResult;
}
public String getProcessResult() {
return processResult;
}
public void setIsLowerLine(String isLowerLine) {
this.isLowerLine = isLowerLine;
}
public String getIsLowerLine() {
return isLowerLine;
}
public String getProductLineName() {
return productLineName;
}
public void setProductLineName(String productLineName) {
this.productLineName = productLineName;
}
public void setGroupCode(String groupCode) {
this.groupCode = groupCode;
}
public String getGroupCode() {
return groupCode;
}
public void setInspectorCode(String inspectorCode) {
this.inspectorCode = inspectorCode;
}
public String getInspectorCode() {
return inspectorCode;
}
public void setInspectorTime(Date inspectorTime) {
this.inspectorTime = inspectorTime;
}
public Date getInspectorTime() {
return inspectorTime;
}
public void setReworkNumber(Long reworkNumber) {
this.reworkNumber = reworkNumber;
}
public Long getReworkNumber() {
return reworkNumber;
}
public void setFinishTime(Date finishTime) {
this.finishTime = finishTime;
}
public Date getFinishTime() {
return finishTime;
}
public void setIsFlag(Long isFlag) {
this.isFlag = isFlag;
}
public Long getIsFlag() {
return isFlag;
}
public void setUpdatedBy(String updatedBy) {
this.updatedBy = updatedBy;
}
public String getUpdatedBy() {
return updatedBy;
}
public void setUpdatedTime(Date updatedTime) {
this.updatedTime = updatedTime;
}
public Date getUpdatedTime() {
return updatedTime;
}
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("objId", getObjId())
.append("barCode", getBarCode())
.append("materialName", getMaterialName())
.append("processCode", getProcessCode())
.append("testItemCode", getTestItemCode())
.append("qualityDefectCode", getQualityDefectCode())
.append("qualityDefectName", getQualityDefectName())
.append("treatmentMeasure", getTreatmentMeasure())
.append("processResult", getProcessResult())
.append("isLowerLine", getIsLowerLine())
.append("groupCode", getGroupCode())
.append("inspectorCode", getInspectorCode())
.append("inspectorTime", getInspectorTime())
.append("reworkNumber", getReworkNumber())
.append("finishTime", getFinishTime())
.append("isFlag", getIsFlag())
.append("updatedBy", getUpdatedBy())
.append("updatedTime", getUpdatedTime())
.toString();
}
}

@ -0,0 +1,32 @@
package com.aucma.production.mapper;
import java.util.List;
import com.aucma.production.domain.ProductionReportQualityInspection;
/**
* Mapper
*
* aucma-report
* com.aucma.report.mapper.ReportQualityInspectionMapper
* aucma-reportmapperbean
*
* @author Yinq
* @date 2023-11-21
*/
public interface ProductionReportQualityInspectionMapper {
/**
*
*
* @param objId
* @return
*/
public ProductionReportQualityInspection selectReportQualityInspectionByObjId(Long objId);
/**
*
*
* @param reportQualityInspection
* @return
*/
public List<ProductionReportQualityInspection> selectReportQualityInspectionList(ProductionReportQualityInspection reportQualityInspection);
}

@ -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)

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
质检记录管理Mapper XML配置生产模块专用
注意此XML直接从aucma-report模块复制而来用于解决循环依赖问题
原始XML路径aucma-report/src/main/resources/mapper/report/ReportQualityInspectionMapper.xml
已更新namespace以避免与aucma-report模块中的mapper产生bean名称冲突
@author Yinq
@date 2023-11-21
-->
<mapper namespace="com.aucma.production.mapper.ProductionReportQualityInspectionMapper">
<resultMap type="com.aucma.production.domain.ProductionReportQualityInspection" id="ReportQualityInspectionResult">
<result property="objId" column="obj_id"/>
<result property="barCode" column="bar_code"/>
<result property="materialName" column="material_name"/>
<result property="processCode" column="process_code"/>
<result property="testItemCode" column="test_item_code"/>
<result property="qualityDefectCode" column="quality_defect_code"/>
<result property="qualityDefectName" column="quality_defect_name"/>
<result property="treatmentMeasure" column="treatment_measure"/>
<result property="processResult" column="process_result"/>
<result property="isLowerLine" column="is_lower_line"/>
<result property="groupCode" column="group_code"/>
<result property="inspectorCode" column="inspector_code"/>
<result property="inspectorTime" column="inspector_time"/>
<result property="reworkNumber" column="rework_number"/>
<result property="finishTime" column="finish_time"/>
<result property="isFlag" column="is_flag"/>
<result property="updatedBy" column="updated_by"/>
<result property="updatedTime" column="updated_time"/>
<result property="stationCode" column="STATION_CODE"/>
<result property="submitQualtyId" column="SUBMINT_QUALTY_ID"/>
<result property="productLineName" column="PRODUCT_LINE_NAME"/>
<result property="processName" column="processName"/>
<result property="groupName" column="groupName"/>
<result property="inspectorName" column="inspectorName"/>
<result property="orderCode" column="ORDER_CODE"/>
</resultMap>
<sql id="selectReportQualityInspectionVo">
select rqi.obj_id,
rqi.bar_code,
rqi.material_name,
rqi.process_code,
bps.PROCESS_NAME processName,
rqi.test_item_code,
pl.PRODUCT_LINE_NAME PRODUCT_LINE_NAME,
rqi.quality_defect_code,
rqi.quality_defect_name,
rqi.treatment_measure,
rqi.process_result,
rqi.is_lower_line,
rqi.group_code,
btm.TEAM_NAME groupName,
rqi.inspector_code,
su.NICK_NAME inspectorName,
rqi.inspector_time,
rqi.rework_number,
rqi.finish_time,
rqi.is_flag,
rqi.updated_by,
rqi.updated_time
from report_quality_inspection rqi
left join BASE_PROCESS_STATION bps on bps.PROCESS_CODE = rqi.PROCESS_CODE
left join BASE_TEAMMEMBERS btm on btm.TEAM_CODE = rqi.group_code
left join Z_SYS_USER su on su.USER_NAME = rqi.inspector_code
left join BASE_PRODUCTLINE pl on pl.PRODUCT_LINE_CODE = rqi.STATION_CODE
</sql>
<!-- 查询质检记录管理列表 -->
<select id="selectReportQualityInspectionList" parameterType="com.aucma.production.domain.ProductionReportQualityInspection"
resultMap="ReportQualityInspectionResult">
<include refid="selectReportQualityInspectionVo"/>
<where>
<if test="barCode != null and barCode != ''">and rqi.bar_code = #{barCode}</if>
<if test="materialName != null and materialName != ''">and rqi.material_name like concat(concat('%',
#{materialName}), '%')
</if>
<if test="processCode != null and processCode != ''">and rqi.process_code = #{processCode}</if>
<if test="testItemCode != null and testItemCode != ''">and rqi.test_item_code = #{testItemCode}</if>
<if test="qualityDefectCode != null and qualityDefectCode != ''">and rqi.quality_defect_code =
#{qualityDefectCode}
</if>
<if test="qualityDefectName != null and qualityDefectName != ''">and rqi.quality_defect_name like
concat(concat('%', #{qualityDefectName}), '%')
</if>
<if test="treatmentMeasure != null and treatmentMeasure != ''">and rqi.treatment_measure =
#{treatmentMeasure}
</if>
<if test="processResult != null and processResult != ''">and rqi.process_result = #{processResult}</if>
<if test="isLowerLine != null and isLowerLine != ''">and rqi.is_lower_line = #{isLowerLine}</if>
<if test="groupCode != null and groupCode != ''">and rqi.group_code = #{groupCode}</if>
<if test="inspectorCode != null and inspectorCode != ''">and rqi.inspector_code = #{inspectorCode}</if>
<if test="stationCode != null and stationCode != ''">and rqi.station_code = #{stationCode}</if>
<if test="reworkNumber != null ">and rqi.rework_number = #{reworkNumber}</if>
<if test="finishTime != null ">and rqi.finish_time = #{finishTime}</if>
<if test="isFlag != null ">and rqi.is_flag = #{isFlag}</if>
<if test="updatedBy != null and updatedBy != ''">and rqi.updated_by = #{updatedBy}</if>
<if test="updatedTime != null ">and rqi.updated_time = #{updatedTime}</if>
<if test="beginBeginTime != null and beginBeginTime != '' and endBeginTime != null and endBeginTime != ''">
AND rqi.inspector_time BETWEEN TO_DATE(#{beginBeginTime}, 'YYYY-MM-DD HH24:MI:SS') AND TO_DATE(#{endBeginTime}, 'YYYY-MM-DD HH24:MI:SS')
</if>
</where>
order by rqi.inspector_time desc
</select>
<!-- 根据主键查询质检记录管理 -->
<select id="selectReportQualityInspectionByObjId" parameterType="Long" resultMap="ReportQualityInspectionResult">
<include refid="selectReportQualityInspectionVo"/>
where rqi.obj_id = #{objId}
</select>
</mapper>
Loading…
Cancel
Save