feat: add admin API for data collection management

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
zephyrdark 2026-02-02 23:57:47 +09:00
parent 8cc2d3fa41
commit d2c5f91b2b
3 changed files with 131 additions and 2 deletions

View File

@ -1,3 +1,4 @@
from app.api.auth import router as auth_router
from app.api.admin import router as admin_router
__all__ = ["auth_router"]
__all__ = ["auth_router", "admin_router"]

127
backend/app/api/admin.py Normal file
View File

@ -0,0 +1,127 @@
"""
Admin API for data collection management.
"""
from typing import List
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from pydantic import BaseModel
from app.core.database import get_db
from app.api.deps import CurrentUser
from app.models.stock import JobLog
from app.services.collectors import (
StockCollector,
SectorCollector,
PriceCollector,
ValuationCollector,
)
router = APIRouter(prefix="/api/admin", tags=["admin"])
class JobLogResponse(BaseModel):
id: int
job_name: str
status: str
started_at: str
finished_at: str | None
records_count: int | None
error_msg: str | None
class Config:
from_attributes = True
class CollectResponse(BaseModel):
message: str
job_id: int
@router.post("/collect/stocks", response_model=CollectResponse)
async def collect_stocks(
current_user: CurrentUser,
db: Session = Depends(get_db),
biz_day: str = None,
):
"""Collect stock master data from KRX."""
try:
collector = StockCollector(db, biz_day=biz_day)
job_log = collector.run()
return CollectResponse(
message=f"Stock collection completed: {job_log.records_count} records",
job_id=job_log.id,
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/collect/sectors", response_model=CollectResponse)
async def collect_sectors(
current_user: CurrentUser,
db: Session = Depends(get_db),
biz_day: str = None,
):
"""Collect sector classification data from WISEindex."""
try:
collector = SectorCollector(db, biz_day=biz_day)
job_log = collector.run()
return CollectResponse(
message=f"Sector collection completed: {job_log.records_count} records",
job_id=job_log.id,
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/collect/prices", response_model=CollectResponse)
async def collect_prices(
current_user: CurrentUser,
db: Session = Depends(get_db),
start_date: str = None,
end_date: str = None,
):
"""Collect price data using pykrx."""
try:
collector = PriceCollector(db, start_date=start_date, end_date=end_date)
job_log = collector.run()
return CollectResponse(
message=f"Price collection completed: {job_log.records_count} records",
job_id=job_log.id,
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/collect/valuations", response_model=CollectResponse)
async def collect_valuations(
current_user: CurrentUser,
db: Session = Depends(get_db),
biz_day: str = None,
):
"""Collect valuation data from KRX."""
try:
collector = ValuationCollector(db, biz_day=biz_day)
job_log = collector.run()
return CollectResponse(
message=f"Valuation collection completed: {job_log.records_count} records",
job_id=job_log.id,
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/collect/status", response_model=List[JobLogResponse])
async def get_collection_status(
current_user: CurrentUser,
db: Session = Depends(get_db),
limit: int = 20,
):
"""Get recent job execution status."""
jobs = (
db.query(JobLog)
.order_by(JobLog.started_at.desc())
.limit(limit)
.all()
)
return jobs

View File

@ -4,7 +4,7 @@ Galaxy-PO Backend API
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.api import auth_router
from app.api import auth_router, admin_router
app = FastAPI(
title="Galaxy-PO API",
@ -22,6 +22,7 @@ app.add_middleware(
# Include routers
app.include_router(auth_router)
app.include_router(admin_router)
@app.get("/health")