Files
All-in-one-Financial-Analysis/atlas-terminal/server/routers/dart.py
T
shawnkim1997andClaude Opus 4.6 51cbaf7f8d feat: major codebase audit — 21 routers, 37 services, 12 pages fully documented
- Add missing numpy, scipy, dbnomics to requirements.txt (fixes ImportError on fresh install)
- Sync claude.md with actual codebase: §3 file structure (37 services, 21 routers),
  §5 API endpoints (92 routes), §6 frontend pages (12), §13 TODO status
- Update README.md with current architecture (92 API routes, 21 routers, 37 services),
  multi-asset overview, research grid, macro dashboard, screener+backtest,
  multi-jurisdiction filings, and 2026-03-26 changelog entry
- Add new routers: dart, edinet, fmp, macro, research
- Add new services: cache, dart_fetcher, dart_filing_service, economic_calendar,
  ecos_fetcher, edinet_filing_service, fmp_client, global_macro_quadrant,
  kpi_history_service, macro_cycle, macro_fetcher, oecd_cycle,
  peer_comparison_service, research_dashboard, smart_money_service, yield_fx_service
- Add new frontend: macro page, screener+backtest, research grid components,
  overview (Equity/ETF/Commodity), filings (SEC/DART/EDINET), error boundaries
- Remove 6 unused services: copilot_context, crypto_fetcher, fx_fetcher,
  gemini_analysis, market_data, technical_analysis
- Remove obsolete docs: .agent/, AGENT.md, ATLAS_EVALUATION.md, docs/

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 21:39:07 +00:00

73 lines
2.4 KiB
Python

"""DART Korea — company search (optional ``DART_API_KEY``) + 사업보고서 sections."""
from typing import Any, Dict, List
from fastapi import APIRouter, HTTPException, Query
from server.models.schemas import EdgarSectionsResponse
from server.services.dart_fetcher import dart_is_configured, search_corporations
from server.services.dart_filing_service import (
dart_filing_is_configured,
get_dart_sections,
)
router = APIRouter()
@router.get("/search", summary="Search DART corporations by name")
async def dart_search(
q: str = Query(..., min_length=1, description="Company name (KO/EN)"),
limit: int = Query(20, ge=1, le=50),
) -> Dict[str, Any]:
if not dart_is_configured():
return {
"configured": False,
"message": "Set DART_API_KEY in the environment.",
"results": [],
}
rows: List[Dict[str, Any]] = search_corporations(q, limit=limit)
return {"configured": True, "query": q, "count": len(rows), "results": rows}
@router.get(
"/sections/{ticker}",
response_model=EdgarSectionsResponse,
summary="Korean 사업보고서 sections (DART Open API)",
)
async def dart_sections(
ticker: str,
include_html: bool = Query(
False,
description="Include HTML fragment for in-app viewer",
),
):
"""Download latest annual report (사업보고서) and map to SEC-like section keys."""
if not dart_filing_is_configured():
return EdgarSectionsResponse(
source="dart",
configured=False,
message="Set DART_API_KEY in the environment (Open DART).",
status="unconfigured",
)
try:
sections, status, html_frag, _rcept = get_dart_sections(ticker)
except ValueError as exc:
raise HTTPException(status_code=422, detail=str(exc)) from exc
except FileNotFoundError as exc:
raise HTTPException(status_code=404, detail=str(exc)) from exc
except Exception as exc:
raise HTTPException(status_code=500, detail=f"DART download failed: {exc}") from exc
html_payload = html_frag if include_html else ""
return EdgarSectionsResponse(
source="dart",
configured=True,
status=status,
item1a=sections.get("item1a", ""),
item3=sections.get("item3", ""),
item7=sections.get("item7", ""),
item8=sections.get("item8", ""),
item9a=sections.get("item9a", ""),
html=html_payload,
)