Zum Inhalt

Plugin-Architektur

Das Prinzip: Erweiterbar, ohne den Hub zu ändern

Die Plugin-Architektur von merchantCENTRAL basiert auf dem Event-Subscriber-Pattern von Business Central. Der Hub selbst kennt keine einzige Connector-App – er weiß nicht, dass Amazon, Otto oder DHL existieren. Stattdessen stellt der Hub Events bereit, auf die sich Connector-Apps abonnieren.

Das bedeutet: Neue Kanäle, Lieferanten oder Versanddienstleister werden durch Installation einer App hinzugefügt – ohne eine einzige Codezeile im Hub zu ändern.

┌──────────────────────────────────────────────────────────────────┐
│                    merchantCENTRAL HUB                            │
│                                                                  │
│  ┌────────────────┐  ┌────────────────┐  ┌────────────────────┐  │
│  │ Event Publisher│  │ Event Publisher│  │ Event Publisher    │  │
│  │ Marketplace    │  │ Supplier      │  │ Shipment           │  │
│  │ (CU 70000)     │  │ (CU 70050)    │  │ (CU 70060)         │  │
│  └───────┬────────┘  └───────┬────────┘  └────────┬───────────┘  │
│          │                   │                     │             │
│          │    Events (OnDiscover*, OnCreate*, OnSync*, ...)      │
│          │                   │                     │             │
└──────────┼───────────────────┼─────────────────────┼─────────────┘
           │                   │                     │
     ┌─────┴─────┐      ┌─────┴─────┐         ┌─────┴─────┐
     │ Subscriber│      │ Subscriber│         │ Subscriber│
     │           │      │           │         │           │
     ▼           ▼      ▼           ▼         ▼           ▼
 ┌────────┐ ┌────────┐ ┌─────────┐ ┌──────┐ ┌─────┐ ┌─────┐
 │ Amazon │ │ Otto   │ │Jarltech │ │BlueSt│ │ DHL │ │ DPD │
 │ App    │ │ App    │ │ App     │ │ App  │ │ App │ │ App │
 └────────┘ └────────┘ └─────────┘ └──────┘ └─────┘ └─────┘

Drei Event-Publisher – drei Connector-Typen

Der Hub stellt drei Event Publisher Codeunits bereit, eine für jeden Connector-Typ:

1. Marketplace Event Publisher (CU 70000)

Verantwortlich für Marktplatz-Connectoren wie Amazon, Otto, Kaufland, eBay, Conrad, Shopify, Shopware, Cdiscount und SAP Ariba.

Wichtigste Events:

Event-Gruppe Events Zweck
Registrierung OnDiscoverMarketplaces, OnAfterRegister Connector meldet sich beim Hub an
Dashboard OnCollectDashboardData, OnCollectCueData KPI-Daten für das zentrale Dashboard
Bestellungen OnBeforeOrderImport, OnAfterOrderImport Bestellimport-Pipeline
Versandbestätigung OnBeforeShipmentConfirm, OnAfterShipmentConfirm Tracking an Marktplatz melden
Preise & Bestand OnSyncPrices, OnSyncInventory, OnCalculatePrice Preis-/Bestandssynchronisation
Artikelverwaltung OnBeforeCreateItem, OnAfterCreateItem, OnCollectItemData Marketplace-Artikellebenszyklus
Navigation OnBuildNavigationMenu, OnDrillDownItemCard Connector-spezifische Navigation
Tracking OnTrackingReceived, OnBeforeTrackingSync Sendungsverfolgung
Inventar OnCalculateAvailableInventory, OnGetChannelAllocatedQty Bestandsberechnung

2. Supplier Event Publisher (CU 70050)

Verantwortlich für Lieferanten-Connectoren wie Jarltech, BlueStar, Wave, VEDES, Systeam, AISCI, GoDEX, Sato, Toshiba, Papyrus, FixPrint, EverIT und IDENTBASE.

Wichtigste Events:

