ai-engineering-init 1.3.3 → 1.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/hooks/skill-forced-eval.js +2 -1
- package/.claude/skills/add-skill/SKILL.md +205 -116
- package/.claude/skills/leniu-report-customization/SKILL.md +42 -2
- package/.claude/skills/leniu-report-standard-customization/SKILL.md +551 -0
- package/.codex/skills/add-skill/SKILL.md +205 -116
- package/.codex/skills/leniu-report-customization/SKILL.md +42 -2
- package/.codex/skills/leniu-report-standard-customization/SKILL.md +551 -0
- package/.cursor/rules/skill-activation.mdc +2 -0
- package/.cursor/skills/add-skill/SKILL.md +205 -116
- package/.cursor/skills/leniu-report-customization/SKILL.md +42 -2
- package/.cursor/skills/leniu-report-standard-customization/SKILL.md +551 -0
- package/AGENTS.md +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: leniu-report-standard-customization
|
|
3
|
+
description: |
|
|
4
|
+
leniu-tengyun-core 标准版(core-report 模块)定制报表开发指南。基于独立 report_order_info / report_refund / report_account_flow 等报表基础表实现汇总报表。
|
|
5
|
+
|
|
6
|
+
触发场景:
|
|
7
|
+
- 在标准版(core-report 模块)中开发定制汇总报表
|
|
8
|
+
- 基于标准版退款表(report_refund)处理退款统计
|
|
9
|
+
- 开发账户流水报表(日结/操作员/钱包消费/消费汇总)
|
|
10
|
+
- 开发经营分析报表(营业额/用户/菜品/评价/充值/设备分析)
|
|
11
|
+
- 开发商户维度的消费/充值汇总报表
|
|
12
|
+
|
|
13
|
+
触发词:标准版报表、core-report、report_refund、report_refund_detail、经营分析、营业额分析、用户活跃度、菜品排行、操作员统计、账户日结、钱包消费汇总、商户消费汇总、ReportOrderConsumeService、ReportAccountConsumeService
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# leniu 标准版定制报表开发指南
|
|
17
|
+
|
|
18
|
+
## ⚠️ 版本识别(必读)
|
|
19
|
+
|
|
20
|
+
**本 skill 仅适用于标准版(core-report 独立模块)**。开始前必须确认项目版本。
|
|
21
|
+
|
|
22
|
+
### 如何判断当前项目版本
|
|
23
|
+
|
|
24
|
+
**方法一:查看目录结构**
|
|
25
|
+
```bash
|
|
26
|
+
# 若存在独立的 core-report 模块 → 标准版(使用本 skill)
|
|
27
|
+
ls leniu-tengyun-core/core-report/
|
|
28
|
+
|
|
29
|
+
# 若报表代码在 sys-canteen 内 → v5.29 版本(使用 leniu-report-customization)
|
|
30
|
+
ls leniu-tengyun-core/sys-canteen/src/main/java/.../report/statistics/
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**方法二:查看 git tag**
|
|
34
|
+
```bash
|
|
35
|
+
git tag --sort=-v:refname | head -5
|
|
36
|
+
# 标准版 tag 格式示例:v6.x.x、standard-xxx、core-report-xxx
|
|
37
|
+
# v5.29 tag 格式示例:v5.29.x
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**方法三:检查 report_order_info 表字段**
|
|
41
|
+
- 有 `consume_type` 字段 → v5.29 版本,使用 `leniu-report-customization`
|
|
42
|
+
- 无 `consume_type`,有独立 `report_refund` 表 → 标准版,使用本 skill
|
|
43
|
+
|
|
44
|
+
### 两版本核心差异速查
|
|
45
|
+
|
|
46
|
+
| 特性 | 标准版(本指南) | v5.29 版本 |
|
|
47
|
+
|------|--------------|-----------|
|
|
48
|
+
| 模块位置 | `core-report` 独立模块 | `sys-canteen` 内嵌 |
|
|
49
|
+
| 退款存储 | 独立 `report_refund` / `report_refund_detail` 表 | 合并入 `report_order_info`,`consumeType=2` |
|
|
50
|
+
| 退款金额 | **正数**存储,需手动减退 | **负数**存储,直接 SUM 即净额 |
|
|
51
|
+
| 第二阶段消费 | 用 `fix()` 按日重算 | 用 `batchConsume()` 增量累加 |
|
|
52
|
+
| report_order_info.consumeType | **无此字段** | 1=消费,2=退款 |
|
|
53
|
+
| 分析模块 | 完整引擎(6 大分析维度) | 无独立分析模块 |
|
|
54
|
+
|
|
55
|
+
> **v5.29 报表开发**请使用 `leniu-report-customization` skill。
|
|
56
|
+
> **钱包枚举(AccWalletIdEnum)、交易类型枚举(AccTradeTypeEnum)**与 v5.29 相同,参见 `leniu-report-customization`。
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 概述
|
|
61
|
+
|
|
62
|
+
本指南适用于 **标准版**(`core-report` 独立模块)的报表系统。
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 一、报表系统架构
|
|
67
|
+
|
|
68
|
+
### 1.1 模块总览
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
core-report/src/main/java/net/xnzn/core/report/statistics/
|
|
72
|
+
├── config/mq/ # 3 大 MQ 监听器 + 消费调度 + 线程池
|
|
73
|
+
├── constants/ # 枚举常量
|
|
74
|
+
├── order/ # 订单报表(basic/summary/fix/analysis)
|
|
75
|
+
├── account/ # 账户流水报表
|
|
76
|
+
├── merchant/ # 商户维度报表
|
|
77
|
+
├── common/ # 金额范围设置/错误日志/定时任务
|
|
78
|
+
├── param/ # 公共参数类
|
|
79
|
+
└── vo/ # 公共 VO
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 1.2 三大 MQ 监听器
|
|
83
|
+
|
|
84
|
+
| 监听器 | Topic/Tag | 说明 |
|
|
85
|
+
|-------|-----------|------|
|
|
86
|
+
| `ReportOrderMQListener` | `order / order-v3-placed` | 下单消费 |
|
|
87
|
+
| `ReportOrderRefundMQListener` | `order / order-v3-refunded` | 退款消费 |
|
|
88
|
+
| `ReportAccountMQListener` | `acc / acc-trade-report-queue` | 账户流水 |
|
|
89
|
+
|
|
90
|
+
### 1.3 两阶段消费模型
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
MQ 消息到达
|
|
94
|
+
↓
|
|
95
|
+
第一阶段(ORDER < 10,同步写基础表)
|
|
96
|
+
├── ORDER=1 ReportOrderInfoService → report_order_info
|
|
97
|
+
├── ORDER=2 ReportOrderDiscountService → report_order_discount
|
|
98
|
+
├── ORDER=3 ReportOrderDetailService → report_order_detail
|
|
99
|
+
├── ORDER=4 ReportOrderPayService → report_order_pay
|
|
100
|
+
├── ORDER=5 ReportRefundService → report_refund
|
|
101
|
+
├── ORDER=6 ReportRefundDetailService → report_refund_detail
|
|
102
|
+
└── ORDER=11 ReportOrderInfoSnapshotService → report_order_info_snapshot
|
|
103
|
+
↓
|
|
104
|
+
第二阶段(ORDER >= 10,按日重算汇总表,由 Redis 计数触发)
|
|
105
|
+
├── ORDER=13 ReportSumMealtimeService → 分餐次汇总
|
|
106
|
+
├── ORDER=16 ReportSumPayService → 支付渠道汇总
|
|
107
|
+
├── ORDER=17 ReportSumPayMerService → 商户支付汇总
|
|
108
|
+
├── ORDER=18 ReportSumDishesService → 菜品销售汇总
|
|
109
|
+
├── ORDER=50 ReportAnalysisCustService → 用户分析汇总
|
|
110
|
+
└── ORDER=51 ReportAnalysisDishesSaleService→ 菜品销售分析
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 1.4 第二阶段核心逻辑(fix 重算模式)
|
|
114
|
+
|
|
115
|
+
**关键区别**:标准版第二阶段使用 `fix()` 方法按日重算,而非 v5.29 的 `batchConsume()` 增量模式。
|
|
116
|
+
|
|
117
|
+
```java
|
|
118
|
+
// ReportConsumerService.consumeOrderReport()
|
|
119
|
+
void consumeOrderReport() {
|
|
120
|
+
for (TenantInfo tenant : allTenants) {
|
|
121
|
+
Executors.doInTenant(tenant.getId(), () -> {
|
|
122
|
+
RLock lock = RedisUtil.getLock(REPORT_ORDER_LOCK);
|
|
123
|
+
try {
|
|
124
|
+
lock.lock(120, TimeUnit.MINUTES);
|
|
125
|
+
List<ReportNotConsumeDTO> list =
|
|
126
|
+
reportOrderInfoService.queryNotConsumeData();
|
|
127
|
+
|
|
128
|
+
// 菜品统计:按就餐日期(orderDate)分组
|
|
129
|
+
list.stream().collect(groupingBy(e -> e.getOrderDate()))
|
|
130
|
+
.forEach((date, items) -> reportSumDishesService.fix(buildParam(date)));
|
|
131
|
+
|
|
132
|
+
// 其他报表:按支付日期(statisticDate)分组
|
|
133
|
+
list.stream().collect(groupingBy(e -> e.getStatisticDate()))
|
|
134
|
+
.forEach((date, items) -> {
|
|
135
|
+
for (ReportOrderConsumeService svc : orderConsumeServices) {
|
|
136
|
+
if (svc.getOrder() >= 10) svc.fix(buildParam(date));
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
reportOrderInfoService.updateOrderMsg(list); // 标记已消费
|
|
141
|
+
} finally { lock.unlock(); }
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### 1.5 触发机制
|
|
148
|
+
|
|
149
|
+
**Redis 计数触发**:每条 MQ 消息递减 `yst:%s:order:report:count:key`,达阈值(默认 100)时异步触发消费。
|
|
150
|
+
|
|
151
|
+
**XxlJob 定时兜底**:`orderReportMsgTask` / `accountReportMsgTask`
|
|
152
|
+
|
|
153
|
+
**线程池**:单线程 + `DiscardPolicy`,保证顺序性。
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## 二、核心基础表字段说明
|
|
158
|
+
|
|
159
|
+
### 2.1 report_order_info(报表订单主表)
|
|
160
|
+
|
|
161
|
+
> **关键**:标准版中此表**仅存正向订单**,退款数据存在独立的 `report_refund` 表中。无 `consumeType` 字段。
|
|
162
|
+
|
|
163
|
+
| 字段 | 类型 | 说明 |
|
|
164
|
+
|------|------|------|
|
|
165
|
+
| `orderId` | Long | 主键(雪花 ID) |
|
|
166
|
+
| `machineSn` | String | 设备 SN |
|
|
167
|
+
| `orgId/custId` | Long | 组织/人员 ID |
|
|
168
|
+
| `nuClearMode` | Integer | 核身方式(1刷卡/2刷脸/3扫码) |
|
|
169
|
+
| `sourceType/ifOnline` | Integer | 来源类型/是否在线(1是/2否) |
|
|
170
|
+
| `canteenId/stallId` | Long | 食堂/档口 ID |
|
|
171
|
+
| `mealtimeType` | Integer | 餐次(1早/2午/3下午茶/4晚/5夜宵) |
|
|
172
|
+
| `psnType` | Integer | 人员类别 |
|
|
173
|
+
| `payableAmount` | BigDecimal | 应付金额(分) |
|
|
174
|
+
| `discountsAmount` | BigDecimal | 优惠金额(分,取负数) |
|
|
175
|
+
| `deliveryAmount/packingAmount` | BigDecimal | 配送费/包装费(分) |
|
|
176
|
+
| `realAmount` | BigDecimal | 实付金额(分) |
|
|
177
|
+
| `accPayAmount/outPayAmount` | BigDecimal | 账户支付/外部支付金额(分) |
|
|
178
|
+
| `refundAmount` | BigDecimal | 累计退款金额(分) |
|
|
179
|
+
| `orderTime` | LocalDateTime | 下单时间 |
|
|
180
|
+
| `orderDate` | LocalDate | 就餐日期 |
|
|
181
|
+
| `orderType` | Integer | 订单类型(1当餐/2预订/3报餐/4扫码/5餐桌/6自助/11商城/12超市/21补扣/22外部) |
|
|
182
|
+
| `orderRefundState` | Integer | 退款状态(1未退/2已退/3部分退) |
|
|
183
|
+
| `payTime` | LocalDateTime | 支付时间 |
|
|
184
|
+
| `payType/payChannel` | Integer | 支付方式/渠道 |
|
|
185
|
+
| `ageType/holidayType` | Integer | 年龄段/节假日类型 |
|
|
186
|
+
| `status` | Integer | 消费状态(0未消费/1已消费) |
|
|
187
|
+
|
|
188
|
+
### 2.2 report_order_detail(订单菜品明细表)
|
|
189
|
+
|
|
190
|
+
| 字段 | 类型 | 说明 |
|
|
191
|
+
|------|------|------|
|
|
192
|
+
| `detailId` | Long | 明细主键 |
|
|
193
|
+
| `orderId` | Long | 关联订单 ID |
|
|
194
|
+
| `goodsDishesId/goodsDishesName` | Long/String | 菜品信息 |
|
|
195
|
+
| `salePrice/prefPrice/price` | BigDecimal | 售卖价/优惠价/最终价(分) |
|
|
196
|
+
| `weightUnit` | BigDecimal | 每份重量(g) |
|
|
197
|
+
| `quantity` | Integer | 数量/重量 |
|
|
198
|
+
| `salesMode` | Integer | 销售方式(1按份/2称重) |
|
|
199
|
+
| `detailType` | Integer | 类别(1菜品/2套餐/3商品/4按键/5补扣/6报餐) |
|
|
200
|
+
| `totalAmount/realAmount` | BigDecimal | 总金额/实付(分) |
|
|
201
|
+
| `detailState` | Integer | 状态(**1正常/2已退菜/3部分退菜**) |
|
|
202
|
+
| `goodsRefundNum` | Integer | 已退数量 |
|
|
203
|
+
| `refundAmount` | BigDecimal | 退款金额(分) |
|
|
204
|
+
|
|
205
|
+
### 2.3 report_refund / report_refund_detail(退款表,标准版特有)
|
|
206
|
+
|
|
207
|
+
**report_refund**:`orderRefundId`(主键), `orderId`(原始订单), `realRefundAmount`(退款金额,**正数**), `applyTime`, `applyType`(1退单/2纠错), `checkTime`
|
|
208
|
+
|
|
209
|
+
**report_refund_detail**:`orderRefundId`, `detailId`(菜品详情), `realQuantity`(退单数量), `realRefundAmount`(**正数**)
|
|
210
|
+
|
|
211
|
+
### 2.4 其他基础表
|
|
212
|
+
|
|
213
|
+
- **report_order_pay**:`orderId`, `payType`, `payChannel`, `outTradeNo`, `payAmount`, `refundAmount`, `payableAmount`
|
|
214
|
+
- **report_order_discount**:`orderId`, `changeAmount`, `changeType`(1上浮/2优惠), `changeDetailType`(1上浮/11菜品优惠/12打折/13累计减免/14固定减免)
|
|
215
|
+
- **report_order_info_snapshot**:订单交易快照,字段同 report_order_info 的维度字段子集
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## 三、退款数据处理(核心重点)
|
|
220
|
+
|
|
221
|
+
### 3.1 标准版退款存储模型
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
正向订单:orderId → report_order_info (realAmount 为正)
|
|
225
|
+
退款记录:orderRefundId → report_refund (realRefundAmount 为正)
|
|
226
|
+
→ report_refund_detail (realRefundAmount 为正)
|
|
227
|
+
同时更新:report_order_info.orderRefundState = 2(全退) 或 3(部分退)
|
|
228
|
+
report_order_info.refundAmount = 累计退款金额
|
|
229
|
+
report_order_detail.detailState = 2 或 3
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### 3.2 退款 MQ 消费
|
|
233
|
+
|
|
234
|
+
```java
|
|
235
|
+
// ReportRefundService.consume() - 仅处理 REFUND 类型
|
|
236
|
+
if (!OrderChangeTypeEnum.REFUND.getKey().equals(payload.getChangeType())) return;
|
|
237
|
+
ReportRefund reportRefund = BeanUtil.copyProperties(payload.getOrderRefund(), ReportRefund.class);
|
|
238
|
+
baseMapper.insert(reportRefund);
|
|
239
|
+
// ReportRefundDetailService 同理,批量插入 refundDetailList
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### 3.3 净消费金额计算(3种方式)
|
|
243
|
+
|
|
244
|
+
**方式一:主表 refundAmount 减退**(推荐)
|
|
245
|
+
```sql
|
|
246
|
+
SELECT SUM(real_amount) AS consumeAmount,
|
|
247
|
+
SUM(real_amount - IFNULL(refund_amount, 0)) AS netAmount
|
|
248
|
+
FROM report_order_info WHERE pay_time BETWEEN #{start} AND #{end}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**方式二:排除全退订单**
|
|
252
|
+
```sql
|
|
253
|
+
SELECT SUM(real_amount - IFNULL(refund_amount, 0)) AS netAmount
|
|
254
|
+
FROM report_order_info WHERE order_refund_state IN (1, 3)
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
**方式三:关联 report_refund**
|
|
258
|
+
```sql
|
|
259
|
+
SELECT o.canteen_id, SUM(o.real_amount) AS consume, IFNULL(SUM(r.real_refund_amount), 0) AS refund
|
|
260
|
+
FROM report_order_info o LEFT JOIN report_refund r ON o.order_id = r.order_id
|
|
261
|
+
GROUP BY o.canteen_id
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### 3.4 菜品级别退款
|
|
265
|
+
|
|
266
|
+
```sql
|
|
267
|
+
-- 净销量 = 数量 - 已退数量,净金额 = 总金额 - 退款
|
|
268
|
+
SELECT goods_dishes_name,
|
|
269
|
+
SUM(quantity - IFNULL(goods_refund_num, 0)) AS netQuantity,
|
|
270
|
+
SUM(total_amount - IFNULL(refund_amount, 0)) AS netAmount
|
|
271
|
+
FROM report_order_detail WHERE detail_state IN (1, 3) GROUP BY goods_dishes_name
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## 四、账户流水报表
|
|
277
|
+
|
|
278
|
+
### 4.1 report_account_flow(流水主表)
|
|
279
|
+
|
|
280
|
+
核心字段:`flowId`(主键), `custId`, `orgId`, `payTime`, `flowType`(AccTradeTypeEnum), `flowRealAmount`, `flowAmount`, `manageCost`, `accTotalBal`(可用余额), `accAllBal`(含冻结), `rechargeSource`, `payChannel/payType`, `status`(0未消费/1已消费)
|
|
281
|
+
|
|
282
|
+
附加字段:`rechargeOperate`(1单人/2批量/3导入/4赠送), `withdrawSource`(1小程序/2web/3openapi/4注销), `operateSource`(1手动清空/2批量/3定时/4注销)
|
|
283
|
+
|
|
284
|
+
### 4.2 report_account_flow_detail(流水钱包明细)
|
|
285
|
+
|
|
286
|
+
字段:`flowId`, `walletId`(1个人/2补贴/4红包), `amount`(转出取负值), `walletBal`, `flowType`, `frozenBalance`, `allWalletBal`
|
|
287
|
+
|
|
288
|
+
### 4.3 report_account_summary(用户账户日结表,核心)
|
|
289
|
+
|
|
290
|
+
联合主键:`statisticDate` + `custId`
|
|
291
|
+
|
|
292
|
+
**期末余额公式**:
|
|
293
|
+
```
|
|
294
|
+
endAmount = beginAmount
|
|
295
|
+
+ rechargeAmount - rechargeRevokeAmount
|
|
296
|
+
+ subsidyAmount - subsidyRevokeAmount
|
|
297
|
+
+ luckAmount + giftAmount
|
|
298
|
+
- consumeAmount - consumeRepairAmount
|
|
299
|
+
+ consumeRefundAmount ← 退款加回
|
|
300
|
+
- withdrawAmount - clearAmount - manageCostAmount
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
附加维度:充值渠道详分(微信/支付宝/现金/银行/第三方)、提现渠道详分、各钱包余额及冻结金额
|
|
304
|
+
|
|
305
|
+
### 4.4 AccountConsumeService 实现类
|
|
306
|
+
|
|
307
|
+
| ORDER | 类名 | 汇总表 |
|
|
308
|
+
|-------|-----|-------|
|
|
309
|
+
| 1 | ReportAccountFlowService | report_account_flow(基础) |
|
|
310
|
+
| 2 | ReportAccountFlowDetailService | report_account_flow_detail(基础) |
|
|
311
|
+
| 13 | ReportAccountSummaryService | report_account_summary(日结) |
|
|
312
|
+
| 14 | ReportAccountOperatorService | report_account_operator(操作员) |
|
|
313
|
+
| 15 | ReportAccountConsumeSummaryService | report_account_consume(消费-个人) |
|
|
314
|
+
| 16 | ReportAccountConsumeSumOrgService | 消费-组织 |
|
|
315
|
+
| 17 | ReportAccountConsumeSumTypeService | 消费-用户类别 |
|
|
316
|
+
| 18 | ReportAccountWalletConsumeService | report_account_wallet_consume(钱包) |
|
|
317
|
+
| 19 | ReportSumRechargeMerService | report_sum_recharge_mer(商户充值) |
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## 五、汇总表开发标准模式
|
|
322
|
+
|
|
323
|
+
### 5.1 接口与实现模板
|
|
324
|
+
|
|
325
|
+
```java
|
|
326
|
+
public interface ReportOrderConsumeService extends Ordered {
|
|
327
|
+
void consume(OrderChangePO payload, ReportOrderInfoDTO baseInfo);
|
|
328
|
+
void fix(ReportBaseParam param);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
@Service @Slf4j
|
|
332
|
+
public class ReportSumXxxService implements ReportOrderConsumeService {
|
|
333
|
+
@Override public int getOrder() { return 15; } // 10-29普通,30+菜品,50+分析
|
|
334
|
+
|
|
335
|
+
@Override public void consume(OrderChangePO payload, ReportOrderInfoDTO baseInfo) {
|
|
336
|
+
// 标准版:汇总表留空,由 fix() 统一处理
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
@Override public void fix(ReportBaseParam param) {
|
|
340
|
+
LocalDateTime start = param.getStartPayTime(), end = param.getEndPayTime();
|
|
341
|
+
// 1. 删除旧数据
|
|
342
|
+
mapper.delete(Wrappers.<ReportSumXxx>lambdaQuery()
|
|
343
|
+
.between(ReportSumXxx::getStatisticDate, start.toLocalDate(), end.toLocalDate()));
|
|
344
|
+
// 2. 从基础表聚合写入
|
|
345
|
+
mapper.initFix(start, end);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### 5.2 fix SQL 模板(MyBatis XML)
|
|
351
|
+
|
|
352
|
+
```xml
|
|
353
|
+
<insert id="initFix">
|
|
354
|
+
INSERT INTO report_sum_xxx (id, statistic_date, canteen_id, canteen_name,
|
|
355
|
+
order_count, consume_amount, refund_amount, net_amount)
|
|
356
|
+
SELECT #{id}, DATE(a.pay_time), a.canteen_id, a.canteen_name,
|
|
357
|
+
COUNT(*), SUM(a.real_amount),
|
|
358
|
+
SUM(IFNULL(a.refund_amount, 0)),
|
|
359
|
+
SUM(a.real_amount - IFNULL(a.refund_amount, 0))
|
|
360
|
+
FROM report_order_info a
|
|
361
|
+
WHERE a.pay_time BETWEEN #{startTime} AND #{endTime}
|
|
362
|
+
GROUP BY DATE(a.pay_time), a.canteen_id, a.canteen_name
|
|
363
|
+
</insert>
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### 5.3 查询接口标准模式
|
|
367
|
+
|
|
368
|
+
```java
|
|
369
|
+
public ReportBaseTotalVO<XxxVO> pageSummary(XxxParam param) {
|
|
370
|
+
MgrUserAuthPO authPO = MgrUserAuthApi.getUserAuthPO();
|
|
371
|
+
CompletableFuture<List<XxxVO>> listF = supplyAsync(() -> mapper.listSummary(param, authPO));
|
|
372
|
+
CompletableFuture<XxxVO> totalF = supplyAsync(() -> mapper.getSummaryTotal(param, authPO));
|
|
373
|
+
CompletableFuture.allOf(listF, totalF).join();
|
|
374
|
+
return new ReportBaseTotalVO<>(PageVO.of(listF.join(), param.getPage()), totalF.join());
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
**权限控制 SQL**:
|
|
379
|
+
```xml
|
|
380
|
+
<if test="'-1'.toString() != authPO.roleType.toString()">
|
|
381
|
+
AND EXISTS (SELECT null FROM mgr_role_org it1
|
|
382
|
+
WHERE a.org_id = it1.org_id AND it1.role_id = #{authPO.roleId})
|
|
383
|
+
</if>
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### 5.4 数据修复
|
|
387
|
+
|
|
388
|
+
```java
|
|
389
|
+
// ReportFixController - POST /summary/fix/order
|
|
390
|
+
// 限制: 日期范围不超过 31 天
|
|
391
|
+
// Redisson 分布式锁 (120 分钟)
|
|
392
|
+
// 按 ORDER 排序依次调用所有 Service.fix()
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## 六、汇总模型实体
|
|
398
|
+
|
|
399
|
+
### 6.1 report_sum_mealtime(分餐次收入汇总)
|
|
400
|
+
|
|
401
|
+
维度:`statisticDate`, `canteenId/stallId`, `orgId`, `ageType`, `mealtimeType`, `psnType`, `machineSn`, `sourceType`
|
|
402
|
+
金额:`custNum`, `consumeNum`, `realAmount`, `refundAmount`, `totalAmount`, `payableAmount`, `discountAmount`
|
|
403
|
+
|
|
404
|
+
### 6.2 report_sum_pay(按支付渠道收入汇总)
|
|
405
|
+
|
|
406
|
+
维度:`statisticDate`, `mealtimeType`, `canteenId/stallId`, `orgId`, `ageType`, `payChannel`, `payType`
|
|
407
|
+
金额:`payNum`, `realAmount`, `refundAmount`, `totalAmount`, `payableAmount`
|
|
408
|
+
|
|
409
|
+
### 6.3 report_sum_dishes(菜品/商品汇总表)
|
|
410
|
+
|
|
411
|
+
维度:`statisticDate`, `areaId`, `canteenId`, `stallId`, `reportOrderType`(101线下/103商超/12自助), `mealtimeType`, `cookId`, `deviceSn`, `goodsDishesId`, `salesMode`, `detailType`
|
|
412
|
+
金额:`quantity`, `realAmount`
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## 七、经营分析模块
|
|
417
|
+
|
|
418
|
+
### 7.1 分析类型总览
|
|
419
|
+
|
|
420
|
+
| 分析类型 | Service | 接口数 | 路由前缀 |
|
|
421
|
+
|---------|---------|-------|---------|
|
|
422
|
+
| 营业额 | ReportAnalysisTurnoverService | 6 | `/summary/analysis/turnover/` |
|
|
423
|
+
| 用户 | ReportAnalysisCustService (ORDER=50) | 8 | `/summary/analysis/cust/` |
|
|
424
|
+
| 菜品 | ReportAnalysisDishesSaleService (ORDER=51) | 10 | `/summary/analysis/dishes/` |
|
|
425
|
+
| 满意度 | ReportAnalysisEvaluateService | 2 | `/summary/analysis/evaluate/` |
|
|
426
|
+
| 充值 | ReportAnalysisTurnoverService | 4 | `/summary/analysis/recharge/` |
|
|
427
|
+
| 设备 | ReportAnalysisTurnoverService | 2 | `/summary/analysis/device/` |
|
|
428
|
+
|
|
429
|
+
### 7.2 用户活跃度分析
|
|
430
|
+
|
|
431
|
+
分段枚举:`AnalysisConsumeTimesEnum`(次数:1-10/10-20/.../≥50)、`AnalysisConsumeAmountEnum`(金额:<200/200-400/.../≥1000元)、`AnalysisConsumeSlienceEnum`(沉默时长)
|
|
432
|
+
|
|
433
|
+
```java
|
|
434
|
+
// ReportAnalysisActiveVO
|
|
435
|
+
activeNumber/activePercent // 活跃用户
|
|
436
|
+
keepNumber/keepPercent // 保留用户
|
|
437
|
+
lossNumber/lossPercent // 流失用户
|
|
438
|
+
newNumber/newPercent // 新增用户
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## 八、商户报表
|
|
444
|
+
|
|
445
|
+
**report_sum_pay_mer**:`tenantId`(商家ID), `statisticDate`, `payChannel`, `payType`, `custNum`, `payNum`, `realAmount`, `refundAmount`, `totalAmount`
|
|
446
|
+
|
|
447
|
+
**API**:`POST /report/merchant/summary/consume` (消费汇总) + `/recharge` (充值汇总)
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
## 九、公共模块
|
|
452
|
+
|
|
453
|
+
### 9.1 报表错误日志(report_error_log)
|
|
454
|
+
|
|
455
|
+
`reportErrorType`(1账户/2订单), `reportErrorState`(1已创建/2已处理)。异常修复定时任务 `@XxlJob("reportExceptionHandle")` 自动查询未处理记录并调用对应 FixService 修复。
|
|
456
|
+
|
|
457
|
+
### 9.2 金额范围设置(report_alloc_amount)
|
|
458
|
+
|
|
459
|
+
`POST /report/alloc/amount-scope/save` 保存金额统计分段范围(不允许重叠)。
|
|
460
|
+
|
|
461
|
+
### 9.3 核心枚举
|
|
462
|
+
|
|
463
|
+
| 枚举 | 说明 |
|
|
464
|
+
|------|------|
|
|
465
|
+
| `ReportClassifyEnum` | 报表分类:1组织/2用户类别/3食堂档口/4设备/5营业收入/6支付渠道/7餐次 |
|
|
466
|
+
| `ReportPayTypeEnum` | 支付方式:1微信/2支付宝/3系统账户/4-8银行/9现金/10收钱吧/20其他 |
|
|
467
|
+
| `ReportSumTypeEnum` | 汇总类型:1按时段/2按日期 |
|
|
468
|
+
| `ReportMsgStatusEnum` | 消费状态:0未消费/1已消费 |
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
## 十、公共参数类
|
|
473
|
+
|
|
474
|
+
```java
|
|
475
|
+
// ReportBaseParam(所有查询参数基类)
|
|
476
|
+
PageDTO page; LocalDate startDate/endDate; LocalDate startOrderDate/endOrderDate;
|
|
477
|
+
Integer sumType; Integer sumDimension; List<Integer> ageTypes; List<Integer> holidayTypeList;
|
|
478
|
+
List<String> exportCols; LocalDateTime startPayTime/endPayTime;
|
|
479
|
+
|
|
480
|
+
// ReportNotConsumeDTO(未消费数据)
|
|
481
|
+
String statisticDate; // 统计日期(支付日期)
|
|
482
|
+
String orderDate; // 就餐日期(菜品统计专用)
|
|
483
|
+
Long relationId;
|
|
484
|
+
|
|
485
|
+
// 支付信息编码: "支付方式-支付渠道-支付金额" 如 "1-1-1200;2-4-1200"
|
|
486
|
+
// 优惠信息编码: "变动类型,详情类型,金额" 如 "1,1,100;2,11,200"
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
## 十一、API 路由总览
|
|
492
|
+
|
|
493
|
+
| 模块 | 前缀 | 核心接口 |
|
|
494
|
+
|------|------|---------|
|
|
495
|
+
| 营业收入明细 | `/summary/basic/` | flow/page, cust/page, remote/detail/page, remote/summary/page |
|
|
496
|
+
| 订单汇总 | `/summary/order/` | organization/pay/type/classify/mealtime/dishes |
|
|
497
|
+
| 账户流水 | `/summary/account/` | flow/cust/psn/organization/operator/consume/recharge/wallet/data |
|
|
498
|
+
| 经营分析 | `/summary/analysis/` | turnover(6)/cust(8)/dishes(10)/recharge(4)/device(2)/evaluate(2) |
|
|
499
|
+
| 数据修复 | `/summary/fix/` | order, account (限31天) |
|
|
500
|
+
| 商户 | `/report/merchant/summary/` | consume, recharge |
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
## 十二、开发检查清单
|
|
505
|
+
|
|
506
|
+
### 建表
|
|
507
|
+
- [ ] 分组维度字段(statisticDate、canteenId、stallId 等)+ 金额汇总字段
|
|
508
|
+
- [ ] 审计字段(crby/crtime/upby/uptime/del_flag),无 tenant_id
|
|
509
|
+
|
|
510
|
+
### 实现
|
|
511
|
+
- [ ] 实现 `ReportOrderConsumeService`(或 Account 版本),设置 `getOrder()`
|
|
512
|
+
- [ ] `fix()` — 先删后插,从基础表聚合(**标准版核心模式**)
|
|
513
|
+
- [ ] `consume()` 可留空(汇总表由 fix 重算)
|
|
514
|
+
|
|
515
|
+
### 退款处理(标准版特有)
|
|
516
|
+
- [ ] 退款在独立 `report_refund` 表(**正数金额**)
|
|
517
|
+
- [ ] 净消费 = `real_amount - IFNULL(refund_amount, 0)`
|
|
518
|
+
- [ ] **不要使用 consumeType 字段**(标准版无此字段)
|
|
519
|
+
|
|
520
|
+
### 查询接口
|
|
521
|
+
- [ ] ReportBaseTotalVO + CompletableFuture 并行 + MgrUserAuthPO 权限
|
|
522
|
+
|
|
523
|
+
---
|
|
524
|
+
|
|
525
|
+
## 十三、关键代码位置
|
|
526
|
+
|
|
527
|
+
| 类型 | 路径 |
|
|
528
|
+
|------|------|
|
|
529
|
+
| MQ 监听器 | `config/mq/ReportOrderMQListener.java` / `ReportAccountMQListener.java` |
|
|
530
|
+
| 消费调度 | `config/mq/service/ReportConsumerService.java` |
|
|
531
|
+
| ConsumeService 接口 | `config/mq/ReportOrderConsumeService.java` |
|
|
532
|
+
| 线程池/定时任务 | `config/mq/threads/ThreadPoolConfig.java` / `config/mq/job/ReportMsgJob.java` |
|
|
533
|
+
| 订单基础表 | `order/basic/model/ReportOrderInfo.java` / `ReportRefund.java` / `ReportOrderDetail.java` |
|
|
534
|
+
| 营业收入 Service | `order/basic/service/ReportOrderInfoService.java` |
|
|
535
|
+
| Fix | `order/fix/controller/ReportFixController.java` / `service/ReportFixService.java` |
|
|
536
|
+
| 汇总 Service | `order/summary/service/ReportSumMealtimeService.java` / `ReportSumPayService.java` / `ReportSumDishesService.java` |
|
|
537
|
+
| 分析 Service | `order/analysis/service/ReportAnalysisTurnoverService.java` / `ReportAnalysisCustService.java` |
|
|
538
|
+
| 账户 | `account/service/ReportAccountFlowService.java` / `ReportAccountSummaryService.java` |
|
|
539
|
+
| 商户 | `merchant/service/ReportSumPayMerService.java` |
|
|
540
|
+
| 公共 | `common/model/ReportErrorLog.java` / `common/task/ReportTask.java` / `constants/ReportConstant.java` |
|
|
541
|
+
|
|
542
|
+
> 路径前缀均为 `core-report/.../statistics/`
|
|
543
|
+
|
|
544
|
+
---
|
|
545
|
+
|
|
546
|
+
## 注意
|
|
547
|
+
|
|
548
|
+
- 本指南适用于**标准版**(core-report),v5.29 版本请使用 `leniu-report-customization`
|
|
549
|
+
- 标准版退款为独立表(正数金额),**不要使用 consumeType 字段**
|
|
550
|
+
- 标准版第二阶段用 `fix()` 按日重算,**不要使用 batchConsume() 增量模式**
|
|
551
|
+
- CRUD 开发用 `leniu-crud-development`,MyBatis 用 `leniu-java-mybatis`,入参设计用 `leniu-java-report-query-param`,合计行用 `leniu-java-total-line`,餐次用 `leniu-mealtime`
|