CiAgICA8IS0tIExpbmtlZEluIC0tPgogICAgPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiPgogICAgICAgIF9saW5rZWRpbl9wYXJ0bmVyX2lkID0gIjEyMzUwNzMiOwogICAgICAgIHdpbmRvdy5fbGlua2VkaW5fZGF0YV9wYXJ0bmVyX2lkcyA9IHdpbmRvdy5fbGlua2VkaW5fZGF0YV9wYXJ0bmVyX2lkcyB8fCBbXTsKICAgICAgICB3aW5kb3cuX2xpbmtlZGluX2RhdGFfcGFydG5lcl9pZHMucHVzaChfbGlua2VkaW5fcGFydG5lcl9pZCk7CiAgICA8L3NjcmlwdD48c2NyaXB0IHR5cGU9InRleHQvamF2YXNjcmlwdCI+CiAgICAgICAgKGZ1bmN0aW9uKCl7dmFyIHMgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgic2NyaXB0IilbMF07CiAgICAgICAgICAgIHZhciBiID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7CiAgICAgICAgICAgIGIudHlwZSA9ICJ0ZXh0L2phdmFzY3JpcHQiO2IuYXN5bmMgPSB0cnVlOwogICAgICAgICAgICBiLnNyYyA9ICJodHRwczovL3NuYXAubGljZG4uY29tL2xpLmxtcy1hbmFseXRpY3MvaW5zaWdodC5taW4uanMiOwogICAgICAgICAgICBzLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKGIsIHMpO30pKCk7CiAgICA8L3NjcmlwdD4KICAgIDxub3NjcmlwdD4KICAgICAgICA8aW1nIGhlaWdodD0iMSIgd2lkdGg9IjEiIHN0eWxlPSJkaXNwbGF5Om5vbmU7IiBhbHQ9IiIgc3JjPSJodHRwczovL3B4LmFkcy5saW5rZWRpbi5jb20vY29sbGVjdC8/cGlkPTEyMzUwNzMmZm10PWdpZiIgLz4KICAgIDwvbm9zY3JpcHQ+CiAgICA8IS0tIEVuZCBMaW5rZWRJbiAtLT4KICAgIA==
Generic filters
Exact matches only
Search in title
Search in excerpt
Search in content

Berechtigungen für Zellkommentare

Wie im Blogbeitrag Zellkommentare beschrieben, bietet DeltaMaster die Möglichkeit, für einzelne Zellwerte Zellkommentare zu erfassen. Das kann z. B. sehr hilfreich sein, wenn während einer Planungsphase genau beschrieben werden soll, warum ein Planwert in einer bestimmten Höhe erfasst wurde oder eine Abweichung zustande gekommen ist. Bei der Planung werden Daten oft auf verschiedenen Aggregationsebenen erfasst. Es kann Top-Down, Bottom-Up oder über das Gegenstromverfahren geplant werden. Dabei werden unterschiedliche Verantwortlichkeiten definiert und jeder Planer darf Werte auf der für ihn definierten Aggregationsebene eingeben. Beispielsweise kann es Planer geben, die nur einzelne Produkte planen dürfen. Andere wiederum dürfen ganze Produktgruppen planen, bzw. die aggregierten Planwerte der Produktplaner korrigieren oder überarbeiten. In manchen Fällen ist eine solche Berechtigungslogik auch für die Erfassung von Zellkommentaren notwendig. Welche Schritte dafür notwendig sind, soll der folgende Blogbeitrag beschreiben.

Benutzerberechtigungstabelle

