Bläddra i källkod

会员管理代码

wwh 1 vecka sedan
förälder
incheckning
8ab1e2a247
16 ändrade filer med 1363 tillägg och 0 borttagningar
  1. 2 0
      baqing-shop/src/main/java/com/ruoyi/web/modules/finance/constant/FinanceConstants.java
  2. 39 0
      baqing-shop/src/main/java/com/ruoyi/web/modules/finance/controller/PlatformWithdrawSummaryController.java
  3. 24 0
      baqing-shop/src/main/java/com/ruoyi/web/modules/finance/dto/PlatformWithdrawAuditQuery.java
  4. 59 0
      baqing-shop/src/main/java/com/ruoyi/web/modules/finance/dto/PlatformWithdrawSummaryDetailQuery.java
  5. 23 0
      baqing-shop/src/main/java/com/ruoyi/web/modules/finance/dto/PlatformWithdrawSummaryQuery.java
  6. 24 0
      baqing-shop/src/main/java/com/ruoyi/web/modules/finance/dto/SellerWithdrawQuery.java
  7. 10 0
      baqing-shop/src/main/java/com/ruoyi/web/modules/finance/mapper/BizShopWithdrawMapper.java
  8. 9 0
      baqing-shop/src/main/java/com/ruoyi/web/modules/finance/service/IShopFundService.java
  9. 43 0
      baqing-shop/src/main/java/com/ruoyi/web/modules/finance/service/impl/ShopFundServiceImpl.java
  10. 151 0
      baqing-shop/src/main/java/com/ruoyi/web/modules/finance/vo/PlatformWithdrawSummaryDetailRowVO.java
  11. 116 0
      baqing-shop/src/main/java/com/ruoyi/web/modules/finance/vo/PlatformWithdrawSummaryRowVO.java
  12. 50 0
      baqing-shop/src/main/resources/mapper/finance/BizShopWithdrawMapper.xml
  13. 52 0
      baqing-shop/src/test/java/com/ruoyi/web/modules/finance/service/ShopFundServiceImplTest.java
  14. 9 0
      doc/平台后台/财务管理/提现汇总/提现汇总功能需求-草稿.md
  15. 406 0
      doc/平台后台/财务管理/提现汇总/提现汇总功能需求.md
  16. 346 0
      doc/平台后台/财务管理/提现汇总/提现汇总技术方案.md

+ 2 - 0
baqing-shop/src/main/java/com/ruoyi/web/modules/finance/constant/FinanceConstants.java

@@ -78,4 +78,6 @@ public final class FinanceConstants
78 78
     public static final String MSG_PAY_ACCOUNT_NO_REQUIRED = "请填写账号";
79 79
 
80 80
     public static final String MSG_NO_PAY_ACCOUNT = "请先添加收款账户";
81
+
82
+    public static final String MSG_SHOP_ID_REQUIRED = "请选择店铺";
81 83
 }

+ 39 - 0
baqing-shop/src/main/java/com/ruoyi/web/modules/finance/controller/PlatformWithdrawSummaryController.java

@@ -0,0 +1,39 @@
1
+package com.ruoyi.web.modules.finance.controller;
2
+
3
+import org.springframework.beans.factory.annotation.Autowired;
4
+import org.springframework.security.access.prepost.PreAuthorize;
5
+import org.springframework.web.bind.annotation.GetMapping;
6
+import org.springframework.web.bind.annotation.RequestMapping;
7
+import org.springframework.web.bind.annotation.RestController;
8
+import com.ruoyi.common.core.controller.BaseController;
9
+import com.ruoyi.common.core.page.TableDataInfo;
10
+import com.ruoyi.web.modules.finance.dto.PlatformWithdrawSummaryDetailQuery;
11
+import com.ruoyi.web.modules.finance.dto.PlatformWithdrawSummaryQuery;
12
+import com.ruoyi.web.modules.finance.service.IShopFundService;
13
+
14
+/**
15
+ * 平台端提现汇总
16
+ */
17
+@RestController
18
+@RequestMapping("/agri/finance/withdrawSummary")
19
+public class PlatformWithdrawSummaryController extends BaseController
20
+{
21
+    @Autowired
22
+    private IShopFundService shopFundService;
23
+
24
+    @PreAuthorize("@ss.hasPermi('agri:finance:withdrawSummary:summary')")
25
+    @GetMapping("/shops")
26
+    public TableDataInfo shops(PlatformWithdrawSummaryQuery query)
27
+    {
28
+        startPage();
29
+        return getDataTable(shopFundService.listPlatformWithdrawSummary(query));
30
+    }
31
+
32
+    @PreAuthorize("@ss.hasPermi('agri:finance:withdrawSummary:detail')")
33
+    @GetMapping("/details")
34
+    public TableDataInfo details(PlatformWithdrawSummaryDetailQuery query)
35
+    {
36
+        startPage();
37
+        return getDataTable(shopFundService.listPlatformWithdrawSummaryDetails(query));
38
+    }
39
+}

+ 24 - 0
baqing-shop/src/main/java/com/ruoyi/web/modules/finance/dto/PlatformWithdrawAuditQuery.java

@@ -11,6 +11,10 @@ public class PlatformWithdrawAuditQuery extends BaseEntity
11 11
 
12 12
     private String withdrawStatus;
13 13
 
14
+    private String beginApplyTime;
15
+
16
+    private String endApplyTime;
17
+
14 18
     public String getWithdrawStatus()
15 19
     {
16 20
         return withdrawStatus;
@@ -20,4 +24,24 @@ public class PlatformWithdrawAuditQuery extends BaseEntity
20 24
     {
21 25
         this.withdrawStatus = withdrawStatus;
22 26
     }
27
+
28
+    public String getBeginApplyTime()
29
+    {
30
+        return beginApplyTime;
31
+    }
32
+
33
+    public void setBeginApplyTime(String beginApplyTime)
34
+    {
35
+        this.beginApplyTime = beginApplyTime;
36
+    }
37
+
38
+    public String getEndApplyTime()
39
+    {
40
+        return endApplyTime;
41
+    }
42
+
43
+    public void setEndApplyTime(String endApplyTime)
44
+    {
45
+        this.endApplyTime = endApplyTime;
46
+    }
23 47
 }

+ 59 - 0
baqing-shop/src/main/java/com/ruoyi/web/modules/finance/dto/PlatformWithdrawSummaryDetailQuery.java

