From 2495a8e1f71b6a0908a423765aaafd9ae0140d0c Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期三, 11 三月 2026 15:21:53 +0800
Subject: [PATCH] 生成生产订单与生产计划关联表

---
 src/main/java/com/ruoyi/productionPlan/pojo/ProductOrderPlan.java                    |   47 +++++++++++
 src/main/java/com/ruoyi/productionPlan/controller/ProductOrderPlanController.java    |   18 ++++
 src/main/java/com/ruoyi/productionPlan/service/impl/ProductionPlanServiceImpl.java   |   51 +++++++++++-
 src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java         |   12 +++
 src/main/java/com/ruoyi/productionPlan/mapper/ProductOrderPlanMapper.java            |   18 ++++
 src/main/java/com/ruoyi/production/service/ProductOrderService.java                  |    5 +
 src/main/java/com/ruoyi/productionPlan/service/ProductionPlanService.java            |   10 ++
 src/main/java/com/ruoyi/productionPlan/controller/ProductionPlanController.java      |    2 
 src/main/java/com/ruoyi/productionPlan/service/ProductOrderPlanService.java          |   16 ++++
 doc/宁夏-中盛建材.sql                                                                      |   17 +++
 src/main/java/com/ruoyi/production/controller/ProductOrderController.java            |    6 +
 src/main/java/com/ruoyi/production/pojo/ProductionProductMain.java                   |    3 
 src/main/java/com/ruoyi/productionPlan/service/impl/ProductOrderPlanServiceImpl.java |   20 +++++
 src/main/resources/mapper/productionPlan/ProductOrderPlanMapper.xml                  |   14 +++
 14 files changed, 230 insertions(+), 9 deletions(-)

diff --git "a/doc/\345\256\201\345\244\217-\344\270\255\347\233\233\345\273\272\346\235\220.sql" "b/doc/\345\256\201\345\244\217-\344\270\255\347\233\233\345\273\272\346\235\220.sql"
index 0ae95a8..b831f87 100644
--- "a/doc/\345\256\201\345\244\217-\344\270\255\347\233\233\345\273\272\346\235\220.sql"
+++ "b/doc/\345\256\201\345\244\217-\344\270\255\347\233\233\345\273\272\346\235\220.sql"
@@ -92,5 +92,18 @@
     add assigned_quantity DECIMAL(10, 4) default 0 not null COMMENT '涓嬪彂鏁伴噺';
 
 alter table product_order
-    add plan_complete_time datetime(0) NULL DEFAULT NULL COMMENT '璁″垝瀹屾垚鏃堕棿',
-    add combine_production_plan_ids varchar(500) default '鍚堝苟鐢熶骇璁″垝id' not null;
+    add plan_complete_time datetime(0) NULL DEFAULT NULL COMMENT '璁″垝瀹屾垚鏃堕棿';
+
+# 鐢熶骇璁㈠崟涓庣敓浜ц鍒掑叧鑱旇〃
+drop table if exists product_order_plan;
+create table product_order_plan
+(
+    id                       bigint auto_increment primary key,
+    product_order_id bigint not null default 0 comment '鐢熶骇璁㈠崟id',
+    production_plan_id  bigint not null default 0 comment '鐢熶骇璁″垝id',
+    create_time              datetime null comment '褰曞叆鏃堕棿',
+    update_time              datetime null comment '鏇存柊鏃堕棿',
+    index idx_product_order_id (product_order_id),
+    index idx_production_plan_id (production_plan_id),
+    unique idx_product_order_production_plan (product_order_id, production_plan_id)
+);
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/production/controller/ProductOrderController.java b/src/main/java/com/ruoyi/production/controller/ProductOrderController.java
index e1c22d1..5a566a5 100644
--- a/src/main/java/com/ruoyi/production/controller/ProductOrderController.java
+++ b/src/main/java/com/ruoyi/production/controller/ProductOrderController.java
@@ -46,6 +46,12 @@
         return R.ok(productOrderService.listProcessRoute(productModelId));
     }
 
