feat(sdk): API-Referenz Frontend + Backend-Konsolidierung (Shared Utilities, CRUD Factory)
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 32s
CI / test-python-backend-compliance (push) Successful in 30s
CI / test-python-document-crawler (push) Successful in 21s
CI / test-python-dsms-gateway (push) Successful in 18s

- API-Referenz Seite (/sdk/api-docs) mit ~690 Endpoints, Suche, Filter, Modul-Index
- Shared db_utils.py (row_to_dict) + tenant_utils Integration in 6 Route-Dateien
- CRUD Factory (crud_factory.py) fuer zukuenftige Module
- Version-Route Auto-Registration in versioning_utils.py
- 1338 Tests bestanden, -232 Zeilen Duplikat-Code

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-07 17:07:43 +01:00
parent 7ec6b9f6c0
commit 6509e64dd9
19 changed files with 1921 additions and 390 deletions

View File

@@ -10,9 +10,13 @@ import logging
from datetime import datetime
from typing import Optional, List
from fastapi import APIRouter, Depends, HTTPException, Request
from sqlalchemy import text
from sqlalchemy.orm import Session
from classroom_engine.database import get_db
from .tenant_utils import get_tenant_id
logger = logging.getLogger(__name__)
# Table → FK column mapping
@@ -173,3 +177,50 @@ def get_version(
"approved_at": r[8].isoformat() if r[8] else None,
"created_at": r[9].isoformat() if r[9] else None,
}
def register_version_routes(
router: APIRouter,
doc_type: str,
id_param: str = "item_id",
resource_name: str = "Item",
):
"""Register GET /{id}/versions and GET /{id}/versions/{v} on an existing router.
Uses a standardized path param name `item_id` in the generated routes.
The actual URL path parameter can be customized via `id_param`.
Args:
router: The APIRouter to add version routes to
doc_type: One of the keys in VERSION_TABLES
id_param: Path parameter name in the URL (e.g. "obligation_id")
resource_name: Human-readable name for error messages
"""
# Capture doc_type and resource_name in closure
_doc_type = doc_type
_resource_name = resource_name
@router.get(f"/{{{id_param}}}/versions")
async def list_item_versions(
request: Request,
db: Session = Depends(get_db),
tid: str = Depends(get_tenant_id),
):
doc_id = request.path_params[id_param]
return list_versions(db, _doc_type, doc_id, tid)
@router.get(f"/{{{id_param}}}/versions/{{version_number}}")
async def get_item_version(
version_number: int,
request: Request,
db: Session = Depends(get_db),
tid: str = Depends(get_tenant_id),
):
doc_id = request.path_params[id_param]
v = get_version(db, _doc_type, doc_id, version_number, tid)
if not v:
raise HTTPException(
status_code=404,
detail=f"{_resource_name} version {version_number} not found",
)
return v