Warenfluss (Bestellung bis Wareneingang) #
Diese Seite zeigt den vollständigen Warenfluss von EULANDA auf SQL-Ebene – von der Bestellung beim Lieferanten bis zum Wareneingang ins Lager. Jeder Schritt enthält ein lauffähiges SQL-Beispiel und einen Verweis auf die detaillierte Prozedurdokumentation. Zusätzlich wird der direkte Wareneingang ohne Bestellung beschrieben.
Übersicht #
graph TD
KF["Bestellung anlegen
cn_KfNewAndSave + cn_KfpNew"]
KFBU["Bestellung buchen
cn_KfBuchen"]
KFSR["Restmengen stornieren
cn_KfStornoRest"]
KFSB["Buchung stornieren
cn_KfStornoBuchung"]
WE["Direkter Wareneingang
cn_WejobCre"]
WEI["Positionen hinzufügen
cn_WeJobItemAdd"]
WEX["WE-Job ausführen
cn_WeJobExec"]
KF --> KFBU
KFBU -->|"komplett"| KFSR
KFBU -->|"Teilstorno"| KFSR
KFBU -->|"Storno"| KFSB
WE --> WEI
WEI --> WEX
style KF fill:#2e86c1,color:#fff
style KFBU fill:#27ae60,color:#fff
style KFSR fill:#e67e22,color:#fff
style KFSB fill:#c0392b,color:#fff
style WE fill:#2e86c1,color:#fff
style WEI fill:#2e86c1,color:#fff
style WEX fill:#27ae60,color:#fff
Blau: Anlegen | Grün: Buchen/Ausführen | Orange: Teilstorno | Rot: Storno
Bestellungs-Flow #
1. Bestellung anlegen #
Eine Bestellung wird über cn_KfNewAndSave (Kopf) und cn_KfpNew (Positionen) erstellt. Der Kopf wird einem Kreditor (Lieferant) zugeordnet.
DECLARE @kf_id int, @kf_nummer int
-- Bestellungskopf anlegen (Kreditor-ID = Lieferant)
EXEC cn_KfNewAndSave
@KreditorId = 15,
@KopfId = @kf_id OUT,
@KopfNummer = @kf_nummer OUT
-- Positionen hinzufügen
EXEC cn_KfpNew @KopfId = @kf_id, @ArtikelId = 100, @Menge = 50
EXEC cn_KfpNew @KopfId = @kf_id, @ArtikelId = 200, @Menge = 30
PRINT 'Bestellung ' + CAST(@kf_nummer AS varchar) + ' angelegt'
| Parameter | Typ | Beschreibung |
|---|---|---|
@KreditorId | int | Kreditor-ID (Lieferant) |
@KopfId | int OUT | ID der neuen Bestellung |
@KopfNummer | int OUT | Bestellnummer |
@BearbeitetDurch | varchar(50) | Sachbearbeiter (optional) |
Alternativ kann cn_KfNew + cn_KfNewPost separat aufgerufen werden, um zwischen Anlage und Nummernvergabe noch Änderungen vorzunehmen.
Positionen mit cn_KfpNew #
| Parameter | Typ | Beschreibung |
|---|---|---|
@KopfId | int | Bestellungs-ID |
@ArtikelId | int | Artikel-ID |
@Menge | numeric(18,4) | Bestellmenge (Standard: aus Positionsmengen-Init) |
@AutoAddKrArtikel | bit | 1 = Kreditor-Artikel automatisch anlegen |
Die Preisfindung erfolgt automatisch über cn_KfpGetPreis. Staffelpreise aus der Kreditor-Artikelzuordnung werden berücksichtigt.
Artikel hinzufügen oder Menge addieren #
Falls ein Artikel bereits in der Bestellung vorhanden ist, kann cn_KfAddUpdateAr verwendet werden. Diese Prozedur legt eine neue Position an oder addiert die Menge auf eine bestehende Position:
-- Fügt 20 Stück hinzu (oder addiert auf bestehende Position)
EXEC cn_KfAddUpdateAr
@KopfId = @kf_id,
@ArtikelId = 100,
@Menge = 20
2. Bestellung buchen (Wareneingang) #
Das Buchen einer Bestellung erzeugt die Lagerbuchung – der physische Lagerbestand wird erhöht. Der Vorgang entspricht dem Wareneingang.
EXEC cn_KfBuchen @Kf_id = @kf_id
-- oder:
EXEC cn_KfBuchen @Kf_Nummer = @kf_nummer
| Parameter | Typ | Beschreibung |
|---|---|---|
@Kf_id | int | Bestellungs-ID (alternativ: @Kf_Nummer) |
@Kf_Nummer | int | Bestellnummer |
Beim Buchen passiert intern:
- Währungsprüfung
- Lagerbuchungsjob wird aus den Bestellpositionen erzeugt
- Lagerbuchung wird über
cn_Lb_DoJobEx1ausgeführt - Status wird auf 3 (gebucht) gesetzt
- Automatisches Ausziffern über
cn_KfAusziff - Optional: Lieferquellen-Pflege in den Kreditor-Artikeln
Das SQL-Ereignis KfBuchen.OnSuccess (10011) wird nach dem Buchen ausgelöst.
3. Restmengen stornieren #
Wenn eine Bestellung nicht vollständig geliefert werden soll, können die verbleibenden Mengen storniert werden:
EXEC cn_KfStornoRest
@Kf_id = @kf_id,
@StornoGrund = 'Lieferant kann Restmenge nicht liefern'
| Parameter | Typ | Beschreibung |
|---|---|---|
@Kf_id | int | Bestellungs-ID (alternativ: @Kf_Nummer) |
@Kf_Nummer | int | Bestellnummer |
@StornoGrund | varchar(100) | Begründung für die Stornierung |
Für die Stornierung einzelner Teilmengen steht cn_KfStornoMengen zur Verfügung. Die zu stornierenden Mengen werden über eine temporäre Tabelle #KfStornoMengen übergeben.
4. Buchung stornieren #
Eine bereits gebuchte Bestellung kann über cn_KfStornoBuchung rückgängig gemacht werden. Dabei wird eine Umkehrbuchung erzeugt und der Status zurückgesetzt:
EXEC cn_KfStornoBuchung @Kf_id = @kf_id
-- oder:
EXEC cn_KfStornoBuchung @Kf_Nummer = @kf_nummer
| Parameter | Typ | Beschreibung |
|---|---|---|
@Kf_id | int | Bestellungs-ID (alternativ: @Kf_Nummer) |
@Kf_Nummer | int | Bestellnummer |
Intern wird cn_Lb_Umkehr aufgerufen, um die Lagerbuchung umzukehren. Der Bestellstatus wird auf 0 (offen) zurückgesetzt.
5. Bestellung kopieren #
Eine bestehende Bestellung kann als Vorlage für eine neue verwendet werden:
DECLARE @neue_kf_id int, @neue_kf_nummer int
EXEC cn_KfCopyFromKf
@KreditorId = 15,
@SourceKopfId = @kf_id,
@KopfId = @neue_kf_id OUT,
@KopfNummer = @neue_kf_nummer OUT,
@CopyPreise = 1
| Parameter | Typ | Beschreibung |
|---|---|---|
@KreditorId | int | Kreditor-ID für die neue Bestellung |
@SourceKopfId | int | ID der Quellbestellung |
@CopyPreise | bit | 1 = Preise übernehmen |
6. Bestellung löschen #
Eine nicht gebuchte Bestellung kann gelöscht werden:
EXEC cn_KfDel @id = @kf_id
Das Ereignis KfDelete.Before (10026) wird vor dem Löschen aufgerufen und erlaubt ein Veto. Nach dem Löschen wird KfDelete.OnSuccess (10025) ausgelöst. Gebuchte Bestellungen mit Lieferungsverknüpfung können nicht gelöscht werden (Option KfDenyDeleteWhenCleared).
Direkter Wareneingang (ohne Bestellung) #
Für Wareneingänge, die nicht über eine Bestellung laufen (z.B. Muster, Gratisware, Korrekturen), steht der direkte Wareneingang über das Job-System zur Verfügung.
1. WE-Job anlegen #
DECLARE @JobID int
EXEC cn_WejobCre
@GegenLO = 8000,
@LagerGr = 1,
@Info = 'Wareneingang Musterlieferung',
@JobID = @JobID OUT
| Parameter | Typ | Beschreibung |
|---|---|---|
@GegenLO | int | Gegenlagerort-ID (8000 = Wareneingangskonto) |
@LagerGr | int | Lagergruppe |
@Info | varchar(100) | Beschreibung des Wareneingangs |
@JobID | int OUT | ID des angelegten Jobs |
@Datum | datetime | Buchungsdatum (Standard: heute) |
Detaillierte Parameter: cn_WeJobCre
2. Positionen hinzufügen #
Für jede eingehende Position wird cn_WeJobItemAdd aufgerufen:
-- Position 1: 50 Stück Artikel 100
EXEC cn_WeJobItemAdd
@JobID = @JobID,
@ar_id = 100,
@Menge = 50
-- Position 2: 30 Stück Artikel 200 mit EK-Preis
EXEC cn_WeJobItemAdd
@JobID = @JobID,
@ar_id = 200,
@Menge = 30,
@EkNetto = 12.50
| Parameter | Typ | Beschreibung |
|---|---|---|
@JobID | int | Job-ID aus cn_WejobCre |
@ar_id | int | Artikel-ID |
@Menge | numeric(18,4) | Eingangsmenge |
@lo_id | int | Lagerort-ID (optional, sonst aus Lagergruppenmatrix) |
@lg_id | int | Lagergruppe (optional, ermittelt Lagerort automatisch) |
@ari_nr | varchar(100) | Identnummer (optional, für identpflichtige Artikel) |
@ari_altnr | varchar(100) | Alternative Identnummer (optional) |
@lp_nr | varchar(50) | Lagerplatznummer (optional) |
@lp_id | int | Lagerplatz-ID (optional) |
@ari_diverse | bit | Diverse Ident (optional) |
@EkNetto | numeric(18,2) | Einkaufspreis netto (optional) |
3. WE-Job ausführen #
Der Job wird ausgeführt und die Lagerbuchung erzeugt:
DECLARE @lbs_id int
EXEC cn_WeJobExec
@JobID = @JobID,
@lbs_id = @lbs_id OUT
PRINT 'Lagerbuchungssatz ' + CAST(@lbs_id AS varchar) + ' erzeugt'
| Parameter | Typ | Beschreibung |
|---|---|---|
@JobID | int | Job-ID aus cn_WejobCre |
@lbs_id | int OUT | ID des erzeugten Lagerbuchungssatzes |
Abhängig von der Einstellung WE_EkBerechnen in konOptionen wird der EK-Preis aktualisiert:
| Wert | Verhalten |
|---|---|
| 0 | Keine EK-Aktualisierung |
| 1 | Letzter EK wird übernommen |
| 2 | Gleitender Durchschnitts-EK (gewichtet nach Bestand und Liefermenge) |
Komplettbeispiel: Bestellung mit Wareneingang (SQL) #
-- ============================================
-- Bestellung anlegen und Ware einbuchen
-- ============================================
DECLARE @kf_id int, @kf_nummer int
-- 1. Bestellung anlegen (Kreditor 15 = Lieferant)
EXEC cn_KfNewAndSave
@KreditorId = 15,
@KopfId = @kf_id OUT,
@KopfNummer = @kf_nummer OUT
-- 2. Positionen hinzufügen
EXEC cn_KfpNew @KopfId = @kf_id, @ArtikelId = 100, @Menge = 50
EXEC cn_KfpNew @KopfId = @kf_id, @ArtikelId = 200, @Menge = 30
-- 3. Bestellung buchen (= Wareneingang)
EXEC cn_KfBuchen @Kf_id = @kf_id
PRINT 'Bestellung ' + CAST(@kf_nummer AS varchar) + ' gebucht (Ware eingelagert)'
Komplettbeispiel: Direkter Wareneingang (SQL) #
-- ============================================
-- Wareneingang ohne Bestellung
-- ============================================
DECLARE @JobID int, @lbs_id int
-- 1. Job anlegen (Gegenlagerort 8000 = WE-Konto)
EXEC cn_WejobCre
@GegenLO = 8000,
@LagerGr = 1,
@Info = 'Musterlieferung April 2026',
@JobID = @JobID OUT
-- 2. Positionen
EXEC cn_WeJobItemAdd @JobID = @JobID, @ar_id = 100, @Menge = 10
EXEC cn_WeJobItemAdd @JobID = @JobID, @ar_id = 200, @Menge = 5, @EkNetto = 12.50
-- 3. Ausführen
EXEC cn_WeJobExec @JobID = @JobID, @lbs_id = @lbs_id OUT
PRINT 'Lagerbuchungssatz ' + CAST(@lbs_id AS varchar) + ' erzeugt'
PowerShell-Beispiele #
Die folgenden Beispiele verwenden das Modul EulandaXtools und eine ADODB-Verbindung über Get-Conn. Da EulandaXtools aktuell keine dedizierten Einkaufs-Cmdlets enthält, werden die SQL-Prozeduren direkt über $conn.Execute() aufgerufen.
Bestellung anlegen und buchen #
Import-Module EulandaXTools.psm1 -Force
# Verbindung über UDL-Datei
$conn = Get-Conn -Udl 'C:\Eulanda\EULANDA_1 Mustermann.udl'
# Bestellungskopf anlegen
$rs = $conn.Execute("
DECLARE @id int, @nr int
EXEC cn_KfNewAndSave @KreditorId = 15, @KopfId = @id OUT, @KopfNummer = @nr OUT
SELECT @id AS KfId, @nr AS KfNummer
")
$kfId = $rs.Fields.Item('KfId').Value
$kfNummer = $rs.Fields.Item('KfNummer').Value
Write-Host "Bestellung $kfNummer angelegt (ID: $kfId)"
# Positionen hinzufügen
$conn.Execute("EXEC cn_KfpNew @KopfId = $kfId, @ArtikelId = 100, @Menge = 50")
$conn.Execute("EXEC cn_KfpNew @KopfId = $kfId, @ArtikelId = 200, @Menge = 30")
# Buchen (= Wareneingang)
$conn.Execute("EXEC cn_KfBuchen @Kf_id = $kfId")
Write-Host "Bestellung $kfNummer gebucht - Ware eingelagert"
Direkter Wareneingang #
Import-Module EulandaXTools.psm1 -Force
$conn = Get-Conn -Udl 'C:\Eulanda\EULANDA_1 Mustermann.udl'
# WE-Job anlegen
$rs = $conn.Execute("
DECLARE @JobID int
EXEC cn_WejobCre @GegenLO = 8000, @LagerGr = 1,
@Info = 'Musterlieferung', @JobID = @JobID OUT
SELECT @JobID AS JobID
")
$jobId = $rs.Fields.Item('JobID').Value
# Positionen
$conn.Execute("EXEC cn_WeJobItemAdd @JobID = $jobId, @ar_id = 100, @Menge = 10")
$conn.Execute("EXEC cn_WeJobItemAdd @JobID = $jobId, @ar_id = 200, @Menge = 5, @EkNetto = 12.50")
# Ausführen
$rs = $conn.Execute("
DECLARE @lbs int
EXEC cn_WeJobExec @JobID = $jobId, @lbs_id = @lbs OUT
SELECT @lbs AS LbsId
")
$lbsId = $rs.Fields.Item('LbsId').Value
Write-Host "Lagerbuchungssatz $lbsId erzeugt"
Nächste Dokumentnummer ermitteln #
Für die Dokumenttypen PurchaseOrder und GoodsReceipt kann die nächste freie Nummer über Get-NextDocumentNumber ermittelt werden:
$nextKfNr = Get-NextDocumentNumber -DocumentType 'PurchaseOrder' -Conn $conn
$nextWeNr = Get-NextDocumentNumber -DocumentType 'GoodsReceipt' -Conn $conn
Write-Host "Nächste Bestellnummer: $nextKfNr, nächste WE-Nummer: $nextWeNr"
Zusammenfassung der Prozeduren #
| Schritt | Prozedur | Ereignis |
|---|---|---|
| Bestellung anlegen | cn_KfNewAndSave + cn_KfpNew | 10012 (KfpCreate) |
| Bestellung buchen | cn_KfBuchen | 10011 (KfBuchen) |
| Restmengen stornieren | cn_KfStornoRest | – |
| Teilmengen stornieren | cn_KfStornoMengen | – |
| Buchung stornieren | cn_KfStornoBuchung | – |
| Bestellung löschen | cn_KfDel | 10025 / 10026 |
| Bestellung kopieren | cn_KfCopyFromKf | – |
| WE-Job anlegen | cn_WejobCre | – |
| WE-Position hinzufügen | cn_WeJobItemAdd | – |
| WE-Job ausführen | cn_WeJobExec | – |
Abkürzungen #
| Kürzel | Tabelle | Bedeutung |
|---|---|---|
| KF | KrAuftrag | Bestellungskopf |
| KFP | KrAuftragPos | Bestellpositionen |
| KR | Kreditor | Lieferant |
| KRAR | KrArtikel | Kreditor-Artikelzuordnung |
| LBS | LagerBuchungsSatz | Lagerbuchungskopf |
| LBZ | LagerBuchungsZeile | Lagerbuchungszeile |
| LG | LagerGruppe | Lagergruppe |
| LKT | LagerOrt | Lagerort |
Siehe auch #
- Belegfluss – Verkaufsseite (Angebot bis Rechnung)
- SQL-Ereignisse – Vollständige Liste aller Events
- Prozeduren und Funktionen – Detaildokumentation
- cn_WeJobCre – WE-Job anlegen