+    @PostMapping("/revoke")
+    @ApiOperation("鎾ゅ洖鐢熶骇璁″垝")
+    public R revoke(@RequestBody ProductOrder productOrder) {
+        return R.ok(productOrderService.revoke(productOrder));
+    }
+
     /**
      * 瀵煎嚭鐢熶骇璁㈠崟
      */
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductionProductMain.java b/src/main/java/com/ruoyi/production/pojo/ProductionProductMain.java
index 2064e04..f02eed1 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductionProductMain.java
+++ b/src/main/java/com/ruoyi/production/pojo/ProductionProductMain.java
@@ -32,6 +32,9 @@
     @ApiModelProperty(value = "宸ュ崟id")
     private Long workOrderId;
 
+    @ApiModelProperty(value = "鐢熶骇璁㈠崟id")
+    private Long productOrderId;
+
     @ApiModelProperty(value = "鎶ュ伐鐘舵��")
     private Integer status;
 
diff --git a/src/main/java/com/ruoyi/production/service/ProductOrderService.java b/src/main/java/com/ruoyi/production/service/ProductOrderService.java
index 5a714a6..7ae2381 100644
--- a/src/main/java/com/ruoyi/production/service/ProductOrderService.java
+++ b/src/main/java/com/ruoyi/production/service/ProductOrderService.java
@@ -18,6 +18,11 @@
 
     int bindingRoute(ProductOrder productOrder);
 
+    /**
+     * 鎾ゅ洖鐢熶骇璁″垝
+     */
+    Boolean revoke(ProductOrder productOrder);
+
     List<ProcessRoute> listProcessRoute(Long productModelId);
 
     List<ProductStructureDto> listProcessBom(Long orderId);
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java
index 8a1099c..95e3f14 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java
@@ -123,6 +123,18 @@
     }
 
     @Override
+    public Boolean revoke(ProductOrder productOrder) {
+        //鍒ゆ柇鏄惁浜х敓宸ュ崟
+        List<ProductionProductMain> productionProductMains = productionProductMainMapper.selectList(Wrappers.<ProductionProductMain>lambdaQuery().eq(ProductionProductMain::getProductOrderId, productOrder.getId()));
+        if (!productionProductMains.isEmpty()) {
+            throw new RuntimeException("鐢熶骇璁㈠崟宸茬粡鎶ュ伐,涓嶈兘鎾ら攢");
+        }
+
+        // 鏌ヨ鍚堝苟鐨勭敓浜ц鍒�
+        return null;
+    }
+
+    @Override
     public List<ProcessRoute> listProcessRoute(Long productModelId) {
         return productOrderMapper.listProcessRoute(productModelId);
     }
diff --git a/src/main/java/com/ruoyi/productionPlan/controller/ProductOrderPlanController.java b/src/main/java/com/ruoyi/productionPlan/controller/ProductOrderPlanController.java
new file mode 100644
index 0000000..a789215
--- /dev/null
+++ b/src/main/java/com/ruoyi/productionPlan/controller/ProductOrderPlanController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.productionPlan.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-11 03:02:58
+ */
+@RestController
+@RequestMapping("/productOrderPlan")
+public class ProductOrderPlanController {
+
+}
diff --git a/src/main/java/com/ruoyi/productionPlan/controller/ProductionPlanController.java b/src/main/java/com/ruoyi/productionPlan/controller/ProductionPlanController.java
index d07b93b..ac5c5ac 100644
--- a/src/main/java/com/ruoyi/productionPlan/controller/ProductionPlanController.java
+++ b/src/main/java/com/ruoyi/productionPlan/controller/ProductionPlanController.java
@@ -67,7 +67,7 @@
     @Log(title = "鏇存柊鐢熶骇璁″垝", businessType = BusinessType.UPDATE)
     @ApiOperation("鏇存柊鐢熶骇璁″垝")
     public AjaxResult update(@RequestBody ProductionPlanDto productionPlanDto) {
-        return AjaxResult.success(productionPlanService.updateById(productionPlanDto));
+        return AjaxResult.success(productionPlanService.update(productionPlanDto));
     }
 
     @DeleteMapping("")
