bmc_hub/app/modules/solution/backend/router.py
Christian 29acdf3e01 Add tests for new SAG module endpoints and module deactivation
- Implement test script for new SAG module endpoints BE-003 (Tag State Management) and BE-004 (Bulk Operations).
- Create test cases for creating, updating, and bulk operations on cases and tags.
- Add a test for module deactivation to ensure data integrity is maintained.
- Include setup and teardown for tests to clear database state before and after each test.
2026-01-31 23:16:24 +01:00

266 lines
7.0 KiB
Python

"""
Solution Module - API Router
Backend endpoints for template module
"""
from fastapi import APIRouter, HTTPException
from typing import List
import logging
from app.core.database import execute_query, execute_insert, execute_update
from app.core.config import get_module_config
logger = logging.getLogger(__name__)
# APIRouter instance (module_loader kigger efter denne)
router = APIRouter()
@router.get("/solution/items")
async def get_items():
"""
Hent alle items fra template module
Returns:
Liste af items
"""
try:
# Check safety switch
read_only = get_module_config("solution", "READ_ONLY", "true") == "true"
# Hent items (bemærk table_prefix)
items = execute_query_single(
"SELECT * FROM solution_items ORDER BY created_at DESC"
)
return {
"success": True,
"items": items,
"read_only": read_only
}
except Exception as e:
logger.error(f"❌ Error fetching items: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/solution/items/{item_id}")
async def get_item(item_id: int):
"""
Hent enkelt item
Args:
item_id: Item ID
Returns:
Item object
"""
try:
item = execute_query(
"SELECT * FROM solution_items WHERE id = %s",
(item_id,))
if not item:
raise HTTPException(status_code=404, detail="Item not found")
return {
"success": True,
"item": item
}
except HTTPException:
raise
except Exception as e:
logger.error(f"❌ Error fetching item {item_id}: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.post("/solution/items")
async def create_item(name: str, description: str = ""):
"""
Opret nyt item
Args:
name: Item navn
description: Item beskrivelse
Returns:
Nyt item med ID
"""
try:
# Check safety switches
read_only = get_module_config("solution", "READ_ONLY", "true") == "true"
dry_run = get_module_config("solution", "DRY_RUN", "true") == "true"
if read_only:
logger.warning("⚠️ READ_ONLY mode enabled - operation blocked")
return {
"success": False,
"message": "Module is in READ_ONLY mode",
"read_only": True
}
if dry_run:
logger.info(f"🧪 DRY_RUN: Would create item: {name}")
return {
"success": True,
"dry_run": True,
"message": f"DRY_RUN: Item '{name}' would be created"
}
# Opret item
item_id = execute_insert(
"INSERT INTO solution_items (name, description) VALUES (%s, %s)",
(name, description)
)
logger.info(f"✅ Created item {item_id}: {name}")
return {
"success": True,
"item_id": item_id,
"name": name
}
except Exception as e:
logger.error(f"❌ Error creating item: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.put("/solution/items/{item_id}")
async def update_item(item_id: int, name: str = None, description: str = None):
"""
Opdater item
Args:
item_id: Item ID
name: Nyt navn (optional)
description: Ny beskrivelse (optional)
Returns:
Success status
"""
try:
# Check safety switches
read_only = get_module_config("solution", "READ_ONLY", "true") == "true"
if read_only:
logger.warning("⚠️ READ_ONLY mode enabled - operation blocked")
return {
"success": False,
"message": "Module is in READ_ONLY mode"
}
# Build update query dynamically
updates = []
params = []
if name is not None:
updates.append("name = %s")
params.append(name)
if description is not None:
updates.append("description = %s")
params.append(description)
if not updates:
raise HTTPException(status_code=400, detail="No fields to update")
params.append(item_id)
query = f"UPDATE solution_items SET {', '.join(updates)} WHERE id = %s"
affected = execute_update(query, tuple(params))
if affected == 0:
raise HTTPException(status_code=404, detail="Item not found")
logger.info(f"✅ Updated item {item_id}")
return {
"success": True,
"item_id": item_id,
"affected": affected
}
except HTTPException:
raise
except Exception as e:
logger.error(f"❌ Error updating item {item_id}: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.delete("/solution/items/{item_id}")
async def delete_item(item_id: int):
"""
Slet item
Args:
item_id: Item ID
Returns:
Success status
"""
try:
# Check safety switches
read_only = get_module_config("solution", "READ_ONLY", "true") == "true"
if read_only:
logger.warning("⚠️ READ_ONLY mode enabled - operation blocked")
return {
"success": False,
"message": "Module is in READ_ONLY mode"
}
affected = execute_update(
"DELETE FROM solution_items WHERE id = %s",
(item_id,)
)
if affected == 0:
raise HTTPException(status_code=404, detail="Item not found")
logger.info(f"✅ Deleted item {item_id}")
return {
"success": True,
"item_id": item_id
}
except HTTPException:
raise
except Exception as e:
logger.error(f"❌ Error deleting item {item_id}: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/solution/health")
async def health_check():
"""
Modul health check
Returns:
Health status
"""
try:
# Test database connectivity
result = execute_query_single("SELECT 1 as test")
return {
"status": "healthy",
"module": "solution",
"version": "1.0.0",
"database": "connected" if result else "error",
"config": {
"read_only": get_module_config("solution", "READ_ONLY", "true"),
"dry_run": get_module_config("solution", "DRY_RUN", "true")
}
}
except Exception as e:
logger.error(f"❌ Health check failed: {e}")
return {
"status": "unhealthy",
"module": "solution",
"error": str(e)
}