# SKILL.md - vala-order-amortization-stat 订单均摊结算统计技能 ## 技能描述 用于统计指定账期内的订单均摊收入、退费冲销,按天计算均摊金额,支持部分退费场景的退后订单金额和周期自动计算。 ## 触发场景 当用户提到以下关键词组合时激活本技能: 1. 订单均摊、按天均摊、收入均摊 2. 账期结算、月度结算、季度结算 3. 退费冲销、部分退款均摊 ## 前置依赖 1. 已连接线上PostgreSQL数据库 vala_bi 库 2. 依赖表: - bi_vala_order:订单主表 - bi_refund_order:退费订单表 - bi_vala_seasonal_ticket:季卡周期表 - bi_vala_app_account:用户账户表(用于关联,不限制status) 3. 表关联规则: - bi_vala_order.out_trade_no ↔ bi_refund_order.out_trade_no 关联 - bi_vala_order.trade_no ↔ bi_refund_order.trade_no 关联 ## 执行方式 本技能已预置为可直接执行的脚本。 ### 快速执行 ```bash python3 ~/.openclaw/workspace/skills/vala-order-amortization-stat/run.py --start {账期起始日} --end {账期结束日} ``` ### 示例 ```bash # 2026年3月账期 python3 ~/.openclaw/workspace/skills/vala-order-amortization-stat/run.py --start 2026-03-01 --end 2026-03-31 # 也支持位置参数 python3 ~/.openclaw/workspace/skills/vala-order-amortization-stat/run.py 2026-03-01 2026-03-31 ``` ### 输出 1. Excel报表保存到:`output/订单均摊结算报表_{start}_{end}.xlsx`(三个Sheet:汇总表、订单明细、本月预收账款) 2. 控制台输出JSON格式的汇总结果 ### 目录结构 ``` vala-order-amortization-stat/ ├── SKILL.md # 技能说明(本文件) ├── run.py # 执行脚本(传入账期参数即可) └── sql/ ├── _common.sql # 公共CTE链(detail/summary 共用),含 order_base → order_with_cycle → order_with_cycle_fixed → order_classified → order_with_days ├── detail.sql # 订单明细输出(SELECT from order_with_days) ├── summary.sql # 汇总输出(聚合 SELECT from order_with_days) └── prepaid.sql # 月度预收账款(独立查询) ``` ## 操作流程 ### 步骤1:确认核心参数 执行前向用户确认: - 账期起始日期(格式:YYYY-MM-DD) - 账期结束日期(格式:YYYY-MM-DD) ### 步骤2:数据过滤规则 1. 订单范围: - 2025-06-01 至 账期结束日 内创建的所有订单 - bi_vala_order.order_status IN (3,4)(已完成、已退款订单) - 订单实际支付金额≥10元:bi_vala_order.pay_amount_int ≥ 1000(单位:分) - 关联 bi_vala_app_account 表(不限制 status,不剔除测试账号) 2. 退费范围: - 退费记录范围:截至账期结束日前的所有退费成功记录,用于标记订单退费状态 - 账期内退费判定:bi_refund_order.updated_at 在账期起止范围内,status = 3 3. 账期前退费订单处理规则: - 全额退费(is_full_refund = 1,累计退费金额 ≥ 原订单金额):本账期完全不统计该订单 - 部分退费(is_full_refund = 0):按退后订单金额/退后周期在本账期内正常均摊 4. 试用期内退费处理规则: - 退费日期 < 转正日(下单日+7天)的退费订单,从未产生均摊收入,不触发冲销 ### 步骤3:核心计算逻辑 #### 3.1 周期计算 - 原始均摊周期 = bi_vala_seasonal_ticket 中同一 out_trade_no 下所有不同 id 数量 × 90 天 - 退后均摊周期 = bi_vala_seasonal_ticket 中同一 out_trade_no 下 status != -1 的不同 id 数量 × 90 天 - 转正日期 = 订单下单日 + 7 天(下单日取 bi_vala_order.pay_success_date 的日期部分) - 示例:4月22日下单,4月29日00:00:00为转正日 #### 3.1.1 退费在账期后 + 季卡已删的fallback(2026-05-15 修复) 当退费发生在账期结束后,季卡状态已经被置为 `status=-1`,导致 `active_cycle_days=0`,但账期内该订单仍处于正常均摊状态,不应被排除。 - 判定条件:`active_cycle_days=0 AND original_cycle_days>0 AND has_refund=0`(退费记录被 `DATE(updated_at) <= period_end` 过滤掉) - 处理:`total_cycle_days` 回退到 `original_cycle_days`,后续计算(均摊结束日、日均摊金额、日税费)均在 `order_with_cycle_fixed` CTE 中用 effective `total_cycle_days` 重算 - 避免此问题的正确做法:不应依赖季卡状态判断订单是否在本账期内正常,退费过滤的时效性需要与订单状态独立判断 #### 3.2 税率与税费计算(价外税) - 税率判定依据:按下单时间(pay_success_date)判定,与退费发生时间无关 - 下单时间 < 2026-05-01 → 1% - 下单时间 ≥ 2026-05-01 → 6% - 示例:4月下单的订单即使5月发生退费,仍按1%税率计算退后金额和税费 - 计税时机:订单在下单日即计税,不等待转正日(下单日+7天) - 计税方式:价外税,订单金额为含税价 - 税后金额(元)= (pay_amount_int / 100) / (1 + tax_rate) - 税费金额(元)= tax_amount = 税后金额 × tax_rate #### 3.3 均摊规则 - 所有均摊计算均基于税后金额进行 - 日均摊金额(税后)= 税后金额 / 总均摊周期 - 🔹 周期最后一天补差规则:订单均摊周期的最后一天,均摊金额 = 税后总金额 - 前(N-1)天累计已均摊金额,避免浮点尾差 #### 3.4 退费场景分类(6类) | 场景 | 描述 | 处理方式 | |------|------|---------| | A | 账期内下单 + 部分退费 | 按退后金额从转正日均摊(period_amort_days) | | B | 历史下单 + 账期内部分退费 | 冲销历史均摊 + 按退后金额重新均摊(refunded_amort_days_to_period_end) | | C | 账期前部分退费 | 按退后金额正常均摊(period_amort_days),无冲销 | | D | 账期内下单 + 全额退费 | 不产生均摊,不触发冲销 | | E | 历史下单 + 账期内全额退费 | 冲销全部历史均摊,无退后均摊 | | F | 账期前全额退费 | 本账期完全排除 | ## 输出格式 1. Excel报表存放于 `output/` 目录,命名格式:`订单均摊结算报表_{start}_{end}.xlsx` 2. 报表包含以下Sheet: ### 汇总表(Sheet1) | 列 | 说明 | |----|------| | 订单数 | 账期内下单的订单总数 | | 正式订单数 | 账期内下单且已过7天试用期的订单数 | | 试用订单数 | 账期内下单但仍处于试用期的订单数 | | 冲销历史累计摊销金额 | 场景B/E冲销的历史均摊金额总和(负数) | | 退后订单历史累计摊销金额 | 仅计算账期内发生退费的订单的历史有效摊销金额总和 | | 冲销原税款 | 场景B/E冲销的税费总和(负数) | | 冲销未确认收入 | 场景B/E冲销的未确认收入总和(负数) | | 当期摊销金额 | 本账期内所有订单产生的均摊收入总和(核心指标) | | 账期税额 | 账期内下单的订单税费总和(下单即计税,不等待转正) | | 部分退退后税费 | 三类部分退费订单(试用期内/历史下单账期内/账期内下单)的当前税额总和 | | 未确认收入 | 截至账期最后一天尚未均摊的税后金额总和 | ### 订单明细(Sheet2) 每笔订单一行,包含:订单号、下单日期、退费日期、订单分类、原订单金额、退款金额、退后金额、税率、原订单税额、当前税后金额、当前税额、部分退退后税费、原始均摊周期、退后均摊周期、历史累计均摊金额、冲销历史累计摊销金额、退后订单历史累计摊销金额、冲销原税款、冲销未确认收入、当期摊销金额、账期税额、未确认收入、剩余周期 > 部分退退后税费:仅对三类部分退费订单有值(试用期内部分退/历史下单账期内部分退/账期内下单部分退),值为退后订单的当前税额;其余订单为0 ### 本月预收账款(Sheet3) 按"上月订单转正"/"本月订单转正"/"本月订单未转正"三类统计新增和退费含税金额。 3. 文字回复核心指标: > 📊 账期{start}至{end}均摊结算结果: > 总订单数:XXX单 | 正式订单数:XXX单 | 试用订单数:XXX单 > 当期摊销金额(税后净收入):XXX元 | 部分退退后税费:XXX元 > 账期税额:XXX元 | 冲销历史累计摊销金额:XXX元 > 未确认收入:XXX元 ## 注意事项 1. 所有金额保留2位小数,百分比保留1位小数 2. 部分退费场景:需确保 bi_vala_seasonal_ticket 中对应退费部分的 status 已更新为 -1 3. 税后金额计算使用价外税公式:含税价 / (1 + 税率) 4. SQL 模板统一使用 `{period_start}` 和 `{period_end}` 占位符,由 run.py 替换 5. 公共 CTE 链位于 `sql/_common.sql`,detail/summary 共享,修改业务逻辑只需改一处