diff --git a/src/main/java/com/ruoyi/productionPlan/mapper/ProductOrderPlanMapper.java b/src/main/java/com/ruoyi/productionPlan/mapper/ProductOrderPlanMapper.java
new file mode 100644
index 0000000..6fae6de
--- /dev/null
+++ b/src/main/java/com/ruoyi/productionPlan/mapper/ProductOrderPlanMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.productionPlan.mapper;
+
+import com.ruoyi.productionPlan.pojo.ProductOrderPlan;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ *  Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-11 03:02:58
+ */
+@Mapper
+public interface ProductOrderPlanMapper extends BaseMapper<ProductOrderPlan> {
+
+}
diff --git a/src/main/java/com/ruoyi/productionPlan/pojo/ProductOrderPlan.java b/src/main/java/com/ruoyi/productionPlan/pojo/ProductOrderPlan.java
new file mode 100644
index 0000000..9088e42
--- /dev/null
+++ b/src/main/java/com/ruoyi/productionPlan/pojo/ProductOrderPlan.java
@@ -0,0 +1,47 @@
+package com.ruoyi.productionPlan.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-11 03:02:58
+ */
+@Getter
+@Setter
+@TableName("product_order_plan")
+@ApiModel(value = "ProductOrderPlan瀵硅薄", description = "")
+public class ProductOrderPlan implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty("鐢熶骇璁㈠崟id")
+    private Long productOrderId;
+
+    @ApiModelProperty("鐢熶骇璁″垝id")
+    private Long productionPlanId;
+
+    @ApiModelProperty("褰曞叆鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+}
diff --git a/src/main/java/com/ruoyi/productionPlan/service/ProductOrderPlanService.java b/src/main/java/com/ruoyi/productionPlan/service/ProductOrderPlanService.java
new file mode 100644
index 0000000..675aeb0
--- /dev/null
+++ b/src/main/java/com/ruoyi/productionPlan/service/ProductOrderPlanService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.productionPlan.service;
+
+import com.ruoyi.productionPlan.pojo.ProductOrderPlan;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-11 03:02:58
+ */
+public interface ProductOrderPlanService extends IService<ProductOrderPlan> {
+
+}
diff --git a/src/main/java/com/ruoyi/productionPlan/service/ProductionPlanService.java b/src/main/java/com/ruoyi/productionPlan/service/ProductionPlanService.java
index d67e5b7..7375c5d 100644
--- a/src/main/java/com/ruoyi/productionPlan/service/ProductionPlanService.java
+++ b/src/main/java/com/ruoyi/productionPlan/service/ProductionPlanService.java
@@ -44,6 +44,16 @@
     boolean add(ProductionPlanDto productionPlanDto);
 
     /**
+     * 鏇存柊鐢熶骇璁″垝
+     */
+    boolean update(ProductionPlanDto productionPlanDto);
+
+    /**
+     * 鍒犻櫎鐢熶骇璁″垝
+     */
+    boolean delete(List<Long> ids);
+
+    /**
      * 鎸夌収浜у搧绫诲埆姹囨�荤粺璁¢渶姹傞噺
      */
     List<ProductionPlanSummaryDto> summaryByProductType(ProductionPlanSummaryDto query);
diff --git a/src/main/java/com/ruoyi/productionPlan/service/impl/ProductOrderPlanServiceImpl.java b/src/main/java/com/ruoyi/productionPlan/service/impl/ProductOrderPlanServiceImpl.java
new file mode 100644
index 0000000..fd80560
--- /dev/null
+++ b/src/main/java/com/ruoyi/productionPlan/service/impl/ProductOrderPlanServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.productionPlan.service.impl;
+
+import com.ruoyi.productionPlan.pojo.ProductOrderPlan;
+import com.ruoyi.productionPlan.mapper.ProductOrderPlanMapper;
+import com.ruoyi.productionPlan.service.ProductOrderPlanService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-11 03:02:58
+ */
+@Service
+public class ProductOrderPlanServiceImpl extends ServiceImpl<ProductOrderPlanMapper, ProductOrderPlan> implements ProductOrderPlanService {
+
+}
diff --git a/src/main/java/com/ruoyi/productionPlan/service/impl/ProductionPlanServiceImpl.java b/src/main/java/com/ruoyi/productionPlan/service/impl/ProductionPlanServiceImpl.java
index 1e9f707..cb916e9 100644
--- a/src/main/java/com/ruoyi/productionPlan/service/impl/ProductionPlanServiceImpl.java
+++ b/src/main/java/com/ruoyi/productionPlan/service/impl/ProductionPlanServiceImpl.java
@@ -5,9 +5,11 @@
 import com.alibaba.fastjson2.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.exception.base.BaseException;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.common.utils.http.HttpUtils;
@@ -18,7 +20,9 @@
 import com.ruoyi.productionPlan.dto.ProductionPlanDto;
 import com.ruoyi.productionPlan.dto.ProductionPlanImportDto;
 import com.ruoyi.productionPlan.dto.ProductionPlanSummaryDto;
+import com.ruoyi.productionPlan.mapper.ProductOrderPlanMapper;
 import com.ruoyi.productionPlan.mapper.ProductionPlanMapper;
+import com.ruoyi.productionPlan.pojo.ProductOrderPlan;
 import com.ruoyi.productionPlan.pojo.ProductionPlan;
 import com.ruoyi.productionPlan.service.ProductionPlanService;
 import lombok.extern.slf4j.Slf4j;
@@ -62,6 +66,9 @@
     @Autowired
     private ProductOrderService productOrderService;
 
+    @Autowired
+    private ProductOrderPlanMapper productOrderPlanMapper;
+
     /**
      * 鍚屾閿侊紝纭繚鎵嬪姩鍜屽畾鏃朵换鍔′笉鍚屾椂鎵ц
      */
@@ -104,15 +111,13 @@
         //  鏍¢獙鏄惁瀛樺湪涓嶅悓鐨勪骇鍝佸悕绉�
         String firstProductName = plans.get(0).getProductName();
         if (plans.stream().anyMatch(p -> !p.getProductName().equals(firstProductName))) {
-            log.warn("鍚堝苟澶辫触锛屽瓨鍦ㄤ笉鍚岀殑浜у搧鍚嶇О");
-            return false;
+            throw new BaseException("鍚堝苟澶辫触锛屽瓨鍦ㄤ笉鍚岀殑浜у搧鍚嶇О");
         }
 
         // 鏍¢獙鏄惁瀛樺湪涓嶅悓鐨勪骇鍝佽鏍�
         String firstProductSpec = plans.get(0).getProductSpec();
         if (plans.stream().anyMatch(p -> !p.getProductSpec().equals(firstProductSpec))) {
-            log.warn("鍚堝苟澶辫触锛屽瓨鍦ㄤ笉鍚岀殑浜у搧瑙勬牸");
-            return false;
+            throw new BaseException("鍚堝苟澶辫触锛屽瓨鍦ㄤ笉鍚岀殑浜у搧瑙勬牸");
         }
 
 
@@ -123,6 +128,7 @@
                 .reduce(BigDecimal.ZERO, BigDecimal::add);
         // 鍒ゆ柇涓嬪彂鏁伴噺鏄惁澶т簬绛変簬鏂规暟
         if (productionPlanDto.getTotalAssignedQuantity().compareTo(totalVolume) > 0) {
+
             log.warn("鎿嶄綔澶辫触锛屼笅鍙戞暟閲忎笉鑳藉ぇ浜庢柟鏁�");
             return false;
         }
@@ -138,6 +144,7 @@
             if (assignedVolume.add(volume).compareTo(productionPlanDto.getTotalAssignedQuantity()) >= 0) {
                 // 鏈�鍚庝竴涓鍒掞紝鍒嗛厤鍓╀綑鏂规暟
                 plan.setAssignedQuantity(productionPlanDto.getTotalAssignedQuantity().subtract(assignedVolume));
+                productionPlanMapper.updateById(plan);
                 break;
             }
 
@@ -149,11 +156,16 @@
 
         // 鍒涘缓鐢熶骇璁㈠崟
         ProductOrder productOrder = new ProductOrder();
-        String combineIds = StringUtils.join(productionPlanDto.getIds(), ",");
-        productOrder.setCombineProductionPlanIds(combineIds);
         productOrder.setQuantity(productionPlanDto.getTotalAssignedQuantity());
         productOrder.setPlanCompleteTime(productionPlanDto.getPlanCompleteTime());
         productOrderService.addProductOrder(productOrder);
+
+        for (Long planId : productionPlanDto.getIds()) {
+            ProductOrderPlan productOrderPlan = new ProductOrderPlan();
+            productOrderPlan.setProductOrderId(productOrder.getId());
+            productOrderPlan.setProductionPlanId(planId);
+            productOrderPlanMapper.insert(productOrderPlan);
+        }
         return true;
     }
 