@@ -0,0 +1,59 @@
1
+package com.ruoyi.web.modules.finance.dto;
2
+
3
+import com.ruoyi.common.core.domain.BaseEntity;
4
+
5
+/**
6
+ * 平台提现汇总明细查询
7
+ */
8
+public class PlatformWithdrawSummaryDetailQuery extends BaseEntity
9
+{
10
+    private static final long serialVersionUID = 1L;
11
+
12
+    private Long shopId;
13
+
14
+    private String withdrawStatus;
15
+
16
+    private String beginApplyTime;
17
+
18
+    private String endApplyTime;
19
+
20
+    public Long getShopId()
21
+    {
22
+        return shopId;
23
+    }
24
+
25
+    public void setShopId(Long shopId)
26
+    {
27
+        this.shopId = shopId;
28
+    }
29
+
30
+    public String getWithdrawStatus()
31
+    {
32
+        return withdrawStatus;
33
+    }
34
+
35
+    public void setWithdrawStatus(String withdrawStatus)
36
+    {
37
+        this.withdrawStatus = withdrawStatus;
38
+    }
39
+
40
+    public String getBeginApplyTime()
41
+    {
42
+        return beginApplyTime;
43
+    }
44
+
45
+    public void setBeginApplyTime(String beginApplyTime)
46
+    {
47
+        this.beginApplyTime = beginApplyTime;
48
+    }
49
+
50
+    public String getEndApplyTime()
51
+    {
52
+        return endApplyTime;
53
+    }
54
+
55
+    public void setEndApplyTime(String endApplyTime)
56
+    {
57
+        this.endApplyTime = endApplyTime;
58
+    }
59
+}

+ 23 - 0
baqing-shop/src/main/java/com/ruoyi/web/modules/finance/dto/PlatformWithdrawSummaryQuery.java

@@ -0,0 +1,23 @@
1
+package com.ruoyi.web.modules.finance.dto;
2
+
3
+import com.ruoyi.common.core.domain.BaseEntity;
4
+
5
+/**
6
+ * 平台提现汇总列表查询
7
+ */
8
+public class PlatformWithdrawSummaryQuery extends BaseEntity
9
+{
10
+    private static final long serialVersionUID = 1L;
11
+
12
+    private String shopName;
13
+
14
+    public String getShopName()
15
+    {
16
+        return shopName;
17
+    }
18
+
19
+    public void setShopName(String shopName)
20
+    {
21
+        this.shopName = shopName;
22
+    }
23
+}

+ 24 - 0
baqing-shop/src/main/java/com/ruoyi/web/modules/finance/dto/SellerWithdrawQuery.java

@@ -11,6 +11,10 @@ public class SellerWithdrawQuery extends BaseEntity
11 11
 
12 12
     private String withdrawStatus;
13 13
 
14
+    private String beginApplyTime;
15
+
16
+    private String endApplyTime;
17
+
14 18
     public String getWithdrawStatus()
15 19
     {
16 20
         return withdrawStatus;
@@ -20,4 +24,24 @@ public class SellerWithdrawQuery extends BaseEntity
20 24
     {
21 25
         this.withdrawStatus = withdrawStatus;
22 26
     }
27
+
28
+    public String getBeginApplyTime()
29
+    {
30
+        return beginApplyTime;
31
+    }
32
+
33
+    public void setBeginApplyTime(String beginApplyTime)
34
+    {
35
+        this.beginApplyTime = beginApplyTime;
36
+    }
37
+
38
+    public String getEndApplyTime()
39
+    {
40
+        return endApplyTime;
41
+    }
42
+
43
+    public void setEndApplyTime(String endApplyTime)
44
+    {
45
+        this.endApplyTime = endApplyTime;
46
+    }
23 47
 }

+ 10 - 0
baqing-shop/src/main/java/com/ruoyi/web/modules/finance/mapper/BizShopWithdrawMapper.java

@@ -4,8 +4,12 @@ import java.util.List;
4 4
 import org.apache.ibatis.annotations.Param;
5 5
 import com.ruoyi.web.modules.finance.domain.BizShopWithdraw;
6 6
 import com.ruoyi.web.modules.finance.dto.PlatformWithdrawAuditQuery;
7
+import com.ruoyi.web.modules.finance.dto.PlatformWithdrawSummaryDetailQuery;
8
+import com.ruoyi.web.modules.finance.dto.PlatformWithdrawSummaryQuery;
7 9
 import com.ruoyi.web.modules.finance.dto.SellerWithdrawQuery;
8 10
 import com.ruoyi.web.modules.finance.vo.PlatformWithdrawAuditListRowVO;
11
+import com.ruoyi.web.modules.finance.vo.PlatformWithdrawSummaryDetailRowVO;
12
+import com.ruoyi.web.modules.finance.vo.PlatformWithdrawSummaryRowVO;
9 13
 import com.ruoyi.web.modules.finance.vo.SellerWithdrawListRowVO;
10 14
 
11 15
 public interface BizShopWithdrawMapper
@@ -21,6 +25,12 @@ public interface BizShopWithdrawMapper
21 25
 
22 26
     List<PlatformWithdrawAuditListRowVO> selectPlatformList(@Param("query") PlatformWithdrawAuditQuery query);
23 27
 
28
+    List<PlatformWithdrawSummaryRowVO> selectPlatformSummaryList(
29
+            @Param("query") PlatformWithdrawSummaryQuery query);
30
+
31
+    List<PlatformWithdrawSummaryDetailRowVO> selectSummaryDetailList(@Param("shopId") Long shopId,
32
+            @Param("query") PlatformWithdrawSummaryDetailQuery query);
33
+
24 34
     int countByStatus(@Param("withdrawStatus") String withdrawStatus);
25 35
 
26 36
     int updateForAudit(BizShopWithdraw withdraw);

+ 9 - 0
baqing-shop/src/main/java/com/ruoyi/web/modules/finance/service/IShopFundService.java

@@ -6,6 +6,8 @@ import java.util.Map;
6 6
 import com.ruoyi.web.modules.finance.dto.PayAccountSaveDTO;
7 7
 import com.ruoyi.web.modules.finance.dto.PlatformFundLogQuery;
8 8
 import com.ruoyi.web.modules.finance.dto.PlatformShopFundRankQuery;
9
+import com.ruoyi.web.modules.finance.dto.PlatformWithdrawSummaryDetailQuery;
10
+import com.ruoyi.web.modules.finance.dto.PlatformWithdrawSummaryQuery;
9 11
 import com.ruoyi.web.modules.finance.dto.PlatformWithdrawAuditQuery;
10 12
 import com.ruoyi.web.modules.finance.dto.SellerWithdrawQuery;
11 13
 import com.ruoyi.web.modules.finance.dto.SellerWithdrawSubmitDTO;
@@ -16,6 +18,8 @@ import com.ruoyi.web.modules.finance.vo.PayAccountListRowVO;
16 18
 import com.ruoyi.web.modules.finance.vo.PayAccountOptionVO;
17 19
 import com.ruoyi.web.modules.finance.vo.PlatformFundOverviewSummaryVO;
18 20
 import com.ruoyi.web.modules.finance.vo.PlatformShopFundRankRowVO;
21
+import com.ruoyi.web.modules.finance.vo.PlatformWithdrawSummaryDetailRowVO;
22
+import com.ruoyi.web.modules.finance.vo.PlatformWithdrawSummaryRowVO;
19 23
 import com.ruoyi.web.modules.finance.vo.PlatformWithdrawAuditListRowVO;
