Эх сурвалжийг харах

feat(order): 添加订单支付功能并优化客户组织架构权限控制

- 新增订单支付接口 orderPay 方法,支持信用支付方式
- 实现临时额度扣减逻辑,优先扣减临时额度再扣剩余额度
- 添加订单金额和客户信用额度校验机制
- 重构客户信息API,新增公司ID字段和销售信息服务
- 优化PC端组织架构权限控制,统一使用 LoginHelper.getLoginUser().getCustomerId()
- 调整PC端联系人、部门、角色等控制器路径映射
- 新增购物车远程服务接口,支持批量查询和删除购物车项
- 添加订单支付DTO和支付类型枚举类
- 完善参数校验和异常处理机制
hurx 2 сар өмнө
parent
commit
89448c1adc
21 өөрчлөгдсөн 418 нэмэгдсэн , 35 устгасан
  1. 12 0
      ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/RemoteCustomerSalesService.java
  2. 1 0
      ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/RemoteCustomerService.java
  3. 13 3
      ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/domain/CustomerApiVo.java
  4. 69 0
      ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/domain/vo/RemoteCustomerSalesVo.java
  5. 14 0
      ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/RemoteProductShoppingCartService.java
  6. 41 0
      ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/RemoteProductShoppingCartVo.java
  7. 17 0
      ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/OrderPayType.java
  8. 1 1
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/CustomerInfoController.java
  9. 16 16
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/pc/PcContactController.java
  10. 7 7
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/pc/PcDeptController.java
  11. 49 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/dubbo/RemoteCustomerSalesServiceImpl.java
  12. 1 0
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/dubbo/RemoteCustomerServiceImpl.java
  13. 3 3
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ICustomerInfoService.java
  14. 2 2
      ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/impl/CustomerInfoServiceImpl.java
  15. 4 0
      ruoyi-modules/ruoyi-order/pom.xml
  16. 14 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/dto/OrderPayDto.java
  17. 2 0
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderMainService.java
  18. 104 2
      ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderMainServiceImpl.java
  19. 18 0
      ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/dubbo/RemoteProductShoppingCartServiceImpl.java
  20. 29 0
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/pc/PcComStaffController.java
  21. 1 1
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/pc/controller/PcRoleController.java

+ 12 - 0
ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/RemoteCustomerSalesService.java

@@ -0,0 +1,12 @@
+package org.dromara.customer.api;
+
+import org.dromara.customer.api.domain.vo.RemoteCustomerSalesVo;
+
+public interface RemoteCustomerSalesService {
+
+    /*根据客户id 查询客户的销售信息  一对一*/
+    RemoteCustomerSalesVo selectCustomerSalesInfoByCustomerId(Long customerId);
+
+    /*更新客户销售信息*/
+    Boolean updateCustomerSalesInfo(RemoteCustomerSalesVo vo);
+}

+ 1 - 0
ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/RemoteCustomerService.java

@@ -21,4 +21,5 @@ public interface RemoteCustomerService {
      * 根据userId查询客户id
      */
     Long selectCustomerIdByUserId(Long userId);
+
 }

+ 13 - 3
ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/domain/CustomerApiVo.java

@@ -14,12 +14,22 @@ public class CustomerApiVo implements Serializable {
     @Serial
     private static final long serialVersionUID = 1L;
 
-    /** 客户ID */
+    /**
+     * 客户ID
+     */
     private Long id;
 
-    /** 客户编号 */
+    private Long companyId;
+
+    /**
+     * 客户编号
+     */
     private String customerNo;
 
-    /** 客户名称 */
+    /**
+     * 客户名称
+     */
     private String customerName;
+
+
 }

+ 69 - 0
ruoyi-api/ruoyi-api-customer/src/main/java/org/dromara/customer/api/domain/vo/RemoteCustomerSalesVo.java

