Beispiel-Nuclet zur Abbildung eines Lagerwesens.
Name: | Lager |
Package: | org.nuclet.lager |
Namensraum: | LAG |
Version: | 1.1.0 |
Datum: | 13.12.2013 |
Nuclos-Kompatibilität: | ab Nuclos 4.0 |
Überblick
Kurzbeschreibung
Das Lager-Nuclet liefert Funktionalität für ein Lagerwesen:
Lager, Lagerorte, Lagerbestände und Lagerbewegungen können erfasst werden
zusätzlich sind Lagerinventuren und Lagerumbuchungen möglich
Bei der Einbindung des Lager-Nuclets ist zu beachten, dass für die Lagerfunktionalität die Existenz gewisser Businessobjekte im Ziel-Nuclet vorausgesetzt wird. Diese Businessobjekte können bereits vor der Integration existieren, sie können aber auch nachträglich erstellt werden.
Bestandsdaten
Das Lager-Nuclet basiert einerseits auf einem Businessobjekt, die einen zu lagernden Artikel repräsentiert. Dieses Artikel-Businessobjekt wird innerhalb des Lager-Nuclets „Artikel“ genannt und derart referenziert, sie ist jedoch nicht Bestandteil des Lager-Nuclets selbst sondern sollte Teil des Ziel-Nuclets sein. Das dahinterliegende, zu hinterlegende bzw. tatsächliche Businessobjekt kann einen davon abweichenden Namen tragen (Material, Ware, Produkt, o.ä.).
Prozessdaten
Grundlage des Lager-Nuclets ist andererseits die Abbildung eines Prozesses, den die Artikel-Bestandsdaten durchlaufen können: Auftrag, Bestellung, Wareneingang, Warenausgang. Dieser Prozess ist im Lager-Nuclet durch vier Businessobjekte abgebildet, die ebenso wie das Artikel-Businessobjekt nicht Bestandteil des Lager-Nuclets sind, sondern Teil des Ziel-Nuclets sein sollten. Die von Ihnen zu bestimmenden, tatsächlichen Businessobjekte können frei benannt werden (bspw. ist es denkbar, dass ein Warenausgang als „Lieferschein“ realisiert wurde), nur sollte dabei beachtet werden, dass dieses Businessobjekt gleichermaßen Funktionsträger des Lager-Nuclets sein werden.
Abbildung 1: Lager-Prozess
Anmerkung: Businessobjekte, die im Lager-Nuclet verwendet werden, jedoch nicht Bestandteil des Lager-Nuclets sind, werden im folgenden „Schnittstellen-Businessobjekt“ genannt.
Mehr zur Einbindung und Anbindung des Lager-Nuclets in Ihre Anwendung finden Sie im Abschnitt „Integration“. Eine Integration des Lager-Nuclets ist im Basistemplate („Einkauf Verkauf“) realisiert worden und dort einzusehen.
Nuclet-Bestandteile
Das Lager-Nuclet umfasst im Rahmen der .nuclet-Datei
diverse Businessobjekte (für Lager, Lagerorte, Lagerbestände, etc.),
die Layouts für diese Businessobjekte,
zwei Statusmodelle (für Lagerinventuren und Lagerumbuchungen),
diverse Java-Regeln (verteilt auf Packages),
eine Benutzergruppe „Lager“,
eine Arbeitsumgebung „Lager“.
Typ | Name, englisch | Name, deutsch | Kurzbeschreibung |
---|---|---|---|
Businessobjekt | Lager | Lager |
|
| Lagerbestand | Lagerbestand |
|
| Lagerinventur | Lagerinventur |
|
| Lagerinventurbestand | Lagerinventurbestand |
|
| Lagerinventurgruppe | Lagerinventurgruppe |
|
| Lagerumbuchung | Lagerumbuchung |
|
| Lagerumbuchungsposition | Lagerumbuchungsposition |
|
Layout | Lager |
|
|
| Lagerinventur |
|
|
| Lagerumbuchung |
|
|
Statusmodell | Lagerinventur |
|
|
| Lagerumbuchung |
|
|
Java-Package | org.nuclet.lager.facade | Businessobjektbezogene Datenbankzugriffe | |
| org.nuclet.lager.logic | Geschäftslogik | |
| org.nuclet.lager.parameter | Konstantenklassen zur Parametrisierung | |
| org.nuclet.lager.rule | Steuerung von Insert-/Update-/Delete-Events, sowie Regeln für Statuswechsel | |
| org.nuclet.lager.wrapper | Wrapper-Klassen für Verallgemeinerungen und als Schnittstellen für die Java-Regeln des Lager-Nuclets | |
Benutzergruppe | Lager |
| Standard-Benutzergruppe |
Arbeitsumgebung | Lager |
|
Tabelle 1: Nuclet-Bestandteile
Java-Package-Struktur
Die Java-Regeln sind in fünf Packages unterteilt:
Regeln für maskengesteuerte Events (org.nuclet.lager.rule)
Regeln für die Geschäftslogik (org.nuclet.lager.logic)
Regeln für Businessobjektsbezogene Datenbankzugriffe (org.nuclet.lager.facade)
Regeln für enitätsübergreifende Verallgemeinerungen und als Schnittstelle für die Java-Klassen des Lager-Nuclets (org.nuclet.lager.wrapper)
Konstantenklassen für Preisinformationen (org.nuclet.lager.parameter)
Die Abhängigkeiten der Packages sind in der folgenden Abbildung veranschaulicht.
Abbildung 2: Java-Package-Struktur
Integration
Notwendige Schritte zur Integration
Die Integration des Lager-Nuclets erfolgt in 4 Schritten:
Download
Nuclet-Import
Konfiguration von System-Parametern (entfällt bis auf weiteres)
Anpassungen im Businessobjekt
Anpassungen in den Java-Regeln
Einhängen der Java-Regeln im Regel-Management
Alle Integrationschritte werden im folgenden im Detail erläutert.
Schritt 1: Download
Download der ZIP-Datei „Lager-v1.0.1.zip“ auf der Nuclos-Webpage unter „Nuclos Services“ > „Download“ > „Nuclet Download“. Das ZIP anschließend lokal entpacken.
Schritt 2: Nuclet-Import
Import des Basistemplate-Nuclets unter „Konfiguration“ > „Nuclet Management“ > „Importieren“ in Ihre bestehende Nuclos-Instanz, Auswahl der Datei „Lager-v1.0.1.nuclet“
Schritt 3: Konfiguration von System-Parametern (entfällt bis auf weiteres)
Die Einrichtung der verwendeten Nuclos-Systemparameter über „Administration“ > „Parameter“.
Parameter | Kurzbeschreibung |
---|---|
LAGERBESTAND_UEBERBUCHUNG | Lagerbestandsüberbuchung zulässig (true), oder nicht (false)? |
Tabelle 2: System-Parameter
Anmerkung: Dieser Schritt wird erst in einer zukünfigen Version notwendig, d.h. sobald die neue Nuclos-API das Auslesen von System-Parametern unterstützt. Solange dies nicht der Fall ist, erfolgt die Konfiguration in Schritt 5, durch Anpassung von entsprechenden Konstanten im Java-Code.
Schritt 4: Anpassungen im Businessobjekt
Im Businessobjektmodell des Lager-Nuclets werden drei Businessobjekte referenziert, die nicht Bestandteil des Lager-Nuclets sind:
Artikel (Artikel, Material, Ware, Produkt, o.ä.)
Artikelgruppe (Artikelgruppierung bzw. -klassifizierung)
Kunde (Kundendaten)
Artikel
Die Businessobjekte, die den Artikel (bzw. Material, Ware, Produkt, o.ä.) repräsentiert, wird in vier Businessobjekte referenziert:
Lagerbestand
Lagerbewegung
Lagerinventurbestand
Lagerumbuchungsposition
Diese Referenzen sind an die tatsächlich genutzte Businessobjekte anzubinden.
Artikelgruppe
Das Businessobjekt, das die Artikelgruppe repräsentiert, wird nur in der Businessobjekt „Lagerinventurgruppe“ referenziert.
Lager
Das Businessobjekt, das den Kunden repräsentiert, wird nur in der Businessobjekt „Lager“ referenziert.
Die folgende Abbildung stellt das Businessobjektmodell des Lager-Nuclets schematisch dar. Die bei der Integration nachzutragenden Referenzen, sind all jene Referenzen, die die Businessobjekte des Lager-Nuclets (schwarz) mit den „Schnittstellen-Businessobjekten“ (rot) verbinden.
Abbildung 3: Businessobjekt-Modell
Schritt 5: Source-Code Anpassungen in Java-Regeln
Java-Klasse / Java-Package | Kurzbeschreibung |
---|---|
org.nuclet.lager.facade.ArtikelFacadeFactory | Eintragen einer anwendungsspezifischen ArtikelFacade |
org.nuclet.lager.parameter.SystemParameter | Konfiguration, ob Lagerbestände überbucht werden dürfen (LAGERBESTAND_UEBERBUCHUNG) |
org.nuclet.lager.rule.LoeseBestellungAus | Auslösen von Bestellungen |
org.nuclet.lager.rule.ReserviereLagerbestand | Reservierung von Lagerbeständen |
org.nuclet.lager.rule.StorniereBestelldifferenz | Stornierung von Bestelldifferenzen |
org.nuclet.lager.rule.StorniereBestellung | Stornierung von Bestellungen |
org.nuclet.lager.rule.StorniereLagerbestandsreservierung | Stornierung von Bestandsreservierungen |
org.nuclet.lager.rule.StorniereReservierungsdifferenz | Stornierung von Reservierungsdifferenzen |
org.nuclet.lager.rule.VerbucheWarenausgang | Verbuchung von Warenausgängen |
org.nuclet.lager.rule.VerbucheWareneingang | Verbuchung von Wareneingängen |
org.nuclet.lager.wrapper.* | Wrapper-Klassen für Schnittstellen-Businessobjekte |
Tabelle 3: Anwendungsspezifische Anpassungen in Java-Regeln
Alle notwendigen Anpassungen werden nun der Reihe nach erläutert.
a) org.nuclet.lager.wrapper.*
Im Java-Package org.nuclet.lager.wrapper sind all jene Klassen als „Wrapper“ definiert, die als Schnittstelle für die Schnittstellen-Businessobjekte Artikel, Auftrag, Bestellung, Wareneingang und Warenausgang dienen:
Artikel: AbstractArtikelWrapper
Auftrag: AbstractAuftragWrapper und AbstractAuftragspositionWrapper
Bestellung: AbstractBestellungWrapper und AbstractBestellpositionWrapper
Warenausgang: AbstractWarenausgangWrapper und AbstractWarenausgangspositionWrapper
Wareneingang: AbstractWareneingangWrapper
Diese Wrapper-Klassen werden im Java-Code des Lager-Nuclets verwendet und sind bei der Nuclet-Integration mit eigenen, konkreten Ausprägungen zu ergänzen. Diese konkreten Implementierungen liefern dann den Zugriff auf die tatsächlichen Business-Objekte bzw. Businessobjekte.
Das folgende Diagramm veranschaulicht die Beziehungen zwischen diesen Businessobjekten und listet je Businessobjekt all jene Attribute auf, die über die Definition der abstrakten Wrapper-Klassen vorausgesetzt werden.
Zu beachten ist:
Für jede Wrapper-Klasse muss eine eigene konkrete Implementierung angelegt werden.
Hinter jeder konkreten Implementierung eines Wrappers sollte eine tatsächliche Businessobjekt mit ihrem Business-Objekt (d.h. der von Nuclos generierten Java-Klasse) stehen.
Jede konkrete Wrapper-Klasse sollte die in der abstrakten Wrapper-Klasse definierten Getter- und Setter-Methoden so implementieren, dass diese Methoden auf den Attributen der tatsächlichen Businessobjekt bzw. des entsprechenden Business-Objektes operieren (Beispiele, s.u.).
Abbildung 4: Schnittstellen-Businessobjekten
Achtung: Die fünf Schnittstellen-Businessobjekten Auftragsposition, Bestellposition, Lieferscheinposition, Warenausgangsposition und Wareneingang referenzieren die Lager-Businessobjekten "Lager" und "Lagerort" (teilweise doppelt über "Lager Bestellt", "Lagerort Bestellt", "Lager Reserviert", "Lagerort Reserviert". Es ist sinnvoll, diese Referenzen in die tatsächlich verwendeten Businessobjekten einzufügen.
Hier nun ein Beispiel für die abstrakte Definition und eine konkrete Implementierung einer solchen Wrapper-Klasse für die Artikel-Businessobjekt.
Zunächst die abstrakte Klasse:
/** * Abstrakte Wrapper-Klasse für Artikel-Objekte * * @note Schnittstelle bei Nuclet-Integration * */ public abstract class AbstractArtikelWrapper extends AbstractWrapper { /** * Liefert die Datenbank-ID des Artikels * * @return die Datenbank-ID des Artikels * */ public abstract Long getId(); /** * Liefert die Information, ob dieser Artikel im Lager geführt wird * * @return true, fall dieser Artikel im Lager geführt wird * */ public abstract Boolean getLagerfuehrung(); }
Die konkrete Implementierung dazu könnte bspw. die folgende Form annehmen, vorausgesetzt eine Businessobjekt bzw. ein Business-Objekt mit dem Namen „Artikel“ wäre vorhanden:
/** * Konkrete Implementierung von org.nuclet.lager.AbstractArtikelWrapper. * Setzt den Lager-Artikel gleich mit der Businessobjekt "Artikel". * */ public class ArtikelWrapper extends AbstractArtikelWrapper { public ArtikelWrapper(final BusinessObject businessObject) { if (businessObject instanceof Artikel) { this.businessObject = businessObject; } } public Long getId() { if (this.businessObject != null) { return ((Artikel)this.businessObject).getId(); } else { return null; } } public Boolean getLagerfuehrung() { if (this.businessObject != null) { return ((Artikel)this.businessObject).getLagerfuehrung(); } else { return null; } } }
b) org.nuclet.lager.parameter.SystemParameter
Es ist notwendig, die Konstante LAGERBESTAND_UEBERBUCHUNG für den eigenen Anwendungszweck zu konfigurieren:
LAGERBESTAND_UEBERBUCHUNG == true: eine Bestandsüberbuchung ist zulässig
LAGERBESTAND_UEBERBUCHUNG == false: eine Bestandsüberbuchung ist nicht zulässig
/** * Nuclos-System-Parameter * */ public class SystemParameter { // // @replace // // Konfiguration, ob eine Lagerbestandsüberbuchung zulässig ist (true) oder nicht (false): // public static final boolean LAGERBESTAND_UEBERBUCHUNG = false; }
Anmerkung: Dieser Schritt wird in einer zukünfigen Version entfallen, d.h. sobald die neue Nuclos-API das Auslesen von System-Parametern unterstützt. Sobald dies der Fall ist, wird diese Anpasung über Schritt 3 geregelt (s.o.).
b) org.nuclet.lager.facade.AbstractArtikelFacade
In diesem Schritt geht es darum, gewisse Zugriffsmethoden auf die Artikel-Businessobjekt in anwendungsspezifischer Form bereitzustellen. Hintergrund: Die Java-Regeln des Lager-Nuclets setzen diese Methoden voraus, da die Artikel-Businessobjekt jedoch kein Bestandteil des Nuclets ist (und je nach Anwendung unterschiedliche Formen annehmen kann), müssen diese Methoden für die tatsächlich verwendeten Businessobjekten und Business-Objekte erstellt werden.
Zunächst die abstrakte Fassaden-Klasse, in der die notwendigen Zugriffsmethoden definiert sind:
/** * Abstrakte Artikel-Facade * * */ public abstract class AbstractArtikelFacade { /** * Ermittelt alle Artikel zur gegebenen Artikelgruppe * * @param lngArtikelgruppeId die Datenbank-ID einer Artikelgruppe * * @return alle Artikel zur gegebenen Artikelgruppe * */ public abstract List<AbstractArtikelWrapper> getArtikelByArtikelgruppe(final Long lngArtikelgruppeId); /** * Ermittelt den Artikel zur gegebenen Datenbank-ID eines Artikels * * @param lngArtikelId die Datenbank-ID eines Artikels * * @return der Artikel zur gegebenen Datenbank-ID eines Artikels * */ public abstract AbstractArtikelWrapper getArtikelById(final Long lngArtikelId); }
Bitte beachten Sie, dass die Rückgabewerte stets auf den Wrapper-Klassen (s.o.) basieren. D.h. das empfohlene Vorgehen bei einer Implementierung dieser Fassade ist es, nach außen hin zu „wrappen“, weil die Java-Regeln des Lager-Nuclets auf diesen Wrapper-Klassen arbeiten. Innerhalb der Methoden aber muss mit den tatsächlichen Business-Objekten gearbeitet, um die Datenbankzugriffe realisieren zu können.
Hier ein Beispiel für eine konkrete Implementierung dieser Fassaden-Klasse – vorausgesetzt wird an dieser Stelle wiederum, eine Businessobjekt bzw. ein Business-Objekt mit dem Namen „Artikel“ wäre vorhanden:
/** * Facade für Artikel-bezogene Datenbankzugriffe * */ public class ArtikelFacade extends AbstractArtikelFacade { private static final ArtikelFacade instance = new ArtikelFacade(); /** * Liefert die Singleton-Instanz dieser Klasse * */ public static ArtikelFacade getInstance() { return instance; } public List<AbstractArtikelWrapper> getArtikelByArtikelgruppe(final Long lngArtikelgruppeId) { final List<AbstractArtikelWrapper> lstArtikelWrapper = new ArrayList<AbstractArtikelWrapper>(); final Query qryByArtikelgruppe = QueryProvider.create(Artikel.class) .where(Artikel.Artikelgruppe.eq(lngArtikelgruppeId)); final List<Artikel> lstArtikel = QueryProvider.execute(qryByArtikelgruppe); for (final Artikel artikel : lstArtikel) { lstArtikelWrapper.add(new ArtikelWrapper(artikel)); } return lstArtikelWrapper; } public AbstractArtikelWrapper getArtikelById(final Long lngArtikelId) { return new ArtikelWrapper(QueryProvider.getById(Artikel.class, lngArtikelId)); } }
Wenn eine derartige Fassaden-Klasse erstellt wurde, ist es schließlich noch notwendig, die Methode getArtikelFacade() in der Klasse org.nuclet.facade.ArtikelFacadeFactory anzupassen:
/** * Factory für konkrete Artikel-Facade * * */ public class ArtikelFacadeFactory { /** * Liefert eine Instanz einer konkreten Fassaden-Klasse für die Artikel-Businessobjekt * * @return eine Instanz einer konkreten Fassaden-Klasse für die Artikel-Businessobjekt * */ public static AbstractArtikelFacade getArtikelFacade() { // // @replace Bitte bei Nuclet-Integration mit eigenem Code ersetzen! // // Beispiel: // // return ArtikelFacade.getInstance(); // return null; } }
c) org.nuclet.lager.rule.*
Das Java-Package org.nuclet.lager.rule umfasst alle diejenigen Regeln, die die Insert/Update/Delete-Events und Statuswechsel von Objekten steuern.
Java-Klasse | Business-Objekt | Typ |
---|---|---|
LoeseBestellungAus | Bestellung | Statuswechsel |
ReserviereLagerbestand | Auftrag | Statuswechsel |
StorniereBestelldifferenz | Bestellung | Statuswechsel |
StorniereBestellung | Bestellung | Statuswechsel |
StorniereLagerbestandsreservierung | Auftrag | Statuswechsel |
StorniereReservierungsdifferenz | Auftrag | Statuswechsel |
VerbucheWarenausgang | Warenausgang | Statuswechsel |
VerbucheWareneingang | Bestellung | Insert |
Tabelle 10: Anpassungen im Package org.nuclet.lager.rule
Diese Regeln müssen derart gestaltet werden, dass die tatsächlich verwendeten Business-Objekte vom jeweiligen Context (InsertContext, UpdateContext, DeleteContext oder StateChangeContext) entgegengenommen werden, um sie anschließend in ein Wrapper-Objekt verpackt an die Methoden der Klasse org.nuclet.lager.LagerLogik weiterzureichen.
Die Regeln sind so vorbereitet, dass bereits geeignete Code-Fragmente auskommentiert in den Methodenrümpfen eingetragen sind. Diese Fragmente müssen bei der Integration also nur aktiviert und evtl. noch an die tatsächlich genutzten Java-Objekte (Business-Objekte und Wrapper-Klassen) angepasst werden.
Ggf. muss auch noch der Typ einiger Regeln variiert werden, wenn z.B. eine dieser Regeln eher für ein Insert/Update/Delete-Event verwendet werden müsste als für einen Statuswechsel.
Hier folgt nun der Source-Code der Klasse org.nuclet.lager.VerbucheWareneingang, um kurz zu zeigen, wie diese Regeln im Lager-Nuclet vor einer Integration aussehen. Im auskommentierten Beispiel wird als tatsächliche Ausprägung der Warenausgangs-Businessobjekt ein Business-Objekt „Lieferschein“ verwendet. An die Logik-Klasse LagerLogik wird ein entsprechendes Wrapper-Objekt weitergereicht:
/** @name VerbucheWarenausgang * @description Verbucht einen Warenausgang * @usage * @change */ @Rule(name="VerbucheWarenausgang", description="Verbucht einen Warenausgang") public class VerbucheWarenausgang implements StateChangeRule { public void changeState(StateChangeContext context) throws BusinessException { // // @replace Bei Nuclet-Integration zu Ersetzen mit eigenem Java-Code! // // // // Beispiel: // // final LagerLogik logik = new LagerLogik(context); // // final Lieferschein lieferschein = context.getBusinessObject(Lieferschein.class); // // logik.verbucheWarenausgang(new WarenausgangWrapper(lieferschein)); } }
Schritt 6: Einhängen der Java-Regeln im Regel-Management
Alle Java-Regeln, die in Schritt 5 angepasst worden sind, müssen im letzten Schritt noch den tatsächlichen Businessobjekten (bzw. deren Events oder Statuswechseln) zugeordnet werden. Dies erfolgt über den Menüpunkt „Konfiguration“ > „Regel Management“.
Diejenigen Regeln hingegen, die auf Businessobjekten des Lager-Nuclets operieren, sind im Regel-Baum bereits eingehängt.
Versionen
Version | Datum | Typ | Änderungen |
---|---|---|---|
1.0.0 | 25.04.2013 | initiale Version | - |
1.0.1 | 19.06.2013 | Fehlerkorrekturen |
|
1.1.0 | 13.12.2013 | Umstellung auf Nuclos 4.0 | Umstellung auf Nuclos 4.0 |