Selaa lähdekoodia

Merge branch 'ljy'

tjxt 2 kuukautta sitten
vanhempi
sitoutus
eb1aee25d8
27 muutettua tiedostoa jossa 1568 lisäystä ja 70 poistoa
  1. 30 0
      ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/RemoteContractProdcutService.java
  2. 72 0
      ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/ContractProductDto.java
  3. 2 1
      ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlatformDataScopeInterceptor.java
  4. 3 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/ContractSupplyController.java
  5. 1 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/CustomerInfoController.java
  6. 1 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/ContractSupply.java
  7. 1 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/SupplierContract.java
  8. 76 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/ContractSupplyBo.java
  9. 4 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/SupplierContactBo.java
  10. 1 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/SupplierContractBo.java
  11. 52 52
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/SupplierInfoBo.java
  12. 496 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/ContractSupplyProductVo.java
  13. 9 3
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/ContractSupplyVo.java
  14. 2 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/CustomerContactVo.java
  15. 14 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/SupplierContactVo.java
  16. 101 6
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/ContractSupplyServiceImpl.java
  17. 9 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierContactServiceImpl.java
  18. 35 3
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierContractServiceImpl.java
  19. 106 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ContractProductController.java
  20. 86 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ContractProduct.java
  21. 74 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ContractProductBo.java
  22. 94 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ContractProductVo.java
  23. 67 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/dubbo/RemoteContractProductServiceImpl.java
  24. 15 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/mapper/ContractProductMapper.java
  25. 70 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IContractProductService.java
  26. 140 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ContractProductServiceImpl.java
  27. 7 0
      ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ContractProductMapper.xml

+ 30 - 0
ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/RemoteContractProdcutService.java

@@ -0,0 +1,30 @@
+package org.dromara.product.api;
+
+/**
+ * author
+ * 时间:2026/1/20,13:52
+ */
+
+import org.dromara.common.core.domain.R;
+import org.dromara.product.api.domain.ContractProductDto;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.List;
+
+/**
+ * 产品与协议供货合同表示接口
+ */
+public interface RemoteContractProdcutService {
+
+    /**
+     * 批量添加商品合同信息
+     * @param bo
+     * @return
+     */
+    boolean add(List<ContractProductDto> bo) ;
+
+    List<ContractProductDto> queryList(Long contractSupplyId);
+
+    boolean delete(Long contractSupplyId);
+
+}

+ 72 - 0
ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/ContractProductDto.java

@@ -0,0 +1,72 @@
+package org.dromara.product.api.domain;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * author
+ * 时间:2026/1/20,13:50
+ */
+@Data
+public class ContractProductDto implements Serializable {
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 合同供货编号
+     */
+    private String contractSupplyNo;
+
+    /**
+     * 合同供货Id
+     */
+    private Long contractSupplyId;
+
+    /**
+     * 产品编号
+     */
+    private String productNo;
+
+    /**
+     * 产品id
+     */
+    private Long productId;
+
+    /**
+     * 供货周期(单位:天/月,根据业务定义)
+     */
+    private Long supplyCycle;
+
+    /**
+     * 库存属性
+     */
+    private String inventoryProperties;
+
+    /**
+     * 最小供货量
+     */
+    private Long minSupply;
+
+    /**
+     * 报价(支持大文本)
+     */
+    private String offerPrice;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    private String delFlag;
+
+    /**
+     * 备注
+     */
+    private String remark;
+}

+ 2 - 1
ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlatformDataScopeInterceptor.java

