74 lines
2.4 KiB
Python
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
|
|
}
|