From 92ce39f23638ebd9cfbe61ad9a44a92297fc3af6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=A3=B7=E5=8F=B6?=
 <14103883+leaf-phos@user.noreply.gitee.com>
Date: Tue, 19 Nov 2024 18:01:46 +0800
Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../common/core/redis/enums/RedisLockKey.java |   3 +-
 .../com/ruoyi/common/enums/LogBizType.java    |   3 +-
 .../common/k3cloud/constants/K3FormIds.java   |   5 +
 .../k3cloud/constants/fileds/K3ProdField.java |   1 +
 .../k3cloud/constants/fileds/K3UnitField.java |  13 ++
 .../com/ruoyi/common/constants/LogTitle.java  |   1 +
 .../controller/ProdOrderController.java       |  14 ++
 .../web/yh/prodOrder/domain/ProdOrder.java    |  13 +-
 .../yh/prodOrder/domain/ProdOrderQuery.java   |   5 +
 .../web/yh/prodOrder/domain/ProdOrderVO.java  |  11 +
 .../yh/prodOrder/mapper/ProdOrderMapper.xml   |  37 ++-
 .../service/impl/ProdOrderConverterImpl.java  |   3 +
 .../service/impl/ProdOrderServiceImpl.java    |   5 +-
 .../report/controller/ReportController.java   |   7 +-
 .../yh/report/service/ReportAssembler.java    |   8 +-
 .../service/impl/ReportAssemblerImpl.java     |  12 +-
 .../service/impl/ReportServiceImpl.java       |  63 ++++++
 .../controller/ReportOrderProdController.java | 107 +++++++++
 .../domain/ReportOrderProd.java               |  44 ++++
 .../domain/ReportOrderProdQuery.java          |  18 ++
 .../domain/ReportOrderProdVO.java             |  27 +++
 .../domain/bo/ReportOrderProdBO.java          |  12 +
 .../mapper/ReportOrderProdMapper.java         |  79 +++++++
 .../mapper/ReportOrderProdMapper.xml          | 161 +++++++++++++
 .../service/IReportOrderProdService.java      |  81 +++++++
 .../service/ReportOrderProdConverter.java     |  20 ++
 .../impl/ReportOrderProdConverterImpl.java    |  36 +++
 .../impl/ReportOrderProdServiceImpl.java      | 133 +++++++++++
 .../controller/ReportProdController.java      |   7 +
 .../yh/reportProd/domain/ReportProdVO.java    |   5 +
 .../yh/reportProd/domain/bo/ReportProdBO.java |   4 +
 .../service/ReportProdAssembler.java          |  22 ++
 .../reportProd/service/ReportProdService.java |   3 +
 .../service/impl/ReportProdAssemblerImpl.java |  73 ++++++
 .../service/impl/ReportProdConverterImpl.java |  27 +++
 .../service/impl/ReportProdServiceImpl.java   |   1 +
 .../service/ReportUserProdAssembler.java      |   4 -
 .../impl/ReportUserProdAssemblerImpl.java     |  21 --
 .../impl/ReportUserProdConverterImpl.java     |   1 -
 .../impl/ReportUserProdServiceImpl.java       |   2 +-
 .../yh/unit/controller/UnitController.java    | 123 ++++++++++
 .../com/ruoyi/web/yh/unit/domain/Unit.java    |  39 ++++
 .../ruoyi/web/yh/unit/domain/UnitQuery.java   |  11 +
 .../com/ruoyi/web/yh/unit/domain/UnitVO.java  |  11 +
 .../ruoyi/web/yh/unit/mapper/UnitMapper.java  |  64 ++++++
 .../ruoyi/web/yh/unit/mapper/UnitMapper.xml   |  81 +++++++
 .../web/yh/unit/service/UnitConverter.java    |  15 ++
 .../web/yh/unit/service/UnitService.java      |  69 ++++++
 .../unit/service/impl/UnitConverterImpl.java  |  55 +++++
 .../yh/unit/service/impl/UnitServiceImpl.java | 213 ++++++++++++++++++
 50 files changed, 1723 insertions(+), 50 deletions(-)
 create mode 100644 common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/k3cloud/constants/fileds/K3UnitField.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/controller/ReportOrderProdController.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/domain/ReportOrderProd.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/domain/ReportOrderProdQuery.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/domain/ReportOrderProdVO.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/domain/bo/ReportOrderProdBO.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/mapper/ReportOrderProdMapper.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/mapper/ReportOrderProdMapper.xml
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/service/IReportOrderProdService.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/service/ReportOrderProdConverter.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/service/impl/ReportOrderProdConverterImpl.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/service/impl/ReportOrderProdServiceImpl.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/ReportProdAssembler.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/impl/ReportProdAssemblerImpl.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/controller/UnitController.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/domain/Unit.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/domain/UnitQuery.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/domain/UnitVO.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/mapper/UnitMapper.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/mapper/UnitMapper.xml
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/service/UnitConverter.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/service/UnitService.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/service/impl/UnitConverterImpl.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/service/impl/UnitServiceImpl.java