@@ -79,7 +79,8 @@ public class PlatformDataScopeInterceptor implements Interceptor {
         "product_",
         "supplier_level",
         "enterprise_scale",
-        "industry_category"
+        "industry_category",
+        "contract_product"
 
 
         // 注意:前缀匹配需特殊处理(如 qrtz_),见 isIgnoreTable 方法

+ 3 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/ContractSupplyController.java

@@ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.constraints.*;
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.validation.annotation.Validated;
 import org.dromara.common.idempotent.annotation.RepeatSubmit;
@@ -67,6 +68,7 @@ public class ContractSupplyController extends BaseController {
     @GetMapping("/{id}")
     public R<ContractSupplyVo> getInfo(@NotNull(message = "主键不能为空")
                                      @PathVariable("id") Long id) {
+
         return R.ok(contractSupplyService.queryById(id));
     }
 
@@ -77,6 +79,7 @@ public class ContractSupplyController extends BaseController {
     @Log(title = "协议供货", businessType = BusinessType.INSERT)
     @RepeatSubmit()
     @PostMapping()
+    @Transactional
     public R<Void> add(@Validated(AddGroup.class) @RequestBody ContractSupplyBo bo) {
         return toAjax(contractSupplyService.insertByBo(bo));
     }

+ 1 - 1
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/CustomerInfoController.java

@@ -118,7 +118,7 @@ public class CustomerInfoController extends BaseController {
     @Log(title = "客户信息", businessType = BusinessType.UPDATE)
     @RepeatSubmit()
     @PutMapping()
-    public R<Void> edit(@Validated(EditGroup.class) @RequestBody CustomerInfoBo bo) {
+    public R<Void> edit(@RequestBody CustomerInfoBo bo) {
         return toAjax(customerInfoService.updateByBo(bo));
     }
 

+ 1 - 1
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/ContractSupply.java

@@ -32,7 +32,7 @@ public class ContractSupply extends TenantEntity {
     /**
      * 协议单号
      */
-    private Long contractSupplyNo;
+    private String contractSupplyNo;
 
     /**
      * 供应商编号

+ 1 - 1
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/SupplierContract.java

@@ -84,7 +84,7 @@ public class SupplierContract extends TenantEntity {
     /**
      * 税率(如13%/9%/6%)
      */
-    private BigDecimal taxRate;
+    private Long taxRate;
 
     /**
      * 结算方式(如月结/季结/一次性)

+ 76 - 1
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/ContractSupplyBo.java

@@ -1,5 +1,7 @@
 package org.dromara.customer.domain.bo;
 
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import org.dromara.customer.domain.ContractSupply;
 import org.dromara.common.mybatis.core.domain.BaseEntity;
 import org.dromara.common.core.validate.AddGroup;
@@ -9,7 +11,10 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import jakarta.validation.constraints.*;
 import java.util.Date;
+import java.util.List;
+
 import com.fasterxml.jackson.annotation.JsonFormat;
+import org.dromara.product.api.domain.ContractProductDto;
 
 /**
  * 协议供货业务对象 contract_supply
@@ -22,10 +27,31 @@ import com.fasterxml.jackson.annotation.JsonFormat;
 @AutoMapper(target = ContractSupply.class, reverseConvertGenerate = false)
 public class ContractSupplyBo extends BaseEntity {
 
+    /**
+     * 主键ID
+     */
+    @TableId(value = "id")
+    private Long id;
+
     /**
      * 协议单号
      */
-    private Long contractSupplyNo;
+    private String contractSupplyNo;
+
+    /**
+     * 供应商编号
+     */
+    private String supplyNo;
+
+    /**
+     * 供应商ID
+     */
+    private Long supplierId;
+
+    /**
+     * 商品数量
+     */
+    private Long productNumber;
 
     /**
      * 开始时间
@@ -37,5 +63,54 @@ public class ContractSupplyBo extends BaseEntity {
      */
     private Date endTime;
 
+    /**
+     * 审核时间
+     */
+    private Date auditTime;
+
+    /**
+     * 价格周期(单位:天/月,根据业务定义)
+     */
+    private Long priceCycle;
+
+    /**
+     * 配送方式(如:自提、快递、送货上门等)
+     */
+    private String deliveryMethod;
+
+    /**
+     * 结算方式(如:月结、现结、账期等)
+     */
+    private String settlementMethod;
+
+    /**
+     * 价格说明(详细描述定价规则、优惠政策等)
+     */
+    private String priceDescription;
+
+    /**
+     * 附件文件路径
+     */
+    private String proFile;
+
+    /**
+     * 附件文件名
+     */
+    private String proFileName;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+
+    /**
+     * 备注信息
+     */
+    private String remark;
+
+
+    private List<ContractProductDto> contractProduct;
+
 
 }

+ 4 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/SupplierContactBo.java

@@ -20,6 +20,7 @@ import jakarta.validation.constraints.*;
 @AutoMapper(target = SupplierContact.class, reverseConvertGenerate = false)
 public class SupplierContactBo extends BaseEntity {
 
+    private Long id;
     /**
      * 供应商编号
      */
@@ -30,6 +31,7 @@ public class SupplierContactBo extends BaseEntity {
      */
     private Long supplierId;
 
+    private String supplierName;
     /**
      * 员工编号
      */
@@ -50,5 +52,7 @@ public class SupplierContactBo extends BaseEntity {
      */
     private String status;
 
+    private String password;
+
 
 }

+ 1 - 1
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/SupplierContractBo.java

@@ -77,7 +77,7 @@ public class SupplierContractBo extends BaseEntity {
     /**
      * 税率(如13%/9%/6%)
      */
-    private BigDecimal taxRate;
+    private Long taxRate;
 
     /**
      * 合同金额

+ 52 - 52
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/SupplierInfoBo.java

@@ -32,205 +32,205 @@ public class SupplierInfoBo extends BaseEntity {
     /**
      * 供应商编号
      */
-    @NotBlank(message = "供应商编号不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "供应商编号不能为空", groups = { AddGroup.class, EditGroup.class })
     private String supplierNo;
 
     /**
      * 企业名称
      */
-    @NotBlank(message = "企业名称不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "企业名称不能为空", groups = { AddGroup.class, EditGroup.class })
     private String enterpriseName;
 
     /**
      * 人员规模
      */
-    @NotBlank(message = "人员规模不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "人员规模不能为空", groups = { AddGroup.class, EditGroup.class })
     private String membershipSize;
 
     /**
      * 供应商类型
      */
-    @NotBlank(message = "供应商类型不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "供应商类型不能为空", groups = { AddGroup.class, EditGroup.class })
     private String supplierType;
 
     /**
      * 合作类型
      */
-    @NotBlank(message = "合作类型不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "合作类型不能为空", groups = { AddGroup.class, EditGroup.class })
     private String cooperationType;
 
     /**
      * 固定电话
      */
-    @NotBlank(message = "固定电话不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "固定电话不能为空", groups = { AddGroup.class, EditGroup.class })
     private String fixedPhone;
 
     /**
      * 传真
      */
-    @NotBlank(message = "传真不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "传真不能为空", groups = { AddGroup.class, EditGroup.class })
     private String fax;
 
     /**
      * 网址
      */
-    @NotBlank(message = "网址不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "网址不能为空", groups = { AddGroup.class, EditGroup.class })
     private String url;
 
     /**
      * 邮政编码
      */
-    @NotBlank(message = "邮政编码不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "邮政编码不能为空", groups = { AddGroup.class, EditGroup.class })
     private String postCode;
 
     /**
      * 邮箱
      */
-    @NotBlank(message = "邮箱不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "邮箱不能为空", groups = { AddGroup.class, EditGroup.class })
     private String mailbox;
 
     /**
      * 办公地址-省
      */
-    @NotBlank(message = "办公地址-省不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "办公地址-省不能为空", groups = { AddGroup.class, EditGroup.class })
     private String officeProvince;
 
     /**
      * 办公地址-市
      */
-    @NotBlank(message = "办公地址-市不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "办公地址-市不能为空", groups = { AddGroup.class, EditGroup.class })
     private String officeCity;
 
     /**
      * 办公地址-区/县
      */
-    @NotBlank(message = "办公地址-区/县不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "办公地址-区/县不能为空", groups = { AddGroup.class, EditGroup.class })
     private String officeCounty;
 
     /**
      * 办公详细地址
      */
-    @NotBlank(message = "办公详细地址不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "办公详细地址不能为空", groups = { AddGroup.class, EditGroup.class })
     private String officeAddress;
 
     /**
      * 营业执照名称
      */
-    @NotBlank(message = "营业执照名称不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "营业执照名称不能为空", groups = { AddGroup.class, EditGroup.class })
     private String businessName;
 
     /**
      * 统一社会信用代码
      */
-    @NotBlank(message = "统一社会信用代码不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "统一社会信用代码不能为空", groups = { AddGroup.class, EditGroup.class })
     private String socialCreditCode;
 
     /**
      * 法人姓名
      */
-    @NotBlank(message = "法人姓名不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "法人姓名不能为空", groups = { AddGroup.class, EditGroup.class })
     private String legalPersonName;
 
     /**
      * 法人身份证号
      */
-    @NotBlank(message = "法人身份证号不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "法人身份证号不能为空", groups = { AddGroup.class, EditGroup.class })
     private String legalPersonId;
 
     /**
      * 注册资本
      */
-    @NotBlank(message = "注册资本不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "注册资本不能为空", groups = { AddGroup.class, EditGroup.class })
     private String registeredCapital;
 
     /**
      * 注册地址-省
      */
-    @NotBlank(message = "注册地址-省不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "注册地址-省不能为空", groups = { AddGroup.class, EditGroup.class })
     private String businessProvince;
 
     /**
      * 注册地址-市
      */
-    @NotBlank(message = "注册地址-市不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "注册地址-市不能为空", groups = { AddGroup.class, EditGroup.class })
     private String businessCity;
 
     /**
      * 注册地址-区/县
      */
-    @NotBlank(message = "注册地址-区/县不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "注册地址-区/县不能为空", groups = { AddGroup.class, EditGroup.class })
     private String businessCounty;
 
     /**
      * 注册详细地址
      */
-    @NotBlank(message = "注册详细地址不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "注册详细地址不能为空", groups = { AddGroup.class, EditGroup.class })
     private String businessAddress;
 
     /**
      * 营业执照图片路径
      */
-    @NotBlank(message = "营业执照图片路径不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "营业执照图片路径不能为空", groups = { AddGroup.class, EditGroup.class })
     private String businessLicense;
 
     /**
      * 发票类型
      */
-    @NotBlank(message = "发票类型不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "发票类型不能为空", groups = { AddGroup.class, EditGroup.class })
     private String invoiceType;
 
     /**
      * 发票抬头
      */
-    @NotBlank(message = "发票抬头不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "发票抬头不能为空", groups = { AddGroup.class, EditGroup.class })
     private String invoiceHeader;
 
     /**
      * 纳税人识别号
      */
-    @NotBlank(message = "纳税人识别号不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "纳税人识别号不能为空", groups = { AddGroup.class, EditGroup.class })
     private String taxpayerIdentifier;
 
     /**
      * 开户银行
      */
-    @NotBlank(message = "开户银行不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "开户银行不能为空", groups = { AddGroup.class, EditGroup.class })
     private String depositaryBank;
 
     /**
      * 行号(可能是银行行号)
      */
-    @NotBlank(message = "行号(可能是银行行号)不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "行号(可能是银行行号)不能为空", groups = { AddGroup.class, EditGroup.class })
     private String rowNum;
 
     /**
      * 银行账号
      */
-    @NotBlank(message = "银行账号不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "银行账号不能为空", groups = { AddGroup.class, EditGroup.class })
     private String bankAccounts;
 
     /**
      * 发票地址
      */
-    @NotBlank(message = "发票地址不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "发票地址不能为空", groups = { AddGroup.class, EditGroup.class })
     private String invoiceAddress;
 
     /**
      * 发票电话
      */
-    @NotBlank(message = "发票电话不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "发票电话不能为空", groups = { AddGroup.class, EditGroup.class })
     private String invoiceLandline;
 
     /**
      * 供货范围
      */
-    @NotBlank(message = "供货范围不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "供货范围不能为空", groups = { AddGroup.class, EditGroup.class })
     private String scopeSupply;
 
     /**
      * 合作方式(0-公开招标, 1-邀请招标...)
      */
-    @NotNull(message = "合作方式(0-公开招标, 1-邀请招标...)不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotNull(message = "合作方式(0-公开招标, 1-邀请招标...)不能为空", groups = { AddGroup.class, EditGroup.class })
     private Long cooperateWay;
 
     /**
@@ -241,7 +241,7 @@ public class SupplierInfoBo extends BaseEntity {
     /**
      * 合同到期时间
      */
-    @NotNull(message = "合同到期时间不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotNull(message = "合同到期时间不能为空", groups = { AddGroup.class, EditGroup.class })
     private Date contractEndTime;
 
     /**
@@ -257,67 +257,67 @@ public class SupplierInfoBo extends BaseEntity {
     /**
      * 年销售额
      */
-    @NotNull(message = "年销售额不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotNull(message = "年销售额不能为空", groups = { AddGroup.class, EditGroup.class })
     private Long yearSales;
 
     /**
      * 供应商联系人姓名
      */
-    @NotBlank(message = "供应商联系人姓名不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "供应商联系人姓名不能为空", groups = { AddGroup.class, EditGroup.class })
     private String supplierName;
 
     /**
      * 供应商联系人电话
      */
-    @NotBlank(message = "供应商联系人电话不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "供应商联系人电话不能为空", groups = { AddGroup.class, EditGroup.class })
     private String supplierPhone;
 
     /**
      * 供应商登录密码(已加密)
      */
-    @NotBlank(message = "供应商登录密码(已加密)不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "供应商登录密码(已加密)不能为空", groups = { AddGroup.class, EditGroup.class })
     private String supplierPassword;
 
     /**
      * 经营品类
      */
-    @NotBlank(message = "经营品类不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "经营品类不能为空", groups = { AddGroup.class, EditGroup.class })
     private String operatingCategory;
 
     /**
      * 经营品牌
      */
-    @NotBlank(message = "经营品牌不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "经营品牌不能为空", groups = { AddGroup.class, EditGroup.class })
     private String operatingBrand;
 
     /**
      * 其他客户
      */
-    @NotBlank(message = "其他客户不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "其他客户不能为空", groups = { AddGroup.class, EditGroup.class })
     private String otherCustomers;
 
     /**
      * 简称
      */
-    @NotBlank(message = "简称不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "简称不能为空", groups = { AddGroup.class, EditGroup.class })
     private String shortName;
 
     /**
      * 所属行业
      */
-    @NotBlank(message = "所属行业不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "所属行业不能为空", groups = { AddGroup.class, EditGroup.class })
     private String industrCategory;
 
     /**
      * 类型(可能与supplier_type重复或细分)
      */
-    @NotBlank(message = "类型(可能与supplier_type重复或细分)不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "类型(可能与supplier_type重复或细分)不能为空", groups = { AddGroup.class, EditGroup.class })
     private String type;
 
     /**
      * 所属公司
      */
-    @NotBlank(message = "所属公司不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "所属公司不能为空", groups = { AddGroup.class, EditGroup.class })
     private String ownedCompany;
 
     /**
@@ -333,31 +333,31 @@ public class SupplierInfoBo extends BaseEntity {
     /**
      * 修改时间
      */
-    @NotNull(message = "修改时间不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotNull(message = "修改时间不能为空", groups = { AddGroup.class, EditGroup.class })
     private Date modify;
 
     /**
      * 有效期开始时间
      */
-    @NotNull(message = "有效期开始时间不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotNull(message = "有效期开始时间不能为空", groups = { AddGroup.class, EditGroup.class })
     private Date validityFromDate;
 
     /**
      * 有效期结束时间
      */
-    @NotNull(message = "有效期结束时间不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotNull(message = "有效期结束时间不能为空", groups = { AddGroup.class, EditGroup.class })
     private Date validityToDate;
 
     /**
      * 行号(可能是内部排序或备用字段)
      */
-    @NotNull(message = "行号(可能是内部排序或备用字段)不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotNull(message = "行号(可能是内部排序或备用字段)不能为空", groups = { AddGroup.class, EditGroup.class })
     private Long rowNo;
 
     /**
      * 法人身份证图片路径
      */
-    @NotBlank(message = "法人身份证图片路径不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotBlank(message = "法人身份证图片路径不能为空", groups = { AddGroup.class, EditGroup.class })
     private String personImage;
 
     /**
@@ -368,7 +368,7 @@ public class SupplierInfoBo extends BaseEntity {
     /**
      * 是否合作(1-是, 0-否)
      */
-    @NotNull(message = "是否合作(1-是, 0-否)不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotNull(message = "是否合作(1-是, 0-否)不能为空", groups = { AddGroup.class, EditGroup.class })
     private Long cooperative;
 
 

+ 496 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/ContractSupplyProductVo.java

@@ -0,0 +1,496 @@
+package org.dromara.customer.domain.vo;
+
+import cn.idev.excel.annotation.ExcelProperty;
+import lombok.Data;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+
+import java.math.BigDecimal;
+
+/**
+ * author
+ * 时间:2026/1/20,15:46
+ */
+@Data
+public class ContractSupplyProductVo {
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 合同供货编号
+     */
+    private String contractSupplyNo;
+
+    /**
+     * 合同供货Id
+     */
+    private Long contractSupplyId;
+
+    /**
+     * 产品编号
+     */
+    private String productNo;
+
+    /**
+     * 产品id
+     */
+    private Long productId;
+
+    /**
+     * 供货周期(单位:天/月,根据业务定义)
+     */
+    private Long supplyCycle;
+
+    /**
+     * 库存属性
+     */
+    private String inventoryProperties;
+
+    /**
+     * 最小供货量
+     */
+    private Long minSupply;
+
+    /**
+     * 报价(支持大文本)
+     */
+    private String offerPrice;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    private String delFlag;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+
+
+
+    /**
+     * 产品名称
+     */
+    @ExcelProperty(value = "项目名称")
+    private String itemName;
+
+    /**
+     * 品牌id
+     */
+    @ExcelProperty(value = "品牌id")
+    private Long brandId;
+
+    /**
+     * 品牌名称
+     */
+    private String brandName;
+
+    /**
+     * 顶级分类id
+     */
+    @ExcelProperty(value = "顶级分类id")
+    private Long topCategoryId;
+
+    /**
+     * 中级分类id
+     */
+    @ExcelProperty(value = "中级分类id")
+    private Long mediumCategoryId;
+
+    /**
+     * 底层分类id
+     */
+    @ExcelProperty(value = "底层分类id")
+    private Long bottomCategoryId;
+
+    /**
+     * 分类名称(底级分类)
+     */
+    private String categoryName;
+
+    /**
+     * 顶级分类名称
+     */
+    private String topCategoryName;
+
+    /**
+     * 中级分类名称
+     */
+    private String mediumCategoryName;
+
+    /**
+     * 底级分类名称
+     */
+    private String bottomCategoryName;
+
+    /**
+     * 单位id
+     */
+    @ExcelProperty(value = "单位id")
+    private String unitId;
+
+    /**
+     * 单位名称(如:件、箱、千克等)
+     */
+    private String unitName;
+
+    /**
+     * 产品图片URL
+     */
+    @ExcelProperty(value = "产品图片URL")
+    private String productImage;
+
+    /**
+     * 是否自营(1=是,0=否)
+     */
+    @ExcelProperty(value = "是否自营", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "1==是,0=否")
+    private Integer isSelf;
+
+    /**
+     * 商品类型 1=默认类型,2精选商品,3=停售商品
+     * */
+    private Integer productCategory;
+
+    /**
+     * 产品审核状态 0=待提交,1=待审核,2=审核通过,3=审核驳回
+     */
+    @ExcelProperty(value = "产品审核状态 0=待采购审核,1=审核通过,2=驳回,3=待营销审核")
+    private Integer productReviewStatus;
+
+    /**
+     * 审核意见
+     * */
+    @ExcelProperty(value = "审核意见")
+    private String reviewComments;
+
+    /**
+     * 首页推荐:1=推荐,0=不推荐
+     */
+    @ExcelProperty(value = "首页推荐:1=推荐,0=不推荐")
+    private Integer homeRecommended;
+
+    /**
+     * 分类推荐:1=推荐,0=不推荐
+     */
+    @ExcelProperty(value = "分类推荐:1=推荐,0=不推荐")
+    private Integer categoryRecommendation;
+
+    /**
+     * 购物车推荐:1=推荐,0=不推荐
+     */
+    @ExcelProperty(value = "购物车推荐:1=推荐,0=不推荐")
+    private Integer cartRecommendation;
+
+    /**
+     * 推荐产品顺序
+     */
+    @ExcelProperty(value = "推荐产品顺序")
+    private Long recommendedProductOrder;
+
+    /**
+     * 是否热门:1=是,0=否
+     */
+    @ExcelProperty(value = "是否热门:1=是,0=否")
+    private Integer isPopular;
+
+    /**
+     * 是否新品:1=是,0=否
+     */
+    @ExcelProperty(value = "是否新品:1=是,0=否")
+    private Integer isNew;
+
+    /**
+     * 商品状态:1=已上架,0=下架 2 上架中等
+     */
+    @ExcelProperty(value = "商品状态:1=已上架,0=下架 2 上架中等")
+    private Integer productStatus;
+
+    /**
+     * 数据来源
+     */
+    @ExcelProperty(value = "数据来源")
+    private String dataSource;
+
+    /**
+     * 市场价
+     * */
+    @ExcelProperty(value = "市场价")
+    private BigDecimal marketPrice;
+
+    /**
+     * 会员价格
+     */
+    @ExcelProperty(value = "会员价格")
+    private BigDecimal memberPrice;
+
+    /**
+     * 最低销售价格
+     */
+    @ExcelProperty(value = "最低销售价格")
+    private BigDecimal minSellingPrice;
+
+    /**
+     * 采购价格
+     */
+    @ExcelProperty(value = "采购价格")
+    private BigDecimal purchasingPrice;
+
+
+    /**
+     * 暂估毛利率
+     * */
+    @ExcelProperty(value = "暂估毛利率")
+    private BigDecimal tempGrossMargin;
+
+
+    /**
+     * A10产品名称
+     */
+    @ExcelProperty(value = "A10产品名称")
+    private String a10ProductName;
+
+    /**
+     * 规格型号
+     */
+    @ExcelProperty(value = "规格型号")
+    private String specification;
+
+    /**
+     * UPC(S)条码
+     */
+    @ExcelProperty(value = "UPC(S)条码")
+    private String upcBarcode;
+
+    /**
+     * 发票名称
+     */
+    @ExcelProperty(value = "发票名称")
+    private String invoiceName;
+
+    /**
+     * 发票规格
+     */
+    @ExcelProperty(value = "发票规格")
+    private String invoiceSpec;
+
+    /**
+     * 包装规格
+     */
+    @ExcelProperty(value = "包装规格")
+    private String packagingSpec;
+
+    /**
+     * 参考链接
+     */
+    @ExcelProperty(value = "参考链接")
+    private String referenceLink;
+
+    /**
+     * 商品重量
+     */
+    @ExcelProperty(value = "商品重量")
+    private String weight;
+
+    /**
+     * 重量单位
+     */
+    @ExcelProperty(value = "重量单位")
+    private String weightUnit;
+
+    /**
+     * 商品体积
+     */
+    @ExcelProperty(value = "商品体积")
+    private String volume;
+
+    /**
+     * 体积单位
+     */
+    @ExcelProperty(value = "体积单位")
+    private String volumeUnit;
+
+    /**
+     * 主库简介
+     */
+    @ExcelProperty(value = "主库简介")
+    private String mainLibraryIntro;
+
+    /**
+     * 售后服务
+     */
+    @ExcelProperty(value = "售后服务")
+    private String afterSalesService;
+
+    /**
+     * 服务保证 - 无忧退货
+     */
+    @ExcelProperty(value = "无忧退货")
+    private String worryFreeReturn;
+
+    /**
+     * 服务保证 - 快速退款
+     */
+    @ExcelProperty(value = "快速退款")
+    private String quickRefund;
+
+    /**
+     * 服务保证 - 免费包邮
+     */
+    @ExcelProperty(value = "免费包邮")
+    private String freeShipping;
+
+    /**
+     * 服务保证 - 正品保障
+     */
+    @ExcelProperty(value = "正品保障")
+    private String genuineGuarantee;
+
+    /**
+     * 安装服务 - 免费安装
+     */
+    @ExcelProperty(value = "免费安装")
+    private String freeInstallation;
+
+    /**
+     * 中档价
+     */
+    @ExcelProperty(value = "中档价")
+    private BigDecimal midRangePrice;
+
+    /**
+     * 平档价
+     */
+    @ExcelProperty(value = "平档价")
+    private BigDecimal standardPrice;
+
+    /**
+     * 套证价
+     */
+    @ExcelProperty(value = "套证价")
+    private BigDecimal certificatePrice;
+
+    /**
+     * 采购价
+     */
+    @ExcelProperty(value = "采购价")
+    private BigDecimal purchasePrice;
+
+    /**
+     * 暂估采购价
+     */
+    @ExcelProperty(value = "暂估采购价")
+    private BigDecimal estimatedPurchasePrice;
+
+    /**
+     * 产品性质
+     */
+    @ExcelProperty(value = "产品性质")
+    private String productNature;
+
+    /**
+     * 采购人员
+     */
+    @ExcelProperty(value = "采购人员")
+    private String purchasingPersonnel;
+
+    /**
+     * 商品详情 - 电脑端
+     */
+    @ExcelProperty(value = "电脑端详情")
+    private String pcDetail;
+
+    /**
+     * 商品详情 - 移动端
+     */
+    @ExcelProperty(value = "移动端详情")
+    private String mobileDetail;
+
+    /**
+     * 税率
+     */
+    @ExcelProperty(value = "税率")
+    private BigDecimal taxRate;
+
+    /**
+     * 币种
+     */
+    @ExcelProperty(value = "币种")
+    private String currency;
+
+    /**
+     * 最低起订量
+     */
+    @ExcelProperty(value = "最低起订量")
+    private Long minOrderQuantity;
+
+    /**
+     * 总库存
+     * */
+    private Long totalInventory;
+    /**
+     * 当前可用库存
+     * */
+    private Long nowInventory;
+
+    /**
+     * 虚拟库存
+     * */
+    private Long virtualInventory;
+
+    /**
+     * 是否可定制
+     */
+    private Boolean customizable;
+
+    /**
+     * 定制说明
+     */
+    private String customDescription;
+
+    /**
+     * 定制详情列表(JSON字符串)
+     */
+    private String customDetailsJson;
+
+    /**
+     * 服务保障(逗号分隔的ID列表)
+     */
+    private String serviceGuarantee;
+
+    /**
+     * 商品属性值(JSON字符串)
+     */
+    private String attributesList;
+
+    /**
+     * 销售量/销量人气
+     */
+    private Long salesVolume;
+
+    /**
+     * 定制方式(逗号分隔)
+     */
+    private String customizedStyle;
+
+    /**
+     * 定制工艺(逗号分隔)
+     */
+    private String customizedCraft;
+
+    /**
+     * 推送状态 0未推送,1已推送
+     */
+    private Long pushStatus;
+
+
+}

+ 9 - 3
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/ContractSupplyVo.java

@@ -11,11 +11,12 @@ import org.dromara.common.excel.annotation.ExcelDictFormat;
 import org.dromara.common.excel.convert.ExcelDictConvert;
 import io.github.linpeilie.annotations.AutoMapper;
 import lombok.Data;
+import org.dromara.product.api.domain.ContractProductDto;
 
 import java.io.Serial;
 import java.io.Serializable;
 import java.util.Date;
-
+import java.util.List;
 
 
 /**
@@ -32,11 +33,13 @@ public class ContractSupplyVo implements Serializable {
     @Serial
     private static final long serialVersionUID = 1L;
 
+
+    private Long id;
     /**
      * 协议单号
      */
     @ExcelProperty(value = "协议单号")
-    private Long contractSupplyNo;
+    private String contractSupplyNo;
 
     /**
      * 供应商编号
@@ -73,16 +76,19 @@ public class ContractSupplyVo implements Serializable {
     private Date endTime;
 
     /**
-     * 状态(0正常 1停用
+     * 状态(0未生效 1生效
      */
     @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
     @ExcelDictFormat(dictType = "contract_supplier_status")
     private String status;
 
+    private String remark;
     /**
      * 剩余时限(天)
      */
     private String timeRemaining;
 
+    private List<ContractSupplyProductVo> contractProduct;
+
 
 }

+ 2 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/CustomerContactVo.java

@@ -39,6 +39,8 @@ public class CustomerContactVo implements Serializable {
     @ExcelProperty(value = "所属客户ID")
     private Long customerId;
 
+
+
     /**
      * 联系人姓名
      */

+ 14 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/SupplierContactVo.java

@@ -28,6 +28,7 @@ public class SupplierContactVo implements Serializable {
     @Serial
     private static final long serialVersionUID = 1L;
 
+    private Long id;
     /**
      * 供应商编号
      */
@@ -112,4 +113,17 @@ public class SupplierContactVo implements Serializable {
     private String status;
 
 
+    private String officePhone;
+
+    /**
+     * 联系地址
+     */
+    private String connAddr;
+
+    /**
+     * 用户描述
+     */
+    private String userDescribe;
+
+
 }

+ 101 - 6
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/ContractSupplyServiceImpl.java

@@ -2,6 +2,8 @@ package org.dromara.customer.service.impl;
 
 import cn.hutool.core.date.DateUtil;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import net.sf.jsqlparser.expression.LongValue;
+import org.apache.dubbo.config.annotation.DubboReference;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.ObjectUtils;
 import org.dromara.common.core.utils.StringUtils;
@@ -13,9 +15,17 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.customer.domain.SupplierInfo;
+import org.dromara.customer.domain.vo.ContractSupplyProductVo;
 import org.dromara.customer.domain.vo.SupplierContractVo;
 import org.dromara.customer.enums.ContractSupplierStatusEnum;
 import org.dromara.customer.service.ISupplierInfoService;
+import org.dromara.product.api.RemoteContractProdcutService;
+import org.dromara.product.api.RemoteProductService;
+import org.dromara.product.api.domain.ContractProductDto;
+import org.dromara.product.api.domain.ProductVo;
+import org.springframework.beans.BeanUtils;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.core.ValueOperations;
 import org.springframework.stereotype.Service;
 import org.dromara.customer.domain.bo.ContractSupplyBo;
 import org.dromara.customer.domain.vo.ContractSupplyVo;
@@ -23,7 +33,9 @@ import org.dromara.customer.domain.ContractSupply;
 import org.dromara.customer.mapper.ContractSupplyMapper;
 import org.dromara.customer.service.IContractSupplyService;
 
+import java.text.SimpleDateFormat;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 /**
@@ -41,6 +53,16 @@ public class ContractSupplyServiceImpl  extends ServiceImpl<ContractSupplyMapper
 
     private final ISupplierInfoService supplierInfoService;
 
+    private final StringRedisTemplate redisTemplate;
+
+    private final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd");
+
+    @DubboReference
+    private final RemoteContractProdcutService remoteContractProdcutService;
+
+    @DubboReference
+    private final RemoteProductService remoteProductService;
+
     /**
      * 查询协议供货
      *
@@ -49,7 +71,26 @@ public class ContractSupplyServiceImpl  extends ServiceImpl<ContractSupplyMapper
      */
     @Override
     public ContractSupplyVo queryById(Long id){
-        return baseMapper.selectVoById(id);
+        ContractSupply contractSupply = getById(id);
+        ContractSupplyVo contractSupplyVo = MapstructUtils.convert(contractSupply, ContractSupplyVo.class);
+        List<ContractProductDto> contractProductDtos = remoteContractProdcutService.queryList(contractSupplyVo.getId());
+
+        List<ContractSupplyProductVo> contractProduct = new ArrayList<>();
+        if (contractProductDtos != null && !contractProductDtos.isEmpty()){
+            for (ContractProductDto dto : contractProductDtos){
+                ContractSupplyProductVo contractSupplyProductVo = new ContractSupplyProductVo();
+                BeanUtils.copyProperties(dto, contractSupplyProductVo);
+                contractProduct.add(contractSupplyProductVo);
+            }
+        }
+        if (contractProduct != null && !contractProduct.isEmpty()) {
+            for (ContractSupplyProductVo vo : contractProduct) {
+                ProductVo productDetail = remoteProductService.getProductDetail(vo.getProductId());
+                BeanUtils.copyProperties(productDetail, vo,"id");
+            }
+        }
+        contractSupplyVo.setContractProduct(contractProduct);
+        return contractSupplyVo;
     }
 
     /**
@@ -177,10 +218,47 @@ public class ContractSupplyServiceImpl  extends ServiceImpl<ContractSupplyMapper
      */
     @Override
     public Boolean insertByBo(ContractSupplyBo bo) {
+        // 1. 生成 年月日+4位序号 的唯一编号
+        String contractSupplyNo = generateContractSupplyNo();
+
+        List<ContractProductDto> contractProduct = bo.getContractProduct();
+
         ContractSupply add = MapstructUtils.convert(bo, ContractSupply.class);
         validEntityBeforeSave(add);
-        boolean flag = baseMapper.insert(add) > 0;
-        return flag;
+        add.setContractSupplyNo(contractSupplyNo);
+        add.setProductNumber((long)contractProduct.size());
+        add.setPriceCycle(0L);
+        boolean flag2 = baseMapper.insert(add) > 0;
+        Long id = add.getId();
+        contractProduct.forEach(product ->{
+            product.setContractSupplyNo(contractSupplyNo);
+            product.setContractSupplyId(id);
+        } );
+        boolean flag1 = remoteContractProdcutService.add(contractProduct);
+        //boolean flag2 = baseMapper.insert(add) > 0;
+        return flag1&&flag2;
+    }
+
+    /**
+     * 生成合同供货编号:年月日 + 4位序号(如 202601200001)
+     * @return 唯一编号
+     */
+    private String generateContractSupplyNo() {
+        // 步骤1:获取当天日期作为 Redis Key 前缀
+        String today = DATE_FORMAT.format(new Date());
+        String redisKey = "contract_supply:seq:" + today;
+
+        // 步骤2:Redis 原子自增(初始值为1,每次+1)
+        ValueOperations<String, String> valueOps = redisTemplate.opsForValue();
+        Long seq = valueOps.increment(redisKey, 1);
+
+        // 步骤3:首次生成时设置过期时间(2天,避免Key永久存在)
+        if (seq == 1) {
+            redisTemplate.expire(redisKey, 2, TimeUnit.DAYS);
+        }
+
+        // 步骤4:拼接编号,4位序号不足补0(如 1 → 0001)
+        return today + String.format("%04d", seq);
     }
 
     /**
@@ -191,9 +269,26 @@ public class ContractSupplyServiceImpl  extends ServiceImpl<ContractSupplyMapper
      */
     @Override
     public Boolean updateByBo(ContractSupplyBo bo) {
-        ContractSupply update = MapstructUtils.convert(bo, ContractSupply.class);
-        validEntityBeforeSave(update);
-        return baseMapper.updateById(update) > 0;
+        List<ContractProductDto> contractProduct = bo.getContractProduct();
+
+        ContractSupply add = MapstructUtils.convert(bo, ContractSupply.class);
+        validEntityBeforeSave(add);
+        add.setProductNumber((long)contractProduct.size());
+        add.setPriceCycle(0L);
+        boolean flag1 = baseMapper.updateById(add)>0;
+        String contractSupplyNo = add.getContractSupplyNo();
+        Long id = add.getId();
+        boolean delete = remoteContractProdcutService.delete(add.getId());
+        boolean flag2=false;
+        if (delete){
+            contractProduct.forEach(product ->{
+                product.setContractSupplyNo(contractSupplyNo);
+                product.setContractSupplyId(id);
+            } );
+            flag2 = remoteContractProdcutService.add(contractProduct);
+        }
+        return flag1&&flag2;
+
     }
 
     /**

+ 9 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierContactServiceImpl.java

@@ -12,6 +12,7 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.customer.controller.SupplierInfoController;
 import org.dromara.customer.domain.SupplierInfo;
+import org.dromara.customer.domain.vo.SupplierInformationVo;
 import org.dromara.customer.service.ISupplierInfoService;
 import org.springframework.stereotype.Service;
 import org.dromara.customer.domain.bo.SupplierContactBo;
@@ -49,6 +50,10 @@ public class SupplierContactServiceImpl  extends ServiceImpl<SupplierContactMapp
      */
     @Override
     public SupplierContactVo queryById(Long id){
+        SupplierContactVo supplierContactVo = baseMapper.selectVoById(id);
+        SupplierInfo one = supplierInfoService.getOne(new LambdaQueryWrapper<SupplierInfo>().eq(SupplierInfo::getId, supplierContactVo.getSupplierId()));
+        one.getEnterpriseName();
+        supplierContactVo.setSupplierName(one.getEnterpriseName());
         return baseMapper.selectVoById(id);
     }
 
@@ -61,6 +66,10 @@ public class SupplierContactServiceImpl  extends ServiceImpl<SupplierContactMapp
      */
     @Override
     public TableDataInfo<SupplierContactVo> queryPageList(SupplierContactBo bo, PageQuery pageQuery) {
+        if (bo.getSupplierName()!= null){
+            SupplierInfo one = supplierInfoService.getOne(new LambdaQueryWrapper<SupplierInfo>().eq(SupplierInfo::getEnterpriseName, bo.getSupplierName()));
+            bo.setSupplierId(one.getId());
+        }
         LambdaQueryWrapper<SupplierContact> lqw = buildQueryWrapper(bo);
         Page<SupplierContactVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
         setSupplierNames(result.getRecords());

+ 35 - 3
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierContractServiceImpl.java

@@ -11,10 +11,12 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.redis.utils.RedisUtils;
 import org.dromara.customer.domain.SupplierInfo;
 import org.dromara.customer.domain.dto.ContractCountDTO;
 import org.dromara.customer.domain.vo.SupplierContactVo;
 import org.dromara.customer.service.ISupplierInfoService;
+import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Service;
 import org.dromara.customer.domain.bo.SupplierContractBo;
 import org.dromara.customer.domain.vo.SupplierContractVo;
@@ -22,6 +24,8 @@ import org.dromara.customer.domain.SupplierContract;
 import org.dromara.customer.mapper.SupplierContractMapper;
 import org.dromara.customer.service.ISupplierContractService;
 
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -40,6 +44,14 @@ public class SupplierContractServiceImpl  extends ServiceImpl<SupplierContractMa
 
     private final ISupplierInfoService supplierInfoService;
 
+    private final StringRedisTemplate redisTemplate;
+
+    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
+    // 合同编号固定前缀
+    private static final String CONTRACT_NO_PREFIX = "contractNo";
+    // Redis Key前缀
+    private static final String REDIS_KEY_PREFIX = "contract_no:";
+
     /**
      * 查询合同管理
      *
@@ -213,13 +225,33 @@ public class SupplierContractServiceImpl  extends ServiceImpl<SupplierContractMa
         SupplierContract add = MapstructUtils.convert(bo, SupplierContract.class);
         validEntityBeforeSave(add);
         add.setContractStatus(0L);
+
+        // 1. 生成当日Redis Key(按日期分桶)
+        String today = LocalDate.now().format(DATE_FORMATTER);
+        String redisKey = REDIS_KEY_PREFIX + today;
+
+        // 2. Redis原子自增,保证并发安全(初始值为1,每次+1)
+        Long incrementNum = redisTemplate.opsForValue().increment(redisKey, 1);
+
+        // 3. 自增数字补零为4位(比如1→0001,12→0012,123→0123)
+        String seqNum = String.format("%04d", incrementNum);
+
+        // 4. 拼接最终合同编号
+        String contractNo =today + seqNum;
+        add.setContractNo(contractNo); // 设置到实体中
+
+        // 5. 设置Redis Key过期时间(可选,避免Key堆积,比如保留7天)
+        redisTemplate.expire(redisKey, 1, java.util.concurrent.TimeUnit.DAYS);
+
+        // 6. 执行数据库插入操作(这里补充你的插入逻辑)
+        // supplierContractMapper.insert(add);
         boolean flag = baseMapper.insert(add) > 0;
-        if (flag) {
-//            bo.setId(add.getId());
-        }
+
         return flag;
+
     }
 
+
     /**
      * 修改合同管理
      *

+ 106 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/ContractProductController.java

@@ -0,0 +1,106 @@
+package org.dromara.product.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.product.domain.vo.ContractProductVo;
+import org.dromara.product.domain.bo.ContractProductBo;
+import org.dromara.product.service.IContractProductService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 合同产品关联
+ * 前端访问路由地址为:/product/contracproduct
+ *
+ * @author LionLi
+ * @date 2026-01-20
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/contracproduct")
+public class ContractProductController extends BaseController {
+
+    private final IContractProductService contractProductService;
+
+    /**
+     * 查询合同产品关联列表
+     */
+    @SaCheckPermission("product:contracproduct:list")
+    @GetMapping("/list")
+    public TableDataInfo<ContractProductVo> list(ContractProductBo bo, PageQuery pageQuery) {
+        return contractProductService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出合同产品关联列表
+     */
+    @SaCheckPermission("product:contracproduct:export")
+    @Log(title = "合同产品关联", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(ContractProductBo bo, HttpServletResponse response) {
+        List<ContractProductVo> list = contractProductService.queryList(bo);
+        ExcelUtil.exportExcel(list, "合同产品关联", ContractProductVo.class, response);
+    }
+
+    /**
+     * 获取合同产品关联详细信息
+     *
+     * @param id 主键
+     */
+    @SaCheckPermission("product:contracproduct:query")
+    @GetMapping("/{id}")
+    public R<ContractProductVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable("id") Long id) {
+        return R.ok(contractProductService.queryById(id));
+    }
+
+    /**
+     * 新增合同产品关联
+     */
+    @SaCheckPermission("product:contracproduct:add")
+    @Log(title = "合同产品关联", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@RequestBody ContractProductBo bo) {
+        return toAjax(contractProductService.insertByBo(bo));
+    }
+
+    /**
+     * 修改合同产品关联
+     */
+    @SaCheckPermission("product:contracproduct:edit")
+    @Log(title = "合同产品关联", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ContractProductBo bo) {
+        return toAjax(contractProductService.updateByBo(bo));
+    }
+
+    /**
+     * 删除合同产品关联
+     *
+     * @param ids 主键串
+     */
+    @SaCheckPermission("product:contracproduct:remove")
+    @Log(title = "合同产品关联", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable("ids") Long[] ids) {
+        return toAjax(contractProductService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 86 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ContractProduct.java

@@ -0,0 +1,86 @@
+package org.dromara.product.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 合同产品关联对象 contract_product
+ *
+ * @author LionLi
+ * @date 2026-01-20
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("contract_product")
+public class ContractProduct extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 合同供货编号
+     */
+    private String contractSupplyNo;
+
+    /**
+     * 合同供货Id
+     */
+    private Long contractSupplyId;
+    /**
+     * 产品编号
+     */
+    private String productNo;
+
+    /**
+     * 产品id
+     */
+    private Long productId;
+
+    /**
+     * 供货周期(单位:天/月,根据业务定义)
+     */
+    private Long supplyCycle;
+
+    /**
+     * 库存属性
+     */
+    private String inventoryProperties;
+
+    /**
+     * 最小供货量
+     */
+    private Long minSupply;
+
+    /**
+     * 报价(支持大文本)
+     */
+    private String offerPrice;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 74 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ContractProductBo.java

@@ -0,0 +1,74 @@
+package org.dromara.product.domain.bo;
+
+import org.dromara.product.domain.ContractProduct;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+
+/**
+ * 合同产品关联业务对象 contract_product
+ *
+ * @author LionLi
+ * @date 2026-01-20
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = ContractProduct.class, reverseConvertGenerate = false)
+public class ContractProductBo extends BaseEntity {
+
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 合同供货编号
+     */
+    private String contractSupplyNo;
+
+    /**
+     * 合同供货Id
+     */
+    private String contractSupplyId;
+
+    /**
+     * 产品编号
+     */
+    private String productNo;
+
+    /**
+     * 产品id
+     */
+    private Long productId;
+
+    /**
+     * 供货周期(单位:天/月,根据业务定义)
+     */
+    private Long supplyCycle;
+
+    /**
+     * 库存属性
+     */
+    private String inventoryProperties;
+
+    /**
+     * 最小供货量
+     */
+    private Long minSupply;
+
+    /**
+     * 报价(支持大文本)
+     */
+    private String offerPrice;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+
+}

+ 94 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ContractProductVo.java

@@ -0,0 +1,94 @@
+package org.dromara.product.domain.vo;
+
+import org.dromara.product.domain.ContractProduct;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 合同产品关联视图对象 contract_product
+ *
+ * @author LionLi
+ * @date 2026-01-20
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = ContractProduct.class)
+public class ContractProductVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    @ExcelProperty(value = "主键ID")
+    private Long id;
+
+    /**
+     * 合同供货编号
+     */
+    @ExcelProperty(value = "合同供货编号")
+    private String contractSupplyNo;
+
+    /**
+     * 合同供货Id
+     */
+    private Long contractSupplyId;
+
+    /**
+     * 产品编号
+     */
+    @ExcelProperty(value = "产品编号")
+    private String productNo;
+
+    /**
+     * 产品id
+     */
+    @ExcelProperty(value = "产品id")
+    private Long productId;
+
+    /**
+     * 供货周期(单位:天/月,根据业务定义)
+     */
+    @ExcelProperty(value = "供货周期", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "单=位:天/月,根据业务定义")
+    private Long supplyCycle;
+
+    /**
+     * 库存属性
+     */
+    @ExcelProperty(value = "库存属性")
+    private String inventoryProperties;
+
+    /**
+     * 最小供货量
+     */
+    @ExcelProperty(value = "最小供货量")
+    private Long minSupply;
+
+    /**
+     * 报价(支持大文本)
+     */
+    @ExcelProperty(value = "报价", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "支=持大文本")
+    private String offerPrice;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "0=正常,1=停用")
+    private String status;
+
+
+}

+ 67 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/dubbo/RemoteContractProductServiceImpl.java

@@ -0,0 +1,67 @@
+package org.dromara.product.dubbo;
+
+import lombok.RequiredArgsConstructor;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.dromara.product.api.RemoteContractProdcutService;
+import org.dromara.product.api.domain.ContractProductDto;
+import org.dromara.product.domain.ContractProduct;
+import org.dromara.product.service.IContractProductService;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * author
+ * 时间:2026/1/20,13:54
+ */
+@RequiredArgsConstructor
+@Service
+@DubboService
+public class RemoteContractProductServiceImpl implements RemoteContractProdcutService {
+
+    private final IContractProductService contractProductService;
+
+
+    @Override
+    public boolean add(List<ContractProductDto> dto) {
+        boolean flag = true;
+        if (dto ==null){
+            return true;
+        }
+        List<ContractProduct> contractProducts = new ArrayList<>();
+        for (ContractProductDto bo : dto) {
+            ContractProduct contractProduct = new ContractProduct();
+            // 这里需要根据实际字段进行属性复制
+            BeanUtils.copyProperties(bo, contractProduct);
+            contractProducts.add(contractProduct);
+        }
+
+        flag = contractProductService.saveBatch(contractProducts);
+        return flag;
+    }
+
+    @Override
+    public List<ContractProductDto> queryList(Long contractSupplyId) {
+        List<ContractProduct> list = contractProductService.lambdaQuery().eq(ContractProduct::getContractSupplyId, contractSupplyId).list();
+
+        // 将实体对象转换为DTO对象
+        List<ContractProductDto> dtoList = new ArrayList<>();
+        for (ContractProduct entity : list) {
+            ContractProductDto dto = new ContractProductDto();
+            BeanUtils.copyProperties(entity, dto);
+            dtoList.add(dto);
+        }
+
+        return dtoList;
+    }
+
+    @Override
+    public boolean delete(Long contractSupplyId) {
+        List<ContractProduct> list = contractProductService.lambdaQuery()
+            .eq(ContractProduct::getContractSupplyId, contractSupplyId)
+            .select(ContractProduct::getId).list();
+        return contractProductService.removeByIds(list);
+    }
+}

+ 15 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/mapper/ContractProductMapper.java

@@ -0,0 +1,15 @@
+package org.dromara.product.mapper;
+
+import org.dromara.product.domain.ContractProduct;
+import org.dromara.product.domain.vo.ContractProductVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 合同产品关联Mapper接口
+ *
+ * @author LionLi
+ * @date 2026-01-20
+ */
+public interface ContractProductMapper extends BaseMapperPlus<ContractProduct, ContractProductVo> {
+
+}

+ 70 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/IContractProductService.java

@@ -0,0 +1,70 @@
+package org.dromara.product.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.product.domain.ContractProduct;
+import org.dromara.product.domain.vo.ContractProductVo;
+import org.dromara.product.domain.bo.ContractProductBo;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 合同产品关联Service接口
+ *
+ * @author LionLi
+ * @date 2026-01-20
+ */
+public interface IContractProductService extends IService<ContractProduct>{
+
+    /**
+     * 查询合同产品关联
+     *
+     * @param id 主键
+     * @return 合同产品关联
+     */
+    ContractProductVo queryById(Long id);
+
+    /**
+     * 分页查询合同产品关联列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 合同产品关联分页列表
+     */
+    TableDataInfo<ContractProductVo> queryPageList(ContractProductBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的合同产品关联列表
+     *
+     * @param bo 查询条件
+     * @return 合同产品关联列表
+     */
+    List<ContractProductVo> queryList(ContractProductBo bo);
+
+    /**
+     * 新增合同产品关联
+     *
+     * @param bo 合同产品关联
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(ContractProductBo bo);
+
+    /**
+     * 修改合同产品关联
+     *
+     * @param bo 合同产品关联
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(ContractProductBo bo);
+
+    /**
+     * 校验并批量删除合同产品关联信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 140 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ContractProductServiceImpl.java

@@ -0,0 +1,140 @@
+package org.dromara.product.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.dromara.product.domain.bo.ContractProductBo;
+import org.dromara.product.domain.vo.ContractProductVo;
+import org.dromara.product.domain.ContractProduct;
+import org.dromara.product.mapper.ContractProductMapper;
+import org.dromara.product.service.IContractProductService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 合同产品关联Service业务层处理
+ *
+ * @author LionLi
+ * @date 2026-01-20
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class ContractProductServiceImpl  extends ServiceImpl<ContractProductMapper, ContractProduct> implements IContractProductService {
+
+    private final ContractProductMapper baseMapper;
+
+    /**
+     * 查询合同产品关联
+     *
+     * @param id 主键
+     * @return 合同产品关联
+     */
+    @Override
+    public ContractProductVo queryById(Long id){
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 分页查询合同产品关联列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 合同产品关联分页列表
+     */
+    @Override
+    public TableDataInfo<ContractProductVo> queryPageList(ContractProductBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<ContractProduct> lqw = buildQueryWrapper(bo);
+        Page<ContractProductVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的合同产品关联列表
+     *
+     * @param bo 查询条件
+     * @return 合同产品关联列表
+     */
+    @Override
+    public List<ContractProductVo> queryList(ContractProductBo bo) {
+        LambdaQueryWrapper<ContractProduct> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<ContractProduct> buildQueryWrapper(ContractProductBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<ContractProduct> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(ContractProduct::getId);
+        lqw.eq(StringUtils.isNotBlank(bo.getContractSupplyNo()), ContractProduct::getContractSupplyNo, bo.getContractSupplyNo());
+        lqw.eq(StringUtils.isNotBlank(bo.getProductNo()), ContractProduct::getProductNo, bo.getProductNo());
+        lqw.eq(bo.getProductId() != null, ContractProduct::getProductId, bo.getProductId());
+        lqw.eq(bo.getSupplyCycle() != null, ContractProduct::getSupplyCycle, bo.getSupplyCycle());
+        lqw.eq(StringUtils.isNotBlank(bo.getInventoryProperties()), ContractProduct::getInventoryProperties, bo.getInventoryProperties());
+        lqw.eq(bo.getMinSupply() != null, ContractProduct::getMinSupply, bo.getMinSupply());
+        lqw.eq(StringUtils.isNotBlank(bo.getOfferPrice()), ContractProduct::getOfferPrice, bo.getOfferPrice());
+        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), ContractProduct::getStatus, bo.getStatus());
+        return lqw;
+    }
+
+    /**
+     * 新增合同产品关联
+     *
+     * @param bo 合同产品关联
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(ContractProductBo bo) {
+        ContractProduct add = MapstructUtils.convert(bo, ContractProduct.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改合同产品关联
+     *
+     * @param bo 合同产品关联
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(ContractProductBo bo) {
+        ContractProduct update = MapstructUtils.convert(bo, ContractProduct.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(ContractProduct entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除合同产品关联信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}

+ 7 - 0
ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ContractProductMapper.xml

@@ -0,0 +1,7 @@
+<?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="org.dromara.product.mapper.ContractProductMapper">
+
+</mapper>