新增同步 ext_data(概念/行业) 和本地化财务数据展示
- 将 ext_data 加入 SYNCABLE_PARTS,概念/行业分类数据可从 local 同步到 serve - 去掉 serve 财务分析接口的 Cap.FINANCIAL 能力门控,依赖本地 parquet 文件来展示数据 - serve 财务分析前端在无 API Key 但有同步数据时正常展示,隐藏同步按钮 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -20,11 +20,7 @@ router = APIRouter(prefix="/api/financials", tags=["financials"])
|
||||
|
||||
@router.get("/status")
|
||||
def financial_status(request: Request):
|
||||
"""返回各财务表的同步状态。无需 FINANCIAL 权限(前端根据 available 决定是否展示)。"""
|
||||
capset = request.app.state.capabilities
|
||||
if not capset.has(Cap.FINANCIAL):
|
||||
return {"available": False, "tables": {}}
|
||||
|
||||
"""返回各财务表的同步状态。"""
|
||||
data_dir = request.app.state.repo.store.data_dir
|
||||
tables = {}
|
||||
|
||||
@@ -42,15 +38,16 @@ def financial_status(request: Request):
|
||||
else:
|
||||
tables[table] = {"rows": 0, "symbols": 0}
|
||||
|
||||
capset = request.app.state.capabilities
|
||||
has_cap = capset.has(Cap.FINANCIAL)
|
||||
fs = getattr(request.app.state, "financial_scheduler", None)
|
||||
last_sync = fs.last_sync if fs else {}
|
||||
has_data = any(t.get("rows", 0) > 0 for t in tables.values())
|
||||
|
||||
return {
|
||||
"available": True,
|
||||
"available": has_cap or has_data,
|
||||
"tables": tables,
|
||||
"last_sync": last_sync,
|
||||
# 服务端是否正在同步(手动触发)——前端据此显示"同步中"并防重复点击,
|
||||
# 且刷新页面后仍能正确反映服务端状态。
|
||||
"syncing": bool(fs and fs.is_syncing),
|
||||
}
|
||||
|
||||
@@ -58,9 +55,6 @@ def financial_status(request: Request):
|
||||
@router.get("/metrics")
|
||||
def get_metrics(request: Request, symbol: str | None = None):
|
||||
"""查询核心财务指标。"""
|
||||
capset = request.app.state.capabilities
|
||||
capset.require(Cap.FINANCIAL)
|
||||
|
||||
df = get_financial_df(request.app.state.repo.store.data_dir, "metrics")
|
||||
if df.is_empty():
|
||||
return {"data": []}
|
||||
@@ -72,9 +66,6 @@ def get_metrics(request: Request, symbol: str | None = None):
|
||||
@router.get("/income")
|
||||
def get_income(request: Request, symbol: str | None = None):
|
||||
"""查询利润表。"""
|
||||
capset = request.app.state.capabilities
|
||||
capset.require(Cap.FINANCIAL)
|
||||
|
||||
df = get_financial_df(request.app.state.repo.store.data_dir, "income")
|
||||
if df.is_empty():
|
||||
return {"data": []}
|
||||
@@ -86,9 +77,6 @@ def get_income(request: Request, symbol: str | None = None):
|
||||
@router.get("/balance-sheet")
|
||||
def get_balance_sheet(request: Request, symbol: str | None = None):
|
||||
"""查询资产负债表。"""
|
||||
capset = request.app.state.capabilities
|
||||
capset.require(Cap.FINANCIAL)
|
||||
|
||||
df = get_financial_df(request.app.state.repo.store.data_dir, "balance_sheet")
|
||||
if df.is_empty():
|
||||
return {"data": []}
|
||||
@@ -100,9 +88,6 @@ def get_balance_sheet(request: Request, symbol: str | None = None):
|
||||
@router.get("/cash-flow")
|
||||
def get_cash_flow(request: Request, symbol: str | None = None):
|
||||
"""查询现金流量表。"""
|
||||
capset = request.app.state.capabilities
|
||||
capset.require(Cap.FINANCIAL)
|
||||
|
||||
df = get_financial_df(request.app.state.repo.store.data_dir, "cash_flow")
|
||||
if df.is_empty():
|
||||
return {"data": []}
|
||||
|
||||
Reference in New Issue
Block a user