Um bei der Erfassung von Kommentaren unterscheiden zu können, welcher Benutzer (Planer) welche Berechtigung besitzt, wird zunächst eine Benutzerberechtigungstabelle benötigt. Die Tabelle trägt den Namen T_D_User und besteht aus den vier Spalten UserID, UserName, UserGroupID und UserGroupName. Die Spalte UserID enthält eine eindeutige Benutzer-ID, die Spalte UserName den Benutzernamen, mit dem sich der Benutzer an die DeltaMaster-Anwendung anmeldet (i.d.R. der Windows-Anmeldename), die Spalte UserGroupID enthält die eindeutige ID der Benutzergruppe und die Spalte UserGroupName den Namen der Benutzergruppe. Im gezeigten Beispiel gehört der Benutzer mit dem Benutzernamen user1 zur Gruppe 2 (Produktplaner) und der Benutzer mit dem Benutzernamen user2 zur Gruppe 1 (Produktgruppenplaner).

Abbildung 1: Berechtigungstabelle

DeltaMaster sendet beim Erfassen von Kommentaren in einer Zelle ein SQL-Statement an die relationale Datenbank, das dafür sorgt, dass der Kommentar in die Kommentartabelle eingefügt bzw. in der Tabelle geändert oder aus ihr gelöscht wird.

Abbildung 2: Dialog zur Erfassung von Zellkommentaren

Das folgende SQL-Statement fügt den erfassten Text auf dem Produkt Hansen 10 mit der ProduktID P16 in die Kommentartabelle ein.


INSERT
INTO [dbo].[T_FACT_01_Deckungsbeitragsrechnung_TEXT] 
	([Umsatz], 
	[Umsatz_UserInfo], 
	[Umsatz_EditDate], 
	[T_DIM_04_01_Kumulation_KumulationID], 
	[T_DIM_01_01_Jahr_JahrID], 
	[T_DIM_03_01_Periodenansicht_PeriodenansichtID], 
	[T_DIM_06_03_Produkt_ProduktID], 
	[T_DIM_06_02_Produktgruppe_ProduktgruppeID], 
	[T_DIM_06_01_Produkthauptgruppe_ProdukthauptgruppeID], 
	[T_DIM_02_01_Wertart_WertartID], 
	[T_DIM_09_01_Einheit_EinheitID]) 
VALUES (
	'Das Modell Hansen 10 läuft Mitte des Jahres 2015 aus!', 
	'domaene\user1', 
	'2014-11-14T10:27:13', 
	'1', 
	'2015', 
	'1', 
	'P16', 
	'4', 
	'3', 
	'P', 
	'1')

Beim Einfügen eines Kommentars wird immer die ID des kommentierten Elementes (P16 – Hansen 10) übergeben und die ID der jeweiligen Elternelemente (4 – Hansen, 3 – Standardmodelle). Dadurch können Kommentare in DeltaMaster „aggregiert“ werden. Wird ein Kommentar auf einer aggregierten Ebene erfasst, wird für die Ebenen darunter kein Wert übergeben und die entsprechenden Spalten in der Kommentartabelle bleiben leer.

In DeltaMaster wird der Kommentar anschließend auf dem Zellwert bzw. Produkt und, wenn aktiviert, auch auf den darüber liegenden Aggregationsebenen der Produktdimension angezeigt.

Abbildung 3: Kommentaranzeige in DeltaMaster auf Produktebene

Der Benutzer mit dem Namen user1 könnte standardmäßig auch Kommentare auf der Produktgruppenebene Hansen erfassen. Um das zu vermeiden, müsste das von DeltaMaster gesendete SQL-Statement abgeändert werden. Aktuell ist das nicht möglich, aber durch die Nutzung eines Datenbank-Triggers kann beeinflusst werden, was mit den an die Kommentartabelle gesendeten Werten passieren soll.

Schreibberechtigungsprüfung mittels Datenbank-Trigger

Datenbank-Trigger können z. B. einem Tabellenobjekt hinterlegt werden, um beim Einfügen, Aktualisieren und Löschen von Daten zu prüfen, ob die jeweilige Aktion zulässig ist. Was zulässig ist oder nicht kann dabei per SQL gesteuert werden. Im gezeigten Beispiel wird ein Datenbank-Trigger mit dem Namen TI_T_FACT_01_Deckungsbeitragsrechnung_TEXT auf die Zellkommentartabelle T_FACT_01_Deckungsbeitragsrechnung_TEXT gelegt, der nach dem Einfügen (AFTER INSERT) eines Datensatzes in die Tabelle ausgeführt wird.


