feat: add API routers for network, tasks, calendar, and services
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,13 +1,37 @@
|
|||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
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
|
@asynccontextmanager
|
||||||
async def lifespan(app: FastAPI):
|
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
|
yield
|
||||||
# Shutdown
|
|
||||||
|
|
||||||
|
|
||||||
app = FastAPI(title="TV Dashboard API", lifespan=lifespan)
|
app = FastAPI(title="TV Dashboard API", lifespan=lifespan)
|
||||||
@@ -19,7 +43,14 @@ app.add_middleware(
|
|||||||
allow_headers=["*"],
|
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")
|
@app.get("/api/health")
|
||||||
async def health():
|
async def health():
|
||||||
return {"status": "ok"}
|
return {"status": "ok", "odoo_connected": odoo_client.uid is not None}
|
||||||
|
|||||||
15
backend/routers/calendar.py
Normal file
15
backend/routers/calendar.py
Normal file
@@ -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}
|
||||||
36
backend/routers/network.py
Normal file
36
backend/routers/network.py
Normal file
@@ -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)}
|
||||||
13
backend/routers/services.py
Normal file
13
backend/routers/services.py
Normal file
@@ -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", {}),
|
||||||
|
}
|
||||||
33
backend/routers/tasks.py
Normal file
33
backend/routers/tasks.py
Normal file
@@ -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}
|
||||||
Reference in New Issue
Block a user