Local changes: Updated model training, removed debug instrumentation, and configuration improvements
This commit is contained in:
155
backend/api/reports.py
Normal file
155
backend/api/reports.py
Normal file
@@ -0,0 +1,155 @@
|
||||
"""Reports API endpoints for background report generation."""
|
||||
|
||||
from typing import Optional
|
||||
from fastapi import APIRouter, HTTPException, Query
|
||||
from pydantic import BaseModel
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class ReportRequest(BaseModel):
|
||||
"""Request model for report generation."""
|
||||
report_type: str # 'performance', 'trades', 'tax', 'backtest'
|
||||
format: str = "pdf" # 'pdf' or 'csv'
|
||||
year: Optional[int] = None # For tax reports
|
||||
method: Optional[str] = "fifo" # For tax reports: 'fifo', 'lifo'
|
||||
|
||||
|
||||
class ExportRequest(BaseModel):
|
||||
"""Request model for data export."""
|
||||
export_type: str # 'orders', 'positions'
|
||||
|
||||
|
||||
@router.post("/generate")
|
||||
async def generate_report(request: ReportRequest):
|
||||
"""Generate a report in the background.
|
||||
|
||||
This endpoint queues a report generation task and returns immediately.
|
||||
Use /api/tasks/{task_id} to monitor progress.
|
||||
|
||||
Supported report types:
|
||||
- performance: Portfolio performance report
|
||||
- trades: Trade history export
|
||||
- tax: Tax report with capital gains calculation
|
||||
|
||||
Returns:
|
||||
Task ID for monitoring
|
||||
"""
|
||||
try:
|
||||
from src.worker.tasks import generate_report_task
|
||||
|
||||
params = {
|
||||
"format": request.format,
|
||||
}
|
||||
|
||||
if request.report_type == "tax":
|
||||
from datetime import datetime
|
||||
params["year"] = request.year or datetime.now().year
|
||||
params["method"] = request.method
|
||||
|
||||
task = generate_report_task.delay(
|
||||
report_type=request.report_type,
|
||||
params=params
|
||||
)
|
||||
|
||||
return {
|
||||
"task_id": task.id,
|
||||
"status": "queued",
|
||||
"report_type": request.report_type,
|
||||
"format": request.format
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.post("/export")
|
||||
async def export_data(request: ExportRequest):
|
||||
"""Export data in the background.
|
||||
|
||||
This endpoint queues a data export task and returns immediately.
|
||||
Use /api/tasks/{task_id} to monitor progress.
|
||||
|
||||
Supported export types:
|
||||
- orders: Order history
|
||||
- positions: Current/historical positions
|
||||
|
||||
Returns:
|
||||
Task ID for monitoring
|
||||
"""
|
||||
try:
|
||||
from src.worker.tasks import export_data_task
|
||||
|
||||
task = export_data_task.delay(
|
||||
export_type=request.export_type,
|
||||
params={}
|
||||
)
|
||||
|
||||
return {
|
||||
"task_id": task.id,
|
||||
"status": "queued",
|
||||
"export_type": request.export_type
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.get("/list")
|
||||
async def list_reports():
|
||||
"""List available reports in the reports directory."""
|
||||
try:
|
||||
from pathlib import Path
|
||||
import os
|
||||
|
||||
reports_dir = Path(os.path.expanduser("~/.local/share/crypto_trader/reports"))
|
||||
|
||||
if not reports_dir.exists():
|
||||
return {"reports": []}
|
||||
|
||||
reports = []
|
||||
for f in reports_dir.iterdir():
|
||||
if f.is_file():
|
||||
stat = f.stat()
|
||||
reports.append({
|
||||
"name": f.name,
|
||||
"path": str(f),
|
||||
"size": stat.st_size,
|
||||
"created": stat.st_mtime,
|
||||
"type": f.suffix.lstrip(".")
|
||||
})
|
||||
|
||||
# Sort by creation time, newest first
|
||||
reports.sort(key=lambda x: x["created"], reverse=True)
|
||||
|
||||
return {"reports": reports}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.delete("/{filename}")
|
||||
async def delete_report(filename: str):
|
||||
"""Delete a generated report."""
|
||||
try:
|
||||
from pathlib import Path
|
||||
import os
|
||||
|
||||
reports_dir = Path(os.path.expanduser("~/.local/share/crypto_trader/reports"))
|
||||
filepath = reports_dir / filename
|
||||
|
||||
if not filepath.exists():
|
||||
raise HTTPException(status_code=404, detail="Report not found")
|
||||
|
||||
# Security check: ensure the file is actually in reports dir
|
||||
if not str(filepath.resolve()).startswith(str(reports_dir.resolve())):
|
||||
raise HTTPException(status_code=403, detail="Access denied")
|
||||
|
||||
filepath.unlink()
|
||||
|
||||
return {"status": "deleted", "filename": filename}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
Reference in New Issue
Block a user