Abonnementdefinition und Bereitstellung – Systembeschreibung
Datenmodell von Definitionen, Tarifverknüpfungen und Positionen, die Lösch-und-Neuschreib-Logik beim Speichern, automatische Elternfunktionen und die Übertragung auf Benutzer.
Überblick
Eine Definition ist ein Abonnementangebot. Auf diesem Bildschirm kommen Funktionen in Tarife; die Bereitstellungsbibliothek (Dlbtprovision) überträgt den Inhalt auf die Zuweisungszeilen der Benutzer. Die Tabellennamen tragen in der Datenbank das eigene Präfix der Installation.
Datenmodell
| Tabelle | Hauptfelder |
|---|---|
subscription_definition | name, code, company_client_id (Eigentümer-Mandant), description, status, enabled, sort_order, version, valid_from, valid_to |
subscription_definition_to_store | Shops |
subscription_definition_plan | wählbare Tarife: billing_cycle (monthly, annual), subscription_price, general_discount, annual_discount, Gültigkeit, Status, Sortierung |
subscription_definition_item | je Tarif: item_type (feature, product, service), item_id, enabled, limit_type (count, amount, metered, unlimited), limit_value, limit_unit, limit_period, included_quantity, unit_price, overage_price, discount (0–100), currency, note; im migrierten Schema reset_rule, rollover, overage_rule, pricing_rule, is_unlimited, priority |
Speichern
- Berechtigung: Formular
canAction(edit); SpeicherncanSave($route, definition_id). - Leerer Name →
error_name; der Mandant muss eine aktive, einer Gruppe zugeordnete Firma im Inhaltsbereich des Benutzers sein (error_client). - Positionen nur für der Definition zugeordnete Tarife; bei Positionen ohne Limit werden die Limitfelder geleert; Rabatt auf 0–100 begrenzt.
- Das Modell legt die Definition an oder aktualisiert sie, löscht und schreibt Tarif- und Positionszeilen neu und ersetzt die Shops.
parentMap()läuft die Kettefeature.parent_feature_idhinauf (bis 20 Ebenen, zyklusgeschützt) und ergänzt fehlende Eltern im selben Tarif alsenabled = 1,unlimited.- Abschließend
dlbtentitlement->flush().
Endpunkte: definition.itemsearch (Dlbtbilling::searchItems: jede aktive Funktion unabhängig von der Einstufung, höchstens 12 Treffer, bereits aufgenommene Positionen werden nach der Abfrage gefiltert), definition.plansearch, definition.plans (vom Auswahlfeld „Parameter laden“ des Funktionsberechtigungs-Bildschirms aufgerufen). Die vorgeladene Liste assignable enthält nur BASE- und SUBSCRIPTION-Funktionen.
Löschen
Gibt es Zuweisungszeilen mit dieser definition_id, wird nicht gelöscht (error_in_use mit Name und Anzahl); sonst physisches Löschen von Positionen, Tarifverknüpfungen und Definition. Eine Papierkorb-Variante gibt es nicht. Sammellöschen nutzt canBulk(delete, n).
Bereitstellung des Inhalts
resolveTemplate($definition_id, $plan_id): läuft die Tarifkette ab (bis 50, zyklusgeschützt) und sammelt aktivierte Positionen; dieselbe Position gewinnt beim ersten Vorkommen (Kind-Tarif).materialise(...): schreibt jede Vorlagenposition auf die Zeilen des Benutzers (usable, Limits, Preise,origin = 'plan', Datumsfenster). Im Ersetzungsmodus werden alle nicht in der Vorlage enthaltenen Zeilen gelöscht (bei angegebener Quelle nur diese Quelle). Die Auswahl speichertuser_permission_state.syncClientPlan(): überträgt das aktive Abonnement des Mandanten (über den Abonnement-Eigentümer vererbt) auf alle seine Benutzer und ersetzt nur Zeilen der Quellesubscription, danachsyncCoreRouteAccess().syncCoreRouteAccess(): verschiebt einen Nicht-Super-Benutzer eines Mandanten in dessen eigene Basisgruppe und ersetzt die Routenrechte der Gruppe durch die gültigen Funktionen der Benutzer, deren Abhängigkeiten und dieSYSTEM-Routen; bei Benutzern ohne Mandant wird nur ergänzt.materialiseResources(): idempotente Kontingent-Gutschriften aus den Positionen ins Ressourcenbuch.
Berechtigungen
list, edit, delete, debug: SYSTEM; add ist nicht eingestuft (nur canSave fragt danach, edit entscheidet). Die Liste filtert nicht nach Inhaltsberechtigung; der Mandantenfilter wird über getCompanyGroupFilter() eingeschränkt.