林小张 пре 2 месеци
родитељ
комит
16cc882ded

+ 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));
     }
 
     /**

+ 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);
 

+ 14 - 0
ruoyi-modules/ruoyi-bill/src/main/java/org/dromara/bill/service/impl/StatementOrderServiceImpl.java

@@ -191,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);
+    }
+
     /**
      * 查询符合条件的对账单主列表
      *