package com.ruoyi.production.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.ruoyi.basic.mapper.ProductMapper;
|
import com.ruoyi.basic.mapper.ProductModelMapper;
|
import com.ruoyi.basic.mapper.SupplierManageMapper;
|
import com.ruoyi.basic.pojo.Product;
|
import com.ruoyi.basic.pojo.ProductModel;
|
import com.ruoyi.basic.pojo.SupplierManage;
|
import com.ruoyi.home.dto.processDataProductionStatisticsDto;
|
import com.ruoyi.production.dto.ProductionStatisticDto;
|
import com.ruoyi.production.mapper.ProductProcessMapper;
|
import com.ruoyi.production.mapper.ProductWorkOrderMapper;
|
import com.ruoyi.production.mapper.ProductionProductInputMapper;
|
import com.ruoyi.production.mapper.ProductionProductOutputMapper;
|
import com.ruoyi.production.pojo.ProductProcess;
|
import com.ruoyi.production.pojo.ProductWorkOrder;
|
import com.ruoyi.production.pojo.ProductionProductInput;
|
import com.ruoyi.production.pojo.ProductionProductOutput;
|
import com.ruoyi.production.service.ProductionStatisticService;
|
import com.ruoyi.quality.mapper.QualityInspectMapper;
|
import com.ruoyi.quality.pojo.QualityInspect;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
|
import java.math.BigDecimal;
|
import java.time.LocalDate;
|
import java.time.LocalDateTime;
|
import java.time.LocalTime;
|
import java.time.YearMonth;
|
import java.time.ZoneId;
|
import java.util.Date;
|
import java.util.Set;
|
import java.util.TreeSet;
|
import java.time.temporal.TemporalAdjusters;
|
import java.util.ArrayList;
|
import java.util.HashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
/**
|
* 生产统计服务实现类
|
*/
|
@Service
|
public class ProductionStatisticServiceImpl implements ProductionStatisticService {
|
|
@Autowired
|
private ProductProcessMapper productProcessMapper;
|
|
@Autowired
|
private ProductWorkOrderMapper productWorkOrderMapper;
|
|
@Autowired
|
private ProductionProductOutputMapper productionProductOutputMapper;
|
|
@Autowired
|
private ProductionProductInputMapper productionProductInputMapper;
|
|
@Autowired
|
private QualityInspectMapper qualityInspectMapper;
|
|
@Autowired
|
private SupplierManageMapper supplierManageMapper;
|
|
@Autowired
|
private ProductModelMapper productModelMapper;
|
|
@Autowired
|
private ProductMapper productMapper;
|
|
@Override
|
public ProductionStatisticDto getWorkOrderCount() {
|
ProductionStatisticDto dto = new ProductionStatisticDto();
|
|
// 查询工单总数
|
Long totalCount = productWorkOrderMapper.selectCount(null);
|
dto.setTotalCount(totalCount);
|
|
// 查询进行中工单(完成数量小于需求数量)
|
Long inProgressCount = productWorkOrderMapper.selectCount(
|
new LambdaQueryWrapper<ProductWorkOrder>()
|
.apply("complete_quantity < plan_quantity and complete_quantity > 0")
|
);
|
dto.setInProgressCount(inProgressCount);
|
|
// 查询已完成工单(完成数量大于等于需求数量)
|
Long completedCount = productWorkOrderMapper.selectCount(
|
new LambdaQueryWrapper<ProductWorkOrder>()
|
.apply("complete_quantity >= plan_quantity and complete_quantity > 0")
|
);
|
dto.setCompletedCount(completedCount);
|
|
// 查询待完成工单(完成数量为0)
|
Long pendingCount = productWorkOrderMapper.selectCount(
|
new LambdaQueryWrapper<ProductWorkOrder>()
|
.eq(ProductWorkOrder::getCompleteQuantity, 0)
|
);
|
dto.setPendingCount(pendingCount);
|
|
return dto;
|
}
|
|
@Override
|
public Map<String, Object> getQualityStatistics() {
|
Map<String, Object> result = new HashMap<>();
|
|
// 查询所有报工记录
|
List<ProductionProductOutput> outputList = productionProductOutputMapper.selectList(null);
|
|
// 计算报工总数、报废总数和不良总数
|
BigDecimal totalOutput = BigDecimal.ZERO;
|
BigDecimal totalScrap = BigDecimal.ZERO;
|
BigDecimal totalDefect = BigDecimal.ZERO;
|
|
for (ProductionProductOutput output : outputList) {
|
// 报工总数
|
if (output.getQuantity() != null) {
|
totalOutput = totalOutput.add(output.getQuantity());
|
}
|
// 报废数量
|
if (output.getScrapQty() != null) {
|
totalScrap = totalScrap.add(output.getScrapQty());
|
}
|
// 不良数量(从QualityInspect表查询)
|
List<QualityInspect> qualityInspects = qualityInspectMapper.selectList(
|
new LambdaQueryWrapper<QualityInspect>()
|
.eq(QualityInspect::getProductMainId, output.getProductMainId())
|
);
|
for (QualityInspect inspect : qualityInspects) {
|
if (inspect.getDefectiveQuantity() != null) {
|
totalDefect = totalDefect.add(inspect.getDefectiveQuantity());
|
}
|
}
|
}
|
|
// 计算合格数量
|
BigDecimal qualifiedQuantity = totalOutput.subtract(totalScrap).subtract(totalDefect);
|
|
// 计算合格率和不良率
|
double qualifiedRate = 0.0;
|
double defectRate = 0.0;
|
if (totalOutput.compareTo(BigDecimal.ZERO) > 0) {
|
// 使用BigDecimal确保精度
|
BigDecimal qualifiedRateBD = qualifiedQuantity.divide(totalOutput, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));
|
BigDecimal defectRateBD = totalDefect.divide(totalOutput, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));
|
// 保留两位小数
|
qualifiedRate = qualifiedRateBD.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
|
defectRate = defectRateBD.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
|
}
|
|
result.put("qualifiedRate", qualifiedRate); // 合格率
|
result.put("defectRate", defectRate); // 不良率
|
result.put("scrapCount", totalScrap.intValue()); // 报废总数
|
|
return result;
|
}
|
|
@Override
|
public Map<String, Object> getProductionStatistics() {
|
Map<String, Object> result = new HashMap<>();
|
|
// 获取当前月份和上一个月份的开始和结束时间
|
LocalDateTime now = LocalDateTime.now();
|
YearMonth currentMonth = YearMonth.from(now);
|
LocalDateTime currentMonthStart = now.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
|
LocalDateTime currentMonthEnd = currentMonth.atEndOfMonth().atTime(23, 59, 59);
|
LocalDateTime lastMonth = now.minusMonths(1);
|
LocalDateTime lastMonthStart = lastMonth.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
|
LocalDateTime lastMonthEnd = currentMonthStart.minusDays(1).withHour(23).withMinute(59).withSecond(59);
|
|
// 计算生产总产出(当前月)
|
List<ProductionProductOutput> currentOutputList = productionProductOutputMapper.selectList(
|
new LambdaQueryWrapper<ProductionProductOutput>()
|
.ge(ProductionProductOutput::getCreateTime, currentMonthStart)
|
.le(ProductionProductOutput::getCreateTime, currentMonthEnd)
|
);
|
BigDecimal currentProductionOutput = BigDecimal.ZERO;
|
for (ProductionProductOutput output : currentOutputList) {
|
if (output.getQuantity() != null) {
|
currentProductionOutput = currentProductionOutput.add(output.getQuantity());
|
}
|
}
|
|
// 计算生产总产出(上月)
|
List<ProductionProductOutput> lastOutputList = productionProductOutputMapper.selectList(
|
new LambdaQueryWrapper<ProductionProductOutput>()
|
.ge(ProductionProductOutput::getCreateTime, lastMonthStart)
|
.le(ProductionProductOutput::getCreateTime, lastMonthEnd)
|
);
|
BigDecimal lastProductionOutput = BigDecimal.ZERO;
|
for (ProductionProductOutput output : lastOutputList) {
|
if (output.getQuantity() != null) {
|
lastProductionOutput = lastProductionOutput.add(output.getQuantity());
|
}
|
}
|
|
// 计算生产总消耗(当前月)
|
List<ProductionProductInput> currentInputList = productionProductInputMapper.selectList(
|
new LambdaQueryWrapper<ProductionProductInput>()
|
.ge(ProductionProductInput::getCreateTime, currentMonthStart)
|
.le(ProductionProductInput::getCreateTime, currentMonthEnd)
|
);
|
BigDecimal currentProductionConsumption = BigDecimal.ZERO;
|
for (ProductionProductInput input : currentInputList) {
|
if (input.getQuantity() != null) {
|
currentProductionConsumption = currentProductionConsumption.add(input.getQuantity());
|
}
|
}
|
|
// 计算生产总消耗(上月)
|
List<ProductionProductInput> lastInputList = productionProductInputMapper.selectList(
|
new LambdaQueryWrapper<ProductionProductInput>()
|
.ge(ProductionProductInput::getCreateTime, lastMonthStart)
|
.le(ProductionProductInput::getCreateTime, lastMonthEnd)
|
);
|
BigDecimal lastProductionConsumption = BigDecimal.ZERO;
|
for (ProductionProductInput input : lastInputList) {
|
if (input.getQuantity() != null) {
|
lastProductionConsumption = lastProductionConsumption.add(input.getQuantity());
|
}
|
}
|
|
// 计算供应商数量(当前月)
|
List<SupplierManage> currentSuppliers = supplierManageMapper.selectList(
|
new LambdaQueryWrapper<SupplierManage>()
|
.ge(SupplierManage::getCreateTime, currentMonthStart)
|
.le(SupplierManage::getCreateTime, currentMonthEnd)
|
);
|
int currentSupplierCount = currentSuppliers != null ? currentSuppliers.size() : 0;
|
|
// 计算供应商数量(上月)
|
List<SupplierManage> lastSuppliers = supplierManageMapper.selectList(
|
new LambdaQueryWrapper<SupplierManage>()
|
.ge(SupplierManage::getCreateTime, lastMonthStart)
|
.le(SupplierManage::getCreateTime, lastMonthEnd)
|
);
|
int lastSupplierCount = lastSuppliers != null ? lastSuppliers.size() : 0;
|
|
// 计算趋势
|
double productionOutputMonthlyChange = 0.0;
|
if (lastProductionOutput.compareTo(BigDecimal.ZERO) > 0) {
|
productionOutputMonthlyChange = (currentProductionOutput.subtract(lastProductionOutput)
|
.divide(lastProductionOutput, 4, BigDecimal.ROUND_HALF_UP).doubleValue()) * 100;
|
}
|
|
double productionConsumptionMonthlyChange = 0.0;
|
if (lastProductionConsumption.compareTo(BigDecimal.ZERO) > 0) {
|
productionConsumptionMonthlyChange = (currentProductionConsumption.subtract(lastProductionConsumption)
|
.divide(lastProductionConsumption, 4, BigDecimal.ROUND_HALF_UP).doubleValue()) * 100;
|
}
|
|
double supplierCountMonthlyChange = 0.0;
|
if (lastSupplierCount > 0) {
|
supplierCountMonthlyChange = ((currentSupplierCount - lastSupplierCount) * 100.0) / lastSupplierCount;
|
}
|
|
result.put("productionOutput", currentProductionOutput.doubleValue()); // 生产总产
|
result.put("productionConsumption", currentProductionConsumption.doubleValue()); // 生产总消耗
|
result.put("productionOutputMonthlyChange", productionOutputMonthlyChange); // 生产总产月度变化
|
result.put("productionConsumptionMonthlyChange", productionConsumptionMonthlyChange); // 生产总消耗月度变化
|
result.put("supplierCount", currentSupplierCount); // 产品总供应公司
|
result.put("supplierCountMonthlyChange", supplierCountMonthlyChange); // 供应商数量月度变化
|
|
return result;
|
}
|
|
@Override
|
public List<Map<String, Object>> getProductOutputCategoryPieData() {
|
List<Map<String, Object>> result = new ArrayList<>();
|
// 按产品大类
|
// 查询所有报工记录
|
List<ProductionProductOutput> outputList = productionProductOutputMapper.selectList(null);
|
|
// 按产品分组计算产出数量
|
Map<Long, BigDecimal> productOutputMap = new HashMap<>();
|
|
for (ProductionProductOutput output : outputList) {
|
if (output.getProductModelId() != null && output.getQuantity() != null) {
|
// 根据productModelId查询ProductModel
|
ProductModel productModel = productModelMapper.selectById(output.getProductModelId());
|
if (productModel != null && productModel.getProductId() != null) {
|
// 根据productId查询Product
|
Product product = productMapper.selectById(productModel.getProductId());
|
if (product != null) {
|
// 按产品ID分组计算产出数量
|
productOutputMap.put(product.getId(),
|
productOutputMap.getOrDefault(product.getId(), BigDecimal.ZERO).add(output.getQuantity()));
|
}
|
}
|
}
|
}
|
|
// 转换为结果格式
|
for (Map.Entry<Long, BigDecimal> entry : productOutputMap.entrySet()) {
|
Product product = productMapper.selectById(entry.getKey());
|
if (product != null) {
|
Map<String, Object> item = new HashMap<>();
|
item.put("name", product.getProductName());
|
item.put("value", entry.getValue().intValue());
|
result.add(item);
|
}
|
}
|
|
return result;
|
}
|
|
@Override
|
public List<Map<String, Object>> getDefectReasonAnalysis() {
|
List<Map<String, Object>> result = new ArrayList<>();
|
|
// 查询所有质量检验记录
|
List<QualityInspect> qualityInspectList = qualityInspectMapper.selectList(null);
|
|
// 按不良原因分组统计数量
|
Map<String, Integer> reasonCountMap = new HashMap<>();
|
|
for (QualityInspect inspect : qualityInspectList) {
|
if (inspect.getDefectiveReason() != null && !inspect.getDefectiveReason().isEmpty()) {
|
String reason = inspect.getDefectiveReason();
|
reasonCountMap.put(reason, reasonCountMap.getOrDefault(reason, 0) + 1);
|
}
|
}
|
|
// 转换为结果格式
|
for (Map.Entry<String, Integer> entry : reasonCountMap.entrySet()) {
|
Map<String, Object> item = new HashMap<>();
|
item.put("name", entry.getKey());
|
item.put("value", entry.getValue());
|
result.add(item);
|
}
|
|
return result;
|
}
|
|
@Override
|
public List<Map<String, Object>> getProcessDefectRateAnalysis(String startDate, String endDate) {
|
List<Map<String, Object>> result = new ArrayList<>();
|
|
// 默认查询近一个月数据
|
if (startDate == null || endDate == null) {
|
LocalDate now = LocalDate.now();
|
startDate = now.minusMonths(1).toString();
|
endDate = now.toString();
|
}
|
|
// 解析日期
|
LocalDate startLocalDate = LocalDate.parse(startDate);
|
LocalDate endLocalDate = LocalDate.parse(endDate);
|
Date start = Date.from(startLocalDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
Date end = Date.from(endLocalDate.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
|
|
// 查询所有工序
|
List<ProductProcess> processList = productProcessMapper.selectList(null);
|
|
// 收集所有日期
|
Set<LocalDate> dateSet = new TreeSet<>();
|
LocalDate currentDate = startLocalDate;
|
while (!currentDate.isAfter(endLocalDate)) {
|
dateSet.add(currentDate);
|
currentDate = currentDate.plusDays(1);
|
}
|
|
// 一次性查询所有日期范围内的质量检验记录
|
List<QualityInspect> allQualityInspects = qualityInspectMapper.selectList(
|
new LambdaQueryWrapper<QualityInspect>()
|
.ge(QualityInspect::getCheckTime, start)
|
.lt(QualityInspect::getCheckTime, end)
|
);
|
|
// 按日期和工序分组处理数据
|
Map<LocalDate, Map<String, BigDecimal[]>> dateProcessMap = new HashMap<>();
|
|
for (QualityInspect inspect : allQualityInspects) {
|
if (inspect.getCheckTime() != null && inspect.getProcess() != null) {
|
// 转换检查时间为LocalDate
|
LocalDate inspectDate = inspect.getCheckTime().toInstant()
|
.atZone(ZoneId.systemDefault()).toLocalDate();
|
|
// 确保日期在查询范围内
|
if (dateSet.contains(inspectDate)) {
|
String processName = inspect.getProcess();
|
|
// 初始化日期和工序数据
|
dateProcessMap.computeIfAbsent(inspectDate, k -> new HashMap<>());
|
BigDecimal[] quantities = dateProcessMap.get(inspectDate)
|
.computeIfAbsent(processName, k -> new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO});
|
|
// 累加数量
|
if (inspect.getQuantity() != null) {
|
quantities[0] = quantities[0].add(inspect.getQuantity());
|
}
|
if (inspect.getDefectiveQuantity() != null) {
|
quantities[1] = quantities[1].add(inspect.getDefectiveQuantity());
|
}
|
}
|
}
|
}
|
|
// 构建结果数据
|
for (LocalDate date : dateSet) {
|
Map<String, Object> item = new HashMap<>();
|
item.put("date", date.toString());
|
|
// 初始化每日总数量和不良数量
|
BigDecimal dailyTotalQuantity = BigDecimal.ZERO;
|
BigDecimal dailyDefectiveQuantity = BigDecimal.ZERO;
|
|
// 初始化工序数据列表
|
List<Map<String, Object>> processesList = new ArrayList<>();
|
|
// 获取该日期的工序数据
|
Map<String, BigDecimal[]> processData = dateProcessMap.getOrDefault(date, new HashMap<>());
|
|
for (ProductProcess process : processList) {
|
if (process.getName() != null) {
|
String processName = process.getName();
|
BigDecimal[] quantities = processData.getOrDefault(processName, new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO});
|
|
BigDecimal processTotalQuantity = quantities[0];
|
BigDecimal processDefectiveQuantity = quantities[1];
|
|
// 累加每日总数量
|
dailyTotalQuantity = dailyTotalQuantity.add(processTotalQuantity);
|
dailyDefectiveQuantity = dailyDefectiveQuantity.add(processDefectiveQuantity);
|
|
// 计算该工序的不良率
|
double processDefectRate = 0.0;
|
if (processTotalQuantity.compareTo(BigDecimal.ZERO) > 0) {
|
// 计算不良率,保留两位小数
|
BigDecimal defectRateDecimal = processDefectiveQuantity.divide(processTotalQuantity, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));
|
processDefectRate = defectRateDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
|
}
|
|
// 构建工序数据对象
|
Map<String, Object> processMap = new HashMap<>();
|
processMap.put(process.getName(), processDefectRate);
|
processesList.add(processMap);
|
}
|
}
|
|
// 计算每日平均不良率
|
double dailyAverageDefectRate = 0.0;
|
if (dailyTotalQuantity.compareTo(BigDecimal.ZERO) > 0) {
|
// 计算不良率,保留两位小数
|
BigDecimal defectRateDecimal = dailyDefectiveQuantity.divide(dailyTotalQuantity, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));
|
dailyAverageDefectRate = defectRateDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
|
}
|
|
// 添加平均不良率和工序数据到结果项
|
item.put("averageDefectRate", dailyAverageDefectRate);
|
item.put("processes", processesList);
|
|
result.add(item);
|
}
|
|
return result;
|
}
|
}
|