OmniSeller:PlugIn Entwicklung: Unterschied zwischen den Versionen

Zur Navigation springen Zur Suche springen
keine Bearbeitungszusammenfassung
Keine Bearbeitungszusammenfassung
Keine Bearbeitungszusammenfassung
 
(8 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
<div class="contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary dark:bg-gray-950"><div class="overflow-y-auto p-4" dir="ltr"><code class="!whitespace-pre hljs language-mediawiki">= OmniSeller PlugIn Entwicklung =
[[Datei:Omniseller plugin c.png|300px|thumb]]
 
<h1>OmniSeller PlugIn Entwicklung</h1>
== Überblick ==
<h2>Überblick</h2>
Der OmniSeller DataService bietet die Möglichkeit, externe Logik über PlugIns zu integrieren. PlugIns können entwickelt werden, um spezifische Geschäftsanforderungen zu erfüllen, beispielsweise das Anpassen von Produktdaten vor dem Upload oder das Modifizieren von Preisen basierend auf bestimmten Kriterien.
<p>Der OmniSeller DataService bietet die Möglichkeit, externe Logik über PlugIns zu integrieren. PlugIns können entwickelt werden, um spezifische Geschäftsanforderungen zu erfüllen, beispielsweise das Anpassen von Produktdaten vor dem Upload oder das Modifizieren von Preisen basierend auf bestimmten Kriterien.</p>
 
<p>OmniSeller PlugIns basieren auf <b>.NET Standard 2.0</b>, um sowohl mit alten (.NET Framework 4.7.2) als auch mit neuen (.NET 6.0) Service-Versionen kompatibel zu sein.</p>
OmniSeller PlugIns basieren auf '''.NET Standard 2.0''', um sowohl mit alten (.NET Framework 4.7.2) als auch mit neuen (.NET 6.0) Service-Versionen kompatibel zu sein.
<h2>Voraussetzungen</h2>
 
<ul>
== Voraussetzungen ==
    <li><b>Entwicklungsumgebung:</b>
# '''Entwicklungsumgebung''':
        <ul>
#* Visual Studio 2019 oder höher.
            <li>Visual Studio 2019 oder höher</li>
#* .NET Standard 2.0 als Zielplattform für PlugIns.
            <li>.NET Standard 2.0 als Zielplattform für PlugIns</li>
# '''Abhängigkeiten''':
</ul></li>
#* `OmniSeller.Common` und `OmniSeller.Enums` aus dem **HTK NuGet Repository**:
    <li><b>Abhängigkeiten:</b>
# ```plaintext
        <ul>
# https://htkpackages/repository/
            <li>OmniSeller.Common und OmniSeller.Enums aus dem HTK NuGet Repository HTKPackages<code></code></li>
# ```
</ul></li>
# '''Nützliche Schnittstellen und Modelle''':
    <li><b>Nützliche Schnittstellen und Modelle:</b>
#* `IEntryPointPlugin` (aus `OmniSeller.Common`).
        <ul>
#* `Enums.EntryPoint` und `Enums.ShopTypes`.
            <li>IEntryPointPlugin (aus OmniSeller.Common)</li>
# '''Zugriff auf ein bestehendes OmniSeller-System''', um das PlugIn zu testen.
            <li>Enums.EntryPoint und Enums.ShopTypes</li>
 
</ul></li>
== Struktur eines OmniSeller PlugIns ==
    <li><b>Zugriff auf ein bestehendes OmniSeller-System</b>, um das PlugIn zu testen</li>
Ein OmniSeller PlugIn muss die Schnittstelle `IEntryPointPlugin` implementieren, die folgende Eigenschaften und Methoden definiert:
</ul>
 
<h2>Struktur eines OmniSeller PlugIns</h2>
```csharp
<p>Ein OmniSeller PlugIn muss die Schnittstelle <code>IEntryPointPlugin</code> implementieren, die folgende Eigenschaften und Methoden definiert:</p>
<pre>
public interface IEntryPointPlugin
public interface IEntryPointPlugin
{
{
     string Name { get; } // Der Name des PlugIns
     string Name { get; }
     EntryPoint SupportedEntryPoints { get; } // Unterstützte EntryPoints
     EntryPoint SupportedEntryPoints { get; }
     string Version { get; } // Version des PlugIns
     string Version { get; }
     int SortOrder { get; } // Reihenfolge des PlugIns
     int SortOrder { get; }
     string Author { get; } // Entwicklername
     string Author { get; }
     string Publisher { get; } // Herausgebername
     string Publisher { get; }
     ShopTypes SupportedShopTypes { get; } // Unterstützte Shop-Typen
     ShopTypes SupportedShopTypes { get; }
     string Notes { get; } // Notizen/Hinweise
     string Notes { get; }
 
     Product Call(ShopTypes shopType, int portalID, Product productObj, EntryPoint entryPoint);
     Product Call(ShopTypes shopType, int portalID, Product productObj, EntryPoint entryPoint); // Hauptlogik
}
}
</code></div></div><p>=== Beispiel für ein PlugIn: ZeroPricePlugIn === Dieses PlugIn setzt automatisch den niedrigsten Preis für Produkte, die den Preis <code>0</code> haben, basierend auf den Preisen der Kind-Produkte.</p><div class="contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary dark:bg-gray-950"><div class="flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none">csharp</div><div class="sticky top-9 md:top-[5.75rem]"><div class="absolute bottom-0 right-2 flex h-9 items-center"><div class="flex items-center rounded bg-token-sidebar-surface-primary px-2 font-sans text-xs text-token-text-secondary dark:bg-token-main-surface-secondary"><button class="flex gap-1 items-center select-none py-1">Code kopieren</button></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="!whitespace-pre hljs language-csharp"><span class="hljs-keyword">using</span> OmniSeller.Enums;
</pre>
<span class="hljs-keyword">using</span> OmniSellerPlugins.Interfaces;
<h3>Beispiel für ein PlugIn: ZeroPricePlugIn</h3>
<span class="hljs-keyword">using</span> OmniSellerPlugins.Models;
<p>Dieses PlugIn setzt automatisch den niedrigsten Preis für Produkte, die den Preis <code>0</code> haben, basierend auf den Preisen der Kind-Produkte.</p>
<span class="hljs-keyword">using</span> System;
<pre>
using OmniSeller.Enums;
using OmniSellerPlugins.Interfaces;
using OmniSellerPlugins.Models;
using System;


<span class="hljs-keyword">namespace</span> <span class="hljs-title">OmniSeller.PlugIns</span>
namespace OmniSeller.PlugIns
{
{
     <span class="hljs-keyword">internal</span> <span class="hljs-keyword">class</span> <span class="hljs-title">ZeroPricePlugIn</span> : <span class="hljs-title">IEntryPointPlugin</span>
     internal class ZeroPricePlugIn : IEntryPointPlugin
     {
     {
         <span class="hljs-keyword">public</span> <span class="hljs-built_in">string</span> Name =&gt; <span class="hljs-string">"OmniSellerZeroPricePlugIn"</span>;
         public string Name => "OmniSellerZeroPricePlugIn";
         <span class="hljs-keyword">public</span> EntryPoint SupportedEntryPoints =&gt; EntryPoint.PRICE_BEFORE_UPLOAD;
         public EntryPoint SupportedEntryPoints => EntryPoint.PRICE_BEFORE_UPLOAD;
         <span class="hljs-keyword">public</span> <span class="hljs-built_in">string</span> Version =&gt; <span class="hljs-string">"1.0.0.0"</span>;
         public string Version => "1.0.0.0";
         <span class="hljs-keyword">public</span> <span class="hljs-built_in">int</span> SortOrder =&gt; <span class="hljs-number">1000</span>;
         public int SortOrder => 1000;
         <span class="hljs-keyword">public</span> <span class="hljs-built_in">string</span> Author =&gt; <span class="hljs-string">"AS"</span>;
         public string Author => "AS";
         <span class="hljs-keyword">public</span> <span class="hljs-built_in">string</span> Publisher =&gt; <span class="hljs-string">"HTK GmbH & Co.KG"</span>;
         public string Publisher => "HTK GmbH & Co.KG";
         <span class="hljs-keyword">public</span> ShopTypes SupportedShopTypes =&gt; ShopTypes.Magento;
         public ShopTypes SupportedShopTypes => ShopTypes.Magento;
         <span class="hljs-keyword">public</span> <span class="hljs-built_in">string</span> Notes =&gt; <span class="hljs-string">"Kein Hinweistext"</span>;
         public string Notes => "Kein Hinweistext";


         <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ZeroPricePlugIn</span>()</span>
         public ZeroPricePlugIn()
         {
         {
             Console.WriteLine(<span class="hljs-string">$"Running PlugIn <span class="hljs-subst">{Name}</span>"</span>);
             Console.WriteLine($"Running PlugIn {Name}");
         }
         }


         <span class="hljs-function"><span class="hljs-keyword">public</span> Product <span class="hljs-title">Call</span>(<span class="hljs-params">ShopTypes shopType, <span class="hljs-built_in">int</span> portalID, Product productObj, EntryPoint entryPoint</span>)</span>
         public Product Call(ShopTypes shopType, int portalID, Product productObj, EntryPoint entryPoint)
         {
         {
             Console.WriteLine(<span class="hljs-string">$"Running PlugIn <span class="hljs-subst">{Name}</span> for <span class="hljs-subst">{shopType}</span> at <span class="hljs-subst">{entryPoint}</span>"</span>);
             Console.WriteLine($"Running PlugIn {Name} for {shopType} at {entryPoint}");
             <span class="hljs-keyword">if</span> (shopType == ShopTypes.Magento)
             if (shopType == ShopTypes.Magento)
             {
             {
                 <span class="hljs-comment">// Logik zur Anpassung von Produktpreisen</span>
                 // Logik zur Anpassung von Produktpreisen
             }
             }
             <span class="hljs-keyword">return</span> productObj;
             return productObj;
         }
         }
     }
     }
}
}
</code></div></div><p>== Schritt-für-Schritt-Anleitung zur Erstellung eines PlugIns == === 1. Projekt einrichten ===</p>
</pre>
*Erstelle ein neues '''.NET Standard 2.0''' Class Library-Projekt in Visual Studio.
<h2>Schritt-für-Schritt-Anleitung zur Erstellung eines PlugIns</h2>
*Füge die folgenden Pakete über das HTK NuGet Repository hinzu:
<h3>1. Projekt einrichten</h3>
<div class="contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary dark:bg-gray-950"><div class="flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none">plaintext</div><div class="sticky top-9 md:top-[5.75rem]"><div class="absolute bottom-0 right-2 flex h-9 items-center"><div class="flex items-center rounded bg-token-sidebar-surface-primary px-2 font-sans text-xs text-token-text-secondary dark:bg-token-main-surface-secondary"><button class="flex gap-1 items-center select-none py-1">Code kopieren</button></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="!whitespace-pre hljs language-plaintext">OmniSeller.Common
<ul>
    <li>Erstelle ein neues <b>.NET Standard 2.0</b> Class Library-Projekt in Visual Studio</li>
    <li>Füge die folgenden Pakete über das HTK NuGet Repository hinzu:</li>
<pre>
OmniSeller.Common
OmniSeller.Enums
OmniSeller.Enums
</code></div></div><p>=== 2. PlugIn-Logik implementieren ===</p>
    </pre></ul>
*Implementiere die Schnittstelle <code>IEntryPointPlugin</code>.
<h3>2. PlugIn-Logik implementieren</h3>
*Definiere die unterstützten <code>EntryPoints</code> und <code>ShopTypes</code>.
<ul>
*Implementiere die Logik in der Methode <code>Call</code>.
    <li>Implementiere die Schnittstelle <code>IEntryPointPlugin</code>.</li>
<p>=== 3. PlugIn erstellen und veröffentlichen ===</p>
    <li>Definiere die unterstützten <code>EntryPoints</code> und <code>ShopTypes</code>.</li>
*Kompiliere das Projekt.
    <li>Implementiere die Logik in der Methode <code>Call</code>.</li>
*Die resultierende <code>.dll</code>-Datei (zusammen mit ihren Abhängigkeiten) wird in das OmniSeller PlugIn-Verzeichnis kopiert:
</ul>
<div class="contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary dark:bg-gray-950"><div class="flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none">plaintext</div><div class="sticky top-9 md:top-[5.75rem]"><div class="absolute bottom-0 right-2 flex h-9 items-center"><div class="flex items-center rounded bg-token-sidebar-surface-primary px-2 font-sans text-xs text-token-text-secondary dark:bg-token-main-surface-secondary"><button class="flex gap-1 items-center select-none py-1">Code kopieren</button></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="!whitespace-pre hljs language-plaintext">C:\OmniVersum\Apps\OmniSellerService2\PlugIns
<h3>3. PlugIn erstellen und veröffentlichen</h3>
</code></div></div><p>=== 4. PlugIn testen ===</p>
<ul>
*Starte den OmniSeller DataService und beobachte die Logs.
    <li>Kompiliere das Projekt.</li>
*Das PlugIn wird automatisch geladen und ausgeführt, wenn der entsprechende <code>EntryPoint</code> erreicht wird.
    <li>Die resultierende <code>.dll</code>-Datei (zusammen mit ihren Abhängigkeiten) wird in das OmniSeller PlugIn-Verzeichnis kopiert:</li>
<p>== EntryPoints und deren Bedeutung == {| class="wikitable" |- ! EntryPoint</p>
<pre>C:\OmniVersum\Apps\OmniSellerService2\PlugIns</pre></ul>
{|<thead>
<h3>4. PlugIn testen</h3>
|-
<ul>
! ! Beschreibung</thead>
    <li>Starte den OmniSeller DataService und beobachte die Logs.</li>
|-
    <li>Das PlugIn wird automatisch geladen und ausgeführt, wenn der entsprechende <code>EntryPoint</code> erreicht wird.</li>
| <code>PORTAL_STARTUP</code>
</ul>
|-
<h2>EntryPoints und deren Bedeutung</h2>
| Wird beim Start eines Portals ausgeführt.
 
|-
{| border="1"
| -
|-  
|-
! | EntryPoint
| <code>PRODUCT_BEFORE_UPLOAD</code>
! | Beschreibung
|-
|-  
| Vor dem Produkt-Upload.
| | PORTAL_STARTUP
|-
| | Wird beim Start einer Portalwarteschlange ausgeführt (einmalig).
| -
|-  
|-
| | PRODUCT_BEFORE_UPLOAD
| <code>PRODUCT_AFTER_UPLOAD</code>
| | Vor dem Produkt-Upload.
|-
|-  
| Nach dem Produkt-Upload.
| | PRODUCT_AFTER_UPLOAD
|-
| | Nach dem Produkt-Upload.
| -
|-  
|-
| | STOCK_BEFORE_UPLOAD
| <code>PRICE_BEFORE_UPLOAD</code>
| | Vor dem Preis-Upload.
|-
|-  
| Vor dem Preis-Upload.
| | STOCK_AFTER_UPLOAD
|-
| | Nach dem Preis-Upload.
| -
|-  
|-
| | ORDER_AFTER_DOWNLOAD
| <code>PRICE_AFTER_UPLOAD</code>
| | Nach dem Herunterladen einer Bestellung.
|-
| Nach dem Preis-Upload.
|-
| -
|-
| <code>ORDER_AFTER_DOWNLOAD</code>
|-
| Nach dem Herunterladen einer Bestellung.
|-
| }
|}
|}
<p>== Best Practices für PlugIns ==</p>
 
= '''Vermeide lange Blockaden''': =
<h2>Best Practices für PlugIns</h2>
<p>#* Die Methode <code>Call</code> sollte möglichst schnell ausgeführt werden, um Verzögerungen im DataService zu vermeiden.</p>
<ul>
= '''Fehlerbehandlung''': =
    <li><b>Vermeide lange Blockaden:</b>
<p>#* Verwende <code>try-catch</code>, um Laufzeitfehler zu verhindern, die den gesamten Service beeinflussen könnten.</p>
        <ul>
= '''Testumgebung nutzen''': =
            <li>Die Methode <code>Call</code> sollte möglichst schnell ausgeführt werden, um Verzögerungen im DataService zu vermeiden.</li>
<p>#* Teste das PlugIn in einer Entwicklungs- oder Staging-Umgebung, bevor es in die Produktion übernommen wird.</p>
</ul></li>
= '''Log-Ausgaben''': =
    <li><b>Fehlerbehandlung:</b>
<p>#* Nutze <code>Console.WriteLine</code>, um wichtige Informationen und Debug-Daten während der PlugIn-Ausführung zu loggen.</p><p>== Beispielhafte Ordnerstruktur ==</p><div class="contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary dark:bg-gray-950"><div class="flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none">plaintext</div><div class="sticky top-9 md:top-[5.75rem]"><div class="absolute bottom-0 right-2 flex h-9 items-center"><div class="flex items-center rounded bg-token-sidebar-surface-primary px-2 font-sans text-xs text-token-text-secondary dark:bg-token-main-surface-secondary"><button class="flex gap-1 items-center select-none py-1">Code kopieren</button></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="!whitespace-pre hljs language-plaintext">C:\OmniVersum\Apps\OmniSellerService2\
        <ul>
            <li>Verwende <code>try-catch</code>, um Laufzeitfehler zu verhindern, die den gesamten Service beeinflussen könnten.</li>
</ul></li>
    <li><b>Testumgebung nutzen:</b>
        <ul>
            <li>Teste das PlugIn in einer Entwicklungs- oder Staging-Umgebung, bevor es in die Produktion übernommen wird.</li>
</ul></li>
    <li><b>Log-Ausgaben:</b>
        <ul>
            <li>Nutze <code>Console.WriteLine</code>, um wichtige Informationen und Debug-Daten während der PlugIn-Ausführung zu loggen.</li>
</ul></li>
</ul>
<h2>Beispielhafte Ordnerstruktur</h2>
<pre>
C:\OmniVersum\Apps\OmniSellerService2\
├── PlugIns\
├── PlugIns\
│  ├── OmniSellerZeroPricePlugIn.dll
│  ├── OmniSellerZeroPricePlugIn.dll
Zeile 142: Zeile 154:
│  ├── OmniSeller.Enums.dll
│  ├── OmniSeller.Enums.dll
├── OmniSellerService.exe
├── OmniSellerService.exe
</code></div></div><p>== Häufige Fehler und Lösungen ==</p>
</pre>
= '''PlugIn wird nicht geladen''': =
<h2>Häufige Fehler und Lösungen</h2>
<p>#* Überprüfe, ob die <code>IEntryPointPlugin</code>-Schnittstelle korrekt implementiert wurde. #* Stelle sicher, dass alle Abhängigkeiten (z. B. <code>OmniSeller.Common</code>) verfügbar sind.</p>
<ul>
= '''Assembly-Version inkompatibel''': =
    <li><b>PlugIn wird nicht geladen:</b>
<p>#* Stelle sicher, dass die Hauptanwendung und das PlugIn dieselben Versionen von <code>OmniSeller.Common</code> und <code>OmniSeller.Enums</code> verwenden.</p>
        <ul>
= '''Kein <code>EntryPoint</code> aktiviert''': =
            <li>Überprüfe, ob die <code>IEntryPointPlugin</code>-Schnittstelle korrekt implementiert wurde.</li>
<p>#* Prüfe, ob der EntryPoint des PlugIns (<code>SupportedEntryPoints</code>) mit dem vom Service ausgelösten EntryPoint übereinstimmt.</p><p>Falls es weitere Fragen oder Probleme gibt, wende dich an das '''OmniSeller-Entwicklungsteam'''.</p>
            <li>Stelle sicher, dass alle Abhängigkeiten (z. B. <code>OmniSeller.Common</code>) verfügbar sind.</li>
</ul></li>
    <li><b>Assembly-Version inkompatibel:</b>
        <ul>
            <li>Stelle sicher, dass die Hauptanwendung und das PlugIn dieselben Versionen von <code>OmniSeller.Common</code> verwenden.</li>
</ul></li>
    <li><b>Kein <code>EntryPoint</code> aktiviert:</b>
        <ul>
            <li>Prüfe, ob der EntryPoint des PlugIns (<code>SupportedEntryPoints</code>) mit dem vom Service ausgelösten EntryPoint übereinstimmt.<br><br><br></li>
</ul></li>
</ul>
<h1>Hinweis zur PlugIn-Entwicklung</h1>
<p>Die Möglichkeit, individuelle PlugIns für den OmniSeller DataService zu erstellen, bietet eine flexible und maßgeschneiderte Lösung für spezifische Kundenanforderungen. Bitte beachten Sie jedoch:</p>
<ul>
    <li><b>Die Entwicklung von PlugIns ist nicht Bestandteil unserer regulären Pakete, einschließlich des Enterprise-Pakets.</b></li>
    <li><b>Eine PlugIn-Entwicklung erfordert immer eine gesonderte Absprache mit HTK.</b></li>
</ul>
<p>PlugIns ermöglichen Anpassungen, die über den Standardumfang hinausgehen. Sie sind ideal, um individuelle Geschäftsprozesse oder spezielle Anforderungen abzubilden, erfordern jedoch eine präzise Abstimmung zwischen Ihnen und unserem Entwicklungsteam.</p>
<h2>Was bedeutet das für Sie?</h2>
<ul>
    <li><b>Keine Standardfunktion:</b> Die PlugIn-Entwicklung ist eine Zusatzleistung und nicht automatisch im Lieferumfang unserer OmniSeller-Pakete enthalten (auch nicht im Enterprise Paket).</li>
    <li><b>Gesonderte Kosten:</b> Jede PlugIn-Entwicklung wird individuell kalkuliert und als separate Leistung abgerechnet.</li>
    <li><b>Kundenspezifische Lösung:</b> PlugIns werden speziell für Ihre Anforderungen erstellt und sind nicht universell einsetzbar.</li>
</ul>
<p>Wenn Sie Interesse an der Entwicklung eines PlugIns haben, kontaktieren Sie bitte Ihren Ansprechpartner bei HTK. Wir freuen uns darauf, Ihre Anforderungen zu besprechen und Ihnen eine passende Lösung anzubieten.</p>
<p>
    <i>HTK behält sich das Recht vor, PlugIn-Anfragen zu prüfen und gegebenenfalls abzulehnen, falls diese nicht mit den technischen oder geschäftlichen Rahmenbedingungen vereinbar sind.</i></p>
1.488

Bearbeitungen

Navigationsmenü