From bee04140fad1310e3d2e66ccbeb6f8b649bff6e8 Mon Sep 17 00:00:00 2001
From: maven <2163098428@qq.com>
Date: 星期三, 28 一月 2026 17:54:23 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_New' into dev_New

---
 src/main/java/com/ruoyi/home/mapper/HomeMapper.java                                   |   20 +
 src/main/java/com/ruoyi/safe/pojo/SafeAccident.java                                   |  106 ++++++
 src/main/java/com/ruoyi/home/controller/HomeController.java                           |   37 ++
 src/main/java/com/ruoyi/safe/service/SafeContingencyPlanService.java                  |   19 +
 src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java                                |    2 
 src/main/java/com/ruoyi/safe/pojo/SafeContingencyPlan.java                            |   87 +++++
 src/main/java/com/ruoyi/safe/service/SafeAccidentService.java                         |   19 +
 src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java                       |   13 
 src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java              |    4 
 src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java                        |  204 +++++++++++
 src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java         |    9 
 src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java                 |   11 
 src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java               |    4 
 src/main/resources/mapper/sales/SalesLedgerProductMapper.xml                          |   46 ++
 src/main/java/com/ruoyi/safe/controller/SafeContingencyPlanController.java            |   56 +++
 doc/20260128_add_unique_to_staff_on_job.sql                                           |    1 
 src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java                |    6 
 src/main/java/com/ruoyi/safe/service/impl/SafeContingencyPlanServiceImpl.java         |   30 +
 src/main/resources/mapper/home/HomeMapper.xml                                         |   16 
 src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java             |   17 
 src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java           |    4 
 src/main/java/com/ruoyi/safe/mapper/SafeContingencyPlanMapper.java                    |   22 +
 src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java |    4 
 src/main/resources/mapper/safe/SafeAccidentMapper.xml                                 |   48 ++
 src/main/resources/mapper/stock/StockInventoryMapper.xml                              |   39 ++
 src/main/java/com/ruoyi/safe/service/impl/SafeHazardRecordServiceImpl.java            |    5 
 src/main/java/com/ruoyi/quality/controller/QualityInspectController.java              |    2 
 src/main/java/com/ruoyi/safe/service/impl/SafeAccidentServiceImpl.java                |   30 +
 src/main/java/com/ruoyi/safe/controller/SafeCertificationController.java              |    2 
 src/main/java/com/ruoyi/safe/mapper/SafeAccidentMapper.java                           |   22 +
 src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java                        |    7 
 src/main/java/com/ruoyi/home/service/HomeService.java                                 |   13 
 src/main/resources/mapper/safe/SafeContingencyPlanMapper.xml                          |   38 ++
 src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java                    |    7 
 src/main/java/com/ruoyi/safe/controller/SafeAccidentController.java                   |   55 +++
 35 files changed, 975 insertions(+), 30 deletions(-)

diff --git a/doc/20260128_add_unique_to_staff_on_job.sql b/doc/20260128_add_unique_to_staff_on_job.sql
new file mode 100644
index 0000000..16b2221
--- /dev/null
+++ b/doc/20260128_add_unique_to_staff_on_job.sql
@@ -0,0 +1 @@
+ALTER TABLE staff_on_job ADD unique (staff_no);
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
index 447ff45..4e4749e 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
@@ -358,7 +358,9 @@
             case 6:
                 return "鎶ヤ环瀹℃壒";
             case 7:
-                return "鍑哄簱瀹℃壒";
+                return "鍙戣揣瀹℃壒";
+            case 8:
+                return "鍗遍櫓浣滀笟瀹℃壒";
         }
         return null;
     }
diff --git a/src/main/java/com/ruoyi/home/controller/HomeController.java b/src/main/java/com/ruoyi/home/controller/HomeController.java
index 9cbb122..82dc3b3 100644
--- a/src/main/java/com/ruoyi/home/controller/HomeController.java
+++ b/src/main/java/com/ruoyi/home/controller/HomeController.java
@@ -7,6 +7,7 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.home.dto.*;
 import com.ruoyi.home.service.HomeService;
+import com.ruoyi.dto.MapDto;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -96,6 +97,41 @@
         return AjaxResult.success(list);
     }
 
+    @GetMapping("/productSalesAnalysis")
+    @ApiOperation("鍚勪骇鍝侀攢鍞噾棰濆垎鏋�")
+    public AjaxResult productSalesAnalysis() {
+        List<MapDto> list = homeService.productSalesAnalysis();
+        return AjaxResult.success(list);
+    }
+
+    @GetMapping("/rawMaterialPurchaseAmountRatio")
+    @ApiOperation("鍘熸潗鏂欓噰璐噾棰濆崰姣�")
+    public AjaxResult rawMaterialPurchaseAmountRatio(){
+        List<MapDto> list = homeService.rawMaterialPurchaseAmountRatio();
+        return AjaxResult.success(list);
+    }
+
+    @GetMapping("/salesPurchaseStorageProductCount")
+    @ApiOperation("閿�鍞�-閲囪喘-鍌ㄥ瓨浜у搧鏁�")
+    public AjaxResult salesPurchaseStorageProductCount(){
+        List<MapDto> list = homeService.salesPurchaseStorageProductCount();
+        return AjaxResult.success(list);
+    }
+
+    @GetMapping("/productInOutAnalysis")
+    @ApiOperation("浜у搧鍑哄叆搴撳垎鏋�")
+    public AjaxResult productInOutAnalysis(@RequestParam(value = "type", defaultValue = "1") Integer type){
+        List<Map<String, Object>> result = homeService.productInOutAnalysis(type);
+        return AjaxResult.success(result);
+    }
+
+    @GetMapping("/productTurnoverDays")
+    @ApiOperation("浜у搧鍛ㄨ浆澶╂暟")
+    public AjaxResult productTurnoverDays(){
+        List<MapDto> list = homeService.productTurnoverDays();
+        return AjaxResult.success(list);
+    }
+
     /********************************************************钀ラ攢閲囪喘绫�**************************************************/
     @GetMapping("/business")
     @Log(title = "閿�鍞�-閲囪喘-搴撳瓨鏁版嵁", businessType = BusinessType.OTHER)
@@ -130,6 +166,7 @@
     }
 
 
+    
     /********************************************************璐ㄩ噺绫�*****************************************************/
     @GetMapping("/qualityStatistics")
     @Log(title = "璐ㄩ噺鍒嗘瀽", businessType = BusinessType.OTHER)
diff --git a/src/main/java/com/ruoyi/home/mapper/HomeMapper.java b/src/main/java/com/ruoyi/home/mapper/HomeMapper.java
new file mode 100644
index 0000000..1bf30e4
--- /dev/null
+++ b/src/main/java/com/ruoyi/home/mapper/HomeMapper.java
@@ -0,0 +1,20 @@
+package com.ruoyi.home.mapper;
+
+import com.ruoyi.dto.MapDto;
+import org.apache.ibatis.annotations.Mapper;
+import java.util.List;
+
+/**
+ * 棣栭〉缁熻 Mapper
+ * 
+ * @author antigravity
+ */
+@Mapper
+public interface HomeMapper {
+    /**
+     * 鏌ヨ浜у搧鍛ㄨ浆澶╂暟
+     * 
+     * @return 浜у搧鍛ㄨ浆澶╂暟鍒楄〃
+     */
+    List<MapDto> productTurnoverDays();
+}
diff --git a/src/main/java/com/ruoyi/home/service/HomeService.java b/src/main/java/com/ruoyi/home/service/HomeService.java
index db43d86..67cd4f3 100644
--- a/src/main/java/com/ruoyi/home/service/HomeService.java
+++ b/src/main/java/com/ruoyi/home/service/HomeService.java
@@ -1,9 +1,8 @@
 package com.ruoyi.home.service;
 
 import com.ruoyi.approve.pojo.ApproveProcess;
