Wir rufen es direkt in der Datenbank ab:
/* -------------------------------------------------------------------------
RÜCKWIRKENDE LAGERBEWERTUNG (ZEITREISE) - V5 FINAL
Stichtag: Oben einstellbar
------------------------------------------------------------------------- */
DECLARE @Stichtag DATETIME = CONVERT(DATETIME, '2026-02-01 01:00:59', 120);
WITH
-- 1. Der HEUTIGE Bestand (Basis) - PRO LAGER
AktuellerBestand AS (
SELECT
WLE.kArtikel,
WL.cName AS LagerName,
SUM(WLE.fAnzahlAktuell) AS BestandHeute
FROM dbo.tWarenLagerEingang WLE
JOIN dbo.tWarenLagerPlatz WLP ON WLE.kWarenLagerPlatz = WLP.kWarenLagerPlatz
JOIN dbo.tWarenLager WL ON WLP.kWarenLager = WL.kWarenLager
GROUP BY WLE.kArtikel, WL.cName
),
-- 2. Abgänge seit Stichtag - PRO LAGER
AbgaengeSeitStichtag AS (
SELECT
WLA.kArtikel,
WL.cName AS LagerName,
SUM(WLA.fAnzahl) AS MengeRaus
FROM dbo.tWarenLagerAusgang WLA
JOIN dbo.tWarenLagerEingang WLE ON WLA.kWarenLagerEingang = WLE.kWarenLagerEingang
JOIN dbo.tWarenLagerPlatz WLP ON WLE.kWarenLagerPlatz = WLP.kWarenLagerPlatz
JOIN dbo.tWarenLager WL ON WLP.kWarenLager = WL.kWarenLager
WHERE WLA.dErstellt > @Stichtag
GROUP BY WLA.kArtikel, WL.cName
),
-- 3. Zugänge seit Stichtag - PRO LAGER
ZugaengeSeitStichtag AS (
SELECT
WLE.kArtikel,
WL.cName AS LagerName,
SUM(WLE.fAnzahl) AS MengeRein
FROM dbo.tWarenLagerEingang WLE
JOIN dbo.tWarenLagerPlatz WLP ON WLE.kWarenLagerPlatz = WLP.kWarenLagerPlatz
JOIN dbo.tWarenLager WL ON WLP.kWarenLager = WL.kWarenLager
WHERE WLE.dErstellt > @Stichtag
GROUP BY WLE.kArtikel, WL.cName
),
-- 4. Hilfs-CTE: Alle Kombinationen sammeln
AlleKombinationen AS (
SELECT kArtikel, LagerName FROM AktuellerBestand
UNION
SELECT kArtikel, LagerName FROM AbgaengeSeitStichtag
UNION
SELECT kArtikel, LagerName FROM ZugaengeSeitStichtag
),
-- 5. Die Berechnung & Verknüpfung der Stammdaten
BestandAmStichtag AS (
SELECT
ART.kArtikel,
ART.cArtNr,
MAX(AB.cName) AS Artikelname,
Base.LagerName,
MAX(LIEF.cFirma) AS Lieferant,
MAX(ART.fEKNetto) AS Preis_GLD,
-- Berechnung
ISNULL(MAX(ABest.BestandHeute), 0)
+ ISNULL(MAX(Abg.MengeRaus), 0)
- ISNULL(MAX(Zug.MengeRein), 0)
AS BestandDamals
FROM AlleKombinationen Base
JOIN dbo.tArtikel ART ON Base.kArtikel = ART.kArtikel
-- Lieferant (Standard)
LEFT JOIN dbo.tLiefArtikel LA ON ART.kArtikel = LA.tArtikel_kArtikel AND LA.nStandard = 1
LEFT JOIN dbo.tLieferant LIEF ON LA.tLieferant_kLieferant = LIEF.kLieferant
LEFT JOIN AktuellerBestand ABest ON Base.kArtikel = ABest.kArtikel AND Base.LagerName = ABest.LagerName
LEFT JOIN AbgaengeSeitStichtag Abg ON Base.kArtikel = Abg.kArtikel AND Base.LagerName = Abg.LagerName
LEFT JOIN ZugaengeSeitStichtag Zug ON Base.kArtikel = Zug.kArtikel AND Base.LagerName = Zug.LagerName
LEFT JOIN dbo.tArtikelBeschreibung AB ON ART.kArtikel = AB.kArtikel AND AB.kSprache = 1 AND AB.kPlattform = 1
GROUP BY ART.kArtikel, ART.cArtNr, Base.LagerName
)
/* -----------------------------------------------------------------
FINALE AUSGABE
----------------------------------------------------------------- */
SELECT
cArtNr AS Artikelnummer,
Artikelname,
LagerName AS Warenlager,
ISNULL(Lieferant, 'Kein Lieferant') AS Lieferant,
-- Wieder neutrale Namen, aber mit 2 Nachkommastellen
CAST(BestandDamals AS DECIMAL(25, 2)) AS Bestand_am_Stichtag,
CAST(Preis_GLD AS DECIMAL(25, 2)) AS Einzelpreis_EK,
CAST(BestandDamals * Preis_GLD AS DECIMAL(25, 2)) AS Gesamtwert_am_Stichtag,
0 AS SortierOrder
FROM BestandAmStichtag
WHERE BestandDamals <> 0
UNION ALL
-- Summenzeile
SELECT
'GESAMTSUMME' AS Artikelnummer,
'---' AS Artikelname,
'---' AS Warenlager,
'---' AS Lieferant,
CAST(SUM(BestandDamals) AS DECIMAL(25, 2)) AS Bestand_am_Stichtag,
NULL AS Einzelpreis_EK,
CAST(SUM(BestandDamals * Preis_GLD) AS DECIMAL(25, 2)) AS Gesamtwert_am_Stichtag,
1 AS SortierOrder
FROM BestandAmStichtag
ORDER BY SortierOrder, Artikelnummer, Warenlager;