Block A: License-Check + Credits-Tracking fuer Enhance und Chat

- Neuer Helper charge_usage_to_tenant() in services/license_service.py:
  UPSERT in token_usage_monthly und Credits-Abzug aus licenses.credits_used.
  Wiederverwendbar fuer alle Claude-Call-Verursacher.
- Orchestrator: Inline-Buchungslogik (35 Zeilen) durch Helper-Aufruf ersetzt.
- routers/incidents.py POST /enhance-description: require_writable_license
  statt get_current_user, db_dependency hinzugefuegt, Credits-Buchung mit
  source="enhance" nach jedem Claude-Call.
- routers/chat.py POST /: analog require_writable_license + Credits-Buchung
  mit source="chat". _call_claude_chat() gibt jetzt zusaetzlich ClaudeUsage
  zurueck.

Abgelaufene/gesperrte Lizenzen koennen damit keine Haiku-Calls mehr ausloesen,
und alle Kosten werden konsistent auf Tenant-Ebene verbucht.
Dieser Commit ist enthalten in:
claude-dev
2026-04-23 17:49:32 +00:00
Ursprung c8a8e10020
Commit e8ac0d0c50
4 geänderte Dateien mit 119 neuen und 40 gelöschten Zeilen

Datei anzeigen

@@ -241,11 +241,13 @@ _enhance_logger = logging.getLogger("osint.enhance")
@router.post("/enhance-description")
async def enhance_description(
data: DescriptionEnhanceRequest,
current_user: dict = Depends(get_current_user),
current_user: dict = Depends(require_writable_license),
db: aiosqlite.Connection = Depends(db_dependency),
):
"""Generiert eine strukturierte Beschreibung per KI aus dem Titel."""
from agents.claude_client import call_claude
from config import CLAUDE_MODEL_FAST
from services.license_service import charge_usage_to_tenant
template = ENHANCE_PROMPT_RESEARCH if data.type == "research" else ENHANCE_PROMPT_ADHOC
context = data.description.strip() if data.description and data.description.strip() else "Kein Kontext angegeben"
@@ -257,6 +259,8 @@ async def enhance_description(
f"Beschreibung generiert fuer \"{data.title[:50]}\": "
f"{usage.input_tokens}in/{usage.output_tokens}out"
)
await charge_usage_to_tenant(db, current_user.get("tenant_id"), usage, source="enhance")
await db.commit()
return {"description": result.strip()}
except Exception as e:
_enhance_logger.error(f"Beschreibung generieren fehlgeschlagen: {e}")