bmc_hub/app/settings/backend/views.py
Christian 3cddb71cec feat: Add Technician Dashboard V1, V2, and V3 with enhanced UI and functionality
- Introduced Technician Dashboard V1 (tech_v1_overview.html) with KPI cards and new cases overview.
- Implemented Technician Dashboard V2 (tech_v2_workboard.html) featuring a workboard layout for daily tasks and opportunities.
- Developed Technician Dashboard V3 (tech_v3_table_focus.html) with a power table for detailed case management.
- Created a dashboard selector page (technician_dashboard_selector.html) for easy navigation between dashboard versions.
- Added user dashboard preferences migration (130_user_dashboard_preferences.sql) to store default dashboard paths.
- Enhanced sag_sager table with assigned group ID (131_sag_assignment_group.sql) for better case management.
- Updated sag_subscriptions table to include cancellation rules and billing dates (132_subscription_cancellation.sql, 134_subscription_billing_dates.sql).
- Implemented subscription staging for CRM integration (136_simply_subscription_staging.sql).
- Added a script to move time tracking section in detail view (move_time_section.py).
- Created a test script for subscription processing (test_subscription_processing.py).
2026-02-17 08:29:05 +01:00

99 lines
3.3 KiB
Python

"""
Settings Frontend Views
"""
from datetime import datetime
from pathlib import Path
from fastapi import APIRouter, Request, HTTPException
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from pydantic import BaseModel
from app.core.config import settings
from app.core.database import get_db_connection, release_db_connection, execute_query_single
router = APIRouter()
templates = Jinja2Templates(directory="app")
@router.get("/settings", response_class=HTMLResponse, tags=["Frontend"])
async def settings_page(request: Request):
"""Render settings page"""
default_dashboard_path = ""
user_id = getattr(request.state, "user_id", None)
if user_id:
try:
row = execute_query_single(
"""
SELECT default_dashboard_path
FROM user_dashboard_preferences
WHERE user_id = %s
""",
(int(user_id),)
)
default_dashboard_path = (row or {}).get("default_dashboard_path") or ""
except Exception:
default_dashboard_path = ""
return templates.TemplateResponse("settings/frontend/settings.html", {
"request": request,
"title": "Indstillinger",
"default_dashboard_path": default_dashboard_path
})
@router.get("/settings/migrations", response_class=HTMLResponse, tags=["Frontend"])
async def migrations_page(request: Request):
"""Render database migrations page"""
migrations_dir = Path(__file__).resolve().parents[3] / "migrations"
migrations = []
if migrations_dir.exists():
for migration_file in sorted(migrations_dir.glob("*.sql")):
stat = migration_file.stat()
migrations.append({
"name": migration_file.name,
"size_kb": round(stat.st_size / 1024, 1),
"modified": datetime.fromtimestamp(stat.st_mtime).strftime("%Y-%m-%d %H:%M")
})
return templates.TemplateResponse("settings/frontend/migrations.html", {
"request": request,
"title": "Database Migrationer",
"migrations": migrations,
"db_user": settings.POSTGRES_USER,
"db_name": settings.POSTGRES_DB,
"db_container": "bmc-hub-postgres",
"is_production": request.url.hostname not in ['localhost', '127.0.0.1', '0.0.0.0']
})
class MigrationExecution(BaseModel):
file_name: str
@router.post("/settings/migrations/execute", tags=["Frontend"])
def execute_migration(payload: MigrationExecution):
"""Execute a migration SQL file"""
migrations_dir = Path(__file__).resolve().parents[3] / "migrations"
migration_file = migrations_dir / payload.file_name
if not migration_file.exists():
raise HTTPException(status_code=404, detail="Migration file not found")
# Determine the container runtime (Podman or Docker)
migration_sql = migration_file.read_text()
conn = get_db_connection()
try:
with conn.cursor() as cursor:
cursor.execute(migration_sql)
conn.commit()
except Exception as exc:
conn.rollback()
raise HTTPException(status_code=500, detail=f"Migration failed: {exc}")
finally:
release_db_connection(conn)
return {"message": "Migration executed successfully"}