leniu-report-standard-customization

详细字段说明见 references/table-fields.md ,经营分析详情见 references/analysis-module.md

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "leniu-report-standard-customization" with this command: npx skills add xu-cell/ai-engineering-init/xu-cell-ai-engineering-init-leniu-report-standard-customization

leniu 标准版定制报表开发指南

详细字段说明见 references/table-fields.md ,经营分析详情见 references/analysis-module.md

版本识别(必读)

本 skill 仅适用于标准版(core-report 独立模块)。

判断方式 标准版(本指南) v5.29 版本

目录结构 core-report/ 独立模块 sys-canteen/ 内嵌

退款存储 独立 report_refund 表(正数) 合并入 report_order_info (consumeType=2 ,负数)

第二阶段 fix() 按日重算 batchConsume() 增量累加

consumeType 无此字段 1=消费,2=退款

v5.29 报表请使用 leniu-report-customization 。钱包/交易类型枚举同 v5.29,参见该 skill。

一、报表系统架构

1.1 模块结构

core-report/.../statistics/ ├── config/mq/ # MQ 监听器 + 消费调度 + 线程池 ├── order/ # 订单报表(basic/summary/fix/analysis) ├── account/ # 账户流水报表 ├── merchant/ # 商户维度报表 ├── common/ # 错误日志/定时任务 └── param/vo/constants/ # 公共类

1.2 三大 MQ 监听器

监听器 Topic/Tag

ReportOrderMQListener

order / order-v3-placed

ReportOrderRefundMQListener

order / order-v3-refunded

ReportAccountMQListener

acc / acc-trade-report-queue

1.3 两阶段消费模型

第一阶段(ORDER < 10,同步写基础表) ├── ORDER=1 ReportOrderInfoService → report_order_info ├── ORDER=2 ReportOrderDiscountService → report_order_discount ├── ORDER=3 ReportOrderDetailService → report_order_detail ├── ORDER=4 ReportOrderPayService → report_order_pay ├── ORDER=5 ReportRefundService → report_refund ├── ORDER=6 ReportRefundDetailService → report_refund_detail └── ORDER=11 ReportOrderInfoSnapshotService → report_order_info_snapshot

第二阶段(ORDER >= 10,fix 按日重算汇总表,由 Redis 计数触发) ├── ORDER=13 ReportSumMealtimeService → 分餐次汇总 ├── ORDER=16 ReportSumPayService → 支付渠道汇总 ├── ORDER=17 ReportSumPayMerService → 商户支付汇总 ├── ORDER=18 ReportSumDishesService → 菜品销售汇总 ├── ORDER=50 ReportAnalysisCustService → 用户分析 └── ORDER=51 ReportAnalysisDishesSaleService→ 菜品销售分析

1.4 第二阶段核心逻辑(fix 重算模式)

// ReportConsumerService.consumeOrderReport() void consumeOrderReport() { for (TenantInfo tenant : allTenants) { Executors.doInTenant(tenant.getId(), () -> { RLock lock = RedisUtil.getLock(REPORT_ORDER_LOCK); lock.lock(120, TimeUnit.MINUTES); try { List<ReportNotConsumeDTO> list = reportOrderInfoService.queryNotConsumeData(); // 菜品:按 orderDate 分组调 fix // 其他:按 statisticDate 分组,依次调所有 ORDER>=10 的 fix() reportOrderInfoService.updateOrderMsg(list); // 标记已消费 } finally { lock.unlock(); } }); } }

触发机制:Redis 计数器每条消息递减,达阈值(默认100)触发 + XxlJob 定时兜底。

二、核心基础表概要

2.1 report_order_info(仅存正向订单,无 consumeType)

关键字段:orderId (主键), canteenId/stallId , mealtimeType , orderType , payableAmount/realAmount/refundAmount (分), accPayAmount/outPayAmount , payTime/orderDate , orderRefundState (1未退/2全退/3部分退), status (0未消费/1已消费), nuClearMode , psnType , ageType/holidayType

