7
0

8 Revīzijas 9227dbfc88 ... 16cc882ded

Autors SHA1 Ziņojums Datums
  林小张 16cc882ded 1-29-zl 2 mēneši atpakaļ
  林小张 f82be86013 Merge branch 'master' into zl 2 mēneši atpakaļ
  hurx 4dfa351e84 feat(order): 添加客户发货单查询功能 2 mēneši atpakaļ
  hurx 978374a33a Merge branch 'hurx' 2 mēneši atpakaļ
  hurx 79e88dbc39 feat(order): 订单模块功能增强 2 mēneši atpakaļ
  林小张 97153a98b0 1-28 2 mēneši atpakaļ
  Lijingyang 15af189fc6 Merge remote-tracking branch 'origin/master' 2 mēneši atpakaļ
  tjxt 8c4841a34e 供应商 2 mēneši atpakaļ
81 mainītis faili ar 3225 papildinājumiem un 136 dzēšanām
  1. 18 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteAddressAreaService.java
  2. 55 0
      ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/domain/dto/AddressAreaDTO.java
  3. 23 0
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/InvoiceStatus.java
  4. 39 0
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/StatementStatus.java
  5. 2 1
      ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlatformDataScopeInterceptor.java
  6. 2 2
      ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java
  7. 7 2
      ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/domain/StatementDetail.java
  8. 2 0
      ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/domain/bo/StatementDetailBo.java
  9. 2 0
      ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/domain/vo/StatementDetailVo.java
  10. 69 0
      ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/pc/controller/PcStatementDetailController.java
  11. 58 0
      ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/pc/controller/PcStatementInvoiceController.java
  12. 147 0
      ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/pc/controller/PcStatementOrderController.java
  13. 103 0
      ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/pc/controller/PcStatementProductController.java
  14. 10 0
      ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/service/IStatementOrderService.java
  15. 5 1
      ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/service/impl/StatementInvoiceServiceImpl.java
  16. 23 4
      ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/service/impl/StatementOrderServiceImpl.java
  17. 18 6
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/SupplierAuthorizeController.java
  18. 1 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/SupplierContractController.java
  19. 106 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/SupplierQualificationController.java
  20. 4 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/CustomerContact.java
  21. 2 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/QualificationFile.java
  22. 2 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/SupplierAuthorize.java
  23. 2 2
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/SupplierContract.java
  24. 96 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/SupplierQualification.java
  25. 6 2
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/CustomerContactBo.java
  26. 3 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/QualificationFileBo.java
  27. 8 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/SupplierAuthorizeBo.java
  28. 32 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/SupplierContractBo.java
  29. 3 2
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/SupplierInfoBo.java
  30. 80 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/SupplierQualificationBo.java
  31. 5 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/SupplierapproveBo.java
  32. 4 2
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/CustomerContactVo.java
  33. 2 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/QualificationFileVo.java
  34. 9 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/SupplierAuthorizeVo.java
  35. 47 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/SupplierContractVo.java
  36. 1 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/SupplierInfoVo.java
  37. 106 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/SupplierQualificationVo.java
  38. 15 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/mapper/SupplierQualificationMapper.java
  39. 4 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ISupplierAuthorizeService.java
  40. 70 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ISupplierQualificationService.java
  41. 22 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerInfoServiceImpl.java
  42. 382 45
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierAuthorizeServiceImpl.java
  43. 5 7
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierInfoServiceImpl.java
  44. 141 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierQualificationServiceImpl.java
  45. 7 0
      ruoyi-modules/ruoyi-customer/src/main/resources/mapper/customer/SupplierQualificationMapper.xml
  46. 31 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/OrderDeliverController.java
  47. 12 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/OrderMainController.java
  48. 106 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/OrderOperateLogController.java
  49. 12 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/OrderDeliverProduct.java
  50. 57 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/OrderOperateLog.java
  51. 6 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/OrderProduct.java
  52. 12 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/bo/OrderDeliverProductBo.java
  53. 49 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/bo/OrderOperateLogBo.java
  54. 6 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/bo/OrderProductBo.java
  55. 12 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/dto/AssignmentStatsDto.java
  56. 13 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderDeliverProductVo.java
  57. 15 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderDeliverVo.java
  58. 62 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderOperateLogVo.java
  59. 6 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderProductVo.java
  60. 1 1
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/mapper/OrderDeliverMapper.java
  61. 15 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/mapper/OrderOperateLogMapper.java
  62. 19 1
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/mapper/OrderProductMapper.java
  63. 14 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderDeliverService.java
  64. 2 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderMainService.java
  65. 70 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderOperateLogService.java
  66. 96 27
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderAssignmentServiceImpl.java
  67. 144 6
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderDeliverServiceImpl.java
  68. 26 14
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderMainServiceImpl.java
  69. 136 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderOperateLogServiceImpl.java
  70. 2 2
      ruoyi-modules/ruoyi-order/src/main/resources/mapper/order/OrderDeliverMapper.xml
  71. 7 0
      ruoyi-modules/ruoyi-order/src/main/resources/mapper/order/OrderOperateLogMapper.xml
  72. 15 5
      ruoyi-modules/ruoyi-order/src/main/resources/mapper/order/OrderProductMapper.xml
  73. 105 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/AuthorizeTypeLevelController.java
  74. 57 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/AuthorizeTypeLevel.java
  75. 44 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/AuthorizeTypeLevelBo.java
  76. 57 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/AuthorizeTypeLevelVo.java
  77. 41 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteAddressAreaServiceImpl.java
  78. 15 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/AuthorizeTypeLevelMapper.java
  79. 70 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IAuthorizeTypeLevelService.java
  80. 135 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/AuthorizeTypeLevelServiceImpl.java
  81. 7 0
      ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/AuthorizeTypeLevelMapper.xml

+ 18 - 0
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteAddressAreaService.java

@@ -0,0 +1,18 @@
+package org.dromara.system.api;
+
+import org.dromara.system.api.domain.dto.AddressAreaDTO;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * author
+ * 时间:2026/1/27,13:58
+ */
+public interface RemoteAddressAreaService {
+
+
+    List<AddressAreaDTO> listByIds(Set<Long> allAreaIds);
+
+    Long getIdsByName(String province);
+}

+ 55 - 0
ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/domain/dto/AddressAreaDTO.java

@@ -0,0 +1,55 @@
+package org.dromara.system.api.domain.dto;
+
+import cn.idev.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * author
+ * 时间:2026/1/27,14:13
+ */
+@Data
+public class AddressAreaDTO implements Serializable {
+
+    /**
+     * 主键ID
+     */
+    private Long id;
+    /**
+     * 地区编码
+     */
+    private String areaCode;
+
+    /**
+     * 地区名称
+     */
+    private String areaName;
+
+    /**
+     * 父类ID
+     */
+    private Long parentCode;
+
+    /**
+     * 地区简称
+     */
+    private String simpleName;
+
+    /**
+     * 地区等级省 1 市 2
+     */
+    private Long level;
+
+    /**
+     * 拼英
+     */
+    private String pinYin;
+
+    /**
+     * 数据来源
+     */
+    private String dataSource;
+
+}

+ 23 - 0
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/InvoiceStatus.java

@@ -0,0 +1,23 @@
+package org.dromara.common.core.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum InvoiceStatus {
+
+    /**
+     * 未开票
+     */
+    NOT_INVOICED("0", "未开票"),
+
+    /**
+     * 已开票
+     */
+    INVOICED("1", "已开票");
+
+
+    private final String code;
+    private final String info;
+}

+ 39 - 0
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/StatementStatus.java

@@ -0,0 +1,39 @@
+package org.dromara.common.core.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum StatementStatus {
+
+    /**
+     * 待确认
+     */
+    PENDING_CONFIRMATION("0", "待确认"),
+
+    /**
+     * 待对账
+     */
+    PENDING_RECONCILIATION("1", "待对账"),
+
+    /**
+     * 已对账
+     */
+    RECONCILED("2", "已对账"),
+
+    /**
+     * 驳回
+     */
+    REJECTED("3", "驳回"),
+
+    /**
+     * 作废
+     */
+    CANCELLED("4", "作废");
+
+
+    private final String code;
+    private final String info;
+
+}

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