+import com.ruoyi.dto.MapDto;
 import com.ruoyi.home.dto.*;
-import com.ruoyi.production.dto.ProductOrderDto;
-import com.ruoyi.production.dto.ProductWorkOrderDto;
 
 import java.text.ParseException;
 import java.util.List;
@@ -45,4 +44,14 @@
     ProductCategoryDistributionDto productCategoryDistribution();
 
     List<CustomerContributionRankingDto> customerContributionRanking(Integer type);
+
+    List<MapDto> productSalesAnalysis();
+
+    List<MapDto> rawMaterialPurchaseAmountRatio();
+
+    List<MapDto> salesPurchaseStorageProductCount();
+
+    List<Map<String, Object>> productInOutAnalysis(Integer type);
+
+    List<MapDto> productTurnoverDays();
 }
diff --git a/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java b/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
index b66def3..137c5fb 100644
--- a/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
+++ b/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -2,8 +2,8 @@
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.home.mapper.HomeMapper;
 import com.ruoyi.approve.mapper.ApproveProcessMapper;
 import com.ruoyi.approve.pojo.ApproveProcess;
 import com.ruoyi.basic.mapper.CustomerMapper;
@@ -12,7 +12,6 @@
 import com.ruoyi.basic.mapper.SupplierManageMapper;
 import com.ruoyi.basic.pojo.Customer;
 import com.ruoyi.basic.pojo.Product;
-import com.ruoyi.basic.pojo.ProductModel;
 import com.ruoyi.basic.pojo.SupplierManage;
 import com.ruoyi.collaborativeApproval.mapper.NoticeMapper;
 import com.ruoyi.collaborativeApproval.pojo.Notice;
@@ -86,6 +85,9 @@
     private SalesLedgerProductMapper salesLedgerProductMapper;
 
     @Autowired
+    private StockInventoryMapper stockInventoryMapper;
+
+    @Autowired
     private ProcurementRecordMapper procurementRecordStorageMapper;
 
     @Autowired
@@ -125,8 +127,9 @@
     private SysUserMapper sysUserMapper;
     @Autowired
     private SysUserDeptMapper sysUserDeptMapper;
+
     @Autowired
-    private StockInventoryMapper stockInventoryMapper;
+    private HomeMapper homeMapper;
 
     @Override
     public HomeBusinessDto business() {
@@ -900,4 +903,199 @@
         }
         return result;
     }
