Sie zeigen eine alte Version dieser Seite an. Zeigen Sie die aktuelle Version an.

Unterschiede anzeigen Seitenhistorie anzeigen

« Vorherige Version anzeigen Version 3 Nächste Version anzeigen »

Beispiel-Nuclet zur Abbildung eines Lagerwesens.

 

Name:Lager
Package:org.nuclet.lager
Namensraum:LAG
Version:1.0.0
Datum:25.04.2013


Ü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 Entitäten im Ziel-Nuclet vorausgesetzt wird. Diese Entitäten können bereits vor der Integration existieren, sie können aber auch nachträglich erstellt werden.

 

Bestandsdaten

Das Lager-Nuclet basiert einerseits auf einer Entität, die einen zu lagernden Artikel repräsentiert. Diese Artikel-Entität 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. Die dahinterliegende, zu hinterlegende bzw. tatsächliche Entität 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 Entitäten abgebildet, die ebenso wie die Artikel-Entität nicht Bestandteil des Lager-Nuclets sind, sondern Teil des Ziel-Nuclets sein sollten. Die von Ihnen zu bestimmenden, tatsächlichen Entitäten können frei benannt werden (bspw. ist es denkbar, dass ein Warenausgang als „Lieferschein“ realisiert wurde), nur sollte dabei beachtet werden, dass diese Entitäten gleichermaßen Funktionsträger des Lager-Nuclets sein werden.

 

 

Abbildung 1: Lager-Prozess


Anmerkung: Entitäten, die im Lager-Nuclet verwendet werden, jedoch nicht Bestandteil des Lager-Nuclets sind, werden im folgenden „Schnittstellen-Entitäten“ 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 Entitäten (für Lager, Lagerorte, Lagerbestände, etc.),

  • die Layouts für diese Entitäten,

  • 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

Entität

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

entitätenbezogene 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 entitätsbezogene 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:

  1. Download

  2. Nuclet-Import

  3. Konfiguration von System-Parametern (entfällt bis auf weiteres)

  4. Anpassungen im Entitäten-Wizard

  5. Anpassungen in den Java-Regeln

  6. 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.0.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.0.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 Entitäten-Wizard

Im Entitätenmodell des Lager-Nuclets werden drei Entitäten referenziert, die nicht Bestandteil des Lager-Nuclets sind:

  • Artikel (Artikel, Material, Ware, Produkt, o.ä.)

  • Artikelgruppe (Artikelgruppierung bzw. -klassifizierung)

  • Kunde (Kundendaten)

 

Artikel

Die Entität, die den Artikel (bzw. Material, Ware, Produkt, o.ä.) repräsentiert, wird in vier Entitäten referenziert:

  • Lagerbestand

  • Lagerbewegung

  • Lagerinventurbestand

  • Lagerumbuchungsposition

Diese Referenzen sind an die tatsächlich genutzte Entität anzubinden.

 

Artikelgruppe

Die Entität, die die Artikelgruppe repräsentiert, wird nur in der Entität „Lagerinventurgruppe“ referenziert.

 

Lager

Die Entität, die den Kunden repräsentiert, wird nur in der Entität „Lager“ referenziert.

 

Die folgende Abbildung stellt das Entitätenmodell des Lager-Nuclets schematisch dar. Die bei der Integration nachzutragenden Referenzen, sind all jene Referenzen, die die Entitäten des Lager-Nuclets (schwarz) mit den „Schnittstellen-Entitäten“ (rot) verbinden.

 

 

Abbildung 3: Entitäten-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-Entitäten

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-Entitäten 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. Entitäten.

 

Das folgende Diagramm veranschaulicht die Beziehungen zwischen diesen Entitäten und listet je Entität all jene Attribute auf, die über die Definition der abstrakten Wrapper-Klassen vorausgesetzt werden.

Zu beachten ist:

  1. Für jede Wrapper-Klasse muss eine eigene konkrete Implementierung angelegt werden.

  2. Hinter jeder konkreten Implementierung eines Wrappers sollte eine tatsächliche Entität mit ihrem Business-Objekt (d.h. der von Nuclos generierten Java-Klasse) stehen.

  3. 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 Entität bzw. des entsprechenden Business-Objektes operieren (Beispiele, s.u.).

 

Abbildung 4: Schnittstellen-Entitäten

 

Hier nun ein Beispiel für die abstrakte Definition und eine konkrete Implementierung einer solchen Wrapper-Klasse für die Artikel-Entität.

Zunächst die abstrakte Klasse:

AbstractArtikelWrapper
/**
 * 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 Entität bzw. ein Business-Objekt mit dem Namen „Artikel“ wäre vorhanden:

 

ArtikelWrapper
/**
 * Konkrete Implementierung von org.nuclet.lager.AbstractArtikelWrapper. 
 * Setzt den Lager-Artikel gleich mit der Entität "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

SystemParameter
/**
 * 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-Entität in anwendungsspezifischer Form bereitzustellen. Hintergrund: Die Java-Regeln des Lager-Nuclets setzen diese Methoden voraus, da die Artikel-Entität jedoch kein Bestandteil des Nuclets ist (und je nach Anwendung unterschiedliche Formen annehmen kann), müssen diese Methoden für die tatsächlich verwendeten Entitäten und Business-Objekte erstellt werden.

Zunächst die abstrakte Fassaden-Klasse, in der die notwendigen Zugriffsmethoden definiert sind:

AbstractArtikelFacade
/**
 * 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 Entität bzw. ein Business-Objekt mit dem Namen „Artikel“ wäre vorhanden:

ArtikelFacade
/** 
 * 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:

 

ArtikelFacadeFactory
/**
 * Factory für konkrete Artikel-Facade
 * 
 *
 */
public class ArtikelFacadeFactory 
{
    /**
     * Liefert eine Instanz einer konkreten Fassaden-Klasse für die Artikel-Entität
     * 
     * @return eine Instanz einer konkreten Fassaden-Klasse für die Artikel-Entität
     *
     */
    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-Entität ein Business-Objekt „Lieferschein“ verwendet. An die Logik-Klasse LagerLogik wird ein entsprechendes Wrapper-Objekt weitergereicht:

 

VerbucheWareneingang
/** @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 Entitäten (bzw. deren Events oder Statuswechseln) zugeordnet werden. Dies erfolgt über den Menüpunkt „Konfiguration“ > „Regel Management“.

Diejenigen Regeln hingegen, die auf Entitäten des Lager-Nuclets operieren, sind im Regel-Baum bereits eingehängt.


  • Keine Stichwörter