2.2 report_order_detail(菜品明细)

关键字段:detailId , orderId , goodsDishesId/goodsDishesName , price/totalAmount/realAmount (分), quantity , salesMode (1按份/2称重), detailState (1正常/2全退/3部分退), goodsRefundNum , refundAmount , detailType

2.3 report_refund / report_refund_detail(标准版特有,退款为正数)

report_refund:orderRefundId (主键), orderId (原订单), realRefundAmount (正数), applyType (1退单/2纠错), checkTime

report_refund_detail:orderRefundId , detailId , realQuantity , realRefundAmount (正数)

2.4 其他基础表

  • report_order_pay:orderId , payType/payChannel , payAmount/refundAmount

  • report_order_discount:orderId , changeAmount , changeType (1上浮/2优惠), changeDetailType

  • report_order_info_snapshot:订单交易快照

三、退款数据处理(核心重点)

3.1 存储模型

正向订单 → report_order_info(realAmount 为正) 退款记录 → report_refund(realRefundAmount 为正)+ report_refund_detail 同时更新 → report_order_info.orderRefundState + refundAmount

3.2 净消费金额计算(3种方式)

方式一:主表 refundAmount 减退(推荐)

SELECT SUM(real_amount - IFNULL(refund_amount, 0)) AS netAmount FROM report_order_info WHERE pay_time BETWEEN #{start} AND #{end}

方式二:排除全退

WHERE order_refund_state IN (1, 3)

方式三:关联 report_refund

SELECT o.canteen_id, SUM(o.real_amount) AS consume, IFNULL(SUM(r.real_refund_amount), 0) AS refund FROM report_order_info o LEFT JOIN report_refund r ON o.order_id = r.order_id GROUP BY o.canteen_id

3.3 菜品级别退款

SELECT goods_dishes_name, SUM(quantity - IFNULL(goods_refund_num, 0)) AS netQuantity, SUM(total_amount - IFNULL(refund_amount, 0)) AS netAmount FROM report_order_detail WHERE detail_state IN (1, 3) GROUP BY goods_dishes_name

四、账户流水报表

4.1 report_account_flow(流水主表)

核心字段:flowId , custId/orgId , payTime , flowType (AccTradeTypeEnum), flowRealAmount/flowAmount , manageCost , accTotalBal/accAllBal , status

4.2 report_account_summary(用户账户日结表)

联合主键:statisticDate

  • custId 。期末余额 = 期初 + 充值 - 撤销充值 + 补贴 - 撤销补贴 + 红包 + 赠送 - 消费 - 补扣 + 退款 - 提现 - 清空 - 管理费

4.3 AccountConsumeService 实现

ORDER 类 汇总表

1/2 Flow/FlowDetail 基础表

13 AccountSummary 日结

14 AccountOperator 操作员

15-17 ConsumeSummary/Org/Type 消费维度

18 WalletConsume 钱包

19 SumRechargeMer 商户充值

五、汇总表开发标准模式

5.1 接口与实现

@Service @Slf4j public class ReportSumXxxService implements ReportOrderConsumeService { @Override public int getOrder() { return 15; } // 10-29普通,30+菜品,50+分析

@Override public void consume(OrderChangePO payload, ReportOrderInfoDTO baseInfo) {
    // 标准版:留空,由 fix() 统一处理
}

@Override public void fix(ReportBaseParam param) {
    LocalDateTime start = param.getStartPayTime(), end = param.getEndPayTime();
    mapper.delete(Wrappers.&#x3C;ReportSumXxx>lambdaQuery()
        .between(ReportSumXxx::getStatisticDate, start.toLocalDate(), end.toLocalDate()));
    mapper.initFix(start, end);
}

}

5.2 fix SQL 模板

