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

@@ -21,6 +21,7 @@ import smtplib
import sqlite3
import string
import time
import uuid
from dataclasses import dataclass
from decimal import Decimal
from email.mime.multipart import MIMEMultipart
@@ -115,6 +116,8 @@ def _ensure_storage() -> None:
con.execute("ALTER TABLE licenses ADD COLUMN current_period_end INTEGER")
if "license_key" not in cols:
con.execute("ALTER TABLE licenses ADD COLUMN license_key TEXT")
if "practice_id" not in cols:
con.execute("ALTER TABLE licenses ADD COLUMN practice_id TEXT")
con.commit()
@@ -409,6 +412,59 @@ def _log_event(kind: str, payload: Dict[str, Any]) -> None:
f.write(json.dumps(rec, ensure_ascii=False, default=_decimal_default) + "\n")
def _new_practice_id() -> str:
"""Gleiches Format wie empfang_routes._generate_practice_id (Mandanten-ID)."""
return f"prac_{uuid.uuid4().hex[:12]}"
def _sync_empfang_practice_from_license(
practice_id: str,
customer_email: Optional[str],
display_name: str,
) -> None:
"""Empfang-Praxisdatei mit SQLite-Lizenz synchronisieren (eine Wahrheit)."""
pid = (practice_id or "").strip()
if not pid:
return
try:
from empfang_routes import _ensure_practice
except Exception as exc:
print(f"[STRIPE] empfang_routes Import: {exc}")
return
try:
em = (customer_email or "").strip()
name = (display_name or "").strip() or (em.split("@")[0] if "@" in em else "Meine Praxis")
_ensure_practice(pid, name=name, admin_email=em)
except Exception as exc:
print(f"[STRIPE] _ensure_practice: {exc}")
def lookup_practice_id_for_license_email(email: str) -> Optional[str]:
"""Liefert die serverseitig gespeicherte practice_id zur Kunden-E-Mail (Lizenz ↔ Praxis)."""
_ensure_storage()
e = (email or "").strip().lower()
if not e:
return None
try:
with sqlite3.connect(DB_PATH) as con:
row = con.execute(
"""
SELECT practice_id FROM licenses
WHERE lower(customer_email) = ?
AND practice_id IS NOT NULL
AND trim(practice_id) != ''
ORDER BY updated_at DESC
LIMIT 1
""",
(e,),
).fetchone()
if not row or not row[0]:
return None
return str(row[0]).strip()
except Exception:
return None
def _upsert_license(
*,
subscription_id: str,
@@ -422,27 +478,36 @@ def _upsert_license(
current_period_end: Optional[int],
license_key: Optional[str] = None,
) -> str:
"""Upsert license row. Returns the license_key (generated if not yet set)."""
"""Upsert license row. Returns the license_key (generated if not yet set).
Jede Lizenzzeile erhält spätestens hier eine stabile practice_id (Mandant),
damit Stripe-Webhook und Desktop/Empfang dieselbe ID nutzen.
"""
now = int(time.time())
with sqlite3.connect(DB_PATH) as con:
existing_key = None
existing_pid = ""
row = con.execute(
"SELECT license_key FROM licenses WHERE subscription_id = ?",
"SELECT license_key, practice_id FROM licenses WHERE subscription_id = ?",
(subscription_id,),
).fetchone()
if row and row[0]:
existing_key = row[0]
if row:
if row[0]:
existing_key = row[0]
if row[1]:
existing_pid = str(row[1]).strip()
final_key = existing_key or license_key or _generate_license_key()
final_pid = existing_pid or _new_practice_id()
con.execute(
"""
INSERT INTO licenses(
subscription_id, customer_id, status, lookup_key,
allowed_users, devices_per_user, customer_email, client_reference_id,
current_period_end, updated_at, license_key
current_period_end, updated_at, license_key, practice_id
)
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(subscription_id) DO UPDATE SET
customer_id=excluded.customer_id,
status=excluded.status,
@@ -453,7 +518,12 @@ def _upsert_license(
client_reference_id=COALESCE(excluded.client_reference_id, client_reference_id),
current_period_end=COALESCE(excluded.current_period_end, current_period_end),
updated_at=excluded.updated_at,
license_key=COALESCE(license_key, excluded.license_key)
license_key=COALESCE(license_key, excluded.license_key),
practice_id=CASE
WHEN licenses.practice_id IS NOT NULL AND trim(licenses.practice_id) != ''
THEN licenses.practice_id
ELSE excluded.practice_id
END
""",
(
subscription_id,
@@ -467,9 +537,21 @@ def _upsert_license(
current_period_end,
now,
final_key,
final_pid,
),
)
con.commit()
row2 = con.execute(
"SELECT practice_id, customer_email FROM licenses WHERE subscription_id = ?",
(subscription_id,),
).fetchone()
if row2:
pid_s = str(row2[0]).strip() if row2[0] else ""
em = (str(row2[1]).strip() if row2[1] else "") or (customer_email or "").strip()
if pid_s:
disp = em.split("@")[0] if "@" in em else "Meine Praxis"
_sync_empfang_practice_from_license(pid_s, em or None, disp)
return final_key