From 263b034b4058bb7a36c709278abdc88ca1ba26c1 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期一, 30 三月 2026 18:01:25 +0800
Subject: [PATCH] feat: 生产成本导入数据入库

---
 src/main/java/com/ruoyi/production/service/IProductionSettlementBatchesService.java         |   21 ++
 src/main/java/com/ruoyi/production/mapper/ProductionSettlementDetailsMapper.java            |   16 +
 src/main/java/com/ruoyi/production/pojo/ProductionSettlementBatches.java                    |   55 ++++++
 src/main/resources/mapper/production/ProductionSettlementBatchesMapper.xml                  |   16 +
 src/main/java/com/ruoyi/production/mapper/ProductionSettlementBatchesMapper.java            |   16 +
 src/main/java/com/ruoyi/production/controller/ProductionSettlementBatchesController.java    |   41 ++++
 src/main/java/com/ruoyi/production/service/impl/ProductionCostServiceImpl.java              |   22 +
 src/main/java/com/ruoyi/production/controller/ProductionSettlementDetailsController.java    |   22 ++
 src/main/java/com/ruoyi/production/pojo/ProductionSettlementDetails.java                    |   81 +++++++++
 src/main/java/com/ruoyi/production/service/impl/ProductionSettlementBatchesServiceImpl.java |   88 +++++++++
 src/main/java/com/ruoyi/production/service/impl/ProductionSettlementDetailsServiceImpl.java |   20 ++
 doc/宁夏-中盛建材.sql                                                                             |   44 ++++
 src/main/java/com/ruoyi/production/service/IProductionSettlementDetailsService.java         |   16 +
 src/main/java/com/ruoyi/production/dto/SettlementImportDto.java                             |   46 +++++
 src/main/resources/mapper/production/ProductionSettlementDetailsMapper.xml                  |   25 ++
 15 files changed, 523 insertions(+), 6 deletions(-)

diff --git "a/doc/\345\256\201\345\244\217-\344\270\255\347\233\233\345\273\272\346\235\220.sql" "b/doc/\345\256\201\345\244\217-\344\270\255\347\233\233\345\273\272\346\235\220.sql"
index 9f95867..3593ec5 100644
--- "a/doc/\345\256\201\345\244\217-\344\270\255\347\233\233\345\273\272\346\235\220.sql"
+++ "b/doc/\345\256\201\345\244\217-\344\270\255\347\233\233\345\273\272\346\235\220.sql"
@@ -468,4 +468,46 @@
     KEY `idx_order_id` (`order_id`) USING BTREE
 ) ENGINE = InnoDB
   DEFAULT CHARSET = utf8mb4