20 24
 import com.ruoyi.web.modules.finance.vo.SellerWithdrawListRowVO;
21 25
 import com.ruoyi.web.modules.order.domain.BizOrder;
@@ -44,6 +48,11 @@ public interface IShopFundService
44 48
 
45 49
     List<FundLogListRowVO> listPlatformFundLogs(PlatformFundLogQuery query);
46 50
 
51
+    List<PlatformWithdrawSummaryRowVO> listPlatformWithdrawSummary(PlatformWithdrawSummaryQuery query);
52
+
53
+    List<PlatformWithdrawSummaryDetailRowVO> listPlatformWithdrawSummaryDetails(
54
+            PlatformWithdrawSummaryDetailQuery query);
55
+
47 56
     List<SellerWithdrawListRowVO> listSellerWithdraws(Long shopId, SellerWithdrawQuery query);
48 57
 
49 58
     List<PlatformWithdrawAuditListRowVO> listPlatformWithdraws(PlatformWithdrawAuditQuery query);

+ 43 - 0
baqing-shop/src/main/java/com/ruoyi/web/modules/finance/service/impl/ShopFundServiceImpl.java

@@ -19,6 +19,8 @@ import com.ruoyi.web.modules.finance.domain.BizShopWithdraw;
19 19
 import com.ruoyi.web.modules.finance.dto.PayAccountSaveDTO;
20 20
 import com.ruoyi.web.modules.finance.dto.PlatformFundLogQuery;
21 21
 import com.ruoyi.web.modules.finance.dto.PlatformShopFundRankQuery;
22
+import com.ruoyi.web.modules.finance.dto.PlatformWithdrawSummaryDetailQuery;
23
+import com.ruoyi.web.modules.finance.dto.PlatformWithdrawSummaryQuery;
22 24
 import com.ruoyi.web.modules.finance.dto.PlatformWithdrawAuditQuery;
23 25
 import com.ruoyi.web.modules.finance.dto.SellerWithdrawQuery;
24 26
 import com.ruoyi.web.modules.finance.dto.SellerWithdrawSubmitDTO;
@@ -35,6 +37,8 @@ import com.ruoyi.web.modules.finance.vo.PayAccountListRowVO;
35 37
 import com.ruoyi.web.modules.finance.vo.PayAccountOptionVO;
36 38
 import com.ruoyi.web.modules.finance.vo.PlatformFundOverviewSummaryVO;
37 39
 import com.ruoyi.web.modules.finance.vo.PlatformShopFundRankRowVO;
40
+import com.ruoyi.web.modules.finance.vo.PlatformWithdrawSummaryDetailRowVO;
41
+import com.ruoyi.web.modules.finance.vo.PlatformWithdrawSummaryRowVO;
38 42
 import com.ruoyi.web.modules.finance.vo.PlatformWithdrawAuditListRowVO;
39 43
 import com.ruoyi.web.modules.finance.vo.SellerWithdrawListRowVO;
40 44
 import com.ruoyi.web.modules.order.domain.BizOrder;
@@ -286,6 +290,33 @@ public class ShopFundServiceImpl implements IShopFundService
286 290
         return rows;
287 291
     }
288 292
 
293
+    @Override
294
+    public List<PlatformWithdrawSummaryRowVO> listPlatformWithdrawSummary(PlatformWithdrawSummaryQuery query)
295
+    {
296
+        List<PlatformWithdrawSummaryRowVO> rows = withdrawMapper.selectPlatformSummaryList(query);
297
+        for (PlatformWithdrawSummaryRowVO row : rows)
298
+        {
299
+            row.setWithdrawnAmount(normalizeAmount(row.getWithdrawnAmount()));
300
+            row.setPendingAuditAmount(normalizeAmount(row.getPendingAuditAmount()));
301
+            row.setDeleted(ShopConstants.DEL_DELETED.equals(row.getDelFlag()));
302
+            row.setShopStatusText(financeSupport.toShopStatusText(row.getShopStatus(), row.getDelFlag()));
303
+        }
304
+        return rows;
305
+    }
306
+
307
+    @Override
308
+    public List<PlatformWithdrawSummaryDetailRowVO> listPlatformWithdrawSummaryDetails(
309
+            PlatformWithdrawSummaryDetailQuery query)
310
+    {
311
+        if (query == null || query.getShopId() == null || query.getShopId() <= 0)
312
+        {
313
+            throw new ServiceException(FinanceConstants.MSG_SHOP_ID_REQUIRED);
314
+        }
315
+        List<PlatformWithdrawSummaryDetailRowVO> rows = withdrawMapper.selectSummaryDetailList(query.getShopId(), query);
316
+        enrichSummaryDetailRows(rows);
317
+        return rows;
318
+    }
319
+
289 320
     @Override
290 321
     public List<SellerWithdrawListRowVO> listSellerWithdraws(Long shopId, SellerWithdrawQuery query)
291 322
     {
@@ -406,6 +437,18 @@ public class ShopFundServiceImpl implements IShopFundService
406 437
         }
407 438
     }
408 439
 
440
+    private void enrichSummaryDetailRows(List<PlatformWithdrawSummaryDetailRowVO> rows)
441
+    {
442
+        for (PlatformWithdrawSummaryDetailRowVO row : rows)
443
+        {
444
+            row.setWithdrawAmount(normalizeAmount(row.getWithdrawAmount()));
445
+            row.setAccountTypeText(financeSupport.toAccountTypeText(row.getAccountType()));
446
+            row.setWithdrawStatusText(financeSupport.toWithdrawStatusText(row.getWithdrawStatus()));
447
+            row.setAccountSummary(financeSupport.buildAccountSummary(row.getAccountType(), row.getAccountRealName(),
448
+                    row.getAccountNoMask()));
449
+        }
450
+    }
451
+
409 452
     private BizShopWithdraw requirePendingWithdraw(Long withdrawId)
