Files
feiqiu-ETL/etl_billiards/quality/balance_checker.py
2025-11-18 02:32:00 +08:00

74 lines
2.4 KiB
Python

# -*- coding: utf-8 -*-
"""余额一致性检查器"""
from .base_checker import BaseDataQualityChecker
class BalanceChecker(BaseDataQualityChecker):
"""检查订单、支付、退款的金额一致性"""
def check(self, store_id: int, start_date: str, end_date: str) -> dict:
"""
检查指定时间范围内的余额一致性
验证: 订单总额 = 支付总额 - 退款总额
"""
checks = []
# 查询订单总额
sql_orders = """
SELECT COALESCE(SUM(final_amount), 0) AS total
FROM billiards.fact_order
WHERE store_id = %s
AND order_time >= %s
AND order_time < %s
AND order_status = 'COMPLETED'
"""
order_total = self.db.query(sql_orders, (store_id, start_date, end_date))[0]["total"]
# 查询支付总额
sql_payments = """
SELECT COALESCE(SUM(pay_amount), 0) AS total
FROM billiards.fact_payment
WHERE store_id = %s
AND pay_time >= %s
AND pay_time < %s
AND pay_status = 'SUCCESS'
"""
payment_total = self.db.query(sql_payments, (store_id, start_date, end_date))[0]["total"]
# 查询退款总额
sql_refunds = """
SELECT COALESCE(SUM(refund_amount), 0) AS total
FROM billiards.fact_refund
WHERE store_id = %s
AND refund_time >= %s
AND refund_time < %s
AND refund_status = 'SUCCESS'
"""
refund_total = self.db.query(sql_refunds, (store_id, start_date, end_date))[0]["total"]
# 验证余额
expected_total = payment_total - refund_total
diff = abs(float(order_total) - float(expected_total))
threshold = 0.01 # 1分钱的容差
passed = diff < threshold
checks.append({
"name": "balance_consistency",
"passed": passed,
"message": f"订单总额: {order_total}, 支付-退款: {expected_total}, 差异: {diff}",
"details": {
"order_total": float(order_total),
"payment_total": float(payment_total),
"refund_total": float(refund_total),
"diff": diff
}
})
all_passed = all(c["passed"] for c in checks)
return {
"passed": all_passed,
"checks": checks
}