<insert id="initFix"> INSERT INTO report_sum_xxx (id, statistic_date, canteen_id, canteen_name, order_count, consume_amount, refund_amount, net_amount) SELECT #{id}, DATE(a.pay_time), a.canteen_id, a.canteen_name, COUNT(*), SUM(a.real_amount), SUM(IFNULL(a.refund_amount, 0)), SUM(a.real_amount - IFNULL(a.refund_amount, 0)) FROM report_order_info a WHERE a.pay_time BETWEEN #{startTime} AND #{endTime} GROUP BY DATE(a.pay_time), a.canteen_id, a.canteen_name </insert>

5.3 查询接口(并行 + 权限)

public ReportBaseTotalVO<XxxVO> pageSummary(XxxParam param) { MgrUserAuthPO authPO = MgrUserAuthApi.getUserAuthPO(); CompletableFuture<List<XxxVO>> listF = supplyAsync(() -> mapper.listSummary(param, authPO)); CompletableFuture<XxxVO> totalF = supplyAsync(() -> mapper.getSummaryTotal(param, authPO)); CompletableFuture.allOf(listF, totalF).join(); return new ReportBaseTotalVO<>(PageVO.of(listF.join(), param.getPage()), totalF.join()); }

权限 SQL:

<if test="'-1'.toString() != authPO.roleType.toString()"> AND EXISTS (SELECT null FROM mgr_role_org it1 WHERE a.org_id = it1.org_id AND it1.role_id = #{authPO.roleId}) </if>

六、汇总模型速查

表 维度 金额

report_sum_mealtime date/canteen/stall/org/age/mealtime/psn/machine/source custNum/consumeNum/realAmount/refundAmount

report_sum_pay date/mealtime/canteen/stall/org/age/payChannel/payType payNum/realAmount/refundAmount

report_sum_dishes date/area/canteen/stall/reportOrderType/mealtime/cook/device/dishes/salesMode/detailType quantity/realAmount

report_sum_pay_mer tenantId/date/payChannel/payType custNum/payNum/realAmount/refundAmount

七、经营分析模块

分析 Service 路由前缀

营业额 ReportAnalysisTurnoverService /summary/analysis/turnover/

用户 ReportAnalysisCustService (ORDER=50) /summary/analysis/cust/

菜品 ReportAnalysisDishesSaleService (ORDER=51) /summary/analysis/dishes/

满意度 ReportAnalysisEvaluateService /summary/analysis/evaluate/

充值 ReportAnalysisTurnoverService /summary/analysis/recharge/

设备 ReportAnalysisTurnoverService /summary/analysis/device/

八、公共模块

  • 报表错误日志(report_error_log):reportErrorType (1账户/2订单), reportErrorState (1已创建/2已处理)。定时任务 @XxlJob("reportExceptionHandle") 自动修复。

  • 金额范围设置:POST /report/alloc/amount-scope/save

  • 数据修复:POST /summary/fix/order|account (限31天,Redisson 锁 120 分钟)

核心枚举

枚举 值

ReportClassifyEnum 1组织/2类别/3食堂/4设备/5收入/6渠道/7餐次

ReportPayTypeEnum 1微信/2支付宝/3系统账户/9现金/20其他

九、MySQL only_full_group_by 规范(必须遵守)

MySQL 默认开启 sql_mode=ONLY_FULL_GROUP_BY ,SELECT 中所有非聚合列必须出现在 GROUP BY 中,且 GROUP BY 表达式必须与 SELECT 表达式完全一致。

核心规则

SELECT 的表达式 == GROUP BY 的表达式(字符级别完全一致)

❌ 错误示例(GROUP BY 与 SELECT 不一致)

<!-- 报错:Expression #1 of SELECT list is not in GROUP BY clause --> SELECT DATE_FORMAT(roi.consume_time, '%Y-%m-%d') AS statisticDate, SUM(roi.real_amount) AS totalAmount FROM report_order_info roi GROUP BY DATE(roi.consume_time) <!-- ❌ DATE() ≠ DATE_FORMAT(..., '%Y-%m-%d') --> ORDER BY DATE(roi.consume_time)

✅ 正确示例(GROUP BY 与 SELECT 完全一致)

SELECT DATE_FORMAT(roi.consume_time, '%Y-%m-%d') AS statisticDate, SUM(roi.real_amount) AS totalAmount FROM report_order_info roi GROUP BY DATE_FORMAT(roi.consume_time, '%Y-%m-%d') <!-- ✅ 与 SELECT 完全一致 --> ORDER BY DATE_FORMAT(roi.consume_time, '%Y-%m-%d') <!-- ✅ ORDER BY 也保持一致 -->

❌ 错误示例(SELECT 含非聚合列未加入 GROUP BY)

SELECT roi.canteen_id, roi.canteen_name, <!-- ❌ 非聚合列未在 GROUP BY 中 --> SUM(roi.real_amount) AS totalAmount FROM report_order_info roi GROUP BY roi.canteen_id

✅ 正确示例(所有非聚合列都在 GROUP BY 中)

SELECT roi.canteen_id, roi.canteen_name, SUM(roi.real_amount) AS totalAmount FROM report_order_info roi GROUP BY roi.canteen_id, roi.canteen_name <!-- ✅ 所有非聚合列都在 GROUP BY -->

检查清单

  • SELECT 中按日期分组时使用 DATE_FORMAT(col, '%Y-%m-%d') ,不要用 DATE()

  • GROUP BY 表达式与 SELECT 中对应列逐字相同(复制粘贴而非重写)

  • ORDER BY 中同样使用与 GROUP BY 一致的表达式

  • SELECT 中所有非聚合列(无 SUM/COUNT/AVG/MAX/MIN 包裹)都出现在 GROUP BY 中

十、开发检查清单

建表

  • 分组维度 + 金额汇总 + 审计字段(crby/crtime/upby/uptime/del_flag),无 tenant_id

实现

  • 实现 ReportOrderConsumeService ,设 getOrder()

  • fix() 先删后插(标准版核心模式),consume() 留空

退款(标准版特有)

  • 退款在独立 report_refund 表(正数金额)

  • 净消费 = real_amount - IFNULL(refund_amount, 0)

  • 不要使用 consumeType 字段

查询

  • ReportBaseTotalVO + CompletableFuture 并行 + MgrUserAuthPO 权限

  • GROUP BY / ORDER BY 表达式与 SELECT 完全一致(only_full_group_by)

十一、关键代码位置

路径前缀均为 core-report/.../statistics/

类型 路径

MQ 监听器 config/mq/ReportOrderMQListener.java / ReportAccountMQListener.java

消费调度 config/mq/service/ReportConsumerService.java

订单基础表 order/basic/model/ReportOrderInfo.java / ReportRefund.java

汇总 Service order/summary/service/ReportSumMealtimeService.java / ReportSumPayService.java

分析 Service order/analysis/service/ReportAnalysisTurnoverService.java

账户 Service account/service/ReportAccountSummaryService.java

Fix order/fix/controller/ReportFixController.java

注意

  • 标准版退款为独立表(正数金额),不要使用 consumeType 字段

  • 标准版第二阶段用 fix() 按日重算,不要使用 batchConsume() 增量模式

  • CRUD 用 leniu-crud-development ,MyBatis 用 leniu-java-mybatis ,入参用 leniu-java-report-query-param ,合计行用 leniu-java-total-line ,餐次用 leniu-mealtime

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

loki-log-query

No summary provided by upstream source.

Repository SourceNeeds Review
General

brainstorm

No summary provided by upstream source.

Repository SourceNeeds Review
General

openspec-ff-change

No summary provided by upstream source.

Repository SourceNeeds Review
General

utils-toolkit

No summary provided by upstream source.

Repository SourceNeeds Review