CREATE TRIGGER [dbo].[TI_T_FACT_01_Deckungsbeitragsrechnung_TEXT] ON [dbo].[T_FACT_01_Deckungsbeitragsrechnung_TEXT]
AFTER INSERT
AS

DECLARE @UserGroupID int
DECLARE @ProduktgruppeID varchar(50)
DECLARE @ProduktID varchar(50)

-- Ermittlung der Benutzergruppe
SELECT @UserGroupID = u.UserGroupID 
FROM [dbo].[T_D_User] u 
WHERE 
	u.UserName = system_user or	
	u.UserName = current_user
	
SELECT @ProduktgruppeID = T_DIM_06_02_Produktgruppe_ProduktgruppeID 
FROM inserted

SELECT @ProduktID = T_DIM_06_03_Produkt_ProduktID 
FROM inserted

-- Benutzer der Gruppe 1 - dürfen auf Ebene Produktgruppe und darunter schreiben
IF @UserGroupID = 1 and @ProduktgruppeID is null  
BEGIN
RAISERROR ('Sie besitzen keine Schreibberechtigung für die Ebene Pro-
duktgruppe!', 9, 1);
	ROLLBACK TRANSACTION;
	RETURN 
END

-- Benutzer der Gruppe 2 - dürfen auf Ebene Produkt und darunter schreiben
IF @UserGroupID = 2 and @ProduktID is null  
BEGIN
RAISERROR ('Sie besitzen keine Schreibberechtigung für die Ebene Pro
dukt!', 9, 1);
	ROLLBACK TRANSACTION;
	RETURN 
END

Dabei wird nach der Deklaration der Variablen zuerst geprüft, welcher Benutzergruppe der eingebende Benutzer angehört. Die Funktion SYSTEM_USER bzw. CURRENT_USER liefert den Namen des aktuellen Benutzers, welcher anschließend an die vorher angelegte Benutzertabelle T_D_User übergeben wird, um die entsprechende Benutzergruppe zu ermitteln. Danach werden die von DeltaMaster übergebenen Werte für die Ebenen Produktgruppe und Produkt abgefragt. Zuletzt findet ein Abgleich von Benutzergruppe und Ebene statt. Wird für die jeweilige Gruppe kein Wert für die entsprechende Ebene übergeben, wird eine Fehlermeldung (RAISERROR) ausgegeben und die Transaktion (Einfügen des Kommentars) rückgängig gemacht (ROLLBACK), d. h. der Wert wird nicht gespeichert. Damit die Prüfung nicht nur bei der Neueingabe von Kommentaren (INSERT) ausgeführt wird, sondern auch beim Ändern eines vorhandenen Kommentars (UPDATE), muss ein zweiter Trigger erstellt werden, der beim Aktualisieren von Datensätzen ausgeführt wird. Dieser Trigger kann den gleichen Code enthalten wie der INSERT-Trigger, muss aber unter einem anderen Namen gespeichert werden und statt der Anweisung AFTER INSERT die Anweisung AFTER UPADTE aufweisen.


CREATE TRIGGER [dbo].[TU_T_FACT_01_Deckungsbeitragsrechnung_TEXT] ON [dbo].[T_FACT_01_Deckungsbeitragsrechnung_TEXT]
AFTER UPDATE
AS
…

Versucht nun ein Benutzer der Gruppe 2 einen Kommentar auf dem Element Hansen einzugeben, welches sich auf der Produktgruppenebene befindet, wird eine Fehlermeldung angezeigt und die Eingabe des Kommentars abgewiesen.

Abbildung 4: Fehlermeldung beim Speichern ohne Berechtigung

Ein Benutzer der Gruppe 1 dagegen kann seinen Kommentar problemlos erfassen.

Abbildung 5: Kommentaranzeige in DeltaMaster auf Produktgruppenebene

Leseberechtigungsprüfung mittels View

Soll zusätzlich zur oben beschriebenen Schreibberechtigung auch eine Leseberechtigung existieren, kann auch diese implementiert werden. Standardmäßig liest DeltaMaster die Kommentare aus einer Kommentartabelle, welche den Namen der zugrundeliegenden Faktentabelle mit dem Zusatz _TEXT trägt, in unserem Beispiel T_FACT_01_Deckungsbeitragsrechnung_TEXT. Findet DeltaMaster beim Start der Analysesitzung ein Objekt, welches mit V statt mit T beginnt, aber ansonsten dem Namen der Kommentartabelle entspricht (V_FACT_01_Deckungsbeitragsrechnung_TEXT), nutzt er zur Abfrage der Kommentare dieses Objekt. Dieses Objekt, eine View, muss die gleichen Spalten wie die referenzierte Tabelle enthalten und kann durch die Nutzung entsprechender SQL-Anweisungen dazu genutzt werden nur bestimmte Datensätze zurückzugeben bzw. anzuzeigen. Die View in unserem Beispiel enthält folgenden SQL-Code:


CREATE VIEW V_FACT_01_Deckungsbeitragsrechnung_TEXT AS
SELECT 
	a.[T_DIM_04_01_Kumulation_KumulationID]
	,a.[T_DIM_04_01_Kumulation_Virtual]
	,a.[T_DIM_05_01_Land_LandID]
	,a.[T_DIM_05_02_Region_RegionID]
	,a.[T_DIM_05_03_Gebiet_GebietID]
	,a.[T_DIM_05_04_PLZ_PLZID]
	,a.[T_DIM_05_05_Kunde_KundeID]
	,a.[T_DIM_05_05_Kunde_Virtual]
	,a.[T_DIM_01_01_Jahr_JahrID]
	,a.[T_DIM_01_02_Quartal_QuartalID]
	,a.[T_DIM_01_03_Monat_MonatID]
	,a.[T_DIM_01_04_Tag_TagID]
	,a.[T_DIM_01_04_Tag_Virtual]
	,a.[T_DIM_03_01_Periodenansicht_PeriodenansichtID]
	,a.[T_DIM_03_01_Periodenansicht_Virtual]
	,a.[T_DIM_06_01_Produkthauptgruppe_ProdukthauptgruppeID]
	,a.[T_DIM_06_02_Produktgruppe_ProduktgruppeID]
	,a.[T_DIM_06_03_Produkt_ProduktID]
	,a.[T_DIM_06_03_Produkt_Virtual]
	,a.[T_DIM_07_01_Stoffgruppe_StoffgruppeID]
	,a.[T_DIM_07_01_Stoffgruppe_Virtual]
	,a.[T_DIM_08_01_Vertretergruppen_VertretergruppenID]
	,a.[T_DIM_08_01_Vertretergruppen_Virtual]
	,a.[T_DIM_02_01_Wertart_WertartID]
	,a.[T_DIM_02_01_Wertart_Virtual]
	,a.[T_DIM_10_01_Firma_FirmaID]
	,a.[T_DIM_10_01_Firma_Virtual]
	,a.[Absatz]
	,a.[Absatz_UserInfo]
	,a.[Absatz_EditDate]
	,a.[Erlösschmälerungen]
	,a.[Erlösschmälerungen_UserInfo]
	,a.[Erlösschmälerungen_EditDate]
	,a.[Lohnkosten]
	,a.[Lohnkosten_UserInfo]
	,a.[Lohnkosten_EditDate]
	,a.[Materialkosten]
	,a.[Materialkosten_UserInfo]
	,a.[Materialkosten_EditDate]
	,a.[Rabatt]
	,a.[Rabatt_UserInfo]
	,a.[Rabatt_EditDate]
	,a.[Umsatz]
	,a.[Umsatz_UserInfo]
	,a.[Umsatz_EditDate]
	,a.[Anzahl_Rechnungen]
	,a.[Anzahl_Rechnungen_UserInfo]
	,a.[Anzahl_Rechnungen_EditDate]
	,a.[Stückpreis]
	,a.[Stückpreis_UserInfo]
	,a.[Stückpreis_EditDate]
	,a.[Berechnungsziel1]
	,a.[Berechnungsziel1_UserInfo]
	,a.[Berechnungsziel1_EditDate]
	,a.[Berechnungsziel2]
	,a.[Berechnungsziel2_UserInfo]
	,a.[Berechnungsziel2_EditDate]
	,a.[Berechnungsziel3]
	,a.[Berechnungsziel3_UserInfo]
	,a.[Berechnungsziel3_EditDate]
	,a.[T_DIM_05_01_Region_RegionID]
	,a.[T_DIM_05_02_Gebiet_GebietID]
	,a.[T_DIM_05_03_PLZ_PLZID]
	,a.[T_DIM_05_04_Kunde_KundeID]
	,a.[T_DIM_05_04_Kunde_VertriebskanalID]
	,a.[T_DIM_05_04_Kunde_BrancheID]
	,a.[T_DIM_05_04_Kunde_Virtual]
	,a.[T_DIM_01_03_Monat_Virtual]
	,a.[T_DIM_08_01_Vertrieb_VertriebID]
	,a.[T_DIM_08_01_Vertrieb_Virtual]
	,a.[T_DIM_09_01_Einheit_EinheitID]
	,a.[T_DIM_09_01_Einheit_Virtual]
	,a.[Skonti]
	,a.[Skonti_UserInfo]
	,a.[Skonti_EditDate]
	,a.[Anzahl_Belegpositionen]
	,a.[Anzahl_Belegpositionen_UserInfo]
	,a.[Anzahl_Belegpositionen_EditDate]
	,a.[DB]
	,a.[DB_UserInfo]
	,a.[DB_EditDate]
	,a.[Lohn]
	,a.[Lohn_UserInfo]
	,a.[Lohn_EditDate]
	,a.[Material]
	,a.[Material_UserInfo]
	,a.[Material_EditDate]
FROM 
	[dbo].[T_FACT_01_Deckungsbeitragsrechnung_TEXT] a
INNER JOIN
	[dbo].[T_D_User] u
	ON	1 = 1
WHERE
ISNULL(a.[T_DIM_06_03_Produkt_ProduktID],convert(varchar(2),u.UserGroupID)) <> '2' AND
(u.UserName = system_user OR
	u.UserName = current_user) 

Die gezeigte View gibt für Benutzer der Gruppe 2 (Produktebene) nur Kommentare zurück, welche direkt auf Elementen der Produktebene erfasst wurden und „aggregiert“ diese. Dazu wird die Kommentartabelle über einen INNERJOIN mit der Benutzertabelle verknüpft. In der WHERE-Klausel werden Datensätze, die in der Spalte T_DIM_06_03_Produkt_ProduktID (Produktebene) keinen Wert enthalten (NULL) durch die ID der Benutzergruppe ersetzt und anschließend auf <> 2 geprüft. Somit werden alle auf höheren Ebenen erfassten Kommentardatensätze für Benutzer der Benutzergruppe 2 ausgefiltert. Befindet sich für den aktuellen Benutzer kein Eintrag in der Benutzertabelle, werden alle Kommentardatensätze aus der Kommentartabelle ausgefiltert und DeltaMaster zeigt keine Kommentare an. Diese View kann entsprechend weiter ausgebaut und an die jeweiligen Anforderungen angepasst werden.