SQL-Ereignisse (EULANDA SQL-API) #
Problemstellung #
Über Trigger lassen sich eine Vielzahl von SQL-Ereignissen abfangen und gesondert behandeln. Es ist möglich besondere Prüfungen beim Speichern einer Adresse durchzuführen oder Änderungen an Daten zu protokollieren. Trigger arbeiten stets auf Tabellenebene. Dadurch ist das mögliche Einsatzgebiet auf diejenigen Ereignisse beschränkt, die primär eine Tabelle betreffen resp. das Anlegen, Ändern und Löschen eines oder mehrerer Datensätze. Komplexe Vorgänge - wie beispielsweise das Umwandeln eines Auftrags in einen Lieferschein - lassen sich nur schwer greifen. Um bei dem Beispiel zu bleiben: Beim Umwandeln eines Auftrags in einen Lieferschein werden etliche Einzelaktionen innerhalb einer Transaktion durchgeführt.
- Anlegen des Lieferscheinkopfes
- Anlegen der Positionen oder Teilpositionen
- ggf. Prüfung des Kreditlimits
- Setzen des Auftragsstatus
- Füllen der Umsetzungsmatrix zwischen Auftragspositionen und Lieferscheinpositionen
- ggf. Anlegen von Titeln, die im Auftrag verwendet werden
- etc..
Diese Auflistung ist beispielhaft und nicht vollständig. Die durchzuführenden Aktionen variieren von einer EULANDA®-Version zur nächsten. Sicherlich könnte man einen Trigger schreiben, der beim Ändern des Auftragsstatus eine benutzerdefinierte Aktionen durchführt. Aber man kann nicht sicherstellen, dass zu diesem Zeitpunkt bereits alle anderen Aktionen durchgeführt worden sind. Man kann beispielsweise nicht sicher sein, dass alle Lieferscheinpositionen angelegt sind. Um dieser Limitierung des Trigger-Konzeptes zu begegnen führt EULANDA® eine neue Klasse von Ereignissen auf Server-Ebene ein. Im Nachfolgenden finden Sie eine Liste der verfügbaren Ereignisse.
Serverseitige Ereignisse #
Eventid | Eventname | Bemerkung |
---|---|---|
10000 | AfBuchen.OnSuccess | Auftrag Buchen |
10003 | AfEdit.OnSuccess | Auftrag weitererfassen |
10004 | AfStornoBuchung.OnSuccess | Auftrag Buchung stornieren |
10005 | TraAfLf_DoJob.OnSuccess | Umwandlung eines Auftrags in einen Lieferschein HINWEIS: Je nach Einstellungen kann dieses Ereignis ausgelöst werden, nachdem der Lieferschein gebucht wurde. Falls buchungsrelevante Änderungen vorgenommen werden müssen, so ist das Ereignis 10019 zu verwenden. |
10006 | TraLfRe_DoJob.OnSuccess | Umwandlung eines Lieferscheins in eine Rechnung |
10007 | AnpCreate.OnSuccess | Anlegen einer Angebotsposition |
10008 | AfpCreate.OnSuccess | Anlegen einer Auftragsposition |
10009 | LfBuchen.OnSuccess | Lager des Lieferscheins wird gebucht |
10010 | TraAnAf.OnSuccess | Nach dem Umwandeln eines Angebots in einen Auftrag |
10011 | KfBuchen.OnSuccess | Wenn die Erfassung der Bestellung abgeschlossen wird (STRG+B) |
10012 | KfpCreate.OnSuccess | Anlegen einer Bestellposition |
10013 | AfStornoRest.OnSuccess | Stornieren der Restmengen des Auftrags |
10014 | AfCreate.OnSuccess | Anlegen eines Auftrags unabhängig davon ob er kopiert oder komplett neu angelegt wird |
10015 | AnCreate.OnSuccess | Anlegen eines Angebots unabhängig davon ob es kopiert oder komplett neu angelegt wird |
10016 | CbBuchen.OnSuccess | nach dem Buchen des Lagers eines Kassenbons |
10017 | CbStornoBuchen.OnSuccess | Stornierung der Lagerbuchung zum Kassenbeleg. Dies geschieht hauptsächlich beim Löschen eines alten Kassenbelegs. |
10018 | CbBuchen.Before | wird vor dem Lagerbuchen des Kassenbelegs aufgerufen. Die Tabelle „cnLbJob“ mit den Buchungsinformationen ist dabei bereits gefüllt. (RefTyp = „CB“, RefId = @ObjId ) |
10019 | LfBuchen.Before | wird vor dem Lagerbuchen des Lieferscheins aufgerufen. |
10020 | LfLdInit.OnSuccess | intern: Vorbereitung der Lagerbuchung von Lieferscheinen |
10021 | JbLdInit.OnSuccess | intern: Vorbereitung der Lagerbuchung von Stücklisten |
10022 | LLInitAbLd.OnSuccess | intern: Vorbereitung der Lagerbuchung von Lagerbelegen (erste Buchung) |
10023 | LLInitZuLd.OnSuccess | intern: Vorbereitung der Lagerbuchung von Lagerbelegen (zweite Buchung) |
10024 | ReStorno.OnSuccess | nach dem Löschen von Rechnungen |
10025 | KfDelete.OnSuccess | Nach dem Löschen von Bestellungen |
10026 | K.BeforefDelete | wird vor dem Löschen von Bestellungen aufgerufen |
10027 | AfBuchen.Before | wird vor dem Buchen des Auftrags aufgerufen |
10028 | TraKfWe.OnSuccess | Nach dem Anlegen einer Lieferung zu einer Bestellung |
10029 | SpnInit.onSuccess | Nach Initialisierung einer SEPA-Nachricht |
10030 | SpnRender.onSuccess | Nach der XML-Erzeugung der SEPA-Nachricht |
10031 | TraAfLf_DoJob.BeforeBuchen | in Vorbereitung |
10032 | ReStorno.Before | in Vorbereitung - wird aufgerufen, bevor die Rechnung storniert wird, um dies ggf. zu unterbinden |
10033 | LLBuchen.OnSuccess | in Vorbereitung - nach dem erfolgreichen Buchen eines Lagerbelegs (Wareneingang, Inventur, Lieferung etc.) |
10034 | LLZuBuchen.OnSuccess | in Vorbereitung - nach dem erfolgreichen Buchen der Alternativbuchung eines Lagerbelegs (Wareneingang, Inventur, Lieferung etc.). Wird von Standardmodulen nicht verwendet |
10035 | LLStornoBuchen.Before | in Vorbereitung - wird vor dem Stornieren eines Lagerbelegs aufgerufen. Die ursprüngliche Buchungs ist zu diesem Zeitpunkt noch vorhanden |
10036 | AfShopCreate.OnSuccess | wird nach dem Anlegen eines Auftrags ausgelöst, der über die Shop-Schnittstelle eingegangen ist. |
10037-10041 | Versandübergabe | reserviert |
10042 | LfVersanduebergabe.OnHandover | ab 7.0.19 wird nach der Versandübergabe ausgelöst |
10043 | LfVersanduebergabe.OnPrint | ab 7.0.19 wird nach dem Drucken der Versandetiketten ausgelöst |
10044-10049 | Versandübergabe | reserviert |
Unterstützte Ereignisse in Ihrer Version #
Die grundlegenden Ereignisse wurden erst in EULANDA 2007 eingeführt. Um eine Liste der von Ihrer Datenbank unterstützten Ereignisse zu erhalten führen Sie folgenden Befehl aus:
IF OBJECT_ID('cnEventType') IS NULL
RAISERROR('In dieser Eulanda-Version werden noch keine SQL-Ereignisse unterstützt',16,1)
ELSE SELECT id,Name FROM cnEventType ORDER BY id
Asynchrone/verzögerte Ausführung #
Ab Version 7.0.19 ist auch eine asynchrone Aufrufen der Ereignisprozedur möglich. Der ursprüngliche Vorgang, der das Ereignis auslöst wird hierbei zunächst abgearbeitet. Die Prozedur wird dann nach einer vorgegebenen Zeitspanne aufgerufen. Hierzu muss in der Tabelle cnEventSubscriber in der Spalte AsyncDeferredSeconds ein Wert größer oder gleich 0 eingetragen werden. Dieser gibt die Wartezeit in Sekunden an, die mindestens gewartet wird, bis die Prozedur ausgeführt wird.
Die verzögerte Ausführung setzt voraus, dass die Prozedur cn_Queue_HandleCnEvents regelmäßig - z.B. alle 5 Minuten - aufgerufen wird. Dies kann bei der Standard Edition des SQL-Server über den SQL-Server Agent erfolgen. Bei Einsatz der Express Edition kann dies über die Windows Aufgabenplanung erreicht werden.
Die die Prozedur nicht mehr in derselben Transaktion des ursprünglichen Vorgangs ausgeführt wird kann dieser selbstredend nicht mehr abgebrochen werden. Eine Rückgabe eines Wertes ungleich Null wird entsprechend ignoriert bzw. kann in zukünftigen Versionen auch als Fehler gewertet werden. Die Asynchrone Ausführung ist beispielsweise für zeitaufwändige Prozesse gedacht, die die ursprüngliche Abarbeitung (Buchen des Lieferscheins etc.) nicht unnötig verzögern sollen. Des Weiteren ist es empfehlenswert zu prüfen, ob das übergebene Objekt noch existiert und dem gewünschten Status entspricht. Denn es kann durchaus vorkommen, dass zum Beispiel ein Lieferschein zwischenzeitlich bereits in eine Rechnung umgewandelt oder wieder storniert wurde.
Prozedur Prototyp #
Die Behandlung eines solchen Ereignisses wird als Prozedur implementiert. Dabei muss die Prozedur streng nach folgendem Schema aufgebaut sein:
CREATE PROC cn_user_evtXXX
@SubsId int,
@ObjType char(4),
@ObjId int
AS
SET NOCOUNT ON
RAISERROR('Fehlermeldung',16,1)
RETURN -1
RETURN 0
Beispiel #
Über nachfolgenden SQL-Code wird eine Preisprüfung implementiert, die bei Unterschreitung des Einkaufspreises das Buchen des Auftrags verhindert
CREATE PROC cn_user_evtAfBuchen_EkPruefung
@SubsId int,
@ObjType char(4),
@ObjId int
AS
SET NOCOUNT ON
DECLARE @Pos int
SELECT TOP 1 @Pos = afp.PosNummer
FROM dbo.AuftragPos afp
WHERE afp.KopfId = @ObjId AND afp.Basis > afp.VkRab
IF @@ROWCOUNT > 0
BEGIN
RAISERROR('Der Einkaufspreis wurde in Position %d unterschritten',16,1,@Pos)
RETURN -1
END ELSE RETURN 0
GO
INSERT cnEventSubscriber (EventId, Vendor, ProcName)
VALUES(10000, 'USER', 'cn_user_evtAfBuchen_EkPruefung')