Vorgangsanzeige 1.1.15 Help

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

id

UUID

Primärschlüssel

number

String

Vorgangsnummer; Grundlage der SEO-URL

customerId/customer

FK, Pflicht

Der Kunde, dem der Vorgang gehört

orderId/order

FK

Optionale Verknüpfung mit einer Shopware-Bestellung (customer und order sind Eins-zu-eins-Beziehungen; die Beziehung order ist nicht ApiAware)

typeId/type

FK

Der Vorgangstyp

billingAddressId/billingAddress

FK

Kundenadresse als Rechnungsadresse

shippingAddressId/shippingAddress

FK

Kundenadresse als Lieferadresse (shippingAddressId ist nicht ApiAware)

fallbackBilling, fallbackShipping

Langtext

Freitext-Adressen, die die Detailseite statt der Kundenadresse zeigt, wenn gesetzt

paymentTerms

String

Zahlungsbedingungen

identifier

String

Referenznummer

description

Langtext

Betreff

documentDate, shippingDate

Datum

Belegdatum und Lieferdatum; das Lieferdatum trägt auch den Status

netAmount, grossAmount, taxAmount

Float

Beträge

updatedBy

String

Bearbeiter

archive

Bool

Archivkennzeichen

state

Int, Runtime

Berechneter Status, nicht gespeichert

items

1:n

Positionen

downloads

1:n

Dokumente zum Herunterladen

seoUrls

1:n

SEO-URLs des Vorgangs

customFields

JSON

Zusatzfelder (ohne ApiAware)

Weitere Entitäten

Entität

Felder

leoparden_business_transactions_transaction_item (Position)

position, transactionId (Pflicht), lineItemId/lineItem (Artikel), name, productNumber, amount, itemPrice, discount, linePrice, shippingDate, state (Runtime)

leoparden_business_transactions_transaction_downloads (Download)

transactionId und mediaId, beide Pflicht, mit den Beziehungen transaction und media

leoparden_business_transactions_transaction_type (Typ)

name (übersetzt), typeMatch (Int, Pflicht, Sortierzahl), groupId (Pflicht) / group, transactions

leoparden_transaction_type_group (Gruppe)

name (übersetzt), types

…_transaction_type_translation, leoparden_transaction_type_group_translation

je name (Pflicht)

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

UNKNOWN

31.12.2444

2444

DELIVERY_CLARIFYING

31.12.2500

2500

READY_WAITING_FOR_CONFIRMATION

31.12.2510

2510

ORDER_WAITING_FOR_CONFIRMATION

31.12.2520

2512

SHIPPING_WAITING_FOR_CONFIRMATION

31.12.2513

2513

WAITING_FOR_QUESTIONNAIRE

31.12.2530

2530

WAITING_FOR_SOMETHING

31.12.2555

2555

WAITING_FOR_PENDING_QUESTIONS

31.12.2599

2599

WAITING_FOR_SHIPPING_ADDRESS

31.12.2666

2666

WAITING_FOR_DELIVERY_ADDRESS

31.12.2700

2700

WAITING_FOR_BAFA

31.12.2777

2777

MISSING_BAFA

31.12.2888

2888

WAITING_FOR_CONFIRMATION

31.12.2900

2900

ORDER_WAITING_FOR_PAYMENT

31.12.2999

2999

SHIPPING_WAITING_FOR_PAYMENT

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 NULL

  • Position → Vorgang und Artikel: ON DELETE SET NULL

  • Download → 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

/store-api/transactions

store-api.business-transactions.transactions

Vorgang

/store-api/transaction-items

store-api.business-transactions.transaction-items

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: customerId bei den Vorgängen, transaction.customerId bei den Positionen

  • einen Filter auf die Typen der Kundengruppe, aus der Einstellung showCategoriesInTransactionsView (Klasse AllowedTypes). Filtert die Anfrage selbst nach typeId bzw. 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 sowie openCategories und invoiceCategories. Ein anderer Typ liefert nichts. Hat die Kundengruppe keine Zuordnung, bleibt die Liste leer. Ist showCategoriesInTransactionsView gar nicht gesetzt, wird nichts eingeschränkt.

  • bei den Vorgängen die Beziehungen items, type und type.group sowie eine Sortierung nach documentDate absteigend (zusätzlich zu den Sortierungen der Anfrage), bei den Positionen die Beziehung transaction

  • die 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

Content\Route\Transactions\TransactionCriteriaEvent

transactions

getCriteria(), setCriteria(), getContext()

Content\Route\TransactionItems\TransactionItemsCriteriaEvent

transaction-items

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

frontend.plugins.transactions

/Transactions

frontend.plugins.transactions.group

/transactions/group/{groupId}

frontend.plugins.transactions.group.archive

/transactions/group/{groupId}/archive

frontend.plugins.transactions.archive

/Transactions/Archive

frontend.plugins.transactions.detail

/transactions/detail/{transactionId}

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 (nach position aufsteigend) und den Downloads samt Medien.

  • Beide setzen noindex,follow und senden vor der Rückgabe AccountTransactionsPageLoadedEvent bzw. 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

AccountTransactionsDetailSeoRoute

frontend.plugins.transactions.detail

/Transaction/{{ transaction.number }}

AccountTransactionsGroupSeoRoute

frontend.plugins.transactions.group

/Transaction-Group/{{ group.name }}

AccountTransactionsGroupArchiveSeoRoute

frontend.plugins.transactions.group.archive

/Transaction-Group/{{ group.name }}/Archive

DynamicSeoUrlPageSubscriber aktualisiert die URLs, wenn Vorgänge oder Gruppen geschrieben oder gelöscht werden.

CMS-Resolver

  • TransactionsCmsElementResolver (Typ transactions) lädt die gewählte Gruppe mit ihren Typen und deren nicht archivierten Vorgängen des Kunden. Er setzt isSingleDisplay und disableHeaderOverride auf true.

  • ProcessesCmsElementResolver (Typ processes) reicht die Einstellungen types, archive, headline und helpText weiter.

  • 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

TransactionCreatedEvent

business_transaction.created

Bei einem Insert

TransactionUpdatedEvent

business_transaction.updated

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

Migration1692860629InstallPlugin

Tabellen, Mailvorlage samt Typ, drei SEO-URL-Vorlagen

Migration1782744702RenameSystemConfig

Benennt BusinessTransactions.config.* in LeopardenBusinessTransactions.config.* um

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_mail und den Typ selbst,

  • alle CMS-Slots der Typen transactions, processes, articles-on-order, recently-delivered und most-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.

Last modified: 08 November 2026