-  COLLATE = utf8mb4_0900_ai_ci COMMENT ='鐢熶骇璁㈠崟缁戝畾鐨勫伐鑹鸿矾绾胯〃';
\ No newline at end of file
+  COLLATE = utf8mb4_0900_ai_ci COMMENT ='鐢熶骇璁㈠崟缁戝畾鐨勫伐鑹鸿矾绾胯〃';
+
+CREATE TABLE `production_settlement_batches`
+(
+    `id`          bigint NOT NULL AUTO_INCREMENT COMMENT '涓婚敭ID',
+    `period_time` date         DEFAULT NULL COMMENT '鏍哥畻褰掑睘鏈堜唤',
+    `batch_name`  varchar(255) DEFAULT NULL COMMENT '鎵规鍚嶇О',
+    `status`      int          DEFAULT '0' COMMENT '鐘舵�侊細0-浠呴绠楋紝1-缁撶畻璁$畻涓紝2-宸插畬鎴愮粨绠楋紝3-宸查攣瀹�',
+    `create_user` varchar(255) DEFAULT NULL COMMENT '瀵煎叆鐢ㄦ埛',
+    `create_time` datetime     DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃ユ湡',
+    `tenant_id`   bigint       DEFAULT NULL COMMENT '绉熸埛ID',
+    PRIMARY KEY (`id`),
+    KEY `idx_period` (`period_time`)
+) ENGINE = InnoDB
+  DEFAULT CHARSET = utf8mb4 COMMENT ='鐢熶骇鎴愭湰鏍哥畻鎵规涓昏〃';
+
+CREATE TABLE `production_settlement_details`
+(
+    `id`           bigint NOT NULL AUTO_INCREMENT COMMENT '涓婚敭ID',
+    `batch_id`     bigint NOT NULL COMMENT '鍏宠仈鏍哥畻鎵规琛↖D',
+    `product_id`   bigint          DEFAULT NULL COMMENT '浜у搧ID',
+    `product_type` varchar(100)    DEFAULT NULL COMMENT '浜у搧绫诲瀷鍚嶇О',
+    `category`     varchar(100)    DEFAULT NULL COMMENT '璐圭敤绫诲埆',
+    `subject_name` varchar(100)    DEFAULT NULL COMMENT '绉戠洰鍚嶇О',
+
+    `budget_qty`   decimal(20, 15) DEFAULT '0.000000000000000' COMMENT '棰勭畻鑰楅噺',
+    `budget_price` decimal(20, 15) DEFAULT '0.000000000000000' COMMENT '棰勭畻鍗曚环',
+    `budget_total` decimal(20, 15) DEFAULT '0.000000000000000' COMMENT '棰勭畻鎬绘垚鏈�',
+
+    `actual_qty`   decimal(20, 15) DEFAULT '0.000000000000000' COMMENT '瀹為檯鑰楅噺',
+    `actual_price` decimal(20, 15) DEFAULT '0.000000000000000' COMMENT '瀹為檯鍗曚环',
+    `actual_total` decimal(20, 15) DEFAULT '0.000000000000000' COMMENT '瀹為檯鎬绘垚鏈�',
+
+    `diff_qty`     decimal(20, 15) DEFAULT '0.000000000000000' COMMENT '鑰楅噺宸紓',
+    `diff_price`   decimal(20, 15) DEFAULT '0.000000000000000' COMMENT '鍗曚环宸紓',
+    `diff_total`   DECIMAL(20, 15) DEFAULT '0.000000000000000' COMMENT '鎬绘垚鏈樊寮�',
+
+    `tenant_id`    bigint          DEFAULT NULL COMMENT '绉熸埛ID',
+    PRIMARY KEY (`id`),
+    KEY `idx_batch_id` (`batch_id`),
+    KEY `idx_product_id` (`product_id`) COMMENT '鏂逛究鎸変骇鍝佹煡璇㈠巻鍙叉垚鏈姣�'
+) ENGINE = InnoDB
+  DEFAULT CHARSET = utf8mb4 COMMENT ='鐢熶骇鎴愭湰鏍哥畻瀵规瘮鏄庣粏琛�';
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionSettlementBatchesController.java b/src/main/java/com/ruoyi/production/controller/ProductionSettlementBatchesController.java
new file mode 100644
index 0000000..64f222f
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/controller/ProductionSettlementBatchesController.java
@@ -0,0 +1,41 @@
+package com.ruoyi.production.controller;
+
+
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.production.service.IProductionSettlementBatchesService;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.time.LocalDate;
+
+/**
+ * <p>
+ * 鐢熶骇鎴愭湰鏍哥畻鎵规涓昏〃 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author deslrey
+ * @since 2026-03-30
+ */
+@RestController
+@RequestMapping("/productionSettlementBatches")
+@ApiModel(value = "ProductionSettlementBatchesController绫�", description = "鐢熶骇鎴愭湰鏍哥畻鎵规涓昏〃 鍓嶇鎺у埗鍣�")
+public class ProductionSettlementBatchesController {
+
+    @Autowired
+    private IProductionSettlementBatchesService productionSettlementBatchesService;
+
+    @PostMapping("/import")
+    @ApiOperation("瀵煎叆鐢熶骇鎴愭湰鏍哥畻琛�")
+    public AjaxResult importProductionSettlement(@RequestParam("file") MultipartFile file, @RequestParam(required = false) LocalDate periodTime, @RequestParam(required = false) String batchName) {
+        productionSettlementBatchesService.importProductionSettlement(file, periodTime, batchName);
+        return AjaxResult.success();
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/production/controller/ProductionSettlementDetailsController.java b/src/main/java/com/ruoyi/production/controller/ProductionSettlementDetailsController.java
new file mode 100644
index 0000000..99bb7f4
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/controller/ProductionSettlementDetailsController.java
@@ -0,0 +1,22 @@
+package com.ruoyi.production.controller;
+
+
+import io.swagger.annotations.ApiModel;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 鐢熶骇鎴愭湰鏍哥畻瀵规瘮鏄庣粏琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author deslrey
+ * @since 2026-03-30
+ */
+@RestController
+@RequestMapping("/production-settlement-details")
+@ApiModel(value = "ProductionSettlementDetailsController绫�", description = "鐢熶骇鎴愭湰鏍哥畻瀵规瘮鏄庣粏琛� 鍓嶇鎺у埗鍣�")
+public class ProductionSettlementDetailsController {
+
+}
diff --git a/src/main/java/com/ruoyi/production/dto/SettlementImportDto.java b/src/main/java/com/ruoyi/production/dto/SettlementImportDto.java
new file mode 100644
index 0000000..3a38f1f
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/dto/SettlementImportDto.java
@@ -0,0 +1,46 @@
+package com.ruoyi.production.dto;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * <br>
+ * 鐢熶骇鎴愭湰鏍哥畻瀵规瘮鏂囦欢瀵煎叆Dto
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/03/30
+ */
+@Data
+@ApiModel(value = "SettlementImportDto", description = "鐢熶骇鎴愭湰鏍哥畻瀵规瘮鏂囦欢瀵煎叆Dto")
+public class SettlementImportDto {
+
+    @Excel(name = "浜у搧绫诲瀷")
+    @ApiModelProperty("浜у搧绫诲瀷")
+    private String productType;
+
+    @Excel(name = "绉戠洰鍚嶇О")
+    @ApiModelProperty("绉戠洰鍚嶇О")
+    private String category;
+
+    @Excel(name = "绉戠洰")
+    @ApiModelProperty("绉戠洰")
+    private String subjectName;
+
+    @Excel(name = "鎴愭湰棰勭畻")
+    @ApiModelProperty("鎴愭湰棰勭畻")
+    private BigDecimal budgetTotal;
+
+    @Excel(name = "鑰楅噺棰勭畻")
+    @ApiModelProperty("鑰楅噺棰勭畻")
+    private BigDecimal budgetQty;
+
+    @Excel(name = "鍗曚环棰勭畻")
+    @ApiModelProperty("鍗曚环棰勭畻")
+    private BigDecimal budgetPrice;
+}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionSettlementBatchesMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionSettlementBatchesMapper.java
new file mode 100644
index 0000000..8b53779
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionSettlementBatchesMapper.java
@@ -0,0 +1,16 @@
+package com.ruoyi.production.mapper;
+
+import com.ruoyi.production.pojo.ProductionSettlementBatches;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 鐢熶骇鎴愭湰鏍哥畻鎵规涓昏〃 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author deslrey
+ * @since 2026-03-30
+ */
+public interface ProductionSettlementBatchesMapper extends BaseMapper<ProductionSettlementBatches> {
+
+}
diff --git a/src/main/java/com/ruoyi/production/mapper/ProductionSettlementDetailsMapper.java b/src/main/java/com/ruoyi/production/mapper/ProductionSettlementDetailsMapper.java
new file mode 100644
index 0000000..20d4ff1
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/mapper/ProductionSettlementDetailsMapper.java
@@ -0,0 +1,16 @@
+package com.ruoyi.production.mapper;
+
+import com.ruoyi.production.pojo.ProductionSettlementDetails;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 鐢熶骇鎴愭湰鏍哥畻瀵规瘮鏄庣粏琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author deslrey
+ * @since 2026-03-30
+ */
+public interface ProductionSettlementDetailsMapper extends BaseMapper<ProductionSettlementDetails> {
+
+}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionSettlementBatches.java b/src/main/java/com/ruoyi/production/pojo/ProductionSettlementBatches.java
new file mode 100644
index 0000000..87e8e97
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionSettlementBatches.java
@@ -0,0 +1,55 @@
+package com.ruoyi.production.pojo;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.IdType;
+import java.time.LocalDate;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import java.io.Serializable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 鐢熶骇鎴愭湰鏍哥畻鎵规涓昏〃
+ * </p>
+ *
+ * @author deslrey
+ * @since 2026-03-30
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@TableName("production_settlement_batches")
+@ApiModel(value="ProductionSettlementBatches瀵硅薄", description="鐢熶骇鎴愭湰鏍哥畻鎵规涓昏〃")
+public class ProductionSettlementBatches implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "涓婚敭ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty(value = "鏍哥畻褰掑睘鏈堜唤")
+    private LocalDate periodTime;
+
+    @ApiModelProperty(value = "鎵规鍚嶇О")
+    private String batchName;
+
+    @ApiModelProperty(value = "鐘舵�侊細0-浠呴绠楋紝1-缁撶畻璁$畻涓紝2-宸插畬鎴愮粨绠楋紝3-宸查攣瀹�")
+    private Integer status;
+
+    @ApiModelProperty(value = "瀵煎叆鐢ㄦ埛")
+    private String createUser;
+
+    @ApiModelProperty(value = "鍒涘缓鏃ユ湡")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty(value = "绉熸埛ID")
+    private Long tenantId;
+
+
+}
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionSettlementDetails.java b/src/main/java/com/ruoyi/production/pojo/ProductionSettlementDetails.java
new file mode 100644
index 0000000..a9fd729
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionSettlementDetails.java
@@ -0,0 +1,81 @@
+package com.ruoyi.production.pojo;
+
+import java.math.BigDecimal;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.io.Serializable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 鐢熶骇鎴愭湰鏍哥畻瀵规瘮鏄庣粏琛�
+ * </p>
+ *
+ * @author deslrey
+ * @since 2026-03-30
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@TableName("production_settlement_details")
+@ApiModel(value="ProductionSettlementDetails瀵硅薄", description="鐢熶骇鎴愭湰鏍哥畻瀵规瘮鏄庣粏琛�")
+public class ProductionSettlementDetails implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "涓婚敭ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty(value = "鍏宠仈鏍哥畻鎵规琛↖D")
+    private Long batchId;
+
+    @ApiModelProperty(value = "浜у搧ID")
+    private Long productId;
+
+    @ApiModelProperty(value = "浜у搧绫诲瀷鍚嶇О")
+    private String productType;
+
+    @ApiModelProperty(value = "璐圭敤绫诲埆")
+    private String category;
+
+    @ApiModelProperty(value = "绉戠洰鍚嶇О")
+    private String subjectName;
+
+    @ApiModelProperty(value = "棰勭畻鑰楅噺")
+    private BigDecimal budgetQty;
+
+    @ApiModelProperty(value = "棰勭畻鍗曚环")
+    private BigDecimal budgetPrice;
+
+    @ApiModelProperty(value = "棰勭畻鎬绘垚鏈�")
+    private BigDecimal budgetTotal;
+
+    @ApiModelProperty(value = "瀹為檯鑰楅噺")
+    private BigDecimal actualQty;
+
+    @ApiModelProperty(value = "瀹為檯鍗曚环")
+    private BigDecimal actualPrice;
+
+    @ApiModelProperty(value = "瀹為檯鎬绘垚鏈�")
+    private BigDecimal actualTotal;
+
+    @ApiModelProperty(value = "鑰楅噺宸紓")
+    private BigDecimal diffQty;
+
+    @ApiModelProperty(value = "鍗曚环宸紓")
+    private BigDecimal diffPrice;
+
+    @ApiModelProperty(value = "鎬绘垚鏈樊寮�")
+    private BigDecimal diffTotal;
+
+    @ApiModelProperty(value = "绉熸埛ID")
+    private Long tenantId;
+
+
+}
diff --git a/src/main/java/com/ruoyi/production/service/IProductionSettlementBatchesService.java b/src/main/java/com/ruoyi/production/service/IProductionSettlementBatchesService.java
new file mode 100644
index 0000000..53c24b0
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/IProductionSettlementBatchesService.java
@@ -0,0 +1,21 @@
+package com.ruoyi.production.service;
+
+import com.ruoyi.production.pojo.ProductionSettlementBatches;
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.time.LocalDate;
+
+/**
+ * <p>
+ * 鐢熶骇鎴愭湰鏍哥畻鎵规涓昏〃 鏈嶅姟绫�
+ * </p>
+ *
+ * @author deslrey
+ * @since 2026-03-30
+ */
+public interface IProductionSettlementBatchesService extends IService<ProductionSettlementBatches> {
+
+    void importProductionSettlement(MultipartFile file, LocalDate periodTime, String batchName);
+
+}
diff --git a/src/main/java/com/ruoyi/production/service/IProductionSettlementDetailsService.java b/src/main/java/com/ruoyi/production/service/IProductionSettlementDetailsService.java
new file mode 100644
index 0000000..1621153
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/IProductionSettlementDetailsService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.production.service;
+
+import com.ruoyi.production.pojo.ProductionSettlementDetails;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 鐢熶骇鎴愭湰鏍哥畻瀵规瘮鏄庣粏琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author deslrey
+ * @since 2026-03-30
+ */
+public interface IProductionSettlementDetailsService extends IService<ProductionSettlementDetails> {
+
+}
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionCostServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionCostServiceImpl.java
index 25a32aa..152173d 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionCostServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionCostServiceImpl.java
@@ -179,12 +179,24 @@
 
     private <T> IPage<T> getMemoryPage(Page<T> page, List<T> list) {
         int total = list.size();
-        int size = (int) page.getSize();
-        int current = (int) page.getCurrent();
-        int fromIndex = (current - 1) * size;
-        int toIndex = Math.min(fromIndex + size, total);
+        long size = page.getSize();
+        long current = page.getCurrent();
 
-        List<T> subList = (fromIndex < total && fromIndex >= 0) ? list.subList(fromIndex, toIndex) : new ArrayList<>();
+        if (size == -1 || current == -1) {
+            page.setTotal(total);
+            page.setRecords(list);
+            return page;
+        }
+
+        int fromIndex = (int) ((current - 1) * size);
+        int toIndex = Math.min(fromIndex + (int) size, total);
+
+        List<T> subList;
+        if (fromIndex >= 0 && fromIndex < total) {
+            subList = list.subList(fromIndex, toIndex);
+        } else {
+            subList = new ArrayList<>();
+        }
 
         page.setTotal(total);
         page.setRecords(subList);
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionSettlementBatchesServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionSettlementBatchesServiceImpl.java
new file mode 100644
index 0000000..7a6bcb2
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionSettlementBatchesServiceImpl.java
@@ -0,0 +1,88 @@
+package com.ruoyi.production.service.impl;
+
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.production.dto.SettlementImportDto;
+import com.ruoyi.production.pojo.ProductionSettlementBatches;
+import com.ruoyi.production.mapper.ProductionSettlementBatchesMapper;
+import com.ruoyi.production.pojo.ProductionSettlementDetails;
+import com.ruoyi.production.service.IProductionSettlementBatchesService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.production.service.IProductionSettlementDetailsService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 鐢熶骇鎴愭湰鏍哥畻鎵规涓昏〃 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author deslrey
+ * @since 2026-03-30
+ */
+@Service
+public class ProductionSettlementBatchesServiceImpl extends ServiceImpl<ProductionSettlementBatchesMapper, ProductionSettlementBatches> implements IProductionSettlementBatchesService {
+
+    @Autowired
+    private IProductionSettlementDetailsService productionSettlementDetailsService;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void importProductionSettlement(MultipartFile file, LocalDate periodTime, String batchName) {
+        if (file == null || file.isEmpty()) {
+            throw new ServiceException("瀵煎叆澶辫触锛屾枃浠朵笉鑳戒负绌�");
+        }
+
+        List<SettlementImportDto> list;
+        try {
+            ExcelUtil<SettlementImportDto> util = new ExcelUtil<>(SettlementImportDto.class);
+            list = util.importExcel(file.getInputStream());
+        } catch (Exception e) {
+            log.error("瀵煎叆鐢熶骇鎴愭湰鏍哥畻澶辫触", e);
+            throw new ServiceException("瑙f瀽Excel鏂囦欢澶辫触锛�" + e.getMessage());
+        }
+
+        if (StringUtils.isEmpty(list)) {
+            throw new ServiceException("瀵煎叆鏁版嵁涓嶈兘涓虹┖锛�");
+        }
+
+        ProductionSettlementBatches batch = new ProductionSettlementBatches();
+        batch.setBatchName(StringUtils.isNotEmpty(batchName) ? batchName : periodTime + "鎴愭湰鏍哥畻瀵煎叆");
+        batch.setPeriodTime(periodTime != null ? periodTime : LocalDate.now());
+        batch.setStatus(0);
+        batch.setCreateTime(LocalDateTime.now());
+        batch.setCreateUser(SecurityUtils.getUsername());
+        this.save(batch);
+
+        List<ProductionSettlementDetails> detailList = list.stream().map(dto -> {
+            ProductionSettlementDetails detail = new ProductionSettlementDetails();
+            detail.setBatchId(batch.getId());
+            detail.setProductType(dto.getProductType());
+            detail.setCategory(dto.getCategory());
+            detail.setSubjectName(dto.getSubjectName());
+            detail.setBudgetQty(dto.getBudgetQty());
+            detail.setBudgetPrice(dto.getBudgetPrice());
+            detail.setBudgetTotal(dto.getBudgetTotal());
+            detail.setActualQty(BigDecimal.ZERO);
+            detail.setActualPrice(BigDecimal.ZERO);
+            detail.setActualTotal(BigDecimal.ZERO);
+            detail.setDiffQty(BigDecimal.ZERO);
+            detail.setDiffPrice(BigDecimal.ZERO);
+            detail.setDiffTotal(BigDecimal.ZERO);
+
+            return detail;
+        }).collect(Collectors.toList());
+
+        productionSettlementDetailsService.saveBatch(detailList);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionSettlementDetailsServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionSettlementDetailsServiceImpl.java
new file mode 100644
index 0000000..4295acd
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionSettlementDetailsServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.production.service.impl;
+
+import com.ruoyi.production.pojo.ProductionSettlementDetails;
+import com.ruoyi.production.mapper.ProductionSettlementDetailsMapper;
+import com.ruoyi.production.service.IProductionSettlementDetailsService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 鐢熶骇鎴愭湰鏍哥畻瀵规瘮鏄庣粏琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author deslrey
+ * @since 2026-03-30
+ */
+@Service
+public class ProductionSettlementDetailsServiceImpl extends ServiceImpl<ProductionSettlementDetailsMapper, ProductionSettlementDetails> implements IProductionSettlementDetailsService {
+
+}
diff --git a/src/main/resources/mapper/production/ProductionSettlementBatchesMapper.xml b/src/main/resources/mapper/production/ProductionSettlementBatchesMapper.xml
new file mode 100644
index 0000000..7e57b58
--- /dev/null
+++ b/src/main/resources/mapper/production/ProductionSettlementBatchesMapper.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.production.mapper.ProductionSettlementBatchesMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionSettlementBatches">
+        <id column="id" property="id" />
+        <result column="period_time" property="periodTime" />
+        <result column="batch_name" property="batchName" />
+        <result column="status" property="status" />
+        <result column="create_user" property="createUser" />
+        <result column="create_time" property="createTime" />
+        <result column="tenant_id" property="tenantId" />
+    </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/production/ProductionSettlementDetailsMapper.xml b/src/main/resources/mapper/production/ProductionSettlementDetailsMapper.xml
new file mode 100644
index 0000000..1476aac
--- /dev/null
+++ b/src/main/resources/mapper/production/ProductionSettlementDetailsMapper.xml
@@ -0,0 +1,25 @@
+<?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.production.mapper.ProductionSettlementDetailsMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionSettlementDetails">
+        <id column="id" property="id" />
+        <result column="batch_id" property="batchId" />
+        <result column="product_id" property="productId" />
+        <result column="product_type" property="productType" />
+        <result column="category" property="category" />
+        <result column="subject_name" property="subjectName" />
+        <result column="budget_qty" property="budgetQty" />
+        <result column="budget_price" property="budgetPrice" />
+        <result column="budget_total" property="budgetTotal" />
+        <result column="actual_qty" property="actualQty" />
+        <result column="actual_price" property="actualPrice" />
+        <result column="actual_total" property="actualTotal" />
+        <result column="diff_qty" property="diffQty" />
+        <result column="diff_price" property="diffPrice" />
+        <result column="diff_total" property="diffTotal" />
+        <result column="tenant_id" property="tenantId" />
+    </resultMap>
+
+</mapper>

--
Gitblit v1.9.3