@@ -165,6 +177,33 @@
         return true;
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean update(ProductionPlanDto productionPlanDto) {
+        // 鏌ヨ鏄惁鏈夊叧鑱旇鍗�
+        boolean hasProductOrderPlan = productOrderPlanMapper.selectList(Wrappers.<ProductOrderPlan>lambdaQuery().eq(ProductOrderPlan::getProductionPlanId, productionPlanDto.getId())).stream().anyMatch(p -> p.getProductOrderId() != null);
+        if (hasProductOrderPlan) {
+            //  濡傛灉鍏宠仈锛屾柟鏁板彧鑳介�掑
+            ProductionPlan currentPlan = productionPlanMapper.selectById(productionPlanDto.getId());
+            if (productionPlanDto.getVolume().compareTo(currentPlan.getVolume()) < 0) {
+                throw new BaseException("鏂规暟涓嶈兘閫掑噺");
+            }
+        }
+
+        return productionPlanMapper.updateById(productionPlanDto) > 0;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean delete(List<Long> ids) {
+        // 濡傛灉鏈夊叧鑱旇鍗曪紝鍒欎笉鑳藉垹闄�
+        if (productOrderPlanMapper.selectList(Wrappers.<ProductOrderPlan>lambdaQuery().in(ProductOrderPlan::getProductionPlanId, ids)).stream().anyMatch(p -> p.getProductOrderId() != null)) {
+            throw new BaseException("鍒犻櫎澶辫触锛屽瓨鍦ㄥ叧鑱旇鍗�");
+        }
+
+        return productionPlanMapper.deleteBatchIds(ids) > 0;
+    }
+
     /**
      * 鍚屾鏁版嵁
      */
diff --git a/src/main/resources/mapper/productionPlan/ProductOrderPlanMapper.xml b/src/main/resources/mapper/productionPlan/ProductOrderPlanMapper.xml
new file mode 100644
index 0000000..9bb37e1
--- /dev/null
+++ b/src/main/resources/mapper/productionPlan/ProductOrderPlanMapper.xml
@@ -0,0 +1,14 @@
+<?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.productionPlan.mapper.ProductOrderPlanMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.productionPlan.pojo.ProductOrderPlan">
+        <id column="id" property="id" />
+        <result column="product_order_id" property="productOrderId" />
+        <result column="production_plan_id" property="productionPlanId" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+    </resultMap>
+
+</mapper>

--
Gitblit v1.9.3