@@ -0,0 +1,69 @@
+package org.dromara.customer.api.domain.vo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+public class RemoteCustomerSalesVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 销售信息ID
+     */
+    private Long id;
+
+    /**
+     * 关联客户ID
+     */
+    private Long customerId;
+
+    /**
+     * 信用额度
+     */
+    private BigDecimal creditAmount;
+
+    /**
+     * 剩余额度
+     */
+    private BigDecimal remainingQuota;
+
+    /**
+     * 临时额度
+     */
+    private BigDecimal temporaryQuota;
+
+    /**
+     * 账期(如:30天)
+     */
+    private Integer accountPeriod;
+
+    /**
+     * 账单日(每月几号)
+     */
+    private Integer billDate;
+
+    /**
+     * 计费日(如:每月1日)
+     */
+    private Integer billingDay;
+
+    /**
+     * 订单审核方式
+     */
+    private String orderAudit;
+
+    /**
+     * 信用管理方式
+     */
+    private Long creditManagementId;
+
+    /**
+     * 信用支付密码
+     */
+    private String creditPaymentPassword;
+}

+ 14 - 0
ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/RemoteProductShoppingCartService.java

@@ -1,5 +1,11 @@
 package org.dromara.product.api;
 
+import org.dromara.product.api.domain.RemoteProductShoppingCartVo;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
 /**
  * author
  * 时间:2026/2/4,17:33
@@ -10,4 +16,12 @@ public interface RemoteProductShoppingCartService {
 
     //解顶购物车 就是 删除购物车
     boolean unlockShoppingCart(Long productId, Long count);
+
+    /*根据购物车id 查询购物车项*/
+    List<RemoteProductShoppingCartVo> getShoppingCartList(Set<Long> cartIds);
+
+    /*批量删除购物车项*/
+    Boolean deleteWithValidByIds(Set<Long> ids);
+
+
 }

+ 41 - 0
ruoyi-api/ruoyi-api-product/src/main/java/org/dromara/product/api/domain/RemoteProductShoppingCartVo.java

@@ -0,0 +1,41 @@
+package org.dromara.product.api.domain;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class RemoteProductShoppingCartVo implements Serializable {
+
+    /**
+     *
+     */
+    private Long id;
+
+    /**
+     * 用户id
+     */
+    private Long userId;
+
+    /**
+     * 商品id
+     */
+    private Long productId;
+
+    /**
+     * 客户id
+     */
+    private Long customerId;
+
+    /**
+     * 商品数量
+     */
+    private Long productNum;
+
+    /**
+     * 状态(0正常 1停用)
+     */
+    private String status;
+
+
+}

+ 17 - 0
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/enums/OrderPayType.java

@@ -0,0 +1,17 @@
+package org.dromara.common.core.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public enum OrderPayType {
+
+    /**
+     * 信用支付
+     */
+    CREDIT_PAY("0", "信用支付");
+
+    private final String code;
+    private final String info;
+}

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

