src/main/java/com/ruoyi/quality/controller/QualityReportController.java
@@ -1,15 +1,12 @@ package com.ruoyi.quality.controller; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.quality.pojo.QualityTestStandardParam; import com.ruoyi.quality.service.QualityReportService; import com.ruoyi.quality.service.QualityTestStandardParamService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.*; import java.util.List; /** * <p> @@ -19,6 +16,7 @@ * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-01-14 03:39:49 */ @Api(tags = "è´¨é管ç") @RestController @RequestMapping("/qualityReport") public class QualityReportController { @@ -26,6 +24,58 @@ @Autowired private QualityReportService qualityReportService; /** * è·åæ£éªç»è®¡æ°æ® */ @ApiOperation("è·åæ£éªç»è®¡æ°æ®") @GetMapping("/getInspectStatistics") public AjaxResult getInspectStatistics() { return AjaxResult.success(qualityReportService.getInspectStatistics()); } /** * è·ååæ ¼çç»è®¡æ°æ® */ @ApiOperation("è·ååæ ¼çç»è®¡æ°æ®") @GetMapping("/getPassRateStatistics") public AjaxResult getPassRateStatistics() { return AjaxResult.success(qualityReportService.getPassRateStatistics()); } /** * è·åæåº¦åæ ¼çç»è®¡æ°æ® */ @ApiOperation("è·åæåº¦åæ ¼çç»è®¡æ°æ®") @GetMapping("/getMonthlyPassRateStatistics") public AjaxResult getMonthlyPassRateStatistics(@RequestParam("year") String year) { return AjaxResult.success(qualityReportService.getMonthlyPassRateStatistics(year)); } /** * è·å年度æ»åæ ¼çç»è®¡æ°æ® */ @ApiOperation("è·å年度æ»åæ ¼çç»è®¡æ°æ®") @GetMapping("/getYearlyPassRateStatistics") public AjaxResult getYearlyPassRateStatistics(@RequestParam("year") String year) { return AjaxResult.success(qualityReportService.getYearlyPassRateStatistics(year)); } /** * è·åæåº¦å®ææç»æ°æ® */ @ApiOperation("è·åæåº¦å®ææç»æ°æ®") @GetMapping("/getMonthlyCompletionDetails") public AjaxResult getMonthlyCompletionDetails(@RequestParam("year") String year) { return AjaxResult.success(qualityReportService.getMonthlyCompletionDetails(year)); } /** * è·åçç¹æ£æµææ ç»è®¡ */ @ApiOperation("è·åçç¹æ£æµææ ç»è®¡") @GetMapping("/getTopParameters") public AjaxResult getTopParameters(@RequestParam("inspectType") Integer inspectType) { return AjaxResult.success(qualityReportService.getTopParameters(inspectType)); } } src/main/java/com/ruoyi/quality/dto/QualityInspectStatDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,24 @@ package com.ruoyi.quality.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.math.BigDecimal; import java.io.Serializable; @Data @ApiModel(value = "QualityInspectStatDto", description = "è´¨éæ£éªç»è®¡DTO") public class QualityInspectStatDto implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "ç±»å«(0:åæææ£éª;1:è¿ç¨æ£éª;2:åºåæ£éª)") private Integer inspectType; @ApiModelProperty(value = "æ»æ°é") private BigDecimal totalCount; @ApiModelProperty(value = "已宿æ°é") private BigDecimal completedCount; } src/main/java/com/ruoyi/quality/dto/QualityMonthlyDetailDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,29 @@ package com.ruoyi.quality.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; /** * è´¨éæåº¦å®ææç»DTO */ @Data @ApiModel(value = "QualityMonthlyDetailDto", description = "è´¨éæåº¦å®ææç»DTO") public class QualityMonthlyDetailDto implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "æä»½") private String month; @ApiModelProperty(value = "åæææ£éªå®ææ°") private BigDecimal rawMaterialCount; @ApiModelProperty(value = "è¿ç¨æ£éªå®ææ°") private BigDecimal processCount; @ApiModelProperty(value = "åºåæ£éªå®ææ°") private BigDecimal outgoingCount; } src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,41 @@ package com.ruoyi.quality.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; /** * è´¨éæåº¦åæ ¼çç»è®¡DTO */ @Data @ApiModel(value = "QualityMonthlyPassRateDto", description = "è´¨éæåº¦åæ ¼çç»è®¡DTO") public class QualityMonthlyPassRateDto implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "æä»½(䏿, äºæ...)") private String month; @ApiModelProperty(value = "ç±»å«(0:åæææ£éª;1:è¿ç¨æ£éª;2:åºåæ£éª)") private Integer inspectType; @ApiModelProperty(value = "æ»æ°é") private BigDecimal totalCount; @ApiModelProperty(value = "已宿æ°é") private BigDecimal completedCount; @ApiModelProperty(value = "åæ ¼æ°é") private BigDecimal qualifiedCount; @ApiModelProperty(value = "ä¸åæ ¼æ°é") private BigDecimal unqualifiedCount; @ApiModelProperty(value = "å®æå æ¯") private BigDecimal completionRate; @ApiModelProperty(value = "åæ ¼çå æ¯") private BigDecimal passRate; } src/main/java/com/ruoyi/quality/dto/QualityMonthlyPassRateWrapperDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,28 @@ package com.ruoyi.quality.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; /** * è´¨éæåº¦åæ ¼çå è£ DTOï¼ææåç»ï¼ */ @Data @ApiModel(value = "QualityMonthlyPassRateWrapperDto", description = "è´¨éæåº¦åæ ¼çå è£ DTOï¼ææåç»ï¼") public class QualityMonthlyPassRateWrapperDto implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "æä»½") private String month; @ApiModelProperty(value = "åæææ£éªæ°æ®") private QualityPassRateDto rawMaterial; @ApiModelProperty(value = "è¿ç¨æ£éªæ°æ®") private QualityPassRateDto process; @ApiModelProperty(value = "åºåæ£éªæ°æ®") private QualityPassRateDto outgoing; } src/main/java/com/ruoyi/quality/dto/QualityParameterStatDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,26 @@ package com.ruoyi.quality.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; /** * æ£éªææ ç»è®¡DTO */ @Data @ApiModel(value = "QualityParameterStatDto", description = "æ£éªææ ç»è®¡DTO") public class QualityParameterStatDto implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "ææ åç§°") private String name; @ApiModelProperty(value = "æ°é") private BigDecimal count; @ApiModelProperty(value = "ç¾åæ¯") private BigDecimal percentage; } src/main/java/com/ruoyi/quality/dto/QualityPassRateDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,39 @@ package com.ruoyi.quality.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; /** * è´¨éåæ ¼çç»è®¡DTO */ @Data @ApiModel(value = "QualityPassRateDto", description = "è´¨éåæ ¼çç»è®¡DTO") public class QualityPassRateDto implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "ç±»å«(0:åæææ£éª;1:è¿ç¨æ£éª;2:åºåæ£éª)") private Integer inspectType; @ApiModelProperty(value = "æ»æ°é") private BigDecimal totalCount; @ApiModelProperty(value = "已宿æ°é") private BigDecimal completedCount; @ApiModelProperty(value = "åæ ¼æ°é") private BigDecimal qualifiedCount; @ApiModelProperty(value = "ä¸åæ ¼æ°é") private BigDecimal unqualifiedCount; @ApiModelProperty(value = "å®æå æ¯") private BigDecimal completionRate; @ApiModelProperty(value = "åæ ¼çå æ¯") private BigDecimal passRate; } src/main/java/com/ruoyi/quality/dto/QualityTopParameterDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,24 @@ package com.ruoyi.quality.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; import java.util.List; /** * è´¨æ£çç¹ææ ç»è®¡ç»æDTO (åç±»å) */ @Data @ApiModel(value = "QualityTopParameterDto", description = "è´¨æ£çç¹ææ ç»è®¡ç»æDTO (åç±»å)") public class QualityTopParameterDto implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "æ»æ£æµé¡¹æ¬¡æ°é") private BigDecimal totalCount; @ApiModelProperty(value = "ææ ç»è®¡å表 (Top 4 + å ¶ä»)") private List<QualityParameterStatDto> list; } src/main/java/com/ruoyi/quality/mapper/QualityInspectMapper.java
@@ -4,9 +4,14 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.quality.pojo.QualityInspect; import com.ruoyi.quality.pojo.QualityTestStandard; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import com.ruoyi.quality.dto.QualityInspectStatDto; import com.ruoyi.quality.dto.QualityPassRateDto; import com.ruoyi.quality.dto.QualityMonthlyPassRateDto; import com.ruoyi.quality.dto.QualityMonthlyDetailDto; import com.ruoyi.quality.dto.QualityParameterStatDto; import java.util.List; @@ -22,4 +27,34 @@ * æ ¹æ®ç产主表IDæ¹éå é¤è¿ç¨æ£éª */ int deleteByProductMainIds(@Param("productMainIds") List<Long> productMainIds); /** * è·åæ£éªç»è®¡æ°æ® */ List<QualityInspectStatDto> getInspectStatistics(); /** * è·ååæ ¼çç»è®¡æ°æ® */ List<QualityPassRateDto> getPassRateStatistics(); /** * è·åæåº¦åæ ¼çç»è®¡æ°æ® */ List<QualityMonthlyPassRateDto> getMonthlyPassRateStatistics(@Param("year") String year); /** * è·åå¹´åº¦åæ ¼çç»è®¡æ°æ® */ List<QualityPassRateDto> getYearlyPassRateStatistics(@Param("year") String year); /** * è·åæåº¦å®ææç»æ°æ® */ List<QualityMonthlyDetailDto> getMonthlyCompletionDetails(@Param("year") String year); /** * è·åçç¹æ£æµææ Top 4 + å ¶ä» */ List<QualityParameterStatDto> getTopParameters(@Param("inspectType") Integer inspectType); } src/main/java/com/ruoyi/quality/service/QualityReportService.java
@@ -1,7 +1,13 @@ package com.ruoyi.quality.service; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.quality.pojo.QualityTestStandardParam; import com.ruoyi.quality.dto.QualityInspectStatDto; import com.ruoyi.quality.dto.QualityPassRateDto; import com.ruoyi.quality.dto.QualityMonthlyDetailDto; import com.ruoyi.quality.dto.QualityParameterStatDto; import com.ruoyi.quality.dto.QualityMonthlyPassRateWrapperDto; import com.ruoyi.quality.dto.QualityTopParameterDto; import java.util.List; /** * <p> @@ -11,6 +17,17 @@ * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-01-13 03:39:49 */ public interface QualityReportService { public interface QualityReportService { List<QualityInspectStatDto> getInspectStatistics(); List<QualityPassRateDto> getPassRateStatistics(); List<QualityMonthlyPassRateWrapperDto> getMonthlyPassRateStatistics(String year); List<QualityPassRateDto> getYearlyPassRateStatistics(String year); List<QualityMonthlyDetailDto> getMonthlyCompletionDetails(String year); QualityTopParameterDto getTopParameters(Integer inspectType); } src/main/java/com/ruoyi/quality/service/impl/QualityReportServiceImpl.java
@@ -1,9 +1,109 @@ package com.ruoyi.quality.service.impl; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.quality.dto.QualityPassRateDto; import com.ruoyi.quality.dto.QualityInspectStatDto; import com.ruoyi.quality.dto.QualityMonthlyPassRateDto; import com.ruoyi.quality.dto.QualityMonthlyDetailDto; import com.ruoyi.quality.dto.QualityParameterStatDto; import com.ruoyi.quality.dto.QualityMonthlyPassRateWrapperDto; import com.ruoyi.quality.dto.QualityTopParameterDto; import com.ruoyi.quality.mapper.QualityInspectMapper; import com.ruoyi.quality.service.QualityReportService; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @Service public class QualityReportServiceImpl implements QualityReportService { @Autowired private QualityInspectMapper qualityInspectMapper; @Override public List<QualityInspectStatDto> getInspectStatistics() { return qualityInspectMapper.getInspectStatistics(); } @Override public List<QualityPassRateDto> getPassRateStatistics() { return qualityInspectMapper.getPassRateStatistics(); } @Override public List<QualityMonthlyPassRateWrapperDto> getMonthlyPassRateStatistics(String year) { if (StringUtils.isEmpty(year)) { return new ArrayList<>(); } List<QualityMonthlyPassRateDto> flatData = qualityInspectMapper.getMonthlyPassRateStatistics(year); // ææä»½åç»ï¼å¹¶ä¿æé¡ºåº Map<String, List<QualityMonthlyPassRateDto>> groupedByMonth = flatData.stream() .collect(Collectors.groupingBy(QualityMonthlyPassRateDto::getMonth, LinkedHashMap::new, Collectors.toList())); List<QualityMonthlyPassRateWrapperDto> result = new ArrayList<>(); groupedByMonth.forEach((month, dtos) -> { QualityMonthlyPassRateWrapperDto wrapper = new QualityMonthlyPassRateWrapperDto(); wrapper.setMonth(month); for (QualityMonthlyPassRateDto dto : dtos) { QualityPassRateDto passRateDto = new QualityPassRateDto(); BeanUtils.copyProperties(dto, passRateDto); if (dto.getInspectType() == 0) { wrapper.setRawMaterial(passRateDto); } else if (dto.getInspectType() == 1) { wrapper.setProcess(passRateDto); } else if (dto.getInspectType() == 2) { wrapper.setOutgoing(passRateDto); } } result.add(wrapper); }); return result; } @Override public List<QualityPassRateDto> getYearlyPassRateStatistics(String year) { if (StringUtils.isEmpty(year)) { return new ArrayList<>(); } return qualityInspectMapper.getYearlyPassRateStatistics(year); } @Override public List<QualityMonthlyDetailDto> getMonthlyCompletionDetails(String year) { if (StringUtils.isEmpty(year)) { return new ArrayList<>(); } return qualityInspectMapper.getMonthlyCompletionDetails(year); } @Override public QualityTopParameterDto getTopParameters(Integer inspectType) { if (inspectType == null) { return new QualityTopParameterDto(); } List<QualityParameterStatDto> list = qualityInspectMapper.getTopParameters(inspectType); BigDecimal total = list.stream() .map(QualityParameterStatDto::getCount) .reduce(BigDecimal.ZERO, BigDecimal::add); QualityTopParameterDto result = new QualityTopParameterDto(); result.setTotalCount(total); result.setList(list); return result; } } src/main/resources/mapper/quality/QualityInspectMapper.xml
@@ -23,7 +23,7 @@ AND check_time >= DATE_FORMAT(#{qualityInspect.entryDateStart},'%Y-%m-%d') </if> <if test="qualityInspect.entryDateEnd != null and qualityInspect.entryDateEnd != '' "> AND check_time <= DATE_FORMAT(#{qualityInspect.entryDateEnd},'%Y-%m-%d') AND check_time <= DATE_FORMAT(#{qualityInspect.entryDateEnd},'%Y-%m-%d') </if> ORDER BY check_time DESC </select> @@ -55,4 +55,286 @@ </foreach> </delete> <select id="getInspectStatistics" resultType="com.ruoyi.quality.dto.QualityInspectStatDto"> SELECT 0 AS inspectType, COALESCE((SELECT SUM(inbound_num) FROM procurement_record_storage WHERE type = 1), 0) + COALESCE((SELECT SUM(quantity) FROM quality_unqualified WHERE inspect_type = 0), 0) AS totalCount, COALESCE((SELECT SUM(inbound_num) FROM procurement_record_storage WHERE type = 1 AND quality_inspect_id != 0 AND quality_inspect_id IS NOT NULL), 0) + COALESCE((SELECT SUM(quantity) FROM quality_unqualified WHERE inspect_type = 0), 0) AS completedCount UNION ALL SELECT 1 AS inspectType, COALESCE((SELECT SUM(inbound_num) FROM procurement_record_storage WHERE type = 2 AND sales_ledger_product_id = 0), 0) AS totalCount, COALESCE((SELECT SUM(inbound_num) FROM procurement_record_storage WHERE type = 2 AND sales_ledger_product_id = 0 AND quality_inspect_id != 0 AND quality_inspect_id IS NOT NULL), 0) AS completedCount UNION ALL SELECT 2 AS inspectType, COALESCE((SELECT SUM(inbound_num) FROM procurement_record_storage WHERE type = 2 AND sales_ledger_product_id != 0), 0) AS totalCount, COALESCE((SELECT SUM(inbound_num) FROM procurement_record_storage WHERE type = 2 AND sales_ledger_product_id != 0 AND quality_inspect_id != 0 AND quality_inspect_id IS NOT NULL), 0) AS completedCount </select> <select id="getPassRateStatistics" resultType="com.ruoyi.quality.dto.QualityPassRateDto"> SELECT t.inspectType, COALESCE(prs.totalCount, 0) AS totalCount, COALESCE(qi.completedCount, 0) AS completedCount, COALESCE(qi.qualifiedCount, 0) AS qualifiedCount, COALESCE(qi.unqualifiedCount, 0) AS unqualifiedCount, IF(COALESCE(prs.totalCount, 0) = 0, 0, ROUND(COALESCE(qi.completedCount, 0) / prs.totalCount * 100, 2)) AS completionRate, IF(COALESCE(qi.completedCount, 0) = 0, 0, ROUND(COALESCE(qi.qualifiedCount, 0) / qi.completedCount * 100, 2)) AS passRate FROM (SELECT 0 AS inspectType UNION ALL SELECT 1 UNION ALL SELECT 2) t LEFT JOIN (SELECT inspect_type, SUM(quantity) AS completedCount, SUM(IF(check_result = 'åæ ¼', quantity, 0)) AS qualifiedCount, SUM(IF(check_result = 'ä¸åæ ¼', quantity, 0)) AS unqualifiedCount FROM quality_inspect WHERE inspect_state = 1 GROUP BY inspect_type) qi ON t.inspectType = qi.inspect_type LEFT JOIN (SELECT 0 AS inspectType, COALESCE((SELECT SUM(inbound_num) FROM procurement_record_storage WHERE type = 1), 0) + COALESCE((SELECT SUM(quantity) FROM quality_unqualified WHERE inspect_type = 0), 0) AS totalCount UNION ALL SELECT 1 AS inspectType, COALESCE((SELECT SUM(inbound_num) FROM procurement_record_storage WHERE type = 2 AND sales_ledger_product_id = 0), 0) AS totalCount UNION ALL SELECT 2 AS inspectType, COALESCE((SELECT SUM(inbound_num) FROM procurement_record_storage WHERE type = 2 AND sales_ledger_product_id != 0), 0) AS totalCount) prs ON t.inspectType = prs.inspectType ORDER BY t.inspectType; </select> <select id="getMonthlyPassRateStatistics" resultType="com.ruoyi.quality.dto.QualityMonthlyPassRateDto"> WITH RECURSIVE months AS (SELECT 1 AS month_num UNION ALL SELECT month_num + 1 FROM months WHERE month_num < 12), types AS (SELECT 0 AS inspectType UNION ALL SELECT 1 UNION ALL SELECT 2), base AS (SELECT m.month_num, t.inspectType FROM months m, types t), qi_data AS (SELECT MONTH(check_time) AS month_num, inspect_type, SUM(quantity) AS completedCount, SUM(CASE WHEN check_result = 'åæ ¼' THEN quantity ELSE 0 END) AS qualifiedCount, SUM(CASE WHEN check_result = 'ä¸åæ ¼' THEN quantity ELSE 0 END) AS unqualifiedCount FROM quality_inspect WHERE YEAR(check_time) = #{year} AND inspect_state = 1 GROUP BY MONTH(check_time), inspect_type), prs_data AS (SELECT month_num, inspectType, SUM(totalCount) AS totalCount FROM (SELECT MONTH(create_time) AS month_num, 0 AS inspectType, inbound_num AS totalCount FROM procurement_record_storage WHERE type = 1 AND YEAR(create_time) = #{year} UNION ALL SELECT MONTH(check_time) AS month_num, 0 AS inspectType, quantity AS totalCount FROM quality_unqualified WHERE inspect_type = 0 AND YEAR(check_time) = #{year} UNION ALL SELECT MONTH(create_time) AS month_num, CASE WHEN sales_ledger_product_id = 0 THEN 1 ELSE 2 END AS inspectType, inbound_num AS totalCount FROM procurement_record_storage WHERE type = 2 AND YEAR(create_time) = #{year}) sub GROUP BY month_num, inspectType) SELECT CASE b.month_num WHEN 1 THEN '䏿' WHEN 2 THEN 'äºæ' WHEN 3 THEN '䏿' WHEN 4 THEN 'åæ' WHEN 5 THEN 'äºæ' WHEN 6 THEN 'å æ' WHEN 7 THEN '䏿' WHEN 8 THEN 'å «æ' WHEN 9 THEN '乿' WHEN 10 THEN 'åæ' WHEN 11 THEN 'å䏿' WHEN 12 THEN 'åäºæ' END AS month, b.inspectType, COALESCE(p.totalCount, 0) AS totalCount, COALESCE(q.completedCount, 0) AS completedCount, COALESCE(q.qualifiedCount, 0) AS qualifiedCount, COALESCE(q.unqualifiedCount, 0) AS unqualifiedCount, CASE WHEN COALESCE(p.totalCount, 0) = 0 THEN 0 ELSE ROUND(COALESCE(q.completedCount, 0) / p.totalCount * 100, 2) END AS completionRate, CASE WHEN COALESCE(q.completedCount, 0) = 0 THEN 0 ELSE ROUND(COALESCE(q.qualifiedCount, 0) / q.completedCount * 100, 2) END AS passRate FROM base b LEFT JOIN qi_data q ON b.month_num = q.month_num AND b.inspectType = q.inspect_type LEFT JOIN prs_data p ON b.month_num = p.month_num AND b.inspectType = p.inspectType ORDER BY b.month_num, b.inspectType </select> <select id="getYearlyPassRateStatistics" resultType="com.ruoyi.quality.dto.QualityPassRateDto"> SELECT t.inspectType, COALESCE(prs.totalCount, 0) AS totalCount, COALESCE(qi.completedCount, 0) AS completedCount, COALESCE(qi.qualifiedCount, 0) AS qualifiedCount, COALESCE(qi.unqualifiedCount, 0) AS unqualifiedCount, CASE WHEN COALESCE(prs.totalCount, 0) = 0 THEN 0 ELSE ROUND(COALESCE(qi.completedCount, 0) / prs.totalCount * 100, 2) END AS completionRate, CASE WHEN COALESCE(qi.completedCount, 0) = 0 THEN 0 ELSE ROUND(COALESCE(qi.qualifiedCount, 0) / qi.completedCount * 100, 2) END AS passRate FROM (SELECT 0 AS inspectType UNION ALL SELECT 1 UNION ALL SELECT 2) t LEFT JOIN (SELECT inspect_type, SUM(quantity) AS completedCount, SUM(CASE WHEN check_result = 'åæ ¼' THEN quantity ELSE 0 END) AS qualifiedCount, SUM(CASE WHEN check_result = 'ä¸åæ ¼' THEN quantity ELSE 0 END) AS unqualifiedCount FROM quality_inspect WHERE YEAR(check_time) = #{year} AND inspect_state = 1 GROUP BY inspect_type) qi ON t.inspectType = qi.inspect_type LEFT JOIN (SELECT 0 AS inspectType, COALESCE((SELECT SUM(inbound_num) FROM procurement_record_storage WHERE type = 1 AND YEAR(create_time) = #{year}), 0) + COALESCE((SELECT SUM(quantity) FROM quality_unqualified WHERE inspect_type = 0 AND YEAR(check_time) = #{year}), 0) AS totalCount UNION ALL SELECT 1 AS inspectType, COALESCE((SELECT SUM(inbound_num) FROM procurement_record_storage WHERE type = 2 AND sales_ledger_product_id = 0 AND YEAR(create_time) = #{year}), 0) AS totalCount UNION ALL SELECT 2 AS inspectType, COALESCE((SELECT SUM(inbound_num) FROM procurement_record_storage WHERE type = 2 AND sales_ledger_product_id != 0 AND YEAR(create_time) = #{year}), 0) AS totalCount) prs ON t.inspectType = prs.inspectType ORDER BY t.inspectType </select> <select id="getMonthlyCompletionDetails" resultType="com.ruoyi.quality.dto.QualityMonthlyDetailDto"> WITH RECURSIVE months AS (SELECT 1 AS month_num UNION ALL SELECT month_num + 1 FROM months WHERE month_num < 12), qi_data AS (SELECT MONTH(check_time) AS month_num, SUM(CASE WHEN inspect_type = 0 THEN quantity ELSE 0 END) AS rawMaterialCount, SUM(CASE WHEN inspect_type = 1 THEN quantity ELSE 0 END) AS processCount, SUM(CASE WHEN inspect_type = 2 THEN quantity ELSE 0 END) AS outgoingCount FROM quality_inspect WHERE YEAR(check_time) = #{year} AND inspect_state = 1 GROUP BY MONTH(check_time)) SELECT CASE m.month_num WHEN 1 THEN '䏿' WHEN 2 THEN 'äºæ' WHEN 3 THEN '䏿' WHEN 4 THEN 'åæ' WHEN 5 THEN 'äºæ' WHEN 6 THEN 'å æ' WHEN 7 THEN '䏿' WHEN 8 THEN 'å «æ' WHEN 9 THEN '乿' WHEN 10 THEN 'åæ' WHEN 11 THEN 'å䏿' WHEN 12 THEN 'åäºæ' END AS month, COALESCE(d.rawMaterialCount, 0) AS rawMaterialCount, COALESCE(d.processCount, 0) AS processCount, COALESCE(d.outgoingCount, 0) AS outgoingCount FROM months m LEFT JOIN qi_data d ON m.month_num = d.month_num ORDER BY m.month_num </select> <select id="getTopParameters" resultType="com.ruoyi.quality.dto.QualityParameterStatDto"> WITH parameter_counts AS (SELECT qip.parameter_item AS name, COUNT(*) AS count FROM quality_inspect_param qip JOIN quality_inspect qi ON qip.inspect_id = qi.id WHERE qi.inspect_type = #{inspectType} GROUP BY qip.parameter_item), total AS (SELECT SUM(count) as total_count FROM parameter_counts), ranked AS (SELECT name, count, ROW_NUMBER() OVER (ORDER BY count DESC) as rn FROM parameter_counts) SELECT name, count, CASE WHEN (SELECT total_count FROM total) = 0 THEN 0 ELSE ROUND(count / (SELECT total_count FROM total) * 100, 2) END as percentage FROM (SELECT name, count, rn FROM ranked WHERE rn <= 4 UNION ALL SELECT 'å ¶ä»' as name, SUM(count) as count, 5 as rn FROM ranked WHERE rn > 4 HAVING count > 0) sub ORDER BY rn </select> </mapper>