Event-Gruppe Events Zweck
Registrierung OnDiscoverSuppliers, OnAfterRegister Connector meldet sich an
Import OnExecuteImport, OnExecuteImportByCode Datenimport auslösen
Datenpipeline OnBeforeInsertData, OnAfterInsertData Daten in Pool schreiben
Preisberechnung OnCalculatePurchasePrice, OnCalculateSalesPrice Price Engine Events
Artikelabfragen OnGetBestSupplierOffer, OnGetTotalQuantity Bestes Angebot / Gesamtbestand
Stammdaten OnApplySupplierDataToItem, OnResolveItemNo Artikelmaster-Aktualisierung

3. Shipment Event Publisher (CU 70060)

Verantwortlich für Versanddienstleister-Connectoren wie DHL, DPD, GLS, UPS und Rhenus.

Wichtigste Events:

Event-Gruppe Events Zweck
Registrierung OnDiscoverProviders, OnAfterRegister Connector meldet sich an
Labels OnCreateLabel, OnAfterCreateLabel, OnGetLabel Label-Erstellung
Stornierung OnCancelShipment, OnAfterCancel Label/Sendung stornieren
Retoure OnCreateReturnLabel, OnAfterReturnLabel Retourenlabel
Manifest OnManifestShipments, OnGetManifestDocument Tagesabschluss
Test OnTestConnection Verbindungstest
Produkte OnGetAvailableProducts Verfügbare Carrier-Produkte

Das Discovery-Pattern

Alle drei Connector-Typen folgen dem identischen Registrierungsmuster:

┌──────────────────────────────────────────────────────────────────┐
│ Schritt 1: Hub ruft Discover-Funktion auf                        │
│            (z.B. bei App-Installation oder manuell)              │
│                                                                  │
│ Schritt 2: Hub erstellt temporäre Record-Tabelle                 │
│                                                                  │
│ Schritt 3: Hub feuert OnDiscover*-Event                          │
│            → Alle installierten Connector-Apps reagieren          │
│            → Jeder Connector fügt seinen Record ein:              │
│              Code, Name, Page IDs, Feature Flags, App Info       │
│                                                                  │
│ Schritt 4: Hub synchronisiert temp → permanent:                  │
│            → NEU: Record wird eingefügt (vollständig)            │
│            → BESTEHEND: Metadaten aktualisiert,                  │
│              Benutzer-Einstellungen (Enabled, Vendor No.) bleiben│
│                                                                  │
│ Schritt 5: Hub feuert OnAfterRegister*                           │
│            → Connector kann Nacharbeit leisten                   │
└──────────────────────────────────────────────────────────────────┘

Beispiel: Amazon-Connector registriert sich

[EventSubscriber(ObjectType::Codeunit, Codeunit::"ADG MC Event Publisher",
                  'OnDiscoverMarketplaces', '', false, false)]
local procedure OnDiscoverMarketplaces(var TempMarketplace: Record "ADG MC Marketplace")
begin
    TempMarketplace.Init();
    TempMarketplace.Code := 'AMAZON';
    TempMarketplace.Name := 'Amazon';
    TempMarketplace."Dashboard Page ID" := Page::"Amazon Dashboard";
    TempMarketplace."Order List Page ID" := Page::"Amazon Order List";
    TempMarketplace."Item List Page ID"  := Page::"Amazon Item List";
    TempMarketplace."Connector App ID"   := '...';
    TempMarketplace."Connector App Name" := 'MC Connector Amazon';
    TempMarketplace.Insert();
end;

Guard-Clause-Pattern

Da alle Connector-Apps auf dieselben Events hören, muss jeder Subscriber zuerst prüfen, ob er zuständig ist:

[EventSubscriber(..., 'OnCreateShipmentLabel', ...)]
local procedure OnCreateShipmentLabel(ProviderCode: Code[20]; ...)
begin
    if ProviderCode <> 'DHL' then
        exit;  // Nicht für mich → sofort raus

    // DHL-spezifische Label-Erstellung
    ...
    IsHandled := true;  // Signalisiert dem Hub: erledigt
end;

Dieses Pattern stellt sicher, dass: - Nur der zuständige Connector reagiert - Kein Connector versehentlich die Daten eines anderen verarbeitet - Die Performance nicht leidet (früher Ausstieg)

