Files
timemaster/backend/app/schemas/reseller.py
T
patrickandClaude Opus 4.8 98cb2f867a
Security Audit / Python Dependency Audit (push) Has been cancelled
Security Audit / Node.js Dependency Audit (push) Has been cancelled
feat: Mandant/Reseller ohne E-Mail anlegbar (Temp-Passwort statt Einladung)
- admin_email bzw. reseller email optional; ohne E-Mail wird interne Login-
  Kennung (<name>@<slug>.local) + einmaliges Temp-Passwort erzeugt, Account
  sofort aktiv, kein Mailversand
- TenantOut/ResellerOut: initial_password (einmalig) ergänzt
- LoginRequest.email: str statt EmailStr (Kennung muss kein zustellbares
  Postfach sein; .local-Domains sind sonst nicht einloggbar)
- Frontend: E-Mail-Felder optional, CredDialog zeigt Login + Temp-Passwort einmalig
- Test: Anlage ohne E-Mail + Login mit generierten Zugangsdaten; 173/173 grün

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 01:34:23 +02:00

77 lines
2.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Schemas für Reseller-Selbstverwaltung und SUPER_ADMIN-Mandantenübersicht.
Wichtig (DSGVO): Reseller sehen ausschließlich Firmen-Stammdaten und Kennzahlen
(z.B. Nutzeranzahl) KEINE personenbezogenen Zeit-/Abwesenheitsdaten.
"""
import uuid
from datetime import datetime
from pydantic import BaseModel, EmailStr, Field
class TenantOut(BaseModel):
"""Eine Firma als Mandant für Reseller- und SUPER_ADMIN-Übersicht."""
model_config = {"from_attributes": True}
id: uuid.UUID
name: str
slug: str
plan: str
is_active: bool
country: str
reseller_id: uuid.UUID | None = None
reseller_name: str | None = None
user_count: int = 0
active_user_count: int = 0
admin_email: str | None = None
created_at: datetime | None = None
# Nur bei Anlage ohne E-Mail befüllt: einmalig anzuzeigende Zugangsdaten
# (Login-Kennung = admin_email, Passwort hier). Sonst None.
initial_password: str | None = None
class TenantCreate(BaseModel):
"""Neue Firma anlegen (durch Reseller oder SUPER_ADMIN).
Es wird automatisch ein erster COMPANY_ADMIN angelegt. Mit admin_email wird
eine Einladung verschickt; ohne admin_email wird eine interne Login-Kennung
plus Temporär-Passwort erzeugt und einmalig zurückgegeben (kein Mailversand).
"""
name: str = Field(min_length=2, max_length=255)
country: str = Field(default="DE", max_length=10)
plan: str = Field(default="trial", max_length=50)
admin_email: EmailStr | None = None
admin_first_name: str = Field(min_length=1, max_length=100)
admin_last_name: str = Field(min_length=1, max_length=100)
class TenantUpdate(BaseModel):
name: str | None = Field(None, min_length=2, max_length=255)
plan: str | None = Field(None, max_length=50)
is_active: bool | None = None
class TenantAssignReseller(BaseModel):
"""SUPER_ADMIN: Firma einem Reseller zuordnen (oder lösen mit null)."""
reseller_id: uuid.UUID | None = None
class ResellerOut(BaseModel):
model_config = {"from_attributes": True}
id: uuid.UUID
email: str
first_name: str
last_name: str
is_active: bool
created_at: datetime | None = None
company_count: int = 0
# Nur bei Anlage ohne E-Mail befüllt: einmalig anzuzeigendes Temporär-Passwort.
initial_password: str | None = None
class ResellerCreate(BaseModel):
email: EmailStr | None = None
first_name: str = Field(min_length=1, max_length=100)
last_name: str = Field(min_length=1, max_length=100)