Berichtsansicht

Aus iDempiere de
Zur Navigation springen Zur Suche springen

In iDempiere kann man per Konfiguration im Application Dictionary eigene Ansichten auf seine Datentabellen definieren. Dies geschieht im Fenster Bericht_Datenbank-Ansicht_(Fenster_ID-180).

Wofür ist die Berichtsansicht nun gut? Die größte Flexibilität bietet es natürlich, in der Datenbank komplett ein Neues View für Berichte anzulegen. Die hier vorgestellte Methode der Berichtsansicht hilft jedoch in vielen Fällen, Daten für verschiedene Auswertungen enger zusammenzustellen. Dabei liegt die größte Stärke eigentlich in der Kombination beider Verfahren.

Dieser Artikel ist von Thomas Bayen. Meine Artikel sind grundsätzlich nie "fertig", sondern immer eine Einladung, sie zu verbessern. Ich lade jeden gerne jederzeit ein, Verbesserungen hier direkt einzupflegen. Wer möchte, kann mich auch gerne kontaktieren.

Welches Verfahren für welche Daten?

Um ein komfortables und flexibles System für Statistik und Berichte zu erhalten, empfehle ich, gedanklich in mehreren Schritten zu arbeiten.

1. Schritt: Tabellen

Die eigentlichen Daten liegen in iDempiere erst einmal in normalen Datentabellen. Diese sind normiert, d.h. es sind sehr viele Daten durch Referenzen miteinander verknüpft. Auf diese Art erhalten wir einerseits eine sehr übersichtliche Datenstruktur aber leider führt das auch dazu, das interessante Daten fehlen. So enthält ein Geschäftspartner zwar eine Referenz zur Geschäftspartnergruppe, aber damit hat man noch lange nicht den Namen dieser Gruppe, um ihn in Berichten auszugeben.

2. Schritt: Datenbank-View

Nun kann man mittels SQL "JOIN" Klauseln in der PostgreSQL-Datenbank Views einrichten, die Daten aus verschiedenen Tabellen zusammenführen. Ein solches View erzeugt eine flache Version der Datenbank und bildet unsere vormals strukturierten Daten auf eine einzige Tabelle ab, die dann sehr viele Spalten hat. Diese Tabelle bekommt eine eigene Tabellendefinition im Application Dictionary von iDempiere, was uns ermöglicht, auf diese Daten zuzugreifen.

3. Schritt: Eingrenzung durch Berichtsansicht

Die hier vorgestellte Funktionalität der Berichtsansicht dient nun dazu, die vorhandenen Daten einzugrenzen. In einer solchen Ansicht werden nur genau jene Spalten ausgewählt, die man in seinem Bericht wirklich benutzen möchte. Außerdem erlaubt die Berichtsansicht, die Daten mittels einer SQL-WHERE Clause einzugrenzen sowie mittels einer SQL GROUP Clause (und entsprechenden Aggregatfunktionen) zu verdichten.

Der Vorteil dieser Vorgehensweise ist, das die hier gemachten Einschränkungen direkt als SELECT-BEfehl an die Datenbank geschickt werden. So hat der Optimizer der Datenbank Gelegenheit, die Daten, die man nicht haben will, gar nicht erst zu laden und bereitzustellen. (Der PostgreSQL-Optimizer ist hier recht gut aufgestellt.) Das spart viel Zeit in der Datenbank, bei der Übertragung nach iDempiere und vor allem in der Persistenzschicht von iDempiere.

Bei der Erstellung eines Berichtes werden die hier zusammengestellten Daten in eine Berichtstabelle kopiert, die dann den angezeigten Bericht darstellt. Diese Berichtstabelle ist dann das Objekt, auf dem der Berichtsgenerator z.B. mit dem Druckformat angewendet wird.

4. Schritt: Ausgabe durch ein Druckformat (oder JasperReports)

Nun kann man im Druckformat nochmals angeben, das bestimmte Spalten gar nicht gedruckt oder gruppiert werden etc. Eine Gruppierung hier (im Gegensatz zum Berichts-View) hat den Vorteil, die Zusammenfassung der Daten flexibel ein- und ausschalten zu können und den Nachteil, das alle Daten erst bereitgestellt werden, was sehr langsam sein kann. Man tauscht also den optimierten Datenzugriff der Datenbank gegen die Flexibilität der Anzeige.

Natürlich kann ein Druckformat auch einen JasperReport benutzen. Hier gilt aber im Grunde das Gleiche. Ein ordentlich implementierter JasperReport in iDempiere wird ebenfalls die vorbereitete Berichtstabelle benutzen und damit den gleichen Gesetzmäßigkeiten wie ein interner Report unterliegen. (Wer in seinem JasperReport die Möglichkeiten des direkten SQL-Zugriffs auf alle Tabellen nutzt, mag hier Argumente für Sonderwege finden.)

Wie geht's?