Hub-Services: Gemeinsam genutzte Infrastruktur

Der Hub stellt allen Connectoren gemeinsame Services bereit:

Service CU Was er bietet
Order Import 70011 Standardisierter Bestellimport: JSON → BC-Verkaufsauftrag
JSON Helper 70012 GetText, GetDecimal, GetInteger, GetArray, GetBoolean
Rate Limit Handler 70014 Exponential Backoff + Circuit Breaker für API-Rate-Limits
Carrier Mapping 70015 Tracking-Nummer → Carrier-Code, Tracking-URL-Templates
Connector Logger 70016 Einheitliches Logging: LogSuccess, LogError, LogInfo, LogApiCall
Credential Store 70018 Sichere Speicherung von API-Keys und OAuth-Tokens
Pagination Helper 70019 HATEOAS, Offset/Limit, Cursor, Token-basierte Paginierung
Doc Attachment 70020 PDF/Bilder an BC-Records anhängen
HTTP Helper 70021 Standardisierte HTTP-Aufrufe mit Logging und Zeitmessung
Item Mgmt. 70022 Zentrale Marketplace-Artikelverwaltung
OAuth2 Blob Helper 70023 Azure Blob Storage Download mit OAuth2 (Entra ID)
Inventory Calc 70024 10-Schritte-Bestandsberechnung
Email Builder 70004 HTML-E-Mail-Templates für Benachrichtigungen

Warum Hub-Services?

Ohne Hub-Services müsste jeder Connector eigene Implementierungen mitbringen für: - JSON-Parsing - HTTP-Aufrufe - Rate-Limiting - Logging - Bestandsberechnung - Bestellimport

Das wären mindestens 30 duplizierte Implementierungen über 9 Marketplace-, 13 Supplier- und 5 Shipment-Connectoren. Die Hub-Services eliminieren diese Redundanz vollständig.

Einen neuen Connector hinzufügen

Um einen neuen Marktplatz zu integrieren, braucht die neue Connector-App nur:

  1. OnDiscoverMarketplaces abonnieren und sich registrieren
  2. OnSyncInventory / OnSyncPrices abonnieren für Datenabgleich
  3. OnBeforeOrderImport abonnieren und Orders per Hub importieren
  4. OnTrackingReceived abonnieren und Tracking an die API senden

Alles andere – Dashboard, Bestandsberechnung, Preiskalkulation, Label-Erstellung, Logging – liefert der Hub automatisch.

Aufwand OHNE Hub:
  ┌─ API-Anbindung
  ├─ Bestellimport + Dublettenprüfung
  ├─ Kundenzuordnung
  ├─ Bestandslogik
  ├─ Preiskalkulation
  ├─ Versandlabel-Integration
  ├─ Logging
  ├─ Rate-Limiting
  └─ Dashboard / Reporting
     = 9 Baustellen

Aufwand MIT Hub:
  ┌─ API-Anbindung
  ├─ Event-Subscriber (5-10 Events)
  └─ Connector-spezifische Logik
     = 3 Baustellen (der Rest kommt vom Hub)

Vorteile der Plugin-Architektur

Unabhängige Releases

Jeder Connector hat einen eigenen Release-Zyklus. Ein Update des Amazon-Connectors erfordert kein Update des Hub oder anderer Connectoren.

Kundenseitige Auswahl

Kunden installieren nur die Connectoren, die sie benötigen. Ein Unternehmen, das nur auf Amazon und Otto verkauft, braucht keinen Kaufland- oder eBay-Connector.

Austauschbarkeit

Ein Connector kann durch eine alternative Implementierung ersetzt werden – solange er die gleichen Hub-Events bedient, funktioniert alles wie gewohnt.

Testbarkeit

Jeder Connector kann isoliert getestet werden. Der Hub stellt Mock-fähige Events bereit.

Graceful Degradation

Wenn ein optionales Modul (z. B. Price Engine, Print Service) nicht installiert ist, funktioniert der Hub trotzdem – mit Standard-Implementierungen oder ohne die optionale Funktion.

Verwandte Seiten