🤖 每日自动备份 - 2026-04-25 08:00:01
This commit is contained in:
parent
96539da13f
commit
ada8a8294f
@ -12,4 +12,4 @@ vala-component-practice-stat 8e768e2641019d27bd41f4647d2d90f24182a0554dad5ad9f41
|
||||
cron-schedule e103cbb1806b28c891b9c856963325086ecaff32edec208f0a841865f26e8f3e
|
||||
refund-user-learning-analysis 648fd4ae2b29167fd66eab4245bdaaef00242db3131f4919cc02f07ca2a9b59c
|
||||
phone-chapter-query ac429b4da5a89db16efdf1066edf4ecb1c050b93aff20dd4c652af5f5568e44f
|
||||
vala-order-amortization-stat 0f55a0c8d2d8bde498ac9781daa6f18cd4e4618d87f42263fe70e991a9980bea
|
||||
vala-order-amortization-stat 4f1facb78e3adb16af09cfab1578d3273bcaad1b4c1b409b9de2a97d0c63409b
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# SKILL.md - vala-order-amortization-stat 订单均摊结算统计技能
|
||||
## 技能描述
|
||||
用于统计指定账期内的订单均摊收入、退费冲销,按天计算均摊金额,支持部分退费场景的剩余金额和周期自动计算。
|
||||
用于统计指定账期内的订单均摊收入、退费冲销,按天计算均摊金额,支持部分退费场景的退后订单金额和周期自动计算。
|
||||
## 触发场景
|
||||
当用户提到以下关键词组合时激活本技能:
|
||||
1. 订单均摊、按天均摊、收入均摊
|
||||
@ -66,7 +66,7 @@ vala-order-amortization-stat/
|
||||
3. 账期前退费订单处理规则:
|
||||
- 退费完成时间在账期起始日之前的订单,不会纳入本账期的冲销逻辑:
|
||||
- 全额退费订单:冲销动作已在退费发生的对应账期执行完毕,本账期完全不统计该订单的任何数据
|
||||
- 部分退费订单:冲销动作、剩余金额/剩余周期调整已在退费发生的对应账期完成,本账期仅按调整后的剩余金额计算均摊,不产生额外冲销金额
|
||||
- 部分退费订单:冲销动作、退后订单金额/剩余周期调整已在退费发生的对应账期完成,本账期仅按调整后的退后订单金额计算均摊,不产生额外冲销金额
|
||||
### 步骤3:核心计算逻辑
|
||||
#### 3.1 周期计算
|
||||
- 每个订单的总均摊周期 = bi_vala_seasonal_ticket中同一order_no下status != -1的不同id数量 × 90天
|
||||
@ -76,13 +76,14 @@ vala-order-amortization-stat/
|
||||
- 税率规则:
|
||||
- 订单下单时间在2026年5月1日之前:税率1%
|
||||
- 订单下单时间在2026年5月1日及之后:税率6%
|
||||
- 订单税后金额 = (bi_vala_order.pay_amount_int / 100) × (1 - 税率)(单位:元)
|
||||
- 订单税费金额 = (bi_vala_order.pay_amount_int / 100) × 税率(单位:元)
|
||||
- 订单税后金额 = (bi_vala_order.pay_amount_int / 100) / (1 + 税率)(单位:元)
|
||||
- 订单税费金额 = (bi_vala_order.pay_amount_int / 100) / (1 + 税率) × 税率(单位:元)
|
||||
- **计税方式**:价外税,即订单金额为含税价,需先剥离税额再计算税后金额
|
||||
- **均摊规则更新**:所有均摊计算均基于税后金额进行,含税金额和税费单独统计
|
||||
- 日均摊金额(税后)= 订单税后金额 / 总均摊周期
|
||||
- 🔹 周期最后一天补差规则:订单均摊周期的最后一天,均摊金额不按日均摊计算,采用补差方式确保总额完全匹配:
|
||||
- 正常订单:最后一天均摊金额 = 订单税后总金额 - 前(总均摊周期-1)天累计已均摊金额
|
||||
- 部分退费订单:最后一天均摊金额 = 订单剩余税后金额 - 剩余均摊周期前(剩余天数-1)天累计已均摊金额
|
||||
- 部分退费订单:最后一天均摊金额 = 退后订单税后金额 - 剩余均摊周期前(剩余天数-1)天累计已均摊金额
|
||||
避免浮点精度导致的金额尾差
|
||||
#### 3.2 退费场景计算
|
||||
所有退费冲销金额均为税后金额,税费同步对应冲销
|
||||
@ -91,7 +92,7 @@ vala-order-amortization-stat/
|
||||
- 历史退费订单冲销税费金额:上述历史均摊金额对应的税费(统一显示为负数,用于冲销)
|
||||
2. **全额退费(bi_refund_order.refund_type = 2)**:无需额外计算补充均摊,仅执行上述通用冲销逻辑
|
||||
3. **部分退费(bi_refund_order.refund_type = 3)**:在通用冲销逻辑基础上,额外计算:
|
||||
- 历史部分退费订单补充均摊金额:部分退费后剩余的待均摊税后金额,在本账期内产生的均摊收入
|
||||
- 历史部分退费订单补充均摊金额:部分退费后的退后订单待均摊税后金额,在本账期内产生的均摊收入
|
||||
- 历史部分退费订单补充税费金额:上述补充均摊金额对应的税费
|
||||
#### 3.3 账期内收入计算
|
||||
账期内总收入 = 账期内所有正常订单的日均摊金额总和 + 账期内所有退费冲销金额总和
|
||||
@ -249,7 +250,7 @@ order_final_amort AS (
|
||||
THEN 1 ELSE 0
|
||||
END AS is_pre_period_full_refund,
|
||||
|
||||
-- 判断是否为账期前部分退费(本账期按剩余金额均摊)
|
||||
-- 判断是否为账期前部分退费(本账期按退后订单金额均摊)
|
||||
CASE WHEN opa.has_refund = 1 AND opa.is_full_refund = 0
|
||||
AND opa.latest_refund_date < '${账期起始日}'::date
|
||||
THEN 1 ELSE 0
|
||||
@ -262,17 +263,17 @@ order_final_amort AS (
|
||||
THEN 1 ELSE 0
|
||||
END AS is_current_period_refund,
|
||||
|
||||
-- 部分退费后的剩余税后金额
|
||||
-- 部分退费后的退后订单税后金额
|
||||
CASE WHEN opa.has_refund = 1 AND opa.is_full_refund = 0
|
||||
THEN (opa.pay_amount - opa.total_refund_amount) * (1 - opa.tax_rate)
|
||||
ELSE opa.after_tax_amount
|
||||
END AS remaining_after_tax_amount,
|
||||
END AS refunded_after_tax_amount,
|
||||
|
||||
-- 部分退费后的剩余税费
|
||||
-- 部分退费后的退后订单税费
|
||||
CASE WHEN opa.has_refund = 1 AND opa.is_full_refund = 0
|
||||
THEN (opa.pay_amount - opa.total_refund_amount) * opa.tax_rate
|
||||
ELSE opa.tax_amount
|
||||
END AS remaining_tax_amount
|
||||
END AS refunded_tax_amount
|
||||
|
||||
FROM order_period_amort opa
|
||||
),
|
||||
@ -299,9 +300,9 @@ summary_calc AS (
|
||||
ROUND(SUM(
|
||||
CASE
|
||||
WHEN is_pre_period_full_refund = 1 THEN 0 -- 账期前全额退费,不统计
|
||||
WHEN is_pre_period_partial_refund = 1 THEN -- 账期前部分退费,按剩余金额均摊
|
||||
WHEN is_pre_period_partial_refund = 1 THEN -- 账期前部分退费,按退后订单金额均摊
|
||||
CASE WHEN total_cycle_days > 0 AND period_amort_days > 0
|
||||
THEN remaining_after_tax_amount / total_cycle_days * period_amort_days
|
||||
THEN refunded_after_tax_amount / total_cycle_days * period_amort_days
|
||||
ELSE 0
|
||||
END
|
||||
WHEN is_current_period_refund = 0 AND period_amort_days > 0 THEN -- 正常未退费订单
|
||||
@ -322,7 +323,7 @@ summary_calc AS (
|
||||
WHEN is_pre_period_full_refund = 1 THEN 0
|
||||
WHEN is_pre_period_partial_refund = 1 THEN
|
||||
CASE WHEN total_cycle_days > 0 AND period_amort_days > 0
|
||||
THEN remaining_tax_amount / total_cycle_days * period_amort_days
|
||||
THEN refunded_tax_amount / total_cycle_days * period_amort_days
|
||||
ELSE 0
|
||||
END
|
||||
WHEN is_current_period_refund = 0 AND period_amort_days > 0 THEN
|
||||
@ -347,7 +348,7 @@ summary_calc AS (
|
||||
END
|
||||
)::numeric, 2) AS writeoff_tax,
|
||||
|
||||
-- ===== 补充均摊金额(税后):账期内部分退费订单,退费后剩余金额的均摊 =====
|
||||
-- ===== 补充均摊金额(税后):账期内部分退费订单,退后订单金额的均摊 =====
|
||||
ROUND(SUM(
|
||||
CASE WHEN is_current_period_refund = 1
|
||||
AND is_full_refund = 0
|
||||
@ -405,7 +406,7 @@ FROM summary_calc;
|
||||
3. **试用订单数**:账期内新增的订单中,截止账期结束日仍处于7天试用期内(下单日+7天 > 账期结束日)的订单数量,试用订单未开始均摊,不参与金额计算
|
||||
4. **冲销前税费**:账期内所有正式订单的含税订单总金额 × 各订单对应税率 的总和
|
||||
5. **冲销税费**:本账期内发生退费的所有订单的含税订单总金额 × 各订单对应税率 的总和(正数展示,计算时扣除)
|
||||
6. **补充税费**:本账期内发生部分退费的订单,退费后剩余的含税订单金额 × 各订单对应税率 的总和,其中:部分退费订单剩余含税金额 = 原订单含税金额 - 退费含税金额
|
||||
6. **补充税费**:本账期内发生部分退费的订单,退后订单含税金额 × 各订单对应税率 的总和,其中:部分退费订单退后含税金额 = 原订单含税金额 - 退费含税金额
|
||||
7. **冲销后税费**:账期内最终确认的总税费,计算公式:`冲销后税费 = 冲销前税费 - 冲销税费 + 补充税费`
|
||||
8. **冲销前均摊金额(税后)**:历史未退费订单 + 账期内正式订单 在本账期内产生的税后均摊收入总和
|
||||
9. **冲销均摊金额(税后)**:本账期内发生退费的所有订单,需要冲销的历史均摊金额总和(正数展示,计算时扣除)
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
WITH
|
||||
-- 步骤0:获取所有历史退费记录(无时间范围,用于标记订单是否为退费订单,不受当前账期限制)
|
||||
-- 步骤0:获取所有历史退费记录
|
||||
all_refund_records AS (
|
||||
SELECT
|
||||
out_trade_no AS order_no,
|
||||
SUM(refund_amount_int) / 100 AS total_refund_amount, -- 累计退费总金额(支持多笔部分退费叠加)
|
||||
MAX(CASE WHEN refund_type = 2 THEN 1 ELSE 0 END) AS is_full_refund, -- 是否全额退费(只要有一笔全额退费即标记为1)
|
||||
SUM(refund_amount_int) / 100 AS total_refund_amount,
|
||||
MAX(CASE WHEN refund_type = 2 THEN 1 ELSE 0 END) AS is_full_refund,
|
||||
MAX(refund_type) AS refund_type,
|
||||
MAX(DATE(updated_at)) AS latest_refund_date -- 最后一次退费完成时间
|
||||
MAX(DATE(updated_at)) AS latest_refund_date
|
||||
FROM bi_refund_order
|
||||
WHERE status = 3
|
||||
GROUP BY out_trade_no
|
||||
@ -15,34 +15,33 @@ all_refund_records AS (
|
||||
order_base AS (
|
||||
SELECT
|
||||
o.id AS order_id,
|
||||
o.out_trade_no AS order_no, -- 修正:bi_vala_order无order_no字段,使用out_trade_no作为订单号
|
||||
o.trade_no, -- 新增:关联退费订单需要trade_no字段
|
||||
o.out_trade_no AS order_no,
|
||||
o.trade_no,
|
||||
DATE(o.created_at) AS order_date,
|
||||
o.pay_amount_int / 100 AS pay_amount,
|
||||
-- 计算税率、税费、税后金额
|
||||
CASE WHEN DATE(o.created_at) < '2026-05-01' THEN 0.01 ELSE 0.06 END AS tax_rate,
|
||||
(o.pay_amount_int / 100) * CASE WHEN DATE(o.created_at) < '2026-05-01' THEN 0.01 ELSE 0.06 END AS tax_amount,
|
||||
(o.pay_amount_int / 100) * (1 - CASE WHEN DATE(o.created_at) < '2026-05-01' THEN 0.01 ELSE 0.06 END) AS after_tax_amount,
|
||||
(o.pay_amount_int / 100.0) / (1 + CASE WHEN DATE(o.created_at) < '2026-05-01' THEN 0.01 ELSE 0.06 END) * CASE WHEN DATE(o.created_at) < '2026-05-01' THEN 0.01 ELSE 0.06 END AS tax_amount,
|
||||
(o.pay_amount_int / 100.0) / (1 + CASE WHEN DATE(o.created_at) < '2026-05-01' THEN 0.01 ELSE 0.06 END) AS after_tax_amount,
|
||||
DATE(o.created_at) + INTERVAL '7 days' AS amortization_start_date,
|
||||
o.order_status, -- 修正:字段名是order_status不是status
|
||||
o.order_status,
|
||||
a.id AS account_id,
|
||||
o.key_from,
|
||||
o.sale_channel,
|
||||
-- 新增:订单退费标记字段(所有历史退费均可识别,不受当前账期限制)
|
||||
CASE WHEN ar.order_no IS NOT NULL THEN 1 ELSE 0 END AS has_refund, -- 是否有退费记录
|
||||
COALESCE(ar.total_refund_amount, 0) AS total_refund_amount, -- 累计退费金额
|
||||
COALESCE(ar.is_full_refund, 0) AS is_full_refund, -- 是否全额退费
|
||||
CASE WHEN ar.order_no IS NOT NULL THEN 1 ELSE 0 END AS has_refund,
|
||||
COALESCE(ar.total_refund_amount, 0) AS total_refund_amount,
|
||||
COALESCE(ar.is_full_refund, 0) AS is_full_refund,
|
||||
ar.refund_type,
|
||||
ar.latest_refund_date -- 退费完成日期(解决历史退费订单退费日期为空的问题)
|
||||
ar.latest_refund_date
|
||||
FROM bi_vala_order o
|
||||
JOIN bi_vala_app_account a ON o.account_id = a.id
|
||||
LEFT JOIN all_refund_records ar ON o.out_trade_no = ar.order_no -- 关联全量退费记录,不限制时间
|
||||
LEFT JOIN all_refund_records ar ON o.out_trade_no = ar.order_no
|
||||
WHERE
|
||||
o.created_at >= '2025-09-01'
|
||||
AND o.order_status IN (3,4) -- 修正:字段名是order_status不是status
|
||||
AND o.order_status IN (3,4)
|
||||
AND o.pay_amount_int >= 1000
|
||||
AND a.status = 1
|
||||
),
|
||||
-- 步骤2:计算每个订单的总均摊周期
|
||||
-- 步骤2:计算每个订单的当前均摊周期(退费后)和原始均摊周期(退费前)
|
||||
order_cycle AS (
|
||||
SELECT
|
||||
out_trade_no AS order_no,
|
||||
@ -51,166 +50,253 @@ order_cycle AS (
|
||||
WHERE status != -1
|
||||
GROUP BY out_trade_no
|
||||
),
|
||||
-- 步骤3:获取账期内的退费记录(仅用于计算当前账期的冲销金额,不影响订单退费状态标记)
|
||||
refund_records AS (
|
||||
order_cycle_original AS (
|
||||
SELECT
|
||||
r.out_trade_no AS order_no,
|
||||
r.refund_amount_int / 100 AS refund_amount, -- 修正:使用分为单位的refund_amount_int,避免字符串转换问题,除以100得到元
|
||||
r.refund_type,
|
||||
DATE(r.updated_at) AS refund_date -- 退费日期使用updated_at(status=3时即为退费完成时间)
|
||||
FROM bi_refund_order r
|
||||
JOIN order_base o ON r.out_trade_no = o.order_no OR r.trade_no = o.trade_no -- 修正:支持out_trade_no/trade_no双字段匹配退费订单
|
||||
WHERE
|
||||
r.status = 3
|
||||
AND r.updated_at BETWEEN '{period_start}' AND '{period_end}'
|
||||
)
|
||||
,
|
||||
-- 步骤4:合并订单基础信息与均摊周期
|
||||
out_trade_no AS order_no,
|
||||
COUNT(DISTINCT id) * 90 AS original_cycle_days
|
||||
FROM bi_vala_seasonal_ticket
|
||||
GROUP BY out_trade_no
|
||||
),
|
||||
-- 步骤3:合并订单基础信息与均摊周期
|
||||
order_with_cycle AS (
|
||||
SELECT
|
||||
ob.*,
|
||||
COALESCE(oc.total_cycle_days, 0) AS total_cycle_days,
|
||||
-- 均摊结束日 = 转正日 + 总周期天数 - 1
|
||||
COALESCE(oco.original_cycle_days, 0) AS original_cycle_days,
|
||||
ob.amortization_start_date + COALESCE(oc.total_cycle_days, 0) * INTERVAL '1 day' - INTERVAL '1 day' AS amortization_end_date,
|
||||
-- 日均摊金额(税后)
|
||||
CASE WHEN COALESCE(oc.total_cycle_days, 0) > 0
|
||||
-- 原始均摊结束日(退费前)
|
||||
ob.amortization_start_date + COALESCE(oco.original_cycle_days, 0) * INTERVAL '1 day' - INTERVAL '1 day' AS original_amortization_end_date,
|
||||
-- 原始日均摊金额(基于原订单税后金额和原始周期)
|
||||
CASE WHEN COALESCE(oco.original_cycle_days, 0) > 0
|
||||
THEN ob.after_tax_amount / oco.original_cycle_days
|
||||
ELSE 0
|
||||
END AS original_daily_amort_amount,
|
||||
-- 原始日税费均摊
|
||||
CASE WHEN COALESCE(oco.original_cycle_days, 0) > 0
|
||||
THEN ob.tax_amount / oco.original_cycle_days
|
||||
ELSE 0
|
||||
END AS original_daily_tax_amount,
|
||||
-- 退后日均摊金额(基于退后订单税后金额和退后周期)
|
||||
CASE WHEN COALESCE(oc.total_cycle_days, 0) > 0 AND ob.has_refund = 1 AND ob.is_full_refund = 0
|
||||
THEN (ob.pay_amount - ob.total_refund_amount) / (1 + ob.tax_rate) / oc.total_cycle_days
|
||||
WHEN COALESCE(oc.total_cycle_days, 0) > 0
|
||||
THEN ob.after_tax_amount / oc.total_cycle_days
|
||||
ELSE 0
|
||||
END AS daily_amort_amount,
|
||||
-- 日税费均摊
|
||||
CASE WHEN COALESCE(oc.total_cycle_days, 0) > 0
|
||||
-- 退后日税费均摊
|
||||
CASE WHEN COALESCE(oc.total_cycle_days, 0) > 0 AND ob.has_refund = 1 AND ob.is_full_refund = 0
|
||||
THEN (ob.pay_amount - ob.total_refund_amount) / (1 + ob.tax_rate) * ob.tax_rate / oc.total_cycle_days
|
||||
WHEN COALESCE(oc.total_cycle_days, 0) > 0
|
||||
THEN ob.tax_amount / oc.total_cycle_days
|
||||
ELSE 0
|
||||
END AS daily_tax_amount
|
||||
FROM order_base ob
|
||||
LEFT JOIN order_cycle oc ON ob.order_no = oc.order_no
|
||||
LEFT JOIN order_cycle_original oco ON ob.order_no = oco.order_no
|
||||
),
|
||||
|
||||
-- 步骤5:判断订单在账期内的状态分类,并计算各类均摊金额
|
||||
order_amortization AS (
|
||||
-- 步骤4:判断订单场景分类
|
||||
order_classified AS (
|
||||
SELECT
|
||||
owc.*,
|
||||
-- 是否为账期内新增订单
|
||||
CASE WHEN DATE(owc.amortization_start_date) <= '{period_end}'
|
||||
AND owc.amortization_start_date >= '{period_start}'::date - INTERVAL '6 days'
|
||||
THEN 1 ELSE 0 END AS is_new_in_period,
|
||||
-- 账期内新增且已转正
|
||||
CASE WHEN DATE(owc.amortization_start_date) >= '{period_start}'
|
||||
AND DATE(owc.amortization_start_date) <= '{period_end}'
|
||||
THEN 1
|
||||
WHEN owc.amortization_start_date < '{period_start}'
|
||||
THEN 1
|
||||
ELSE 0
|
||||
END AS is_formal,
|
||||
|
||||
-- ===== 正常均摊金额计算(未退费 或 账期前部分退费的订单)=====
|
||||
-- 均摊有效起始日(取转正日和账期起始日的较大值)
|
||||
-- 均摊有效起始日
|
||||
GREATEST(owc.amortization_start_date, '{period_start}'::date) AS eff_start,
|
||||
-- 均摊有效结束日(取均摊结束日和账期结束日的较小值)
|
||||
LEAST(owc.amortization_end_date, '{period_end}'::date) AS eff_end
|
||||
-- 均摊有效结束日
|
||||
LEAST(owc.amortization_end_date, '{period_end}'::date) AS eff_end,
|
||||
|
||||
FROM order_with_cycle owc
|
||||
WHERE owc.total_cycle_days > 0 -- 排除无均摊周期的异常订单
|
||||
),
|
||||
|
||||
-- 步骤6:计算每个订单在账期内的均摊天数和金额
|
||||
order_period_amort AS (
|
||||
SELECT
|
||||
oa.*,
|
||||
-- 账期内有效均摊天数
|
||||
CASE WHEN oa.eff_end >= oa.eff_start
|
||||
THEN EXTRACT(DAY FROM (oa.eff_end - oa.eff_start))::int + 1
|
||||
ELSE 0
|
||||
END AS period_amort_days,
|
||||
|
||||
-- 该订单从转正日到账期结束日的总已均摊天数(用于计算历史累计)
|
||||
CASE WHEN '{period_end}'::date >= oa.amortization_start_date
|
||||
THEN EXTRACT(DAY FROM (LEAST('{period_end}'::date, oa.amortization_end_date) - oa.amortization_start_date))::int + 1
|
||||
ELSE 0
|
||||
END AS total_amorted_days_to_period_end,
|
||||
|
||||
-- 该订单从转正日到账期起始日前一天的历史已均摊天数
|
||||
CASE WHEN '{period_start}'::date > oa.amortization_start_date
|
||||
THEN EXTRACT(DAY FROM (LEAST('{period_start}'::date - 1, oa.amortization_end_date) - oa.amortization_start_date))::int + 1
|
||||
ELSE 0
|
||||
END AS historical_amorted_days
|
||||
|
||||
FROM order_amortization oa
|
||||
),
|
||||
|
||||
-- 步骤7:计算最终均摊金额(含补差逻辑)
|
||||
order_final_amort AS (
|
||||
SELECT
|
||||
opa.*,
|
||||
|
||||
-- === 正常订单(未退费 或 账期前已处理的退费订单)在账期内的均摊 ===
|
||||
|
||||
-- 判断是否为账期前全额退费(本账期完全不统计)
|
||||
CASE WHEN opa.has_refund = 1 AND opa.is_full_refund = 1
|
||||
AND opa.latest_refund_date < '{period_start}'::date
|
||||
-- 判断是否为账期前全额退费(场景F:排除)
|
||||
CASE WHEN owc.has_refund = 1 AND owc.is_full_refund = 1
|
||||
AND owc.latest_refund_date < '{period_start}'::date
|
||||
THEN 1 ELSE 0
|
||||
END AS is_pre_period_full_refund,
|
||||
|
||||
-- 判断是否为账期前部分退费(本账期按剩余金额均摊)
|
||||
CASE WHEN opa.has_refund = 1 AND opa.is_full_refund = 0
|
||||
AND opa.latest_refund_date < '{period_start}'::date
|
||||
-- 判断是否为账期前部分退费(场景C)
|
||||
CASE WHEN owc.has_refund = 1 AND owc.is_full_refund = 0
|
||||
AND owc.latest_refund_date < '{period_start}'::date
|
||||
THEN 1 ELSE 0
|
||||
END AS is_pre_period_partial_refund,
|
||||
|
||||
-- 判断是否为账期内退费
|
||||
CASE WHEN opa.has_refund = 1
|
||||
AND opa.latest_refund_date >= '{period_start}'::date
|
||||
AND opa.latest_refund_date <= '{period_end}'::date
|
||||
CASE WHEN owc.has_refund = 1
|
||||
AND owc.latest_refund_date >= '{period_start}'::date
|
||||
AND owc.latest_refund_date <= '{period_end}'::date
|
||||
THEN 1 ELSE 0
|
||||
END AS is_current_period_refund,
|
||||
|
||||
-- 部分退费后的剩余税后金额
|
||||
CASE WHEN opa.has_refund = 1 AND opa.is_full_refund = 0
|
||||
THEN (opa.pay_amount - opa.total_refund_amount) * (1 - opa.tax_rate)
|
||||
ELSE opa.after_tax_amount
|
||||
END AS remaining_after_tax_amount,
|
||||
-- 判断是否为账期内下单(下单日在账期内)
|
||||
CASE WHEN owc.order_date >= '{period_start}'::date
|
||||
AND owc.order_date <= '{period_end}'::date
|
||||
THEN 1 ELSE 0
|
||||
END AS is_ordered_in_period,
|
||||
|
||||
-- 部分退费后的剩余税费
|
||||
CASE WHEN opa.has_refund = 1 AND opa.is_full_refund = 0
|
||||
THEN (opa.pay_amount - opa.total_refund_amount) * opa.tax_rate
|
||||
ELSE opa.tax_amount
|
||||
END AS remaining_tax_amount
|
||||
-- 退后订单税后金额
|
||||
CASE WHEN owc.has_refund = 1 AND owc.is_full_refund = 0
|
||||
THEN (owc.pay_amount - owc.total_refund_amount) / (1 + owc.tax_rate)
|
||||
ELSE owc.after_tax_amount
|
||||
END AS refunded_after_tax_amount,
|
||||
|
||||
FROM order_period_amort opa
|
||||
-- 退后订单税费
|
||||
CASE WHEN owc.has_refund = 1 AND owc.is_full_refund = 0
|
||||
THEN (owc.pay_amount - owc.total_refund_amount) / (1 + owc.tax_rate) * owc.tax_rate
|
||||
ELSE owc.tax_amount
|
||||
END AS refunded_tax_amount
|
||||
|
||||
FROM order_with_cycle owc
|
||||
WHERE owc.total_cycle_days > 0 OR (owc.has_refund = 1 AND owc.is_full_refund = 1 AND owc.original_cycle_days > 0)
|
||||
),
|
||||
|
||||
-- 步骤5:计算均摊天数
|
||||
order_with_days AS (
|
||||
SELECT
|
||||
oc2.*,
|
||||
-- 账期内有效均摊天数(基于退后周期)
|
||||
CASE WHEN oc2.eff_end >= oc2.eff_start AND oc2.total_cycle_days > 0
|
||||
THEN EXTRACT(DAY FROM (oc2.eff_end - oc2.eff_start))::int + 1
|
||||
ELSE 0
|
||||
END AS period_amort_days,
|
||||
|
||||
-- 从转正日到账期结束日的总已均摊天数(基于退后周期)
|
||||
CASE WHEN '{period_end}'::date >= oc2.amortization_start_date AND oc2.total_cycle_days > 0
|
||||
THEN EXTRACT(DAY FROM (LEAST('{period_end}'::date, oc2.amortization_end_date) - oc2.amortization_start_date))::int + 1
|
||||
ELSE 0
|
||||
END AS total_amorted_days_to_period_end,
|
||||
|
||||
-- 从转正日到账期起始日前一天的历史已均摊天数(基于原始周期,用于冲销计算)
|
||||
CASE WHEN '{period_start}'::date > oc2.amortization_start_date AND oc2.original_cycle_days > 0
|
||||
THEN EXTRACT(DAY FROM (LEAST('{period_start}'::date - 1, oc2.original_amortization_end_date) - oc2.amortization_start_date))::int + 1
|
||||
ELSE 0
|
||||
END AS historical_amorted_days,
|
||||
|
||||
-- 从转正日到账期结束日的天数(基于退后周期,用于退后订单的重新均摊)
|
||||
CASE WHEN '{period_end}'::date >= oc2.amortization_start_date AND oc2.total_cycle_days > 0
|
||||
THEN EXTRACT(DAY FROM (LEAST('{period_end}'::date, oc2.amortization_end_date) - oc2.amortization_start_date))::int + 1
|
||||
ELSE 0
|
||||
END AS refunded_amort_days_to_period_end
|
||||
|
||||
FROM order_classified oc2
|
||||
)
|
||||
-- 最终输出
|
||||
SELECT
|
||||
order_no AS "订单号",
|
||||
order_date AS "下单日期",
|
||||
latest_refund_date AS "退费日期",
|
||||
CASE
|
||||
WHEN is_pre_period_full_refund = 1 THEN '账期前全额退费'
|
||||
WHEN is_pre_period_partial_refund = 1 THEN '账期前部分退费'
|
||||
WHEN is_current_period_refund = 1 AND is_full_refund = 1 AND is_ordered_in_period = 1 THEN '账期内下单全额退费'
|
||||
WHEN is_current_period_refund = 1 AND is_full_refund = 1 AND is_ordered_in_period = 0 THEN '历史下单账期内全额退费'
|
||||
WHEN is_current_period_refund = 1 AND is_full_refund = 0 AND is_ordered_in_period = 1 THEN '账期内下单部分退费'
|
||||
WHEN is_current_period_refund = 1 AND is_full_refund = 0 AND is_ordered_in_period = 0 THEN '历史下单账期内部分退费'
|
||||
WHEN DATE(amortization_start_date) > '{period_end}'::date THEN '试用期中'
|
||||
ELSE '正常订单'
|
||||
END AS "订单分类",
|
||||
ROUND(pay_amount::numeric, 2) AS "订单金额",
|
||||
ROUND(tax_rate::numeric, 2) AS "税率",
|
||||
ROUND(tax_amount::numeric, 2) AS "税额",
|
||||
ROUND(after_tax_amount::numeric, 2) AS "税后金额",
|
||||
total_cycle_days AS "总均摊周期",
|
||||
period_amort_days AS "账期内均摊天数",
|
||||
ROUND((historical_amorted_days * daily_amort_amount)::numeric, 2) AS "历史均摊金额",
|
||||
ROUND(tax_rate::numeric, 4) AS "税率",
|
||||
ROUND(tax_amount::numeric, 2) AS "原订单税额",
|
||||
ROUND(after_tax_amount::numeric, 2) AS "原订单税后金额",
|
||||
original_cycle_days AS "原始均摊周期",
|
||||
total_cycle_days AS "退后均摊周期",
|
||||
|
||||
-- 历史均摊金额(基于原始日均摊)
|
||||
ROUND((historical_amorted_days * original_daily_amort_amount)::numeric, 2) AS "历史均摊金额",
|
||||
|
||||
-- 冲销历史均摊(场景B/E:历史下单+账期内退费)
|
||||
ROUND(
|
||||
CASE WHEN is_current_period_refund = 1 AND is_ordered_in_period = 0 AND historical_amorted_days > 0
|
||||
THEN -(historical_amorted_days * original_daily_amort_amount)
|
||||
ELSE 0
|
||||
END::numeric, 2
|
||||
) AS "冲销历史均摊",
|
||||
|
||||
-- 冲销原税款(场景B/E:历史下单+账期内退费)
|
||||
ROUND(
|
||||
CASE WHEN is_current_period_refund = 1 AND is_ordered_in_period = 0
|
||||
THEN -tax_amount
|
||||
ELSE 0
|
||||
END::numeric, 2
|
||||
) AS "冲销原税款",
|
||||
|
||||
-- 冲销未确认收入(场景B/E:历史下单+账期内退费)
|
||||
ROUND(
|
||||
CASE WHEN is_current_period_refund = 1 AND is_ordered_in_period = 0
|
||||
THEN -(after_tax_amount - historical_amorted_days * original_daily_amort_amount)
|
||||
ELSE 0
|
||||
END::numeric, 2
|
||||
) AS "冲销未确认收入",
|
||||
|
||||
-- 账期均摊金额
|
||||
ROUND(
|
||||
CASE
|
||||
-- 场景F:账期前全额退费,不统计
|
||||
WHEN is_pre_period_full_refund = 1 THEN 0
|
||||
WHEN is_pre_period_partial_refund = 1 THEN
|
||||
-- 场景D:账期内下单+全额退费,无均摊
|
||||
WHEN is_current_period_refund = 1 AND is_full_refund = 1 AND is_ordered_in_period = 1 THEN 0
|
||||
-- 场景E:历史下单+账期内全额退费,无退后均摊
|
||||
WHEN is_current_period_refund = 1 AND is_full_refund = 1 AND is_ordered_in_period = 0 THEN 0
|
||||
-- 场景A:账期内下单+部分退费,按退后订单金额/退后周期从转正日均摊
|
||||
WHEN is_current_period_refund = 1 AND is_full_refund = 0 AND is_ordered_in_period = 1 THEN
|
||||
CASE WHEN total_cycle_days > 0 AND period_amort_days > 0
|
||||
THEN remaining_after_tax_amount / total_cycle_days * period_amort_days
|
||||
THEN daily_amort_amount * period_amort_days
|
||||
ELSE 0
|
||||
END
|
||||
WHEN is_current_period_refund = 0 AND period_amort_days > 0 THEN
|
||||
-- 场景B:历史下单+账期内部分退费,按退后订单金额/退后周期从转正日重新均摊
|
||||
WHEN is_current_period_refund = 1 AND is_full_refund = 0 AND is_ordered_in_period = 0 THEN
|
||||
CASE WHEN total_cycle_days > 0 AND refunded_amort_days_to_period_end > 0
|
||||
THEN daily_amort_amount * refunded_amort_days_to_period_end
|
||||
ELSE 0
|
||||
END
|
||||
-- 场景C:账期前部分退费,按退后订单金额/退后周期正常均摊
|
||||
WHEN is_pre_period_partial_refund = 1 THEN
|
||||
CASE WHEN total_cycle_days > 0 AND period_amort_days > 0
|
||||
THEN daily_amort_amount * period_amort_days
|
||||
ELSE 0
|
||||
END
|
||||
-- 正常订单
|
||||
WHEN period_amort_days > 0 THEN
|
||||
CASE
|
||||
WHEN eff_end = amortization_end_date
|
||||
THEN after_tax_amount - daily_amort_amount * (total_cycle_days - 1) + daily_amort_amount * (period_amort_days - 1)
|
||||
ELSE daily_amort_amount * period_amort_days
|
||||
THEN after_tax_amount - original_daily_amort_amount * (original_cycle_days - 1) + original_daily_amort_amount * (period_amort_days - 1)
|
||||
ELSE original_daily_amort_amount * period_amort_days
|
||||
END
|
||||
ELSE 0
|
||||
END::numeric, 2
|
||||
) AS "账期均摊金额",
|
||||
|
||||
-- 退后订单税额(仅账期内下单且已转正的非全额退费订单计税)
|
||||
ROUND(
|
||||
(CASE
|
||||
WHEN is_pre_period_partial_refund = 1 OR (is_current_period_refund = 1 AND is_full_refund = 0)
|
||||
THEN remaining_after_tax_amount
|
||||
ELSE after_tax_amount
|
||||
END - (historical_amorted_days * daily_amort_amount))::numeric, 2
|
||||
CASE
|
||||
-- 账期内下单 + 已转正 + 部分退费 → 退后订单税额
|
||||
WHEN is_ordered_in_period = 1
|
||||
AND DATE(amortization_start_date) <= '{period_end}'::date
|
||||
AND is_current_period_refund = 1 AND is_full_refund = 0
|
||||
THEN refunded_tax_amount
|
||||
-- 账期内下单 + 已转正 + 未全额退费(含未退费)→ 原订单税额
|
||||
WHEN is_ordered_in_period = 1
|
||||
AND DATE(amortization_start_date) <= '{period_end}'::date
|
||||
AND (has_refund = 0 OR (is_current_period_refund = 0 AND is_full_refund = 0))
|
||||
THEN tax_amount
|
||||
ELSE 0
|
||||
END::numeric, 2
|
||||
) AS "账期税额",
|
||||
|
||||
-- 未确认收入
|
||||
ROUND(
|
||||
CASE
|
||||
WHEN is_pre_period_full_refund = 1 THEN 0
|
||||
WHEN is_current_period_refund = 1 AND is_full_refund = 1 THEN 0
|
||||
WHEN is_current_period_refund = 1 AND is_full_refund = 0 THEN
|
||||
refunded_after_tax_amount - daily_amort_amount * refunded_amort_days_to_period_end
|
||||
WHEN is_pre_period_partial_refund = 1 THEN
|
||||
refunded_after_tax_amount - daily_amort_amount * total_amorted_days_to_period_end
|
||||
ELSE
|
||||
after_tax_amount - original_daily_amort_amount * total_amorted_days_to_period_end
|
||||
END::numeric, 2
|
||||
) AS "未确认收入",
|
||||
(total_cycle_days - total_amorted_days_to_period_end) AS "剩余周期"
|
||||
FROM order_final_amort
|
||||
|
||||
-- 剩余周期
|
||||
CASE
|
||||
WHEN is_current_period_refund = 1 AND is_full_refund = 1 THEN 0
|
||||
ELSE (total_cycle_days - total_amorted_days_to_period_end)
|
||||
END AS "剩余周期"
|
||||
|
||||
FROM order_with_days
|
||||
WHERE is_pre_period_full_refund = 0;
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
WITH
|
||||
-- 步骤0:获取所有历史退费记录(无时间范围,用于标记订单是否为退费订单,不受当前账期限制)
|
||||
-- 步骤0:获取所有历史退费记录
|
||||
all_refund_records AS (
|
||||
SELECT
|
||||
out_trade_no AS order_no,
|
||||
SUM(refund_amount_int) / 100 AS total_refund_amount, -- 累计退费总金额(支持多笔部分退费叠加)
|
||||
MAX(CASE WHEN refund_type = 2 THEN 1 ELSE 0 END) AS is_full_refund, -- 是否全额退费(只要有一笔全额退费即标记为1)
|
||||
SUM(refund_amount_int) / 100 AS total_refund_amount,
|
||||
MAX(CASE WHEN refund_type = 2 THEN 1 ELSE 0 END) AS is_full_refund,
|
||||
MAX(refund_type) AS refund_type,
|
||||
MAX(DATE(updated_at)) AS latest_refund_date -- 最后一次退费完成时间
|
||||
MAX(DATE(updated_at)) AS latest_refund_date
|
||||
FROM bi_refund_order
|
||||
WHERE status = 3
|
||||
GROUP BY out_trade_no
|
||||
@ -15,274 +15,202 @@ all_refund_records AS (
|
||||
order_base AS (
|
||||
SELECT
|
||||
o.id AS order_id,
|
||||
o.out_trade_no AS order_no, -- 修正:bi_vala_order无order_no字段,使用out_trade_no作为订单号
|
||||
o.trade_no, -- 新增:关联退费订单需要trade_no字段
|
||||
o.out_trade_no AS order_no,
|
||||
o.trade_no,
|
||||
DATE(o.created_at) AS order_date,
|
||||
o.pay_amount_int / 100 AS pay_amount,
|
||||
-- 计算税率、税费、税后金额
|
||||
CASE WHEN DATE(o.created_at) < '2026-05-01' THEN 0.01 ELSE 0.06 END AS tax_rate,
|
||||
(o.pay_amount_int / 100) * CASE WHEN DATE(o.created_at) < '2026-05-01' THEN 0.01 ELSE 0.06 END AS tax_amount,
|
||||
(o.pay_amount_int / 100) * (1 - CASE WHEN DATE(o.created_at) < '2026-05-01' THEN 0.01 ELSE 0.06 END) AS after_tax_amount,
|
||||
(o.pay_amount_int / 100.0) / (1 + CASE WHEN DATE(o.created_at) < '2026-05-01' THEN 0.01 ELSE 0.06 END) * CASE WHEN DATE(o.created_at) < '2026-05-01' THEN 0.01 ELSE 0.06 END AS tax_amount,
|
||||
(o.pay_amount_int / 100.0) / (1 + CASE WHEN DATE(o.created_at) < '2026-05-01' THEN 0.01 ELSE 0.06 END) AS after_tax_amount,
|
||||
DATE(o.created_at) + INTERVAL '7 days' AS amortization_start_date,
|
||||
o.order_status, -- 修正:字段名是order_status不是status
|
||||
o.order_status,
|
||||
a.id AS account_id,
|
||||
o.key_from,
|
||||
o.sale_channel,
|
||||
-- 新增:订单退费标记字段(所有历史退费均可识别,不受当前账期限制)
|
||||
CASE WHEN ar.order_no IS NOT NULL THEN 1 ELSE 0 END AS has_refund, -- 是否有退费记录
|
||||
COALESCE(ar.total_refund_amount, 0) AS total_refund_amount, -- 累计退费金额
|
||||
COALESCE(ar.is_full_refund, 0) AS is_full_refund, -- 是否全额退费
|
||||
CASE WHEN ar.order_no IS NOT NULL THEN 1 ELSE 0 END AS has_refund,
|
||||
COALESCE(ar.total_refund_amount, 0) AS total_refund_amount,
|
||||
COALESCE(ar.is_full_refund, 0) AS is_full_refund,
|
||||
ar.refund_type,
|
||||
ar.latest_refund_date -- 退费完成日期(解决历史退费订单退费日期为空的问题)
|
||||
ar.latest_refund_date
|
||||
FROM bi_vala_order o
|
||||
JOIN bi_vala_app_account a ON o.account_id = a.id
|
||||
LEFT JOIN all_refund_records ar ON o.out_trade_no = ar.order_no -- 关联全量退费记录,不限制时间
|
||||
LEFT JOIN all_refund_records ar ON o.out_trade_no = ar.order_no
|
||||
WHERE
|
||||
o.created_at >= '2025-09-01'
|
||||
AND o.order_status IN (3,4) -- 修正:字段名是order_status不是status
|
||||
AND o.order_status IN (3,4)
|
||||
AND o.pay_amount_int >= 1000
|
||||
AND a.status = 1
|
||||
),
|
||||
-- 步骤2:计算每个订单的总均摊周期
|
||||
-- 步骤2:计算均摊周期
|
||||
order_cycle AS (
|
||||
SELECT
|
||||
out_trade_no AS order_no,
|
||||
COUNT(DISTINCT id) * 90 AS total_cycle_days
|
||||
FROM bi_vala_seasonal_ticket
|
||||
WHERE status != -1
|
||||
GROUP BY out_trade_no
|
||||
SELECT out_trade_no AS order_no, COUNT(DISTINCT id) * 90 AS total_cycle_days
|
||||
FROM bi_vala_seasonal_ticket WHERE status != -1 GROUP BY out_trade_no
|
||||
),
|
||||
-- 步骤3:获取账期内的退费记录(仅用于计算当前账期的冲销金额,不影响订单退费状态标记)
|
||||
refund_records AS (
|
||||
SELECT
|
||||
r.out_trade_no AS order_no,
|
||||
r.refund_amount_int / 100 AS refund_amount, -- 修正:使用分为单位的refund_amount_int,避免字符串转换问题,除以100得到元
|
||||
r.refund_type,
|
||||
DATE(r.updated_at) AS refund_date -- 退费日期使用updated_at(status=3时即为退费完成时间)
|
||||
FROM bi_refund_order r
|
||||
JOIN order_base o ON r.out_trade_no = o.order_no OR r.trade_no = o.trade_no -- 修正:支持out_trade_no/trade_no双字段匹配退费订单
|
||||
WHERE
|
||||
r.status = 3
|
||||
AND r.updated_at BETWEEN '{period_start}' AND '{period_end}'
|
||||
)
|
||||
,
|
||||
-- 步骤4:合并订单基础信息与均摊周期
|
||||
order_cycle_original AS (
|
||||
SELECT out_trade_no AS order_no, COUNT(DISTINCT id) * 90 AS original_cycle_days
|
||||
FROM bi_vala_seasonal_ticket GROUP BY out_trade_no
|
||||
),
|
||||
-- 步骤3:合并
|
||||
order_with_cycle AS (
|
||||
SELECT
|
||||
ob.*,
|
||||
COALESCE(oc.total_cycle_days, 0) AS total_cycle_days,
|
||||
-- 均摊结束日 = 转正日 + 总周期天数 - 1
|
||||
COALESCE(oco.original_cycle_days, 0) AS original_cycle_days,
|
||||
ob.amortization_start_date + COALESCE(oc.total_cycle_days, 0) * INTERVAL '1 day' - INTERVAL '1 day' AS amortization_end_date,
|
||||
-- 日均摊金额(税后)
|
||||
CASE WHEN COALESCE(oc.total_cycle_days, 0) > 0
|
||||
THEN ob.after_tax_amount / oc.total_cycle_days
|
||||
ELSE 0
|
||||
ob.amortization_start_date + COALESCE(oco.original_cycle_days, 0) * INTERVAL '1 day' - INTERVAL '1 day' AS original_amortization_end_date,
|
||||
CASE WHEN COALESCE(oco.original_cycle_days, 0) > 0
|
||||
THEN ob.after_tax_amount / oco.original_cycle_days ELSE 0
|
||||
END AS original_daily_amort_amount,
|
||||
CASE WHEN COALESCE(oco.original_cycle_days, 0) > 0
|
||||
THEN ob.tax_amount / oco.original_cycle_days ELSE 0
|
||||
END AS original_daily_tax_amount,
|
||||
CASE WHEN COALESCE(oc.total_cycle_days, 0) > 0 AND ob.has_refund = 1 AND ob.is_full_refund = 0
|
||||
THEN (ob.pay_amount - ob.total_refund_amount) / (1 + ob.tax_rate) / oc.total_cycle_days
|
||||
WHEN COALESCE(oc.total_cycle_days, 0) > 0
|
||||
THEN ob.after_tax_amount / oc.total_cycle_days ELSE 0
|
||||
END AS daily_amort_amount,
|
||||
-- 日税费均摊
|
||||
CASE WHEN COALESCE(oc.total_cycle_days, 0) > 0
|
||||
THEN ob.tax_amount / oc.total_cycle_days
|
||||
ELSE 0
|
||||
CASE WHEN COALESCE(oc.total_cycle_days, 0) > 0 AND ob.has_refund = 1 AND ob.is_full_refund = 0
|
||||
THEN (ob.pay_amount - ob.total_refund_amount) / (1 + ob.tax_rate) * ob.tax_rate / oc.total_cycle_days
|
||||
WHEN COALESCE(oc.total_cycle_days, 0) > 0
|
||||
THEN ob.tax_amount / oc.total_cycle_days ELSE 0
|
||||
END AS daily_tax_amount
|
||||
FROM order_base ob
|
||||
LEFT JOIN order_cycle oc ON ob.order_no = oc.order_no
|
||||
LEFT JOIN order_cycle_original oco ON ob.order_no = oco.order_no
|
||||
),
|
||||
|
||||
-- 步骤5:判断订单在账期内的状态分类,并计算各类均摊金额
|
||||
order_amortization AS (
|
||||
-- 步骤4:分类
|
||||
order_classified AS (
|
||||
SELECT
|
||||
owc.*,
|
||||
-- 是否为账期内新增订单
|
||||
CASE WHEN DATE(owc.amortization_start_date) <= '{period_end}'
|
||||
AND owc.amortization_start_date >= '{period_start}'::date - INTERVAL '6 days'
|
||||
THEN 1 ELSE 0 END AS is_new_in_period,
|
||||
-- 账期内新增且已转正
|
||||
CASE WHEN DATE(owc.amortization_start_date) >= '{period_start}'
|
||||
AND DATE(owc.amortization_start_date) <= '{period_end}'
|
||||
THEN 1
|
||||
WHEN owc.amortization_start_date < '{period_start}'
|
||||
THEN 1
|
||||
ELSE 0
|
||||
END AS is_formal,
|
||||
|
||||
-- ===== 正常均摊金额计算(未退费 或 账期前部分退费的订单)=====
|
||||
-- 均摊有效起始日(取转正日和账期起始日的较大值)
|
||||
GREATEST(owc.amortization_start_date, '{period_start}'::date) AS eff_start,
|
||||
-- 均摊有效结束日(取均摊结束日和账期结束日的较小值)
|
||||
LEAST(owc.amortization_end_date, '{period_end}'::date) AS eff_end
|
||||
|
||||
LEAST(owc.amortization_end_date, '{period_end}'::date) AS eff_end,
|
||||
CASE WHEN owc.has_refund = 1 AND owc.is_full_refund = 1 AND owc.latest_refund_date < '{period_start}'::date
|
||||
THEN 1 ELSE 0 END AS is_pre_period_full_refund,
|
||||
CASE WHEN owc.has_refund = 1 AND owc.is_full_refund = 0 AND owc.latest_refund_date < '{period_start}'::date
|
||||
THEN 1 ELSE 0 END AS is_pre_period_partial_refund,
|
||||
CASE WHEN owc.has_refund = 1
|
||||
AND owc.latest_refund_date >= '{period_start}'::date AND owc.latest_refund_date <= '{period_end}'::date
|
||||
THEN 1 ELSE 0 END AS is_current_period_refund,
|
||||
CASE WHEN owc.order_date >= '{period_start}'::date AND owc.order_date <= '{period_end}'::date
|
||||
THEN 1 ELSE 0 END AS is_ordered_in_period,
|
||||
CASE WHEN owc.has_refund = 1 AND owc.is_full_refund = 0
|
||||
THEN (owc.pay_amount - owc.total_refund_amount) / (1 + owc.tax_rate) ELSE owc.after_tax_amount
|
||||
END AS refunded_after_tax_amount,
|
||||
CASE WHEN owc.has_refund = 1 AND owc.is_full_refund = 0
|
||||
THEN (owc.pay_amount - owc.total_refund_amount) / (1 + owc.tax_rate) * owc.tax_rate ELSE owc.tax_amount
|
||||
END AS refunded_tax_amount
|
||||
FROM order_with_cycle owc
|
||||
WHERE owc.total_cycle_days > 0 -- 排除无均摊周期的异常订单
|
||||
WHERE owc.total_cycle_days > 0 OR (owc.has_refund = 1 AND owc.is_full_refund = 1 AND owc.original_cycle_days > 0)
|
||||
),
|
||||
|
||||
-- 步骤6:计算每个订单在账期内的均摊天数和金额
|
||||
order_period_amort AS (
|
||||
-- 步骤5:计算天数
|
||||
order_with_days AS (
|
||||
SELECT
|
||||
oa.*,
|
||||
-- 账期内有效均摊天数
|
||||
CASE WHEN oa.eff_end >= oa.eff_start
|
||||
THEN EXTRACT(DAY FROM (oa.eff_end - oa.eff_start))::int + 1
|
||||
ELSE 0
|
||||
oc2.*,
|
||||
CASE WHEN oc2.eff_end >= oc2.eff_start AND oc2.total_cycle_days > 0
|
||||
THEN EXTRACT(DAY FROM (oc2.eff_end - oc2.eff_start))::int + 1 ELSE 0
|
||||
END AS period_amort_days,
|
||||
|
||||
-- 该订单从转正日到账期结束日的总已均摊天数(用于计算历史累计)
|
||||
CASE WHEN '{period_end}'::date >= oa.amortization_start_date
|
||||
THEN EXTRACT(DAY FROM (LEAST('{period_end}'::date, oa.amortization_end_date) - oa.amortization_start_date))::int + 1
|
||||
ELSE 0
|
||||
CASE WHEN '{period_end}'::date >= oc2.amortization_start_date AND oc2.total_cycle_days > 0
|
||||
THEN EXTRACT(DAY FROM (LEAST('{period_end}'::date, oc2.amortization_end_date) - oc2.amortization_start_date))::int + 1 ELSE 0
|
||||
END AS total_amorted_days_to_period_end,
|
||||
|
||||
-- 该订单从转正日到账期起始日前一天的历史已均摊天数
|
||||
CASE WHEN '{period_start}'::date > oa.amortization_start_date
|
||||
THEN EXTRACT(DAY FROM (LEAST('{period_start}'::date - 1, oa.amortization_end_date) - oa.amortization_start_date))::int + 1
|
||||
ELSE 0
|
||||
END AS historical_amorted_days
|
||||
|
||||
FROM order_amortization oa
|
||||
CASE WHEN '{period_start}'::date > oc2.amortization_start_date AND oc2.original_cycle_days > 0
|
||||
THEN EXTRACT(DAY FROM (LEAST('{period_start}'::date - 1, oc2.original_amortization_end_date) - oc2.amortization_start_date))::int + 1 ELSE 0
|
||||
END AS historical_amorted_days,
|
||||
CASE WHEN '{period_end}'::date >= oc2.amortization_start_date AND oc2.total_cycle_days > 0
|
||||
THEN EXTRACT(DAY FROM (LEAST('{period_end}'::date, oc2.amortization_end_date) - oc2.amortization_start_date))::int + 1 ELSE 0
|
||||
END AS refunded_amort_days_to_period_end
|
||||
FROM order_classified oc2
|
||||
),
|
||||
|
||||
-- 步骤7:计算最终均摊金额(含补差逻辑)
|
||||
order_final_amort AS (
|
||||
SELECT
|
||||
opa.*,
|
||||
|
||||
-- === 正常订单(未退费 或 账期前已处理的退费订单)在账期内的均摊 ===
|
||||
|
||||
-- 判断是否为账期前全额退费(本账期完全不统计)
|
||||
CASE WHEN opa.has_refund = 1 AND opa.is_full_refund = 1
|
||||
AND opa.latest_refund_date < '{period_start}'::date
|
||||
THEN 1 ELSE 0
|
||||
END AS is_pre_period_full_refund,
|
||||
|
||||
-- 判断是否为账期前部分退费(本账期按剩余金额均摊)
|
||||
CASE WHEN opa.has_refund = 1 AND opa.is_full_refund = 0
|
||||
AND opa.latest_refund_date < '{period_start}'::date
|
||||
THEN 1 ELSE 0
|
||||
END AS is_pre_period_partial_refund,
|
||||
|
||||
-- 判断是否为账期内退费
|
||||
CASE WHEN opa.has_refund = 1
|
||||
AND opa.latest_refund_date >= '{period_start}'::date
|
||||
AND opa.latest_refund_date <= '{period_end}'::date
|
||||
THEN 1 ELSE 0
|
||||
END AS is_current_period_refund,
|
||||
|
||||
-- 部分退费后的剩余税后金额
|
||||
CASE WHEN opa.has_refund = 1 AND opa.is_full_refund = 0
|
||||
THEN (opa.pay_amount - opa.total_refund_amount) * (1 - opa.tax_rate)
|
||||
ELSE opa.after_tax_amount
|
||||
END AS remaining_after_tax_amount,
|
||||
|
||||
-- 部分退费后的剩余税费
|
||||
CASE WHEN opa.has_refund = 1 AND opa.is_full_refund = 0
|
||||
THEN (opa.pay_amount - opa.total_refund_amount) * opa.tax_rate
|
||||
ELSE opa.tax_amount
|
||||
END AS remaining_tax_amount
|
||||
|
||||
FROM order_period_amort opa
|
||||
),
|
||||
|
||||
-- 步骤8:最终汇总计算
|
||||
-- 步骤6:汇总
|
||||
summary_calc AS (
|
||||
SELECT
|
||||
-- ===== 账期内新增订单统计 =====
|
||||
COUNT(CASE WHEN DATE(amortization_start_date - INTERVAL '7 days') >= '{period_start}'::date
|
||||
AND DATE(amortization_start_date - INTERVAL '7 days') <= '{period_end}'::date
|
||||
THEN 1 END) AS total_new_orders,
|
||||
-- 账期内新增订单统计
|
||||
COUNT(CASE WHEN order_date >= '{period_start}'::date AND order_date <= '{period_end}'::date THEN 1 END) AS total_new_orders,
|
||||
COUNT(CASE WHEN order_date >= '{period_start}'::date AND order_date <= '{period_end}'::date
|
||||
AND amortization_start_date <= '{period_end}'::date THEN 1 END) AS formal_orders,
|
||||
COUNT(CASE WHEN order_date >= '{period_start}'::date AND order_date <= '{period_end}'::date
|
||||
AND amortization_start_date > '{period_end}'::date THEN 1 END) AS trial_orders,
|
||||
|
||||
COUNT(CASE WHEN DATE(amortization_start_date - INTERVAL '7 days') >= '{period_start}'::date
|
||||
AND DATE(amortization_start_date - INTERVAL '7 days') <= '{period_end}'::date
|
||||
AND amortization_start_date <= '{period_end}'::date
|
||||
THEN 1 END) AS formal_orders,
|
||||
|
||||
COUNT(CASE WHEN DATE(amortization_start_date - INTERVAL '7 days') >= '{period_start}'::date
|
||||
AND DATE(amortization_start_date - INTERVAL '7 days') <= '{period_end}'::date
|
||||
AND amortization_start_date > '{period_end}'::date
|
||||
THEN 1 END) AS trial_orders,
|
||||
|
||||
-- ===== 冲销前均摊金额(税后):所有非"账期前全额退费"订单在账期内的均摊 =====
|
||||
-- 冲销历史均摊(场景B/E:历史下单+账期内退费)
|
||||
ROUND(SUM(
|
||||
CASE
|
||||
WHEN is_pre_period_full_refund = 1 THEN 0 -- 账期前全额退费,不统计
|
||||
WHEN is_pre_period_partial_refund = 1 THEN -- 账期前部分退费,按剩余金额均摊
|
||||
CASE WHEN total_cycle_days > 0 AND period_amort_days > 0
|
||||
THEN remaining_after_tax_amount / total_cycle_days * period_amort_days
|
||||
ELSE 0
|
||||
END
|
||||
WHEN is_current_period_refund = 0 AND period_amort_days > 0 THEN -- 正常未退费订单
|
||||
CASE
|
||||
-- 补差逻辑:如果账期结束日恰好是均摊最后一天
|
||||
WHEN eff_end = amortization_end_date
|
||||
THEN after_tax_amount - daily_amort_amount * (total_cycle_days - 1)
|
||||
+ daily_amort_amount * (period_amort_days - 1)
|
||||
ELSE daily_amort_amount * period_amort_days
|
||||
END
|
||||
ELSE 0
|
||||
END
|
||||
)::numeric, 2) AS pre_writeoff_amort,
|
||||
|
||||
-- ===== 冲销前税费 =====
|
||||
ROUND(SUM(
|
||||
CASE
|
||||
WHEN is_pre_period_full_refund = 1 THEN 0
|
||||
WHEN is_pre_period_partial_refund = 1 THEN
|
||||
CASE WHEN total_cycle_days > 0 AND period_amort_days > 0
|
||||
THEN remaining_tax_amount / total_cycle_days * period_amort_days
|
||||
ELSE 0
|
||||
END
|
||||
WHEN is_current_period_refund = 0 AND period_amort_days > 0 THEN
|
||||
daily_tax_amount * period_amort_days
|
||||
ELSE 0
|
||||
END
|
||||
)::numeric, 2) AS pre_writeoff_tax,
|
||||
|
||||
-- ===== 冲销均摊金额(税后):账期内退费订单的历史已均摊金额 =====
|
||||
ROUND(SUM(
|
||||
CASE WHEN is_current_period_refund = 1 AND historical_amorted_days > 0
|
||||
THEN daily_amort_amount * historical_amorted_days
|
||||
CASE WHEN is_current_period_refund = 1 AND is_ordered_in_period = 0 AND historical_amorted_days > 0
|
||||
THEN historical_amorted_days * original_daily_amort_amount
|
||||
ELSE 0
|
||||
END
|
||||
)::numeric, 2) AS writeoff_amort,
|
||||
|
||||
-- ===== 冲销税费 =====
|
||||
-- 冲销原税款(场景B/E:历史下单+账期内退费)
|
||||
ROUND(SUM(
|
||||
CASE WHEN is_current_period_refund = 1 AND historical_amorted_days > 0
|
||||
THEN daily_tax_amount * historical_amorted_days
|
||||
CASE WHEN is_current_period_refund = 1 AND is_ordered_in_period = 0
|
||||
THEN tax_amount
|
||||
ELSE 0
|
||||
END
|
||||
)::numeric, 2) AS writeoff_tax,
|
||||
|
||||
-- ===== 补充均摊金额(税后):账期内部分退费订单,退费后剩余金额的均摊 =====
|
||||
-- 冲销未确认收入(场景B/E:历史下单+账期内退费)
|
||||
ROUND(SUM(
|
||||
CASE WHEN is_current_period_refund = 1
|
||||
AND is_full_refund = 0
|
||||
AND total_cycle_days > 0
|
||||
AND period_amort_days > 0
|
||||
THEN (pay_amount - total_refund_amount) * (1 - tax_rate) / total_cycle_days * period_amort_days
|
||||
CASE WHEN is_current_period_refund = 1 AND is_ordered_in_period = 0
|
||||
THEN after_tax_amount - historical_amorted_days * original_daily_amort_amount
|
||||
ELSE 0
|
||||
END
|
||||
)::numeric, 2) AS supplement_amort,
|
||||
)::numeric, 2) AS writeoff_unconfirmed,
|
||||
|
||||
-- ===== 补充税费 =====
|
||||
-- 账期均摊金额
|
||||
ROUND(SUM(
|
||||
CASE WHEN is_current_period_refund = 1
|
||||
AND is_full_refund = 0
|
||||
AND total_cycle_days > 0
|
||||
AND period_amort_days > 0
|
||||
THEN (pay_amount - total_refund_amount) * tax_rate / total_cycle_days * period_amort_days
|
||||
CASE
|
||||
WHEN is_pre_period_full_refund = 1 THEN 0
|
||||
WHEN is_current_period_refund = 1 AND is_full_refund = 1 THEN 0
|
||||
-- 场景A:账期内下单+部分退费
|
||||
WHEN is_current_period_refund = 1 AND is_full_refund = 0 AND is_ordered_in_period = 1 THEN
|
||||
CASE WHEN total_cycle_days > 0 AND period_amort_days > 0
|
||||
THEN daily_amort_amount * period_amort_days ELSE 0 END
|
||||
-- 场景B:历史下单+账期内部分退费,从转正日重新均摊
|
||||
WHEN is_current_period_refund = 1 AND is_full_refund = 0 AND is_ordered_in_period = 0 THEN
|
||||
CASE WHEN total_cycle_days > 0 AND refunded_amort_days_to_period_end > 0
|
||||
THEN daily_amort_amount * refunded_amort_days_to_period_end ELSE 0 END
|
||||
-- 场景C:账期前部分退费
|
||||
WHEN is_pre_period_partial_refund = 1 THEN
|
||||
CASE WHEN total_cycle_days > 0 AND period_amort_days > 0
|
||||
THEN daily_amort_amount * period_amort_days ELSE 0 END
|
||||
-- 正常订单
|
||||
WHEN period_amort_days > 0 THEN
|
||||
CASE
|
||||
WHEN eff_end = amortization_end_date
|
||||
THEN after_tax_amount - original_daily_amort_amount * (original_cycle_days - 1) + original_daily_amort_amount * (period_amort_days - 1)
|
||||
ELSE original_daily_amort_amount * period_amort_days
|
||||
END
|
||||
ELSE 0
|
||||
END
|
||||
)::numeric, 2) AS supplement_tax
|
||||
)::numeric, 2) AS period_amort,
|
||||
|
||||
FROM order_final_amort
|
||||
-- 账期税费(仅账期内下单且已转正的非全额退费订单)
|
||||
ROUND(SUM(
|
||||
CASE
|
||||
-- 账期内下单 + 已转正 + 部分退费 → 退后订单税额
|
||||
WHEN is_ordered_in_period = 1
|
||||
AND amortization_start_date <= '{period_end}'::date
|
||||
AND is_current_period_refund = 1 AND is_full_refund = 0
|
||||
THEN refunded_tax_amount
|
||||
-- 账期内下单 + 已转正 + 未全额退费(含未退费) → 原订单税额
|
||||
WHEN is_ordered_in_period = 1
|
||||
AND amortization_start_date <= '{period_end}'::date
|
||||
AND (has_refund = 0 OR (is_current_period_refund = 0 AND is_full_refund = 0))
|
||||
THEN tax_amount
|
||||
ELSE 0
|
||||
END
|
||||
)::numeric, 2) AS period_tax
|
||||
|
||||
FROM order_with_days
|
||||
WHERE is_pre_period_full_refund = 0
|
||||
)
|
||||
SELECT
|
||||
total_new_orders AS "订单数",
|
||||
formal_orders AS "正式订单数",
|
||||
trial_orders AS "试用订单数",
|
||||
pre_writeoff_tax AS "冲销前税费",
|
||||
writeoff_tax AS "冲销税费",
|
||||
supplement_tax AS "补充税费",
|
||||
ROUND((pre_writeoff_tax - writeoff_tax + supplement_tax)::numeric, 2) AS "冲销后税费",
|
||||
pre_writeoff_amort AS "冲销前均摊金额",
|
||||
writeoff_amort AS "冲销均摊金额",
|
||||
supplement_amort AS "补充均摊金额",
|
||||
ROUND((pre_writeoff_amort - writeoff_amort + supplement_amort)::numeric, 2) AS "冲销后均摊金额"
|
||||
writeoff_amort AS "冲销历史均摊",
|
||||
writeoff_tax AS "冲销原税款",
|
||||
writeoff_unconfirmed AS "冲销未确认收入",
|
||||
period_amort AS "账期均摊金额",
|
||||
period_tax AS "账期税费",
|
||||
ROUND((period_amort - writeoff_amort)::numeric, 2) AS "冲销后均摊金额",
|
||||
ROUND((period_tax - writeoff_tax)::numeric, 2) AS "冲销后税费"
|
||||
FROM summary_calc;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user