Grundsätzlich kann eine Berichtsansicht bei der Anlage eines Druckformats angegeben werden. Auch eigenständige Berichts-Prozesse (die z.B. aus dem Menü heraus aufgerufen werden), erlauben die Angabe einer Berichtsansicht. Öffnet man diese (Bericht_Datenbank-Ansicht_(Fenster_ID-180)), so kann man zuerst einmal einen Namen vergeben. Diese sollte z.B. mit einem eigenen Prefix beginnen, um die eigenen Ansichten später leichter finden zu können. Auch den Entity Typ kann man entsprechend angeben (oder "User Maintained" lassen, falls man keinen eigenen verwendet). Als Tabelle sollte man nun die Basistabelle angeben, die durch diese Ansicht "abgespeckt" werden soll. Bei dieser Tabelle kann es sich natürlich sowohl um eine "echte" Tabelle als auch um ein Datenbankview handeln. Beide werden bekanntlich in iDempiere fast gleich eingerichtet.

WHERE-Klausel

Die erste - und wichtigste - Einschränkung ist nun die Angabe einer WHERE-Klausel. Hier können die angezeigten Daten zeilenweise eingeschränkt werden. An dieser Stelle können übrigens auch Umgebungs-Variablen verwendet werden, so das man z.B. nur die Kunden des aktuell eingeloggten Benutzers anzeigen kann.

Berichtszeilen

Unterhalb gibt es nun ein Detail-Register "Berichtsansichts-Zeilen". Dieses Register kann man völlig unangetastet lassen, was bedeutet, das alle Zeilen der zugrundeliegenden Tabelle für den Bericht eingelesen werden. Gibt man jedoch hier eine Zeile an, so müssen alle verwendeten Zeilen explizit angegeben werden.

Formeln

In jeder Zeile muss ich eine Formel angeben. Innerhalb dieser Formel steht der Platzhalter "@" für den Spaltenwert selbst. Möchte ich also nur die Menge der geladenen Spalten einschränken, reicht es, diesen überall einzusetzen. Ich kann hier aber auch SQL-Formeln angeben und mit einem Wert rechnen etc. Dabei muss ich (so, wie der Code in JavaEngine.java im Moment implementiert ist), genau ein '@' in der Formel verwenden, das dann durch die Spaltenbezeichnung ersetzt wird.

Leider kann man auf diese Art keine zusätzlichen Spalten (also z.B. eine Summe zweier anderer Spalten) definieren, da jeder Eintrag später über die angegebene Spalten-Definition (deren Auswahlfeld durch die zugrundeliegende Tabelle vorgegeben ist) gefunden und benutzt werden kann. Es steht einem allerdings frei, eine vorhandene, aber nicht benutzte Spalte für einen solchen Zweck "umzuwidmen".

Gruppierung

Unter Gruppierung versteht man die Zusammenfassung mehrerer Zeilen. Hier gibt es zwei Besonderheiten. Zum einen muss ich die Spalten angeben, nach denen ich gruppiere. Als Spaltenfunktion setze ich hier auch am einfachsten "@". Die Spalten, deren Werte ich nun innerhalb der Gruppe aggregieren will, erhalten eine Funktion. Hier kann man im SQL Formelfeld sogenannte Aggregatfunktionen benutzen, um z.B. eine Summe zu berechnen. Ein Beispiel ist "SUM(@)". Diese aggregierten Felder erhalten nun noch einen Haken beim Feld "Gruppierungsfunktion". Wichtig ist, das alle Felder, die Aggegatfunktionen enthalten, diesen Haken gesetzt haben und alle, die keine enthalten (also nach denen gruppiert wird), keinen.

Bei gruppierten Feldern ist übrigens darauf zu achten, das die Gruppierungsfelder später im Druckformat auch als Sortierfelder angegeben werden. Erstens würde das anders keinen Sinn machen und zweitens gibt das auch sonst eine Fehlermeldung bei der Ausgabe des Berichts.

Beispiel

Als Beispiel möchte ich z.B. aus den Buchhaltungsdaten die Umsätze eines Kunden zusammenfassen:

  • Als Basistabelle nehme ich "RV_Fact_Acct". Das ist ein View, das die Tabelle der Buchführungs-Details mit einigen anderen (von dort referenzierten) Tabellen kombiniert.
  • Mittels des WHERE-Feldes begrenze ich die Daten auf die Zeilen, die auf mein Verbindlichkeiten-Konto buchen (dazu vergleiche ich mit der Kontonummer in "accountvalue").
  • Ich erzeuge zwei Zeilen für die Kundennummer und den Kundennamen (beide sind Spalten in RV_Fact_Acct) und lasse den Haken für die Gruppierungsfunktion ausgeschaltet. Als Formel setze ich jeweils "@".
  • Dann erzeuge ich eine dritte Spalte mit der Formel "SUM(@)". Dort setze ich den Haken für eine Gruppierungsfunktion.

Das war's schon. Jetzt muss ich noch bei der Anzeige im Druckformat darauf achten, das ich die richtigen drei Spalten benutze ich nach den ersten beiden sortiere.