410 453
     {
411 454
         BizShopWithdraw withdraw = withdrawMapper.selectById(withdrawId);

+ 151 - 0
baqing-shop/src/main/java/com/ruoyi/web/modules/finance/vo/PlatformWithdrawSummaryDetailRowVO.java

@@ -0,0 +1,151 @@
1
+package com.ruoyi.web.modules.finance.vo;
2
+
3
+import java.math.BigDecimal;
4
+import java.util.Date;
5
+
6
+public class PlatformWithdrawSummaryDetailRowVO
7
+{
8
+    private Date applyTime;
9
+
10
+    private String shopName;
11
+
12
+    private String accountType;
13
+
14
+    private String accountTypeText;
15
+
16
+    private String accountRealName;
17
+
18
+    private String accountNoMask;
19
+
20
+    private String accountSummary;
21
+
22
+    private BigDecimal withdrawAmount;
23
+
24
+    private String remark;
25
+
26
+    private String withdrawStatus;
27
+
28
+    private String withdrawStatusText;
29
+
30
+    private String processRemark;
31
+
32
+    public Date getApplyTime()
33
+    {
34
+        return applyTime;
35
+    }
36
+
37
+    public void setApplyTime(Date applyTime)
38
+    {
39
+        this.applyTime = applyTime;
40
+    }
41
+
42
+    public String getShopName()
43
+    {
44
+        return shopName;
45
+    }
46
+
47
+    public void setShopName(String shopName)
48
+    {
49
+        this.shopName = shopName;
50
+    }
51
+
52
+    public String getAccountType()
53
+    {
54
+        return accountType;
55
+    }
56
+
57
+    public void setAccountType(String accountType)
58
+    {
59
+        this.accountType = accountType;
60
+    }
61
+
62
+    public String getAccountTypeText()
63
+    {
64
+        return accountTypeText;
65
+    }
66
+
67
+    public void setAccountTypeText(String accountTypeText)
68
+    {
69
+        this.accountTypeText = accountTypeText;
70
+    }
71
+
72
+    public String getAccountRealName()
73
+    {
74
+        return accountRealName;
75
+    }
76
+
77
+    public void setAccountRealName(String accountRealName)
78
+    {
79
+        this.accountRealName = accountRealName;
80
+    }
81
+
82
+    public String getAccountNoMask()
83
+    {
84
+        return accountNoMask;
85
+    }
86
+
87
+    public void setAccountNoMask(String accountNoMask)
88
+    {
89
+        this.accountNoMask = accountNoMask;
90
+    }
91
+
92
+    public String getAccountSummary()
93
+    {
94
+        return accountSummary;
95
+    }
96
+
97
+    public void setAccountSummary(String accountSummary)
98
+    {
99
+        this.accountSummary = accountSummary;
100
+    }
101
+
102
+    public BigDecimal getWithdrawAmount()
103
+    {
104
+        return withdrawAmount;
105
+    }
106
+
107
+    public void setWithdrawAmount(BigDecimal withdrawAmount)
108
+    {
109
+        this.withdrawAmount = withdrawAmount;
110
+    }
111
+
112
+    public String getRemark()
113
+    {
114
+        return remark;
115
+    }
116
+
117
+    public void setRemark(String remark)
118
+    {
119
+        this.remark = remark;
120
+    }
121
+
122
+    public String getWithdrawStatus()
123
+    {
124
+        return withdrawStatus;
125
+    }
126
+
127
+    public void setWithdrawStatus(String withdrawStatus)
128
+    {
129
+        this.withdrawStatus = withdrawStatus;
130
+    }
131
+
132
+    public String getWithdrawStatusText()
133
+    {
134
+        return withdrawStatusText;
135
+    }
136
+
137
+    public void setWithdrawStatusText(String withdrawStatusText)
138
+    {
139
+        this.withdrawStatusText = withdrawStatusText;
140
+    }
141
+
142
+    public String getProcessRemark()
143
+    {
144
+        return processRemark;
145
+    }
146
+
147
+    public void setProcessRemark(String processRemark)
148
+    {
149
+        this.processRemark = processRemark;
150
+    }
151
+}

+ 116 - 0
baqing-shop/src/main/java/com/ruoyi/web/modules/finance/vo/PlatformWithdrawSummaryRowVO.java

@@ -0,0 +1,116 @@
1
+package com.ruoyi.web.modules.finance.vo;
2
+
3
+import java.math.BigDecimal;
4
+import com.fasterxml.jackson.annotation.JsonIgnore;
5
+
6
+public class PlatformWithdrawSummaryRowVO
7
+{
8
+    private Long shopId;
9
+
10
+    private String shopName;
11
+
12
+    private String shopAvatar;
13
+
14
+    private String shopStatus;
15
+
16
+    private String shopStatusText;
17
+
18
+    private Boolean deleted;
19
+
20
+    private BigDecimal withdrawnAmount;
21
+
22
+    private BigDecimal pendingAuditAmount;
23
+
24
+    @JsonIgnore
25
+    private String delFlag;
26
+
27
+    public Long getShopId()
28
+    {
29
+        return shopId;
30
+    }
31
+
32
+    public void setShopId(Long shopId)
33
+    {
34
+        this.shopId = shopId;
35
+    }
36
+
37
+    public String getShopName()
38
+    {
39
+        return shopName;
40
+    }
41
+
42
+    public void setShopName(String shopName)
43
+    {
44
+        this.shopName = shopName;
45
+    }
46
+
47
+    public String getShopAvatar()
48
+    {
49
+        return shopAvatar;
50
+    }
51
+
52
+    public void setShopAvatar(String shopAvatar)
53
+    {
54
+        this.shopAvatar = shopAvatar;
55
+    }
56
+
57
+    public String getShopStatus()
58
+    {
59
+        return shopStatus;
60
+    }
61
+
62
+    public void setShopStatus(String shopStatus)
63
+    {
64
+        this.shopStatus = shopStatus;
65
+    }
66
+
67
+    public String getShopStatusText()
68
+    {
69
+        return shopStatusText;
70
+    }
71
+
72
+    public void setShopStatusText(String shopStatusText)
73
+    {
74
+        this.shopStatusText = shopStatusText;
75
+    }
76
+
77
+    public Boolean getDeleted()
78
+    {
79
+        return deleted;
80
+    }
81
+
82
+    public void setDeleted(Boolean deleted)
83
+    {
84
+        this.deleted = deleted;
85
+    }
86
+
87
+    public BigDecimal getWithdrawnAmount()
88
+    {
89
+        return withdrawnAmount;
90
+    }
91
+
92
+    public void setWithdrawnAmount(BigDecimal withdrawnAmount)
93
+    {
94
+        this.withdrawnAmount = withdrawnAmount;
95
+    }
96
+
97
+    public BigDecimal getPendingAuditAmount()
98
+    {
99
+        return pendingAuditAmount;
100
+    }
101
+
102
+    public void setPendingAuditAmount(BigDecimal pendingAuditAmount)
103
+    {
104
+        this.pendingAuditAmount = pendingAuditAmount;
105
+    }
106
+
107
+    public String getDelFlag()
108
+    {
109
+        return delFlag;
110
+    }
111
+
112
+    public void setDelFlag(String delFlag)
113
+    {
114
+        this.delFlag = delFlag;
115
+    }
116
+}

+ 50 - 0
baqing-shop/src/main/resources/mapper/finance/BizShopWithdrawMapper.xml

@@ -78,6 +78,56 @@
78 78
         order by apply_time desc, withdraw_id desc
79 79
     </select>
80 80
 
81
+    <select id="selectPlatformSummaryList" resultType="com.ruoyi.web.modules.finance.vo.PlatformWithdrawSummaryRowVO">
82
+        select s.shop_id as shopId,
83
+               s.shop_name as shopName,
84
+               s.shop_avatar as shopAvatar,
85
+               s.shop_status as shopStatus,
86
+               s.del_flag as delFlag,
87
+               ifnull(wd.withdrawn_amount, 0) as withdrawnAmount,
88
+               ifnull(wd.pending_audit_amount, 0) as pendingAuditAmount
89
+        from biz_shop s
90
+        left join (
91
+            select shop_id,
92
+                   sum(case when withdraw_status = '3' then withdraw_amount else 0 end) as withdrawn_amount,
93
+                   sum(case when withdraw_status = '1' then withdraw_amount else 0 end) as pending_audit_amount
94
+            from biz_shop_withdraw
95
+            group by shop_id
96
+        ) wd on wd.shop_id = s.shop_id
97
+        where (
98
+            s.del_flag = '0'
99
+            or wd.shop_id is not null
100
+        )
101
+        <if test="query.shopName != null and query.shopName != ''">
102
+            and s.shop_name like concat('%', #{query.shopName}, '%')
103
+        </if>
104
+        order by pendingAuditAmount desc, s.shop_id desc
105
+    </select>
106
+
107
+    <select id="selectSummaryDetailList" resultType="com.ruoyi.web.modules.finance.vo.PlatformWithdrawSummaryDetailRowVO">
108
+        select apply_time as applyTime,
109
+               shop_name as shopName,
110
+               account_type as accountType,
111
+               account_real_name as accountRealName,
112
+               account_no_mask as accountNoMask,
113
+               withdraw_amount as withdrawAmount,
114
+               remark as remark,
115
+               withdraw_status as withdrawStatus,
116
+               process_remark as processRemark
117
+        from biz_shop_withdraw
118
+        where shop_id = #{shopId}
119
+        <if test="query.withdrawStatus != null and query.withdrawStatus != ''">
120
+            and withdraw_status = #{query.withdrawStatus}
121
+        </if>
122
+        <if test="query.beginApplyTime != null and query.beginApplyTime != ''">
123
+            and apply_time &gt;= concat(#{query.beginApplyTime}, ' 00:00:00')
124
+        </if>
125
+        <if test="query.endApplyTime != null and query.endApplyTime != ''">
126
+            and apply_time &lt;= concat(#{query.endApplyTime}, ' 23:59:59')
127
+        </if>
128
+        order by apply_time desc, withdraw_id desc
129
+    </select>
130
+
81 131
     <select id="countByStatus" resultType="int">
82 132
         select count(1) from biz_shop_withdraw where withdraw_status = #{withdrawStatus}
83 133
     </select>

+ 52 - 0
baqing-shop/src/test/java/com/ruoyi/web/modules/finance/service/ShopFundServiceImplTest.java

@@ -32,6 +32,9 @@ import com.ruoyi.web.modules.finance.vo.PlatformFundOverviewSummaryVO;
32 32
 import com.ruoyi.web.modules.finance.vo.PlatformShopFundRankRowVO;
33 33
 import com.ruoyi.web.modules.finance.dto.PlatformFundLogQuery;
34 34
 import com.ruoyi.web.modules.finance.dto.PlatformShopFundRankQuery;
35
+import com.ruoyi.web.modules.finance.dto.PlatformWithdrawSummaryDetailQuery;
36
+import com.ruoyi.web.modules.finance.vo.PlatformWithdrawSummaryDetailRowVO;
37
+import com.ruoyi.web.modules.finance.vo.PlatformWithdrawSummaryRowVO;
35 38
 import com.ruoyi.web.modules.finance.support.FinanceSupport;
36 39
 import com.ruoyi.web.modules.order.mapper.BizOrderMapper;
37 40
 import com.ruoyi.web.modules.store.domain.BizShop;
@@ -197,4 +200,53 @@ class ShopFundServiceImplTest
197 200
         java.util.List<FundLogListRowVO> logRows = shopFundService.listPlatformFundLogs(new PlatformFundLogQuery());
198 201
         assertEquals("订单收支", logRows.get(0).getChangeReasonText());
199 202
     }
203
+
204
+    @Test
205
+    void listPlatformWithdrawSummary_enrichesStatus()
206
+    {
207
+        PlatformWithdrawSummaryRowVO row = new PlatformWithdrawSummaryRowVO();
208
+        row.setShopStatus("0");
209
+        row.setDelFlag("0");
210
+        row.setWithdrawnAmount(new BigDecimal("100"));
211
+        row.setPendingAuditAmount(new BigDecimal("50"));
212
+        when(withdrawMapper.selectPlatformSummaryList(any())).thenReturn(Collections.singletonList(row));
213
+        when(financeSupport.toShopStatusText("0", "0")).thenReturn("开业");
214
+
215
+        java.util.List<PlatformWithdrawSummaryRowVO> rows = shopFundService
216
+                .listPlatformWithdrawSummary(new com.ruoyi.web.modules.finance.dto.PlatformWithdrawSummaryQuery());
217
+        assertEquals(1, rows.size());
218
+        assertEquals("开业", rows.get(0).getShopStatusText());
219
+        assertEquals(new BigDecimal("100.00"), rows.get(0).getWithdrawnAmount());
220
+    }
221
+
222
+    @Test
223
+    void listPlatformWithdrawSummaryDetails_requiresShopId()
224
+    {
225
+        ServiceException ex = assertThrows(ServiceException.class,
226
+                () -> shopFundService.listPlatformWithdrawSummaryDetails(new PlatformWithdrawSummaryDetailQuery()));
227
+        assertEquals(FinanceConstants.MSG_SHOP_ID_REQUIRED, ex.getMessage());
228
+    }
229
+
230
+    @Test
231
+    void listPlatformWithdrawSummaryDetails_enrichesAccount()
232
+    {
233
+        PlatformWithdrawSummaryDetailQuery query = new PlatformWithdrawSummaryDetailQuery();
234
+        query.setShopId(SHOP_ID);
235
+        PlatformWithdrawSummaryDetailRowVO row = new PlatformWithdrawSummaryDetailRowVO();
236
+        row.setAccountType(FinanceConstants.ACCOUNT_TYPE_BANK);
237
+        row.setAccountRealName("张三");
238
+        row.setAccountNoMask("****7890");
239
+        row.setWithdrawStatus(FinanceConstants.WITHDRAW_STATUS_PENDING);
240
+        row.setWithdrawAmount(new BigDecimal("88"));
241
+        when(withdrawMapper.selectSummaryDetailList(eq(SHOP_ID), any())).thenReturn(Collections.singletonList(row));
242
+        when(financeSupport.toAccountTypeText(FinanceConstants.ACCOUNT_TYPE_BANK)).thenReturn("银行卡");
243
+        when(financeSupport.toWithdrawStatusText(FinanceConstants.WITHDRAW_STATUS_PENDING)).thenReturn("待审核");
244
+        when(financeSupport.buildAccountSummary(FinanceConstants.ACCOUNT_TYPE_BANK, "张三", "****7890"))
245
+                .thenReturn("银行卡 ****7890 张三");
246
+
247
+        java.util.List<PlatformWithdrawSummaryDetailRowVO> rows = shopFundService
248
+                .listPlatformWithdrawSummaryDetails(query);
249
+        assertEquals("待审核", rows.get(0).getWithdrawStatusText());
250
+        assertEquals("银行卡 ****7890 张三", rows.get(0).getAccountSummary());
251
+    }
200 252
 }

+ 9 - 0
doc/平台后台/财务管理/提现汇总/提现汇总功能需求-草稿.md

@@ -0,0 +1,9 @@
1
+做一个提现汇总模块:
2
+
3
+1. 列表内容:店铺名称、店铺LOGO、已提现金额、待审核金额、操作;
4
+2. 高级检索:支持按店铺名称检索;
5
+3. 操作:
6
+   (1)查看提现明细,列表内容:申请时间、店铺名称、提现账号、提现金额、备注、提现状态、提现处理说明,支持按申请时间、提现状态检索;
7
+4. 汇总入驻平台的商户的提现情况
8
+5. 异常返回:统一格式 code、msg、data。
9
+6. 技术栈:RuoYi v3.9.2-springboot2 分支 + MySQL-5.7.39。

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 406 - 0
doc/平台后台/财务管理/提现汇总/提现汇总功能需求.md


+ 346 - 0
doc/平台后台/财务管理/提现汇总/提现汇总技术方案.md

@@ -0,0 +1,346 @@
1
+# 提现汇总 — 技术方案
2
+
3
+> **依据:** 《提现汇总功能需求.md》v1.0  
4
+> **关联:** 平台《账务管理.md》v1.0、《提现审核功能需求》v1.0、《提现审核技术方案》v1.0、《资金概览功能需求》v1.0、《资金概览技术方案》v1.0;商家《提现管理功能需求》v1.0、《提现管理技术方案》v1.0、《账户管理功能需求》v1.0;《关联需求分析.md》v1.6  
5
+> **范围:** 平台端 **财务管理 · 提现汇总** — **按店汇总列表**、**单店提现明细**(只读);**不含** 提现审核、商家提交、账户维护。  
6
+> **原则:** **全平台** 可见;**纯查询**;汇总/明细与 **提现审核、商家提现记录** **同源同口径**。
7
+
8
+---
9
+
10
+## 1. 技术架构
11
+
12
+| 项 | 选型 |
13
+|----|------|
14
+| 基础框架 | RuoYi **v3.9.2**(`springboot2` 分支) |
15
+| 数据库 | **MySQL 5.7.39**;读 **`biz_shop_withdraw`**、**`biz_shop`** |
16
+| ORM / 权限 / 响应 | MyBatis;`@PreAuthorize`;`AjaxResult` / `TableDataInfo` |
17
+| 店铺上下文 | **无** `X-Shop-Id`(平台端全平台) |
18
+| 金额 | `BigDecimal`;两位小数 |
19
+
20
+### 1.1 与兄弟模块边界
21
+
22
+| 维度 | **本模块 · 提现汇总** | 平台 · 提现审核 | 商家 · 提现管理 | 平台 · 资金概览 |
23
+|------|----------------------|-----------------|-----------------|-----------------|
24
+| 路径 | `/agri/finance/withdrawSummary` | `/withdrawAudit` | `/agri/seller/finance/withdraw` | `/fundOverview` |
25
+| 写操作 | **无** | approve/reject | submit | **无** |
26
+| 列表形态 | **按店汇总** + 单店明细 | **全平台逐单** | **单店逐单** | 余额/冻结排行 |
27
+| 汇总列 | 已提现 / 待审核 | **无** | **无** | **无** |
28
+| 数据源 | `biz_shop_withdraw` | 同左 | 同左 | wallet / order / log |
29
+
30
+### 1.2 数据流(只读展示)
31
+
32
+```text
33
+【上游写入 · 非本模块】
34
+    商家 POST /withdraw/submit → biz_shop_withdraw(status=1 待审核)
35
+    平台 PUT /withdrawAudit/approve|reject → status=3|2
36
+
37
+【本模块 · 只读】
38
+    GET /shops   → biz_shop LEFT JOIN 按店 SUM(withdraw)
39
+    GET /details → biz_shop_withdraw WHERE shop_id = ?(分页+检索)
40
+```
41
+
42
+> 汇总 **不缓存**;随 **提现审核** 结果 **实时** 变化。详见《账务管理.md》:**已提现** = 完成态单据;**待审核** = 待审态单据。
43
+
44
+### 1.3 模块落位
45
+
46
+**文档目录:** `doc/平台后台/财务管理/提现汇总/`  
47
+**菜单:** 财务管理 → 提现汇总(建议 `menu_id=7630`,`parent_id=7600`)  
48
+**后端包:** `com.ruoyi.web.modules.finance`
49
+
50
+```text
51
+finance/
52
+├── controller/PlatformWithdrawSummaryController.java   # 本模块入口
53
+├── service/IShopFundService.java                       # 扩展汇总/明细方法
54
+├── service/impl/ShopFundServiceImpl.java
55
+├── dto/PlatformWithdrawSummaryQuery.java
56
+├── dto/PlatformWithdrawSummaryDetailQuery.java
57
+├── vo/PlatformWithdrawSummaryRowVO.java
58
+├── vo/PlatformWithdrawSummaryDetailRowVO.java
59
+├── mapper/BizShopWithdrawMapper.java                   # 扩展汇总/明细 SQL
60
+├── support/FinanceSupport.java                         # 状态/账号文案
61
+resources/mapper/finance/BizShopWithdrawMapper.xml
62
+
63
+sql/biz_shop_finance.sql                                # 已有,本模块不增表
64
+sql/biz_platform_withdraw_summary_menu.sql              # 7630 菜单与权限
65
+```
66
+
67
+**前端(建议):**
68
+
69
+| 项 | 值 |
70
+|----|-----|
71
+| 页面 | `ruoyi-ui/src/views/agri/finance/withdrawSummary/index.vue` |
72
+| API | `ruoyi-ui/src/api/agri/finance/withdrawSummary.js` |
73
+| 明细弹窗 | 汇总行「查看提现明细」→ 抽屉调 `/details?shopId=` |
74
+
75
+---
76
+
77
+## 2. 数据库设计
78
+
79
+**权威 DDL:** [`sql/biz_shop_finance.sql`](../../../../sql/biz_shop_finance.sql)
80
+
81
+本模块 **不建表**;**只读** 下列表。
82
+
83
+### 2.1 提现单 `biz_shop_withdraw`(汇总 + 明细)
84
+
85
+| 字段 | 用途 |
86
+|------|------|
87
+| shop_id | 按店汇总、明细过滤 |
88
+| shop_name | 明细 **店铺名称** 列(申请快照;汇总列表 **优先** 读 `biz_shop` 当前名) |
89
+| withdraw_amount | 汇总 **求和**、明细 **展示** |
90
+| withdraw_status | `1`待审核 `2`审核不通过 `3`提现完成 |
91
+| apply_time | 明细 **申请时间**;检索、排序 |
92
+| account_type / account_real_name / account_no_mask | 明细 **提现账号** 摘要 |
93
+| remark | 商家备注 |
94
+| process_remark | **提现处理说明** |
95
+
96
+**状态常量(`FinanceConstants`):**
97
+
98
+| withdraw_status | 文案 | 计入已提现 | 计入待审核 |
99
+|-----------------|------|------------|------------|
100
+| `1` | 待审核 | 否 | **是** |
101
+| `2` | 审核不通过 | 否 | 否 |
102
+| `3` | 提现完成 | **是** | 否 |
103
+
104
+**索引(已有):** `idx_shop_status_time (shop_id, withdraw_status, apply_time)`、`idx_status_time (withdraw_status, apply_time)` — 满足按店聚合与明细检索。
105
+
106
+### 2.2 店铺 `biz_shop`(汇总 · 展示)
107
+
108
+| 字段 | 用途 |
109
+|------|------|
110
+| shop_id | 主键 |
111
+| shop_name | 汇总 **店铺名称**;明细检索 **店名** 过滤(汇总列表) |
112
+| shop_avatar | 汇总 **店铺 LOGO** |
113
+| shop_status | `0` 开业 / `1` 停业 |
114
+| del_flag | `0` 正常;`2` 逻辑删除 |
115
+
116
+**汇总数据范围:**
117
+
118
+```sql
119
+-- 纳入:未删店(含从未提现,金额展示 0)
120
+-- 追加:已逻辑删除 且 存在提现单
121
+WHERE s.del_flag = '0'
122
+   OR EXISTS (SELECT 1 FROM biz_shop_withdraw wd WHERE wd.shop_id = s.shop_id LIMIT 1)
123
+```
124
+
125
+### 2.3 按店汇总 SQL 骨架
126
+
127
+```sql
128
+SELECT s.shop_id,
129
+       s.shop_name,
130
+       s.shop_avatar,
131
+       s.shop_status,
132
+       s.del_flag,
133
+       IFNULL(wd.withdrawn_amount, 0)     AS withdrawnAmount,
134
+       IFNULL(wd.pending_audit_amount, 0) AS pendingAuditAmount
135
+FROM biz_shop s
136
+LEFT JOIN (
137
+    SELECT shop_id,
138
+           SUM(CASE WHEN withdraw_status = '3' THEN withdraw_amount ELSE 0 END) AS withdrawn_amount,
139
+           SUM(CASE WHEN withdraw_status = '1' THEN withdraw_amount ELSE 0 END) AS pending_audit_amount
140
+    FROM biz_shop_withdraw
141
+    GROUP BY shop_id
142
+) wd ON wd.shop_id = s.shop_id
143
+WHERE (s.del_flag = '0' OR wd.shop_id IS NOT NULL)
144
+  /* 可选:AND s.shop_name LIKE ... */
145
+ORDER BY pending_audit_amount DESC, s.shop_id DESC
146
+```
147
+
148
+> **验收(WS-A3/A4):** 单店 `withdrawnAmount` = 该店 `withdraw_status='3'` 的 `SUM(withdraw_amount)`;`pendingAuditAmount` 同理 `status='1'`。
149
+
150
+### 2.4 单店明细 SQL 骨架
151
+
152
+```sql
153
+SELECT apply_time,
154
+       shop_name,
155
+       account_type, account_real_name, account_no_mask,
156
+       withdraw_amount, remark, withdraw_status, process_remark
157
+FROM biz_shop_withdraw
158
+WHERE shop_id = #{shopId}
159
+  /* 可选:withdraw_status、apply_time 区间 */
160
+ORDER BY apply_time DESC, withdraw_id DESC
161
+```
162
+
163
+> 与 **`selectSellerList`**(商家提现记录)、**`selectPlatformList`**(提现审核)**同一数据源**;本接口 **固定** `shop_id`。
164
+
165
+---
166
+
167
+## 3. 接口设计
168
+
169
+**基路径:** `/agri/finance/withdrawSummary`  
170
+**上下文:** **无** 店铺请求头  
171
+**写接口:** **无**
172
+
173
+### 3.1 接口一览
174
+
175
+| 方法 | 路径 | 权限 | 说明 |
176
+|------|------|------|------|
177
+| GET | `/shops` | `agri:finance:withdrawSummary:summary` | 店铺提现汇总(分页) |
178
+| GET | `/details` | `agri:finance:withdrawSummary:detail` | 单店提现明细(分页) |
179
+
180
+> v1 可合并为 `agri:finance:withdrawSummary:query`;需求允许 **分权**(§8)。
181
+
182
+### 3.2 店铺提现汇总 `GET /shops`
183
+
184
+**Query(PlatformWithdrawSummaryQuery):**
185
+
186
+| 参数 | 类型 | 必填 | 说明 |
187
+|------|------|------|------|
188
+| pageNum | int | 是 | 页码 |
189
+| pageSize | int | 是 | 每页条数 |
190
+| shopName | string | 否 | 店铺名称 **模糊** |
191
+
192
+**定稿默认排序:** `pendingAuditAmount DESC, shopId DESC`(待审核金额降序,便于运营优先关注)。
193
+
194
+**行 VO(PlatformWithdrawSummaryRowVO):**
195
+
196
+| 字段 | 来源 | 说明 |
197
+|------|------|------|
198
+| shopId | `biz_shop` | 下钻明细时传入 |
199
+| shopName | `biz_shop.shop_name` | 当前店名 |
200
+| shopAvatar | `biz_shop.shop_avatar` | LOGO |
201
+| shopStatus | `biz_shop.shop_status` | `0`/`1` |
202
+| shopStatusText | 服务层 | 开业/停业/已删除 |
203
+| deleted | 服务层 | `del_flag='2'` |
204
+| withdrawnAmount | SUM withdraw `status=3` | **已提现金额** |
205
+| pendingAuditAmount | SUM withdraw `status=1` | **待审核金额** |
206
+
207
+**无提现记录店:** 两金额返回 `0.00`(WS-A11)。
208
+
209
+### 3.3 提现明细 `GET /details`
210
+
211
+**Query(PlatformWithdrawSummaryDetailQuery):**
212
+
213
+| 参数 | 类型 | 必填 | 说明 |
214
+|------|------|------|------|
215
+| pageNum | int | 是 | 页码 |
216
+| pageSize | int | 是 | 每页条数 |
217
+| shopId | long | **是** | 汇总行传入;**固定单店** |
218
+| withdrawStatus | string | 否 | `1`/`2`/`3`;空=全部 |
219
+| beginApplyTime | date | 否 | 申请时间起(含 `00:00:00`) |
220
+| endApplyTime | date | 否 | 申请时间止(含 `23:59:59`) |
221
+
222
+**固定排序:** `apply_time DESC, withdraw_id DESC`。
223
+
224
+**行 VO(PlatformWithdrawSummaryDetailRowVO):**
225
+
226
+| 字段 | 说明 |
227
+|------|------|
228
+| applyTime | 申请时间 |
229
+| shopName | 店铺名称(快照) |
230
+| accountSummary | 提现账号摘要(`FinanceSupport.buildAccountSummary`) |
231
+| withdrawAmount | 提现金额 |
232
+| remark | 商家备注 |
233
+| withdrawStatus / withdrawStatusText | 状态码 + 文案 |
234
+| processRemark | 提现处理说明;待审核为 **null** 或 **—**(前端) |
235
+
236
+**与提现审核列表差异:**
237
+
238
+| 字段 | 提现审核 `/withdrawAudit/list` | 本模块 `/details` |
239
+|------|----------------------------------|-------------------|
240
+| withdrawNo | **有** | **非本期**(需求 §10) |
241
+| withdrawId / 操作 | **有** | **无** |
242
+| shopId 过滤 | 全平台 | **必填** |
243
+
244
+**与商家 `/withdraw/list` 对账:** 同一 `shopId` + 相同筛选条件下,**申请时间、金额、状态、处理说明、账号摘要** **须一致**(WS-A6)。
245
+
246
+### 3.4 与兄弟接口对照
247
+
248
+| 能力 | 本模块 | 提现审核 | 商家提现管理 |
249
+|------|--------|----------|--------------|
250
+| 按店已提现/待审 | `/shops` | — | — |
251
+| 全平台逐单 | — | `/list` | — |
252
+| 单店逐单 | `/details` | — | `/list` |
253
+| 审核 | — | `/approve` `/reject` | — |
254
+| 提交 | — | — | `/submit` |
255
+
256
+---
257
+
258
+## 4. 业务规则(实现)
259
+
260
+| 编号 | 需求规则 | 实现要点 |
261
+|------|----------|----------|
262
+| WS-A1 | 只读 | Controller **仅 GET** |
263
+| WS-A2 | 全平台 | `/shops` **无** shopId 限制 |
264
+| WS-A3 | 已提现 = 完成态之和 | SQL `CASE status='3'` |
265
+| WS-A4 | 待审核 = 待审态之和 | SQL `CASE status='1'` |
266
+| WS-A5 | 驳回不计入汇总 | 聚合 **不含** `status='2'` |
267
+| WS-A6 | 明细与审核/商家一致 | 复用 enrich 逻辑(账号/状态文案) |
268
+| WS-A7 | 店名/LOGO 读 shop | 汇总 JOIN `biz_shop` |
269
+| WS-A8 | 明细检索 | `withdrawStatus` + `begin/endApplyTime` |
270
+| WS-A9 | 汇总检索 | `shopName LIKE` |
271
+| WS-A10 | 不写审核 | **无** approve/reject |
272
+| WS-A11 | 无提现店仍展示 | LEFT JOIN 聚合;NULL→0 |
273
+
274
+**店铺状态文案:** 复用 `FinanceSupport.toShopStatusText(shopStatus, delFlag)`(与 **资金概览** 一致)。
275
+
276
+**明细 enrich(与 `listPlatformWithdraws` 对齐):**
277
+
278
+```text
279
+accountTypeText  ← toAccountTypeText
280
+withdrawStatusText ← toWithdrawStatusText
281
+accountSummary ← buildAccountSummary(type, realName, mask)
282
+```
283
+
284
+---
285
+
286
+## 5. 权限与菜单
287
+
288
+| 权限 | 说明 |
289
+|------|------|
290
+| `agri:finance:withdrawSummary:summary` | 店铺汇总列表 |
291
+| `agri:finance:withdrawSummary:detail` | 提现明细 |
292
+
293
+| 菜单 | menu_id | path | 父菜单 |
294
+|------|---------|------|--------|
295
+| 财务管理(平台) | 7600 | finance | — |
296
+| 提现审核 | 7610 | withdrawAudit | 7600 |
297
+| 资金概览 | 7620 | fundOverview | 7600 |
298
+| **提现汇总** | **7630** | **withdrawSummary** | **7600** |
299
+
300
+脚本:[`sql/biz_platform_withdraw_summary_menu.sql`](../../../../sql/biz_platform_withdraw_summary_menu.sql)(待建)。
301
+
302
+---
303
+
304
+## 6. 测试要点
305
+
306
+| 编号 | 场景 | 预期 |
307
+|------|------|------|
308
+| T1 | 从未提现的店 | 汇总行存在;两金额 **0** |
309
+| T2 | 提交 100 待审 | 该店 `pendingAuditAmount=100` |
310
+| T3 | 审核通过 | `withdrawnAmount+100`;`pendingAuditAmount-100` |
311
+| T4 | 审核驳回 | 汇总两列 **不变**;明细 **status=2** |
312
+| T5 | shops 店名检索 | 仅匹配店名行 |
313
+| T6 | details shopId 必填 | 缺参 **400/业务提示** |
314
+| T7 | details 时间/状态筛选 | 与 SQL 条件一致 |
315
+| T8 | 与商家 list 对账 | 同 shopId 明细 **一致** |
316
+| T9 | 与 withdrawAudit 对账 | 同店待审金额 = 审核列表该店待审 **SUM** |
317
+| T10 | 已删店有历史单 | 汇总仍展示;`deleted=true` |
318
+
319
+**建议测试类:** `ShopFundServiceImplTest`(汇总/明细)、`PlatformWithdrawSummaryControllerTest`(MockMvc)。
320
+
321
+---
322
+
323
+## 7. 实现状态
324
+
325
+| 项 | 状态 |
326
+|----|------|
327
+| DDL(withdraw / shop) | **已有** |
328
+| `PlatformWithdrawSummaryController` | **待建** |
329
+| `IShopFundService` 汇总/明细方法 | **待扩展** |
330
+| `BizShopWithdrawMapper` 汇总/明细 SQL | **待扩展** |
331
+| VO/DTO | **待建** |
332
+| 菜单 SQL 7630 | **待建** |
333
+| ruoyi-ui 提现汇总页 | **待建** |
334
+| 汇总列排序 / 跳转审核 / 导出 | **非本期** |
335
+
336
+---
337
+
338
+## 8. 版本记录
339
+
340
+| 版本 | 说明 |
341
+|------|------|
342
+| **v1.0** | 首版:对齐《提现汇总功能需求》v1.0;关联提现审核/资金概览/商家提现;简练 DB/接口设计;RuoYi v3.9.2 + MySQL 5.7.39 |
343
+
344
+---
345
+
346
+*文档版本:v1.0 · 依据《提现汇总功能需求.md》v1.0*