konzept billing ext
This commit is contained in:
parent
d5679f6e07
commit
4c7cc4069a
1 changed files with 24 additions and 60 deletions
|
|
@ -46,9 +46,10 @@ Mandant (Kostenstelle)
|
|||
|--------|--------------|--------------|---------|
|
||||
| `PREPAY_MANDATE` | Vorbezahltes Guthaben auf Mandantenebene | Mandant | Gemeinsames Budget für alle User |
|
||||
| `PREPAY_USER` | Vorbezahltes Guthaben pro User | User (im Mandanten-Kontext) | Individuelles Budget |
|
||||
| `CREDIT_POSTPAY` | Nutzung auf Kredit mit Nachzahlung | Mandant (Rechnungsadresse erforderlich) | Monatsrechnung |
|
||||
| `UNLIMITED` | Keine Kostenlimitierung | - | Nur für interne Mandanten |
|
||||
|
||||
**Hinweis:** Das frühere Modell `CREDIT_POSTPAY` ist **nicht mehr** Teil des Produkts. Alte gespeicherte Werte werden beim Lesen auf `PREPAY_MANDATE` normalisiert (ohne DB-Migration).
|
||||
|
||||
### Modell: PREPAY_MANDATE
|
||||
|
||||
```
|
||||
|
|
@ -74,7 +75,7 @@ Mandant "SOHA Treuhand AG"
|
|||
```
|
||||
Mandant "ROOT" (Bootstrap-Mandant)
|
||||
├── Abrechnungsmodell: PREPAY_USER
|
||||
├── Startguthaben für neue User: 10.00 CHF
|
||||
├── Startguthaben bei neuem User nur hier (Root): z. B. 5.00 CHF (defaultUserCredit)
|
||||
└── Nutzer:
|
||||
├── User A: Guthaben 10.00 CHF → verbraucht 3.50 → Rest 6.50 CHF
|
||||
└── User B: Guthaben 25.00 CHF → verbraucht 12.00 → Rest 13.00 CHF
|
||||
|
|
@ -82,26 +83,13 @@ Mandant "ROOT" (Bootstrap-Mandant)
|
|||
|
||||
**Eigenschaften:**
|
||||
- Jeder User hat eigenes Guthaben im Mandanten-Kontext
|
||||
- Neuer User erhält Startguthaben (konfigurierbar)
|
||||
- **Automatisches** Startguthaben nur, wenn ein User dem **Root-Mandanten** neu zugeordnet wird; bei allen anderen Mandanten wird das Nutzerkonto mit 0 CHF angelegt (Aufladung z. B. per Admin/Stripe)
|
||||
- User kann Guthaben aufladen
|
||||
- Bei Guthaben = 0 → AI-Features blockiert für diesen User
|
||||
|
||||
### Modell: CREDIT_POSTPAY
|
||||
### Modell: CREDIT_POSTPAY (entfernt)
|
||||
|
||||
```
|
||||
Mandant "Enterprise AG"
|
||||
├── Abrechnungsmodell: CREDIT_POSTPAY
|
||||
├── Rechnungsadresse: Enterprise AG, Musterstrasse 1, 8000 Zürich
|
||||
├── Kreditlimit: 2000.00 CHF (optional)
|
||||
├── Aktueller Saldo: -450.00 CHF (Schulden)
|
||||
└── Monatsende: Rechnung über 450.00 CHF
|
||||
```
|
||||
|
||||
**Eigenschaften:**
|
||||
- Nutzung ohne Vorauszahlung
|
||||
- Monatliche Abrechnung
|
||||
- Optionales Kreditlimit
|
||||
- Für verifizierte Geschäftskunden
|
||||
Nicht mehr unterstützt. Siehe Hinweis in der Modell-Übersicht.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -110,18 +98,7 @@ Mandant "Enterprise AG"
|
|||
### Neue Tabellen
|
||||
|
||||
```python
|
||||
# modules/datamodels/datamodelBilling.py
|
||||
|
||||
class BillingAddress(BaseModel):
|
||||
"""Rechnungsadresse für CREDIT_POSTPAY Mandanten"""
|
||||
|
||||
company: str # Firmenname
|
||||
street: str # Strasse und Hausnummer
|
||||
zip: str # PLZ
|
||||
city: str # Ort
|
||||
country: str # Land (Default: "CH")
|
||||
vatNumber: Optional[str] # MwSt-Nummer (optional)
|
||||
|
||||
# modules/datamodels/datamodelBilling.py (vereinfacht, Stand Implementierung)
|
||||
|
||||
class BillingAccount(BaseModel):
|
||||
"""Abrechnungskonto pro Mandant oder User-Mandant-Kombination"""
|
||||
|
|
@ -130,8 +107,7 @@ class BillingAccount(BaseModel):
|
|||
mandateId: str # FK → Mandate
|
||||
userId: Optional[str] # FK → User (nur bei PREPAY_USER)
|
||||
accountType: str # MANDATE | USER
|
||||
balance: float # Aktuelles Guthaben/Saldo in CHF
|
||||
creditLimit: Optional[float] # Kreditlimit in CHF (nur CREDIT_POSTPAY)
|
||||
balance: float # Aktuelles Guthaben in CHF (Prepaid)
|
||||
warningThreshold: float # Warnschwelle in CHF
|
||||
lastWarningAt: Optional[datetime] # Letzte Warnung gesendet
|
||||
enabled: bool # Account aktiv
|
||||
|
|
@ -161,15 +137,11 @@ class BillingSettings(BaseModel):
|
|||
|
||||
id: str # UUID
|
||||
mandateId: str # FK → Mandate (UNIQUE)
|
||||
billingModel: str # PREPAY_MANDATE | PREPAY_USER | CREDIT_POSTPAY | UNLIMITED
|
||||
billingModel: str # PREPAY_MANDATE | PREPAY_USER | UNLIMITED
|
||||
|
||||
# Konfiguration
|
||||
defaultUserCredit: float # Startguthaben in CHF für neue User (bei PREPAY_USER)
|
||||
defaultUserCredit: float # Startguthaben nur sinnvoll Root + PREPAY_USER (Bootstrap setzt z. B. 5 CHF); sonst typ. 0
|
||||
warningThresholdPercent: float # Warnschwelle in % (z.B. 10)
|
||||
blockOnZeroBalance: bool # AI blockieren bei Guthaben = 0
|
||||
|
||||
# Rechnungsadresse (erforderlich für CREDIT_POSTPAY)
|
||||
billingAddress: Optional[BillingAddress]
|
||||
|
||||
# Benachrichtigungen
|
||||
notifyEmails: List[str] # Email-Adressen für Monatsberichte
|
||||
|
|
@ -322,13 +294,12 @@ class BillingService:
|
|||
return BillingCheckResult(allowed=True)
|
||||
|
||||
if account.balance < estimatedCost:
|
||||
if self.settings.blockOnZeroBalance:
|
||||
return BillingCheckResult(
|
||||
allowed=False,
|
||||
reason='INSUFFICIENT_BALANCE',
|
||||
currentBalance=account.balance,
|
||||
requiredAmount=estimatedCost
|
||||
)
|
||||
return BillingCheckResult(
|
||||
allowed=False,
|
||||
reason='INSUFFICIENT_BALANCE',
|
||||
currentBalance=account.balance,
|
||||
requiredAmount=estimatedCost
|
||||
)
|
||||
|
||||
return BillingCheckResult(allowed=True, currentBalance=account.balance)
|
||||
|
||||
|
|
@ -473,9 +444,8 @@ def _setupRootMandate():
|
|||
id=generateUuid(),
|
||||
mandateId=rootMandate.id,
|
||||
billingModel='PREPAY_USER',
|
||||
defaultUserCredit=10.0, # 10 CHF Startguthaben
|
||||
defaultUserCredit=5.0, # 5 CHF Startguthaben (siehe DEFAULT_USER_CREDIT_CHF im Code)
|
||||
warningThresholdPercent=20,
|
||||
blockOnZeroBalance=True,
|
||||
notifyOnWarning=True
|
||||
)
|
||||
|
||||
|
|
@ -518,7 +488,7 @@ def _setupNewUserInRoot(user: User):
|
|||
mandateId=rootMandate.id,
|
||||
userId=user.id,
|
||||
accountType='USER',
|
||||
balance=settings.defaultUserCredit, # 10 CHF
|
||||
balance=settings.defaultUserCredit, # z. B. 5 CHF Default
|
||||
warningThreshold=settings.defaultUserCredit * 0.2, # 20%
|
||||
enabled=True
|
||||
)
|
||||
|
|
@ -788,7 +758,6 @@ Das Automation-Editor Modal wird in drei Tabs aufgeteilt:
|
|||
- Übersicht aller Mandanten mit Billing-Status
|
||||
- Abrechnungsmodell ändern
|
||||
- Guthaben manuell aufladen (Stripe-Vorbereitung für Zukunft)
|
||||
- Rechnungsadresse verwalten (für CREDIT_POSTPAY)
|
||||
- Email-Empfänger verwalten
|
||||
|
||||
```
|
||||
|
|
@ -801,7 +770,7 @@ Das Automation-Editor Modal wird in drei Tabs aufgeteilt:
|
|||
│ │ ──────────────────────────────────────────────── │ │
|
||||
│ │ ROOT PREPAY_USER n/a ✓ │ │
|
||||
│ │ SOHA Treuhand PREPAY_MANDATE CHF 299 ✓ │ │
|
||||
│ │ Enterprise AG CREDIT_POSTPAY CHF -450 ✓ │ │
|
||||
│ │ Enterprise AG PREPAY_MANDATE CHF 1200 ✓ │ │
|
||||
│ │ Test GmbH PREPAY_MANDATE CHF 5 ⚠ │ │
|
||||
│ └──────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
|
|
@ -812,11 +781,6 @@ Das Automation-Editor Modal wird in drei Tabs aufgeteilt:
|
|||
│ │ Abrechnungsmodell: [PREPAY_MANDATE ▼] │ │
|
||||
│ │ │ │
|
||||
│ │ Warnschwelle: [10] % │ │
|
||||
│ │ Blockieren bei 0: [✓] │ │
|
||||
│ │ │ │
|
||||
│ │ Rechnungsadresse (für CREDIT_POSTPAY): │ │
|
||||
│ │ [Firma: ________________] [Strasse: _________] │ │
|
||||
│ │ [PLZ: ____] [Ort: _______] [MwSt-Nr: ________] │ │
|
||||
│ │ │ │
|
||||
│ │ Benachrichtigungs-Emails: │ │
|
||||
│ │ [admin@soha.ch, billing@soha.ch ] │ │
|
||||
|
|
@ -975,7 +939,7 @@ PowerOn Platform
|
|||
|
||||
1. **Root-Mandant Setup**
|
||||
- `PREPAY_USER` Modell
|
||||
- 10 CHF Startguthaben für neue User
|
||||
- 5 CHF automatisches Startguthaben nur für neu im Root-Mandanten angelegte User (`DEFAULT_USER_CREDIT_CHF`)
|
||||
- RBAC-Berechtigungen für alle LLM-Provider
|
||||
|
||||
2. **Bestehende User migrieren**
|
||||
|
|
@ -1064,7 +1028,7 @@ Jedes AICore-Plugin definiert seine eigenen Preise via `calculatePriceCHF()`. Di
|
|||
|---------|--------------|
|
||||
| **AICore** | Plugin-System für LLM-Provider Integration |
|
||||
| **Billing Account** | Konto für Guthaben/Saldo (pro Mandant oder User) |
|
||||
| **Billing Address** | Rechnungsadresse, erforderlich für CREDIT_POSTPAY |
|
||||
| **parseBillingModelFromStoredValue** | Mappt unbekannte/legacy `billingModel`-Strings auf `PREPAY_MANDATE` |
|
||||
| **Connector** | AICore-Plugin für einen spezifischen Provider |
|
||||
| **Kostenstelle** | Mandant, dem Kosten zugeordnet werden |
|
||||
| **Mandate** | Mandant/Tenant in der Multi-Tenant-Architektur |
|
||||
|
|
@ -1133,9 +1097,9 @@ frontend_nyla/src/
|
|||
|
||||
### Phase 1: Backend Grundstruktur
|
||||
|
||||
- [ ] `datamodelBilling.py` erstellen (BillingAccount, BillingTransaction, BillingSettings, UsageStatistics, BillingAddress)
|
||||
- [ ] `interfaceDbBilling.py` erstellen (CRUD-Operationen)
|
||||
- [ ] Datenbank-Migrations-Script erstellen
|
||||
- [x] `datamodelBilling.py` (BillingAccount, BillingTransaction, BillingSettings, UsageStatistics)
|
||||
- [x] `interfaceDbBilling.py` (CRUD-Operationen)
|
||||
- [x] Kein separates Migrations-Script nötig (Legacy-Werte werden beim Lesen normalisiert)
|
||||
- [ ] AICore-Plugins: Preise von USD auf CHF umstellen (`calculatepriceCHF` mit echten CHF-Werten)
|
||||
|
||||
### Phase 2: Service-Layer
|
||||
|
|
|
|||
Loading…
Reference in a new issue