Backend
Dieses Kapitel beschreibt die Server-Seite der Linie für Shopware 6.7.
Entitäten
Das Plugin registriert sieben Entitäten. Die Felder tragen das Flag ApiAware und sind damit über die API sichtbar, soweit nicht anders vermerkt.
Vorgang
leoparden_business_transactions_transaction, Klasse TransactionDefinition.
Feld | Typ | Bedeutung |
|---|---|---|
| UUID | Primärschlüssel |
| String | Vorgangsnummer; Grundlage der SEO-URL |
| FK, Pflicht | Der Kunde, dem der Vorgang gehört |
| FK | Optionale Verknüpfung mit einer Shopware-Bestellung ( |
| FK | Der Vorgangstyp |
| FK | Kundenadresse als Rechnungsadresse |
| FK | Kundenadresse als Lieferadresse ( |
| Langtext | Freitext-Adressen, die die Detailseite statt der Kundenadresse zeigt, wenn gesetzt |
| String | Zahlungsbedingungen |
| String | Referenznummer |
| Langtext | Betreff |
| Datum | Belegdatum und Lieferdatum; das Lieferdatum trägt auch den Status |
| Float | Beträge |
| String | Bearbeiter |
| Bool | Archivkennzeichen |
| Int, | Berechneter Status, nicht gespeichert |
| 1:n | Positionen |
| 1:n | Dokumente zum Herunterladen |
| 1:n | SEO-URLs des Vorgangs |
| JSON | Zusatzfelder (ohne |
Weitere Entitäten
Entität | Felder |
|---|---|
|
|
|
|
|
|
|
|
| je |
Die Entität Vorgang erhält über TransactionExtension das Laufzeitfeld url (String, ApiAware, Runtime). Der TransactionSubscriber füllt es beim Laden: Für jeden geladenen Vorgang und jede geladene Position hängt er die Erweiterung url mit der Adresse der Route frontend.plugins.transactions.detail an. Bei einer Position wird dabei die ID der Position eingesetzt, nicht die des Vorgangs.
Ein geladener Vorgang und eine geladene Position berechnen ihren Status außerdem über StateAwareTrait::getState() aus dem Lieferdatum.
Der Status
TransactionStateStruct ordnet bestimmte Lieferdaten einem Statuswert zu. Jedes andere Datum und ein fehlendes Lieferdatum ergeben 0.
Lieferdatum | Status | Konstante |
|---|---|---|
30.12.1899 | 1899 |
|
31.12.2444 | 2444 |
|
31.12.2500 | 2500 |
|
31.12.2510 | 2510 |
|
31.12.2520 | 2512 |
|
31.12.2513 | 2513 |
|
31.12.2530 | 2530 |
|
31.12.2555 | 2555 |
|
31.12.2599 | 2599 |
|
31.12.2666 | 2666 |
|
31.12.2700 | 2700 |
|
31.12.2777 | 2777 |
|
31.12.2888 | 2888 |
|
31.12.2900 | 2900 |
|
31.12.2999 | 2999 |
|
Der Text zu einem Status steht im Snippet plugin.leoparden.BusinessTransactions.states.<Status>.
Tabellen
Die Installationsmigration legt diese sieben Tabellen an: leoparden_business_transactions_transaction, …_transaction_downloads, …_transaction_item, …_transaction_type, …_transaction_type_translation, leoparden_transaction_type_group und leoparden_transaction_type_group_translation. Wichtige Fremdschlüssel:
Vorgang → Kunde:
ON DELETE CASCADE(mit dem Kunden verschwinden seine Vorgänge)Vorgang → Bestellung, Typ und Adressen:
ON DELETE SET NULLPosition → Vorgang und Artikel:
ON DELETE SET NULLDownload → Vorgang und Medium:
ON DELETE CASCADE
Store-API-Routen
Beide Routen liegen im Routenbereich store-api, verlangen einen angemeldeten Kunden und nehmen ein Shopware-Criteria als JSON-Body entgegen (POST).
Route | Name | Entität |
|---|---|---|
|
| Vorgang |
|
| Position |
Jede Route besteht aus einer abstrakten Klasse (AbstractTransactionsRoute, AbstractTransactionItemsRoute), der Basisklasse (TransactionsRoute, TransactionItemsRoute). Eine zwischenspeichernde Dekoration gibt es in dieser Linie nicht. Die Antwort ist eine TransactionsRouteResponse bzw. TransactionItemsRouteResponse mit einem EntitySearchResult.
Was die Basisklasse der Anfrage hinzufügt:
einen Filter auf den angemeldeten Kunden:
customerIdbei den Vorgängen,transaction.customerIdbei den Positioneneinen Filter auf die Typen der Kundengruppe, aus der Einstellung
showCategoriesInTransactionsView(KlasseAllowedTypes). Filtert die Anfrage selbst nachtypeIdbzw.transaction.typeId, wie es die Elemente für offene Positionen und Rechnungen tun, darf sie nur unter den Typen wählen, die die Konfiguration irgendwo nennt: die der Kundengruppe sowieopenCategoriesundinvoiceCategories. Ein anderer Typ liefert nichts. Hat die Kundengruppe keine Zuordnung, bleibt die Liste leer. IstshowCategoriesInTransactionsViewgar nicht gesetzt, wird nichts eingeschränkt.bei den Vorgängen die Beziehungen
items,typeundtype.groupsowie eine Sortierung nachdocumentDateabsteigend (zusätzlich zu den Sortierungen der Anfrage), bei den Positionen die Beziehungtransactiondie Gesamtzahl als eigene Abfrage ohne Limit
Kriterien-Ereignisse
Vor der Abfrage senden die Routen ein Ereignis, über das ein Plugin das Criteria ändern kann:
Ereignis | Route | Methoden |
|---|---|---|
|
|
|
|
| dieselben |
Das Ereignis wird nach den oben genannten Filtern gesendet. BusinessSalesRepresentative ersetzt damit den Kundenfilter durch eine Oder-Bedingung.
Zwischenspeicher
Die Linie 6.7 hat keine zwischenspeichernde Dekoration der Routen (Cached…Route). Statt dessen tragen TransactionsRoute und TransactionItemsRoute ihre Antwort beim Laden in den Cache-Tag-Mechanismus des Kerns ein (CacheTagCollector). Die Tags sind:
der Criteria-Hash (
EntityCacheKeyGenerator::getCriteriaHash),der Hash des Verkaufskanal-Kontexts,
transactions-<Kunden-ID>bei den Vorgängen,transaction-items-<Kunden-ID>bei den Positionen.
Die Klassen Event\Transactions\TransactionsRouteCacheKeyEvent und Event\Transactions\TransactionsRouteCacheTagsEvent gibt es auch in dieser Linie, doch kein Code des Plugins sendet sie. Ein Subscriber auf diese Ereignisse bleibt daher ohne Wirkung.
Die Linie 6.7 enthält außerdem keinen CmsCacheKeySubscriber, der den Schlüssel zwischengespeicherter Kategorie- und Landingpages um den Kunden ergänzt. Die Elemente Vorgänge und Prozesse zeigen aber Daten des angemeldeten Kunden. Wie der 6.7-Kern solche Seiten für verschiedene Kunden trennt, ist in dieser Dokumentation nicht geprüft; testen Sie das mit zwei Kunden, bevor Sie die Elemente produktiv einsetzen.
Storefront-Seiten
Controller\AccountController stellt fünf GET-Routen bereit (Routenbereich storefront, jeweils ensureLoggedIn(false)):
Route | Adresse |
|---|---|
|
|
|
|
|
|
|
|
|
|
Die ersten drei laufen durch dieselbe Methode index(), die am Routennamen erkennt, ob es das Archiv ist. Alle Seiten rendert AccountTransactionsPageLoader:
listing()lädt die Seite (AccountTransactionsPage) mit allen Gruppen samt Typen und setzt den Seitentitel auf den Namen der gewählten Gruppe, ersatzweise der ersten Gruppe. In der Linie 6.7 fragt sie keine Vorgänge ab; die Liste lädt das CMS-Element im Browser nach. Die Seitenklasse initialisiert Vorgänge und Gruppen als leere Collections.detail()lädt einen Vorgang über die Store-API-Route, mit den Positionen (nachpositionaufsteigend) und den Downloads samt Medien.Beide setzen
noindex,followund senden vor der RückgabeAccountTransactionsPageLoadedEventbzw.AccountTransactionsDetailPageLoadedEvent. Beide enthalten die Seite (getPage()), den Kontext und die Anfrage.
SEO-URLs
Drei Klassen registrieren SEO-URL-Vorlagen (shopware.seo_url.route):
Klasse | Route | Standardvorlage |
|---|---|---|
|
|
|
|
|
|
|
|
|
DynamicSeoUrlPageSubscriber aktualisiert die URLs, wenn Vorgänge oder Gruppen geschrieben oder gelöscht werden.
CMS-Resolver
TransactionsCmsElementResolver(Typtransactions) lädt die gewählte Gruppe mit ihren Typen und deren nicht archivierten Vorgängen des Kunden. Er setztisSingleDisplayunddisableHeaderOverrideauftrue.ProcessesCmsElementResolver(Typprocesses) reicht die Einstellungentypes,archive,headlineundhelpTextweiter.Die drei übrigen Elemente haben keinen Resolver; ihre Daten kommen im Browser aus der Store-API.
Ereignisse für den Flow Builder und Mailversand
Der TransactionSubscriber hört auf leoparden_business_transactions_transaction.written und sendet für jedes Schreibergebnis ein Ereignis:
Ereignis | Name | Wann |
|---|---|---|
|
| Bei einem Insert |
|
| Bei jeder anderen Schreiboperation |
Der Verkaufskanal ist der gebundene Verkaufskanal des Kunden, sonst der erste gefundene. Gibt es keinen, wird kein Ereignis gesendet. Beide Ereignisse sind MailAware, CustomerAware, SalesChannelAware und TransactionAware; der Empfänger ist der Kunde des Vorgangs. Sie erscheinen im Flow Builder als Auslöser (Gruppe „Vorgang"), TransactionEventStorer speichert dafür transactionId und salesChannelId.
Die Installation legt den Mailvorlagentyp business_transaction_mail an („Vorgangsbenachrichtigung" bzw. „Transaction Mail"; verfügbare Entitäten: Verkaufskanal, Vorgang, Kunde) und eine Mailvorlage dazu: Absendername {{ salesChannel.name }}, Betreff „Ein neues Dokument wurde Ihrem Account hinzugefügt" bzw. „A new document was added to your account". Der Text begrüßt den Kunden mit Namen und teilt mit, dass ein neues Dokument hinzugefügt wurde; er nennt keine Vorgangsnummer. Das Plugin selbst versendet keine Mail: Einen Flow, der den Auslöser mit der Aktion „Mail senden" verbindet, legt der Betreiber an.
Migrationen
Migration | Aufgabe |
|---|---|
| Tabellen, Mailvorlage samt Typ, drei SEO-URL-Vorlagen |
| Benennt |
Deinstallation
LeopardenBusinessTransactions::uninstall() tut nur etwas, wenn der Benutzer die Daten nicht behalten will (keepUserData() === false). Dann entfernt es
alle SEO-URLs und SEO-URL-Vorlagen der drei Routen,
die Mailvorlagen des Typs
business_transaction_mailund den Typ selbst,alle CMS-Slots der Typen
transactions,processes,articles-on-order,recently-deliveredundmost-bought-by-customer(Layouts, die sie noch platzieren, würden sonst nicht mehr rendern),alle Konfigurationseinträge mit dem Präfix
LeopardenBusinessTransactions.config., auch die einzelner Verkaufskanäle,die sieben eigenen Tabellen. Die Fremdschlüsselprüfung schaltet es dafür kurz aus und danach auf den vorherigen Wert zurück.
Mit „Benutzerdaten behalten" bleibt alles erhalten.