Backend — new DELETE /purge-all endpoints:
- /api/logs/purge-all → truncate system_logs (immediate, no 30d wait)
- /api/reports/purge-all → cycle_reports + ai_reports
- /api/portfolio/purge-all → portfolio + trade_entry_prices
- /api/analytics/purge-all → pattern_score_history, regime_clusters,
pattern_embeddings, cycle_runs,
macro_regime_history, geo_alert_history
- /api/var/purge-all → var_snapshots + pnl_snapshots
- /api/pattern-lab/purge-all → backtest_lab_runs
Frontend — Config.tsx: new 'Data Management' tab
- PurgeButton component with inline double-confirm (click Purge → confirm)
- Shows table names affected + row count deleted
- 6 purge actions: Logs, AI Reports, Portfolio, Analytics, VaR, Pattern Lab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
53 lines
1.6 KiB
Python
53 lines
1.6 KiB
Python
from fastapi import APIRouter, HTTPException
|
|
from services.database import (
|
|
get_cycle_reports, get_cycle_report, get_latest_cycle_report,
|
|
get_trade_assessments, get_latest_trade_assessments, get_conn,
|
|
)
|
|
|
|
router = APIRouter(prefix="/api/reports", tags=["reports"])
|
|
|
|
|
|
@router.get("/cycle/latest")
|
|
def cycle_report_latest():
|
|
"""Most recent generated cycle report."""
|
|
return {"report": get_latest_cycle_report()}
|
|
|
|
|
|
@router.get("/cycle/list")
|
|
def cycle_report_list(limit: int = 20):
|
|
"""List of cycle report summaries (no full JSON)."""
|
|
return {"reports": get_cycle_reports(limit)}
|
|
|
|
|
|
@router.get("/cycle/{run_id}")
|
|
def cycle_report_detail(run_id: str):
|
|
"""Full cycle report for a specific run_id."""
|
|
report = get_cycle_report(run_id)
|
|
if not report:
|
|
raise HTTPException(404, "Rapport de cycle introuvable")
|
|
return report
|
|
|
|
|
|
@router.get("/assessments/latest")
|
|
def assessments_latest(limit: int = 20):
|
|
"""Latest options technical assessments (one per trade, for Journal badges)."""
|
|
return {"assessments": get_latest_trade_assessments(limit)}
|
|
|
|
|
|
@router.get("/assessments/{run_id}")
|
|
def assessments_by_run(run_id: str):
|
|
"""Options technical assessments for a specific cycle run."""
|
|
return {"assessments": get_trade_assessments(run_id)}
|
|
|
|
|
|
@router.delete("/purge-all")
|
|
def purge_all_reports():
|
|
"""Delete all AI cycle reports and trade assessments."""
|
|
conn = get_conn()
|
|
conn.execute("DELETE FROM cycle_reports")
|
|
conn.execute("DELETE FROM ai_reports")
|
|
n = conn.total_changes
|
|
conn.commit()
|
|
conn.close()
|
|
return {"deleted": n}
|