Backend (Django 4.2 + DRF): - Admin auth with SimpleJWT - Volcengine API client with HMAC-SHA256 signing - IAM user management (create/sync/import/disable/enable) - Billing query with pagination - Feishu webhook notifications (async) - APScheduler for periodic spending checks - AES-256 encrypted credential storage - API key auth for external system integration Frontend (Vue 3 + Element Plus): - Login page - Dashboard with stats overview - IAM user list with per-user threshold config - Billing view with spending progress bars - Alert history with type filtering - Settings page for global config and Volcengine account management Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
60 lines
1.8 KiB
Python
60 lines
1.8 KiB
Python
"""消费查询服务"""
|
|
|
|
import logging
|
|
from decimal import Decimal
|
|
from .volcengine_client import get_billing_client
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class BillingService:
|
|
"""封装火山引擎 Billing API"""
|
|
|
|
def __init__(self, ak: str, sk: str):
|
|
self.client = get_billing_client(ak, sk)
|
|
|
|
def get_spending_by_project(self, bill_period: str, project_name: str = None) -> Decimal:
|
|
"""查询指定项目的消费总额(带分页)"""
|
|
total = Decimal("0")
|
|
offset = 0
|
|
page_size = 300
|
|
|
|
while True:
|
|
params = {
|
|
"BillPeriod": bill_period,
|
|
"Limit": str(page_size),
|
|
"Offset": str(offset),
|
|
"GroupTerm": "0",
|
|
"GroupPeriod": "0",
|
|
"NeedRecordNum": "1",
|
|
}
|
|
result = self.client.call("ListBillDetail", params)
|
|
items = result.get("Result", {}).get("List", [])
|
|
record_num = int(result.get("Result", {}).get("Total", 0))
|
|
|
|
for item in items:
|
|
if project_name and item.get("Project") != project_name:
|
|
continue
|
|
amount = item.get("PayableAmount", "0")
|
|
total += Decimal(str(amount))
|
|
|
|
offset += page_size
|
|
if offset >= record_num or not items:
|
|
break
|
|
|
|
return total
|
|
|
|
def get_bill_overview(self, bill_period: str) -> dict:
|
|
"""获取账单总览(按产品维度)"""
|
|
result = self.client.call("ListBillOverviewByProd", {
|
|
"BillPeriod": bill_period,
|
|
"Limit": "100",
|
|
"NeedRecordNum": "1",
|
|
})
|
|
return result.get("Result", {})
|
|
|
|
def get_balance(self) -> dict:
|
|
"""查询主账号余额"""
|
|
result = self.client.call("QueryBalanceAcct")
|
|
return result.get("Result", {})
|