2025-12-13 12:06:28 +01:00
|
|
|
"""
|
|
|
|
|
Test Module 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("/test_module/items")
|
|
|
|
|
async def get_items():
|
|
|
|
|
"""
|
|
|
|
|
Hent alle items fra template module
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Liste af items
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
# Check safety switch
|
|
|
|
|
read_only = get_module_config("test_module", "READ_ONLY", "true") == "true"
|
|
|
|
|
|
|
|
|
|
# Hent items (bemærk table_prefix)
|
2025-12-16 15:36:11 +01:00
|
|
|
items = execute_query_single(
|
2025-12-13 12:06:28 +01:00
|
|
|
"SELECT * FROM test_module_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("/test_module/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 test_module_items WHERE id = %s",
|
2025-12-16 15:36:11 +01:00
|
|
|
(item_id,))
|
2025-12-13 12:06:28 +01:00
|
|
|
|
|
|
|
|
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("/test_module/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("test_module", "READ_ONLY", "true") == "true"
|
|
|
|
|
dry_run = get_module_config("test_module", "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 test_module_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("/test_module/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("test_module", "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 test_module_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("/test_module/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("test_module", "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 test_module_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("/test_module/health")
|
|
|
|
|
async def health_check():
|
|
|
|
|
"""
|
|
|
|
|
Modul health check
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Health status
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
# Test database connectivity
|
2025-12-16 15:36:11 +01:00
|
|
|
result = execute_query_single("SELECT 1 as test")
|
2025-12-13 12:06:28 +01:00
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
"status": "healthy",
|
|
|
|
|
"module": "test_module",
|
|
|
|
|
"version": "1.0.0",
|
|
|
|
|
"database": "connected" if result else "error",
|
|
|
|
|
"config": {
|
|
|
|
|
"read_only": get_module_config("test_module", "READ_ONLY", "true"),
|
|
|
|
|
"dry_run": get_module_config("test_module", "DRY_RUN", "true")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"❌ Health check failed: {e}")
|
|
|
|
|
return {
|
|
|
|
|
"status": "unhealthy",
|
|
|
|
|
"module": "test_module",
|
|
|
|
|
"error": str(e)
|
|
|
|
|
}
|