diff --git a/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/enums/RedisLockKey.java b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/enums/RedisLockKey.java
index dd4ac18..9d77b46 100644
--- a/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/enums/RedisLockKey.java
+++ b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/enums/RedisLockKey.java
@@ -12,7 +12,8 @@ import lombok.Getter;
 public enum RedisLockKey {
 
     SYNC_PROD_BILL("sync_prod_bill", "同步生产订单"),
-    SAVE_MATERIAL("save_material", "保存物料");
+    SAVE_MATERIAL("save_material", "保存物料"),
+    SAVE_UNIT("save_unit", "保存单位");
 
 
     private final String key;
diff --git a/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/enums/LogBizType.java b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/enums/LogBizType.java
index 8e7dd4c..06a150a 100644
--- a/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/enums/LogBizType.java
+++ b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/enums/LogBizType.java
@@ -16,7 +16,8 @@ public enum LogBizType {
     PRICE("1", "单价"),
     REPORT("2", "报表"),
     PROD_ORDER("3", "生产订单" ),
-    MATERIAL("4", "物料");
+    MATERIAL("4", "物料"),
+    UNIT("5", "单位");
 
     private final String type;
     private final String msg;
diff --git a/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/k3cloud/constants/K3FormIds.java b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/k3cloud/constants/K3FormIds.java
index ff4521a..5e4d4d9 100644
--- a/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/k3cloud/constants/K3FormIds.java
+++ b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/k3cloud/constants/K3FormIds.java
@@ -16,6 +16,11 @@ public class K3FormIds {
      */
     public static final String MATERIAL = "BD_MATERIAL";
 
+    /**
+     * 单位
+     */
+    public static final String UNIT = "BD_UNIT";
+
     /**
      * 部门
      */
diff --git a/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/k3cloud/constants/fileds/K3ProdField.java b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/k3cloud/constants/fileds/K3ProdField.java
index 2e91369..b4d5969 100644
--- a/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/k3cloud/constants/fileds/K3ProdField.java
+++ b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/k3cloud/constants/fileds/K3ProdField.java
@@ -23,4 +23,5 @@ public class K3ProdField {
     public static final String F_BASE_UNIT_QTY = "FBaseUnitQty"; // 明细.基本单位数量
     public static final String F_QTY = "FQty"; // 明细.数量
     public static final String F_UNIT_ID = "FUnitId"; // 明细.单位
+    public static final String F_NO_STOCK_IN_QTY = "FNoStockInQty"; // 明细.未入库数量
 }
diff --git a/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/k3cloud/constants/fileds/K3UnitField.java b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/k3cloud/constants/fileds/K3UnitField.java
new file mode 100644
index 0000000..2e337d6
--- /dev/null
+++ b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/k3cloud/constants/fileds/K3UnitField.java
@@ -0,0 +1,13 @@
+package com.ruoyi.common.k3cloud.constants.fileds;
+
+/**
+ * @author wjh
+ * 2024/11/18
+ */
+public class K3UnitField {
+
+    public static final String F_UNIT_ID = "FUNITID";   // 单位ID
+    public static final String F_NAME = "FName"; // 名称
+    public static final String F_NUMBER = "FNumber"; // 编码
+    public static final String F_FORBID_STATUS = "FForbidStatus"; // 禁用状态
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/common/constants/LogTitle.java b/ruoyi-web/src/main/java/com/ruoyi/common/constants/LogTitle.java
index 951fab5..f5683d2 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/common/constants/LogTitle.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/common/constants/LogTitle.java
@@ -14,4 +14,5 @@ public class LogTitle {
     public static final String LOG_IMPORT = "导入日志";
     public static final String LOG_IMPORT_DETAIL = "导入日志明细";
     public static final String MATERIAL = "物料";
+    public static final String UNIT = "单位";
 }
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/controller/ProdOrderController.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/controller/ProdOrderController.java
index a374884..69cda19 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/controller/ProdOrderController.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/controller/ProdOrderController.java
@@ -3,6 +3,7 @@ package com.ruoyi.web.yh.prodOrder.controller;
 import java.util.List;
 import javax.servlet.http.HttpServletResponse;
 
+import com.ruoyi.common.annotation.DataScope;
 import com.ruoyi.common.constants.LogTitle;
 import com.ruoyi.common.enums.LogBizType;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -51,6 +52,18 @@ public class ProdOrderController extends BaseController
         List<ProdOrderVO> list = prodOrderService.selectProdOrderList(query);
         return getDataTable(list);
     }
+    /**
+     * 查询生产订单列表ByIds
+     */
+    @PreAuthorize("@ss.hasPermi('yh:prodOrder:list')")
+    @PostMapping("/listByIds")
+    public AjaxResult list(@RequestBody List<Long> ids)
+    {
+        ProdOrderQuery query = new ProdOrderQuery();
+        query.setIds(ids);
+        List<ProdOrderVO> list = prodOrderService.selectProdOrderList(query);
+        return success(list);
+    }
 
     /**
      * 导出生产订单列表
@@ -114,4 +127,5 @@ public class ProdOrderController extends BaseController
     public AjaxResult sync() {
         return success(prodOrderService.sync());
     }
+
 }
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/domain/ProdOrder.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/domain/ProdOrder.java
index 18b3043..2fb3827 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/domain/ProdOrder.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/domain/ProdOrder.java
@@ -3,6 +3,8 @@ package com.ruoyi.web.yh.prodOrder.domain;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.util.Date;
+import java.util.List;
+
 import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -88,10 +90,6 @@ public class ProdOrder extends BaseEntity
     @ApiModelProperty("ERP明细数量")
     private BigDecimal erpQty;
 
-    @Excel(name = "部门ID")
-    @ApiModelProperty("部门ID")
-    private Long deptId;
-
     @Excel(name = "ERP明细基本单位数量")
     @ApiModelProperty("ERP明细基本单位数量")
     private BigDecimal erpBaseUnitQty;
@@ -104,5 +102,12 @@ public class ProdOrder extends BaseEntity
     @ApiModelProperty("ERP物料ID")
     private String erpMaterialId;
 
+    @Excel(name = "匹配上的工序单价ID列表")
+    @ApiModelProperty("匹配上的工序单价ID列表")
+    private List<String> matchPrices;
+
+    @Excel(name = "ERP未入库数量")
+    @ApiModelProperty("ERP未入库数量")
+    private BigDecimal erpNoStockInQty;
 
 }
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/domain/ProdOrderQuery.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/domain/ProdOrderQuery.java
index cf346b0..61b473b 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/domain/ProdOrderQuery.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/domain/ProdOrderQuery.java
@@ -3,6 +3,8 @@ package com.ruoyi.web.yh.prodOrder.domain;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.util.List;
+
 /**
  * @author wjh
  * 2024/10/29
@@ -19,5 +21,8 @@ public class ProdOrderQuery extends ProdOrderVO {
     @ApiModelProperty("精准ERP明细ID")
     private String eqErpRowId;
 
+    @ApiModelProperty("订单ID列表")
+    private List<Long> ids;
+
 
 }
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/domain/ProdOrderVO.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/domain/ProdOrderVO.java
index 7cac88a..ab3cf75 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/domain/ProdOrderVO.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/domain/ProdOrderVO.java
@@ -3,6 +3,8 @@ package com.ruoyi.web.yh.prodOrder.domain;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import java.util.List;
+
 /**
  * @author wjh
  * 2024/10/29
@@ -16,4 +18,13 @@ public class ProdOrderVO extends ProdOrder {
     @ApiModelProperty("生产车间名称")
     private String workShopName;
 
+    @ApiModelProperty("单位名称")
+    private String unitName;
+
+    @ApiModelProperty("部门ID")
+    private Long deptId;
+
+    @ApiModelProperty("ERP业务状态列表")
+    private List<String> erpStatusList;
+
 }
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/mapper/ProdOrderMapper.xml b/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/mapper/ProdOrderMapper.xml
index 163a4b8..d83ef25 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/mapper/ProdOrderMapper.xml
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/mapper/ProdOrderMapper.xml
@@ -4,7 +4,9 @@
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.ruoyi.web.yh.prodOrder.mapper.ProdOrderMapper">
 
-    <resultMap type="ProdOrderVO" id="ProdOrderResult" autoMapping="true"/>
+    <resultMap type="ProdOrderVO" id="ProdOrderResult" autoMapping="true">
+        <result property="matchPrices" column="match_prices" typeHandler="com.ruoyi.common.mybatis.typehandler.StringSplitListTypeHandler"/>
+    </resultMap>
 
     <sql id="selectProdOrderVo">
         select
@@ -24,16 +26,20 @@
             bpo.erp_work_shop_id,
             bpo.erp_req_src,
             bpo.erp_qty,
-            bpo.dept_id,
             bpo.erp_base_unit_qty,
             bpo.erp_unit_id,
             bpo.create_time,
             bpo.erp_material_id,
+            bpo.match_prices,
+            bpo.erp_no_stock_in_qty,
             bm.erp_number as material_number,
-            sd.dept_name as work_shop_name
+            sd.dept_name as work_shop_name,
+            sd.dept_id as dept_id,
+            bu.erp_name as unit_name
         from bst_prod_order bpo
-            left join bst_material bm on bm.erp_id = bpo.erp_material_id
             left join sys_dept sd on sd.erp_id = bpo.erp_work_shop_id
+            left join bst_material bm on bm.erp_id = bpo.erp_material_id
+            left join bst_unit bu on bu.erp_id = bpo.erp_unit_id
     </sql>
 
     <sql id="searchCondition">
@@ -51,8 +57,20 @@
         <if test="query.erpStatus != null  and query.erpStatus != ''"> and bpo.erp_status = #{query.erpStatus}</if>
         <if test="query.erpWorkShopId != null  and query.erpWorkShopId != ''"> and bpo.erp_work_shop_id = #{query.erpWorkShopId}</if>
         <if test="query.erpReqSrc != null  and query.erpReqSrc != ''"> and bpo.erp_req_src = #{query.erpReqSrc}</if>
-        <if test="query.deptId != null "> and bpo.dept_id = #{query.deptId}</if>
+        <if test="query.deptId != null "> and sd.dept_id = #{query.deptId}</if>
         <if test="query.erpMaterialId != null and query.erpMaterialId != ''"> and bpo.erp_material_id = #{query.erpMaterialId}</if>
+        <if test="query.erpStatusList != null and query.erpStatusList.size() > 0">
+            and bpo.erp_status in
+            <foreach collection="query.erpStatusList" item="item" open="(" close=")" separator=",">
+                #{item}
+            </foreach>
+        </if>
+        <if test="query.ids != null and query.ids.size() > 0">
+            and bpo.id in
+            <foreach collection="query.ids" item="item" open="(" close=")" separator=",">
+                #{item}
+            </foreach>
+        </if>
         ${query.params.dataScope}
     </sql>
 
@@ -86,11 +104,12 @@
             <if test="erpWorkShopId != null">erp_work_shop_id,</if>
             <if test="erpReqSrc != null">erp_req_src,</if>
             <if test="erpQty != null">erp_qty,</if>
-            <if test="deptId != null">dept_id,</if>
             <if test="erpBaseUnitQty != null">erp_base_unit_qty,</if>
             <if test="erpUnitId != null">erp_unit_id,</if>
             <if test="createTime != null">create_time,</if>
             <if test="erpMaterialId != null">erp_material_id,</if>
+            <if test="matchPrices != null">match_prices,</if>
+            <if test="erpNoStockInQty != null">erp_no_stock_in_qty,</if>
         </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="erpId != null and erpId != ''">#{erpId},</if>
@@ -108,11 +127,12 @@
             <if test="erpWorkShopId != null">#{erpWorkShopId},</if>
             <if test="erpReqSrc != null">#{erpReqSrc},</if>
             <if test="erpQty != null">#{erpQty},</if>
-            <if test="deptId != null">#{deptId},</if>
             <if test="erpBaseUnitQty != null">#{erpBaseUnitQty},</if>
             <if test="erpUnitId != null">#{erpUnitId},</if>
             <if test="createTime != null">#{createTime},</if>
             <if test="erpMaterialId != null">#{erpMaterialId},</if>
+            <if test="matchPrices != null">#{matchPrices,typeHandler=com.ruoyi.common.mybatis.typehandler.StringSplitListTypeHandler},</if>
+            <if test="erpNoStockInQty != null">#{erpNoStockInQty},</if>
         </trim>
     </insert>
 
@@ -140,11 +160,12 @@
         <if test="data.erpWorkShopId != null">erp_work_shop_id = #{data.erpWorkShopId},</if>
         <if test="data.erpReqSrc != null">erp_req_src = #{data.erpReqSrc},</if>
         <if test="data.erpQty != null">erp_qty = #{data.erpQty},</if>
-        <if test="data.deptId != null">dept_id = #{data.deptId},</if>
         <if test="data.erpBaseUnitQty != null">erp_base_unit_qty = #{data.erpBaseUnitQty},</if>
         <if test="data.erpUnitId != null">erp_unit_id = #{data.erpUnitId},</if>
         <if test="data.createTime != null">create_time = #{data.createTime},</if>
         <if test="data.erpMaterialId != null">erp_material_id = #{data.erpMaterialId},</if>
+        <if test="data.matchPrices != null">match_prices = #{data.matchPrices,typeHandler=com.ruoyi.common.mybatis.typehandler.StringSplitListTypeHandler},</if>
+        <if test="data.erpNoStockInQty != null">erp_no_stock_in_qty = #{data.erpNoStockInQty},</if>
     </sql>
 
     <delete id="deleteProdOrderById" parameterType="Long">
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/service/impl/ProdOrderConverterImpl.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/service/impl/ProdOrderConverterImpl.java
index 3473bd8..11aa5cd 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/service/impl/ProdOrderConverterImpl.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/service/impl/ProdOrderConverterImpl.java
@@ -98,6 +98,9 @@ public class ProdOrderConverterImpl implements ProdOrderConverter {
                     case K3ProdField.F_MATERIAL_ID:
                         po.setErpMaterialId(row.getString(i));
                         break;
+                    case K3ProdField.F_NO_STOCK_IN_QTY:
+                        po.setErpNoStockInQty(row.getBigDecimal(i));
+                        break;
                     default: break;
                 }
             }
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/service/impl/ProdOrderServiceImpl.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/service/impl/ProdOrderServiceImpl.java
index eb7e640..8cd60ab 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/service/impl/ProdOrderServiceImpl.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/prodOrder/service/impl/ProdOrderServiceImpl.java
@@ -7,6 +7,7 @@ import java.util.concurrent.TimeUnit;
 
 import com.alibaba.fastjson2.JSONArray;
 import com.github.pagehelper.PageHelper;
+import com.ruoyi.common.annotation.DataScope;
 import com.ruoyi.common.core.redis.RedisLock;
 import com.ruoyi.common.core.redis.enums.RedisLockKey;
 import com.ruoyi.common.exception.ServiceException;
@@ -71,6 +72,7 @@ public class ProdOrderServiceImpl implements ProdOrderService
      * @return 生产订单
      */
     @Override
+    @DataScope(deptAlias = "sd")
     public List<ProdOrderVO> selectProdOrderList(ProdOrderQuery prodOrder)
     {
         return prodOrderMapper.selectProdOrderList(prodOrder);
@@ -146,7 +148,8 @@ public class ProdOrderServiceImpl implements ProdOrderService
                 K3ProdField.F_BASE_UNIT_QTY,
                 K3ProdField.F_QTY,
                 K3ProdField.F_UNIT_ID,
-                K3ProdField.F_MATERIAL_ID
+                K3ProdField.F_MATERIAL_ID,
+                K3ProdField.F_NO_STOCK_IN_QTY
         );
         int startRow = 0;
         int limit = 10000;
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/report/controller/ReportController.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/report/controller/ReportController.java
index a9b0005..8092ba9 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/report/controller/ReportController.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/report/controller/ReportController.java
@@ -81,13 +81,14 @@ public class ReportController extends BaseController
     @PreAuthorize("@ss.hasPermi('yh:report:query')")
     @GetMapping(value = "/{reportId}")
     public AjaxResult getInfo(@PathVariable("reportId") Long reportId,
-                              @RequestParam(required = false, defaultValue = "true") Boolean needProductList,
-                              @RequestParam(required = false, defaultValue = "true") Boolean needUserProd
+                              @RequestParam(required = false, defaultValue = "false") Boolean needProductList,
+                              @RequestParam(required = false, defaultValue = "false") Boolean needUserProd,
+                              @RequestParam(required = false, defaultValue = "false") Boolean needOrderProd
     ) {
         ReportVO report = reportService.selectReportByReportId(reportId);
         List<ReportVO> list = Collections.singletonList(report);
         if (needProductList) {
-            reportAssembler.assembleProductList(list, needUserProd);  // 拼接产量明细
+            reportAssembler.assembleProductList(list, needUserProd, needOrderProd);  // 拼接产量明细
         }
         return success(report);
     }
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/report/service/ReportAssembler.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/report/service/ReportAssembler.java
index 5581425..41d77f2 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/report/service/ReportAssembler.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/report/service/ReportAssembler.java
@@ -12,9 +12,11 @@ public interface ReportAssembler {
 
     /**
      * 拼接产量数据
-     * @param list 待拼接列表
-     * @param assembleUserProd 是否拼接员工产量
+     *
+     * @param list              待拼接列表
+     * @param assembleUserProd  是否拼接员工产量
+     * @param assembleOrderProd
      */
-    void assembleProductList(List<ReportVO> list, boolean assembleUserProd);
+    void assembleProductList(List<ReportVO> list, boolean assembleUserProd, boolean assembleOrderProd);
 
 }
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/report/service/impl/ReportAssemblerImpl.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/report/service/impl/ReportAssemblerImpl.java
index 1fbe950..89533fe 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/report/service/impl/ReportAssemblerImpl.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/report/service/impl/ReportAssemblerImpl.java
@@ -6,6 +6,7 @@ import com.ruoyi.web.yh.report.service.ReportAssembler;
 import com.ruoyi.web.yh.report.service.ReportService;
 import com.ruoyi.web.yh.reportProd.domain.ReportProdQuery;
 import com.ruoyi.web.yh.reportProd.domain.ReportProdVO;
+import com.ruoyi.web.yh.reportProd.service.ReportProdAssembler;
 import com.ruoyi.web.yh.reportProd.service.ReportProdService;
 import com.ruoyi.web.yh.reportUserProd.service.ReportUserProdAssembler;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -32,8 +33,11 @@ public class ReportAssemblerImpl implements ReportAssembler {
     @Autowired
     private ReportUserProdAssembler reportUserProdAssembler;
 
+    @Autowired
+    private ReportProdAssembler reportProdAssembler;
+
     @Override
-    public void assembleProductList(List<ReportVO> list, boolean assembleUserProd) {
+    public void assembleProductList(List<ReportVO> list, boolean assembleUserProd, boolean assembleOrderProd) {
         if (CollectionUtils.isEmptyElement(list)) {
             return;
         }
@@ -44,7 +48,11 @@ public class ReportAssemblerImpl implements ReportAssembler {
 
         // 拼接员工产量
         if (assembleUserProd) {
-            reportUserProdAssembler.assembleUserProd(prodList);
+            reportProdAssembler.assembleUserProdList(prodList);
+        }
+        // 拼接订单产量
+        if (assembleOrderProd) {
+            reportProdAssembler.assembleOrderProdList(prodList);
         }
 
         // 分组
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/report/service/impl/ReportServiceImpl.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/report/service/impl/ReportServiceImpl.java
index c3bb809..5529b0d 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/report/service/impl/ReportServiceImpl.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/report/service/impl/ReportServiceImpl.java
@@ -15,6 +15,10 @@ import com.ruoyi.web.yh.report.domain.bo.ReportBO;
 import com.ruoyi.web.yh.report.domain.dto.ReportVerifyDTO;
 import com.ruoyi.web.yh.report.domain.enums.ReportStatus;
 import com.ruoyi.web.yh.report.service.ReportValidator;
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProd;
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdVO;
+import com.ruoyi.web.yh.reportOrderProd.domain.bo.ReportOrderProdBO;
+import com.ruoyi.web.yh.reportOrderProd.service.IReportOrderProdService;
 import com.ruoyi.web.yh.reportProd.domain.ReportProd;
 import com.ruoyi.web.yh.reportProd.domain.ReportProdVO;
 import com.ruoyi.web.yh.reportProd.domain.bo.ReportProdBO;
@@ -53,6 +57,9 @@ public class ReportServiceImpl implements ReportService
     @Autowired
     private ReportUserProdService reportUserProdService;
 
+    @Autowired
+    private IReportOrderProdService reportOrderProdService;
+
     @Autowired
     private ISysUserService userService;
 
@@ -154,12 +161,65 @@ public class ReportServiceImpl implements ReportService
             // 更新员工产量表
             this.batchUpdateUserProductList(bo);
 
+            // 更新订单产量表
+            this.batchUpdateOrderProductList(bo);
+
             return insert;
         });
 
         return result == null ? 0 : result;
     }
 
+    /**
+     * 更新订单产量表
+     */
+    private int batchUpdateOrderProductList(ReportBO bo) {
+        if (bo == null || bo.getReportId() == null || CollectionUtils.isEmptyElement(bo.getProductList())) {
+            return 0;
+        }
+        // 设置总产量ID
+        for (ReportProdBO prod : bo.getProductList()) {
+            if (prod.getUserProdList() == null) {
+                continue;
+            }
+            for (ReportOrderProdBO userProd : prod.getOrderProdList()) {
+                userProd.setReportProdId(prod.getId());
+            }
+        }
+
+        // 扁平化,获取列表
+        List<ReportOrderProdBO> newList = bo.getProductList().stream()
+                .map(ReportProdBO::getOrderProdList)
+                .flatMap(List::stream)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+
+        // 查询旧列表
+        List<ReportOrderProdVO> oldList = reportOrderProdService.selectListByReportId(bo.getReportId());
+
+        // 获取差异
+        DiffListVO<ReportOrderProdBO, ReportOrderProdVO> diff = CollectionUtils.convertToDiffList(newList, oldList, ReportOrderProd::getId);
+
+        int result = 0;
+        if (diff.getAddCount() > 0) {
+            int insert = reportOrderProdService.batchInsert(diff.getAddList());
+            ServiceUtil.assertion(insert != diff.getAddCount(), "新增订单产量明细失败");
+            result += insert;
+        }
+        if (diff.getUpdateCount() > 0) {
+            int update = reportOrderProdService.batchUpdate(diff.getUpdateList());
+            ServiceUtil.assertion(update != diff.getUpdateCount(), "修改订单产量明细失败");
+            result += update;
+        }
+        if (diff.getDelCount() > 0) {
+            int del = reportOrderProdService.batchLogicDel(diff.getDelList());
+            ServiceUtil.assertion(del != diff.getDelCount(), "删除订单产量明细失败");
+            result += del;
+        }
+
+        return result;
+    }
+
     /**
      * 更新员工产量表
      * @param bo
@@ -228,6 +288,9 @@ public class ReportServiceImpl implements ReportService
             // 修改员工产量表
             this.batchUpdateUserProductList(bo);
 
+            // 修改订单产量表
+            this.batchUpdateOrderProductList(bo);
+
             return update;
         });
 
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/controller/ReportOrderProdController.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/controller/ReportOrderProdController.java
new file mode 100644
index 0000000..5a6eebd
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/controller/ReportOrderProdController.java
@@ -0,0 +1,107 @@
+package com.ruoyi.web.yh.reportOrderProd.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProd;
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdVO;
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdQuery;
+import com.ruoyi.web.yh.reportOrderProd.service.IReportOrderProdService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 订单产量Controller
+ *
+ * @author ruoyi
+ * @date 2024-11-19
+ */
+@RestController
+@RequestMapping("/yh/reportOrderProd")
+public class ReportOrderProdController extends BaseController
+{
+    @Autowired
+    private IReportOrderProdService reportOrderProdService;
+
+    /**
+     * 查询订单产量列表
+     */
+    @PreAuthorize("@ss.hasPermi('yh:reportOrderProd:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(ReportOrderProdQuery query)
+    {
+        startPage();
+        startOrderBy();
+        List<ReportOrderProdVO> list = reportOrderProdService.selectReportOrderProdList(query);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出订单产量列表
+     */
+    @PreAuthorize("@ss.hasPermi('yh:reportOrderProd:export')")
+    @Log(title = "订单产量", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, ReportOrderProdQuery query)
+    {
+        List<ReportOrderProdVO> list = reportOrderProdService.selectReportOrderProdList(query);
+        ExcelUtil<ReportOrderProdVO> util = new ExcelUtil<ReportOrderProdVO>(ReportOrderProdVO.class);
+        util.exportExcel(response, list, "订单产量数据");
+    }
+
+    /**
+     * 获取订单产量详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('yh:reportOrderProd:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(reportOrderProdService.selectReportOrderProdById(id));
+    }
+
+    /**
+     * 新增订单产量
+     */
+    @PreAuthorize("@ss.hasPermi('yh:reportOrderProd:add')")
+    @Log(title = "订单产量", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody ReportOrderProd reportOrderProd)
+    {
+        return toAjax(reportOrderProdService.insertReportOrderProd(reportOrderProd));
+    }
+
+    /**
+     * 修改订单产量
+     */
+    @PreAuthorize("@ss.hasPermi('yh:reportOrderProd:edit')")
+    @Log(title = "订单产量", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody ReportOrderProd reportOrderProd)
+    {
+        return toAjax(reportOrderProdService.updateReportOrderProd(reportOrderProd));
+    }
+
+    /**
+     * 删除订单产量
+     */
+    @PreAuthorize("@ss.hasPermi('yh:reportOrderProd:remove')")
+    @Log(title = "订单产量", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(reportOrderProdService.deleteReportOrderProdByIds(ids));
+    }
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/domain/ReportOrderProd.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/domain/ReportOrderProd.java
new file mode 100644
index 0000000..343787a
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/domain/ReportOrderProd.java
@@ -0,0 +1,44 @@
+package com.ruoyi.web.yh.reportOrderProd.domain;
+
+import java.math.BigDecimal;
+
+import com.ruoyi.common.core.validate.ValidGroup;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+
+/**
+ * 订单产量对象 bst_report_order_prod
+ *
+ * @author ruoyi
+ * @date 2024-11-19
+ */
+@Data
+public class ReportOrderProd extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    private Long id;
+
+    @Excel(name = "报表产量ID")
+    @ApiModelProperty("报表产量ID")
+    private Long reportProdId;
+
+    @Excel(name = "生产订单ID")
+    @ApiModelProperty("生产订单ID")
+    @NotNull(message = "生产订单不允许为空", groups = {ValidGroup.Create.class})
+    private Long orderId;
+
+    @Excel(name = "生产数量")
+    @ApiModelProperty("生产数量")
+    @NotNull(message = "生产数量不允许为空", groups = {ValidGroup.Create.class})
+    @Min(value = 0, message = "生产数量不允许小于0")
+    private BigDecimal num;
+
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/domain/ReportOrderProdQuery.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/domain/ReportOrderProdQuery.java
new file mode 100644
index 0000000..499567d
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/domain/ReportOrderProdQuery.java
@@ -0,0 +1,18 @@
+package com.ruoyi.web.yh.reportOrderProd.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author wjh
+ * 2024/11/19
+ */
+@Data
+public class ReportOrderProdQuery extends ReportOrderProdVO {
+
+    @ApiModelProperty("报表产量ID列表")
+    private List<Long> reportProdIds;
+
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/domain/ReportOrderProdVO.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/domain/ReportOrderProdVO.java
new file mode 100644
index 0000000..c1cf649
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/domain/ReportOrderProdVO.java
@@ -0,0 +1,27 @@
+package com.ruoyi.web.yh.reportOrderProd.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @author wjh
+ * 2024/11/19
+ */
+@Data
+public class ReportOrderProdVO extends ReportOrderProd {
+
+    @ApiModelProperty("报表ID")
+    private Long reportId;
+
+    @ApiModelProperty("订单编号")
+    private String orderErpBillNo;
+
+    @ApiModelProperty("订单数量")
+    private BigDecimal orderErpQty;
+
+    @ApiModelProperty("订单未入库数量")
+    private BigDecimal orderErpNoStockInQty;
+
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/domain/bo/ReportOrderProdBO.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/domain/bo/ReportOrderProdBO.java
new file mode 100644
index 0000000..be077d0
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/domain/bo/ReportOrderProdBO.java
@@ -0,0 +1,12 @@
+package com.ruoyi.web.yh.reportOrderProd.domain.bo;
+
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProd;
+import lombok.Data;
+
+/**
+ * @author wjh
+ * 2024/11/19
+ */
+@Data
+public class ReportOrderProdBO extends ReportOrderProd {
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/mapper/ReportOrderProdMapper.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/mapper/ReportOrderProdMapper.java
new file mode 100644
index 0000000..790b818
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/mapper/ReportOrderProdMapper.java
@@ -0,0 +1,79 @@
+package com.ruoyi.web.yh.reportOrderProd.mapper;
+
+import java.util.List;
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProd;
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdVO;
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdQuery;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 订单产量Mapper接口
+ *
+ * @author ruoyi
+ * @date 2024-11-19
+ */
+public interface ReportOrderProdMapper
+{
+    /**
+     * 查询订单产量
+     *
+     * @param id 订单产量主键
+     * @return 订单产量
+     */
+    public ReportOrderProdVO selectReportOrderProdById(Long id);
+
+    /**
+     * 查询订单产量列表
+     *
+     * @param query 订单产量
+     * @return 订单产量集合
+     */
+    public List<ReportOrderProdVO> selectReportOrderProdList(@Param("query")ReportOrderProdQuery query);
+
+    /**
+     * 新增订单产量
+     *
+     * @param reportOrderProd 订单产量
+     * @return 结果
+     */
+    public int insertReportOrderProd(ReportOrderProd reportOrderProd);
+
+    /**
+     * 修改订单产量
+     *
+     * @param reportOrderProd 订单产量
+     * @return 结果
+     */
+    public int updateReportOrderProd(@Param("data") ReportOrderProd reportOrderProd);
+
+    /**
+     * 删除订单产量
+     *
+     * @param id 订单产量主键
+     * @return 结果
+     */
+    public int deleteReportOrderProdById(Long id);
+
+    /**
+     * 批量删除订单产量
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    public int deleteReportOrderProdByIds(Long[] ids);
+
+    /**
+     * 批量新增
+     */
+    int batchInsert(@Param("list") List<? extends ReportOrderProd> list);
+
+    /**
+     * 批量修改
+     */
+    int batchUpdate(@Param("list") List<? extends ReportOrderProd> list);
+
+    /**
+     * 批量逻辑删除
+     */
+    int batchLogicDel(@Param("ids") List<Long> ids);
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/mapper/ReportOrderProdMapper.xml b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/mapper/ReportOrderProdMapper.xml
new file mode 100644
index 0000000..d2f37aa
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/mapper/ReportOrderProdMapper.xml
@@ -0,0 +1,161 @@
+<?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.web.yh.reportOrderProd.mapper.ReportOrderProdMapper">
+
+    <resultMap type="ReportOrderProdVO" id="ReportOrderProdResult" autoMapping="true"/>
+
+    <sql id="selectReportOrderProdVo">
+        select
+            brop.id,
+            brop.report_prod_id,
+            brop.order_id,
+            brop.num,
+            brop.deleted,
+            brp.report_id as report_id,
+            bpo.erp_bill_no as order_erp_bill_no,
+            bpo.erp_qty as order_erp_qty,
+            bpo.erp_no_stock_in_qty as order_erp_no_stock_in_qty
+        from bst_report_order_prod brop
+            left join bst_report_prod brp on brp.id = brop.report_prod_id
+            left join bst_prod_order bpo on bpo.id = brop.order_id
+    </sql>
+
+    <sql id="searchCondition">
+        <if test="query.id != null "> and brop.id = #{query.id}</if>
+        <if test="query.reportProdId != null "> and brop.report_prod_id = #{query.reportProdId}</if>
+        <if test="query.orderId != null "> and brop.order_id = #{query.orderId}</if>
+        <if test="query.reportId != null "> and brp.report_id = #{query.reportId}</if>
+        <if test="query.deleted == null "> and brop.deleted = false</if>
+        <if test="query.deleted != null "> and brop.deleted = #{query.deleted}</if>
+        <if test="query.reportProdIds != null and query.reportProdIds.size() > 0">
+            and brop.report_prod_id in
+            <foreach collection="query.reportProdIds" item="item" open="(" separator="," close=")">
+                #{item}
+            </foreach>
+        </if>
+        ${query.params.dataScope}
+    </sql>
+
+    <select id="selectReportOrderProdList" parameterType="ReportOrderProdQuery" resultMap="ReportOrderProdResult">
+        <include refid="selectReportOrderProdVo"/>
+        <where>
+            <include refid="searchCondition"/>
+        </where>
+    </select>
+
+    <select id="selectReportOrderProdById" parameterType="Long" resultMap="ReportOrderProdResult">
+        <include refid="selectReportOrderProdVo"/>
+        where brop.id = #{id}
+    </select>
+
+    <insert id="insertReportOrderProd" parameterType="ReportOrderProd" useGeneratedKeys="true" keyProperty="id">
+        insert into bst_report_order_prod
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="reportProdId != null">report_prod_id,</if>
+            <if test="orderId != null">order_id,</if>
+            <if test="num != null">num,</if>
+            <if test="deleted != null">deleted,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="reportProdId != null">#{reportProdId},</if>
+            <if test="orderId != null">#{orderId},</if>
+            <if test="num != null">#{num},</if>
+            <if test="deleted != null">#{deleted},</if>
+         </trim>
+    </insert>
+
+    <insert id="batchInsert">
+        insert into bst_report_order_prod(
+            report_prod_id,
+            order_id,
+            num
+        )
+        values
+        <foreach collection="list" item="i" separator=",">
+            <trim prefix="(" suffix=")" suffixOverrides=",">
+                <if test="i.reportProdId != null">#{i.reportProdId},</if>
+                <if test="i.reportProdId == null">default,</if>
+                <if test="i.orderId != null">#{i.orderId},</if>
+                <if test="i.orderId == null">default,</if>
+                <if test="i.num != null">#{i.num},</if>
+                <if test="i.num == null">default,</if>
+            </trim>
+        </foreach>
+    </insert>
+
+    <update id="updateReportOrderProd" parameterType="ReportOrderProd">
+        update bst_report_order_prod
+        <trim prefix="SET" suffixOverrides=",">
+            <include refid="updateColumns"/>
+        </trim>
+        where id = #{data.id}
+    </update>
+
+    <sql id="updateColumns">
+        <if test="data.reportProdId != null">report_prod_id = #{data.reportProdId},</if>
+        <if test="data.orderId != null">order_id = #{data.orderId},</if>
+        <if test="data.num != null">num = #{data.num},</if>
+    </sql>
+
+    <update id="batchUpdate">
+        update bst_report_order_prod
+        <trim prefix="SET" suffixOverrides=",">
+            <foreach open="report_prod_id = CASE id" collection="list" item="item" close="END,">
+                <choose>
+                    <when test="item.reportProdId != null">
+                        WHEN #{item.id} THEN #{item.reportProdId}
+                    </when>
+                    <otherwise>
+                        WHEN #{item.id} THEN `report_prod_id`
+                    </otherwise>
+                </choose>
+            </foreach>
+            <foreach open="order_id = CASE id" collection="list" item="item" close="END,">
+                <choose>
+                    <when test="item.orderId != null">
+                        WHEN #{item.id} THEN #{item.orderId}
+                    </when>
+                    <otherwise>
+                        WHEN #{item.id} THEN `order_id`
+                    </otherwise>
+                </choose>
+            </foreach>
+            <foreach open="num = CASE id" collection="list" item="item" close="END,">
+                <choose>
+                    <when test="item.num != null">
+                        WHEN #{item.id} THEN #{item.num}
+                    </when>
+                    <otherwise>
+                        WHEN #{item.id} THEN `num`
+                    </otherwise>
+                </choose>
+            </foreach>
+        </trim>
+        where id in
+        <foreach item="item" collection="list" open="(" separator="," close=")">
+            #{item.id}
+        </foreach>
+    </update>
+
+    <update id="batchLogicDel">
+        update bst_report_order_prod
+        set deleted = true
+        where id in
+        <foreach item="id" collection="ids" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </update>
+
+    <delete id="deleteReportOrderProdById" parameterType="Long">
+        delete from bst_report_order_prod where id = #{id}
+    </delete>
+
+    <delete id="deleteReportOrderProdByIds" parameterType="String">
+        delete from bst_report_order_prod where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/service/IReportOrderProdService.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/service/IReportOrderProdService.java
new file mode 100644
index 0000000..25b7744
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/service/IReportOrderProdService.java
@@ -0,0 +1,81 @@
+package com.ruoyi.web.yh.reportOrderProd.service;
+
+import java.util.List;
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProd;
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdVO;
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdQuery;
+import com.ruoyi.web.yh.reportOrderProd.domain.bo.ReportOrderProdBO;
+
+/**
+ * 订单产量Service接口
+ *
+ * @author ruoyi
+ * @date 2024-11-19
+ */
+public interface IReportOrderProdService
+{
+    /**
+     * 查询订单产量
+     *
+     * @param id 订单产量主键
+     * @return 订单产量
+     */
+    public ReportOrderProdVO selectReportOrderProdById(Long id);
+
+    /**
+     * 查询订单产量列表
+     *
+     * @param reportOrderProd 订单产量
+     * @return 订单产量集合
+     */
+    public List<ReportOrderProdVO> selectReportOrderProdList(ReportOrderProdQuery reportOrderProd);
+
+    /**
+     * 新增订单产量
+     *
+     * @param reportOrderProd 订单产量
+     * @return 结果
+     */
+    public int insertReportOrderProd(ReportOrderProd reportOrderProd);
+
+    /**
+     * 修改订单产量
+     *
+     * @param reportOrderProd 订单产量
+     * @return 结果
+     */
+    public int updateReportOrderProd(ReportOrderProd reportOrderProd);
+
+    /**
+     * 批量删除订单产量
+     *
+     * @param ids 需要删除的订单产量主键集合
+     * @return 结果
+     */
+    public int deleteReportOrderProdByIds(Long[] ids);
+
+    /**
+     * 删除订单产量信息
+     *
+     * @param id 订单产量主键
+     * @return 结果
+     */
+    public int deleteReportOrderProdById(Long id);
+
+    /**
+     * 根据报表ID查询订单产量列表
+     */
+    List<ReportOrderProdVO> selectListByReportId(Long reportId);
+
+    /**
+     * 批量新增
+     */
+    int batchInsert(List<? extends ReportOrderProd> list);
+
+    /**
+     * 批量修改
+     */
+    int batchUpdate(List<? extends ReportOrderProd> list);
+
+    int batchLogicDel(List<? extends ReportOrderProd> list);
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/service/ReportOrderProdConverter.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/service/ReportOrderProdConverter.java
new file mode 100644
index 0000000..6ddde88
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/service/ReportOrderProdConverter.java
@@ -0,0 +1,20 @@
+package com.ruoyi.web.yh.reportOrderProd.service;
+
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdVO;
+import com.ruoyi.web.yh.reportOrderProd.domain.bo.ReportOrderProdBO;
+
+/**
+ * @author wjh
+ * 2024/11/19
+ */
+public interface ReportOrderProdConverter {
+    /**
+     * 创建时 vo -> bo
+     */
+    ReportOrderProdBO toBoByCreate(ReportOrderProdVO vo);
+
+    /**
+     * 修改时 vo -> bo
+     */
+    ReportOrderProdBO toBoByUpdate(ReportOrderProdVO vo);
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/service/impl/ReportOrderProdConverterImpl.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/service/impl/ReportOrderProdConverterImpl.java
new file mode 100644
index 0000000..8270d89
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/service/impl/ReportOrderProdConverterImpl.java
@@ -0,0 +1,36 @@
+package com.ruoyi.web.yh.reportOrderProd.service.impl;
+
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdVO;
+import com.ruoyi.web.yh.reportOrderProd.domain.bo.ReportOrderProdBO;
+import com.ruoyi.web.yh.reportOrderProd.service.ReportOrderProdConverter;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author wjh
+ * 2024/11/19
+ */
+@Service
+public class ReportOrderProdConverterImpl implements ReportOrderProdConverter {
+    @Override
+    public ReportOrderProdBO toBoByCreate(ReportOrderProdVO vo) {
+        if (vo == null) {
+            return null;
+        }
+        ReportOrderProdBO bo = new ReportOrderProdBO();
+        bo.setOrderId(vo.getOrderId());
+        bo.setNum(vo.getNum());
+        return bo;
+    }
+
+    @Override
+    public ReportOrderProdBO toBoByUpdate(ReportOrderProdVO vo) {
+        if (vo == null) {
+            return null;
+        }
+        ReportOrderProdBO bo = new ReportOrderProdBO();
+        bo.setId(vo.getId());
+        bo.setOrderId(vo.getOrderId());
+        bo.setNum(vo.getNum());
+        return bo;
+    }
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/service/impl/ReportOrderProdServiceImpl.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/service/impl/ReportOrderProdServiceImpl.java
new file mode 100644
index 0000000..3daad67
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportOrderProd/service/impl/ReportOrderProdServiceImpl.java
@@ -0,0 +1,133 @@
+package com.ruoyi.web.yh.reportOrderProd.service.impl;
+
+import java.util.Collections;
+import java.util.List;
+
+import com.ruoyi.common.utils.collection.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.web.yh.reportOrderProd.mapper.ReportOrderProdMapper;
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProd;
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdVO;
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdQuery;
+import com.ruoyi.web.yh.reportOrderProd.service.IReportOrderProdService;
+
+/**
+ * 订单产量Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2024-11-19
+ */
+@Service
+public class ReportOrderProdServiceImpl implements IReportOrderProdService
+{
+    @Autowired
+    private ReportOrderProdMapper reportOrderProdMapper;
+
+    /**
+     * 查询订单产量
+     *
+     * @param id 订单产量主键
+     * @return 订单产量
+     */
+    @Override
+    public ReportOrderProdVO selectReportOrderProdById(Long id)
+    {
+        return reportOrderProdMapper.selectReportOrderProdById(id);
+    }
+
+    /**
+     * 查询订单产量列表
+     *
+     * @param reportOrderProd 订单产量
+     * @return 订单产量
+     */
+    @Override
+    public List<ReportOrderProdVO> selectReportOrderProdList(ReportOrderProdQuery reportOrderProd)
+    {
+        return reportOrderProdMapper.selectReportOrderProdList(reportOrderProd);
+    }
+
+    /**
+     * 新增订单产量
+     *
+     * @param reportOrderProd 订单产量
+     * @return 结果
+     */
+    @Override
+    public int insertReportOrderProd(ReportOrderProd reportOrderProd)
+    {
+        return reportOrderProdMapper.insertReportOrderProd(reportOrderProd);
+    }
+
+    /**
+     * 修改订单产量
+     *
+     * @param reportOrderProd 订单产量
+     * @return 结果
+     */
+    @Override
+    public int updateReportOrderProd(ReportOrderProd reportOrderProd)
+    {
+        return reportOrderProdMapper.updateReportOrderProd(reportOrderProd);
+    }
+
+    /**
+     * 批量删除订单产量
+     *
+     * @param ids 需要删除的订单产量主键
+     * @return 结果
+     */
+    @Override
+    public int deleteReportOrderProdByIds(Long[] ids)
+    {
+        return reportOrderProdMapper.deleteReportOrderProdByIds(ids);
+    }
+
+    /**
+     * 删除订单产量信息
+     *
+     * @param id 订单产量主键
+     * @return 结果
+     */
+    @Override
+    public int deleteReportOrderProdById(Long id)
+    {
+        return reportOrderProdMapper.deleteReportOrderProdById(id);
+    }
+
+    @Override
+    public List<ReportOrderProdVO> selectListByReportId(Long reportId) {
+        if (reportId == null) {
+            return null;
+        }
+        ReportOrderProdQuery query = new ReportOrderProdQuery();
+        query.setReportId(reportId);
+        return this.selectReportOrderProdList(query);
+    }
+
+    @Override
+    public int batchInsert(List<? extends ReportOrderProd> list) {
+        if (CollectionUtils.isEmptyElement(list)) {
+            return 0;
+        }
+        return reportOrderProdMapper.batchInsert(list);
+    }
+
+    @Override
+    public int batchUpdate(List<? extends ReportOrderProd> list) {
+        if (CollectionUtils.isEmptyElement(list)) {
+            return 0;
+        }
+        return reportOrderProdMapper.batchUpdate(list);
+    }
+
+    @Override
+    public int batchLogicDel(List<? extends ReportOrderProd> list) {
+        if (CollectionUtils.isEmptyElement(list)) {
+            return 0;
+        }
+        List<Long> ids = CollectionUtils.map(list, ReportOrderProd::getId);
+        return reportOrderProdMapper.batchLogicDel(ids);
+    }
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/controller/ReportProdController.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/controller/ReportProdController.java
index f038c12..635e068 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/controller/ReportProdController.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/controller/ReportProdController.java
@@ -2,6 +2,8 @@ package com.ruoyi.web.yh.reportProd.controller;
 
 import java.util.List;
 import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.web.yh.reportProd.service.ReportProdAssembler;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -36,6 +38,9 @@ public class ReportProdController extends BaseController
     @Autowired
     private ReportProdService reportProdService;
 
+    @Autowired
+    private ReportProdAssembler reportProdAssembler;
+
     /**
      * 查询报表产量列表
      */
@@ -46,6 +51,8 @@ public class ReportProdController extends BaseController
         startPage();
         startOrderBy();
         List<ReportProdVO> list = reportProdService.selectReportProdList(query);
+        reportProdAssembler.assembleUserProdList(list);
+        reportProdAssembler.assembleOrderProdList(list);
         return getDataTable(list);
     }
 
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/domain/ReportProdVO.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/domain/ReportProdVO.java
index 8c9edd5..f8ff355 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/domain/ReportProdVO.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/domain/ReportProdVO.java
@@ -1,5 +1,6 @@
 package com.ruoyi.web.yh.reportProd.domain;
 
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdVO;
 import com.ruoyi.web.yh.reportUserProd.domain.ReportUserProdVO;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
@@ -17,4 +18,8 @@ public class ReportProdVO extends ReportProd {
     @ApiModelProperty("员工产量列表")
     @Valid
     private List<ReportUserProdVO> userProdList;
+
+    @ApiModelProperty("订单产量列表")
+    @Valid
+    private List<ReportOrderProdVO> orderProdList;
 }
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/domain/bo/ReportProdBO.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/domain/bo/ReportProdBO.java
index c78c194..5d6d1b2 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/domain/bo/ReportProdBO.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/domain/bo/ReportProdBO.java
@@ -1,5 +1,6 @@
 package com.ruoyi.web.yh.reportProd.domain.bo;
 
+import com.ruoyi.web.yh.reportOrderProd.domain.bo.ReportOrderProdBO;
 import com.ruoyi.web.yh.reportProd.domain.ReportProd;
 import com.ruoyi.web.yh.reportUserProd.domain.bo.ReportUserProdBO;
 import lombok.Data;
@@ -17,4 +18,7 @@ public class ReportProdBO extends ReportProd {
     // 员工产量列表
     private List<ReportUserProdBO> userProdList;
 
+    // 订单产量列表
+    private List<ReportOrderProdBO> orderProdList;
+
 }
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/ReportProdAssembler.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/ReportProdAssembler.java
new file mode 100644
index 0000000..a280970
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/ReportProdAssembler.java
@@ -0,0 +1,22 @@
+package com.ruoyi.web.yh.reportProd.service;
+
+import com.ruoyi.web.yh.reportProd.domain.ReportProdVO;
+
+import java.util.List;
+
+/**
+ * @author wjh
+ * 2024/11/18
+ */
+public interface ReportProdAssembler {
+
+    /**
+     * 拼接员工产量列表
+     */
+    void assembleUserProdList(List<ReportProdVO> list);
+
+    /**
+     * 拼接订单产量列表
+     */
+    void assembleOrderProdList(List<ReportProdVO> list);
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/ReportProdService.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/ReportProdService.java
index f7a0325..a09717c 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/ReportProdService.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/ReportProdService.java
@@ -1,6 +1,8 @@
 package com.ruoyi.web.yh.reportProd.service;
 
 import java.util.List;
+
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdVO;
 import com.ruoyi.web.yh.reportProd.domain.ReportProd;
 import com.ruoyi.web.yh.reportProd.domain.ReportProdVO;
 import com.ruoyi.web.yh.reportProd.domain.ReportProdQuery;
@@ -85,4 +87,5 @@ public interface ReportProdService
      * 批量逻辑删除
      */
     int batchLogicDel(List<ReportProdVO> list);
+
 }
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/impl/ReportProdAssemblerImpl.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/impl/ReportProdAssemblerImpl.java
new file mode 100644
index 0000000..48405ff
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/impl/ReportProdAssemblerImpl.java
@@ -0,0 +1,73 @@
+package com.ruoyi.web.yh.reportProd.service.impl;
+
+import com.ruoyi.common.utils.collection.CollectionUtils;
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdQuery;
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdVO;
+import com.ruoyi.web.yh.reportOrderProd.service.IReportOrderProdService;
+import com.ruoyi.web.yh.reportProd.domain.ReportProdVO;
+import com.ruoyi.web.yh.reportProd.service.ReportProdAssembler;
+import com.ruoyi.web.yh.reportUserProd.domain.ReportUserProdQuery;
+import com.ruoyi.web.yh.reportUserProd.domain.ReportUserProdVO;
+import com.ruoyi.web.yh.reportUserProd.service.ReportUserProdService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author wjh
+ * 2024/11/18
+ */
+@Service
+public class ReportProdAssemblerImpl implements ReportProdAssembler {
+
+    @Autowired
+    private ReportUserProdService reportUserProdService;
+
+    @Autowired
+    private IReportOrderProdService reportOrderProdService;
+
+    @Override
+    public void assembleUserProdList(List<ReportProdVO> list) {
+        if (CollectionUtils.isEmptyElement(list)) {
+            return;
+        }
+
+        ReportUserProdQuery query = new ReportUserProdQuery();
+        query.setProdIds(CollectionUtils.map(list, ReportProdVO::getId));
+        Map<Long, List<ReportUserProdVO>> group = reportUserProdService.selectReportUserProdList(query)
+                .stream().collect(Collectors.groupingBy(ReportUserProdVO::getProdId));
+
+        for (ReportProdVO prod : list) {
+            List<ReportUserProdVO> userProdList = group.get(prod.getId());
+            if (userProdList == null) {
+                userProdList = new ArrayList<>();
+            }
+            prod.setUserProdList(userProdList);
+        }
+    }
+
+    @Override
+    public void assembleOrderProdList(List<ReportProdVO> list) {
+        if (CollectionUtils.isEmptyElement(list)) {
+            return;
+        }
+
+        ReportOrderProdQuery query = new ReportOrderProdQuery();
+        query.setReportProdIds(CollectionUtils.map(list, ReportProdVO::getId));
+        Map<Long, List<ReportOrderProdVO>> group = reportOrderProdService.selectReportOrderProdList(query)
+                .stream().collect(Collectors.groupingBy(ReportOrderProdVO::getReportProdId));
+
+        for (ReportProdVO prod : list) {
+            List<ReportOrderProdVO> orderProdList = group.get(prod.getId());
+            if (orderProdList == null) {
+                orderProdList = new ArrayList<>();
+            }
+            prod.setOrderProdList(orderProdList);
+        }
+
+    }
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/impl/ReportProdConverterImpl.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/impl/ReportProdConverterImpl.java
index ee79b22..a35a5dd 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/impl/ReportProdConverterImpl.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/impl/ReportProdConverterImpl.java
@@ -1,5 +1,8 @@
 package com.ruoyi.web.yh.reportProd.service.impl;
 
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdVO;
+import com.ruoyi.web.yh.reportOrderProd.domain.bo.ReportOrderProdBO;
+import com.ruoyi.web.yh.reportOrderProd.service.ReportOrderProdConverter;
 import com.ruoyi.web.yh.reportProd.domain.ReportProdVO;
 import com.ruoyi.web.yh.reportProd.domain.bo.ReportProdBO;
 import com.ruoyi.web.yh.reportProd.service.ReportProdConverter;
@@ -23,6 +26,9 @@ public class ReportProdConverterImpl implements ReportProdConverter {
     @Autowired
     private ReportUserProdConverter reportUserProdConverter;
 
+    @Autowired
+    private ReportOrderProdConverter reportOrderProdConverter;
+
     @Override
     public ReportProdBO toBoByCreate(ReportProdVO vo) {
         if (vo == null) {
@@ -55,6 +61,16 @@ public class ReportProdConverterImpl implements ReportProdConverter {
         }
         bo.setUserProdList(userProdList);
 
+        // 订单产量明细
+        List<ReportOrderProdBO> orderProdList = new ArrayList<>();
+        if (CollectionUtils.isNotEmpty(vo.getOrderProdList())) {
+            for (ReportOrderProdVO item : vo.getOrderProdList()) {
+                ReportOrderProdBO orderProd = reportOrderProdConverter.toBoByCreate(item);
+                orderProdList.add(orderProd);
+            }
+        }
+        bo.setOrderProdList(orderProdList);
+
         return bo;
     }
 
@@ -92,6 +108,17 @@ public class ReportProdConverterImpl implements ReportProdConverter {
         }
         bo.setUserProdList(userProdList);
 
+        // 订单产量明细
+        List<ReportOrderProdBO> orderProdList = new ArrayList<>();
+        if (CollectionUtils.isNotEmpty(vo.getOrderProdList())) {
+            for (ReportOrderProdVO item : vo.getOrderProdList()) {
+                ReportOrderProdBO orderProd = reportOrderProdConverter.toBoByUpdate(item);
+                orderProdList.add(orderProd);
+            }
+        }
+        bo.setOrderProdList(orderProdList);
+
+
         return bo;
     }
 }
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/impl/ReportProdServiceImpl.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/impl/ReportProdServiceImpl.java
index 209b613..be9e167 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/impl/ReportProdServiceImpl.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportProd/service/impl/ReportProdServiceImpl.java
@@ -7,6 +7,7 @@ import java.util.stream.Collectors;
 
 import com.ruoyi.common.utils.ServiceUtil;
 import com.ruoyi.common.utils.collection.CollectionUtils;
+import com.ruoyi.web.yh.reportOrderProd.domain.ReportOrderProdVO;
 import com.ruoyi.web.yh.reportProd.domain.bo.ReportProdBO;
 import com.ruoyi.web.yh.reportUserProd.domain.bo.ReportUserProdBO;
 import com.ruoyi.web.yh.reportUserProd.service.ReportUserProdService;
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportUserProd/service/ReportUserProdAssembler.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportUserProd/service/ReportUserProdAssembler.java
index fcf668d..d6a3fb9 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportUserProd/service/ReportUserProdAssembler.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportUserProd/service/ReportUserProdAssembler.java
@@ -10,8 +10,4 @@ import java.util.List;
  */
 public interface ReportUserProdAssembler {
 
-    /**
-     * 拼接员工产量
-     */
-    void assembleUserProd(List<ReportProdVO> list);
 }
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportUserProd/service/impl/ReportUserProdAssemblerImpl.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportUserProd/service/impl/ReportUserProdAssemblerImpl.java
index 65e0dbe..a7d9a90 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportUserProd/service/impl/ReportUserProdAssemblerImpl.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportUserProd/service/impl/ReportUserProdAssemblerImpl.java
@@ -24,25 +24,4 @@ public class ReportUserProdAssemblerImpl implements ReportUserProdAssembler {
     @Autowired
     private ReportUserProdService reportUserProdService;
 
-    @Override
-    public void assembleUserProd(List<ReportProdVO> list) {
-        if (CollectionUtils.isEmptyElement(list)) {
-            return;
-        }
-
-        ReportUserProdQuery query = new ReportUserProdQuery();
-        query.setProdIds(CollectionUtils.map(list, ReportProdVO::getId));
-        Map<Long, List<ReportUserProdVO>> group = reportUserProdService.selectReportUserProdList(query)
-                .stream().collect(Collectors.groupingBy(ReportUserProdVO::getProdId));
-
-        for (ReportProdVO prod : list) {
-            List<ReportUserProdVO> userProdList = group.get(prod.getId());
-            if (userProdList == null) {
-                prod.setUserProdList(new ArrayList<>());
-            } else {
-                prod.setUserProdList(userProdList);
-            }
-        }
-
-    }
 }
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportUserProd/service/impl/ReportUserProdConverterImpl.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportUserProd/service/impl/ReportUserProdConverterImpl.java
index 62b2059..fe9e0dd 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportUserProd/service/impl/ReportUserProdConverterImpl.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportUserProd/service/impl/ReportUserProdConverterImpl.java
@@ -38,7 +38,6 @@ public class ReportUserProdConverterImpl implements ReportUserProdConverter {
 
         ReportUserProdBO bo = new ReportUserProdBO();
         bo.setId(vo.getId());
-        bo.setProdId(vo.getProdId());
         bo.setUserId(vo.getUserId());
         bo.setNum(vo.getNum());
         return bo;
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportUserProd/service/impl/ReportUserProdServiceImpl.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportUserProd/service/impl/ReportUserProdServiceImpl.java
index 251980a..57efeec 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportUserProd/service/impl/ReportUserProdServiceImpl.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/reportUserProd/service/impl/ReportUserProdServiceImpl.java
@@ -128,7 +128,7 @@ public class ReportUserProdServiceImpl implements ReportUserProdService
         if (CollectionUtils.isEmptyElement(list)) {
             return 0;
         }
-        List<Long> ids = list.stream().map(ReportUserProd::getId).collect(Collectors.toList());
+        List<Long> ids = CollectionUtils.map(list, ReportUserProd::getId);
         return reportUserProdMapper.batchLogicDel(ids);
     }
 }
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/controller/UnitController.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/controller/UnitController.java
new file mode 100644
index 0000000..592be9d
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/controller/UnitController.java
@@ -0,0 +1,123 @@
+package com.ruoyi.web.yh.unit.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.constants.LogTitle;
+import com.ruoyi.common.enums.LogBizType;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.web.yh.unit.domain.Unit;
+import com.ruoyi.web.yh.unit.domain.UnitVO;
+import com.ruoyi.web.yh.unit.domain.UnitQuery;
+import com.ruoyi.web.yh.unit.service.UnitService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 单位Controller
+ *
+ * @author ruoyi
+ * @date 2024-11-18
+ */
+@RestController
+@RequestMapping("/yh/unit")
+public class UnitController extends BaseController
+{
+    @Autowired
+    private UnitService unitService;
+
+    private static final String LOG_TITLE = LogTitle.UNIT;
+
+    /**
+     * 查询单位列表
+     */
+    @PreAuthorize("@ss.hasPermi('yh:unit:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(UnitQuery query)
+    {
+        startPage();
+        startOrderBy();
+        List<UnitVO> list = unitService.selectUnitList(query);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出单位列表
+     */
+    @PreAuthorize("@ss.hasPermi('yh:unit:export')")
+    @Log(title = LOG_TITLE, businessType = BusinessType.EXPORT, bizType = LogBizType.UNIT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, UnitQuery query)
+    {
+        List<UnitVO> list = unitService.selectUnitList(query);
+        ExcelUtil<UnitVO> util = new ExcelUtil<UnitVO>(UnitVO.class);
+        util.exportExcel(response, list, "单位数据");
+    }
+
+    /**
+     * 获取单位详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('yh:unit:query')")
+    @GetMapping(value = "/{unitId}")
+    public AjaxResult getInfo(@PathVariable("unitId") Long unitId)
+    {
+        return success(unitService.selectUnitByUnitId(unitId));
+    }
+
+    /**
+     * 新增单位
+     */
+    @PreAuthorize("@ss.hasPermi('yh:unit:add')")
+    @Log(title = LOG_TITLE, businessType = BusinessType.INSERT, bizType = LogBizType.UNIT, bizIdName = "arg0")
+    @PostMapping
+    public AjaxResult add(@RequestBody Unit unit)
+    {
+        return toAjax(unitService.insertUnit(unit));
+    }
+
+    /**
+     * 修改单位
+     */
+    @PreAuthorize("@ss.hasPermi('yh:unit:edit')")
+    @Log(title = LOG_TITLE, businessType = BusinessType.UPDATE, bizType = LogBizType.UNIT, bizIdName = "arg0")
+    @PutMapping
+    public AjaxResult edit(@RequestBody Unit unit)
+    {
+        return toAjax(unitService.updateUnit(unit));
+    }
+
+    /**
+     * 删除单位
+     */
+    @PreAuthorize("@ss.hasPermi('yh:unit:remove')")
+    @Log(title = LOG_TITLE, businessType = BusinessType.DELETE, bizType = LogBizType.UNIT, bizIdName = "arg0")
+	@DeleteMapping("/{unitIds}")
+    public AjaxResult remove(@PathVariable Long[] unitIds)
+    {
+        return toAjax(unitService.deleteUnitByUnitIds(unitIds));
+    }
+
+    /**
+     * 同步单位
+     */
+    @PreAuthorize("@ss.hasPermi('yh:unit:sync')")
+    @Log(title = LOG_TITLE, businessType = BusinessType.SYNC, bizType = LogBizType.UNIT)
+	@PutMapping("/sync")
+    public AjaxResult sync()
+    {
+        return toAjax(unitService.sync());
+    }
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/domain/Unit.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/domain/Unit.java
new file mode 100644
index 0000000..47389af
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/domain/Unit.java
@@ -0,0 +1,39 @@
+package com.ruoyi.web.yh.unit.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 单位对象 bst_unit
+ *
+ * @author ruoyi
+ * @date 2024-11-18
+ */
+@Data
+public class Unit extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    private Long unitId;
+
+    @Excel(name = "ERP单位ID")
+    @ApiModelProperty("ERP单位ID")
+    private String erpId;
+
+    @Excel(name = "ERP禁用状态", readConverterExp = "A=否,B=是")
+    @ApiModelProperty("ERP禁用状态")
+    private String erpForbidStatus;
+
+    @Excel(name = "ERP名称")
+    @ApiModelProperty("ERP名称")
+    private String erpName;
+
+    @Excel(name = "ERP编码")
+    @ApiModelProperty("ERP编码")
+    private String erpNumber;
+
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/domain/UnitQuery.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/domain/UnitQuery.java
new file mode 100644
index 0000000..e127733
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/domain/UnitQuery.java
@@ -0,0 +1,11 @@
+package com.ruoyi.web.yh.unit.domain;
+
+import lombok.Data;
+
+/**
+ * @author wjh
+ * 2024/11/18
+ */
+@Data
+public class UnitQuery extends UnitVO {
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/domain/UnitVO.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/domain/UnitVO.java
new file mode 100644
index 0000000..caadb4d
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/domain/UnitVO.java
@@ -0,0 +1,11 @@
+package com.ruoyi.web.yh.unit.domain;
+
+import lombok.Data;
+
+/**
+ * @author wjh
+ * 2024/11/18
+ */
+@Data
+public class UnitVO extends Unit {
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/mapper/UnitMapper.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/mapper/UnitMapper.java
new file mode 100644
index 0000000..7a3116b
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/mapper/UnitMapper.java
@@ -0,0 +1,64 @@
+package com.ruoyi.web.yh.unit.mapper;
+
+import java.util.List;
+import com.ruoyi.web.yh.unit.domain.Unit;
+import com.ruoyi.web.yh.unit.domain.UnitVO;
+import com.ruoyi.web.yh.unit.domain.UnitQuery;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 单位Mapper接口
+ *
+ * @author ruoyi
+ * @date 2024-11-18
+ */
+public interface UnitMapper
+{
+    /**
+     * 查询单位
+     *
+     * @param unitId 单位主键
+     * @return 单位
+     */
+    public UnitVO selectUnitByUnitId(Long unitId);
+
+    /**
+     * 查询单位列表
+     *
+     * @param query 单位
+     * @return 单位集合
+     */
+    public List<UnitVO> selectUnitList(@Param("query")UnitQuery query);
+
+    /**
+     * 新增单位
+     *
+     * @param unit 单位
+     * @return 结果
+     */
+    public int insertUnit(Unit unit);
+
+    /**
+     * 修改单位
+     *
+     * @param unit 单位
+     * @return 结果
+     */
+    public int updateUnit(@Param("data") Unit unit);
+
+    /**
+     * 删除单位
+     *
+     * @param unitId 单位主键
+     * @return 结果
+     */
+    public int deleteUnitByUnitId(Long unitId);
+
+    /**
+     * 批量删除单位
+     *
+     * @param unitIds 需要删除的数据主键集合
+     * @return 结果
+     */
+    public int deleteUnitByUnitIds(Long[] unitIds);
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/mapper/UnitMapper.xml b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/mapper/UnitMapper.xml
new file mode 100644
index 0000000..9c76593
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/mapper/UnitMapper.xml
@@ -0,0 +1,81 @@
+<?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.web.yh.unit.mapper.UnitMapper">
+
+    <resultMap type="UnitVO" id="UnitResult" autoMapping="true"/>
+
+    <sql id="selectUnitVo">
+        select
+            bu.unit_id,
+            bu.erp_id,
+            bu.erp_forbid_status,
+            bu.erp_name,
+            bu.erp_number
+        from bst_unit bu
+    </sql>
+
+    <sql id="searchCondition">
+        <if test="query.unitId != null "> and bu.unit_id = #{query.unitId}</if>
+        <if test="query.erpId != null  and query.erpId != ''"> and bu.erp_id = #{query.erpId}</if>
+        <if test="query.erpForbidStatus != null  and query.erpForbidStatus != ''"> and bu.erp_forbid_status = #{query.erpForbidStatus}</if>
+        <if test="query.erpName != null  and query.erpName != ''"> and bu.erp_name like concat('%', #{query.erpName}, '%')</if>
+        <if test="query.erpNumber != null  and query.erpNumber != ''"> and bu.erp_number like concat('%', #{query.erpNumber}, '%')</if>
+        ${query.params.dataScope}
+    </sql>
+
+    <select id="selectUnitList" parameterType="UnitQuery" resultMap="UnitResult">
+        <include refid="selectUnitVo"/>
+        <where>
+            <include refid="searchCondition"/>
+        </where>
+    </select>
+
+    <select id="selectUnitByUnitId" parameterType="Long" resultMap="UnitResult">
+        <include refid="selectUnitVo"/>
+        where bu.unit_id = #{unitId}
+    </select>
+
+    <insert id="insertUnit" parameterType="Unit" useGeneratedKeys="true" keyProperty="unitId">
+        insert into bst_unit
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="erpId != null and erpId != ''">erp_id,</if>
+            <if test="erpForbidStatus != null">erp_forbid_status,</if>
+            <if test="erpName != null">erp_name,</if>
+            <if test="erpNumber != null">erp_number,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="erpId != null and erpId != ''">#{erpId},</if>
+            <if test="erpForbidStatus != null">#{erpForbidStatus},</if>
+            <if test="erpName != null">#{erpName},</if>
+            <if test="erpNumber != null">#{erpNumber},</if>
+         </trim>
+    </insert>
+
+    <update id="updateUnit" parameterType="Unit">
+        update bst_unit
+        <trim prefix="SET" suffixOverrides=",">
+            <include refid="updateColumns"/>
+        </trim>
+        where unit_id = #{data.unitId}
+    </update>
+
+    <sql id="updateColumns">
+        <if test="data.erpId != null and data.erpId != ''">erp_id = #{data.erpId},</if>
+        <if test="data.erpForbidStatus != null">erp_forbid_status = #{data.erpForbidStatus},</if>
+        <if test="data.erpName != null">erp_name = #{data.erpName},</if>
+        <if test="data.erpNumber != null">erp_number = #{data.erpNumber},</if>
+    </sql>
+
+    <delete id="deleteUnitByUnitId" parameterType="Long">
+        delete from bst_unit where unit_id = #{unitId}
+    </delete>
+
+    <delete id="deleteUnitByUnitIds" parameterType="String">
+        delete from bst_unit where unit_id in
+        <foreach item="unitId" collection="array" open="(" separator="," close=")">
+            #{unitId}
+        </foreach>
+    </delete>
+</mapper>
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/service/UnitConverter.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/service/UnitConverter.java
new file mode 100644
index 0000000..d07a116
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/service/UnitConverter.java
@@ -0,0 +1,15 @@
+package com.ruoyi.web.yh.unit.service;
+
+import com.alibaba.fastjson2.JSONArray;
+import com.ruoyi.web.yh.unit.domain.Unit;
+
+import java.util.List;
+
+/**
+ * @author wjh
+ * 2024/11/18
+ */
+public interface UnitConverter {
+
+    List<Unit> toPoByErpList(List<String> headers, List<JSONArray> erpList);
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/service/UnitService.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/service/UnitService.java
new file mode 100644
index 0000000..f349fda
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/service/UnitService.java
@@ -0,0 +1,69 @@
+package com.ruoyi.web.yh.unit.service;
+
+import java.util.List;
+import com.ruoyi.web.yh.unit.domain.Unit;
+import com.ruoyi.web.yh.unit.domain.UnitVO;
+import com.ruoyi.web.yh.unit.domain.UnitQuery;
+
+/**
+ * 单位Service接口
+ *
+ * @author ruoyi
+ * @date 2024-11-18
+ */
+public interface UnitService
+{
+    /**
+     * 查询单位
+     *
+     * @param unitId 单位主键
+     * @return 单位
+     */
+    public UnitVO selectUnitByUnitId(Long unitId);
+
+    /**
+     * 查询单位列表
+     *
+     * @param unit 单位
+     * @return 单位集合
+     */
+    public List<UnitVO> selectUnitList(UnitQuery unit);
+
+    /**
+     * 新增单位
+     *
+     * @param unit 单位
+     * @return 结果
+     */
+    public int insertUnit(Unit unit);
+
+    /**
+     * 修改单位
+     *
+     * @param unit 单位
+     * @return 结果
+     */
+    public int updateUnit(Unit unit);
+
+    /**
+     * 批量删除单位
+     *
+     * @param unitIds 需要删除的单位主键集合
+     * @return 结果
+     */
+    public int deleteUnitByUnitIds(Long[] unitIds);
+
+    /**
+     * 删除单位信息
+     *
+     * @param unitId 单位主键
+     * @return 结果
+     */
+    public int deleteUnitByUnitId(Long unitId);
+
+    /**
+     * 同步ERP单位
+     */
+    int sync();
+
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/service/impl/UnitConverterImpl.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/service/impl/UnitConverterImpl.java
new file mode 100644
index 0000000..be9bb23
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/service/impl/UnitConverterImpl.java
@@ -0,0 +1,55 @@
+package com.ruoyi.web.yh.unit.service.impl;
+
+import com.alibaba.fastjson2.JSONArray;
+import com.ruoyi.common.k3cloud.constants.fileds.K3UnitField;
+import com.ruoyi.common.utils.collection.CollectionUtils;
+import com.ruoyi.web.yh.unit.domain.Unit;
+import com.ruoyi.web.yh.unit.service.UnitConverter;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author wjh
+ * 2024/11/18
+ */
+@Service
+public class UnitConverterImpl implements UnitConverter {
+    @Override
+    public List<Unit> toPoByErpList(List<String> headers, List<JSONArray> erpList) {
+        if (CollectionUtils.isEmpty(headers) || CollectionUtils.isEmpty(erpList)) {
+            return Collections.emptyList();
+        }
+
+        // 创建erpList大小的对象列表
+        List<Unit> result = new ArrayList<>(erpList.size());
+
+        for (JSONArray row : erpList) {
+            Unit po = new Unit();
+            for (int i = 0; i < headers.size(); i++) {
+                String header = headers.get(i);
+                switch (header) {
+                    case K3UnitField.F_UNIT_ID:
+                        po.setErpId(row.getString(i));
+                        break;
+                    case K3UnitField.F_NAME:
+                        po.setErpName(row.getString(i));
+                        break;
+                    case K3UnitField.F_NUMBER:
+                        po.setErpNumber(row.getString(i));
+                        break;
+                    case K3UnitField.F_FORBID_STATUS:
+                        po.setErpForbidStatus(row.getString(i));
+                        break;
+                    default:
+                        break;
+                }
+            }
+            result.add(po);
+        }
+
+        return result;
+    }
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/service/impl/UnitServiceImpl.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/service/impl/UnitServiceImpl.java
new file mode 100644
index 0000000..8ea3620
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/unit/service/impl/UnitServiceImpl.java
@@ -0,0 +1,213 @@
+package com.ruoyi.web.yh.unit.service.impl;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import com.alibaba.fastjson2.JSONArray;
+import com.github.pagehelper.PageHelper;
+import com.ruoyi.common.core.redis.RedisLock;
+import com.ruoyi.common.core.redis.enums.RedisLockKey;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.k3cloud.constants.K3FormIds;
+import com.ruoyi.common.k3cloud.constants.fileds.K3UnitField;
+import com.ruoyi.common.k3cloud.service.K3Service;
+import com.ruoyi.common.utils.ServiceUtil;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.collection.CollectionUtils;
+import com.ruoyi.web.yh.unit.service.UnitConverter;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.web.yh.unit.mapper.UnitMapper;
+import com.ruoyi.web.yh.unit.domain.Unit;
+import com.ruoyi.web.yh.unit.domain.UnitVO;
+import com.ruoyi.web.yh.unit.domain.UnitQuery;
+import com.ruoyi.web.yh.unit.service.UnitService;
+
+/**
+ * 单位Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2024-11-18
+ */
+@Service
+@Slf4j
+public class UnitServiceImpl implements UnitService
+{
+    @Autowired
+    private UnitMapper unitMapper;
+
+    @Autowired
+    private K3Service k3Service;
+
+    @Autowired
+    private UnitConverter unitConverter;
+
+    @Autowired
+    private ScheduledExecutorService scheduledExecutorService;
+
+    @Autowired
+    private RedisLock redisLock;
+
+    /**
+     * 查询单位
+     *
+     * @param unitId 单位主键
+     * @return 单位
+     */
+    @Override
+    public UnitVO selectUnitByUnitId(Long unitId)
+    {
+        return unitMapper.selectUnitByUnitId(unitId);
+    }
+
+    /**
+     * 查询单位列表
+     *
+     * @param unit 单位
+     * @return 单位
+     */
+    @Override
+    public List<UnitVO> selectUnitList(UnitQuery unit)
+    {
+        return unitMapper.selectUnitList(unit);
+    }
+
+    /**
+     * 新增单位
+     *
+     * @param unit 单位
+     * @return 结果
+     */
+    @Override
+    public int insertUnit(Unit unit)
+    {
+        return unitMapper.insertUnit(unit);
+    }
+
+    /**
+     * 修改单位
+     *
+     * @param unit 单位
+     * @return 结果
+     */
+    @Override
+    public int updateUnit(Unit unit)
+    {
+        return unitMapper.updateUnit(unit);
+    }
+
+    /**
+     * 批量删除单位
+     *
+     * @param unitIds 需要删除的单位主键
+     * @return 结果
+     */
+    @Override
+    public int deleteUnitByUnitIds(Long[] unitIds)
+    {
+        return unitMapper.deleteUnitByUnitIds(unitIds);
+    }
+
+    /**
+     * 删除单位信息
+     *
+     * @param unitId 单位主键
+     * @return 结果
+     */
+    @Override
+    public int deleteUnitByUnitId(Long unitId)
+    {
+        return unitMapper.deleteUnitByUnitId(unitId);
+    }
+
+    @Override
+    public int sync() {
+// 查询字段
+        List<String> fieldKeys = Arrays.asList(
+                K3UnitField.F_UNIT_ID,
+                K3UnitField.F_NUMBER,
+                K3UnitField.F_NAME,
+                K3UnitField.F_FORBID_STATUS
+        );
+        int startRow = 0;
+        int limit = 10000;
+        int size = 0;
+
+        // 一直查询,直到查到的数据量比limit小,说明查完了
+        while(true) {
+            // 查询ERP数据
+            List<JSONArray> erpList = k3Service.selectList(K3FormIds.UNIT, fieldKeys, startRow, limit);
+
+            // 转为PO
+            List<Unit> unitList = unitConverter.toPoByErpList(fieldKeys, erpList);
+
+            // 保存
+            for (Unit unit : unitList) {
+                scheduledExecutorService.schedule(() -> {
+                    this.saveByErpId(unit);
+                }, 0, TimeUnit.SECONDS);
+            }
+
+            size += unitList.size();
+
+            if (unitList.size() < limit) {
+                break;
+            } else {
+                startRow += limit;
+            }
+        }
+
+        return size;
+    }
+
+    private int saveByErpId(Unit unit) {
+        String errorMsg = "成功";
+        try {
+            if (unit == null || StringUtils.isBlank(unit.getErpId())) {
+                throw new ServiceException("参数错误");
+            }
+            String lockKey = unit.getErpId();
+            ServiceUtil.assertion(!redisLock.lock(RedisLockKey.SAVE_UNIT, lockKey), "当前单位正在处理中,请稍后重试");
+
+            try {
+                // 若数据库中没有,则新增,否则修改
+                UnitVO old = this.selectUnitByErpId(unit.getErpId());
+                if (old == null) {
+                    return this.insertUnit(unit);
+                } else {
+                    unit.setUnitId(old.getUnitId());
+                    return this.updateUnit(unit);
+                }
+            } finally {
+                redisLock.unlock(RedisLockKey.SAVE_UNIT, lockKey);
+            }
+        } catch (Exception e) {
+            errorMsg = e.getMessage();
+            return 0;
+        } finally {
+            // TODO 记录日志
+            log.info("保存单位:{}",  errorMsg);
+        }
+    }
+
+    private UnitVO selectUnitByErpId(String erpId) {
+        if (StringUtils.isBlank(erpId)) {
+            return null;
+        }
+        UnitQuery query = new UnitQuery();
+        query.setErpId(erpId);
+        return this.selectOne(query);
+    }
+
+    private UnitVO selectOne(UnitQuery query) {
+        PageHelper.startPage(1, 1);
+        List<UnitVO> list = this.selectUnitList(query);
+        if (CollectionUtils.isEmpty(list)) {
+            return null;
+        }
+        return list.get(0);
+    }
+}