CREATE TYPE CustomWorkflows.Parameter_spLSFulfillmentAbrechnungPosSetzen_JSON
FROM NVARCHAR(4000);
GO
EXEC CustomWorkflows._SetActionParameterDisplayName
@parameterName = 'Parameter_spLSFulfillmentAbrechnungPosSetzen_JSON',
@displayname = 'Positionen JSON [{"id":x,"qty":y},..]';
GO
CREATE TYPE CustomWorkflows.Parameter_spLSFulfillmentAbrechnungPosSetzen_KundenId
FROM NVARCHAR(255);
GO
EXEC CustomWorkflows._SetActionParameterDisplayName
@parameterName = 'Parameter_spLSFulfillmentAbrechnungPosSetzen_KundenId',
@displayname = 'FFN-KundenId';
GO
CREATE TYPE CustomWorkflows.Parameter_spLSFulfillmentAbrechnungPosSetzen_MwSt
FROM NVARCHAR(255);
GO
EXEC CustomWorkflows._SetActionParameterDisplayName
@parameterName = 'Parameter_spLSFulfillmentAbrechnungPosSetzen_MwSt',
@displayname = 'Mehrwertssteuersatz';
GO
CREATE TYPE CustomWorkflows.Parameter_spLSFulfillmentAbrechnungPosSetzen_Hinweis
FROM NVARCHAR(4000);
GO
EXEC CustomWorkflows._SetActionParameterDisplayName
@parameterName = 'Parameter_spLSFulfillmentAbrechnungPosSetzen_Hinweis',
@displayname = 'AbrechnungsPos. Hinweis';
GO
CREATE PROCEDURE CustomWorkflows.spLSFulfillmentAbrechnungPosSetzen
@kLieferschein INT,
@KundenId CustomWorkflows.Parameter_spLSFulfillmentAbrechnungPosSetzen_KundenId,
@PositionenJson CustomWorkflows.Parameter_spLSFulfillmentAbrechnungPosSetzen_JSON,
@Mehrwertssteuersatz CustomWorkflows.Parameter_spLSFulfillmentAbrechnungPosSetzen_MwSt,
@cHinweis CustomWorkflows.Parameter_spLSFulfillmentAbrechnungPosSetzen_Hinweis
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;
BEGIN TRANSACTION;
BEGIN TRY
-- 1) Variablen deklarieren und default setzen
DECLARE
@nObjektPk INT = @kLieferschein,
@nObjekt TINYINT = 7,
@kKunde INT,
@fMwSt DECIMAL(25,13),
@kFulfillerEinstellungen INT,
@kBenutzer INT = 1, -- Default-User
@kAbrechnung INT,
@nNeueAbrechnung TINYINT;
-- 2) Kunden-ID validieren
SET @kKunde = TRY_CAST(@KundenId AS INT);
IF @kKunde IS NULL
BEGIN
RAISERROR(N'Die übergebene Kunden-ID muss eine gültige Ganzzahl sein.',16,1);
RETURN;
END
-- 3) MwSt validieren
SET @fMwSt = TRY_CAST(@Mehrwertssteuersatz AS DECIMAL(25,13));
IF @fMwSt IS NULL
BEGIN
RAISERROR(
N'Der angegebene Mehrwertsteuersatz muss ein gültiger Decimal(25,13)-Wert sein (z. B. ''0'' oder ''19.00'').',
16,1
);
RETURN;
END
-- 4) Einstellungen für diesen Kunden holen
SELECT TOP 1
@kFulfillerEinstellungen = kFulfillerEinstellungen
FROM FulfillmentNetwork.tFulfillerEinstellungen
WHERE kKunde = @kKunde;
IF @kFulfillerEinstellungen IS NULL
BEGIN
RAISERROR(N'Für Kundennummer %d sind keine Fulfillment-Einstellungen hinterlegt.',16,1,@kKunde);
RETURN;
END
-- 5) Aktuelle Abrechnung und ggf. neue ID holen
EXEC FulfillmentNetwork.spGetAktuelleAbrechnung
@kFulfillerEinstellungen = @kFulfillerEinstellungen,
@kBenutzer = @kBenutzer,
@kAbrechnung = @kAbrechnung OUTPUT,
@nNeueAbrechnung = @nNeueAbrechnung OUTPUT;
-- 6) JSON validieren und parsen
IF ISJSON(@PositionenJson) <> 1
BEGIN
RAISERROR(N'Ungültiges JSON-Format für PositionenJson. Erwartet: Array von Objekten.',16,1);
RETURN;
END
DECLARE @tblPosTemp TABLE (
kArtikel INT,
fAnzahl DECIMAL(25,13)
);
INSERT INTO @tblPosTemp(kArtikel,fAnzahl)
SELECT id, qty
FROM OPENJSON(@PositionenJson)
WITH (
id INT '$.id',
qty DECIMAL(25,13) '$.qty'
);
DECLARE
@origCount INT = (SELECT COUNT(*) FROM OPENJSON(@PositionenJson)),
@goodCount INT = (SELECT COUNT(*) FROM @tblPosTemp);
IF @origCount <> @goodCount
BEGIN
RAISERROR(
N'Die JSON-Struktur stimmt nicht: Jedes Element muss ein Integer-Feld "id" und ein Decimal-Feld "qty" haben.',
16,1
);
RETURN;
END
DECLARE @tblPos TABLE (
kArtikel INT,
fAnzahl DECIMAL(25,13)
);
INSERT INTO @tblPos(kArtikel,fAnzahl)
SELECT kArtikel, fAnzahl
FROM @tblPosTemp;
-- 7) Loop über alle Positionen und Aufruf der Abrechnungs-SP
DECLARE
@kArtikel INT,
@fAnzahl DECIMAL(25,13),
@cBezeichnung NVARCHAR(256),
@fVkNetto DECIMAL(25,13),
@fVKPreis DECIMAL(25,13),
@fEKNetto DECIMAL(25,13),
@cArtNr NVARCHAR(100),
@cEinheit NVARCHAR(255),
@kPreis INT,
@kEinheit INT,
@fSonderpreis DECIMAL(25,13),
@dErstellt DATETIME = GETDATE();
DECLARE pos_cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT kArtikel, fAnzahl
FROM @tblPos;
OPEN pos_cursor;
FETCH NEXT FROM pos_cursor INTO @kArtikel, @fAnzahl;
WHILE @@FETCH_STATUS = 0
BEGIN
-- 7.1) Stammdaten aus tArtikel holen
SELECT
@fVkNetto = fVkNetto,
@fEKNetto = fEKNetto,
@cArtNr = cArtNr,
@kEinheit = kVerkaufsEinheit
FROM dbo.tArtikel
WHERE kArtikel = @kArtikel;
-- Bezeichnung aus Sprach-Tabelle
SELECT
@cBezeichnung = cName
FROM dbo.tArtikelBeschreibung
WHERE kArtikel = @kArtikel;
-- Einheit in der richtigen Sprache
SELECT
@cEinheit = cName
FROM dbo.tEinheitSprache
WHERE kEinheit = @kEinheit;
-- 7.2) Vereinfachter Sonderpreis-Check
-- **Reset beider Variablen am Schleifenbeginn**
SET @kPreis = NULL;
SET @fSonderpreis = NULL;
SELECT TOP 1 @kPreis = kPreis
FROM dbo.tPreis
WHERE kKunde = @kKunde
AND kArtikel = @kArtikel;
IF @kPreis IS NOT NULL
BEGIN
-- Staffelpreis bestimmen: nAnzahlAb ≤ bestellte Menge, höchste nAnzahlAb zuerst
SELECT TOP 1
@fSonderpreis = fNettoPreis
FROM dbo.tPreisDetail
WHERE kPreis = @kPreis
AND nAnzahlAb <= @fAnzahl
ORDER BY nAnzahlAb DESC;
END
IF @fSonderpreis IS NOT NULL
BEGIN
-- Override auf den Sonderpreis (auch wenn 0.00)
SET @fVkNetto = @fSonderpreis;
SET @fVKPreis = @fSonderpreis * (1 + (@fMwSt/100));
END
ELSE
BEGIN
-- Kein Sonderpreis: Standard-Bruttopreis aus fVkNetto
SET @fVKPreis = @fVkNetto * (1 + (@fMwSt/100));
END
-- 7.3) Call der bestehenden Procedure
EXEC FulfillmentNetwork.spAbrechnungPositionAnlegen
@kArtikel = @kArtikel,
@kAbrechnung = @kAbrechnung,
@cBezeichnung = @cBezeichnung,
@fVkNetto = @fVkNetto,
@fVKPreis = @fVKPreis,
@fEKNetto = @fEKNetto,
@fAnzahl = @fAnzahl,
@fRabatt = 0,
@fMwSt = @fMwSt,
@cArtNr = @cArtNr,
@cEinheit = @cEinheit,
@cHinweis = @cHinweis,
@nType = 1,
@kObjektPk = @nObjektPk,
@nObjekt = @nObjekt,
@dErstellt = @dErstellt;
FETCH NEXT FROM pos_cursor INTO @kArtikel, @fAnzahl;
END
CLOSE pos_cursor;
DEALLOCATE pos_cursor;
COMMIT;
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0 ROLLBACK;
DECLARE
@ErrMsg NVARCHAR(4000) = ERROR_MESSAGE(),
@ErrSev INT = ERROR_SEVERITY(),
@ErrSta INT = ERROR_STATE();
RAISERROR(@ErrMsg,@ErrSev,@ErrSta);
END CATCH
END;
GO
-- 4) Action-DisplayName und CheckAction
EXEC CustomWorkflows._SetActionDisplayName
@actionName = 'spLSFulfillmentAbrechnungPosSetzen',
@displayName = 'LS-Fulfillment: Abrechnungs-Positionen setzen';
GO
EXEC CustomWorkflows._CheckAction
@actionName = 'spLSFulfillmentAbrechnungPosSetzen';
GO