@@ -172,7 +172,7 @@ public class CustomerInfoController extends BaseController {
     @Log(title = "客户信息", businessType = BusinessType.UPDATE)
     @PutMapping("/updateCreditAmount")
     public R<Void> updateCreditAmount(@RequestBody CustomerSalesInfoBo bo) {
-        return toAjax(customerInfoService.updateCreditAmount(bo.getCustomerIds(), bo.getCreditAmount()));
+        return toAjax(customerInfoService.updateCreditAmount(bo.getCustomerIds(), bo.getTemporaryQuota()));
     }
 
     /**

+ 16 - 16
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/pc/PcContactController.java

@@ -1,11 +1,13 @@
 package org.dromara.customer.controller.pc;
 
-import java.util.List;
-
 import cn.dev33.satoken.annotation.SaIgnore;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
 import lombok.RequiredArgsConstructor;
-import jakarta.validation.constraints.*;
 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.idempotent.annotation.RepeatSubmit;
 import org.dromara.common.log.annotation.Log;
 import org.dromara.common.log.enums.BusinessType;
 import org.dromara.common.mybatis.core.page.PageQuery;
@@ -17,9 +19,8 @@ import org.dromara.customer.domain.vo.CustomerContactVo;
 import org.dromara.customer.service.ICustomerContactService;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
-import org.dromara.common.core.validate.AddGroup;
-import org.dromara.common.core.validate.EditGroup;
-import org.dromara.common.idempotent.annotation.RepeatSubmit;
+
+import java.util.List;
 
 /**
  * PC端 - 人员管理
@@ -32,7 +33,7 @@ import org.dromara.common.idempotent.annotation.RepeatSubmit;
 @Validated
 @RequiredArgsConstructor
 @RestController
-@RequestMapping("/pc/organization/contact")
+@RequestMapping("/organization/contact")
 public class PcContactController extends BaseController {
 
     private final ICustomerContactService customerContactService;
@@ -45,18 +46,17 @@ public class PcContactController extends BaseController {
         // TODO: 需要根据当前登录用户的实际ID查询联系人信息
         // 目前LoginHelper.getUserId()返回的是customerId(企业ID)
         // 需要通过其他方式(如手机号、用户名)来查询当前用户的联系人记录
-        Long customerId = LoginHelper.getUserId();
+        Long userId = LoginHelper.getUserId();
 
         // 查询该企业下的联系人(不限制是否为主联系人)
         CustomerContactBo bo = new CustomerContactBo();
-        bo.setCustomerId(customerId);
-
-        List<CustomerContactVo> list = customerContactService.queryList(bo);
-        if (list != null && !list.isEmpty()) {
-            return R.ok(list.get(0));
+        bo.setId(userId);
+        CustomerContactVo customerContactVo = customerContactService.queryById(userId);
+        if (customerContactVo != null) {
+            return R.ok(customerContactVo);
         }
 
-        return R.fail("未找到当前用户信息,customerId: " + customerId);
+        return R.fail("未找到当前用户信息");
     }
 
     /**
@@ -87,7 +87,7 @@ public class PcContactController extends BaseController {
 
         // 验证联系人是否属于当前用户的企业
         if (vo != null) {
-            Long customerId = LoginHelper.getUserId();
+            Long customerId = LoginHelper.getLoginUser().getCustomerId();
             if (!customerId.equals(vo.getCustomerId())) {
                 return R.fail("无权访问该联系人");
             }
@@ -119,7 +119,7 @@ public class PcContactController extends BaseController {
     @PutMapping()
     public R<Void> edit(@Validated(EditGroup.class) @RequestBody CustomerContactBo bo) {
         // 获取当前登录用户的企业ID
-        Long customerId = LoginHelper.getUserId();
+        Long customerId = LoginHelper.getLoginUser().getCustomerId();
 
         // 验证联系人是否属于当前用户的企业
         CustomerContactVo existingContact = customerContactService.queryById(bo.getId());

+ 7 - 7
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/controller/pc/PcDeptController.java

@@ -31,7 +31,7 @@ import org.dromara.common.idempotent.annotation.RepeatSubmit;
 @Validated
 @RequiredArgsConstructor
 @RestController
-@RequestMapping("/pc/organization/dept")
+@RequestMapping("/organization/dept")
 public class PcDeptController extends BaseController {
 
     private final ICustomerDeptService customerDeptService;
@@ -43,7 +43,7 @@ public class PcDeptController extends BaseController {
     @GetMapping("/tree")
     public R<List<CustomerDeptTreeVo>> getDeptTree() {
         // 获取当前登录用户的企业ID
-        Long customerId = LoginHelper.getUserId();
+        Long customerId = LoginHelper.getLoginUser().getCustomerId();
 
         List<CustomerDeptTreeVo> tree = customerDeptService.getCustomerDeptTree(customerId);
         return R.ok(tree);
@@ -56,7 +56,7 @@ public class PcDeptController extends BaseController {
     @GetMapping("/list")
     public R<List<CustomerDeptVo>> list(CustomerDeptBo bo) {
         // 获取当前登录用户的企业ID
-        Long customerId = LoginHelper.getUserId();
+        Long customerId = LoginHelper.getLoginUser().getCustomerId();
         // 强制设置企业ID,防止越权访问
         bo.setCustomerId(customerId);
 
@@ -78,7 +78,7 @@ public class PcDeptController extends BaseController {
 
         // 验证部门是否属于当前用户的企业
         if (vo != null) {
-            Long customerId = LoginHelper.getUserId();
+            Long customerId = LoginHelper.getLoginUser().getCustomerId();
             if (!customerId.equals(vo.getCustomerId())) {
                 return R.fail("无权访问该部门");
             }
@@ -95,7 +95,7 @@ public class PcDeptController extends BaseController {
     @PostMapping()
     public R<Void> add(@Validated(AddGroup.class) @RequestBody CustomerDeptBo bo) {
         // 获取当前登录用户的企业ID
-        Long customerId = LoginHelper.getUserId();
+        Long customerId = LoginHelper.getLoginUser().getCustomerId();
         // 强制设置企业ID,防止为其他企业添加部门
         bo.setCustomerId(customerId);
 
@@ -110,7 +110,7 @@ public class PcDeptController extends BaseController {
     @PutMapping()
     public R<Void> edit(@Validated(EditGroup.class) @RequestBody CustomerDeptBo bo) {
         // 获取当前登录用户的企业ID
-        Long customerId = LoginHelper.getUserId();
+        Long customerId = LoginHelper.getLoginUser().getCustomerId();
 
         // 验证部门是否属于当前用户的企业
         CustomerDeptVo existingDept = customerDeptService.queryById(bo.getDeptId());
@@ -137,7 +137,7 @@ public class PcDeptController extends BaseController {
     public R<Void> remove(@NotEmpty(message = "主键不能为空")
                           @PathVariable("ids") Long[] ids) {
         // 获取当前登录用户的企业ID
-        Long customerId = LoginHelper.getUserId();
+        Long customerId = LoginHelper.getLoginUser().getCustomerId();
 
         // 验证所有部门是否都属于当前用户的企业
         for (Long id : ids) {

+ 49 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/dubbo/RemoteCustomerSalesServiceImpl.java

@@ -0,0 +1,49 @@
+package org.dromara.customer.dubbo;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.customer.api.RemoteCustomerSalesService;
+import org.dromara.customer.api.domain.vo.RemoteCustomerSalesVo;
+import org.dromara.customer.domain.CustomerSalesInfo;
+import org.dromara.customer.domain.IndustryCategory;
+import org.dromara.customer.domain.vo.CustomerSalesInfoVo;
+import org.dromara.customer.service.ICustomerSalesInfoService;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+@DubboService
+public class RemoteCustomerSalesServiceImpl implements RemoteCustomerSalesService {
+
+    private final ICustomerSalesInfoService customerSalesInfoService;
+
+    @Override
+    public RemoteCustomerSalesVo selectCustomerSalesInfoByCustomerId(Long customerId) {
+        CustomerSalesInfoVo salesInfoVo = customerSalesInfoService.queryByCustomerId(customerId);
+        return MapstructUtils.convert(salesInfoVo, RemoteCustomerSalesVo.class);
+    }
+
+    /*更新客户销售信息*/
+    @Override
+    public Boolean updateCustomerSalesInfo(RemoteCustomerSalesVo vo) {
+        CustomerSalesInfo salesInfo = customerSalesInfoService.getOne(Wrappers.lambdaQuery(CustomerSalesInfo.class)
+            .eq(CustomerSalesInfo::getCustomerId, vo.getCustomerId())
+        );
+
+        if (salesInfo == null) {
+            salesInfo = new CustomerSalesInfo();
+        }
+        salesInfo.setId(vo.getId());
+        salesInfo.setRemainingQuota(vo.getRemainingQuota());
+
+        return customerSalesInfoService.saveOrUpdate(salesInfo);
+
+    }
+}

