B2B Plattform

    Firmenkonten, Mitarbeiter, Rollen, Budgets und Firmenadressen direkt im Checkout

    Überblick

    Die Bronn B2B-Plattform ist das zentrale Plugin der Bronner B2B Suite. Sie erweitert Shopware 6 um vollständige Firmenkonten-Verwaltung mit Mitarbeitern, Rollen, Budgets, Kostenstellen, Firmenadressen, Produktbeschränkungen und mehrstufigen Freigabeprozessen.

    Das Plugin bildet komplexe B2B-Organisationsstrukturen direkt im Shop ab. Firmenkunden verwalten ihre eigene Hierarchie selbstständig, ohne dass der Shop-Betreiber bei jeder Personaländerung manuell eingreifen muss.

    Das Plugin verfuegt ueber vollstaendige Lifecycle-Methoden: install, update, activate, deactivate und uninstall. Bei der Deinstallation werden alle Plugin-Daten sauber entfernt (Tabellen, Mail-Templates, Flows, Event-Actions). Beim Install und Update werden Mail-Templates und Flow-Builder-Flows automatisch angelegt bzw. aktualisiert.

    Aktuelle Version: 1.8.1. Mit v1.8.0 wurde die komplette interne API durch vier BackedEnums (B2bPermission, BudgetPeriod, ApprovalStatus, RestrictionType) typsicher gemacht. Zwei Unique-Indizes verhindern Duplikate auf Datenbankebene (Permission pro Rolle, Mitarbeiter-Cost-Center-Mapping). Zwei XOR-Validatoren erzwingen saubere Datenmodelle (Budget: Abteilung XOR Cost-Center, ProductRestriction: Produkt-IDs XOR Kategorien). Eine Legacy-Bridge mappt bestehende String-Werte transparent in Enums — keine Breaking-Changes. v1.8.1 ist der UX-Hotfix dazu: spezifische Snippet-Texte bei XOR-Verletzungen statt generischem businessError-Flash.

    Änderungen v1.8.1 (Hotfix XOR-Flash):

  1. Fix: XOR-Verletzungen (Budget mit Abteilung UND Cost-Center, ProductRestriction mit Produkt-IDs UND Kategorien) zeigten in v1.8.0 einen generischen `businessError`-Flash. Jetzt prüft das Plugin die XOR-Bedingung vor dem try-Block und zeigt spezifische, übersetzte Snippet-Texte an (`bronnB2b.budget.xor.violation`, `bronnB2b.productRestriction.xor.violation`).
  2. Admins verstehen sofort, welche XOR-Regel verletzt wurde und wie sie sie reparieren.
  3. Änderungen v1.8.0 (Type-Design ab v1.8.0):

  4. Type-Safe API durch vier BackedEnums:
  5. - B2bPermission (alle Permission-Strings — shop.purchase, approvals.submit, approvals.decide, employees.manage, roles.manage, budgets.manage, costCenters.manage, addresses.manage, productRestrictions.manage)

    - BudgetPeriod (monthly, quarterly, yearly, one_time)

    - ApprovalStatus (pending, approved, rejected, withdrawn)

    - RestrictionType (product, category)

  6. Unique-Indizes: `bronn_b2b_permission` (UNIQUE `role_id, permission`), `bronn_b2b_employee_cost_center` (UNIQUE `employee_id, cost_center_id`). Migrationen deduplizieren bestehende Einträge vor der Index-Anlage, sodass auch Shops mit manuell entstandenen Duplikaten sauber migriert werden.
  7. XOR-Validatoren: Budget gehört entweder zu einer Abteilung ODER zu einem Cost-Center (nie beides). ProductRestriction filtert entweder über Produkt-IDs ODER über Kategorien (nie beides). Verletzungen werfen `WriteConstraintViolationException`.
  8. Legacy-Bridge: Bestehende String-Werte aus der Datenbank werden transparent in den Enum-Wert gemappt. Keine Breaking-Changes — Custom-Erweiterungen, die noch mit Strings arbeiten, bleiben funktionsfähig.
  9. Änderungen v1.7.9 (Admin-UI-Polish):

  10. Fix: Die `config.xml` nutzt wieder Inline-Labels mit `lang="de-DE"` und `lang="en-GB"` statt Snippet-Schlüsseln. Hintergrund: Der Shopware-Extension-Manager löst Snippet-Keys in der Config-View nicht zuverlässig auf — Admins sahen leere Felder oder rohe Snippet-Keys. Mit Inline-Labels ist die Plugin-Konfiguration jetzt vollständig deutsch und englisch sichtbar. Storefront-Snippets bleiben unverändert über das Snippet-System lokalisiert.
  11. Änderungen v1.7.8 (Audit-Log-Sichtbarkeit):

  12. Fix: Der `CrossCompanyAccessAuditLogger` loggt Cross-Company-Zugriffsversuche jetzt auf `ERROR`-Level (vorher `WARNING`). Hintergrund: Der Shopware-Default-Monolog filtert `WARNING` in vielen Setups standardmäßig weg, sodass sicherheitsrelevante Events unsichtbar blieben. Mit `ERROR` landen alle Cross-Company-Versuche garantiert in den Server-Logs und sind in Standard-Log-Tools (ELK, Sentry, Datadog) ohne Sonderkonfiguration sichtbar.
  13. Änderungen v1.7.7 (Hotfix):

  14. Fix: Storefront-Snippets für die Plugin-Config liegen jetzt im korrekten Path (`src/Resources/snippet/de_DE/` bzw. `en_GB/`). Vorher wurde der Storefront-Snippet-Loader sie nicht eingelesen, weil sie im Admin-Snippet-Verzeichnis lagen.
  15. Audit: Der neue `CrossCompanyAccessAuditLogger` wird in 9 Controller-Catches gefeuert. Jeder gefangene Cross-Company-Versuch landet als `WARNING` im Symfony-Logger inklusive Customer-ID, Customer-E-Mail, Entity-Typ, Entity-ID, Controller-Action und User-Agent.
  16. Änderungen v1.7.6 (Observability + Hygiene):

  17. Observability: `LoggerInterface` flächig in alle 9 B2B-Controller injiziert. Catch-Pattern vereinheitlicht — DAL-Fehler werden mit `INFO` geloggt, unerwartete `Throwable`s mit `ERROR`, Cross-Company-Versuche mit `WARNING`. Stack-Traces tauchen nicht mehr im Storefront-DOM auf.
  18. Approval-Default konservativ: `requiresApproval()` gibt jetzt `true` zurück, wenn das Customer-Datenmodell unvollständig ist (z. B. kein Employee an Customer verknüpft, keine Company-ID). Vorher gingen solche Bestellungen ohne Freigabe durch — fachlich riskant.
  19. Plugin-Config auf Snippets: Alle Inline-Labels in `config.xml` wurden durch Snippet-Schlüssel ersetzt. Damit sind die Admin-Konfigurationstexte voll i18n-fähig und nicht mehr in XML hartkodiert.
  20. Migration: Neue Migration `NormalizeFlowsAndMailTemplates` normalisiert bestehende Flow-Builder- und Mail-Template-Einträge (Event-Names, Sales-Channel-Zuordnung, Namensschema mit "Bronn B2B:"-Prefix) auf den aktuellen Stand.
  21. Änderungen v1.7.5 (Security-Hardening):

  22. Cross-Company-Schutz: Zentraler Helper `B2bContextService::assertEntityBelongsToOwnCompany($entity, $context)` prüft, dass die geladene Entity zur Company-ID des angemeldeten Mitarbeiters gehört. Wird in jedem Controller-Pfad aufgerufen, der eine ID aus dem Request entgegennimmt (6 Vektoren aus dem Audit geschlossen).
  23. Cart-Bypass präzise: Statt `Cart::isModified()`-basiertem statischen Bypass wird jetzt eine Cart-Extension `BronnB2bAddItemContext` gesetzt, die genau das gerade hinzugefügte LineItem markiert. Alle anderen LineItems im selben Cart laufen weiter durch den vollen Permission-Check.
  24. Permission-Trennung: Neue Permission `approvals.submit` (Einreichen einer Freigabe) getrennt von `approvals.decide` (Entscheiden). Vorher konnten Mitarbeiter mit reiner View-Permission Submit-Events feuern.
  25. Migration-Idempotenz: Neue Helper `bronnColumnExists` und `bronnIndexExists` in einem Migration-Helper-Trait. Migrationen können sicher mehrfach laufen, auch wenn Teile davon schon manuell installiert wurden. Hotfix v1.7.5 hat das Helper-Naming entkonfliktiert (bronn-Prefix), nachdem v1.7.4 wegen Trait-Konflikt mit Core-Migrations broken war.
  26. Änderungen v1.7.3:

  27. Fix: Der `BronnB2bAddressManager` respektiert nun den initialen Tab — wenn das Modal mit `data-billing-active="1"` geöffnet wird, ist der Rechnungsadressen-Tab vorausgewählt.
  28. Fix: Das Submit-Button-Label switcht beim Tab-Wechsel zwischen "Als Lieferadresse übernehmen" und "Als Rechnungsadresse übernehmen".
  29. Änderungen v1.7.2 (Hotfix):

  30. Fix: AddressManager-Modal-Stabilisierung. Das neue Storefront-Plugin `BronnB2bModalInit` re-initialisiert das `BronnB2bAddressManager`-Plugin nach jedem Modal-AJAX-Load (vorher blieb das Modal bei einem zweiten Öffnen leer).
  31. Fix: Hidden-Stub-Inputs (`<input type="hidden" name="..." value="">`) und leere Pane-Divs werden gerendert, damit Shopware-Core-Code beim Re-Render nicht auf `undefined` läuft und das Modal crasht.
  32. Änderungen v1.7.1 (Should-Fix-Sammelrelease):

  33. Performance: Inhaber-Performance-Bypass im Modal-Subscriber — für Firmen-Inhaber wird der Subscriber sofort verlassen, bevor unnötige Permission-Lookups laufen.
  34. Sicherheit/CSP: Inline-Modal-JS wurde in ein externes Plugin-Bundle ausgelagert (`BronnB2bAddressManager`), CSP-fest und cache-freundlich.
  35. UX: Snippet-Anrede vereinheitlicht — alle Storefront-Texte sprechen jetzt konsistent in der Sie-Form (vorher gemischt Du/Sie).
  36. DB: Die Permission-Migration läuft als Batch `INSERT ... SELECT` statt Row-by-Row — Sekunden statt Minuten bei großen Rollen-Bestand.
  37. Cart: Cart-Error-IDs sind eindeutig pro LineItem (`b2b-cart-add-blocked-{lineItemId}` statt globalem Key), damit Fehler-Stacking pro Produkt sichtbar bleibt.
  38. Änderungen v1.7.0 (Breaking — Permission-Konsolidierung):

  39. Breaking: Die getrennten Permissions `cart.add` (in den Warenkorb legen) und `product.view_prices` (Preise sehen) wurden zur einen Permission `shop.purchase` konsolidiert. Beide Fähigkeiten gehören fachlich zusammen: Wer einkaufen darf, muss Preise sehen.
  40. Migration: `Migration1762000000MergeCartAndPriceViewPermissions` hebt bestehende Rollen automatisch — jede Rolle, die vorher mindestens eine der beiden alten Permissions hatte, bekommt jetzt `shop.purchase`.
  41. Subscriber: `CartAddPermissionSubscriber` prüft auf `shop.purchase`, bevor ein LineItem in den Warenkorb kommt (Frontend-, Backend- und Cart-Summary-Pfad konsistent).
  42. Änderungen v1.6.0:

  43. Breaking: Die Standard-Shopware-Adress-UI wurde für B2B-Mitarbeiter vollständig durch die B2B-Adressverwaltung ersetzt. Drei Eingriffspunkte:
  44. 1. /account/address leitet Mitarbeiter automatisch auf das Firmenadressen-Modul um.

    2. Im Checkout öffnet der Adress-Wechsler das BronnB2bAddressManager-Modal (Tabs Liefer-/Rechnungsadresse, gefüllt aus Firmenadressen-Pool).

    3. Direkte Standard-Save-Routen (/account/address/create, /account/address/edit) werden serverseitig mit HTTP 403 geblockt.

  45. Subscriber: `AddressManagerModalSubscriber` injiziert die B2B-Adressdaten ins Modal-Template; respektiert den initialen Tab und CSRF-Token.
  46. Änderungen v1.5.2 (Hotfix):

  47. Sicherheit: Cart-Add ohne Preis-Sicht wird konsistent geblockt — Frontend (Buy-Button versteckt), Backend (`CartAddPermissionSubscriber`) und Cart-Summary (LineItem-Removal-Hinweis).
  48. Änderungen v1.5.1 (Hotfix):

  49. Fix: Anlegen und Bearbeiten von Firmenadressen schlug mit dem DAL-Fehler `Expected data at /0/company to be an array, string given` fehl. Naming-Konflikt in `CompanyAddressDefinition` zwischen `StringField('company')` und `ManyToOneAssociationField('company', ...)`.
  50. Fix: Die Assoziation wurde von `company` auf `parentCompany` umbenannt; das `StringField('company')` bleibt unverändert.
  51. Änderungen v1.5.0:

  52. Neu: Firmenadressen direkt im Checkout auswählbar (zwei Dropdowns auf Confirm-Seite).
  53. Fix: Firmen-Inhaber sehen den Menüpunkt "Firmenadressen" jetzt zuverlässig (synthetische Owner-Permissions im `AccountMenuSubscriber`).
  54. Sicherheit: Route `adopt-and-select` ist POST-only mit CSRF-Token; Exception-Details werden nicht mehr an den Client durchgereicht.
  55. Vorherige Aenderungen (v1.3.28):

  56. Budget-Widget im Checkout fuer Mitarbeiter mit zugewiesenem Budget
  57. Flow event_name korrigiert (Unterstriche zu Punkte)
  58. Flow-Namen mit "Bronn B2B:" Prefix
  59. Systemvoraussetzungen

  60. Shopware 6.7 oder höher
  61. PHP 8.1 oder höher
  62. MySQL 8.0 oder höher
  63. Empfohlen: mindestens 256 MB PHP Memory Limit
  64. Installation

  65. 1.Plugin über den Shopware Plugin-Manager installieren oder manuell in custom/plugins/BronnB2bPlatform ablegen
  66. 2.Plugin im Plugin-Manager aktivieren
  67. 3.Cache leeren:
  68. php bin/console cache:clear
  69. 4.Datenbank-Migrationen werden automatisch bei der Installation ausgeführt (8 Migrationen für Firmen, Rollen, Mitarbeiter, Berechtigungen, Budgets, Freigaben, Kostenstellen, Adressen, Produktbeschränkungen und Mail-Templates)
  70. Das Plugin enthaelt vorkompiliertes Admin-JS und funktioniert ohne build-administration.sh – eine reine Installation ueber den Shopware Plugin-Manager im Admin ist ausreichend.

    Konfiguration

    Die Plugin-Konfiguration befindet sich unter Erweiterungen > Meine Erweiterungen > Bronn B2B Plattform > Konfiguration (config.xml).

    Allgemeine Einstellungen:

  71. **Plugin aktiv** (`BronnB2bPlatform.config.active`, Typ: `bool`, Standard: `true`): Aktiviert oder deaktiviert die B2B-Plattform-Funktionen im Storefront und in der Administration.
  72. **Maximale Anzahl Mitarbeiter pro Firma** (`BronnB2bPlatform.config.maxEmployeesPerCompany`, Typ: `int`, Standard: `0`): Begrenzt die Anzahl der Mitarbeiter, die einer Firma zugewiesen werden können. 0 = unbegrenzt.
  73. **Selbstregistrierung für Mitarbeiter erlauben** (`BronnB2bPlatform.config.allowEmployeeSelfRegistration`, Typ: `bool`, Standard: `false`): Ermöglicht es Mitarbeitern, sich selbst für eine Firma zu registrieren. Der Firmen-Admin muss die Anfrage bestätigen.
  74. Genehmigungen:

  75. **Genehmigung bei Budgetüberschreitung** (`BronnB2bPlatform.config.requireApprovalAboveBudget`, Typ: `bool`, Standard: `true`): Bestellungen, die das Budget des Mitarbeiters überschreiten, erfordern eine Freigabe.
  76. **Immer Genehmigung erforderlich** (`BronnB2bPlatform.config.requireApprovalAlways`, Typ: `bool`, Standard: `false`): Wenn aktiviert, erfordern alle Bestellungen von Unterkonten eine Freigabe, unabhängig vom Budget.
  77. **E-Mail-Adresse für Genehmigungsbenachrichtigungen** (`BronnB2bPlatform.config.approvalNotifyEmail`, Typ: `text`): Zusätzliche E-Mail-Adresse, die bei neuen Freigabeanfragen benachrichtigt wird. Leer = nur Firmen-Admin wird benachrichtigt.
  78. Budget:

  79. **Standard-Budgetzeitraum** (`BronnB2bPlatform.config.defaultBudgetPeriod`, Typ: `single-select`, Standard: `monthly`): Optionen: `monthly` (Monatlich), `quarterly` (Quartalsweise), `yearly` (Jährlich), `one_time` (Einmalig).
  80. **Budget-Widget im Checkout anzeigen** (`BronnB2bPlatform.config.showBudgetWidget`, Typ: `bool`, Standard: `true`): Zeigt dem Mitarbeiter sein verbleibendes Budget auf der Bestellbestätigungsseite an.
  81. Funktionen:

  82. **Kostenstellen aktivieren** (`BronnB2bPlatform.config.showCostCenters`, Typ: `bool`, Standard: `true`): Aktiviert die Kostenstellen-Funktion. Mitarbeiter können bei der Bestellung eine Kostenstelle auswählen.
  83. Funktionen

    Firmenkonten-Verwaltung

    Jedes Firmenkonto (bronn_b2b_company) enthält Stammdaten (Firmenname, Firmennummer, USt-IdNr., Ansprechpartner), zugeordnete Mitarbeiter und Abteilungen. Firmenkunden können ihre Daten im Storefront selbst verwalten. Ein Dashboard zeigt Firmenübersicht, Mitarbeiterzahl, Budget-Auslastung und offene Genehmigungen.

    Mitarbeiter-Management

    Mitarbeiter (bronn_b2b_employee) werden einem Firmenkonto zugeordnet. Jeder Mitarbeiter hat eine Rolle, die seine Berechtigungen steuert. Mitarbeiter können vom Firmenkonto-Administrator direkt im Storefront angelegt, bearbeitet und deaktiviert werden.

    Rollen und Berechtigungen

    Rollen (bronn_b2b_role) definieren, was ein Mitarbeiter darf. Berechtigungen (bronn_b2b_permission) werden granular pro Rolle konfiguriert: Produkte ansehen, Warenkorb befüllen, Bestellungen auslösen, Freigaben erteilen, Mitarbeiter verwalten.

    Budgets

    Budgets (bronn_b2b_budget) können pro Mitarbeiter gesetzt werden. Der Budgetzeitraum ist konfigurierbar (monatlich, quartalsweise, jährlich, einmalig). Bei Überschreitung wird die Bestellung automatisch in den Freigabeprozess überführt.

    Freigabeprozesse

    Bestellungen, die das Budget übersteigen oder immer eine Genehmigung erfordern, landen als Freigabeanfrage (bronn_b2b_order_approval) beim Vorgesetzten. Dieser kann im Storefront-Account genehmigen oder ablehnen.

    Kostenstellen

    Kostenstellen (bronn_b2b_cost_center) können pro Firma angelegt werden. Mitarbeiter werden über die Mapping-Tabelle (bronn_b2b_employee_cost_center) zugeordnet und können bei der Bestellung eine Kostenstelle auswählen.

    Firmenadressen

    Firmenadressen (bronn_b2b_company_address) ermöglichen die Verwaltung mehrerer Liefer- und Rechnungsadressen pro Firma.

    Produktbeschränkungen

    Produktbeschränkungen (bronn_b2b_product_restriction) erlauben es, bestimmte Produkte für einzelne Firmen oder Mitarbeiter zu sperren.

    Events & Hooks

    Das Plugin löst folgende Flow-Builder-fähige Events aus (alle implementieren FlowEventAware, MailAware, CustomerAware, ScalarValuesAware):

  84. **`bronn_b2b.approval_requested`** (`BronnB2bPlatform\Core\Event\ApprovalRequestedEvent`) -- Eine Bestellung wurde zur Freigabe eingereicht
  85. **`bronn_b2b.approval_approved`** (`BronnB2bPlatform\Core\Event\ApprovalApprovedEvent`) -- Eine Freigabeanfrage wurde genehmigt
  86. **`bronn_b2b.approval_rejected`** (`BronnB2bPlatform\Core\Event\ApprovalRejectedEvent`) -- Eine Freigabeanfrage wurde abgelehnt
  87. **`bronn_b2b.employee_invited`** (`BronnB2bPlatform\Core\Event\EmployeeInvitedEvent`) -- Ein Mitarbeiter wurde zu einem Firmenkonto eingeladen
  88. **`bronn_b2b.budget_exceeded`** (`BronnB2bPlatform\Core\Event\BudgetExceededEvent`) -- Ein Budget wurde überschritten
  89. Zusätzliche Cart-Fehler-Events:

  90. `B2bApprovalRequiredError` -- Warenkorb erfordert Freigabe
  91. `B2bBudgetExceededError` -- Warenkorbwert übersteigt Budget
  92. `B2bProductRestrictedError` -- Produkt ist nicht freigegeben
  93. Flow Builder Events

    Alle fünf Plugin-Events sind im Shopware Flow Builder verfügbar und können für automatische Workflows genutzt werden:

    | Event-Name | Klasse | Beschreibung |

    |---|---|---|

    | bronn_b2b.approval_requested | ApprovalRequestedEvent | Trigger bei neuer Freigabeanfrage |

    | bronn_b2b.approval_approved | ApprovalApprovedEvent | Trigger bei Genehmigung |

    | bronn_b2b.approval_rejected | ApprovalRejectedEvent | Trigger bei Ablehnung |

    | bronn_b2b.employee_invited | EmployeeInvitedEvent | Trigger bei Mitarbeiter-Einladung |

    | bronn_b2b.budget_exceeded | BudgetExceededEvent | Trigger bei Budgetüberschreitung |

    Alle Events stellen ShopwareSalesChannelEvent-Daten bereit und können mit Mail-Aktionen, Webhooks oder eigenen Flow-Actions kombiniert werden.

    Textbausteine (Snippets)

    Das Plugin registriert Storefront-Snippets unter dem Namespace bronn-b2b-platform in DE und EN:

    Storefront-Snippets (src/Resources/snippet/de_DE/bronn-b2b-platform.de-DE.json):

  94. `checkout.b2b-approval-required` -- Hinweis bei erforderlicher Freigabe
  95. `checkout.b2b-budget-exceeded` -- Hinweis bei Budgetüberschreitung (mit Platzhaltern `%cartTotal%` und `%remaining%`)
  96. `checkout.b2b-product-restricted` -- Hinweis bei gesperrtem Produkt
  97. `bronn-b2b-platform.checkout.addressPicker.*` -- NEU in v1.5.0: Labels und Texte für die beiden Firmenadress-Dropdowns auf der Confirm-Seite (`headline`, `shippingLabel`, `billingLabel`, `placeholder`, `submitButton`, `errorGeneric`)
  98. `bronn-b2b-platform.account.menu.*` -- Menüpunkte: Firmenübersicht, Mitarbeiter, Rollen & Rechte, Budgets, Genehmigungen, Kostenstellen, Artikelbeschränkungen, Firmenadressen
  99. `bronn-b2b-platform.account.dashboard.*` -- Dashboard-Labels und -Texte
  100. `bronn-b2b-platform.account.noPermission` -- Fehlermeldung bei fehlender Berechtigung
  101. Admin-Snippets (src/Resources/app/administration/src/module/bronn-b2b-platform/snippet/de-DE.json, en-GB.json)

    Scheduled Tasks

  102. **`bronn_b2b.budget_reset`** (`BronnB2bPlatform\ScheduledTask\BudgetResetTask`): Wird täglich ausgeführt (Intervall: 86400 Sekunden / 24 Stunden). Setzt abgelaufene Budgetperioden zurück. Der zugehörige Handler ist `BudgetResetTaskHandler`.
  103. Datenbank-Tabellen

    Das Plugin erstellt folgende Datenbank-Tabellen über 8 Migrationen:

    | Tabelle | Entity-Name | Beschreibung |

    |---|---|---|

    | bronn_b2b_company | bronn_b2b_company | Firmenkonten mit Stammdaten |

    | bronn_b2b_role | bronn_b2b_role | Berechtigungsrollen |

    | bronn_b2b_employee | bronn_b2b_employee | Mitarbeiter-Zuordnungen |

    | bronn_b2b_permission | bronn_b2b_permission | Granulare Berechtigungen pro Rolle |

    | bronn_b2b_budget | bronn_b2b_budget | Budget-Definitionen |

    | bronn_b2b_order_approval | bronn_b2b_order_approval | Freigabeanfragen |

    | bronn_b2b_cost_center | bronn_b2b_cost_center | Kostenstellen |

    | bronn_b2b_company_address | bronn_b2b_company_address | Firmenadressen |

    | bronn_b2b_employee_cost_center | bronn_b2b_employee_cost_center | Zuordnung Mitarbeiter zu Kostenstellen |

    | bronn_b2b_product_restriction | bronn_b2b_product_restriction | Produktbeschränkungen pro Firma/Mitarbeiter |

    Migrationen:

  104. `Migration1712000000CreateCompanyAndRoleTables`
  105. `Migration1712000001CreateEmployeeAndPermissionTables`
  106. `Migration1712000002CreateBudgetApprovalCostCenterTables`
  107. `Migration1712000003CreateCompanyAddressTable`
  108. `Migration1712000004CreateMailTemplatesAndFlows`
  109. `Migration1712000005CreateCostCenterAssignmentAndProductRestriction`
  110. `Migration1712000006AddCartPayloadToOrderApproval`
  111. `Migration1712000007AddShowTooltipsToCompany`
  112. Admin-Integration

    Das Plugin registriert ein eigenes Admin-Modul bronn-b2b-platform unter dem Menüpunkt B2B:

    Seiten:

  113. `bronn-b2b-company-list` -- Liste aller Firmenkonten
  114. `bronn-b2b-company-detail` -- Detailansicht mit Tabs
  115. Detail-Views (Tabs):

  116. `bronn-b2b-company-detail-base` -- Stammdaten der Firma
  117. `bronn-b2b-company-detail-employees` -- Mitarbeiter-Verwaltung
  118. `bronn-b2b-company-detail-roles` -- Rollen und Berechtigungen
  119. `bronn-b2b-company-detail-budgets` -- Budget-Übersicht und -Verwaltung
  120. `bronn-b2b-company-detail-approvals` -- Offene und abgeschlossene Freigaben
  121. `bronn-b2b-company-detail-cost-centers` -- Kostenstellen-Verwaltung
  122. `bronn-b2b-company-detail-addresses` -- Firmenadressen-Verwaltung
  123. Die Admin-Module liegen unter:

    src/Resources/app/administration/src/module/bronn-b2b-platform/

    Storefront-Integration

    Das Plugin erweitert den Account-Bereich im Storefront um folgende Seiten und Templates:

    Account-Seiten (src/Resources/views/storefront/page/account/b2b/):

  124. `dashboard.html.twig` -- Firmenübersicht-Dashboard
  125. `employees/index.html.twig` -- Mitarbeiter-Verwaltung
  126. `roles/index.html.twig` -- Rollenverwaltung
  127. `roles/form.html.twig` -- Rollenformular
  128. `budgets/index.html.twig` -- Budget-Übersicht
  129. `approvals/index.html.twig` -- Freigaben-Übersicht
  130. `approvals/submitted.html.twig` -- Eingereichte Freigaben
  131. `cost-centers/index.html.twig` -- Kostenstellen
  132. `restrictions/index.html.twig` -- Produktbeschränkungen
  133. `addresses/index.html.twig` -- Firmenadressen
  134. `addresses/form.html.twig` -- Adressformular
  135. `no-permission.html.twig` -- Fehlerseite bei fehlender Berechtigung
  136. Sidebar-Erweiterung:

  137. `page/account/sidebar.html.twig` -- Erweitert das Account-Menü um B2B-Menüpunkte. Der `AccountMenuSubscriber` injiziert synthetische Owner-Permissions, damit Firmen-Inhaber den Menüpunkt "Firmenadressen" zuverlässig sehen (Fix v1.5.0).
  138. Checkout-Erweiterung:

  139. `page/checkout/confirm/index.html.twig` -- Budget-Widget, Kostenstellen-Auswahl und ab v1.5.0 zusätzlich zwei Firmenadress-Dropdowns ("als Lieferadresse" / "als Rechnungsadresse").
  140. Subscriber `CheckoutConfirmAddressSubscriber` (auf `CheckoutConfirmPageLoadedEvent`) reichert die Confirm-Seite mit den verfügbaren Firmenadressen an.
  141. Controller-Methode `B2bAddressController::adoptAndSelect()` (Route `bronn-b2b.adopt-and-select`, **POST-only, CSRF-pflichtig**) kopiert die gewählte Firmenadresse in das persönliche Adressbuch des Mitarbeiters und setzt sie sofort als aktive Liefer- bzw. Rechnungsadresse. Exception-Details werden nicht mehr an den Client durchgereicht (Sicherheits-Hardening v1.5.0).
  142. Neue Snippet-Keys unter `bronn-b2b-platform.checkout.addressPicker.*` (DE/EN): Labels für die beiden Dropdowns, Platzhalter "Keine Firmenadresse ausgewählt" und Fehlertexte.
  143. Adressverwaltungs-Override (ab v1.6.0):

  144. Subscriber `AddressManagerModalSubscriber` (auf den Checkout-AddressManager-PageLoadedEvent) ersetzt im Modal die Standard-Adressverwaltung durch den `BronnB2bAddressManager`. Tabs für Liefer- und Rechnungsadresse, gefüllt aus dem Firmenadressen-Pool des Mitarbeiters.
  145. Account-Redirect: `/account/address` für Mitarbeiter wird auf das Firmenadressen-Modul weitergeleitet — Mitarbeiter sehen keine private Adressverwaltung mehr.
  146. Backend-Block: Direkte Standard-Save-Routen (`/account/address/create`, `/account/address/edit`) werden serverseitig mit HTTP 403 abgewiesen, damit Mitarbeiter auch per Direct-POST keine privaten Adressen anlegen können.
  147. Produkt-Erweiterungen:

  148. `component/product/card/action.html.twig` -- Produktkarten-Aktionen
  149. `component/product/card/price-unit.html.twig` -- Preisanzeige
  150. `component/buy-widget/buy-widget.html.twig` -- Kauf-Widget
  151. JavaScript-Plugins:

  152. `BronnB2bCostCenterPlugin` (`src/Resources/app/storefront/src/js/plugin/bronn-b2b-cost-center.plugin.js`)
  153. `BronnB2bAddressManager` (v1.6.0, externes Bundle, CSP-fest seit v1.7.1) — rendert das Tab-Modal mit Liefer-/Rechnungsadressen, respektiert den initialen Tab (v1.7.3) und switcht das Submit-Button-Label beim Tab-Wechsel.
  154. `BronnB2bModalInit` (v1.7.2) — Helper-Plugin, das `BronnB2bAddressManager` nach Modal-AJAX-Reloads re-initialisiert. Verhindert leere Modals beim zweiten Öffnen.
  155. Berechtigungs-Modell

    Ab v1.7.0 nutzt das Plugin eine konsolidierte Permission shop.purchase anstelle der vorher getrennten Permissions cart.add und product.view_prices.

    Permission-Liste (Auszug):

    | Permission-Key | Bedeutung |

    |---|---|

    | shop.purchase | Mitarbeiter darf Preise sehen UND Produkte in den Warenkorb legen (konsolidiert seit v1.7.0). |

    | company.manage | Firmen-Stammdaten und -Verwaltung. |

    | employees.manage | Mitarbeiter anlegen, bearbeiten, deaktivieren. |

    | roles.manage | Rollen und Permissions verwalten. |

    | budgets.manage | Budgets definieren und zuweisen. |

    | approvals.decide | Freigaben erteilen oder ablehnen. |

    | costcenters.manage | Kostenstellen verwalten. |

    | addresses.manage | Firmenadressen verwalten. |

    | restrictions.manage | Produktbeschränkungen pflegen. |

    Hintergrund Konsolidierung:

    In der Praxis ergab die Trennung cart.add vs. product.view_prices keine sinnvollen Kombinationen — Cart-Add ohne Preis-Sicht erzeugte UI-Inkonsistenzen, Preis-Sicht ohne Cart war ein seltenes Edge-Case-Setup. Beide Capabilities werden jetzt gemeinsam vergeben.

    Migration `Migration1762000000MergeCartAndPriceViewPermissions`:

    Die Migration läuft beim Plugin-Update automatisch und konsolidiert bestehende Rollen via Batch-INSERT-SELECT (v1.7.1):

  156. Jede Rolle, die `cart.add` ODER `product.view_prices` (oder beide) hatte, bekommt jetzt `shop.purchase`.
  157. Die alten Permission-Strings werden aus `bronn_b2b_permission` entfernt.
  158. Sekunden statt Minuten Laufzeit auf großen Rollen-Beständen.
  159. Enforcement:

  160. `CartAddPermissionSubscriber` prüft `shop.purchase` vor jedem Cart-Add (Frontend + Backend + Cart-Summary).
  161. Buy-Buttons werden im Storefront ausgeblendet, wenn die Permission fehlt.
  162. Cart-Error-IDs sind eindeutig pro LineItem (`b2b-cart-add-blocked-{lineItemId}` seit v1.7.1).
  163. Kompatibilität

  164. Vollständig kompatibel mit allen anderen Plugins der Bronner B2B Suite
  165. Kompatibel mit Standard-Shopware-Themes und gängigen Theme-Erweiterungen
  166. Getestet mit Shopware 6.7.x
  167. Unterstützt Multi-Language (DE/EN)
  168. Unterstützt Multi-Sales-Channel
  169. FAQ

    Bereit für professionelles B2B?

    Statt 30.000–80.000 € Individualentwicklung: fertige, getestete Plugins — einsatzbereit in Stunden.

    • Alle 12 Plugins im vollen Funktionsumfang
    • Persönliche Einführung durch den Entwickler
    • Individuelle Beratung für deinen Use Case

    Keine Kreditkarte nötig · Unverbindlich · Antwort innerhalb von 24h