This commit is contained in:
2026-04-21 10:00:36 +02:00
parent dcce7107ab
commit de8a7284d0
16 changed files with 1772 additions and 485 deletions

View File

@@ -1601,6 +1601,19 @@ def telemetry_ping(data: TelemetryPing, request: Request):
return {"status": "ok"}
def _sync_empfang_practice_record(practice_id: str, admin_email: str, display_name: str) -> None:
"""Legt die Praxis in empfang_practices.json an (idempotent)."""
try:
from empfang_routes import _ensure_practice
except Exception as exc:
print(f"[LICENSE] empfang_routes import failed: {exc}")
return
try:
_ensure_practice(practice_id, name=display_name, admin_email=admin_email or "")
except Exception as exc:
print(f"[LICENSE] _ensure_practice failed: {exc}")
@app.get("/admin/telemetry/stats")
def telemetry_stats():
uptime_seconds = int((datetime.utcnow() - _server_start_time).total_seconds())
@@ -1664,6 +1677,7 @@ def license_status(
status = None
current_period_end = None
customer_email = None
license_practice_id: Optional[str] = None
try:
try:
import stripe_routes # type: ignore
@@ -1677,7 +1691,7 @@ def license_status(
if license_key and license_key.strip():
row = con.execute(
"""
SELECT status, current_period_end, customer_email
SELECT status, current_period_end, customer_email, practice_id
FROM licenses
WHERE upper(license_key) = ?
ORDER BY updated_at DESC
@@ -1688,7 +1702,7 @@ def license_status(
if row is None and email and email.strip():
row = con.execute(
"""
SELECT status, current_period_end, customer_email
SELECT status, current_period_end, customer_email, practice_id
FROM licenses
WHERE lower(customer_email) = ?
ORDER BY updated_at DESC
@@ -1697,29 +1711,17 @@ def license_status(
(email.strip().lower(),),
).fetchone()
if row is None:
n_active = con.execute(
"SELECT COUNT(*) FROM licenses WHERE status = 'active'"
).fetchone()[0]
if n_active == 1:
row = con.execute(
"""
SELECT status, current_period_end, customer_email
FROM licenses
WHERE status = 'active'
LIMIT 1
"""
).fetchone()
print(f"[LICENSE-STATUS] fallback: single active license -> {row[2] if row else 'none'}")
else:
print(f"[LICENSE-STATUS] fallback: {n_active} active licenses, no auto-select")
print("[LICENSE-STATUS] keine eindeutige Lizenzzeile (license_key oder customer_email erforderlich)")
if row:
status = row[0]
current_period_end = int(row[1]) if row[1] is not None else None
customer_email = str(row[2]).strip() if row[2] is not None else None
license_practice_id = str(row[3]).strip() if len(row) > 3 and row[3] else None
except Exception:
status = None
current_period_end = None
customer_email = None
license_practice_id = None
decision = compute_license_decision(current_period_end=current_period_end, status=status)
@@ -1736,11 +1738,14 @@ def license_status(
"used_devices": 0,
"device_allowed": True,
"reason": "ok",
"practice_id": license_practice_id or None,
}
dev_user_key = license_practice_id.strip() if license_practice_id and license_practice_id.strip() else "default"
if device_id and customer_email:
dd = enforce_and_touch_device(
customer_email=customer_email, user_key="default",
customer_email=customer_email, user_key=dev_user_key,
device_id=device_id, db_path=str(db_path),
device_name=device_name, app_version=app_version,
device_fingerprint=device_fingerprint,
@@ -1784,7 +1789,7 @@ def license_activate(
row = con.execute(
"""
SELECT subscription_id, status, current_period_end, customer_email,
allowed_users, devices_per_user
allowed_users, devices_per_user, practice_id
FROM licenses
WHERE upper(license_key) = ?
ORDER BY updated_at DESC
@@ -1796,9 +1801,30 @@ def license_activate(
if not row:
raise HTTPException(status_code=404, detail="Lizenzschluessel ungueltig.")
sub_id, status, cpe, cust_email, au, dpu = row
sub_id, status, cpe, cust_email, au, dpu = row[:6]
practice_id_raw = row[6] if len(row) > 6 else None
current_period_end = int(cpe) if cpe is not None else None
practice_id = (str(practice_id_raw).strip() if practice_id_raw else "") or ""
if not practice_id:
practice_id = f"prac_{uuid.uuid4().hex[:12]}"
try:
with sqlite3.connect(db_path) as con:
con.execute(
"""
UPDATE licenses
SET practice_id = ?, updated_at = ?
WHERE subscription_id = ?
""",
(practice_id, int(time.time()), sub_id),
)
con.commit()
except Exception as exc:
print(f"[LICENSE] practice_id update failed: {exc}")
display_name = (str(cust_email).strip() if cust_email else "") or "Meine Praxis"
_sync_empfang_practice_record(practice_id, str(cust_email or "").strip(), display_name)
decision = compute_license_decision(current_period_end=current_period_end, status=status)
device_id = request.headers.get("X-Device-Id")
@@ -1823,11 +1849,14 @@ def license_activate(
"used_devices": 0,
"device_allowed": True,
"reason": "ok",
"practice_id": practice_id,
}
dev_user_key = practice_id.strip() if practice_id.strip() else "default"
if cust_email:
dd = enforce_and_touch_device(
customer_email=cust_email, user_key="default",
customer_email=cust_email, user_key=dev_user_key,
device_id=device_id, db_path=str(db_path),
device_name=device_name, app_version=app_version,
device_fingerprint=device_fingerprint,