fix: scheduler now refreshes last 3 months billing
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m35s

Volcengine bill data has 1-2 day delay. Previously the scheduler
only refreshed current month, so when the month rolls over the
previous month's incomplete snapshot was frozen. Now it refreshes
the current month plus 2 prior months.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
seaislee1209 2026-05-07 18:20:40 +08:00
parent d0a97c3dbe
commit a455753fdc

View File

@ -19,7 +19,19 @@ def check_spending():
config = GlobalConfig.get_solo()
webhook = config.feishu_webhook_url
bill_period = timezone.now().strftime("%Y-%m")
# 同时刷新最近 3 个月的账单(火山账单延迟 1-2 天,月初切换时上月账单还在补全)
now = timezone.now()
bill_periods = []
y, m = now.year, now.month
for _ in range(3):
bill_periods.append(f"{y:04d}-{m:02d}")
m -= 1
if m == 0:
m = 12
y -= 1
current_period = bill_periods[0]
logger.info(f"刷新账单期: {bill_periods}")
for volc_account in VolcAccount.objects.filter(is_active=True):
ak = decrypt(volc_account.access_key_enc)
@ -31,12 +43,14 @@ def check_spending():
billing = BillingService(ak, sk)
iam_svc = IAMService(ak, sk)
# 一次性查询所有项目的消费(避免 N+1 API 调用)
try:
all_project_spending = billing.get_spending_all_projects(bill_period)
except Exception as e:
logger.error(f"批量查询消费失败: {e}")
all_project_spending = {}
# 批量查询最近 3 个月每个项目的消费
spending_by_period = {}
for period in bill_periods:
try:
spending_by_period[period] = billing.get_spending_all_projects(period)
except Exception as e:
logger.error(f"批量查询 {period} 消费失败: {e}")
spending_by_period[period] = {}
users = IAMUser.objects.filter(
volc_account=volc_account,
@ -45,7 +59,7 @@ def check_spending():
for user in users:
try:
# --- 遍历所有开启监测的项目,从批量结果中获取消费 ---
# --- 遍历所有开启监测的项目,更新最近 3 个月的快照 ---
enabled_projects = IAMUserProject.objects.filter(
iam_user=user, monitor_enabled=True
)
@ -54,26 +68,24 @@ def check_spending():
logger.info(f"用户 {user.username} 无开启监测的项目,跳过")
continue
total_spending = Decimal('0')
for project in enabled_projects:
proj_spending = all_project_spending.get(
# 更新当月项目级消费(用于前端显示)
proj_current = spending_by_period.get(current_period, {}).get(
project.project_name, project.current_spending
)
# 更新项目级消费
project.current_spending = proj_spending
project.current_spending = proj_current
project.save(update_fields=['current_spending'])
# 记录项目级月度快照
SpendingRecord.objects.update_or_create(
iam_user=user,
project_name=project.project_name,
bill_period=bill_period,
defaults={'amount': proj_spending},
)
total_spending += proj_spending
# 更新最近 3 个月每个月的快照
for period in bill_periods:
period_data = spending_by_period.get(period, {})
if project.project_name in period_data:
SpendingRecord.objects.update_or_create(
iam_user=user,
project_name=project.project_name,
bill_period=period,
defaults={'amount': period_data[project.project_name]},
)
# 更新子账号总消费
# 累计消费 = 所有月份的所有开启监测项目的消费之和