+ 1 - 0
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/dubbo/RemoteCustomerServiceImpl.java

@@ -47,6 +47,7 @@ public class RemoteCustomerServiceImpl implements RemoteCustomerService {
             c -> {
                 CustomerApiVo vo = new CustomerApiVo();
                 vo.setId(c.getId());
+                vo.setCompanyId(c.getBelongCompanyId());
                 vo.setCustomerNo(c.getCustomerNo());
                 vo.setCustomerName(c.getCustomerName() != null ? c.getCustomerName() : c.getBusinessCustomerName());
                 return vo;

+ 3 - 3
ruoyi-modules/ruoyi-customer/src/main/java/org/dromara/customer/service/ICustomerInfoService.java

@@ -99,7 +99,7 @@ public interface ICustomerInfoService extends IService<CustomerInfo> {
     int updateCustomerCheckStatus(Long customerId, String status);
 
     /*修改临时额度*/
-    int updateCreditAmount(List<Long> customerIds, BigDecimal creditAmount);
+    int updateCreditAmount(List<Long> customerIds, BigDecimal temporaryQuota);
 
     /*设置客户标签*/
     int setCustomerInfoTag(List<Long> customerIds, List<Long> tagIds);
@@ -124,7 +124,7 @@ public interface ICustomerInfoService extends IService<CustomerInfo> {
     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
 
     /**
-    * 客户注册
-    * */
+     * 客户注册
+     */
     Boolean register(CustomerRegisterBo bo);
 }

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

@@ -725,14 +725,14 @@ public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, Cus
     }
 
     @Override
-    public int updateCreditAmount(List<Long> customerIds, BigDecimal creditAmount) {
+    public int updateCreditAmount(List<Long> customerIds, BigDecimal temporaryQuota) {
         if (customerIds == null || customerIds.isEmpty()) {
             return 0; // 避免无效更新
         }
         return customerSalesInfoMapper.update(
             null,
             new LambdaUpdateWrapper<CustomerSalesInfo>()
-                .set(CustomerSalesInfo::getCreditAmount, creditAmount)
+                .set(CustomerSalesInfo::getTemporaryQuota, temporaryQuota)
                 .in(CustomerSalesInfo::getCustomerId, customerIds)
         );
     }

+ 4 - 0
ruoyi-modules/ruoyi-order/pom.xml

@@ -122,6 +122,10 @@
             <artifactId>sdk</artifactId>
             <version>1.0.11</version>
         </dependency>
+        <dependency>
+            <groupId>org.dromara</groupId>
+            <artifactId>ruoyi-api-product</artifactId>
+        </dependency>
 
     </dependencies>
 

+ 14 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/dto/OrderPayDto.java

@@ -0,0 +1,14 @@
+package org.dromara.order.domain.dto;
+
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Data
+public class OrderPayDto {
+
+    @NotNull(message = "订单ID不能为空")
+    private Long orderId;
+
+    @NotNull(message = "支付方式不能为空")
+    private String payType;
+}

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

@@ -79,6 +79,8 @@ public interface IOrderMainService extends IService<OrderMain> {
     int updateStatus(OrderMainBo bo);
 
 
+    Boolean orderPay(Long customerId, Long orderId, String payType);
+
     /**
      * 修改订单审核状态
      *

+ 104 - 2
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/OrderMainServiceImpl.java

@@ -10,13 +10,16 @@ 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.OrderPayType;
 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;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.redis.utils.SequenceUtils;
+import org.dromara.customer.api.RemoteCustomerSalesService;
 import org.dromara.customer.api.RemoteCustomerService;
+import org.dromara.customer.api.domain.vo.RemoteCustomerSalesVo;
 import org.dromara.order.domain.OrderMain;
 import org.dromara.order.domain.OrderProduct;
 import org.dromara.order.domain.bo.OrderMainBo;
@@ -60,6 +63,9 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
     @DubboReference
     private RemoteCustomerService remoteCustomerService;
 
+    @DubboReference
+    private RemoteCustomerSalesService remoteCustomerSalesService;
+
     private final OrderMainMapper baseMapper;
 
     private final OrderProductMapper orderProductMapper;
@@ -303,9 +309,25 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
             // 4. 转换并填充子订单商品
             List<OrderProduct> orderProducts = orderProductBos.stream()
                 .map(productBo -> {
+                    BigDecimal unitPrice = productBo.getOrderPrice();
+                    Long quantity = productBo.getOrderQuantity();
+
+                    // 防御性校验
+                    if (unitPrice == null) {
+                        throw new IllegalArgumentException("商品单价不能为空");
+                    }
+                    if (quantity == null || quantity <= 0) {
+                        throw new IllegalArgumentException("商品数量必须大于0");
+                    }
+
                     OrderProduct product = MapstructUtils.convert(productBo, OrderProduct.class);
-                    product.setOrderId(orderId);      // 关联主单ID
-                    product.setOrderNo(orderNo);      // 关联订单号
+                    product.setOrderId(orderId);
+                    product.setOrderNo(orderNo);
+
+                    // 小计 = 单价 × 数量
+                    BigDecimal subtotal = unitPrice.multiply(BigDecimal.valueOf(quantity));
+                    product.setSubtotal(subtotal);
+
                     return product;
                 })
                 .collect(Collectors.toList());
@@ -442,6 +464,86 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain
         log.info("订单 {} 已确认,状态更新为待发货", orderId);
     }
 
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean orderPay(Long customerId, Long orderId, String payType) {
+        // 参数校验
+        if (orderId == null) {
+            throw new IllegalArgumentException("订单ID不能为空");
+        }
+        if (customerId == null) {
+            throw new IllegalArgumentException("客户ID不能为空");
+        }
+        if (payType == null || !OrderPayType.CREDIT_PAY.getCode().equals(payType)) {
+            throw new IllegalArgumentException("仅支持信用支付方式");
+        }
+
+        // 查询订单
+        OrderMainVo orderMainVo = baseMapper.selectVoById(orderId);
+        if (orderMainVo == null) {
+            throw new IllegalArgumentException("订单不存在");
+        }
+        if (!Objects.equals(customerId, orderMainVo.getCustomerId())) {
+            throw new IllegalArgumentException("订单不属于当前客户");
+        }
+
+        BigDecimal totalAmount = orderMainVo.getTotalAmount();
+        if (totalAmount == null || totalAmount.compareTo(BigDecimal.ZERO) <= 0) {
+            throw new IllegalArgumentException("订单金额无效");
+        }
+
+        // 查询客户信用销售信息
+        RemoteCustomerSalesVo salesInfo = remoteCustomerSalesService.selectCustomerSalesInfoByCustomerId(customerId);
+        if (salesInfo == null) {
+            throw new IllegalStateException("客户信用信息未配置,无法使用信用支付");
+        }
+
+        // 获取可用额度:剩余额度 + 临时额度
+        BigDecimal remainingQuota = Optional.ofNullable(salesInfo.getRemainingQuota()).orElse(BigDecimal.ZERO);
+        BigDecimal temporaryQuota = Optional.ofNullable(salesInfo.getTemporaryQuota()).orElse(BigDecimal.ZERO);
+
+
+        // 临时额度可用于支付
+        BigDecimal availableCredit = remainingQuota.add(temporaryQuota);
+
+        // 判断额度是否足够
+        if (availableCredit.compareTo(totalAmount) < 0) {
+            throw new IllegalStateException("信用额度不足,无法完成支付");
+        }
+
+        // 扣减逻辑:优先扣减临时额度,再扣剩余额度
+        BigDecimal newRemainingQuota = remainingQuota;
+        BigDecimal newTemporaryQuota = temporaryQuota;
+
+        if (temporaryQuota.compareTo(totalAmount) >= 0) {
+            // 临时额度足够,只扣临时额度
+            newTemporaryQuota = temporaryQuota.subtract(totalAmount);
+        } else {
+            // 临时额度不足,先清空临时额度,再扣剩余额度
+            BigDecimal remainingToDeduct = totalAmount.subtract(temporaryQuota);
+            newTemporaryQuota = BigDecimal.ZERO;
+            newRemainingQuota = remainingQuota.subtract(remainingToDeduct);
+
+            // 理论上不会为负(前面已校验总额度足够),但防御性检查
+            if (newRemainingQuota.compareTo(BigDecimal.ZERO) < 0) {
+                throw new IllegalStateException("信用额度计算异常,请联系管理员");
+            }
+        }
+
+        // 更新对象
+        salesInfo.setRemainingQuota(newRemainingQuota);
+        salesInfo.setTemporaryQuota(newTemporaryQuota);
+
+        // 执行更新
+        boolean updated = remoteCustomerSalesService.updateCustomerSalesInfo(salesInfo);
+        if (!updated) {
+            throw new RuntimeException("信用额度更新失败,请重试");
+        }
+
+        return true;
+    }
+
     /**
      * 修改状态
      *

+ 18 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/dubbo/RemoteProductShoppingCartServiceImpl.java

@@ -3,11 +3,17 @@ package org.dromara.product.dubbo;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.config.annotation.DubboService;
+import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.product.api.RemoteProductShoppingCartService;
+import org.dromara.product.api.domain.RemoteProductShoppingCartVo;
+import org.dromara.product.domain.ProductShoppingCart;
 import org.dromara.product.domain.bo.ProductShoppingCartBo;
 import org.dromara.product.service.IProductShoppingCartService;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+import java.util.Set;
+
 /**
  * author
  * 时间:2026/2/4,17:35
@@ -19,6 +25,7 @@ import org.springframework.stereotype.Service;
 public class RemoteProductShoppingCartServiceImpl implements RemoteProductShoppingCartService {
 
     private final IProductShoppingCartService productShoppingCartService;
+
     @Override
     public boolean lockShoppingCart(Long productId, Long count) {
         ProductShoppingCartBo productShoppingCartBo = new ProductShoppingCartBo();
@@ -36,4 +43,15 @@ public class RemoteProductShoppingCartServiceImpl implements RemoteProductShoppi
     public boolean unlockShoppingCart(Long productId, Long count) {
         return false;
     }
+
+    @Override
+    public List<RemoteProductShoppingCartVo> getShoppingCartList(Set<Long> cartIds) {
+        List<ProductShoppingCart> productShoppingCarts = productShoppingCartService.listByIds(cartIds);
+        return MapstructUtils.convert(productShoppingCarts, RemoteProductShoppingCartVo.class);
+    }
+
+    @Override
+    public Boolean deleteWithValidByIds(Set<Long> ids) {
+        return productShoppingCartService.deleteWithValidByIds(ids, true);
+    }
 }

+ 29 - 0
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/pc/PcComStaffController.java

@@ -0,0 +1,29 @@
+package org.dromara.system.controller.pc;
+
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.RequiredArgsConstructor;
+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.annotation.Log;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.system.domain.bo.SysRoleBo;
+import org.dromara.system.domain.vo.SysRoleVo;
+import org.dromara.system.service.IComStaffService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/organization/comStaff")
+public class PcComStaffController extends BaseController {
+
+    private final IComStaffService comStaffService;
+
+   
+}

+ 1 - 1
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/pc/controller/PcRoleController.java

@@ -29,7 +29,7 @@ import org.springframework.web.bind.annotation.*;
 @Validated
 @RequiredArgsConstructor
 @RestController
-@RequestMapping("/pc/organization/role")
+@RequestMapping("/organization/role")
 public class PcRoleController extends BaseController {
 
     private final ISysRoleService sysRoleService;