diff --git a/backend/main.py b/backend/main.py index b6e2512..a6ced52 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1,13 +1,37 @@ from contextlib import asynccontextmanager +from pathlib import Path + from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware +from modules.config_manager import ConfigManager +from modules.odoo_client import OdooClient + +CONFIG_DIR = Path(__file__).parent / "config" + +app_config = ConfigManager( + settings_path=str(CONFIG_DIR / "settings.yaml"), + services_path=str(CONFIG_DIR / "services.yaml"), +) + +settings = app_config.get_settings() +odoo_settings = settings.get("odoo", {}) + +odoo_client = OdooClient( + url=odoo_settings.get("url", "http://localhost:8069"), + database=odoo_settings.get("database", "odoo"), + username=odoo_settings.get("username", "admin"), + password=odoo_settings.get("password", "admin"), +) + @asynccontextmanager async def lifespan(app: FastAPI): - # Startup + try: + await odoo_client.authenticate() + except Exception as e: + print(f"Warning: Could not connect to Odoo: {e}") yield - # Shutdown app = FastAPI(title="TV Dashboard API", lifespan=lifespan) @@ -19,7 +43,14 @@ app.add_middleware( allow_headers=["*"], ) +from routers import network, tasks, calendar, services + +app.include_router(network.router) +app.include_router(tasks.router) +app.include_router(calendar.router) +app.include_router(services.router) + @app.get("/api/health") async def health(): - return {"status": "ok"} + return {"status": "ok", "odoo_connected": odoo_client.uid is not None} diff --git a/backend/routers/calendar.py b/backend/routers/calendar.py new file mode 100644 index 0000000..6fe677d --- /dev/null +++ b/backend/routers/calendar.py @@ -0,0 +1,15 @@ +from datetime import datetime, timedelta +from fastapi import APIRouter, Query + +router = APIRouter(prefix="/api/calendar", tags=["calendar"]) + + +@router.get("/events") +async def get_events( + days: int = Query(default=7, ge=1, le=30), +): + from main import odoo_client + today = datetime.now().strftime("%Y-%m-%d") + end = (datetime.now() + timedelta(days=days)).strftime("%Y-%m-%d") + events = await odoo_client.get_calendar_events(date_from=today, date_to=end) + return {"events": events, "date_from": today, "date_to": end} diff --git a/backend/routers/network.py b/backend/routers/network.py new file mode 100644 index 0000000..690e8b2 --- /dev/null +++ b/backend/routers/network.py @@ -0,0 +1,36 @@ +from fastapi import APIRouter, Depends +from modules.config_manager import ConfigManager +from modules.network_scanner import NetworkScanner + +router = APIRouter(prefix="/api/network", tags=["network"]) + + +def get_config() -> ConfigManager: + from main import app_config + return app_config + + +@router.get("/topology") +async def get_topology(config: ConfigManager = Depends(get_config)): + scan_config = config.get_network_scan_config() + configured_nodes = config.get_nodes() + + scanner = NetworkScanner(subnet=scan_config.get("subnet", "192.168.1.0/24")) + + if scan_config.get("enabled", False): + try: + scan_data = scanner.scan() + discovered = scanner.parse_scan_results(scan_data) + nodes = scanner.merge_with_config(discovered, configured_nodes) + except Exception: + nodes = [{**n, "status": "unknown"} for n in configured_nodes] + else: + nodes = [{**n, "status": "unknown"} for n in configured_nodes] + + # Ping all nodes for current status + ips = [n["ip"] for n in nodes] + statuses = await scanner.ping_all(ips) + for node in nodes: + node["status"] = "up" if statuses.get(node["ip"], False) else "down" + + return {"nodes": nodes, "scan_enabled": scan_config.get("enabled", False)} diff --git a/backend/routers/services.py b/backend/routers/services.py new file mode 100644 index 0000000..a3b2441 --- /dev/null +++ b/backend/routers/services.py @@ -0,0 +1,13 @@ +from fastapi import APIRouter + +router = APIRouter(prefix="/api/services", tags=["services"]) + + +@router.get("/config") +async def get_config(): + from main import app_config + settings = app_config.get_settings() + return { + "display": settings.get("display", {}), + "refresh": settings.get("refresh", {}), + } diff --git a/backend/routers/tasks.py b/backend/routers/tasks.py new file mode 100644 index 0000000..b243de6 --- /dev/null +++ b/backend/routers/tasks.py @@ -0,0 +1,33 @@ +from fastapi import APIRouter + +router = APIRouter(prefix="/api/tasks", tags=["tasks"]) + + +@router.get("/by-project") +async def get_tasks_by_project(): + from main import odoo_client + projects = await odoo_client.get_projects() + tasks = await odoo_client.get_tasks() + + result = [] + for project in projects: + project_tasks = [t for t in tasks if t.get("project_id") and t["project_id"][0] == project["id"]] + stages: dict[str, list] = {} + for task in project_tasks: + stage_name = task["stage_id"][1] if task.get("stage_id") else "Sin etapa" + stages.setdefault(stage_name, []).append({ + "id": task["id"], + "name": task["name"], + "assigned": task.get("user_ids", []), + "priority": task.get("priority", "0"), + "deadline": task.get("date_deadline"), + "kanban_state": task.get("kanban_state", "normal"), + }) + result.append({ + "id": project["id"], + "name": project["name"], + "color": project.get("color", 0), + "stages": stages, + }) + + return {"projects": result}