@@ -92,7 +92,8 @@ public class PlatformDataScopeInterceptor implements Interceptor {
         "partner_qualification",
         "address_area",
         "supplier_",
-        "supply_area"
+        "supply_area",
+        "authorize_type_level"
 
 
 

+ 2 - 2
ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java

@@ -89,10 +89,10 @@ public class LoginHelper {
     public static Long getUserId() {
         // ⚠️⚠️⚠️ 临时测试代码,登录功能完成后必须删除 ⚠️⚠️⚠️
         // TODO: 临时返回固定的客户ID用于测试PC端接口,登录功能完成后删除此行
-         return 2009201047173152769L;
+//         return 2009201047173152769L;
 
         // 原来的代码(登录功能完成后恢复)
-        // return Convert.toLong(getExtra(USER_KEY));
+         return Convert.toLong(getExtra(USER_KEY));
     }
 
     /**

+ 7 - 2
ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/domain/StatementDetail.java

@@ -48,15 +48,20 @@ public class StatementDetail extends TenantEntity {
     private String type;
 
     /**
-     * 关联的订单id
+     * 关联的订单id----关联的发货单的订单id
      */
     private Long orderId;
 
     /**
-     * 关联的订单编号
+     * 关联的订单编号----订单主表的订单编号
      */
     private String orderNo;
 
+    /**
+     * 订单发货单编号
+     */
+    private String deliverCode;
+
     /**
      * 该明细金额
      */

+ 2 - 0
ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/domain/bo/StatementDetailBo.java

@@ -51,6 +51,8 @@ public class StatementDetailBo extends BaseEntity {
      */
     private String orderNo;
 
+    private String deliverCode;
+
     /**
      * 该明细金额
      */

+ 2 - 0
ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/domain/vo/StatementDetailVo.java

@@ -70,6 +70,8 @@ public class StatementDetailVo implements Serializable {
     @ExcelProperty(value = "关联的订单编号")
     private String orderNo;
 
+    private String deliverCode;
+
     /**
      * 该明细金额
      */

+ 69 - 0
ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/pc/controller/PcStatementDetailController.java

@@ -0,0 +1,69 @@
+package org.dromara.bill.pc.controller;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.validation.constraints.*;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.bill.domain.bo.StatementDetailBo;
+import org.dromara.bill.domain.vo.StatementDetailVo;
+import org.dromara.bill.domain.vo.StatementOrderVo;
+import org.dromara.bill.service.IStatementDetailService;
+import org.dromara.bill.service.IStatementOrderService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * PC端 - 对账单明细管理
+ * 前端访问路由地址为:/pc/enterprise/statementDetail
+ *
+ * @author Claude
+ * @date 2026-01-29
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/pc/enterprise/statementDetail")
+public class PcStatementDetailController extends BaseController {
+
+    private final IStatementDetailService statementDetailService;
+    private final IStatementOrderService statementOrderService;
+
+    /**
+     * 查询对账单明细列表
+     */
+    @GetMapping("/list")
+    public TableDataInfo<StatementDetailVo> list(StatementDetailBo bo, PageQuery pageQuery) {
+        if (bo.getStatementOrderId() != null) {
+            StatementOrderVo statement = statementOrderService.queryById(bo.getStatementOrderId());
+            if (statement != null) {
+                Long customerId = LoginHelper.getUserId();
+                if (!customerId.equals(statement.getCustomerId())) {
+                    throw new IllegalArgumentException("无权访问该对账单明细");
+                }
+            }
+        }
+        return statementDetailService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 获取对账单明细详细信息
+     */
+    @GetMapping("/{id}")
+    public R<StatementDetailVo> getInfo(@NotNull(message = "主键不能为空")
+                                        @PathVariable("id") Long id) {
+        StatementDetailVo vo = statementDetailService.queryById(id);
+        if (vo != null && vo.getStatementOrderId() != null) {
+            StatementOrderVo statement = statementOrderService.queryById(vo.getStatementOrderId());
+            if (statement != null) {
+                Long customerId = LoginHelper.getUserId();
+                if (!customerId.equals(statement.getCustomerId())) {
+                    return R.fail("无权访问该对账单明细");
+                }
+            }
+        }
+        return R.ok(vo);
+    }
+}

+ 58 - 0
ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/pc/controller/PcStatementInvoiceController.java

@@ -0,0 +1,58 @@
+package org.dromara.bill.pc.controller;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.validation.constraints.*;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.bill.domain.bo.StatementInvoiceBo;
+import org.dromara.bill.domain.vo.StatementInvoiceVo;
+import org.dromara.bill.service.IStatementInvoiceService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * PC端 - 对账单发票管理
+ * 前端访问路由地址为:/pc/enterprise/statementInvoice
+ *
+ * @author Claude
+ * @date 2026-01-29
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/pc/enterprise/statementInvoice")
+public class PcStatementInvoiceController extends BaseController {
+
+    private final IStatementInvoiceService statementInvoiceService;
+
+    /**
+     * 查询对账单发票列表
+     * PC端用户只能查询自己企业的对账单发票
+     */
+    @GetMapping("/list")
+    public TableDataInfo<StatementInvoiceVo> list(StatementInvoiceBo bo, PageQuery pageQuery) {
+        Long customerId = LoginHelper.getUserId();
+        bo.setCustomerId(customerId);
+        return statementInvoiceService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 获取对账单发票详细信息
+     * PC端用户只能查询自己企业的对账单发票
+     */
+    @GetMapping("/{id}")
+    public R<StatementInvoiceVo> getInfo(@NotNull(message = "主键不能为空")
+                                         @PathVariable("id") Long id) {
+        StatementInvoiceVo vo = statementInvoiceService.queryById(id);
+        if (vo != null) {
+            Long customerId = LoginHelper.getUserId();
+            if (!customerId.equals(vo.getCustomerId())) {
+                return R.fail("无权访问该对账单发票");
+            }
+        }
+        return R.ok(vo);
+    }
+}

+ 147 - 0
ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/pc/controller/PcStatementOrderController.java

@@ -0,0 +1,147 @@
+package org.dromara.bill.pc.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.RequiredArgsConstructor;
+import jakarta.validation.constraints.*;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.bill.domain.StatementOrder;
+import org.dromara.bill.domain.bo.StatementOrderBo;
+import org.dromara.bill.domain.vo.StatementOrderVo;
+import org.dromara.bill.domain.vo.StatementDetailVo;
+import org.dromara.bill.service.IStatementOrderService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * PC端 - 对账单管理
+ * 前端访问路由地址为:/pc/enterprise/statement
+ *
+ * @author Claude
+ * @date 2026-01-29
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/pc/enterprise/statement")
+public class PcStatementOrderController extends BaseController {
+
+    private final IStatementOrderService statementOrderService;
+
+    /**
+     * 查询当前企业的对账单列表
+     * PC端用户只能查询自己企业的对账单
+     * 只允许查询状态为 1(待对账)、2(已对账)、3(驳回) 的对账单
+     * 不允许查询状态为 0(待确认)、4(作废) 的对账单
+     */
+    @GetMapping("/list")
+    public TableDataInfo<StatementOrderVo> list(StatementOrderBo bo, PageQuery pageQuery) {
+        Long customerId = LoginHelper.getUserId();
+
+        // PC端权限控制:强制只查询状态为 1、2、3 的对账单
+        LambdaQueryWrapper<StatementOrder> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StatementOrder::getCustomerId, customerId);
+        wrapper.in(StatementOrder::getStatementStatus, Arrays.asList("1", "2", "3"));
+
+        // 如果用户指定了状态,且状态在允许范围内,则使用用户指定的状态
+        String statementStatus = bo.getStatementStatus();
+        if (statementStatus != null && !statementStatus.isEmpty()) {
+            if ("1".equals(statementStatus) || "2".equals(statementStatus) || "3".equals(statementStatus)) {
+                // 用户指定的状态在允许范围内,覆盖 IN 条件
+                wrapper.clear();
+                wrapper.eq(StatementOrder::getCustomerId, customerId);
+                wrapper.eq(StatementOrder::getStatementStatus, statementStatus);
+            }
+            // 如果用户指定了不允许的状态(0或4),保持 IN 条件,会返回空结果
+        }
+
+        // 添加其他查询条件
+        if (bo.getStatementOrderNo() != null && !bo.getStatementOrderNo().isEmpty()) {
+            wrapper.like(StatementOrder::getStatementOrderNo, bo.getStatementOrderNo());
+        }
+        if (bo.getIsInvoiceStatus() != null && !bo.getIsInvoiceStatus().isEmpty()) {
+            wrapper.eq(StatementOrder::getIsInvoiceStatus, bo.getIsInvoiceStatus());
+        }
+        if (bo.getIsPaymentStatus() != null && !bo.getIsPaymentStatus().isEmpty()) {
+            wrapper.eq(StatementOrder::getIsPaymentStatus, bo.getIsPaymentStatus());
+        }
+
+        // 使用新添加的 PC 端专用方法
+        return statementOrderService.queryPageListByWrapper(wrapper, pageQuery);
+    }
+
+    /**
+     * 获取对账单详细信息
+     * PC端用户只能查询自己企业的对账单
+     */
+    @GetMapping("/{id}")
+    public R<StatementOrderVo> getInfo(@NotNull(message = "主键不能为空")
+                                       @PathVariable("id") Long id) {
+        StatementOrderVo vo = statementOrderService.queryById(id);
+        if (vo != null) {
+            Long customerId = LoginHelper.getUserId();
+            if (!customerId.equals(vo.getCustomerId())) {
+                return R.fail("无权访问该对账单");
+            }
+        }
+        return R.ok(vo);
+    }
+
+    /**
+     * 查询当前企业的对账单明细列表
+     */
+    @GetMapping("/details")
+    public TableDataInfo<StatementDetailVo> getDetails(PageQuery pageQuery) {
+        Long customerId = LoginHelper.getUserId();
+        return statementOrderService.listDetailsByCustomerIdPage(customerId, pageQuery);
+    }
+
+    /**
+     * 确认对账单
+     */
+    @Log(title = "PC端-对账单确认", businessType = BusinessType.UPDATE)
+    @PutMapping("/confirm")
+    public R<Void> confirm(@RequestBody StatementOrderBo bo) {
+        Long customerId = LoginHelper.getUserId();
+        StatementOrderVo existingStatement = statementOrderService.queryById(bo.getId());
+        if (existingStatement == null) {
+            return R.fail("对账单不存在");
+        }
+        if (!customerId.equals(existingStatement.getCustomerId())) {
+            return R.fail("无权确认该对账单");
+        }
+        bo.setCustomerId(customerId);
+        bo.setStatementStatus("1");
+        return toAjax(statementOrderService.updateStatus(bo));
+    }
+
+    /**
+     * 驳回对账单
+     */
+    @Log(title = "PC端-对账单驳回", businessType = BusinessType.UPDATE)
+    @PutMapping("/reject")
+    public R<Void> reject(@RequestBody StatementOrderBo bo) {
+        Long customerId = LoginHelper.getUserId();
+        StatementOrderVo existingStatement = statementOrderService.queryById(bo.getId());
+        if (existingStatement == null) {
+            return R.fail("对账单不存在");
+        }
+        if (!customerId.equals(existingStatement.getCustomerId())) {
+            return R.fail("无权驳回该对账单");
+        }
+        bo.setCustomerId(customerId);
+        bo.setStatementStatus("2");
+        return toAjax(statementOrderService.updateStatus(bo));
+    }
+}

+ 103 - 0
ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/pc/controller/PcStatementProductController.java

@@ -0,0 +1,103 @@
+package org.dromara.bill.pc.controller;
+
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import lombok.RequiredArgsConstructor;
+import jakarta.validation.constraints.*;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.bill.domain.bo.StatementProductBo;
+import org.dromara.bill.domain.dto.StatementOrderItem;
+import org.dromara.bill.domain.vo.StatementProductVo;
+import org.dromara.bill.domain.vo.StatementOrderVo;
+import org.dromara.bill.service.IStatementProductService;
+import org.dromara.bill.service.IStatementOrderService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * PC端 - 对账单商品管理
+ * 前端访问路由地址为:/pc/enterprise/statementProduct
+ *
+ * @author Claude
+ * @date 2026-01-29
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/pc/enterprise/statementProduct")
+public class PcStatementProductController extends BaseController {
+
+    private final IStatementProductService statementProductService;
+    private final IStatementOrderService statementOrderService;
+
+    /**
+     * 查询对账单商品列表
+     */
+    @GetMapping("/list")
+    public TableDataInfo<StatementProductVo> list(StatementProductBo bo, PageQuery pageQuery) {
+        if (bo.getStatementOrderId() != null) {
+            StatementOrderVo statement = statementOrderService.queryById(bo.getStatementOrderId());
+            if (statement != null) {
+                Long customerId = LoginHelper.getUserId();
+                if (!customerId.equals(statement.getCustomerId())) {
+                    throw new IllegalArgumentException("无权访问该对账单商品");
+                }
+            }
+        }
+        return statementProductService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 根据订单ID查询对账单商品列表
+     */
+    @PostMapping("/getStatementProductList")
+    public TableDataInfo<StatementProductVo> getStatementProductList(
+        @RequestBody List<StatementOrderItem> items) {
+
+        if (CollectionUtils.isEmpty(items)) {
+            throw new IllegalArgumentException("至少选择一个订单");
+        }
+
+        if (items.stream().anyMatch(item -> item.getStatementOrderId() == null || item.getOrderId() == null)) {
+            throw new IllegalArgumentException("statementOrderId 和 orderId 不能为空");
+        }
+
+        Long customerId = LoginHelper.getUserId();
+        for (StatementOrderItem item : items) {
+            Long statementOrderId = Long.parseLong(item.getStatementOrderId());
+            StatementOrderVo statement = statementOrderService.queryById(statementOrderId);
+            if (statement == null) {
+                throw new IllegalArgumentException("对账单不存在");
+            }
+            if (!customerId.equals(statement.getCustomerId())) {
+                throw new IllegalArgumentException("无权访问该对账单商品");
+            }
+        }
+
+        return statementOrderService.getStatementProductList(items);
+    }
+
+    /**
+     * 获取对账单商品详细信息
+     */
+    @GetMapping("/{id}")
+    public R<StatementProductVo> getInfo(@NotNull(message = "主键不能为空")
+                                         @PathVariable("id") Long id) {
+        StatementProductVo vo = statementProductService.queryById(id);
+        if (vo != null && vo.getStatementOrderId() != null) {
+            StatementOrderVo statement = statementOrderService.queryById(vo.getStatementOrderId());
+            if (statement != null) {
+                Long customerId = LoginHelper.getUserId();
+                if (!customerId.equals(statement.getCustomerId())) {
+                    return R.fail("无权访问该对账单商品");
+                }
+            }
+        }
+        return R.ok(vo);
+    }
+}

+ 10 - 0
ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/service/IStatementOrderService.java

@@ -56,6 +56,16 @@ public interface IStatementOrderService extends IService<StatementOrder> {
      */
     TableDataInfo<StatementOrderVo> queryPageList(StatementOrderBo bo, PageQuery pageQuery);
 
+    /**
+     * 使用自定义 Wrapper 分页查询对账单列表
+     * 用于 PC 端权限控制,支持自定义查询条件
+     *
+     * @param wrapper   查询条件包装器
+     * @param pageQuery 分页参数
+     * @return 对账单主分页列表
+     */
+    TableDataInfo<StatementOrderVo> queryPageListByWrapper(com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<StatementOrder> wrapper, PageQuery pageQuery);
+
 
     TableDataInfo<StatementProductVo> getStatementProductList(List<StatementOrderItem> items);
 

+ 5 - 1
ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/service/impl/StatementInvoiceServiceImpl.java

@@ -224,12 +224,16 @@ public class StatementInvoiceServiceImpl extends ServiceImpl<StatementInvoiceMap
     }
 
     /**
-     * 公共方法:删除明细和商品
+     * 公共方法:删除明细,商品和发票明细
      */
     private void deleteDetailsAndProductsAndInvoiceInfos(Long statementInvoiceId) {
+
         statementInvoiceDetailMapper.deleteByStatementInvoiceId(statementInvoiceId);
+
         statementInvoiceProductMapper.deleteByStatementInvoiceId(statementInvoiceId);
+
         invoiceInfoMapper.deleteByStatementInvoiceId(statementInvoiceId);
+
     }
 
     /**

+ 23 - 4
ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/service/impl/StatementOrderServiceImpl.java

@@ -22,6 +22,7 @@ import org.dromara.bill.mapper.StatementDetailMapper;
 import org.dromara.bill.mapper.StatementOrderMapper;
 import org.dromara.bill.mapper.StatementProductMapper;
 import org.dromara.bill.service.IStatementOrderService;
+import org.dromara.common.core.enums.InvoiceStatus;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.PageQuery;
@@ -127,7 +128,7 @@ public class StatementOrderServiceImpl extends ServiceImpl<StatementOrderMapper,
 
         // 查询客户的所有有效对账单
         LambdaQueryWrapper<StatementOrder> orderWrapper = new LambdaQueryWrapper<>();
-        orderWrapper.eq(StatementOrder::getCustomerId, customerId)
+        orderWrapper.eq(StatementOrder::getCustomerId, customerId)//.ne(StatementOrder::getIsInvoiceStatus, InvoiceStatus.INVOICED.getCode())
             .eq(StatementOrder::getDelFlag, "0");
 
         List<StatementOrder> statementOrders = baseMapper.selectList(orderWrapper);
@@ -190,6 +191,20 @@ public class StatementOrderServiceImpl extends ServiceImpl<StatementOrderMapper,
         return TableDataInfo.build(result);
     }
 
+    /**
+     * 使用自定义 Wrapper 分页查询对账单列表
+     * 用于 PC 端权限控制,支持自定义查询条件
+     *
+     * @param wrapper   查询条件包装器
+     * @param pageQuery 分页参数
+     * @return 对账单主分页列表
+     */
+    @Override
+    public TableDataInfo<StatementOrderVo> queryPageListByWrapper(LambdaQueryWrapper<StatementOrder> wrapper, PageQuery pageQuery) {
+        Page<StatementOrderVo> result = baseMapper.selectVoPage(pageQuery.build(), wrapper);
+        return TableDataInfo.build(result);
+    }
+
     /**
      * 查询符合条件的对账单主列表
      *
@@ -307,14 +322,18 @@ public class StatementOrderServiceImpl extends ServiceImpl<StatementOrderMapper,
         Map<Long, List<StatementProductBo>> productGroupByOrderId =
             CollectionUtil.isNotEmpty(bo.getProductList())
                 ? bo.getProductList().stream()
+                .filter(product -> product.getOrderId() != null)
                 .collect(Collectors.groupingBy(StatementProductBo::getOrderId))
                 : Collections.emptyMap();
 
-        // 3. 为每个明细,找到对应的商品
+        // 3. 处理每个明细
         for (StatementDetailBo detailBo : bo.getDetailList()) {
-            Long originalOrderId = detailBo.getOrderId();
-            List<StatementProductBo> productListForThisOrder = productGroupByOrderId.get(originalOrderId);
+            Long originalOrderId = detailBo.getOrderId(); // 可能为 null
+            if (originalOrderId == null) {
+                continue; // 跳过无效明细
+            }
 
+            List<StatementProductBo> productListForThisOrder = productGroupByOrderId.get(originalOrderId);
             if (CollectionUtil.isNotEmpty(productListForThisOrder)) {
                 for (StatementProductBo productBo : productListForThisOrder) {
                     StatementProduct product = MapstructUtils.convert(productBo, StatementProduct.class);

+ 18 - 6
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/SupplierAuthorizeController.java

@@ -64,7 +64,7 @@ public class SupplierAuthorizeController extends BaseController {
      *
      * @param id 主键
      */
-    @SaCheckPermission("supplier:supplierauthorize:query")
+    //@SaCheckPermission("supplier:supplierauthorize:query")
     @GetMapping("/{id}")
     public R<SupplierAuthorizeVo> getInfo(@NotNull(message = "主键不能为空")
                                      @PathVariable("id") Long id) {
@@ -76,14 +76,26 @@ public class SupplierAuthorizeController extends BaseController {
      */
 //    @SaCheckPermission("supplier:supplierauthorize:query")
     @GetMapping("/getAuthorizeDetailList")
-    public R<List<SupplierAuthorizeVo>> getAuthorizeDetailList(Long supplierId) {
-        return R.ok(supplierAuthorizeService.getAuthorizeDetailList(supplierId));
+    public R<List<SupplierAuthorizeVo>> getAuthorizeDetailList(Long supplierId, PageQuery pageQuery) {
+        return R.ok(supplierAuthorizeService.getAuthorizeDetailList(supplierId, pageQuery));
     }
 
+    @GetMapping("/getDetailList")
+    public R<List<SupplierAuthorizeVo>> getDetailList(SupplierAuthorizeBo bo) {
+        return R.ok(supplierAuthorizeService.srmgetAuthorizeDetailList(bo));
+    }
+
+    @GetMapping("/getBrandAuthorizeDetail")
+    public R<SupplierAuthorizeVo> getBrandAuthorizeDetail(@RequestParam Long id) {
+        return R.ok(supplierAuthorizeService.getBrandAuthorizeDetail(id));
+    }
+
+
+
     /**
      * 供应能力查询信息列表
      */
-    @SaCheckPermission("supplier:supplierauthorize:list")
+    //@SaCheckPermission("supplier:supplierauthorize:list")
     @GetMapping("/getSupplyCapacityList")
     public TableDataInfo<SupplierAuthorizeVo> getSupplyCapacityList(SupplierAuthorizeBo bo, PageQuery pageQuery) {
         return supplierAuthorizeService.getSupplyCapacityList(bo, pageQuery);
@@ -92,7 +104,7 @@ public class SupplierAuthorizeController extends BaseController {
     /**
      * 新增供应能力查询
      */
-    @SaCheckPermission("supplier:supplierauthorize:add")
+    //@SaCheckPermission("supplier:supplierauthorize:add")
     @Log(title = "供应能力查询", businessType = BusinessType.INSERT)
     @RepeatSubmit()
     @PostMapping()
@@ -103,7 +115,7 @@ public class SupplierAuthorizeController extends BaseController {
     /**
      * 修改供应能力查询
      */
-    @SaCheckPermission("supplier:supplierauthorize:edit")
+    //@SaCheckPermission("supplier:supplierauthorize:edit")
     @Log(title = "供应能力查询", businessType = BusinessType.UPDATE)
     @RepeatSubmit()
     @PutMapping()

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

@@ -83,7 +83,7 @@ public class SupplierContractController extends BaseController {
      *
      * @param id 主键
      */
-    @SaCheckPermission("supplier:contract:query")
+    //@SaCheckPermission("supplier:contract:query")
     @GetMapping("/{id}")
     public R<SupplierContractVo> getInfo(@NotNull(message = "主键不能为空")
                                      @PathVariable("id") Long id) {

+ 106 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/SupplierQualificationController.java

@@ -0,0 +1,106 @@
+package org.dromara.customer.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.customer.domain.vo.SupplierQualificationVo;
+import org.dromara.customer.domain.bo.SupplierQualificationBo;
+import org.dromara.customer.service.ISupplierQualificationService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 供应商资质信息
+ * 前端访问路由地址为:/supplier/qualification
+ *
+ * @author LionLi
+ * @date 2026-01-27
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/qualification")
+public class SupplierQualificationController extends BaseController {
+
+    private final ISupplierQualificationService supplierQualificationService;
+
+    /**
+     * 查询供应商资质信息列表
+     */
+    //@SaCheckPermission("supplier:qualification:list")
+    @GetMapping("/list")
+    public TableDataInfo<SupplierQualificationVo> list(SupplierQualificationBo bo, PageQuery pageQuery) {
+        return supplierQualificationService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出供应商资质信息列表
+     */
+    //@SaCheckPermission("supplier:qualification:export")
+    @Log(title = "供应商资质信息", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(SupplierQualificationBo bo, HttpServletResponse response) {
+        List<SupplierQualificationVo> list = supplierQualificationService.queryList(bo);
+        ExcelUtil.exportExcel(list, "供应商资质信息", SupplierQualificationVo.class, response);
+    }
+
+    /**
+     * 获取供应商资质信息详细信息
+     *
+     * @param id 主键
+     */
+    //@SaCheckPermission("supplier:qualification:query")
+    @GetMapping("/{id}")
+    public R<SupplierQualificationVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable("id") Long id) {
+        return R.ok(supplierQualificationService.queryById(id));
+    }
+
+    /**
+     * 新增供应商资质信息
+     */
+    //@SaCheckPermission("supplier:qualification:add")
+    @Log(title = "供应商资质信息", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody SupplierQualificationBo bo) {
+        return toAjax(supplierQualificationService.insertByBo(bo));
+    }
+
+    /**
+     * 修改供应商资质信息
+     */
+    //@SaCheckPermission("supplier:qualification:edit")
+    @Log(title = "供应商资质信息", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody SupplierQualificationBo bo) {
+        return toAjax(supplierQualificationService.updateByBo(bo));
+    }
+
+    /**
+     * 删除供应商资质信息
+     *
+     * @param ids 主键串
+     */
+    //@SaCheckPermission("supplier:qualification:remove")
+    @Log(title = "供应商资质信息", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable("ids") Long[] ids) {
+        return toAjax(supplierQualificationService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

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

@@ -66,8 +66,12 @@ public class CustomerContact extends TenantEntity {
      */
     private Long roleId;
 
+    private String roleName;
+
     private Long deptId;
 
+    private String deptName;
+
     private String email;
 
     private Date birthday;

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

@@ -34,6 +34,8 @@ public class QualificationFile extends TenantEntity {
      */
     private String authorizeNo;
 
+    private Long authorizeId;
+
     /**
      * 资质类型名称
      */

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

@@ -39,6 +39,8 @@ public class SupplierAuthorize extends TenantEntity {
      */
     private String supplierNo;
 
+    private Long brandId;
+
     /**
      * 供应商ID
      */

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

@@ -79,7 +79,7 @@ public class SupplierContract extends TenantEntity {
     /**
      * 发票类型(如增值税专票/普票)
      */
-    private String invoiceType;
+    private Long invoiceType;
 
     /**
      * 税率(如13%/9%/6%)
@@ -89,7 +89,7 @@ public class SupplierContract extends TenantEntity {
     /**
      * 结算方式(如月结/季结/一次性)
      */
-    private String settlementMethod;
+    private Long settlementMethod;
 
     /**
      * 合同说明

+ 96 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/SupplierQualification.java

@@ -0,0 +1,96 @@
+package org.dromara.customer.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.io.Serial;
+
+/**
+ * 供应商资质信息对象 supplier_qualification
+ *
+ * @author LionLi
+ * @date 2026-01-27
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("supplier_qualification")
+public class SupplierQualification extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 资质名称(对应表单“资质名称”)
+     */
+    private String qualificationName;
+
+    /**
+     * 资质级别(对应表单“资质级别”)
+     */
+    private String qualificationLevel;
+
+    private Long qualificationLevelId;
+
+    /**
+     * 证件编号(对应表单“证件编号”)
+     */
+    private String certificateNo;
+
+    /**
+     * 发证机构(对应表单“发证机构”)
+     */
+    private String issuingAuthority;
+
+    /**
+     * 资质有效期-开始日期(对应表单“开始日期”)
+     */
+    private Date startDate;
+
+    /**
+     * 资质有效期-结束日期(对应表单“结束日期”,长期有效时为NULL)
+     */
+    private Date endDate;
+
+    /**
+     * 是否长期有效(0=否 1=是,对应表单“长期有效”复选框)
+     */
+    private Long isLongValid;
+
+    /**
+     * 附件存储地址(对应表单“上传附件”)
+     */
+    private String attachmentUrl;
+
+    /**
+     * 附件原文件名
+     */
+    private String attachmentName;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 6 - 2
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/CustomerContactBo.java

@@ -35,13 +35,13 @@ public class CustomerContactBo extends BaseEntity {
     /**
      * 联系人姓名
      */
-    @NotBlank(message = "联系人姓名不能为空", groups = {AddGroup.class, EditGroup.class})
+//    @NotBlank(message = "联系人姓名不能为空", groups = {AddGroup.class, EditGroup.class})
     private String contactName;
 
     /**
      * 手机号码
      */
-    @NotBlank(message = "手机号码不能为空", groups = {AddGroup.class, EditGroup.class})
+//    @NotBlank(message = "手机号码不能为空", groups = {AddGroup.class, EditGroup.class})
     private String phone;
 
     /**
@@ -67,8 +67,12 @@ public class CustomerContactBo extends BaseEntity {
      */
     private Long roleId;
 
+    private String roleName;
+
     private Long deptId;
 
+    private String deptName;
+
     private String email;
 
     private Date birthday;

+ 3 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/QualificationFileBo.java

@@ -32,6 +32,9 @@ public class QualificationFileBo extends BaseEntity {
      */
     private String authorizeNo;
 
+
+    private Long authorizeId;
+
     /**
      * 资质类型名称
      */

+ 8 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/SupplierAuthorizeBo.java

@@ -1,5 +1,6 @@
 package org.dromara.customer.domain.bo;
 
+import org.dromara.customer.domain.QualificationFile;
 import org.dromara.customer.domain.SupplierAuthorize;
 import org.dromara.common.mybatis.core.domain.BaseEntity;
 import org.dromara.common.core.validate.AddGroup;
@@ -158,5 +159,12 @@ public class SupplierAuthorizeBo extends BaseEntity {
      */
     private String city;
 
+    private Long brandId;
+
+
+    private List<QualificationFile>  qualificationFiles;
+
+    private List<Long> categoryIds;
+
 
 }

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

@@ -54,13 +54,44 @@ public class SupplierContractBo extends BaseEntity {
     /**
      * 合同类型(年度合作/项目采购/其他合作)
      */
-    private Long contractType;
+    private String contractType;
 
     /**
      * 合同生效时间
      */
     private Date contractStartTime;
 
+    /**
+     * 发票类型(如增值税专票/普票)
+     */
+    private Long invoiceType;
+
+    /**
+     * 结算方式(如月结/季结/一次性)
+     */
+    private Long settlementMethod;
+
+    /**
+     * 项目负责人(姓名/工号)
+     */
+    private String projectLeader;
+
+    /**
+     * 状态变更原因(如终止原因/作废理由)
+     */
+    private String reason;
+
+    /**
+     * 合同附件原文件名
+     */
+    private String filename;
+
+    /**
+     * 备注信息
+     */
+    private String remark;
+
+
     /**
      * 合同到期时间
      */

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

@@ -159,6 +159,8 @@ public class SupplierInfoBo extends BaseEntity {
     //@NotBlank(message = "注册地址-省不能为空", groups = { AddGroup.class, EditGroup.class })
     private String businessProvince;
 
+    private String businessLicense;
+
     /**
      * 注册地址-市
      */
@@ -180,8 +182,7 @@ public class SupplierInfoBo extends BaseEntity {
     /**
      * 营业执照图片路径
      */
-    //@NotBlank(message = "营业执照图片路径不能为空", groups = { AddGroup.class, EditGroup.class })
-    private String businessLicense;
+
 
     /**
      * 发票类型

+ 80 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/SupplierQualificationBo.java

@@ -0,0 +1,80 @@
+package org.dromara.customer.domain.bo;
+
+import org.dromara.customer.domain.SupplierQualification;
+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.*;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 供应商资质信息业务对象 supplier_qualification
+ *
+ * @author LionLi
+ * @date 2026-01-27
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = SupplierQualification.class, reverseConvertGenerate = false)
+public class SupplierQualificationBo extends BaseEntity {
+
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 资质名称(对应表单“资质名称”)
+     */
+    private String qualificationName;
+
+    /**
+     * 资质级别(对应表单“资质级别”)
+     */
+    private String qualificationLevel;
+
+    /**
+     * 证件编号(对应表单“证件编号”)
+     */
+    private String certificateNo;
+
+    /**
+     * 发证机构(对应表单“发证机构”)
+     */
+    private String issuingAuthority;
+
+    private Long qualificationLevelId;
+
+    /**
+     * 资质有效期-开始日期(对应表单“开始日期”)
+     */
+    private Date startDate;
+
+    /**
+     * 资质有效期-结束日期(对应表单“结束日期”,长期有效时为NULL)
+     */
+    private Date endDate;
+
+    /**
+     * 是否长期有效(0=否 1=是,对应表单“长期有效”复选框)
+     */
+    private Long isLongValid;
+
+    /**
+     * 附件存储地址(对应表单“上传附件”)
+     */
+    private String attachmentUrl;
+
+    /**
+     * 附件原文件名
+     */
+    private String attachmentName;
+
+    private String remark;
+
+
+}

+ 5 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/bo/SupplierapproveBo.java

@@ -1,5 +1,6 @@
 package org.dromara.customer.domain.bo;
 
+import org.dromara.customer.domain.QualificationFile;
 import org.dromara.customer.domain.Supplierapprove;
 import org.dromara.common.mybatis.core.domain.BaseEntity;
 import org.dromara.common.core.validate.AddGroup;
@@ -10,6 +11,8 @@ import lombok.EqualsAndHashCode;
 import jakarta.validation.constraints.*;
 import org.dromara.common.translation.annotation.Translation;
 import java.util.Date;
+import java.util.List;
+
 import com.fasterxml.jackson.annotation.JsonFormat;
 import org.dromara.common.translation.constant.TransConstant;
 
@@ -62,4 +65,6 @@ public class SupplierapproveBo extends BaseEntity {
     private String status;
 
 
+
+
 }

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

@@ -40,7 +40,6 @@ public class CustomerContactVo implements Serializable {
     private Long customerId;
 
 
-
     /**
      * 联系人姓名
      */
@@ -79,11 +78,14 @@ public class CustomerContactVo implements Serializable {
      * 采购角色(如:采购经理、财务)
      */
     @ExcelProperty(value = "采购角色", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(readConverterExp = "如=:采购经理、财务")
     private Long roleId;
 
+    private String roleName;
+
     private Long deptId;
 
+    private String deptName;
+
     /**
      * 是否主联系人:0=是,1=否
      */

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

@@ -42,6 +42,8 @@ public class QualificationFileVo implements Serializable {
     @ExcelProperty(value = "资质编号")
     private String authorizeNo;
 
+    private Long authorizeId;
+
     /**
      * 资质类型名称
      */

+ 9 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/SupplierAuthorizeVo.java

@@ -2,6 +2,7 @@ package org.dromara.customer.domain.vo;
 
 import java.util.Date;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import org.dromara.customer.domain.QualificationFile;
 import org.dromara.customer.domain.SupplierAuthorize;
 import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
 import cn.idev.excel.annotation.ExcelProperty;
@@ -13,6 +14,7 @@ import lombok.Data;
 import java.io.Serial;
 import java.io.Serializable;
 import java.util.Date;
+import java.util.List;
 import java.util.Map;
 
 
@@ -37,6 +39,8 @@ public class SupplierAuthorizeVo implements Serializable {
      */
     private Long categoryId;
 
+    private Long brandId;
+
     /**
      * 供应商编号
      */
@@ -204,4 +208,9 @@ public class SupplierAuthorizeVo implements Serializable {
     Map<String, String> categorysMap;
 
 
+    private List<QualificationFile> qualificationFiles;
+
+
+
+
 }

+ 47 - 1
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/SupplierContractVo.java

@@ -55,7 +55,7 @@ public class SupplierContractVo implements Serializable {
     /**
      * 合同类型(年度合作/项目采购/其他合作)
      */
-    private Long contractType;
+    private String contractType;
 
     /**
      * 合同名称
@@ -79,6 +79,21 @@ public class SupplierContractVo implements Serializable {
      */
     private Date contractEndTime;
 
+    /**
+     * 到期提醒时间(单位:天,如提前7天提醒)
+     */
+    private Long demandReminderTime;
+
+    /**
+     * 发票类型(如增值税专票/普票)
+     */
+    private Long invoiceType;
+
+    /**
+     * 结算方式(如月结/季结/一次性)
+     */
+    private Long settlementMethod;
+
 
     /**
      * 上传时间
@@ -90,6 +105,36 @@ public class SupplierContractVo implements Serializable {
      */
     private Long contractStatus;
 
+    /**
+     * 税率(如13%/9%/6%)
+     */
+    private Long taxRate;
+    /**
+     * 合同说明
+     */
+    private String contractDescription;
+    /**
+     * 项目负责人(姓名/工号)
+     */
+    private String projectLeader;
+
+    /**
+     * 状态变更原因(如终止原因/作废理由)
+     */
+    private String reason;
+
+    /**
+     * 合同附件原文件名
+     */
+    private String filename;
+
+    /**
+     * 备注信息
+     */
+    private String remark;
+
+
+
 
     /**
      * 合同附件存储地址(多个附件用分隔符区分)
@@ -110,4 +155,5 @@ public class SupplierContractVo implements Serializable {
      */
     private String invalidContract;
 
+
 }

+ 1 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/SupplierInfoVo.java

@@ -68,6 +68,7 @@ public class SupplierInfoVo implements Serializable {
     @ExcelProperty(value = "合作类型")
     private Long cooperationType;
 
+
     /**
      * 固定电话
      */

+ 106 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/domain/vo/SupplierQualificationVo.java

@@ -0,0 +1,106 @@
+package org.dromara.customer.domain.vo;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.dromara.customer.domain.SupplierQualification;
+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;
+
+
+
+/**
+ * 供应商资质信息视图对象 supplier_qualification
+ *
+ * @author LionLi
+ * @date 2026-01-27
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = SupplierQualification.class)
+public class SupplierQualificationVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    @ExcelProperty(value = "主键ID")
+    private Long id;
+
+    /**
+     * 资质名称(对应表单“资质名称”)
+     */
+    @ExcelProperty(value = "资质名称", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "对=应表单“资质名称”")
+    private String qualificationName;
+
+    /**
+     * 资质级别(对应表单“资质级别”)
+     */
+    @ExcelProperty(value = "资质级别", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "对=应表单“资质级别”")
+    private String qualificationLevel;
+
+    private Long qualificationLevelId;
+
+    /**
+     * 证件编号(对应表单“证件编号”)
+     */
+    @ExcelProperty(value = "证件编号", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "对=应表单“证件编号”")
+    private String certificateNo;
+
+    /**
+     * 发证机构(对应表单“发证机构”)
+     */
+    @ExcelProperty(value = "发证机构", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "对=应表单“发证机构”")
+    private String issuingAuthority;
+
+    /**
+     * 资质有效期-开始日期(对应表单“开始日期”)
+     */
+    @ExcelProperty(value = "资质有效期-开始日期", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "对=应表单“开始日期”")
+    private Date startDate;
+
+    /**
+     * 资质有效期-结束日期(对应表单“结束日期”,长期有效时为NULL)
+     */
+    @ExcelProperty(value = "资质有效期-结束日期", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "对=应表单“结束日期”,长期有效时为NULL")
+    private Date endDate;
+
+    /**
+     * 是否长期有效(0=否 1=是,对应表单“长期有效”复选框)
+     */
+    @ExcelProperty(value = "是否长期有效", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "0==否,1==是,对应表单“长期有效”复选框")
+    private Long isLongValid;
+
+    /**
+     * 附件存储地址(对应表单“上传附件”)
+     */
+    @ExcelProperty(value = "附件存储地址", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "对=应表单“上传附件”")
+    private String attachmentUrl;
+
+    /**
+     * 附件原文件名
+     */
+    @ExcelProperty(value = "附件原文件名")
+    private String attachmentName;
+
+    private String remark;
+
+
+}

+ 15 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/mapper/SupplierQualificationMapper.java

@@ -0,0 +1,15 @@
+package org.dromara.customer.mapper;
+
+import org.dromara.customer.domain.SupplierQualification;
+import org.dromara.customer.domain.vo.SupplierQualificationVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 供应商资质信息Mapper接口
+ *
+ * @author LionLi
+ * @date 2026-01-27
+ */
+public interface SupplierQualificationMapper extends BaseMapperPlus<SupplierQualification, SupplierQualificationVo> {
+
+}

+ 4 - 1
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ISupplierAuthorizeService.java

@@ -69,9 +69,12 @@ public interface ISupplierAuthorizeService extends IService<SupplierAuthorize>{
      */
     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
 
-    List<SupplierAuthorizeVo> getAuthorizeDetailList(Long supplierId);
+    List<SupplierAuthorizeVo> getAuthorizeDetailList(Long supplierId,PageQuery pageQuery);
+
+    List<SupplierAuthorizeVo> srmgetAuthorizeDetailList(SupplierAuthorizeBo  bo);
 
     TableDataInfo<SupplierAuthorizeVo> getSupplyCapacityList(SupplierAuthorizeBo bo, PageQuery pageQuery);
 
 
+    SupplierAuthorizeVo getBrandAuthorizeDetail(Long id);
 }

+ 70 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ISupplierQualificationService.java

@@ -0,0 +1,70 @@
+package org.dromara.customer.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.customer.domain.SupplierQualification;
+import org.dromara.customer.domain.vo.SupplierQualificationVo;
+import org.dromara.customer.domain.bo.SupplierQualificationBo;
+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-27
+ */
+public interface ISupplierQualificationService extends IService<SupplierQualification>{
+
+    /**
+     * 查询供应商资质信息
+     *
+     * @param id 主键
+     * @return 供应商资质信息
+     */
+    SupplierQualificationVo queryById(Long id);
+
+    /**
+     * 分页查询供应商资质信息列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 供应商资质信息分页列表
+     */
+    TableDataInfo<SupplierQualificationVo> queryPageList(SupplierQualificationBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的供应商资质信息列表
+     *
+     * @param bo 查询条件
+     * @return 供应商资质信息列表
+     */
+    List<SupplierQualificationVo> queryList(SupplierQualificationBo bo);
+
+    /**
+     * 新增供应商资质信息
+     *
+     * @param bo 供应商资质信息
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(SupplierQualificationBo bo);
+
+    /**
+     * 修改供应商资质信息
+     *
+     * @param bo 供应商资质信息
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(SupplierQualificationBo bo);
+
+    /**
+     * 校验并批量删除供应商资质信息信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 22 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerInfoServiceImpl.java

@@ -1,6 +1,7 @@
 package org.dromara.customer.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.crypto.digest.BCrypt;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -15,12 +16,14 @@ import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.satoken.utils.LoginHelper;
 import org.dromara.customer.domain.*;
 import org.dromara.customer.domain.bo.*;
 import org.dromara.customer.domain.vo.*;
 import org.dromara.customer.mapper.*;
 import org.dromara.customer.service.ICustomerInfoService;
 import org.dromara.system.api.*;
+import org.dromara.system.api.domain.bo.RemoteUserBo;
 import org.dromara.system.api.domain.vo.RemoteDeptVo;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -43,6 +46,8 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
     @DubboReference
     private RemoteDeptService remoteDeptService;
     @DubboReference
+    private RemoteUserService remoteUserService;
+    @DubboReference
     private RemoteComPostService remoteComPostService;
     @DubboReference
     private RemoteComStaffService remoteComStaffService;
@@ -593,6 +598,23 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
 
             // 联系人列表
             if (contactList != null && !contactList.isEmpty()) {
+                CustomerContactBo primaryContact = contactList.stream()
+                    .filter(contact -> contact.getIsPrimary().equals("0"))
+                    .findFirst()
+                    .orElse(null);
+                RemoteUserBo remoteUserBo = new RemoteUserBo();
+                remoteUserBo.setNickName(bo.getCustomerName());
+                if (null != primaryContact) {
+                    remoteUserBo.setUserName(primaryContact.getPhone());
+                } else {
+                    remoteUserBo.setUserName(contactList.get(0).getPhone());
+                }
+
+                String password = "123456";
+                remoteUserBo.setPassword(BCrypt.hashpw(password));
+                remoteUserBo.setUserSonType("3");
+                remoteUserBo.setTenantId(LoginHelper.getTenantId());
+                remoteUserService.addUser(remoteUserBo);
                 for (CustomerContactBo contactBo : contactList) {
                     CustomerContact contact = MapstructUtils.convert(contactBo, CustomerContact.class);
                     contact.setCustomerId(customerId);

+ 382 - 45
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierAuthorizeServiceImpl.java

@@ -1,5 +1,6 @@
 package org.dromara.customer.service.impl;
 
+import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.apache.dubbo.config.annotation.DubboReference;
@@ -12,15 +13,19 @@ 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.customer.domain.QualificationFile;
 import org.dromara.customer.domain.SupplierInfo;
 import org.dromara.customer.domain.SupplyArea;
 import org.dromara.customer.domain.vo.SupplierContractVo;
 import org.dromara.customer.domain.vo.SupplyAreaVo;
+import org.dromara.customer.service.IQualificationFileService;
 import org.dromara.customer.service.ISupplierInfoService;
 import org.dromara.customer.service.ISupplyAreaService;
 import org.dromara.product.api.RemoteCategoryService;
 import org.dromara.product.api.RemoteProductService;
 import org.dromara.product.api.domain.RemoteProductBrand;
+import org.dromara.system.api.RemoteAddressAreaService;
+import org.dromara.system.api.domain.dto.AddressAreaDTO;
 import org.springframework.beans.BeanUtils;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Service;
@@ -29,9 +34,12 @@ import org.dromara.customer.domain.vo.SupplierAuthorizeVo;
 import org.dromara.customer.domain.SupplierAuthorize;
 import org.dromara.customer.mapper.SupplierAuthorizeMapper;
 import org.dromara.customer.service.ISupplierAuthorizeService;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 
+import java.text.SimpleDateFormat;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 /**
@@ -53,13 +61,168 @@ public class SupplierAuthorizeServiceImpl  extends ServiceImpl<SupplierAuthorize
 
     private final StringRedisTemplate stringRedisTemplate;
 
+    private final IQualificationFileService qualificationFileService;
+
     @DubboReference
     private final RemoteCategoryService remoteCategoryService;
 
     @DubboReference
     private final RemoteProductService remoteProductService;
 
-    private static final String SUPPLY_CAPACITY_KEY = "supply_capacity:";
+    @DubboReference
+    private final RemoteAddressAreaService remoteAddressAreaService;
+
+    // 日期格式化(yyyyMMdd)
+    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd");
+    // 序号Key前缀
+    private static final String SEQ_KEY_PREFIX = "supplier:authorize:seq:";
+    // 序号过期时间(1天,避免Redis冗余数据)
+    private static final long EXPIRE_DAYS = 1;
+
+
+    /**
+     * 新增供应能力查询
+     *
+     * @param bo 供应能力查询
+     * @return 是否新增成功
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean insertByBo(SupplierAuthorizeBo bo) {
+        // 1. 校验入参
+        if (bo.getCategoryIds() == null || bo.getCategoryIds().isEmpty()) {
+            throw new RuntimeException("品类ID列表不能为空");
+        }
+        if (bo.getQualificationFiles() == null) {
+            throw new RuntimeException("资质文件不能为空");
+        }
+        Date endDate = bo.getQualificationFiles().stream()
+            .filter(file -> file.getEndTime() != null)
+            .map(QualificationFile::getEndTime)
+            .min(Date::compareTo)
+            .orElse(null);
+        // 2. 遍历categoryIds,逐个插入主表
+        List<QualificationFile> allFiles = new ArrayList<>();
+        List<Long> categoryIds = bo.getCategoryIds();
+        for (Long categoryId : categoryIds) {
+            // 核心变更:从Redis生成唯一授权单号(替代数据库查询)
+            String authorizeNo =generateAuthorizeNo();
+
+            // 构建主表数据
+            SupplierAuthorize save = new SupplierAuthorize();
+            BeanUtils.copyProperties(bo, save);
+            save.setAuthorizeNo(authorizeNo);
+            save.setCategoryId(categoryId);
+            save.setAuthorizationEndTime(endDate);
+            save.setAuthorizedStatus("0");
+
+            // 插入主表(MyBatis-Plus自动回填ID)
+            int insert = baseMapper.insert(save);
+            Long approveId = save.getId();
+
+            // 构建关联文件数据
+            for (QualificationFile file : bo.getQualificationFiles()) {
+                QualificationFile saveFile = new QualificationFile();
+                BeanUtils.copyProperties(file, saveFile);
+                saveFile.setAuthorizeId(approveId);
+                saveFile.setAuthorizeNo(authorizeNo);
+                allFiles.add(saveFile);
+            }
+        }
+
+        boolean flag = false;
+        if (!allFiles.isEmpty()) {
+            flag = qualificationFileService.saveBatch(allFiles);
+        }
+
+        return flag;
+    }
+
+    /**
+     * 修改供应能力查询
+     *
+     * @param bo 供应能力查询
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(SupplierAuthorizeBo bo) {
+        Date endDate = bo.getQualificationFiles().stream()
+            .filter(file -> file.getEndTime() != null)
+            .map(QualificationFile::getEndTime)
+            .min(Date::compareTo)
+            .orElse(null);
+
+        // 步骤1:删除该授权单下的旧资质文件(先删后加,避免文件冗余)
+        LambdaQueryWrapper<QualificationFile> fileWrapper = new LambdaQueryWrapper<>();
+        fileWrapper.eq(QualificationFile::getAuthorizeId, bo.getId());
+        qualificationFileService.remove(fileWrapper);
+
+        // 步骤2:更新授权单主表信息
+        SupplierAuthorize update = new SupplierAuthorize();
+        BeanUtils.copyProperties(bo, update);
+        update.setAuthorizationEndTime(endDate);
+        // 如需保留原有授权单号,注释下面这行;如需重新生成,放开
+        // update.setAuthorizeNo(generateAuthorizeNo());
+
+        int updateCount = baseMapper.updateById(update);
+        if (updateCount == 0) {
+            throw new RuntimeException("授权单不存在,修改失败");
+        }
+
+        // 步骤3:插入新的资质文件
+        List<QualificationFile> allFiles = new ArrayList<>();
+        Long approveId = bo.getId();
+        String authorizeNo = bo.getAuthorizeNo(); // 用原有授权单号
+        for (QualificationFile file : bo.getQualificationFiles()) {
+            QualificationFile saveFile = new QualificationFile();
+            BeanUtils.copyProperties(file, saveFile);
+            saveFile.setAuthorizeId(approveId);
+            saveFile.setAuthorizeNo(authorizeNo);
+            allFiles.add(saveFile);
+        }
+
+        // 批量插入新文件
+        boolean flag = false;
+        if (!allFiles.isEmpty()) {
+            flag = qualificationFileService.saveBatch(allFiles);
+        }
+        return flag;
+    }
+
+
+
+    /**
+     * 生成当日自增序号
+     * @return 当日序号(如1、2、3...)
+     */
+    public int generateDailySeq() {
+        // 1. 生成当日Key(如supplier:authorize:seq:20260127)
+        String dateStr = DATE_FORMAT.format(new Date());
+        String seqKey = SEQ_KEY_PREFIX + dateStr;
+
+        // 2. Redis原子自增(不存在则初始化为1)
+        Long seq = stringRedisTemplate.opsForValue().increment(seqKey, 1);
+        int currentSeq = seq.intValue();
+
+        // 3. 首次生成时设置过期时间(仅执行一次)
+        if (currentSeq == 1) {
+            stringRedisTemplate.expire(seqKey, EXPIRE_DAYS, TimeUnit.DAYS);
+        }
+
+        return currentSeq;
+    }
+
+    /**
+     * 生成完整授权单号(日期+5位补零序号)
+     * @return 如2026012700001
+     */
+    public String generateAuthorizeNo() {
+        String dateStr = DATE_FORMAT.format(new Date());
+        int seq = generateDailySeq();
+        // 5位补零(如1→00001,10→00010)
+        String seqStr = String.format("%05d", seq);
+        return dateStr + seqStr;
+    }
 
     /**
      * 查询供应能力查询
@@ -188,8 +351,42 @@ public class SupplierAuthorizeServiceImpl  extends ServiceImpl<SupplierAuthorize
         // 设置转换后的Vo列表
         voPage.setRecords(collect);
         return TableDataInfo.build(voPage);
+
+
+    }
+
+    @Override
+    public SupplierAuthorizeVo getBrandAuthorizeDetail(Long id) {
+        SupplierAuthorizeVo supplierAuthorizeVo = baseMapper.selectVoById(id);
+        if (supplierAuthorizeVo == null){
+            throw new RuntimeException("未找到授权信息");
+        }
+
+        setSupplyAreaInfoForSingle(supplierAuthorizeVo);
+
+        // 查询资质文件列表并赋值给VO
+        List<QualificationFile> qualificationFiles = qualificationFileService.list(
+            new LambdaQueryWrapper<QualificationFile>()
+                .eq(QualificationFile::getAuthorizeId, id)
+        );
+        supplierAuthorizeVo.setQualificationFiles(qualificationFiles);
+
+        // 查询一级二级三级产品分类
+        Long categoryId = supplierAuthorizeVo.getCategoryId();
+        if (categoryId != null) {
+            // 调用远程分类服务获取完整的分类信息
+            Map<String, String> categoryMap = remoteCategoryService.getallCategoryNameById(
+                Collections.singletonMap(supplierAuthorizeVo.getId(), categoryId)
+            ).get(supplierAuthorizeVo.getId());
+
+            if (categoryMap != null) {
+                supplierAuthorizeVo.setCategorysMap(categoryMap);
+            }
+        }
+        return supplierAuthorizeVo;
     }
 
+
     private Map<Long, String> supplierBrandMap(List<Long> ids){
         List<SupplierAuthorize> authorizeList = baseMapper.selectList(
             new LambdaQueryWrapper<SupplierAuthorize>()
@@ -309,35 +506,9 @@ public class SupplierAuthorizeServiceImpl  extends ServiceImpl<SupplierAuthorize
         return lqw;
     }
 
-    /**
-     * 新增供应能力查询
-     *
-     * @param bo 供应能力查询
-     * @return 是否新增成功
-     */
-    @Override
-    public Boolean insertByBo(SupplierAuthorizeBo bo) {
-        SupplierAuthorize add = MapstructUtils.convert(bo, SupplierAuthorize.class);
-        // stringRedisTemplate.opsForValue().set(RedisConstants.SUPPLY_CAPACITY_KEY+add.getId(),add);
-        boolean flag = baseMapper.insert(add) > 0;
-        if (flag){
-            add.setId(add.getId());
-        }
-        return flag;
-    }
 
-    /**
-     * 修改供应能力查询
-     *
-     * @param bo 供应能力查询
-     * @return 是否修改成功
-     */
-    @Override
-    public Boolean updateByBo(SupplierAuthorizeBo bo) {
-        SupplierAuthorize update = MapstructUtils.convert(bo, SupplierAuthorize.class);
-        validEntityBeforeSave(update);
-        return baseMapper.updateById(update) > 0;
-    }
+
+
 
     /**
      * 保存前的数据校验
@@ -362,26 +533,17 @@ public class SupplierAuthorizeServiceImpl  extends ServiceImpl<SupplierAuthorize
     }
 
     @Override
-    public List<SupplierAuthorizeVo> getAuthorizeDetailList(Long supplierId) {
+    public List<SupplierAuthorizeVo> getAuthorizeDetailList(Long supplierId,PageQuery pageQuery) {
         LambdaQueryWrapper<SupplierAuthorize> lqw = new LambdaQueryWrapper<>();
         lqw.eq(SupplierAuthorize::getSupplierId, supplierId);
-        List<SupplierAuthorizeVo> supplierAuthorizeVos = baseMapper.selectVoList(lqw);
+        Page<SupplierAuthorize> page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize());
+        IPage<SupplierAuthorizeVo> supplierAuthorizePage = baseMapper.selectVoPage(page,lqw);
+        List<SupplierAuthorizeVo> supplierAuthorizeVos = supplierAuthorizePage.getRecords();
         setSupplierNames(supplierAuthorizeVos);
-        //供应区域(省)
-        Map<Long,List<String>> areaMap = supplierAuthorizeVos.stream().collect(Collectors.toMap(
-            SupplierAuthorizeVo::getId,
-            item -> Arrays.stream(item.getAuthorizedArea().split(",")).toList()
-        ));
-        Map<Long,String> provinceMap =supplyAreaService.queryProvincesorCity(supplierId,areaMap,1);
-        provinceMap.forEach((id,province) -> {
-            supplierAuthorizeVos.stream().filter(item -> item.getId().equals(id)).forEach(item -> item.setProvince(province));
-        });
 
-        //供应区域(市)
-        Map<Long,String> cityMap =supplyAreaService.queryProvincesorCity(supplierId,areaMap,2);
-        cityMap.forEach((id,city) -> {
-            supplierAuthorizeVos.stream().filter(item -> item.getId().equals(id)).forEach(item -> item.setCity(city));
-        });
+        // 使用AddressAreaService查询地区信息
+        setSupplyAreaInfo(supplierAuthorizeVos);
+
         //一级 二级 三级 品目
         Map<Long,Long> categoryMap = supplierAuthorizeVos.stream()
             .filter(item -> item.getId() != null && item.getCategoryId() != null)
@@ -400,7 +562,182 @@ public class SupplierAuthorizeServiceImpl  extends ServiceImpl<SupplierAuthorize
         return supplierAuthorizeVos;
     }
 
+    @Override
+    public List<SupplierAuthorizeVo> srmgetAuthorizeDetailList(SupplierAuthorizeBo  bo) {
+        LambdaQueryWrapper<SupplierAuthorize> lqw = new LambdaQueryWrapper<>();
+        lqw.eq(SupplierAuthorize::getSupplierId, bo.getSupplierId());
+
+        // 核心:省/市查询条件(合并字段用AND匹配)
+        if (ObjectUtil.isNotEmpty(bo.getProvince()) || ObjectUtil.isNotEmpty(bo.getCity())) {
+            lqw.and(wrapper -> {
+                // 1. 省份查询
+                if (ObjectUtil.isNotEmpty(bo.getProvince())) {
+                    Long provinceId = remoteAddressAreaService.getIdsByName(bo.getProvince());
+                    if (provinceId != null) {
+                        wrapper.like(SupplierAuthorize::getAuthorizedArea, provinceId);
+                    }
+                }
+                // 2. 城市查询(和省份用AND关联,必须同时满足)
+                if (ObjectUtil.isNotEmpty(bo.getCity())) {
+                    Long cityId = remoteAddressAreaService.getIdsByName(bo.getCity());
+                    if (cityId != null) {
+                        wrapper.like(SupplierAuthorize::getAuthorizedArea, cityId);
+                    }
+                }
+            });
+        }
+
+
+        List<SupplierAuthorizeVo> supplierAuthorizeVos = baseMapper.selectVoList(lqw);
+        setSupplierNames(supplierAuthorizeVos);
+
+        // 使用AddressAreaService查询地区信息
+        setSupplyAreaInfo(supplierAuthorizeVos);
+
+        //一级 二级 三级 品目
+        Map<Long,Long> categoryMap = supplierAuthorizeVos.stream()
+            .filter(item -> item.getId() != null && item.getCategoryId() != null)
+            .collect(Collectors.toMap(
+                SupplierAuthorizeVo::getId,
+                item ->item.getCategoryId()
+            ));
+
+        Map<Long, Map<String, String>> categorysMap = remoteCategoryService.getallCategoryNameById(categoryMap);
+
+        supplierAuthorizeVos.forEach(item -> {
+            Map<String, String> stringStringMap = categorysMap.get(item.getId());
+            item.setCategorysMap(stringStringMap);
+        });
+
+        return supplierAuthorizeVos;
+    }
+
+    /**
+     * 使用AddressAreaService设置单个供应区域信息(省和市)- 优化版本
+     *
+     * @param supplierAuthorizeVo 授权详情对象
+     */
+    private void setSupplyAreaInfoForSingle(SupplierAuthorizeVo supplierAuthorizeVo) {
+        if (supplierAuthorizeVo == null || StringUtils.isBlank(supplierAuthorizeVo.getAuthorizedArea())) {
+            return;
+        }
+
+        // 解析地区ID字符串
+        String[] areaIds = supplierAuthorizeVo.getAuthorizedArea().split(",");
+
+        // 收集所有有效的地区ID
+        Set<Long> validAreaIds = new HashSet<>();
+        for (String areaIdStr : areaIds) {
+            try {
+                Long areaId = Long.parseLong(areaIdStr.trim());
+                if (areaId != null) {
+                    validAreaIds.add(areaId);
+                }
+            } catch (NumberFormatException e) {
+                // 忽略无效的ID格式
+                continue;
+            }
+        }
+
+        // 如果没有有效的地区ID,直接返回
+        if (validAreaIds.isEmpty()) {
+            supplierAuthorizeVo.setProvince("");
+            supplierAuthorizeVo.setCity("");
+            return;
+        }
+
+        // 批量查询所有地区信息 - 一次性远程调用
+        List<AddressAreaDTO> areas = remoteAddressAreaService.listByIds(validAreaIds);
+
+        // 按地区级别分类存储
+        Set<String> provinces = new HashSet<>();
+        Set<String> cities = new HashSet<>();
+
+        for (AddressAreaDTO area : areas) {
+            if (area != null && area.getLevel() != null) {
+                if (area.getLevel() == 1) { // 省级
+                    provinces.add(area.getAreaName());
+                } else if (area.getLevel() == 2) { // 市级
+                    cities.add(area.getAreaName());
+                }
+            }
+        }
+
+        // 设置省份和城市信息到VO对象
+        supplierAuthorizeVo.setProvince(String.join(",", provinces));
+        supplierAuthorizeVo.setCity(String.join(",", cities));
+    }
+
+    /**
+     * 使用AddressAreaService批量设置供应区域信息(省和市)
+     *
+     * @param supplierAuthorizeVos 授权详情列表
+     */
+    private void setSupplyAreaInfo(List<SupplierAuthorizeVo> supplierAuthorizeVos) {
+        if (supplierAuthorizeVos == null || supplierAuthorizeVos.isEmpty()) {
+            return;
+        }
+        // 收集所有需要查询的地区ID
+        Set<Long> allAreaIds = new HashSet<>();
+        for (SupplierAuthorizeVo item : supplierAuthorizeVos) {
+            if (StringUtils.isNotBlank(item.getAuthorizedArea())) {
+                String[] areaIds = item.getAuthorizedArea().split(",");
+                for (String areaIdStr : areaIds) {
+                    try {
+                        Long areaId = Long.parseLong(areaIdStr.trim());
+                        if (areaId != null) {
+                            allAreaIds.add(areaId);
+                        }
+                    } catch (NumberFormatException e) {
+                        // 忽略无效的ID格式
+                        continue;
+                    }
+                }
+            }
+        }
+        // 如果没有地区ID需要查询,直接返回
+        if (allAreaIds.isEmpty()) {
+            return;
+        }
+
+        // 批量查询地区信息
+        List<AddressAreaDTO> areas = remoteAddressAreaService.listByIds(allAreaIds);
+
+        // 按地区ID建立索引映射,提高查找效率
+        Map<Long, AddressAreaDTO> areaIndexMap = areas.stream()
+            .collect(Collectors.toMap(AddressAreaDTO::getId, area -> area, (existing, replacement) -> existing));
+
+        // 为每个授权项设置地区信息
+        for (SupplierAuthorizeVo item : supplierAuthorizeVos) {
+            if (StringUtils.isNotBlank(item.getAuthorizedArea())) {
+                String[] areaIds = item.getAuthorizedArea().split(",");
+
+                Set<String> provinces = new HashSet<>();
+                Set<String> cities = new HashSet<>();
 
+                for (String areaIdStr : areaIds) {
+                    try {
+                        Long areaId = Long.parseLong(areaIdStr.trim());
+                        if (areaId != null) {
+                            AddressAreaDTO area = areaIndexMap.get(areaId); // O(1) 查找
+                            if (area != null && area.getLevel() != null) {
+                                if (area.getLevel() == 1) { // 省级
+                                    provinces.add(area.getAreaName());
+                                } else if (area.getLevel() == 2) { // 市级
+                                    cities.add(area.getAreaName());
+                                }
+                            }
+                        }
+                    } catch (NumberFormatException e) {
+                        continue;
+                    }
+                }
+
+                item.setProvince(String.join(",", provinces));
+                item.setCity(String.join(",", cities));
+            }
+        }
+    }
 
     private void setSupplierNames(List<SupplierAuthorizeVo> records) {
         if (records == null || records.isEmpty()) {

+ 5 - 7
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierInfoServiceImpl.java

@@ -450,7 +450,6 @@ public class SupplierInfoServiceImpl  extends ServiceImpl<SupplierInfoMapper, Su
         supplierInfoVo.setEstablishmentDate(businessInfoVo.getEstablishmentDate());
         supplierInfoVo.setRegistrationStatus(businessInfoVo.getRegistrationStatus());
         supplierInfoVo.setRegistrationAuthority(businessInfoVo.getRegistrationAuthority());
-        supplierInfoVo.setBusinessLicense(businessInfoVo.getBusinessLicense());
         supplierInfoVo.setBusinessAddress(businessInfoVo.getBusinessAddress());
 
     }
@@ -935,10 +934,9 @@ public class SupplierInfoServiceImpl  extends ServiceImpl<SupplierInfoMapper, Su
 
 
     private SupplierInfoVo handleProcurementInfo(SupplierInfoVo records) {
-        SupplierInfoVo targetVo = new SupplierInfoVo();
-        BeanUtils.copyProperties(records, targetVo, "otherCustomers");
+
             // 查询管理人员和采购人员
-            Long id = targetVo.getId();
+            Long id = records.getId();
             //查询供应地区
             LambdaQueryWrapper<SupplyArea> supplyProvinceAreaLqw = Wrappers.lambdaQuery();
             supplyProvinceAreaLqw.eq(SupplyArea::getSupplierId, id)
@@ -962,11 +960,11 @@ public class SupplierInfoServiceImpl  extends ServiceImpl<SupplierInfoMapper, Su
                 .filter(Objects::nonNull)
                 .collect(Collectors.joining(","));
 
-        targetVo.setProvince(provinceNames);
-        targetVo.setCity(cityNames);
+        records.setProvince(provinceNames);
+        records.setCity(cityNames);
 
 
-        return targetVo;
+        return records;
     }
 
 

+ 141 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/SupplierQualificationServiceImpl.java

@@ -0,0 +1,141 @@
+package org.dromara.customer.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.customer.domain.bo.SupplierQualificationBo;
+import org.dromara.customer.domain.vo.SupplierQualificationVo;
+import org.dromara.customer.domain.SupplierQualification;
+import org.dromara.customer.mapper.SupplierQualificationMapper;
+import org.dromara.customer.service.ISupplierQualificationService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 供应商资质信息Service业务层处理
+ *
+ * @author LionLi
+ * @date 2026-01-27
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class SupplierQualificationServiceImpl  extends ServiceImpl<SupplierQualificationMapper, SupplierQualification> implements ISupplierQualificationService {
+
+    private final SupplierQualificationMapper baseMapper;
+
+    /**
+     * 查询供应商资质信息
+     *
+     * @param id 主键
+     * @return 供应商资质信息
+     */
+    @Override
+    public SupplierQualificationVo queryById(Long id){
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 分页查询供应商资质信息列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 供应商资质信息分页列表
+     */
+    @Override
+    public TableDataInfo<SupplierQualificationVo> queryPageList(SupplierQualificationBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<SupplierQualification> lqw = buildQueryWrapper(bo);
+        Page<SupplierQualificationVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的供应商资质信息列表
+     *
+     * @param bo 查询条件
+     * @return 供应商资质信息列表
+     */
+    @Override
+    public List<SupplierQualificationVo> queryList(SupplierQualificationBo bo) {
+        LambdaQueryWrapper<SupplierQualification> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<SupplierQualification> buildQueryWrapper(SupplierQualificationBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<SupplierQualification> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(SupplierQualification::getId);
+        lqw.like(StringUtils.isNotBlank(bo.getQualificationName()), SupplierQualification::getQualificationName, bo.getQualificationName());
+        lqw.eq(StringUtils.isNotBlank(bo.getQualificationLevel()), SupplierQualification::getQualificationLevel, bo.getQualificationLevel());
+        lqw.eq(StringUtils.isNotBlank(bo.getCertificateNo()), SupplierQualification::getCertificateNo, bo.getCertificateNo());
+        lqw.eq(StringUtils.isNotBlank(bo.getIssuingAuthority()), SupplierQualification::getIssuingAuthority, bo.getIssuingAuthority());
+        lqw.eq(bo.getStartDate() != null, SupplierQualification::getStartDate, bo.getStartDate());
+        lqw.eq(bo.getEndDate() != null, SupplierQualification::getEndDate, bo.getEndDate());
+        lqw.eq(bo.getIsLongValid() != null, SupplierQualification::getIsLongValid, bo.getIsLongValid());
+        lqw.eq(StringUtils.isNotBlank(bo.getAttachmentUrl()), SupplierQualification::getAttachmentUrl, bo.getAttachmentUrl());
+        lqw.like(StringUtils.isNotBlank(bo.getAttachmentName()), SupplierQualification::getAttachmentName, bo.getAttachmentName());
+        return lqw;
+    }
+
+    /**
+     * 新增供应商资质信息
+     *
+     * @param bo 供应商资质信息
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(SupplierQualificationBo bo) {
+        SupplierQualification add = MapstructUtils.convert(bo, SupplierQualification.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改供应商资质信息
+     *
+     * @param bo 供应商资质信息
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(SupplierQualificationBo bo) {
+        SupplierQualification update = MapstructUtils.convert(bo, SupplierQualification.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(SupplierQualification 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-customer/src/main/resources/mapper/customer/SupplierQualificationMapper.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.customer.mapper.SupplierQualificationMapper">
+
+</mapper>

+ 31 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/OrderDeliverController.java

@@ -1,11 +1,17 @@
 package org.dromara.order.controller;
 
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import lombok.RequiredArgsConstructor;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.constraints.*;
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.dromara.order.domain.OrderDeliver;
+import org.dromara.order.domain.vo.OrderDeliverProductVo;
+import org.dromara.order.domain.vo.OrderProductVo;
 import org.dromara.order.utils.kd100.domain.TrackVO;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.validation.annotation.Validated;
@@ -113,4 +119,29 @@ public class OrderDeliverController extends BaseController {
                           @PathVariable("ids") Long[] ids) {
         return toAjax(orderDeliverService.deleteWithValidByIds(List.of(ids), true));
     }
+
+    /*根据客户id查询客户对账单对应的订单*/
+    @GetMapping("/getCustomerDeliverOrders/{customerId}")
+    public TableDataInfo<OrderDeliverVo> getCustomerDeliverOrders(@PathVariable Long customerId,
+                                                                  PageQuery pageQuery) {
+        return orderDeliverService.listDeliverOrderByCustomerIdPage(customerId, pageQuery);
+    }
+
+    /**
+     * 根据订单id查询订单商品
+     */
+    @GetMapping("/getCustomerOrderProductList")
+    public TableDataInfo<OrderDeliverProductVo> getCustomerOrderProductList(
+        @RequestParam(value = "orderId", required = false) List<Long> orderIdList) {
+
+        if (CollectionUtils.isEmpty(orderIdList)) {
+            throw new IllegalArgumentException("订单ID列表不能为空");
+        }
+        if (orderIdList.size() > 1000) {
+            throw new IllegalArgumentException("订单ID数量不能超过1000个");
+        }
+
+        Set<Long> uniqueOrderIds = new HashSet<>(orderIdList);
+        return orderDeliverService.getCustomerOrderProductList(uniqueOrderIds);
+    }
 }

+ 12 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/OrderMainController.java

@@ -143,6 +143,18 @@ public class OrderMainController extends BaseController {
         return toAjax(orderMainService.deleteWithValidByIds(List.of(ids), true));
     }
 
+    /**
+     * 关闭订单
+     *
+     * @param ids 主键串
+     */
+    @Log(title = "订单主信息", businessType = BusinessType.UPDATE)
+    @PostMapping("closeOrder")
+    public R<Void> closeOrder(@NotEmpty(message = "主键不能为空")
+                              @RequestParam Long[] ids) {
+        return toAjax(orderMainService.closeOrderByIds(List.of(ids), true));
+    }
+
     /**
      * 状态修改
      */

+ 106 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/OrderOperateLogController.java

@@ -0,0 +1,106 @@
+package org.dromara.order.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.order.domain.vo.OrderOperateLogVo;
+import org.dromara.order.domain.bo.OrderOperateLogBo;
+import org.dromara.order.service.IOrderOperateLogService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 订单操作记录
+ * 前端访问路由地址为:/order/orderOperateLog
+ *
+ * @author LionLi
+ * @date 2026-01-26
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/orderOperateLog")
+public class OrderOperateLogController extends BaseController {
+
+    private final IOrderOperateLogService orderOperateLogService;
+
+    /**
+     * 查询订单操作记录列表
+     */
+    //@SaCheckPermission("order:orderOperateLog:list")
+    @GetMapping("/list")
+    public TableDataInfo<OrderOperateLogVo> list(OrderOperateLogBo bo, PageQuery pageQuery) {
+        return orderOperateLogService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出订单操作记录列表
+     */
+    //@SaCheckPermission("order:orderOperateLog:export")
+    @Log(title = "订单操作记录", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(OrderOperateLogBo bo, HttpServletResponse response) {
+        List<OrderOperateLogVo> list = orderOperateLogService.queryList(bo);
+        ExcelUtil.exportExcel(list, "订单操作记录", OrderOperateLogVo.class, response);
+    }
+
+    /**
+     * 获取订单操作记录详细信息
+     *
+     * @param id 主键
+     */
+    //@SaCheckPermission("order:orderOperateLog:query")
+    @GetMapping("/{id}")
+    public R<OrderOperateLogVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable("id") Long id) {
+        return R.ok(orderOperateLogService.queryById(id));
+    }
+
+    /**
+     * 新增订单操作记录
+     */
+    //@SaCheckPermission("order:orderOperateLog:add")
+    @Log(title = "订单操作记录", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody OrderOperateLogBo bo) {
+        return toAjax(orderOperateLogService.insertByBo(bo));
+    }
+
+    /**
+     * 修改订单操作记录
+     */
+    //@SaCheckPermission("order:orderOperateLog:edit")
+    @Log(title = "订单操作记录", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody OrderOperateLogBo bo) {
+        return toAjax(orderOperateLogService.updateByBo(bo));
+    }
+
+    /**
+     * 删除订单操作记录
+     *
+     * @param ids 主键串
+     */
+    //@SaCheckPermission("order:orderOperateLog:remove")
+    @Log(title = "订单操作记录", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable("ids") Long[] ids) {
+        return toAjax(orderOperateLogService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 12 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/OrderDeliverProduct.java

@@ -6,6 +6,7 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 
 import java.io.Serial;
+import java.math.BigDecimal;
 
 /**
  * 订单发货商品明细对象 order_deliver_product
@@ -62,6 +63,17 @@ public class OrderDeliverProduct extends TenantEntity {
      */
     private Long deliverNum;
 
+
+    /**
+     * 订单单价(元)
+     */
+    private BigDecimal orderPrice;
+
+    /**
+     * 行小计金额(元)
+     */
+    private BigDecimal subtotal;
+
     private String dataSource;
 
     /**

+ 57 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/OrderOperateLog.java

@@ -0,0 +1,57 @@
+package org.dromara.order.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 订单操作记录对象 order_operate_log
+ *
+ * @author LionLi
+ * @date 2026-01-26
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("order_operate_log")
+public class OrderOperateLog extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ID
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 订单id
+     */
+    private Long orderId;
+
+    /**
+     * 操作
+     */
+    private String action;
+
+    /**
+     * 用户名
+     */
+    private String userName;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 6 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/OrderProduct.java

@@ -41,6 +41,12 @@ public class OrderProduct extends TenantEntity {
      */
     private Long orderId;
 
+    /*原始商品ID(用于子订单商品指向主订单)*/
+    private Long originalItemId;
+
+    /*被分配到的子订单ID*/
+    private Long assignedChildOrderId;
+
     /**
      * 订单编号
      */

+ 12 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/bo/OrderDeliverProductBo.java

@@ -9,6 +9,8 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import jakarta.validation.constraints.*;
 
+import java.math.BigDecimal;
+
 /**
  * 订单发货商品明细业务对象 order_deliver_product
  *
@@ -60,6 +62,16 @@ public class OrderDeliverProductBo extends BaseEntity {
      */
     private Long deliverNum;
 
+    /**
+     * 订单单价(元)
+     */
+    private BigDecimal orderPrice;
+
+    /**
+     * 行小计金额(元)
+     */
+    private BigDecimal subtotal;
+
     private String dataSource;
 
     /**

+ 49 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/bo/OrderOperateLogBo.java

@@ -0,0 +1,49 @@
+package org.dromara.order.domain.bo;
+
+import org.dromara.order.domain.OrderOperateLog;
+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.*;
+
+/**
+ * 订单操作记录业务对象 order_operate_log
+ *
+ * @author LionLi
+ * @date 2026-01-26
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = OrderOperateLog.class, reverseConvertGenerate = false)
+public class OrderOperateLogBo extends BaseEntity {
+
+    /**
+     * ID
+     */
+    private Long id;
+
+    /**
+     * 订单id
+     */
+    private Long orderId;
+
+    /**
+     * 操作
+     */
+    private String action;
+
+    /**
+     * 用户名
+     */
+    private String userName;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 6 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/bo/OrderProductBo.java

@@ -40,6 +40,12 @@ public class OrderProductBo extends BaseEntity {
     @NotNull(message = "订单ID不能为空", groups = {AddGroup.class, EditGroup.class})
     private Long orderId;
 
+    /*原始商品ID(用于子订单商品指向主订单)*/
+    private Long originalItemId;
+
+    /*被分配到的子订单ID*/
+    private Long assignedChildOrderId;
+
     /**
      * 订单编号
      */

+ 12 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/dto/AssignmentStatsDto.java

@@ -0,0 +1,12 @@
+package org.dromara.order.domain.dto;
+
+import lombok.Data;
+
+@Data
+public class AssignmentStatsDto {
+
+    private Long total;
+
+    private Long assigned;
+
+}

+ 13 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderDeliverProductVo.java

@@ -10,6 +10,7 @@ import lombok.Data;
 
 import java.io.Serial;
 import java.io.Serializable;
+import java.math.BigDecimal;
 import java.util.Date;
 
 
@@ -74,6 +75,16 @@ public class OrderDeliverProductVo implements Serializable {
     @ExcelProperty(value = "本次发货数量")
     private Long deliverNum;
 
+    /**
+     * 订单单价(元)
+     */
+    private BigDecimal orderPrice;
+
+    /**
+     * 行小计金额(元)
+     */
+    private BigDecimal subtotal;
+
     /**
      * 备注
      */
@@ -82,5 +93,7 @@ public class OrderDeliverProductVo implements Serializable {
 
     private String dataSource;
 
+    private String orderNo;
+
 
 }

+ 15 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderDeliverVo.java

@@ -10,6 +10,7 @@ import lombok.Data;
 
 import java.io.Serial;
 import java.io.Serializable;
+import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
 
@@ -131,5 +132,19 @@ public class OrderDeliverVo implements Serializable {
 
     private Date createTime;
 
+    private String customerName;
+
+    private BigDecimal totalAmount;
+
+    private Date orderTime;
+
+    private Long createBy;
+
+    private String createName;
+
+    private Long createDept;
+
+    private String createDeptName;
+
     private List<OrderDeliverProductVo> deliverProductList;
 }

+ 62 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderOperateLogVo.java

@@ -0,0 +1,62 @@
+package org.dromara.order.domain.vo;
+
+import org.dromara.order.domain.OrderOperateLog;
+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;
+
+
+
+/**
+ * 订单操作记录视图对象 order_operate_log
+ *
+ * @author LionLi
+ * @date 2026-01-26
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = OrderOperateLog.class)
+public class OrderOperateLogVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ID
+     */
+    @ExcelProperty(value = "ID")
+    private Long id;
+
+    /**
+     * 订单id
+     */
+    @ExcelProperty(value = "订单id")
+    private Long orderId;
+
+    /**
+     * 操作
+     */
+    @ExcelProperty(value = "操作")
+    private String action;
+
+    /**
+     * 用户名
+     */
+    @ExcelProperty(value = "用户名")
+    private String userName;
+
+    /**
+     * 备注
+     */
+    @ExcelProperty(value = "备注")
+    private String remark;
+
+
+}

+ 6 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/vo/OrderProductVo.java

@@ -47,6 +47,12 @@ public class OrderProductVo implements Serializable {
     @ExcelProperty(value = "订单ID")
     private Long orderId;
 
+    /*原始商品ID(用于子订单商品指向主订单)*/
+    private Long originalItemId;
+
+    /*被分配到的子订单ID*/
+    private Long assignedChildOrderId;
+
     /**
      * 订单编号
      */

+ 1 - 1
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/mapper/OrderDeliverMapper.java

@@ -1,8 +1,8 @@
 package org.dromara.order.mapper;
 
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
 import org.dromara.order.domain.OrderDeliver;
 import org.dromara.order.domain.vo.OrderDeliverVo;
-import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
 
 /**
  * 订单发货主Mapper接口

+ 15 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/mapper/OrderOperateLogMapper.java

@@ -0,0 +1,15 @@
+package org.dromara.order.mapper;
+
+import org.dromara.order.domain.OrderOperateLog;
+import org.dromara.order.domain.vo.OrderOperateLogVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 订单操作记录Mapper接口
+ *
+ * @author LionLi
+ * @date 2026-01-26
+ */
+public interface OrderOperateLogMapper extends BaseMapperPlus<OrderOperateLog, OrderOperateLogVo> {
+
+}

+ 19 - 1
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/mapper/OrderProductMapper.java

@@ -1,11 +1,14 @@
 package org.dromara.order.mapper;
 
 import org.apache.ibatis.annotations.Param;
+import org.dromara.common.core.enums.OrderAssignStatus;
 import org.dromara.order.domain.OrderProduct;
+import org.dromara.order.domain.dto.AssignmentStatsDto;
 import org.dromara.order.domain.vo.OrderProductVo;
 import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
 import org.dromara.order.domain.vo.OrderQuantitySummary;
 
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
@@ -36,5 +39,20 @@ public interface OrderProductMapper extends BaseMapperPlus<OrderProduct, OrderPr
 
 
     /*查询  订单商品种数与已分配商品种数*/
-    Map getAssignmentStats(@Param("orderId") Long orderId);
+    AssignmentStatsDto getAssignmentStats(@Param("parentId") Long parentId);
+
+    /**
+     * 批量更新商品的分配状态和关联的子订单ID
+     *
+     * @param itemIds          要更新的商品ID列表
+     * @param assignmentStatus 分配状态(如 "1" 表示已分配)
+     * @param childOrderId     被分配到的子订单ID
+     * @param updateTime       更新时间
+     */
+    void updateAssignmentInfo(
+        @Param("itemIds") List<Long> itemIds,
+        @Param("assignmentStatus") String assignmentStatus,
+        @Param("childOrderId") Long childOrderId,
+        @Param("updateTime") Date updateTime
+    );
 }

+ 14 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderDeliverService.java

@@ -2,14 +2,17 @@ package org.dromara.order.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import org.dromara.order.domain.OrderDeliver;
+import org.dromara.order.domain.vo.OrderDeliverProductVo;
 import org.dromara.order.domain.vo.OrderDeliverVo;
 import org.dromara.order.domain.bo.OrderDeliverBo;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.order.domain.vo.OrderProductVo;
 import org.dromara.order.utils.kd100.domain.TrackVO;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Set;
 
 /**
  * 订单发货主Service接口
@@ -77,4 +80,15 @@ public interface IOrderDeliverService extends IService<OrderDeliver> {
      * @return 是否删除成功
      */
     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+    /**
+     * 分页查询客户发货单
+     *
+     * @param customerId 客户ID
+     * @param pageQuery  分页参数
+     * @return 分页结果
+     */
+    TableDataInfo<OrderDeliverVo> listDeliverOrderByCustomerIdPage(Long customerId, PageQuery pageQuery);
+
+    TableDataInfo<OrderDeliverProductVo> getCustomerOrderProductList(Set<Long> orderIdList);
 }

+ 2 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderMainService.java

@@ -86,4 +86,6 @@ public interface IOrderMainService extends IService<OrderMain> {
      * @return 是否删除成功
      */
     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+    Boolean closeOrderByIds(Collection<Long> ids, Boolean isValid);
 }

+ 70 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderOperateLogService.java

@@ -0,0 +1,70 @@
+package org.dromara.order.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.order.domain.OrderOperateLog;
+import org.dromara.order.domain.vo.OrderOperateLogVo;
+import org.dromara.order.domain.bo.OrderOperateLogBo;
+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-26
+ */
+public interface IOrderOperateLogService extends IService<OrderOperateLog>{
+
+    /**
+     * 查询订单操作记录
+     *
+     * @param id 主键
+     * @return 订单操作记录
+     */
+    OrderOperateLogVo queryById(Long id);
+
+    /**
+     * 分页查询订单操作记录列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 订单操作记录分页列表
+     */
+    TableDataInfo<OrderOperateLogVo> queryPageList(OrderOperateLogBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的订单操作记录列表
+     *
+     * @param bo 查询条件
+     * @return 订单操作记录列表
+     */
+    List<OrderOperateLogVo> queryList(OrderOperateLogBo bo);
+
+    /**
+     * 新增订单操作记录
+     *
+     * @param bo 订单操作记录
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(OrderOperateLogBo bo);
+
+    /**
+     * 修改订单操作记录
+     *
+     * @param bo 订单操作记录
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(OrderOperateLogBo bo);
+
+    /**
+     * 校验并批量删除订单操作记录信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 96 - 27
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderAssignmentServiceImpl.java

@@ -26,6 +26,7 @@ import org.dromara.order.domain.OrderProduct;
 import org.dromara.order.domain.OrderProductAssignRule;
 import org.dromara.order.domain.bo.OrderAssignmentBo;
 import org.dromara.order.domain.bo.OrderSplitAssignBo;
+import org.dromara.order.domain.dto.AssignmentStatsDto;
 import org.dromara.order.domain.vo.OrderAssignmentVo;
 import org.dromara.order.domain.vo.OrderMainVo;
 import org.dromara.order.mapper.OrderAssignmentMapper;
@@ -35,6 +36,7 @@ import org.dromara.order.service.IOrderAssignmentService;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.math.BigDecimal;
 import java.time.Duration;
 import java.util.*;
 import java.util.function.Function;
@@ -208,11 +210,11 @@ public class OrderAssignmentServiceImpl extends ServiceImpl<OrderAssignmentMappe
         if (parentOrder == null) {
             throw new ServiceException("父订单不存在");
         }
-        if ("1".equals(parentOrder.getSplitStatus())) { // 已拆分
+      /*  if (OrderSplitStatus.SPLITED.getCode().equals(parentOrder.getSplitStatus())) {
             throw new ServiceException("该订单已被拆分,不可重复操作");
-        }
+        }*/
 
-        // 2. 验证商品行
+        // 2. 验证商品行(必须属于该主订单且未分配)
         List<Long> itemIds = rules.stream().map(OrderProductAssignRule::getItemId).collect(Collectors.toList());
         List<OrderProduct> items = orderProductMapper.selectBatchIds(itemIds);
         Map<Long, OrderProduct> itemMap = items.stream()
@@ -223,12 +225,12 @@ public class OrderAssignmentServiceImpl extends ServiceImpl<OrderAssignmentMappe
             if (item == null || !parentId.equals(item.getOrderId())) {
                 throw new ServiceException("商品行不属于该订单或不存在");
             }
-            if ("1".equals(item.getAssignmentStatus())) { // 已分配
+            if (OrderAssignStatus.ASSIGNED.getCode().equals(item.getAssignmentStatus())) {
                 throw new ServiceException("商品 [" + item.getProductName() + "] 已分配,不可重复操作");
             }
-            // 校验 assigneeType 合法性
             String type = rule.getAssigneeType();
-            if (!AssigneeTypeConstants.SUPPLIER.getCode().equals(type) && !AssigneeTypeConstants.PARTNER.getCode().equals(type)) {
+            if (!AssigneeTypeConstants.SUPPLIER.getCode().equals(type) &&
+                !AssigneeTypeConstants.PARTNER.getCode().equals(type)) {
                 throw new ServiceException("分配对象类型不支持: " + type);
             }
         }
@@ -239,51 +241,118 @@ public class OrderAssignmentServiceImpl extends ServiceImpl<OrderAssignmentMappe
         Map<AssigneeKey, List<OrderProductAssignRule>> assigneeGroups = rules.stream()
             .collect(Collectors.groupingBy(rule -> new AssigneeKey(rule.getAssigneeId(), rule.getAssigneeType())));
 
-        // 4. 为每个分配对象创建子订单
+        // 4. 为每个分配对象创建子订单 + 商品副本
         for (Map.Entry<AssigneeKey, List<OrderProductAssignRule>> entry : assigneeGroups.entrySet()) {
             AssigneeKey key = entry.getKey();
             List<OrderProductAssignRule> groupRules = entry.getValue();
 
-            // 创建子订单
+            // 创建子订单(从主订单拷贝必要字段)
             OrderMain childOrder = copyParentToChild(parentOrder, key.id(), key.type());
             orderMainMapper.insert(childOrder);
+            Long childOrderId = childOrder.getId();
+
+            // 准备子订单商品列表(副本)
+            List<OrderProduct> childProducts = new ArrayList<>();
+            List<Long> parentItemIdsToUpdate = new ArrayList<>();
+
+            for (OrderProductAssignRule rule : groupRules) {
+                OrderProduct parentItem = itemMap.get(rule.getItemId());
+
+                // 1. 收集主订单商品ID,用于后续批量更新分配状态
+                parentItemIdsToUpdate.add(parentItem.getId());
+
+                // 2. 创建子订单商品副本
+                OrderProduct childProduct = new OrderProduct();
+
+                // 继承租户信息
+                childProduct.setTenantId(parentItem.getTenantId());
+
+                // 关联信息
+                childProduct.setOrderId(childOrderId);           // 归属子订单
+                childProduct.setOriginalItemId(parentItem.getId()); // 指向主订单商品
+
+                // 订单基础信息
+                childProduct.setOrderNo(childOrder.getOrderNo()); // 子订单编号
+                childProduct.setDataSource(parentItem.getDataSource());
+
+                // 商品核心信息
+                childProduct.setProductId(parentItem.getProductId());
+                childProduct.setProductNo(parentItem.getProductNo());
+                childProduct.setProductName(parentItem.getProductName());
+                childProduct.setProductUnitId(parentItem.getProductUnitId());
+                childProduct.setProductUnit(parentItem.getProductUnit());
+                childProduct.setProductImage(parentItem.getProductImage());
+
+                // 价格信息
+                childProduct.setPlatformPrice(parentItem.getPlatformPrice());
+                childProduct.setMarketPrice(parentItem.getMarketPrice());
+                childProduct.setMemberPrice(parentItem.getMemberPrice());
+                childProduct.setPurchasingPrice(parentItem.getPurchasingPrice());
+                childProduct.setMaxPurchasePrice(parentItem.getMaxPurchasePrice());
+                childProduct.setMinSellingPrice(parentItem.getMinSellingPrice());
+                childProduct.setTaxRate(parentItem.getTaxRate());
+                childProduct.setOrderPrice(parentItem.getOrderPrice());
+                childProduct.setSubtotal(parentItem.getSubtotal());
+
+                // 数量信息(注意:履约数量应重置)
+                childProduct.setOrderQuantity(parentItem.getOrderQuantity());
+                childProduct.setMinOrderQuantity(parentItem.getMinOrderQuantity());
+                childProduct.setUnsentQuantity(parentItem.getOrderQuantity()); // 未发货 = 总数
+                childProduct.setReturnAmount(BigDecimal.ZERO);
+
+                // 状态与标志
+                childProduct.setAssignmentStatus(OrderAssignStatus.ASSIGNED.getCode()); // 已分配
+
+                // 时间 & 其他
+                childProduct.setPreDeliveryDate(parentItem.getPreDeliveryDate());
+                childProduct.setRemark(parentItem.getRemark());
+
+                childProducts.add(childProduct);
+            }
 
-            // 更新商品:指向子订单 + 标记已分配
-            List<Long> groupItemIds = groupRules.stream().map(OrderProductAssignRule::getItemId).collect(Collectors.toList());
-            orderProductMapper.updateForSplitAssign(
-                groupItemIds,
-                childOrder.getId(),
-                OrderAssignStatus.ASSIGNED.getCode() // assignmentStatus = 已分配
-            );
+            // 批量插入子订单商品
+            if (!childProducts.isEmpty()) {
+                orderProductMapper.insertBatch(childProducts);
+            }
+
+            // 批量更新主订单商品:标记已分配 + 记录分配到的子订单ID
+            if (!parentItemIdsToUpdate.isEmpty()) {
+                orderProductMapper.updateAssignmentInfo(
+                    parentItemIdsToUpdate,
+                    OrderAssignStatus.ASSIGNED.getCode(),
+                    childOrderId,
+                    now
+                );
+            }
 
-            // 插入分配记录
+            // 插入分配记录(分配动作日志)
             OrderAssignment assignment = new OrderAssignment();
-            assignment.setOrderId(childOrder.getId());
+            assignment.setOrderId(childOrderId);
             assignment.setOrderNo(childOrder.getOrderNo());
             assignment.setPlatformBefore(parentOrder.getPlatformCode());
             assignment.setAssignedBy(operatorId);
             assignment.setAssignTime(now);
-            assignment.setAssignType("0");
+            assignment.setAssignType("0"); // 可按需定义
             assignment.setRemark(bo.getRemark());
             assignment.setAssigneeId(key.id());
             assignment.setAssigneeType(key.type());
-            baseMapper.insert(assignment); // 假设 baseMapper 是 OrderAssignmentMapper
+            baseMapper.insert(assignment); // 假设是 OrderAssignmentMapper
         }
 
-        Map<String, Object> stats = orderProductMapper.getAssignmentStats(parentId);
-        Long total = (Long) stats.getOrDefault("total", 0L);
-        Long assigned = (Long) stats.getOrDefault("assigned", 0L);
+        // 5. 更新主订单的拆分状态和分配状态
+        AssignmentStatsDto stats = orderProductMapper.getAssignmentStats(parentId);
+        Long total = stats.getTotal();
+        Long assigned = stats.getAssigned();
 
         String parentAssignmentStatus;
         if (assigned == 0) {
-            parentAssignmentStatus = OrderAssignStatus.WAIT_ASSIGN.getCode(); // 待分配
-        } else if (assigned.equals(total)) {
-            parentAssignmentStatus = OrderAssignStatus.ASSIGNED.getCode(); // 已分配
+            parentAssignmentStatus = OrderAssignStatus.WAIT_ASSIGN.getCode();
+        } else if (assigned == total) {
+            parentAssignmentStatus = OrderAssignStatus.ASSIGNED.getCode();
         } else {
-            parentAssignmentStatus = OrderAssignStatus.PARTIALLY_ASSIGNED.getCode();// 部分分配
+            parentAssignmentStatus = OrderAssignStatus.PARTIALLY_ASSIGNED.getCode();
         }
 
-        // 5. 更新父订单状态
         OrderMain updateParent = new OrderMain();
         updateParent.setId(parentId);
         updateParent.setSplitStatus(OrderSplitStatus.SPLITED.getCode()); // 已拆分

+ 144 - 6
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderDeliverServiceImpl.java

@@ -1,12 +1,16 @@
 package org.dromara.order.service.impl;
 
+import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.dromara.common.core.enums.InvoiceStatus;
 import org.dromara.common.core.enums.OrderStatus;
 import org.dromara.common.core.exception.ServiceException;
 import org.dromara.common.core.utils.MapstructUtils;
@@ -14,13 +18,14 @@ import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.redis.utils.SequenceUtils;
+import org.dromara.customer.api.RemoteCustomerService;
 import org.dromara.order.domain.OrderDeliver;
 import org.dromara.order.domain.OrderDeliverProduct;
 import org.dromara.order.domain.OrderMain;
+import org.dromara.order.domain.OrderProduct;
 import org.dromara.order.domain.bo.OrderDeliverBo;
 import org.dromara.order.domain.bo.OrderDeliverProductBo;
-import org.dromara.order.domain.vo.OrderDeliverVo;
-import org.dromara.order.domain.vo.OrderQuantitySummary;
+import org.dromara.order.domain.vo.*;
 import org.dromara.order.mapper.OrderDeliverMapper;
 import org.dromara.order.mapper.OrderDeliverProductMapper;
 import org.dromara.order.mapper.OrderMainMapper;
@@ -29,13 +34,13 @@ import org.dromara.order.service.IOrderDeliverService;
 import org.dromara.order.utils.kd100.Kd100Util;
 import org.dromara.order.utils.kd100.domain.QueryTrackDTO;
 import org.dromara.order.utils.kd100.domain.TrackVO;
+import org.dromara.system.api.RemoteDeptService;
+import org.dromara.system.api.RemoteUserService;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import java.math.BigDecimal;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -49,6 +54,15 @@ import java.util.stream.Collectors;
 @Service
 public class OrderDeliverServiceImpl extends ServiceImpl<OrderDeliverMapper, OrderDeliver> implements IOrderDeliverService {
 
+    @DubboReference
+    private RemoteUserService remoteUserService;
+
+    @DubboReference
+    private RemoteDeptService remoteDeptService;
+
+    @DubboReference
+    private RemoteCustomerService remoteCustomerService;
+
     private final OrderDeliverMapper baseMapper;
 
     private final OrderMainMapper orderMainMapper;
@@ -219,6 +233,38 @@ public class OrderDeliverServiceImpl extends ServiceImpl<OrderDeliverMapper, Ord
         }
     }
 
+    @Override
+    public TableDataInfo<OrderDeliverProductVo> getCustomerOrderProductList(Set<Long> orderIdList) {
+        // 1. 空值与空集合校验
+        if (CollectionUtils.isEmpty(orderIdList)) {
+            return TableDataInfo.build(Collections.emptyList());
+        }
+
+        List<OrderDeliverVo> orderDeliverVoList = baseMapper.selectVoList(
+            new LambdaQueryWrapper<OrderDeliver>()
+                .in(OrderDeliver::getId, orderIdList)
+        );
+
+        /*构建发货id与订单编号对应关系的map*/
+        Map<Long, String> deliverIdToOrderNoMap = orderDeliverVoList.stream()
+            .collect(Collectors.toMap(
+                OrderDeliverVo::getId,
+                OrderDeliverVo::getOrderCode,
+                (v1, v2) -> v1
+            ));
+
+        List<OrderDeliverProductVo> orderProductVoList = orderDeliverProductMapper.selectVoList(
+            new LambdaQueryWrapper<OrderDeliverProduct>()
+                .in(OrderDeliverProduct::getDeliverId, orderIdList)
+        );
+
+        orderProductVoList.forEach(v -> {
+            v.setOrderNo(deliverIdToOrderNoMap.get(v.getDeliverId()));
+        });
+
+        return TableDataInfo.build(orderProductVoList);
+    }
+
     /**
      * 修改订单发货主
      *
@@ -267,6 +313,7 @@ public class OrderDeliverServiceImpl extends ServiceImpl<OrderDeliverMapper, Ord
             .map(bo -> {
                 OrderDeliverProduct product = MapstructUtils.convert(bo, OrderDeliverProduct.class);
                 product.setDeliverId(deliverId);
+                product.setSubtotal(product.getOrderPrice().multiply(BigDecimal.valueOf(product.getDeliverNum())));
                 return product;
             })
             .collect(Collectors.toList());
@@ -276,6 +323,97 @@ public class OrderDeliverServiceImpl extends ServiceImpl<OrderDeliverMapper, Ord
         }
     }
 
+    @Override
+    public TableDataInfo<OrderDeliverVo> listDeliverOrderByCustomerIdPage(Long customerId, PageQuery pageQuery) {
+        if (customerId == null) {
+            return TableDataInfo.build(new Page<>(0, 0));
+        }
+
+        // 查询客户的所有有效订单
+        LambdaQueryWrapper<OrderMain> orderWrapper = new LambdaQueryWrapper<>();
+        orderWrapper.eq(OrderMain::getCustomerId, customerId)
+            .eq(OrderMain::getDelFlag, "0");
+
+        List<OrderMain> orderMainList = orderMainMapper.selectList(orderWrapper);
+        if (orderMainList.isEmpty()) {
+            return TableDataInfo.build(new Page<>(0, 0));
+        }
+
+        List<Long> orderIds = orderMainList.stream()
+            .map(OrderMain::getId)
+            .collect(Collectors.toList());
+
+        // 构建 orderId -> totalAmount 映射
+        Map<Long, BigDecimal> orderIdToAmountMap = orderMainList.stream()
+            .collect(Collectors.toMap(
+                OrderMain::getId,
+                OrderMain::getTotalAmount,
+                (v1, v2) -> v1
+            ));
+
+        // 构建 orderId -> orderTime 映射
+        Map<Long, Date> orderIdToorderTimeMap = orderMainList.stream()
+            .collect(Collectors.toMap(
+                OrderMain::getId,
+                OrderMain::getOrderTime,
+                (v1, v2) -> v1
+            ));
+
+        Set<Long> createUserIds = orderMainList.stream().map(OrderMain::getCreateBy).collect(Collectors.toSet());
+        Set<Long> createDeptIds = orderMainList.stream().map(OrderMain::getCreateDept).collect(Collectors.toSet());
+
+        final Map<Long, String> userMap = new HashMap<>();
+        if (!createUserIds.isEmpty()) {
+            userMap.putAll(remoteUserService.selectUserNamesByIds(new ArrayList<>(createUserIds)));
+        }
+
+        final Map<Long, String> deptMap = new HashMap<>();
+        if (!createDeptIds.isEmpty()) {
+            deptMap.putAll(remoteDeptService.selectDeptNameByIds(new HashSet<>(createDeptIds)));
+        }
+
+        // 查询明细(分页)
+        LambdaQueryWrapper<OrderDeliver> deliverWrapper = new LambdaQueryWrapper<>();
+        deliverWrapper.in(OrderDeliver::getOrderId, orderIds)
+            .eq(OrderDeliver::getDelFlag, "0");
+
+        Page<OrderDeliverVo> pageResult = baseMapper.selectVoPage(pageQuery.build(), deliverWrapper);
+        List<OrderDeliverVo> records = pageResult.getRecords();
+        if (CollUtil.isNotEmpty(records)) {
+            // 1. 提取所有 deliverId
+            List<Long> deliverIds = records.stream()
+                .map(OrderDeliverVo::getId)
+                .collect(Collectors.toList());
+
+            // 批量查询所有商品明细
+            List<OrderDeliverProductVo> allProducts = orderDeliverProductMapper.selectVoList(
+                new LambdaQueryWrapper<OrderDeliverProduct>()
+                    .in(OrderDeliverProduct::getDeliverId, deliverIds)
+            );
+
+            // 安全聚合:处理 null subtotal
+            Map<Long, BigDecimal> deliverIdToTotalAmount = allProducts.stream()
+                .collect(Collectors.groupingBy(
+                    OrderDeliverProductVo::getDeliverId,
+                    Collectors.reducing(
+                        BigDecimal.ZERO,
+                        product -> Optional.ofNullable(product.getSubtotal()).orElse(BigDecimal.ZERO),
+                        BigDecimal::add
+                    )
+                ));
+
+            // 4. 回填 totalAmount 和其他字段
+            for (OrderDeliverVo record : records) {
+                record.setTotalAmount(deliverIdToTotalAmount.getOrDefault(record.getId(), BigDecimal.ZERO));
+                record.setCreateName(userMap.getOrDefault(record.getCreateBy(), "未知用户"));
+                record.setCreateDeptName(deptMap.getOrDefault(record.getCreateDept(), "未知部门"));
+                record.setOrderTime(orderIdToorderTimeMap.get(record.getOrderId()));
+            }
+        }
+
+        return TableDataInfo.build(pageResult);
+    }
+
     /**
      * 保存前的数据校验
      */

+ 26 - 14
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderMainServiceImpl.java

@@ -2,6 +2,7 @@ package org.dromara.order.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -9,6 +10,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.config.annotation.DubboReference;
+import org.dromara.common.core.enums.OrderStatus;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.PageQuery;
@@ -19,6 +21,7 @@ import org.dromara.order.domain.OrderMain;
 import org.dromara.order.domain.OrderProduct;
 import org.dromara.order.domain.bo.OrderMainBo;
 import org.dromara.order.domain.bo.OrderProductBo;
+import org.dromara.order.domain.dto.AssignmentStatsDto;
 import org.dromara.order.domain.vo.OrderMainVo;
 import org.dromara.order.domain.vo.OrderProductVo;
 import org.dromara.order.domain.vo.OrderStatusStats;
@@ -93,20 +96,11 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
             orderDeliverProductMapper.selectDeliverProductsByOrderId(orderMainVo.getId())
         );
 
-        Map<String, Object> stats = orderProductMapper.getAssignmentStats(orderMainVo.getId());
-        Object totalObj = stats.get("total");
-        Long total = (totalObj instanceof BigDecimal)
-            ? ((BigDecimal) totalObj).longValue()
-            : (totalObj instanceof Long)
-            ? (Long) totalObj
-            : 0L;
-
-        Object assignedObj = stats.get("assigned");
-        Long assigned = (assignedObj instanceof BigDecimal)
-            ? ((BigDecimal) assignedObj).longValue()
-            : (assignedObj instanceof Long)
-            ? (Long) assignedObj
-            : 0L;
+        // 查询主订单原始商品的总行数与已分配行数
+        AssignmentStatsDto stats = orderProductMapper.getAssignmentStats(orderMainVo.getId());
+        Long total = stats.getTotal();
+        Long assigned = stats.getAssigned();
+
         orderMainVo.setProductTotal(total);
         orderMainVo.setUnassigned(total - assigned);
         orderMainVo.setAssigned(assigned);
@@ -380,4 +374,22 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
         }
         return baseMapper.deleteByIds(ids) > 0;
     }
+
+    @Override
+    public Boolean closeOrderByIds(Collection<Long> ids, Boolean isValid) {
+        if (ids == null || ids.isEmpty()) {
+            return true;
+        }
+
+        if (isValid) {
+            // TODO 业务校验
+        }
+
+        LambdaUpdateWrapper<OrderMain> wrapper = new LambdaUpdateWrapper<>();
+        wrapper.in(OrderMain::getId, ids)
+            .set(OrderMain::getOrderStatus, OrderStatus.CLOSED.getCode());
+
+        int affectedRows = baseMapper.update(null, wrapper);
+        return affectedRows > 0;
+    }
 }

+ 136 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderOperateLogServiceImpl.java

@@ -0,0 +1,136 @@
+package org.dromara.order.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.order.domain.bo.OrderOperateLogBo;
+import org.dromara.order.domain.vo.OrderOperateLogVo;
+import org.dromara.order.domain.OrderOperateLog;
+import org.dromara.order.mapper.OrderOperateLogMapper;
+import org.dromara.order.service.IOrderOperateLogService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 订单操作记录Service业务层处理
+ *
+ * @author LionLi
+ * @date 2026-01-26
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class OrderOperateLogServiceImpl  extends ServiceImpl<OrderOperateLogMapper, OrderOperateLog> implements IOrderOperateLogService {
+
+    private final OrderOperateLogMapper baseMapper;
+
+    /**
+     * 查询订单操作记录
+     *
+     * @param id 主键
+     * @return 订单操作记录
+     */
+    @Override
+    public OrderOperateLogVo queryById(Long id){
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 分页查询订单操作记录列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 订单操作记录分页列表
+     */
+    @Override
+    public TableDataInfo<OrderOperateLogVo> queryPageList(OrderOperateLogBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<OrderOperateLog> lqw = buildQueryWrapper(bo);
+        Page<OrderOperateLogVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的订单操作记录列表
+     *
+     * @param bo 查询条件
+     * @return 订单操作记录列表
+     */
+    @Override
+    public List<OrderOperateLogVo> queryList(OrderOperateLogBo bo) {
+        LambdaQueryWrapper<OrderOperateLog> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<OrderOperateLog> buildQueryWrapper(OrderOperateLogBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<OrderOperateLog> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(OrderOperateLog::getId);
+        lqw.eq(bo.getOrderId() != null, OrderOperateLog::getOrderId, bo.getOrderId());
+        lqw.eq(StringUtils.isNotBlank(bo.getAction()), OrderOperateLog::getAction, bo.getAction());
+        lqw.like(StringUtils.isNotBlank(bo.getUserName()), OrderOperateLog::getUserName, bo.getUserName());
+        lqw.eq(StringUtils.isNotBlank(bo.getPlatformCode()), OrderOperateLog::getPlatformCode, bo.getPlatformCode());
+        return lqw;
+    }
+
+    /**
+     * 新增订单操作记录
+     *
+     * @param bo 订单操作记录
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(OrderOperateLogBo bo) {
+        OrderOperateLog add = MapstructUtils.convert(bo, OrderOperateLog.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改订单操作记录
+     *
+     * @param bo 订单操作记录
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(OrderOperateLogBo bo) {
+        OrderOperateLog update = MapstructUtils.convert(bo, OrderOperateLog.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(OrderOperateLog entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除订单操作记录信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}

+ 2 - 2
ruoyi-modules/ruoyi-order/src/main/resources/mapper/order/OrderDeliverMapper.xml

@@ -1,7 +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">
+    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="org.dromara.order.mapper.OrderDeliverMapper">
 
 </mapper>

+ 7 - 0
ruoyi-modules/ruoyi-order/src/main/resources/mapper/order/OrderOperateLogMapper.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.order.mapper.OrderOperateLogMapper">
+
+</mapper>

+ 15 - 5
ruoyi-modules/ruoyi-order/src/main/resources/mapper/order/OrderProductMapper.xml

@@ -82,12 +82,22 @@
       AND del_flag = '0'
     </select>
 
-    <select id="getAssignmentStats" resultType="map">
-        SELECT COUNT(*)                                                 AS total,
-               SUM(CASE WHEN assignment_status = '1' THEN 1 ELSE 0 END) AS assigned
+    <select id="getAssignmentStats" resultType="org.dromara.order.domain.dto.AssignmentStatsDto">
+        SELECT COUNT(*)                                                              AS total,
+               COALESCE(SUM(CASE WHEN assignment_status = '1' THEN 1 ELSE 0 END), 0) AS assigned
         FROM order_product
-        WHERE order_id = #{orderId}
-          AND del_flag = '0'
+        WHERE order_id = #{parentId}
+          AND original_item_id IS NULL
     </select>
+    <update id="updateAssignmentInfo">
+        UPDATE order_product
+        SET assignment_status = #{assignmentStatus},
+        assigned_child_order_id = #{childOrderId},
+        update_time = #{updateTime}
+        WHERE id IN
+        <foreach collection="itemIds" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </update>
 
 </mapper>

+ 105 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/AuthorizeTypeLevelController.java

@@ -0,0 +1,105 @@
+package org.dromara.system.controller.system;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+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.system.domain.vo.AuthorizeTypeLevelVo;
+import org.dromara.system.domain.bo.AuthorizeTypeLevelBo;
+import org.dromara.system.service.IAuthorizeTypeLevelService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 供应商授权等级和授权类型
+ * 前端访问路由地址为:/system/authorizetypeLevel
+ *
+ * @author LionLi
+ * @date 2026-01-27
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/authorizetypeLevel")
+public class AuthorizeTypeLevelController extends BaseController {
+
+    private final IAuthorizeTypeLevelService authorizeTypeLevelService;
+
+    /**
+     * 查询供应商授权等级和授权类型列表
+     */
+    //@SaCheckPermission("system:authorizetypeLevel:list")
+    @GetMapping("/list")
+    public TableDataInfo<AuthorizeTypeLevelVo> list(AuthorizeTypeLevelBo bo, PageQuery pageQuery) {
+        return authorizeTypeLevelService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出供应商授权等级和授权类型列表
+     */
+    //@SaCheckPermission("system:authorizetypeLevel:export")
+    @Log(title = "供应商授权等级和授权类型", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(AuthorizeTypeLevelBo bo, HttpServletResponse response) {
+        List<AuthorizeTypeLevelVo> list = authorizeTypeLevelService.queryList(bo);
+        ExcelUtil.exportExcel(list, "供应商授权等级和授权类型", AuthorizeTypeLevelVo.class, response);
+    }
+
+    /**
+     * 获取供应商授权等级和授权类型详细信息
+     *
+     * @param id 主键
+     */
+    //@SaCheckPermission("system:authorizetypeLevel:query")
+    @GetMapping("/{id}")
+    public R<AuthorizeTypeLevelVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable("id") Long id) {
+        return R.ok(authorizeTypeLevelService.queryById(id));
+    }
+
+    /**
+     * 新增供应商授权等级和授权类型
+     */
+    //@SaCheckPermission("system:authorizetypeLevel:add")
+    @Log(title = "供应商授权等级和授权类型", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody AuthorizeTypeLevelBo bo) {
+        return toAjax(authorizeTypeLevelService.insertByBo(bo));
+    }
+
+    /**
+     * 修改供应商授权等级和授权类型
+     */
+    //@SaCheckPermission("system:authorizetypeLevel:edit")
+    @Log(title = "供应商授权等级和授权类型", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody AuthorizeTypeLevelBo bo) {
+        return toAjax(authorizeTypeLevelService.updateByBo(bo));
+    }
+
+    /**
+     * 删除供应商授权等级和授权类型
+     *
+     * @param ids 主键串
+     */
+    //@SaCheckPermission("system:authorizetypeLevel:remove")
+    @Log(title = "供应商授权等级和授权类型", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable("ids") Long[] ids) {
+        return toAjax(authorizeTypeLevelService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 57 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/AuthorizeTypeLevel.java

@@ -0,0 +1,57 @@
+package org.dromara.system.domain;
+
+import org.dromara.common.tenant.core.TenantEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 供应商授权等级和授权类型对象 authorize_type_level
+ *
+ * @author LionLi
+ * @date 2026-01-27
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("authorize_type_level")
+public class AuthorizeTypeLevel extends TenantEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ID
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     * 授权类型
+     */
+    private String authorizeType;
+
+    /**
+     * 授权等级
+     */
+    private Long authorizeLevel;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+    /**
+     * 删除标志(0代表存在 2代表删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}

+ 44 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/AuthorizeTypeLevelBo.java

@@ -0,0 +1,44 @@
+package org.dromara.system.domain.bo;
+
+import org.dromara.system.domain.AuthorizeTypeLevel;
+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.*;
+
+/**
+ * 供应商授权等级和授权类型业务对象 authorize_type_level
+ *
+ * @author LionLi
+ * @date 2026-01-27
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = AuthorizeTypeLevel.class, reverseConvertGenerate = false)
+public class AuthorizeTypeLevelBo extends BaseEntity {
+
+    /**
+     * ID
+     */
+    private Long id;
+
+    /**
+     * 授权类型
+     */
+    private String authorizeType;
+
+    /**
+     * 授权等级
+     */
+    private Long authorizeLevel;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+
+}

+ 57 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/AuthorizeTypeLevelVo.java

@@ -0,0 +1,57 @@
+package org.dromara.system.domain.vo;
+
+import org.dromara.system.domain.AuthorizeTypeLevel;
+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;
+
+
+
+/**
+ * 供应商授权等级和授权类型视图对象 authorize_type_level
+ *
+ * @author LionLi
+ * @date 2026-01-27
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = AuthorizeTypeLevel.class)
+public class AuthorizeTypeLevelVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ID
+     */
+    @ExcelProperty(value = "ID")
+    private Long id;
+
+    /**
+     * 授权类型
+     */
+    @ExcelProperty(value = "授权类型")
+    private String authorizeType;
+
+    /**
+     * 授权等级
+     */
+    @ExcelProperty(value = "授权等级")
+    private Long authorizeLevel;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "0=正常,1=停用")
+    private String status;
+
+
+}

+ 41 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteAddressAreaServiceImpl.java

@@ -0,0 +1,41 @@
+package org.dromara.system.dubbo;
+
+import lombok.RequiredArgsConstructor;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.dromara.system.api.RemoteAddressAreaService;
+import org.dromara.system.api.domain.dto.AddressAreaDTO;
+import org.dromara.system.domain.AddressArea;
+import org.dromara.system.service.IAddressAreaService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * author
+ * 时间:2026/1/27,14:14
+ */
+@RequiredArgsConstructor
+@Service
+@DubboService
+public class RemoteAddressAreaServiceImpl implements RemoteAddressAreaService {
+
+    private final IAddressAreaService addressAreaService;
+    @Override
+    public List<AddressAreaDTO> listByIds(Set<Long> allAreaIds) {
+        return addressAreaService.listByIds(allAreaIds).stream().map(item -> {
+            AddressAreaDTO addressAreaDTO = new AddressAreaDTO();
+            addressAreaDTO.setId(item.getId());
+            addressAreaDTO.setAreaName(item.getAreaName());
+            addressAreaDTO.setLevel(item.getLevel());
+            addressAreaDTO.setParentCode(item.getParentCode());
+            return addressAreaDTO;
+        }).toList();
+    }
+
+    @Override
+    public Long getIdsByName(String province) {
+        AddressArea one = addressAreaService.lambdaQuery().eq(AddressArea::getAreaName, province).select(AddressArea::getId).one();
+        return one == null ? 0L : one.getId();
+    }
+}

+ 15 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/AuthorizeTypeLevelMapper.java

@@ -0,0 +1,15 @@
+package org.dromara.system.mapper;
+
+import org.dromara.system.domain.AuthorizeTypeLevel;
+import org.dromara.system.domain.vo.AuthorizeTypeLevelVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 供应商授权等级和授权类型Mapper接口
+ *
+ * @author LionLi
+ * @date 2026-01-27
+ */
+public interface AuthorizeTypeLevelMapper extends BaseMapperPlus<AuthorizeTypeLevel, AuthorizeTypeLevelVo> {
+
+}

+ 70 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/IAuthorizeTypeLevelService.java

@@ -0,0 +1,70 @@
+package org.dromara.system.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.dromara.system.domain.AuthorizeTypeLevel;
+import org.dromara.system.domain.vo.AuthorizeTypeLevelVo;
+import org.dromara.system.domain.bo.AuthorizeTypeLevelBo;
+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-27
+ */
+public interface IAuthorizeTypeLevelService extends IService<AuthorizeTypeLevel>{
+
+    /**
+     * 查询供应商授权等级和授权类型
+     *
+     * @param id 主键
+     * @return 供应商授权等级和授权类型
+     */
+    AuthorizeTypeLevelVo queryById(Long id);
+
+    /**
+     * 分页查询供应商授权等级和授权类型列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 供应商授权等级和授权类型分页列表
+     */
+    TableDataInfo<AuthorizeTypeLevelVo> queryPageList(AuthorizeTypeLevelBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的供应商授权等级和授权类型列表
+     *
+     * @param bo 查询条件
+     * @return 供应商授权等级和授权类型列表
+     */
+    List<AuthorizeTypeLevelVo> queryList(AuthorizeTypeLevelBo bo);
+
+    /**
+     * 新增供应商授权等级和授权类型
+     *
+     * @param bo 供应商授权等级和授权类型
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(AuthorizeTypeLevelBo bo);
+
+    /**
+     * 修改供应商授权等级和授权类型
+     *
+     * @param bo 供应商授权等级和授权类型
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(AuthorizeTypeLevelBo bo);
+
+    /**
+     * 校验并批量删除供应商授权等级和授权类型信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 135 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/AuthorizeTypeLevelServiceImpl.java

@@ -0,0 +1,135 @@
+package org.dromara.system.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.system.domain.bo.AuthorizeTypeLevelBo;
+import org.dromara.system.domain.vo.AuthorizeTypeLevelVo;
+import org.dromara.system.domain.AuthorizeTypeLevel;
+import org.dromara.system.mapper.AuthorizeTypeLevelMapper;
+import org.dromara.system.service.IAuthorizeTypeLevelService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 供应商授权等级和授权类型Service业务层处理
+ *
+ * @author LionLi
+ * @date 2026-01-27
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class AuthorizeTypeLevelServiceImpl  extends ServiceImpl<AuthorizeTypeLevelMapper, AuthorizeTypeLevel> implements IAuthorizeTypeLevelService {
+
+    private final AuthorizeTypeLevelMapper baseMapper;
+
+    /**
+     * 查询供应商授权等级和授权类型
+     *
+     * @param id 主键
+     * @return 供应商授权等级和授权类型
+     */
+    @Override
+    public AuthorizeTypeLevelVo queryById(Long id){
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 分页查询供应商授权等级和授权类型列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 供应商授权等级和授权类型分页列表
+     */
+    @Override
+    public TableDataInfo<AuthorizeTypeLevelVo> queryPageList(AuthorizeTypeLevelBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<AuthorizeTypeLevel> lqw = buildQueryWrapper(bo);
+        Page<AuthorizeTypeLevelVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的供应商授权等级和授权类型列表
+     *
+     * @param bo 查询条件
+     * @return 供应商授权等级和授权类型列表
+     */
+    @Override
+    public List<AuthorizeTypeLevelVo> queryList(AuthorizeTypeLevelBo bo) {
+        LambdaQueryWrapper<AuthorizeTypeLevel> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<AuthorizeTypeLevel> buildQueryWrapper(AuthorizeTypeLevelBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<AuthorizeTypeLevel> lqw = Wrappers.lambdaQuery();
+        lqw.orderByAsc(AuthorizeTypeLevel::getId);
+        lqw.eq(StringUtils.isNotBlank(bo.getAuthorizeType()), AuthorizeTypeLevel::getAuthorizeType, bo.getAuthorizeType());
+        lqw.eq(bo.getAuthorizeLevel() != null, AuthorizeTypeLevel::getAuthorizeLevel, bo.getAuthorizeLevel());
+        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), AuthorizeTypeLevel::getStatus, bo.getStatus());
+        return lqw;
+    }
+
+    /**
+     * 新增供应商授权等级和授权类型
+     *
+     * @param bo 供应商授权等级和授权类型
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(AuthorizeTypeLevelBo bo) {
+        AuthorizeTypeLevel add = MapstructUtils.convert(bo, AuthorizeTypeLevel.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改供应商授权等级和授权类型
+     *
+     * @param bo 供应商授权等级和授权类型
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(AuthorizeTypeLevelBo bo) {
+        AuthorizeTypeLevel update = MapstructUtils.convert(bo, AuthorizeTypeLevel.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(AuthorizeTypeLevel 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-system/src/main/resources/mapper/system/AuthorizeTypeLevelMapper.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.system.mapper.AuthorizeTypeLevelMapper">
+
+</mapper>