feat: FF CSV bundled in image + auto-import on startup

- forex_factory_cache.csv moved to backend/ (Docker build context)
  → available at /app/forex_factory_cache.csv inside container
- main.py startup: auto-imports CSV in background thread if ff_calendar empty
  (idempotent — skips if rows already present)
- CSV path candidates: /app/ (Docker) → /tmp/ (upload) → local dev paths
- CalendarPage: remove Upload CSV + Import into DB buttons
  → replaced by auto-import status indicator + Sync Live only

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OpenSquared
2026-06-26 16:58:31 +02:00
parent afbfeff468
commit 7aca0c307a
4 changed files with 83491 additions and 88 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -95,6 +95,33 @@ def startup():
from services.institutional_scheduler import start_institutional_scheduler
start_institutional_scheduler()
# Auto-import Forex Factory CSV if ff_calendar table is empty
import threading
def _auto_import_ff():
import time, os
from services.database import get_conn
from routers.eco import _find_csv, _run_ff_import, _ff_import_status
try:
conn = get_conn()
count = conn.execute("SELECT COUNT(*) FROM ff_calendar").fetchone()[0]
conn.close()
if count > 0:
print(f"[Startup] ff_calendar already has {count} rows — skipping auto-import", flush=True)
return
csv_path = _find_csv()
if not csv_path:
print("[Startup] forex_factory_cache.csv not found — skipping auto-import", flush=True)
return
print(f"[Startup] ff_calendar empty — auto-importing {csv_path}", flush=True)
_run_ff_import(csv_path)
result = _ff_import_status.get("last_result") or {}
inserted = result.get("inserted", 0)
print(f"[Startup] FF auto-import done — {inserted} rows inserted", flush=True)
except Exception as e:
print(f"[Startup] FF auto-import error: {e}", flush=True)
threading.Thread(target=_auto_import_ff, daemon=True).start()
@app.on_event("shutdown")
def shutdown():

View File

@@ -296,11 +296,12 @@ def upcoming_events() -> List[Dict[str, Any]]:
_ff_import_status: Dict[str, Any] = {"running": False, "last_result": None}
_ff_sync_status: Dict[str, Any] = {"running": False, "last_result": None}
# CSV may sit at project root (local dev) or in /tmp (uploaded via browser on server)
# CSV search order: Docker image (/app), uploaded to /tmp, local dev paths
_FF_CSV_CANDIDATES = [
"/tmp/forex_factory_cache.csv",
os.path.join(os.path.dirname(__file__), "..", "forex_factory_cache.csv"),
os.path.join(os.path.dirname(__file__), "..", "..", "forex_factory_cache.csv"),
"/app/forex_factory_cache.csv", # Docker (backend/ copied to /app)
"/tmp/forex_factory_cache.csv", # browser upload
os.path.join(os.path.dirname(__file__), "..", "forex_factory_cache.csv"), # local dev (backend/)
os.path.join(os.path.dirname(__file__), "..", "..", "forex_factory_cache.csv"), # project root
]