فهرست منبع

产品入库统计接口
总生产达成率接口
安全生产天数接口
生产实时监控接口

wangpx 8 ماه پیش
والد
کامیت
38106af68c

+ 68 - 0
src/main/java/cn/com/mes/controller/BigViewMesController.java

@@ -108,6 +108,74 @@ public class BigViewMesController extends BaseController {
         }
     }
 
+    /**
+     * 4. 产品入库统计接口(一周内每天不同产品的数据)
+     * 查询wm_product_recpt表status不为NULL且不为PREPARE的所有数据,recpt_date为入库日期
+     * wm_product_recpt_line表和wm_product_recpt表使用recpt_id关联
+     * wm_product_recpt_line表中的产品item_code,quantity_recived为入库数量和unit_of_measure为入库单位
+     * 传入产品itemCodes,按日期和产品分组统计,返回一周内每天每个产品的入库信息
+     */
+    @ApiOperation(value = "根据产品itemCodes获取产品入库统计", notes = "获取一周内每天不同产品的产品入库统计数据")
+    @GetMapping("/productReceiptStatisticsByItemCodes")
+    public AjaxResult getProductReceiptStatisticsByItemCodes(@RequestParam String itemCodes) {
+        try {
+            List<Map<String, Object>> result = bigViewStatisticsService.getProductReceiptStatisticsByItemCodes(itemCodes);
+            return success().put("data", result);
+        } catch (Exception e) {
+//            logger.error("获取产品入库统计失败", e);
+            return AjaxResult.error("获取产品入库统计失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 2.1 总生产达成率
+     * 查询pro_workorder表中status不为NULL且不为PREPARE且finish_date小于等于request_date
+     */
+    @ApiOperation(value = "获取总生产达成率", notes = "获取总生产达成率统计数据")
+    @GetMapping("/totalProductionAchievementRate")
+    public AjaxResult getTotalProductionAchievementRate() {
+        try {
+            Map<String, Object> result = bigViewStatisticsService.getTotalProductionAchievementRate();
+            return success().put("data", result);
+        } catch (Exception e) {
+//            logger.error("获取总生产达成率统计失败", e);
+            return AjaxResult.error("获取总生产达成率统计失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 2.2 安全生产天数
+     * 传入一个日期,获取当前日期与传入日期相差的天数,返回此天数, 传入的内容为"2025-08-03"
+     */
+    @ApiOperation(value = "获取安全生产天数", notes = "获取安全生产天数统计数据")
+    @GetMapping("/safeProductionDays")
+    public AjaxResult getSafeProductionDays(@RequestParam String endDate) {
+        try {
+            int result = bigViewStatisticsService.getSafeProductionDays(endDate);
+            return success().put("data", result);
+        } catch (Exception e) {
+//            logger.error("获取安全生产天数统计失败", e);
+            return AjaxResult.error("获取安全生产天数统计失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 2.3 生产实时监控
+     * 查询pro_workorder表中status不为NULL且不为PREPARE的所有数据
+     * 包含工单进度,工单状态等数据
+     */
+    @ApiOperation(value = "获取生产实时监控", notes = "获取生产实时监控统计数据")
+    @GetMapping("/productionWorkorderMonitoring")
+    public AjaxResult getProductionWorkorderMonitoring() {
+        try {
+            List<Map<String, Object>> result = bigViewStatisticsService.getProductionWorkorderMonitoring();
+            return success().put("data", result);
+        } catch (Exception e) {
+//            logger.error("获取生产实时监控统计失败", e);
+            return AjaxResult.error("获取生产实时监控统计失败:" + e.getMessage());
+        }
+    }
+
     // TODO
     /**
      * 2. 月预计工单完成总量接口

+ 20 - 0
src/main/java/cn/com/mes/mapper/BigViewMesMapper.java

@@ -108,4 +108,24 @@ public interface BigViewMesMapper {
 
     List<Map<String, Object>> selectWmProductSalseLineList();
 
+    /**
+     * 获取产品入库统计数据
+     * @param itemCodes 产品编码列表
+     * @return 入库统计数据
+     */
+    List<Map<String, Object>> selectProductReceiptStatisticsByItemCodes(@Param("itemCodes") String itemCodes);
+
+    /**
+     * 获取总生产达成率统计数据
+     * @return 总生产达成率统计数据
+     */
+    Map<String, Object> getTotalProductionAchievementRate();
+
+    /**
+     * 获取生产实时监控数据
+     * @return 生产实时监控数据列表
+     */
+    List<Map<String, Object>> getProductionWorkorderMonitoring();
+
+
 }

+ 28 - 0
src/main/java/cn/com/mes/service/IBigViewMesService.java

@@ -100,4 +100,32 @@ public interface IBigViewMesService {
      */
     List<Map<String, Object>> getUnplannedWorkorderStatistics();
 
+    /**
+     * 获取产品入库统计数据(一周内每天不同产品的数据)
+     * 查询wm_product_recpt表中status不为NULL且不为PREPARE的所有数据
+     * 传入产品itemCodes,按日期和产品分组统计,返回一周内每天每个产品的入库信息
+     * @param itemCodes 产品编码列表,逗号分隔
+     * @return 按日期和产品分组的入库统计列表
+     */
+    List<Map<String, Object>> getProductReceiptStatisticsByItemCodes(String itemCodes);
+
+    /**
+     * 获取总生产达成率统计数据
+     * 统计工单完成情况和数量完成情况
+     * @return 总生产达成率统计数据
+     */
+    Map<String, Object> getTotalProductionAchievementRate();
+
+    /**
+     * 获取安全生产天数
+     * @param endDate 结束日期(格式:yyyy-MM-dd)
+     * @return 安全生产天数
+     */
+    int getSafeProductionDays(String endDate);
+
+    /**
+     * 获取生产实时监控数据
+     * @return 生产实时监控数据列表
+     */
+    List<Map<String, Object>> getProductionWorkorderMonitoring();
 }

+ 217 - 55
src/main/java/cn/com/mes/service/impl/BigViewMesServiceImpl.java

@@ -7,19 +7,12 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 import java.time.format.TextStyle;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.time.temporal.ChronoUnit;
+import java.util.*;
 
 /**
  * 大屏统计服务实现类
@@ -35,7 +28,7 @@ public class BigViewMesServiceImpl implements IBigViewMesService {
 
     @Override
     public Map<String, Object> getProductTotal() {
-
+        
         // 直接从mapper查询产品总量
         Map<String, Object> result = bigViewMesMapper.getProductTotal();
 
@@ -61,6 +54,137 @@ public class BigViewMesServiceImpl implements IBigViewMesService {
         return result;
     }
 
+    @Override
+    public Map<String, Object> getTotalProductionAchievementRate() {
+        // 获取生产达成率统计数据
+        Map<String, Object> result = bigViewMesMapper.getTotalProductionAchievementRate();
+        
+        // 添加统计时间
+        result.put("statisticsTime", DateUtil.now());
+        
+        return result;
+    }
+
+    @Override
+    public List<Map<String, Object>> getProductionWorkorderMonitoring() {
+        // 获取生产实时监控数据
+        List<Map<String, Object>> result = bigViewMesMapper.getProductionWorkorderMonitoring();
+        
+        // 为每条记录添加统计时间
+        for (Map<String, Object> record : result) {
+            record.put("statisticsTime", DateUtil.now());
+        }
+        
+        return result;
+    }
+
+    @Override
+    public int getSafeProductionDays(String endDate) {
+        try {
+            // 解析传入的日期
+            LocalDate end = LocalDate.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+            // 获取当前日期
+            LocalDate now = LocalDate.now();
+            
+            // 计算两个日期之间的天数差(绝对值)
+            long days = Math.abs(ChronoUnit.DAYS.between(now, end));
+            
+            return (int) days;
+        } catch (Exception e) {
+            throw new RuntimeException("日期格式错误,请使用yyyy-MM-dd格式", e);
+        }
+    }
+
+    @Override
+    public List<Map<String, Object>> getProductReceiptStatisticsByItemCodes(String itemCodes) {
+        // 获取原始数据
+        List<Map<String, Object>> rawData = bigViewMesMapper.selectProductReceiptStatisticsByItemCodes(itemCodes);
+
+        // 生成过去7天的日期列表
+        Map<String, Map<String, Object>> groupedByDate = new TreeMap<>(Collections.reverseOrder());
+        LocalDate today = LocalDate.now();
+        for (int i = 0; i < 7; i++) {
+            LocalDate date = today.minusDays(i);
+            String dateStr = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+            String dayOfWeek = date.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.CHINESE);
+
+            Map<String, Object> dayData = new HashMap<>();
+            dayData.put("date", dateStr);
+            dayData.put("dayOfWeek", dayOfWeek);
+            dayData.put("products", new HashMap<String, Object>());
+
+            groupedByDate.put(dateStr, dayData);
+        }
+
+        // 按日期和产品编码分组统计数据
+        Map<String, Map<String, List<Map<String, Object>>>> groupedData = new HashMap<>();
+        Set<String> allItemCodes = new HashSet<>();
+        Map<String, String> itemNames = new HashMap<>();
+        Map<String, String> unitOfMeasures = new HashMap<>();
+
+        // 第一次遍历:按日期和产品分组原始数据
+        for (Map<String, Object> record : rawData) {
+            Date receiptDate = (Date) record.get("date");
+            String dateStr = new SimpleDateFormat("yyyy-MM-dd").format(receiptDate);
+            String itemCode = (String) record.get("item_code");
+            String itemName = (String) record.get("item_name");
+            String unitOfMeasure = (String) record.get("unit_of_measure");
+
+            if (itemCode != null && itemName != null) {
+                allItemCodes.add(itemCode);
+                itemNames.put(itemCode, itemName);
+                unitOfMeasures.put(itemCode, unitOfMeasure);
+
+                // 只处理7天内的数据
+                if (groupedByDate.containsKey(dateStr)) {
+                    groupedData.computeIfAbsent(dateStr, k -> new HashMap<>())
+                            .computeIfAbsent(itemCode, k -> new ArrayList<>())
+                            .add(record);
+                }
+            }
+        }
+
+        // 处理分组后的数据
+        for (Map.Entry<String, Map<String, Object>> dateEntry : groupedByDate.entrySet()) {
+            String dateStr = dateEntry.getKey();
+            Map<String, Object> dayData = dateEntry.getValue();
+            Map<String, Object> products = (Map<String, Object>) dayData.get("products");
+
+            // 处理每个产品的数据
+            for (String itemCode : allItemCodes) {
+                // 创建产品统计数据
+                Map<String, Object> productData = new HashMap<>();
+                productData.put("itemCode", itemCode);
+                productData.put("itemName", itemNames.get(itemCode));
+                productData.put("unitOfMeasure", unitOfMeasures.get(itemCode));
+
+                // 获取当天该产品的记录
+                List<Map<String, Object>> productRecords = groupedData
+                        .getOrDefault(dateStr, new HashMap<>())
+                        .getOrDefault(itemCode, new ArrayList<>());
+
+                if (!productRecords.isEmpty()) {
+                    // 统计该产品当天的数据
+                    int receiptCount = productRecords.size();
+                    double totalQuantity = productRecords.stream()
+                            .mapToDouble(r -> ((Number) r.get("quantity_recived")).doubleValue())
+                            .sum();
+
+                    productData.put("receiptCount", receiptCount);
+                    productData.put("totalQuantity", totalQuantity);
+                } else {
+                    // 当天无数据时填充为0
+                    productData.put("receiptCount", 0);
+                    productData.put("totalQuantity", 0.0);
+                }
+
+                products.put(itemCode, productData);
+            }
+        }
+
+        return new ArrayList<>(groupedByDate.values());
+    }
+
     @Override
     public Map<String, Object> getMonthlyWorkorderCompletion() {
         Map<String, Object> result = new HashMap<>();
@@ -262,59 +386,97 @@ public class BigViewMesServiceImpl implements IBigViewMesService {
         // 获取原始数据
         List<Map<String, Object>> rawData = bigViewMesMapper.selectProductionWorkorderStatisticsByProductIds(productIds);
         
-        // 按日期分组
-        Map<String, Map<String, Object>> groupedByDate = new HashMap<>();
-        Set<String> productNames = new HashSet<>();
-        
-        // 第一次遍历:收集所有产品名称并按日期分组
-        for (Map<String, Object> record : rawData) {
-            String date = (String) record.get("statisticsDate");
-            String productName = (String) record.get("productName");
-            productNames.add(productName);
+        // 生成过去7天的日期列表
+        Map<String, Map<String, Object>> groupedByDate = new TreeMap<>(Collections.reverseOrder());
+        LocalDate today = LocalDate.now();
+        for (int i = 0; i < 7; i++) {
+            LocalDate date = today.minusDays(i);
+            String dateStr = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+            String dayOfWeek = date.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.CHINESE);
             
-            // 初始化或获取该日期的数据
-            Map<String, Object> dayData = groupedByDate.computeIfAbsent(date, k -> {
-                Map<String, Object> newDay = new HashMap<>();
-                newDay.put("date", date);
-                // 获取星期几
-                try {
-                    LocalDate localDate = LocalDate.parse(date);
-                    String dayOfWeek = localDate.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.CHINESE);
-                    newDay.put("dayOfWeek", dayOfWeek);
-                } catch (Exception e) {
-                    newDay.put("dayOfWeek", "未知");
-                }
-                return newDay;
-            });
+            Map<String, Object> dayData = new HashMap<>();
+            dayData.put("date", dateStr);
+            dayData.put("dayOfWeek", dayOfWeek);
+            dayData.put("products", new HashMap<String, Object>());
             
-            // 将产品数据添加到日期数据中
-            dayData.put(productName, new HashMap<String, Object>() {{
-                put("workorderCount", record.get("workorderCount"));
-                put("totalQuantity", record.get("totalQuantity"));
-                put("totalProducedQuantity", record.get("totalProducedQuantity"));
-                put("totalIncompleteQuantity", record.get("totalIncompleteQuantity"));
-            }});
+            groupedByDate.put(dateStr, dayData);
         }
         
-        // 确保每天都有所有产品的数据,没有的补零
-        for (Map<String, Object> dayData : groupedByDate.values()) {
-            for (String productName : productNames) {
-                if (!dayData.containsKey(productName)) {
-                    dayData.put(productName, new HashMap<String, Object>() {{
-                        put("workorderCount", 0);
-                        put("totalQuantity", 0);
-                        put("totalProducedQuantity", 0);
-                        put("totalIncompleteQuantity", 0);
-                    }});
+        // 按日期和产品ID分组统计数据
+        Map<String, Map<String, List<Map<String, Object>>>> groupedData = new HashMap<>();
+        Set<String> allProductIds = new HashSet<>();
+        Map<String, String> productNames = new HashMap<>();
+        
+        // 第一次遍历:按日期和产品分组原始数据
+        for (Map<String, Object> record : rawData) {
+            Date createTime = (Date) record.get("date");
+            String dateStr = new SimpleDateFormat("yyyy-MM-dd").format(createTime);
+            String productId = String.valueOf(record.get("product_id"));
+            String productName = (String) record.get("product_name");
+            
+            if (productId != null && productName != null) {
+                allProductIds.add(productId);
+                productNames.put(productId, productName);
+                
+                // 只处理7天内的数据
+                if (groupedByDate.containsKey(dateStr)) {
+                    groupedData.computeIfAbsent(dateStr, k -> new HashMap<>())
+                             .computeIfAbsent(productId, k -> new ArrayList<>())
+                             .add(record);
                 }
             }
         }
         
-        // 转换为列表并按日期排序
-        List<Map<String, Object>> result = new ArrayList<>(groupedByDate.values());
-        result.sort((a, b) -> ((String) a.get("date")).compareTo((String) b.get("date")));
+        // 处理分组后的数据
+        for (Map.Entry<String, Map<String, Object>> dateEntry : groupedByDate.entrySet()) {
+            String dateStr = dateEntry.getKey();
+            Map<String, Object> dayData = dateEntry.getValue();
+            Map<String, Object> products = (Map<String, Object>) dayData.get("products");
+            
+            // 处理每个产品的数据
+            for (String productId : allProductIds) {
+                List<Map<String, Object>> productRecords = groupedData
+                    .getOrDefault(dateStr, new HashMap<>())
+                    .getOrDefault(productId, new ArrayList<>());
+                
+                // 统计该产品当天的数据
+                int workorderCount = productRecords.size();
+                int totalQuantity = productRecords.stream()
+                    .mapToInt(r -> ((Number) r.get("quantity")).intValue())
+                    .sum();
+                int producedQuantity = productRecords.stream()
+                    .mapToInt(r -> r.get("quantity_produced") != null ? 
+                        ((Number) r.get("quantity_produced")).intValue() : 0)
+                    .sum();
+                int scheduledQuantity = productRecords.stream()
+                    .mapToInt(r -> r.get("quantity_scheduled") != null ? 
+                        ((Number) r.get("quantity_scheduled")).intValue() : 0)
+                    .sum();
+                int changedQuantity = productRecords.stream()
+                    .mapToInt(r -> r.get("quantity_changed") != null ? 
+                        ((Number) r.get("quantity_changed")).intValue() : 0)
+                    .sum();
+                
+                // 创建产品统计数据
+                Map<String, Object> productData = new HashMap<>();
+                productData.put("productId", productId);
+                productData.put("productName", productNames.get(productId));
+                productData.put("workorderCount", workorderCount);
+                productData.put("totalQuantity", totalQuantity);
+                productData.put("producedQuantity", producedQuantity);
+                productData.put("scheduledQuantity", scheduledQuantity);
+                productData.put("changedQuantity", changedQuantity);
+                productData.put("incompleteQuantity", totalQuantity - producedQuantity);
+                productData.put("completionRate", totalQuantity > 0 ? 
+                    Math.round(producedQuantity * 100.0 / totalQuantity * 100) / 100.0 : 0.00);
+                productData.put("schedulingRate", totalQuantity > 0 ? 
+                    Math.round(scheduledQuantity * 100.0 / totalQuantity * 100) / 100.0 : 0.00);
+                
+                products.put(productId, productData);
+            }
+        }
         
-        return result;
+        return new ArrayList<>(groupedByDate.values());
     }
     
     @Override

+ 106 - 74
src/main/resources/mapper/mes/BigViewMesMapper.xml

@@ -122,77 +122,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <!-- 根据产品IDs获取生产工单统计(一周内每天不同产品的数据) -->
     <select id="selectProductionWorkorderStatisticsByProductIds" resultType="java.util.Map" parameterType="string">
-        SELECT
-        DATE_FORMAT(d.stat_date, '%Y-%m-%d') as stat_date_str,
-        YEAR(d.stat_date) as stat_year,
-        MONTH(d.stat_date) as stat_month,
-        DAY(d.stat_date) as stat_day,
-        DATE_FORMAT(d.stat_date, '%Y-%m') as month_year_str,
-        DAYOFWEEK(d.stat_date) as day_of_week,
-        CASE DAYOFWEEK(d.stat_date)
-        WHEN 1 THEN '周日'
-        WHEN 2 THEN '周一'
-        WHEN 3 THEN '周二'
-        WHEN 4 THEN '周三'
-        WHEN 5 THEN '周四'
-        WHEN 6 THEN '周五'
-        WHEN 7 THEN '周六'
-        END as day_name,
-        COALESCE(w.product_id, 0) as product_id,
-        COALESCE(w.product_code, '') as product_code,
-        COALESCE(w.product_name, '') as product_name,
-        COALESCE(w.product_spc, '') as product_spc,
-        COALESCE(w.unit_of_measure, '') as unit_of_measure,
-        COALESCE(w.workorder_count, 0) as workorder_count,
-        COALESCE(w.total_quantity, 0) as total_quantity,
-        COALESCE(w.total_produced_quantity, 0) as total_produced_quantity,
-        COALESCE(w.total_scheduled_quantity, 0) as total_scheduled_quantity,
-        COALESCE(w.total_changed_quantity, 0) as total_changed_quantity,
-        COALESCE(w.total_incomplete_quantity, 0) as total_incomplete_quantity,
-        COALESCE(w.completion_rate, 0.00) as completion_rate,
-        COALESCE(w.scheduling_rate, 0.00) as scheduling_rate,
-        w.earliest_request_date,
-        w.latest_request_date,
-        COALESCE(w.all_statuses, '') as all_statuses
-        FROM (
-        SELECT DATE_SUB(CURDATE(), INTERVAL nums.n DAY) AS stat_date
-        FROM (
-        SELECT 0 AS n UNION ALL
-        SELECT 1 UNION ALL
-        SELECT 2 UNION ALL
-        SELECT 3 UNION ALL
-        SELECT 4 UNION ALL
-        SELECT 5 UNION ALL
-        SELECT 6
-        ) nums
-        ) d
-        LEFT JOIN (
-        SELECT
-        DATE(create_time) as work_date,
-        product_id,
-        product_code,
-        product_name,
-        product_spc,
-        unit_of_measure,
-        COUNT(*) as workorder_count,
-        SUM(quantity) as total_quantity,
-        SUM(COALESCE(quantity_produced, 0)) as total_produced_quantity,
-        SUM(COALESCE(quantity_scheduled, 0)) as total_scheduled_quantity,
-        SUM(COALESCE(quantity_changed, 0)) as total_changed_quantity,
-        SUM(quantity - COALESCE(quantity_produced, 0)) as total_incomplete_quantity,
-        CASE
-        WHEN SUM(quantity) > 0
-        THEN ROUND(SUM(COALESCE(quantity_produced, 0)) * 100.0 / SUM(quantity), 2)
-        ELSE 0.00
-        END as completion_rate,
-        CASE
-        WHEN SUM(quantity) > 0
-        THEN ROUND(SUM(COALESCE(quantity_scheduled, 0)) * 100.0 / SUM(quantity), 2)
-        ELSE 0.00
-        END as scheduling_rate,
-        MIN(request_date) as earliest_request_date,
-        MAX(request_date) as latest_request_date,
-        GROUP_CONCAT(DISTINCT status) as all_statuses
+        SELECT 
+            DATE(create_time) as date,
+            product_id,
+            product_name,
+            product_code,
+            quantity,
+            quantity_produced,
+            quantity_scheduled,
+            quantity_changed,
+            status
         FROM pro_workorder
         WHERE status IS NOT NULL
         AND status NOT IN ('PREPARE', 'FINISHED')
@@ -203,9 +142,102 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 #{productId}
             </foreach>
         </if>
-        GROUP BY DATE(create_time), product_id, product_code, product_name, product_spc, unit_of_measure
-        ) w ON d.stat_date = w.work_date
-        ORDER BY d.stat_date DESC, w.product_id ASC
+        ORDER BY create_time DESC
+    </select>
+
+    <!-- 获取生产实时监控数据 -->
+    <select id="getProductionWorkorderMonitoring" resultType="java.util.Map">
+        SELECT 
+            workorder_id as workorderId,
+            workorder_code as workorderCode,
+            workorder_name as workorderName,
+            product_id as productId,
+            product_code as productCode,
+            product_name as productName,
+            product_spc as productSpec,
+            unit_of_measure as unitOfMeasure,
+            status,
+            DATE_FORMAT(create_time, '%m-%d') as createTime,
+            DATE_FORMAT(request_date, '%m-%d') as requestDate,
+            finish_date as finishDate,
+            quantity as totalQuantity,
+            COALESCE(quantity_produced, 0) as producedQuantity,
+            COALESCE(quantity_scheduled, 0) as scheduledQuantity,
+            COALESCE(quantity_changed, 0) as changedQuantity,
+            (quantity - COALESCE(quantity_produced, 0)) as remainingQuantity,
+            CASE 
+                WHEN quantity > 0 THEN ROUND((COALESCE(quantity_produced, 0) * 100.0 / quantity), 2)
+                ELSE 0.00 
+            END as completionRate,
+            CASE 
+                WHEN quantity > 0 THEN ROUND((COALESCE(quantity_scheduled, 0) * 100.0 / quantity), 2)
+                ELSE 0.00 
+            END as schedulingRate,
+            CASE 
+                WHEN status = 'RUNNING' THEN '生产中'
+                WHEN status = 'PAUSED' THEN '已暂停'
+                WHEN status = 'FINISHED' THEN '已完成'
+                ELSE status 
+            END as statusName,
+            CASE
+                WHEN finish_date IS NOT NULL AND finish_date > request_date THEN '已超期'
+                WHEN finish_date IS NULL AND CURDATE() > request_date THEN '已超期'
+                ELSE '正常'
+            END as scheduleStatus
+        FROM pro_workorder 
+        WHERE status IS NOT NULL
+        AND status != 'PREPARE'
+        ORDER BY create_time DESC
+    </select>
+
+    <!-- 获取总生产达成率统计数据 -->
+    <select id="getTotalProductionAchievementRate" resultType="java.util.Map">
+        <![CDATA[
+        SELECT 
+            COUNT(*) as totalWorkorders,
+            COUNT(CASE WHEN status = 'FINISHED' AND finish_date <= request_date THEN 1 END) as achievedWorkorders,
+            CASE 
+                WHEN COUNT(*) > 0 
+                THEN ROUND(COUNT(CASE WHEN status = 'FINISHED' AND finish_date <= request_date THEN 1 END) * 100.0 / COUNT(*), 2)
+                ELSE 0.00 
+            END as achievementRate,
+            SUM(quantity) as totalQuantity,
+            SUM(CASE WHEN status = 'FINISHED' AND finish_date <= request_date THEN quantity ELSE 0 END) as achievedQuantity,
+            CASE 
+                WHEN SUM(quantity) > 0 
+                THEN ROUND(SUM(CASE WHEN status = 'FINISHED' AND finish_date <= request_date THEN quantity ELSE 0 END) * 100.0 / SUM(quantity), 2)
+                ELSE 0.00 
+            END as quantityAchievementRate
+        FROM pro_workorder
+        WHERE status IS NOT NULL
+        AND status != 'PREPARE'
+        ]]>
+    </select>
+
+    <!-- 获取产品入库统计数据 -->
+    <select id="selectProductReceiptStatisticsByItemCodes" resultType="java.util.Map">
+        SELECT
+        DATE(r.recpt_date) as date,
+        l.item_code,
+        l.item_name,
+        l.unit_of_measure,
+        l.quantity_recived,
+        r.status,
+        r.recpt_code,
+        r.warehouse_code,
+        r.warehouse_name
+        FROM wm_product_recpt r
+        JOIN wm_product_recpt_line l ON r.recpt_id = l.recpt_id
+        WHERE r.status IS NOT NULL
+        AND r.status != 'PREPARE'
+        AND r.recpt_date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
+        <if test="itemCodes != null and itemCodes != ''">
+            AND l.item_code IN
+            <foreach collection="itemCodes.split(',')" item="itemCode" open="(" separator="," close=")">
+                #{itemCode}
+            </foreach>
+        </if>
+        ORDER BY r.recpt_date DESC
     </select>
 
     <!-- TODO -->