+
+    @Override
+    public List<MapDto> productSalesAnalysis() {
+        // 鑾峰彇鎵�鏈変骇鍝佸ぇ绫荤殑閿�鍞
+        List<Map<String, Object>> analysisResults = salesLedgerProductMapper.selectProductSalesAnalysis();
+        if (CollectionUtils.isEmpty(analysisResults)) {
+            return new ArrayList<>();
+        }
+
+        // 璁$畻鎬婚攢鍞
+        BigDecimal totalSalesAmount = analysisResults.stream()
+                .map(r -> (BigDecimal) r.get("value"))
+                .filter(Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+        return analysisResults.stream()
+                .map(result -> {
+                    MapDto mapDto = new MapDto();
+                    String name = (String) result.get("name");
+                    BigDecimal value = (BigDecimal) result.get("value");
+
+                    mapDto.setName(name);
+                    mapDto.setValue(value != null ? value.setScale(2, RoundingMode.HALF_UP).toString() : "0.00");
+
+                    if (totalSalesAmount.compareTo(BigDecimal.ZERO) == 0 || value == null) {
+                        mapDto.setRate("0.00");
+                    } else {
+                        String rate = value.divide(totalSalesAmount, 4, RoundingMode.HALF_UP)
+                                .multiply(new BigDecimal("100"))
+                                .setScale(2, RoundingMode.HALF_UP)
+                                .toString();
+                        mapDto.setRate(rate);
+                    }
+                    return mapDto;
+                })
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public List<MapDto> rawMaterialPurchaseAmountRatio() {
+        // 鑾峰彇鎵�鏈夊師鏉愭枡鐨勯噰璐
+        List<Map<String, Object>> analysisResults = salesLedgerProductMapper.selectRawMaterialPurchaseAnalysis();
+        if (CollectionUtils.isEmpty(analysisResults)) {
+            return new ArrayList<>();
+        }
+
+        // 璁$畻鎬婚噰璐
+        BigDecimal totalPurchaseAmount = analysisResults.stream()
+                .map(r -> (BigDecimal) r.get("value"))
+                .filter(Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+        return analysisResults.stream()
+                .map(result -> {
+                    MapDto mapDto = new MapDto();
+                    String name = (String) result.get("name");
+                    BigDecimal value = (BigDecimal) result.get("value");
+
+                    mapDto.setName(name);
+                    mapDto.setValue(value != null ? value.setScale(2, RoundingMode.HALF_UP).toString() : "0.00");
+
+                    if (totalPurchaseAmount.compareTo(BigDecimal.ZERO) == 0 || value == null) {
+                        mapDto.setRate("0.00");
+                    } else {
+                        String rate = value.divide(totalPurchaseAmount, 4, RoundingMode.HALF_UP)
+                                .multiply(new BigDecimal("100"))
+                                .setScale(2, RoundingMode.HALF_UP)
+                                .toString();
+                        mapDto.setRate(rate);
+                    }
+                    return mapDto;
+                })
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public List<MapDto> salesPurchaseStorageProductCount() {
+        LocalDate now = LocalDate.now();
+        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+        String currentMonthStart = now.with(TemporalAdjusters.firstDayOfMonth()).format(dtf);
+        String currentMonthNow = now.format(dtf);
+
+        LocalDate lastMonth = now.minusMonths(1);
+        String lastMonthStart = lastMonth.with(TemporalAdjusters.firstDayOfMonth()).format(dtf);
+        String lastMonthEnd = lastMonth.with(TemporalAdjusters.lastDayOfMonth()).format(dtf);
+
+        // 閿�鍞�
+        int currentSales = salesLedgerProductMapper.selectProductCountByTypeAndDate(1, currentMonthStart, currentMonthNow);
+        int lastSales = salesLedgerProductMapper.selectProductCountByTypeAndDate(1, lastMonthStart, lastMonthEnd);
+
+        // 閲囪喘
+        int currentPurchase = salesLedgerProductMapper.selectProductCountByTypeAndDate(2, currentMonthStart, currentMonthNow);
+        int lastPurchase = salesLedgerProductMapper.selectProductCountByTypeAndDate(2, lastMonthStart, lastMonthEnd);
+
+        // 鍌ㄥ瓨
+        int currentStorage = stockInventoryMapper.selectStorageProductCountByDate(currentMonthStart, currentMonthNow);
+        int lastStorage = stockInventoryMapper.selectStorageProductCountByDate(lastMonthStart, lastMonthEnd);
+
+        List<MapDto> list = new ArrayList<>();
+        list.add(createMapDto("閿�鍞骇鍝佹暟", currentSales, lastSales));
+        list.add(createMapDto("閲囪喘浜у搧鏁�", currentPurchase, lastPurchase));
+        list.add(createMapDto("鍌ㄥ瓨浜у搧鏁�", currentStorage, lastStorage));
+
+        return list;
+    }
+
+    private MapDto createMapDto(String name, int current, int last) {
+        MapDto dto = new MapDto();
+        dto.setName(name);
+        dto.setValue(String.valueOf(current));
+
+        if (last == 0) {
+            dto.setRate(current > 0 ? "100.00" : "0.00");
+        } else {
+            BigDecimal curDec = new BigDecimal(current);
+            BigDecimal lastDec = new BigDecimal(last);
+            // 澧為暱鐜�
+            String rate = curDec.subtract(lastDec)
+                    .divide(lastDec, 4, RoundingMode.HALF_UP)
+                    .multiply(new BigDecimal("100"))
+                    .setScale(2, RoundingMode.HALF_UP)
+                    .toString();
+            dto.setRate(rate);
+        }
+        return dto;
+    }
+
+    @Override
+    public List<Map<String, Object>> productInOutAnalysis(Integer type) {
+        String targetName;
+        if (type == 1) {
+            targetName = "鍘熸潗鏂�";
+        } else if (type == 2) {
+            targetName = "鎴愬搧";
+        } else if (type == 3) {
+            targetName = "鍗婃垚鍝�";
+        } else {
+            return new ArrayList<>();
+        }
+
+        LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(Product::getProductName, targetName).isNull(Product::getParentId);
+        Product rootCategory = productMapper.selectOne(queryWrapper);
+
+        if (rootCategory == null) {
+            log.warn("鏈壘鍒板悕绉颁负 {} 鐨勯《绾т骇鍝佸垎绫�", targetName);
+            return new ArrayList<>();
+        }
+        Long rootCategoryId = rootCategory.getId();
+
+        LocalDate now = LocalDate.now();
+        DateTimeFormatter displayDtf = DateTimeFormatter.ofPattern("M/d");
+
+        String startDate = now.minusDays(6).toString();
+        String endDate = now.toString();
+
+        List<Map<String, Object>> inCounts = stockInventoryMapper.selectDailyStockInCounts(rootCategoryId, startDate, endDate + " 23:59:59");
+
+        List<Map<String, Object>> outCounts = stockInventoryMapper.selectDailyStockOutCounts(rootCategoryId, startDate, endDate + " 23:59:59");
+
+        Map<LocalDate, BigDecimal> inMap = inCounts.stream()
+                .collect(Collectors.toMap(
+                        m -> ((java.sql.Date) m.get("date")).toLocalDate(),
+                        m -> (BigDecimal) m.get("count"),
+                        BigDecimal::add
+                ));
+
+        Map<LocalDate, BigDecimal> outMap = outCounts.stream()
+                .collect(Collectors.toMap(
+                        m -> ((java.sql.Date) m.get("date")).toLocalDate(),
+                        m -> (BigDecimal) m.get("count"),
+                        BigDecimal::add
+                ));
+
+        List<Map<String, Object>> result = new ArrayList<>();
+
+        for (int i = 6; i >= 0; i--) {
+            LocalDate date = now.minusDays(i);
+
+            Map<String, Object> dataPoint = new LinkedHashMap<>();
+            dataPoint.put("date", date.format(displayDtf)); // 1/23
+            dataPoint.put("inCount", inMap.getOrDefault(date, BigDecimal.ZERO));
+            dataPoint.put("outCount", outMap.getOrDefault(date, BigDecimal.ZERO));
+
+            result.add(dataPoint);
+        }
+
+        return result;
+    }
+
+    @Override
+    public List<MapDto> productTurnoverDays() {
+        return homeMapper.productTurnoverDays();
+    }
 }
diff --git a/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java b/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
index 3031652..9d87223 100644
--- a/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
+++ b/src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
@@ -7,10 +7,13 @@
 import com.ruoyi.stock.dto.StockInventoryDto;
 import com.ruoyi.stock.dto.StockUninventoryDto;
 import com.ruoyi.stock.pojo.StockInRecord;
+import com.ruoyi.stock.pojo.StockOutRecord;
 import com.ruoyi.stock.service.StockInRecordService;
 import com.ruoyi.stock.service.StockInventoryService;
+import com.ruoyi.stock.service.StockOutRecordService;
 import com.ruoyi.stock.service.StockUninventoryService;
 import com.ruoyi.stock.service.impl.StockInRecordServiceImpl;
+import com.ruoyi.stock.service.impl.StockOutRecordServiceImpl;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Component;
 
@@ -27,6 +30,7 @@
     private final StockUninventoryService stockUninventoryService;
     private final StockInventoryService stockInventoryService;
     private final StockInRecordService stockInRecordService;
+    private final StockOutRecordService stockOutRecordService;
 
     /**
      * 涓嶅悎鏍煎叆搴�
@@ -93,11 +97,18 @@
     }
 
     //涓嶅悎鏍煎簱瀛樺垹闄�
-    public void deleteStockRecord(Long recordId, String recordType) {
+    public void deleteStockInRecord(Long recordId, String recordType) {
         StockInRecord one = stockInRecordService.getOne(new QueryWrapper<StockInRecord>()
                 .lambda().eq(StockInRecord::getRecordId, recordId)
                 .eq(StockInRecord::getRecordType, recordType));
 
         stockInRecordService.batchDelete(Collections.singletonList(one.getId()));
     }
+    public void deleteStockOutRecord(Long recordId, String recordType) {
+        StockOutRecord one = stockOutRecordService.getOne(new QueryWrapper<StockOutRecord>()
+                .lambda().eq(StockOutRecord::getRecordId, recordId)
+                .eq(StockOutRecord::getRecordType, recordType));
+
+        stockOutRecordService.batchDelete(Collections.singletonList(one.getId()));
+    }
 }
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
index 8be62c1..553e0d0 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -287,9 +287,9 @@
         productionProductInputMapper.delete(new LambdaQueryWrapper<ProductionProductInput>()
                 .eq(ProductionProductInput::getProductMainId, productionProductMain.getId()));
         //鍒犻櫎鎶ュ簾鐨勫叆搴撹褰�
-        stockUtils.deleteStockRecord(productionProductMain.getId(), StockUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode());
+        stockUtils.deleteStockInRecord(productionProductMain.getId(), StockUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode());
         //鍒犻櫎鎶曞叆瀵瑰簲鐨勫嚭搴撹褰�
-        stockUtils.deleteStockRecord(productionProductMain.getId(), StockQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode());
+        stockUtils.deleteStockOutRecord(productionProductMain.getId(), StockQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode());
         // 鍒犻櫎涓昏〃
         productionProductMainMapper.deleteById(productionProductMain.getId());
         return true;
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java b/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java
index 7dfae1f..3348a8e 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java
@@ -74,7 +74,7 @@
         .in(QualityInspectFile::getInspectId,ids));
         //鍒犻櫎鍏ュ簱璁板綍
         for (Integer id : ids) {
-            stockUtils.deleteStockRecord(Long.valueOf(id), StockQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode());
+            stockUtils.deleteStockInRecord(Long.valueOf(id), StockQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode());
         }
         //鍒犻櫎妫�楠屽崟
         return AjaxResult.success(qualityInspectService.removeBatchByIds(ids));
diff --git a/src/main/java/com/ruoyi/safe/controller/SafeAccidentController.java b/src/main/java/com/ruoyi/safe/controller/SafeAccidentController.java
new file mode 100644
index 0000000..615514a
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/controller/SafeAccidentController.java
@@ -0,0 +1,55 @@
+package com.ruoyi.safe.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.safe.pojo.SafeAccident;
+import com.ruoyi.safe.pojo.SafeContingencyPlan;
+import com.ruoyi.safe.service.SafeAccidentService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--浜嬫晠涓婃姤璁板綍 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-28 02:40:31
+ */
+@RestController
+@RequestMapping("/safeAccident")
+@Api(tags = "瀹夊叏鐢熶骇--浜嬫晠涓婃姤璁板綍")
+public class SafeAccidentController {
+
+    @Autowired
+    private SafeAccidentService safeAccidentService;
+
+    @GetMapping("/page")
+    @ApiOperation("鍒嗛〉鏌ヨ")
+    public R page(Page page, SafeAccident safeAccident) {
+        return R.ok(safeAccidentService.pageSafeAccident(page, safeAccident));
+    }
+
+    @ApiOperation("鏂板浜嬫晠涓婃姤璁板綍")
+    @PostMapping()
+    public R add(@RequestBody SafeAccident safeAccident) {
+        return R.ok(safeAccidentService.save(safeAccident));
+    }
+
+    @ApiOperation("淇敼浜嬫晠涓婃姤璁板綍")
+    @PutMapping ()
+    public R update(@RequestBody  SafeAccident safeAccident) {
+        return R.ok(safeAccidentService.updateById(safeAccident));
+    }
+
+    @ApiOperation("鍒犻櫎浜嬫晠涓婃姤璁板綍")
+    @DeleteMapping("/{ids}")
+    public R delSafeCertification(@RequestBody List<Integer> ids) {
+        return R.ok(safeAccidentService.removeBatchByIds(ids));
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/safe/controller/SafeCertificationController.java b/src/main/java/com/ruoyi/safe/controller/SafeCertificationController.java
index 898b9d2..7e13eb8 100644
--- a/src/main/java/com/ruoyi/safe/controller/SafeCertificationController.java
+++ b/src/main/java/com/ruoyi/safe/controller/SafeCertificationController.java
@@ -43,11 +43,13 @@
     public R add(@RequestBody SafeCertification safeCertification) {
         return R.ok(safeCertificationService.save(safeCertification));
     }
+
     @ApiOperation("淇敼瀹夊叏瑙勭▼涓庤祫璐ㄧ鐞�")
     @PutMapping ()
     public R update(@RequestBody  SafeCertification safeCertification) {
         return R.ok(safeCertificationService.updateById(safeCertification));
     }
+
     @ApiOperation("鍒犻櫎瀹夊叏瑙勭▼涓庤祫璐ㄧ鐞�")
     @DeleteMapping("/{ids}")
     public R delSafeCertification(@RequestBody List<Integer> ids) {
diff --git a/src/main/java/com/ruoyi/safe/controller/SafeContingencyPlanController.java b/src/main/java/com/ruoyi/safe/controller/SafeContingencyPlanController.java
new file mode 100644
index 0000000..33d32bd
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/controller/SafeContingencyPlanController.java
@@ -0,0 +1,56 @@
+package com.ruoyi.safe.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.safe.pojo.SafeCertification;
+import com.ruoyi.safe.pojo.SafeContingencyPlan;
+import com.ruoyi.safe.service.SafeCertificationService;
+import com.ruoyi.safe.service.SafeContingencyPlanService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--搴旀�ラ妗堟煡闃� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-28 02:07:29
+ */
+@RestController
+@RequestMapping("/safeContingencyPlan")
+@Api(tags = "瀹夊叏鐢熶骇--搴旀�ラ妗堟煡闃�")
+public class SafeContingencyPlanController {
+
+    @Autowired
+    private SafeContingencyPlanService safeContingencyPlanService;
+
+    @GetMapping("/page")
+    @ApiOperation("鍒嗛〉鏌ヨ")
+    public R page(Page page, SafeContingencyPlan safeContingencyPlan) {
+        return R.ok(safeContingencyPlanService.pageSafeContingencyPlan(page, safeContingencyPlan));
+    }
+
+    @ApiOperation("鏂板搴旀�ラ妗堟煡闃�")
+    @PostMapping()
+    public R add(@RequestBody SafeContingencyPlan safeContingencyPlan) {
+        return R.ok(safeContingencyPlanService.save(safeContingencyPlan));
+    }
+
+    @ApiOperation("淇敼搴旀�ラ妗堟煡闃�")
+    @PutMapping ()
+    public R update(@RequestBody  SafeContingencyPlan safeContingencyPlan) {
+        return R.ok(safeContingencyPlanService.updateById(safeContingencyPlan));
+    }
+
+    @ApiOperation("鍒犻櫎搴旀�ラ妗堟煡闃�")
+    @DeleteMapping("/{ids}")
+    public R delSafeCertification(@RequestBody List<Integer> ids) {
+        return R.ok(safeContingencyPlanService.removeBatchByIds(ids));
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/safe/mapper/SafeAccidentMapper.java b/src/main/java/com/ruoyi/safe/mapper/SafeAccidentMapper.java
new file mode 100644
index 0000000..4309dc8
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/mapper/SafeAccidentMapper.java
@@ -0,0 +1,22 @@
+package com.ruoyi.safe.mapper;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.safe.pojo.SafeAccident;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--浜嬫晠涓婃姤璁板綍 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-28 02:40:31
+ */
+@Mapper
+public interface SafeAccidentMapper extends BaseMapper<SafeAccident> {
+
+    IPage<SafeAccident> pageSafeAccident(Page page, @Param("c") SafeAccident safeAccident);
+}
diff --git a/src/main/java/com/ruoyi/safe/mapper/SafeContingencyPlanMapper.java b/src/main/java/com/ruoyi/safe/mapper/SafeContingencyPlanMapper.java
new file mode 100644
index 0000000..a41b347
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/mapper/SafeContingencyPlanMapper.java
@@ -0,0 +1,22 @@
+package com.ruoyi.safe.mapper;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.safe.pojo.SafeContingencyPlan;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--搴旀�ラ妗堟煡闃� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-28 02:07:29
+ */
+@Mapper
+public interface SafeContingencyPlanMapper extends BaseMapper<SafeContingencyPlan> {
+
+    IPage<SafeContingencyPlan> pageSafeContingencyPlan(Page page, @Param("c") SafeContingencyPlan safeContingencyPlan);
+}
diff --git a/src/main/java/com/ruoyi/safe/pojo/SafeAccident.java b/src/main/java/com/ruoyi/safe/pojo/SafeAccident.java
new file mode 100644
index 0000000..8bbc898
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/pojo/SafeAccident.java
@@ -0,0 +1,106 @@
+package com.ruoyi.safe.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.format.annotation.DateTimeFormat;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--浜嬫晠涓婃姤璁板綍
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-28 02:40:31
+ */
+@Getter
+@Setter
+@TableName("safe_accident")
+@ApiModel(value = "SafeAccident瀵硅薄", description = "瀹夊叏鐢熶骇--浜嬫晠涓婃姤璁板綍")
+public class SafeAccident implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty("浜嬫晠缂栧彿")
+    private String accidentCode;
+
+    @ApiModelProperty("浜嬫晠鍚嶇О")
+    private String accidentName;
+
+    @ApiModelProperty("浜嬫晠绫诲瀷")
+    private String accidentType;
+
+    @ApiModelProperty("浜嬫晠鍙戠敓鏃堕棿")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime happenTime;
+
+    @ApiModelProperty("浜嬫晠鍙戠敓浣嶇疆")
+    private String happenLocation;
+
+    @ApiModelProperty("浜嬫晠绛夌骇")
+    private String accidentGrade;
+
+    @ApiModelProperty("浜嬫晠鐩存帴鍘熷洜")
+    private String accidentCause;
+
+    @ApiModelProperty("浜嬫晠鏍规湰鍘熷洜")
+    private String rootCause;
+
+    @ApiModelProperty("浜哄憳鎹熷け鎯呭喌")
+    private String personLoss;
+
+    @ApiModelProperty("鐩存帴璐骇鎹熷け锛堝厓锛�	")
+    private BigDecimal assetLoss;
+
+    @ApiModelProperty("鐢熶骇褰卞搷鎯呭喌")
+    private String productionLoss;
+
+    @ApiModelProperty("鐜板満搴旀�ュ缃帾鏂�")
+    private String handleMeasures;
+
+    @ApiModelProperty("浜嬫晠璐d换浜�")
+    private String responsiblePerson;
+
+    @ApiModelProperty("澶囨敞")
+    private String remark;
+
+    @ApiModelProperty("涓婃姤鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("涓婃姤浜篿d")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @ApiModelProperty("涓婃姤浜�")
+    @TableField(exist = false)
+    private String createUserName;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Integer tenantId;
+}
diff --git a/src/main/java/com/ruoyi/safe/pojo/SafeContingencyPlan.java b/src/main/java/com/ruoyi/safe/pojo/SafeContingencyPlan.java
new file mode 100644
index 0000000..2cad42f
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/pojo/SafeContingencyPlan.java
@@ -0,0 +1,87 @@
+package com.ruoyi.safe.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.format.annotation.DateTimeFormat;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--搴旀�ラ妗堟煡闃�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-28 02:07:29
+ */
+@Getter
+@Setter
+@TableName("safe_contingency_plan")
+@ApiModel(value = "SafeContingencyPlan瀵硅薄", description = "瀹夊叏鐢熶骇--搴旀�ラ妗堟煡闃�")
+public class SafeContingencyPlan implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty("搴旀�ラ妗堢紪鐮�")
+    private String planCode;
+
+    @ApiModelProperty("搴旀�ラ妗堝悕绉�")
+    private String planName;
+
+    @ApiModelProperty("棰勬绫诲瀷")
+    private String planType;
+
+    @ApiModelProperty("閫傜敤鑼冨洿")
+    private String applyScope;
+
+    @ApiModelProperty("鏍稿績璐d换浜�")
+    private Integer coreResponsorUserId;
+
+    @ApiModelProperty("鏍稿績璐d换浜�")
+    @TableField(exist = false)
+    private String coreResponsorUserName;
+
+    @ApiModelProperty("搴旀�ュ缃楠�")
+    private String execSteps;
+
+    @ApiModelProperty("鍙戝竷鐢熸晥鏃堕棿")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate publishTime;
+
+    @ApiModelProperty("澶囨敞")
+    private String remark;
+
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @ApiModelProperty("鏈�鍚庝慨璁㈡椂闂�")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    @TableField(fill = FieldFill.INSERT)
+    private Integer tenantId;
+}
diff --git a/src/main/java/com/ruoyi/safe/service/SafeAccidentService.java b/src/main/java/com/ruoyi/safe/service/SafeAccidentService.java
new file mode 100644
index 0000000..6919f7a
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/service/SafeAccidentService.java
@@ -0,0 +1,19 @@
+package com.ruoyi.safe.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.safe.pojo.SafeAccident;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--浜嬫晠涓婃姤璁板綍 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-28 02:40:31
+ */
+public interface SafeAccidentService extends IService<SafeAccident> {
+
+    IPage<SafeAccident> pageSafeAccident(Page page, SafeAccident safeAccident);
+}
diff --git a/src/main/java/com/ruoyi/safe/service/SafeContingencyPlanService.java b/src/main/java/com/ruoyi/safe/service/SafeContingencyPlanService.java
new file mode 100644
index 0000000..798e93b
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/service/SafeContingencyPlanService.java
@@ -0,0 +1,19 @@
+package com.ruoyi.safe.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.safe.pojo.SafeContingencyPlan;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--搴旀�ラ妗堟煡闃� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-28 02:07:29
+ */
+public interface SafeContingencyPlanService extends IService<SafeContingencyPlan> {
+
+    IPage<SafeContingencyPlan> pageSafeContingencyPlan(Page page, SafeContingencyPlan safeContingencyPlan);
+}
diff --git a/src/main/java/com/ruoyi/safe/service/impl/SafeAccidentServiceImpl.java b/src/main/java/com/ruoyi/safe/service/impl/SafeAccidentServiceImpl.java
new file mode 100644
index 0000000..131ba24
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/service/impl/SafeAccidentServiceImpl.java
@@ -0,0 +1,30 @@
+package com.ruoyi.safe.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.safe.pojo.SafeAccident;
+import com.ruoyi.safe.mapper.SafeAccidentMapper;
+import com.ruoyi.safe.service.SafeAccidentService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--浜嬫晠涓婃姤璁板綍 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-28 02:40:31
+ */
+@Service
+public class SafeAccidentServiceImpl extends ServiceImpl<SafeAccidentMapper, SafeAccident> implements SafeAccidentService {
+
+    @Autowired
+    private SafeAccidentMapper safeAccidentMapper;
+
+    @Override
+    public IPage<SafeAccident> pageSafeAccident(Page page, SafeAccident safeAccident) {
+        return safeAccidentMapper.pageSafeAccident(page, safeAccident);
+    }
+}
diff --git a/src/main/java/com/ruoyi/safe/service/impl/SafeContingencyPlanServiceImpl.java b/src/main/java/com/ruoyi/safe/service/impl/SafeContingencyPlanServiceImpl.java
new file mode 100644
index 0000000..b3ebd98
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/service/impl/SafeContingencyPlanServiceImpl.java
@@ -0,0 +1,30 @@
+package com.ruoyi.safe.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.safe.pojo.SafeContingencyPlan;
+import com.ruoyi.safe.mapper.SafeContingencyPlanMapper;
+import com.ruoyi.safe.service.SafeContingencyPlanService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 瀹夊叏鐢熶骇--搴旀�ラ妗堟煡闃� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-01-28 02:07:29
+ */
+@Service
+public class SafeContingencyPlanServiceImpl extends ServiceImpl<SafeContingencyPlanMapper, SafeContingencyPlan> implements SafeContingencyPlanService {
+
+    @Autowired
+    private SafeContingencyPlanMapper safeContingencyPlanMapper;
+
+    @Override
+    public IPage<SafeContingencyPlan> pageSafeContingencyPlan(Page page, SafeContingencyPlan safeContingencyPlan) {
+        return safeContingencyPlanMapper.pageSafeContingencyPlan(page, safeContingencyPlan);
+    }
+}
diff --git a/src/main/java/com/ruoyi/safe/service/impl/SafeHazardRecordServiceImpl.java b/src/main/java/com/ruoyi/safe/service/impl/SafeHazardRecordServiceImpl.java
index e6c6a08..2d6fa1d 100644
--- a/src/main/java/com/ruoyi/safe/service/impl/SafeHazardRecordServiceImpl.java
+++ b/src/main/java/com/ruoyi/safe/service/impl/SafeHazardRecordServiceImpl.java
@@ -16,6 +16,7 @@
 import org.springframework.transaction.annotation.Transactional;
 
 import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
 import java.util.List;
 
 /**
@@ -51,6 +52,10 @@
         safeHazardRecord.setApplyUserId(SecurityUtils.getUserId().intValue());
         safeHazardRecord.setApplyTime(LocalDate.now());
         safeHazardRecordMapper.insert(safeHazardRecord);
+        String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
+        String no = "LY" + String.format("%s%03d", datePrefix, safeHazardRecord.getId());
+        safeHazardRecord.setMaterialRecordCode(no);
+        safeHazardRecordMapper.updateById(safeHazardRecord);
         //鍑忓簱瀛�
         safeHazard.setStockQty(safeHazard.getStockQty().subtract(safeHazardRecord.getApplyQty()));
         safeHazardMapper.updateById(safeHazard);
diff --git a/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java b/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java
index 9db21f5..2117d96 100644
--- a/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java
+++ b/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java
@@ -12,6 +12,7 @@
 
 import java.math.BigDecimal;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 浜у搧淇℃伅Mapper鎺ュ彛
@@ -33,4 +34,10 @@
     IPage<ProcurementBusinessSummaryDto> procurementBusinessSummaryListPage(Page page,@Param("req") ProcurementBusinessSummaryDto procurementBusinessSummaryDto);
 
     List<LossProductModelDto> selectProductBomStructure(@Param("salesLedegerId") Long salesLedegerId);
+
+    List<Map<String, Object>> selectProductSalesAnalysis();
+
+    List<Map<String, Object>> selectRawMaterialPurchaseAnalysis();
+
+    int selectProductCountByTypeAndDate(@Param("type") Integer type, @Param("startDate") String startDate, @Param("endDate") String endDate);
 }
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
index c0c53ca..f87ebd8 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
@@ -7,6 +7,8 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.enums.StockQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockUnQualifiedRecordTypeEnum;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.procurementrecord.utils.StockUtils;
@@ -388,6 +390,13 @@
                                 new LambdaQueryWrapper<QualityInspect>()
                                         .in(QualityInspect::getProductMainId, productMainIds)
                         );
+                        //鍒犻櫎鍑哄簱璁板綍
+                        for (Long productMainId : productMainIds) {
+                            //鍒犻櫎鐢熶骇鍑哄簱璁板綍
+                            stockUtils.deleteStockOutRecord(productMainId, StockQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode());
+                            //鍒犻櫎鎶ュ簾鐨勫叆搴撹褰�
+                            stockUtils.deleteStockInRecord(productMainId, StockUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode());
+                        }
                         qualityInspects.forEach(qualityInspect -> {
                             //inspectState=1 宸叉彁浜� 涓嶈兘鍒犻櫎
                             if (qualityInspect.getInspectState() == 1) {
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
index 7464933..af21c1c 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -1,7 +1,6 @@
 package com.ruoyi.sales.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
@@ -9,14 +8,11 @@
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.account.pojo.AccountIncome;
 import com.ruoyi.account.service.AccountIncomeService;
 import com.ruoyi.basic.mapper.CustomerMapper;
 import com.ruoyi.basic.mapper.ProductMapper;
 import com.ruoyi.basic.mapper.ProductModelMapper;
 import com.ruoyi.basic.pojo.Customer;
-import com.ruoyi.basic.pojo.Product;
-import com.ruoyi.basic.pojo.ProductModel;
 import com.ruoyi.common.enums.FileNameType;
 import com.ruoyi.common.exception.base.BaseException;
 import com.ruoyi.common.utils.DateUtils;
@@ -27,7 +23,6 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.other.mapper.TempFileMapper;
 import com.ruoyi.other.pojo.TempFile;
-import com.ruoyi.production.dto.ProductStructureDto;
 import com.ruoyi.production.mapper.*;
 import com.ruoyi.production.pojo.*;
 import com.ruoyi.project.system.domain.SysDept;
@@ -151,6 +146,7 @@
     private ProductMapper productMapper;
     @Autowired
     private ProductStructureMapper productStructureMapper;
+;
 
     @Override
     public List<SalesLedger> selectSalesLedgerList(SalesLedgerDto salesLedgerDto) {
diff --git a/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
index 72bd074..3a5a0ab 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
@@ -8,7 +8,6 @@
 import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl;
 import com.ruoyi.common.enums.FileNameType;
 import com.ruoyi.common.enums.StockQualifiedRecordTypeEnum;
-import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.other.service.impl.TempFileServiceImpl;
 import com.ruoyi.procurementrecord.utils.StockUtils;
 import com.ruoyi.sales.dto.ShippingInfoDto;
@@ -16,7 +15,6 @@
 import com.ruoyi.sales.mapper.ShippingInfoMapper;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import com.ruoyi.sales.pojo.ShippingInfo;
-import com.ruoyi.sales.service.ICommonFileService;
 import com.ruoyi.sales.service.ShippingInfoService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
@@ -88,7 +86,7 @@
         // 鎵e凡鍙戣揣搴撳瓨
         for (ShippingInfo shippingInfo : shippingInfos) {
             if("宸插彂璐�".equals(shippingInfo.getStatus())) {
-                stockUtils.deleteStockRecord(shippingInfo.getId(), StockQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode());
+                stockUtils.deleteStockOutRecord(shippingInfo.getId(), StockQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode());
             }
         }
         // 鍒犻櫎鍙戣揣瀹℃壒
diff --git a/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
index ac9792c..53604e0 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/StaffLeaveServiceImpl.java
@@ -5,6 +5,8 @@
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.exception.base.BaseException;
 import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.mapper.SysUserMapper;
 import com.ruoyi.staff.dto.StaffLeaveDto;
 import com.ruoyi.staff.mapper.StaffLeaveMapper;
 import com.ruoyi.staff.mapper.StaffOnJobMapper;
@@ -29,6 +31,9 @@
 
     @Autowired
     private StaffOnJobMapper staffOnJobMapper;
+
+    @Autowired
+    private SysUserMapper sysUserMapper;
 
     //鏂板绂昏亴鍒楄〃鍒嗛〉鏌ヨ
     @Override
@@ -61,6 +66,12 @@
         }
         staffLeaveMapper.insert(staffLeave);
 
+        // 鏇存柊瀵瑰簲鐢ㄦ埛鐘舵�佷负鍋滅敤
+        // 鏍规嵁鍛樺伐缂栧彿鏌ヨ鐢ㄦ埛
+        SysUser sysUser = sysUserMapper.selectUserByUserName(staffOnJob.getStaffNo());
+        sysUser.setStatus("1");
+        sysUserMapper.updateUser(sysUser);
+
         // 鏇存柊绂昏亴鐘舵�佷负绂昏亴
         staffOnJob.setStaffState(0);
        return staffOnJobMapper.updateById(staffOnJob);
diff --git a/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java b/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java
index 15dcbbc..e58db7c 100644
--- a/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java
+++ b/src/main/java/com/ruoyi/stock/mapper/StockInventoryMapper.java
@@ -13,6 +13,7 @@
 import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.util.List;
+import java.util.Map;
 
 /**
  * <p>
@@ -40,5 +41,11 @@
 
     BigDecimal selectTotal();
 
+    int selectStorageProductCountByDate(@Param("startDate") String startDate, @Param("endDate") String endDate);
+
+    List<Map<String, Object>> selectDailyStockInCounts(@Param("rootCategoryId") Long rootCategoryId, @Param("startDate") String startDate, @Param("endDate") String endDate);
+
+    List<Map<String, Object>> selectDailyStockOutCounts(@Param("rootCategoryId") Long rootCategoryId, @Param("startDate") String startDate, @Param("endDate") String endDate);
+
     BigDecimal selectTotalByDate( @Param("now") LocalDate now);
 }
diff --git a/src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java b/src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java
index 7fba29a..e4e3b82 100644
--- a/src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java
+++ b/src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java
@@ -29,7 +29,7 @@
     private static final long serialVersionUID = 1L;
 
     @TableId(value = "id", type = IdType.AUTO)
-    private Integer id;
+    private Long id;
 
     @ApiModelProperty("鍏ュ簱鎵规")
     private String outboundBatches;
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
index bf64268..ce6241a 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
@@ -80,7 +80,7 @@
                     StockInventoryDto stockInRecordDto = new StockInventoryDto();
                     stockInRecordDto.setProductModelId(stockInventory.getProductModelId());
                     stockInRecordDto.setQualitity(stockInRecord.getStockInNum());
-                    stockInventoryMapper.updateAddStockInventory(stockInRecordDto);
+                    stockInventoryMapper.updateSubtractStockInventory(stockInRecordDto);
                 }
             }else if (stockInRecord.getType().equals("1")) {
                 StockUninventory stockUninventory = stockUninventoryMapper.selectOne(new LambdaQueryWrapper<StockUninventory>().eq(StockUninventory::getProductModelId, stockInRecord.getProductModelId()));
@@ -90,7 +90,7 @@
                     StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
                     stockUninventoryDto.setProductModelId(stockUninventory.getProductModelId());
                     stockUninventoryDto.setQualitity(stockInRecord.getStockInNum());
-                    stockUninventoryMapper.updateAddStockUnInventory(stockUninventoryDto);
+                    stockUninventoryMapper.updateSubtractStockUnInventory(stockUninventoryDto);
                 }
             }
         }
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
index 99c4544..4c89975 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
@@ -25,6 +25,7 @@
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -83,7 +84,7 @@
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Boolean subtractStockInventory(StockInventoryDto stockInventoryDto) {
-            //  鏂板鍑哄簱璁板綍
+        //  鏂板鍑哄簱璁板綍
         StockOutRecordDto stockOutRecordDto = new StockOutRecordDto();
         stockOutRecordDto.setRecordId(stockInventoryDto.getRecordId());
         stockOutRecordDto.setRecordType(stockInventoryDto.getRecordType());
@@ -92,14 +93,18 @@
         stockOutRecordDto.setType("0");
         stockOutRecordService.add(stockOutRecordDto);
         StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId()));
-        if (stockInventoryDto.getQualitity().compareTo( oldStockInventory.getQualitity().subtract(oldStockInventory.getLockedQuantity()))>0) {
-            throw new RuntimeException("搴撳瓨涓嶈冻鏃犳硶鍑哄簱");
-        }
         if (ObjectUtils.isEmpty(oldStockInventory)) {
             throw new RuntimeException("浜у搧搴撳瓨涓嶅瓨鍦�");
-        }else {
-            stockInventoryMapper.updateSubtractStockInventory(stockInventoryDto);
         }
+        BigDecimal lockedQty = oldStockInventory.getLockedQuantity();
+        if (lockedQty == null) {
+            lockedQty = BigDecimal.ZERO;
+        }
+        if (stockInventoryDto.getQualitity().compareTo(oldStockInventory.getQualitity().subtract(lockedQty)) > 0) {
+            throw new RuntimeException("搴撳瓨涓嶈冻鏃犳硶鍑哄簱");
+        }
+
+        stockInventoryMapper.updateSubtractStockInventory(stockInventoryDto);
         return true;
     }
 
diff --git a/src/main/resources/mapper/home/HomeMapper.xml b/src/main/resources/mapper/home/HomeMapper.xml
new file mode 100644
index 0000000..060099a
--- /dev/null
+++ b/src/main/resources/mapper/home/HomeMapper.xml
@@ -0,0 +1,16 @@
+<?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 namespace="com.ruoyi.home.mapper.HomeMapper">
+
+    <select id="productTurnoverDays" resultType="com.ruoyi.dto.MapDto">
+        SELECT p.product_name                                                      AS name,
+               DATEDIFF(IFNULL(MAX(sor.create_time), NOW()), MAX(sir.create_time)) AS value
+        FROM product p
+                 JOIN product_model pm ON p.id = pm.product_id
+                 JOIN stock_in_record sir ON pm.id = sir.product_model_id
+                 LEFT JOIN stock_out_record sor ON pm.id = sor.product_model_id
+        GROUP BY p.id, p.product_name
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/safe/SafeAccidentMapper.xml b/src/main/resources/mapper/safe/SafeAccidentMapper.xml
new file mode 100644
index 0000000..159e7cd
--- /dev/null
+++ b/src/main/resources/mapper/safe/SafeAccidentMapper.xml
@@ -0,0 +1,48 @@
+<?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 namespace="com.ruoyi.safe.mapper.SafeAccidentMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.safe.pojo.SafeAccident">
+        <id column="id" property="id" />
+        <result column="accident_code" property="accidentCode" />
+        <result column="accident_name" property="accidentName" />
+        <result column="accident_type" property="accidentType" />
+        <result column="happen_time" property="happenTime" />
+        <result column="happen_location" property="happenLocation" />
+        <result column="accident_grade" property="accidentGrade" />
+        <result column="accident_cause" property="accidentCause" />
+        <result column="root_cause" property="rootCause" />
+        <result column="person_loss" property="personLoss" />
+        <result column="asset_loss" property="assetLoss" />
+        <result column="production_loss" property="productionLoss" />
+        <result column="handle_measures" property="handleMeasures" />
+        <result column="responsible_person" property="responsiblePerson" />
+        <result column="remark" property="remark" />
+        <result column="create_time" property="createTime" />
+        <result column="create_user" property="createUser" />
+        <result column="update_time" property="updateTime" />
+        <result column="update_user" property="updateUser" />
+        <result column="tenant_id" property="tenantId" />
+    </resultMap>
+    <select id="pageSafeAccident" resultType="com.ruoyi.safe.pojo.SafeAccident">
+        select sa.*,
+               su.nick_name createUserName,
+        from safe_accident sa
+        left join sys_user su on sa.create_user = su.user_id
+        where 1=1
+        <if test="c.accidentCode != null and c.accidentCode != ''">
+            and sa.accident_code like concat('%', #{c.accidentCode}, '%')
+        </if>
+        <if test="c.accidentName != null and c.accidentName != ''">
+            and sa.accident_name like concat('%', #{accidentName}, '%')
+        </if>
+        <if test="c.accidentType != null and c.accidentType != ''">
+            and sa.accident_type like concat('%', #{accidentType}, '%')
+        </if>
+        <if test="c.accidentGrade != null and c.accidentGrade != ''">
+            and sa.accident_grade like concat('%', #{accidentGrade}, '%')
+        </if>
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/safe/SafeContingencyPlanMapper.xml b/src/main/resources/mapper/safe/SafeContingencyPlanMapper.xml
new file mode 100644
index 0000000..d979545
--- /dev/null
+++ b/src/main/resources/mapper/safe/SafeContingencyPlanMapper.xml
@@ -0,0 +1,38 @@
+<?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 namespace="com.ruoyi.safe.mapper.SafeContingencyPlanMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.safe.pojo.SafeContingencyPlan">
+        <id column="id" property="id" />
+        <result column="plan_code" property="planCode" />
+        <result column="plan_name" property="planName" />
+        <result column="plan_type" property="planType" />
+        <result column="apply_scope" property="applyScope" />
+        <result column="core_responsor_user_id" property="coreResponsorUserId" />
+        <result column="exec_steps" property="execSteps" />
+        <result column="publish_time" property="publishTime" />
+        <result column="remark" property="remark" />
+        <result column="create_time" property="createTime" />
+        <result column="create_user" property="createUser" />
+        <result column="update_time" property="updateTime" />
+        <result column="update_user" property="updateUser" />
+        <result column="tenant_id" property="tenantId" />
+    </resultMap>
+    <select id="pageSafeContingencyPlan" resultType="com.ruoyi.safe.pojo.SafeContingencyPlan">
+         select scp.*, su.nick_name coreResponsorUserName
+        from safe_contingency_plan scp
+        left join sys_user su on scp.core_responsor_user_id = su.user_id
+        where 1=1
+        <if test="c.planCode != null and c.planCode != ''">
+            and scp.plan_code like concat('%', #{c.planCode}, '%')
+        </if>
+        <if test="c.planName != null and c.planName != ''">
+            and scp.plan_name like concat('%', #{c.planName}, '%')
+        </if>
+        <if test="c.planType != null and c.planType != ''">
+            and scp.plan_type like concat('%', #{c.planType}, '%')
+        </if>
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
index 2fdd8d3..ae9f718 100644
--- a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
+++ b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -147,7 +147,7 @@
                        LEFT JOIN product_structure ps ON pb.id = ps.bom_id
                        LEFT JOIN product_model pm1 ON pm1.id = ps.product_model_id
                        LEFT JOIN product p ON p.id = pm1.product_id
-              WHERE sl.id = #{salesLedegerId}) A
+               WHERE sl.id = #{salesLedegerId}) A
         group by a.model, a.product_name, a.unit
     </select>
     <select id="selectProduct" resultType="com.ruoyi.sales.pojo.SalesLedgerProduct">
@@ -158,4 +158,46 @@
         from product_model pm
         left join product p on pm.product_id = p.id
     </select>
-</mapper>
\ No newline at end of file
+
+    <select id="selectProductSalesAnalysis" resultType="java.util.LinkedHashMap">
+        SELECT
+            product_category as name,
+            SUM( tax_inclusive_total_price ) AS value
+        FROM
+            sales_ledger_product
+        WHERE
+            type = 1
+        GROUP BY
+            product_category
+        ORDER BY
+            value DESC
+        LIMIT 5
+    </select>
+
+    <select id="selectRawMaterialPurchaseAnalysis" resultType="java.util.LinkedHashMap">
+        SELECT
+            pr.product_name AS name,
+            SUM( slp.tax_inclusive_total_price ) AS value
+        FROM
+            sales_ledger_product slp
+            JOIN product pr ON slp.product_id = pr.id
+        WHERE
+            slp.type = 2
+            AND pr.parent_id = ( SELECT id FROM product WHERE product_name = '鍘熸潗鏂�' )
+        GROUP BY
+            pr.id,
+            pr.product_name
+        ORDER BY
+            value DESC
+        LIMIT 5
+    </select>
+
+    <select id="selectProductCountByTypeAndDate" resultType="int">
+        SELECT COUNT(*)
+        FROM sales_ledger_product
+        WHERE type = #{type}
+        AND register_date &gt;= #{startDate}
+        AND register_date &lt;= #{endDate}
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/stock/StockInventoryMapper.xml b/src/main/resources/mapper/stock/StockInventoryMapper.xml
index 0c47ede..97dc81d 100644
--- a/src/main/resources/mapper/stock/StockInventoryMapper.xml
+++ b/src/main/resources/mapper/stock/StockInventoryMapper.xml
@@ -185,7 +185,7 @@
         p.product_name
     </select>
     <select id="selectTotal" resultType="java.math.BigDecimal">
-        select ifnull(sum(qualitity),0)
+        select ifnull(sum(qualitity), 0)
         from stock_inventory
     </select>
     <select id="selectTotalByDate" resultType="java.math.BigDecimal">
@@ -195,4 +195,41 @@
            create_time &gt;= #{now} and create_time &lt; DATE_ADD(#{now}, INTERVAL 1 DAY)
     </select>
 
+    <select id="selectStorageProductCountByDate" resultType="int">
+        SELECT COUNT(*)
+        FROM (SELECT create_time
+              FROM stock_inventory
+              UNION ALL
+              SELECT create_time
+              FROM stock_uninventory) combined
+        WHERE create_time &gt;= #{startDate}
+          AND create_time &lt;= #{endDate}
+    </select>
+
+    <select id="selectDailyStockInCounts" resultType="java.util.Map">
+        SELECT DATE(sir.create_time) AS date,
+               SUM(sir.stock_in_num) AS count
+        FROM stock_in_record sir
+                 JOIN product_model pm ON sir.product_model_id = pm.id
+                 JOIN product p ON pm.product_id = p.id
+        WHERE (p.parent_id = #{rootCategoryId} OR p.id = #{rootCategoryId})
+          AND sir.create_time &gt;= #{startDate}
+          AND sir.create_time &lt;= #{endDate}
+        GROUP BY DATE(sir.create_time)
+        ORDER BY DATE(sir.create_time) ASC
+    </select>
+
+    <select id="selectDailyStockOutCounts" resultType="java.util.Map">
+        SELECT DATE(sor.create_time)  AS date,
+               SUM(sor.stock_out_num) AS count
+        FROM stock_out_record sor
+                 JOIN product_model pm ON sor.product_model_id = pm.id
+                 JOIN product p ON pm.product_id = p.id
+        WHERE (p.parent_id = #{rootCategoryId} OR p.id = #{rootCategoryId})
+          AND sor.create_time &gt;= #{startDate}
+          AND sor.create_time &lt;= #{endDate}
+        GROUP BY DATE(sor.create_time)
+        ORDER BY DATE(sor.create_time) ASC
+    </select>
+
 </mapper>

--
Gitblit v1.9.3