'Kommentar' hinzufügen zu PDF-Export "Umsätze nach Kategorien' (Auswertungen)

legis

Betreff:

'Kommentar' hinzufügen zu PDF-Export "Umsätze nach Kategorien' (Auswertungen)

 ·  Gepostet: 22.08.2026 - 12:03 Uhr  ·  #187646
Hallo Olaf, die Hausverwaltung 7 Whgen mit Mieterstrommodell ist komplexer geworden.
Per Kategorien ordne ich die DATEV-Buchhaltungskonten zu.
Für die Steuererklärung möchte ich dem StBer eine Konten/ -Kategorien-Liste geben, so, wie sie in Einstellungen/Kategorien aufgeklappt zu sehen ist.
Das funktioniert gut über Auswertungen/Umsätze nach Kategorien, nur fehlt da bei PDF-Export "Summen aller Kategorien mit EinN u. Ausg." die Einblendung der Kategorietitel, die in der Spalte 'Kommentar' bei der Kat-Anlage in 'Einstellungen' erfasst werden.
Inwelcher Steuerdatei kann ich das nachtragen, so daß als 2. Spalte im PDF "Kommentar", also die textliche Bezeichnung der Kategorie eingefügt wird?
Danke im Voraus,
Legis

legis

Betreff:

Google- KI-Antwort

 ·  Gepostet: 23.08.2026 - 11:33 Uhr  ·  #187653
Ich antworte mir mal selbst:
Auf die Frage in Google's Sucheingabezeile:
KI: welche Konfigurationsdatei in jameica/hibiscus auf linux Mint muss ich ändern, um in dem PDF Auswertungen/'Umsätze nach Kategorien mit Ennahmen und Ausgaben' zusätzlich den Namen der Kategorie aus der Spalte 'Kommentar' aus dem Formular 'Einstellungen/Kategorien anzeigen zu lassen?

habe ich diese Antwort bekommen:
Das Layout und die Spalten der PDF-Auswertungen in Hibiscus sind fest im Java-Quellcode des Programms programmiert. Es gibt keine einfache Konfigurationsdatei (wie eine .properties- oder .xml-Datei) im Verzeichnis ~/.jameica/hibiscus/, über die sich die Spaltenstruktur für diesen Export anpassen lässt.
Alternativen und Wege zur Lösung
Quellcode anpassen: Der Quellcode von Jameica und Hibiscus ist Open Source. Um eine Spalte hinzuzufügen, müssten Sie den Java-Code des Berichtsgenerators ändern und das Plugin neu kompilieren.
Externe Tools nutzen: Für erweiterte oder angepasste Berichte verwenden manche Nutzer Zusatzlösungen wie den Hibi-BuBe (Buchungs-Report Generator) aus dem Support-Forum, der erweiterte Exportfunktionen bietet.
CSV-Export: Exportieren Sie die Daten stattdessen im CSV-Format, und passen Sie die Tabelle in einer Tabellenkalkulation (wie LibreOffice Calc auf Linux Mint) an.


Da ich hibiscus in Base eingebunden habe, werde ich die csv in base einkopieren und dort viel komfortabler per Abfrage gestalten.
Könntest du die im System vorhandene SQL-Anweisung für die Abfrage hier einstellen, die der csv bzw. dem PDF zugrundeliegt?
Danke...
Nachtrag: Das Problem ist, daß diese Auswertung nur als PDF verfügbar ist, csv wird gar nicht angeboten...

infoman

Betreff:

Re: 'Kommentar' hinzufügen zu PDF-Export "Umsätze nach Kategorien' (Auswertungen)

 ·  Gepostet: 23.08.2026 - 13:28 Uhr  ·  #187657
Zitat geschrieben von legis
Für die Steuererklärung möchte ich dem StBer eine Konten/ -Kategorien-Liste geben

ist das mit dem Stb. abgesprochen, denn in der Regel will der doch Einzelpositionen selbst verarbeiten
wäre es nicht sinnvoller die relevanten Buchungen über den Export der Sachbearbeiterin zur Verfügung zu stellen, damit es korrekt im DATEV-System verarbeitet werden kann. (bei entsprechender Vorbereitung, erfolgt dies dann ja halbautomatisch)

legis

Betreff:

Re: 'Kommentar' hinzufügen zu PDF-Export "Umsätze nach Kategorien' (Auswertungen)

 ·  Gepostet: 23.08.2026 - 14:13 Uhr  ·  #187659
Hi Infoman,
- das ist eine Selbstverständlichkeit.
Natürlich hat der StBer die exportierten Buchungen längst als csv. Darin ist auch, wie du weißt, nur der "Name" der Kategorie enthalten - und das ist bei mir sinnvollerweise die Nummer des Datev-Kontos.
Damit arbeitet Datev - und im Übrigen auch meine Buchhaltung, mit der ich zB die BWA, Su+Saldenlisten EÜR etc erstelle.
Ich möchte ihm aber die benannte Übersicht geben, in der dann auch die textliche Bezeichnung zum Konto dargestellt wird und nicht nur die Kto-Nr.
In der PDF erscheint so nur der "Name", - und das ist bei mir die DATEV-Kontonummer, zB 810500 für die Mieteinnahmen mit den 810510-570 für die Whgen 1-7.
'Kommentar' für 810500 ist "Mieteinnahmen" und 810510 ist "Miete Wohnung 1".
Ist das jetzt verständlich? -Ich dachte, das wäre es.
Deine Antwort wird dem leider nicht gerecht.

hibiscus

Betreff:

Re: 'Kommentar' hinzufügen zu PDF-Export "Umsätze nach Kategorien' (Auswertungen)

 ·  Gepostet: Gestern um 07:47 Uhr  ·  #187666
Die KI schlägt doch hier als Lösung auch das neuee Plugin von little.yoda vor, welches einen generischen Report-Generator enthält, mit dem du dir die passenden Auswertungen selbst zusammenstellen kannst. Das wäre doch dafür genau die richtige Lösung: forum/topic.php?t=28128

little.yoda

Betreff:

Re: 'Kommentar' hinzufügen zu PDF-Export "Umsätze nach Kategorien' (Auswertungen)

 ·  Gepostet: Gestern um 08:10 Uhr  ·  #187668
kleine Korrektur: Das Hibi-BuBe-Pythonskript ist nicht von mir.

In meinem Plugin könntest du den gewünschten Report wahrscheinlich nachbauen.
https://github.com/littleyoda/hibiscus.ly.reports
Aktuell verstehe ich jedoch, auch nach mehrmaligen Lesen, die Anforderungen nicht.
Wahrscheinlich benötige ich ein Beispiel, um weiter zu helfen.

hibiscus

Betreff:

Re: 'Kommentar' hinzufügen zu PDF-Export "Umsätze nach Kategorien' (Auswertungen)

 ·  Gepostet: Gestern um 08:51 Uhr  ·  #187669
Sorry, da hatte ich etwas verwechselt. Ich meinte dein Plugin.
Ich hab die Anforderung so verstanden: In der Auswertung "Umsätze nach Kategorien" kann man auf "Exportieren..." klicken und dort als Format "PDF-Format: Summen aller Kategorien mit Einnahmen und Ausgaben" wählen. Dabei entsteht ein tabellarisches PDF mit den Spalten Kategorie, Einnahmen, Ausgaben, Betrag. legis hätte gern entweder in der Spalte "Kategorie" oder in einer neuen Extra-Spalte zusätzlich die Notizen mit ausgegeben, die bei der Kategorie hinterlegt sind. Das könnte man fest mit implementieren. Allerdings besteht da das Risiko, dass User dort vertrauliche/interne Vermerke eintragen, die eben NICHT mit exportiert werden sollen. Oder dass sie (da die Notizen eine Textarea sind) dort recht viele Informationen hinterlegen, die das Tabellenlayout beim Export kaputt machen würden. Als zusätzliche Checkbox-Option im Export-Dialog sehe ich es auch nicht, da es zu speziell nur für dieses ein Format gelten würde. Als Workaround hätte ich jetzt noch vorgeschlagen, die Bezeichnung der Kategorie einfach entsprechend um den zusätzlich auszugebenden Text zu erweitern.

little.yoda

Betreff:

Re: 'Kommentar' hinzufügen zu PDF-Export "Umsätze nach Kategorien' (Auswertungen)

 ·  Gepostet: Gestern um 09:35 Uhr  ·  #187675
Ist es so gemeint? [Nur bei ein paar Kategorien habe ich jetzt eine Notiz hinterlegt]
Der an diesem Beitrag angefügte Anhang ist entweder nur im eingeloggten Zustand sichtbar oder die Berechtigung Deiner Benutzergruppe ist nicht ausreichend.

hibiscus

Betreff:

Re: 'Kommentar' hinzufügen zu PDF-Export "Umsätze nach Kategorien' (Auswertungen)

 ·  Gepostet: Gestern um 09:37 Uhr  ·  #187676
Ja, ich denke, so ist das gemeint.

legis

Betreff:

Re: 'Kommentar' hinzufügen zu PDF-Export "Umsätze nach Kategorien' (Auswertungen)

 ·  Gepostet: Gestern um 10:43 Uhr  ·  #187680
Zitat geschrieben von legis

Nein - nicht 'Notizen', sondern ich habe bei 'Einstellungen - Umsatzkategorien' in der Anfangsspalte "Bezeichnung" die Kontonummer eingetragen und in der letzten Spalte "Kommentar" die Beschreibung der Kategorie, so:
Bezeichnung | Reihenf. | Suchbegr. | Umsatzart | Konto | Kommentar
1360 ---------- xyxyxy ---- egal ---- xy ---- Geldtransit
1590 --------- xyxyxy ---- egal ---- Kanzlei ---- Umbuchungen
1800 ---------- xyxyxy ---- egal ---- Spk ---- Umsatzsteuer
4210 ---------- Miete ---- Ausgabe -------- Miete
.......
und so weiter.
Das heißt, es müßte eine Abfrage aus den verbundenen Tabellen Umsatz und Umsatztyp erfolgen...

Die genannte PDF-Auswertung soll nach Spalten aussehen:
Kategorie | Kommentar | Einnahmen | Ausgaben | Betrag
4210 -------- Miete -------- xyx.-- € ------ 0,00 € -------xyx,-- €
Mit den textlichen Bezeichnungen als Kategorie, wie little.yoda sie dargestellt hat, kann der Steuerberater für das Steuererklärungsprogramm nichts anfangen, er müßte die erst in die Datev-Kontonummern umwandeln.
Auch meine eigene Buchhaltung ist so aufgebaut, habe ich mal vor fast 30 Jahren mit Access aufgebaut und muß ich noch in LO Base umbauen, dann kann ich die Buchhaltung direkt aus der Hibiscus-DB H2 als BWA etc, auch Umsatzsteuer-Voranmeldung, mit dem Jahr als Parameterfeld mit einem Mausklick erstellen lassen.
Die begehrte PDF-Auswertung dient nur der Übersicht für die steuerliche Verarbeitung.
Wäre schön, wenn sich das einbauen ließe.
Danke!

hibiscus

Betreff:

Re: 'Kommentar' hinzufügen zu PDF-Export "Umsätze nach Kategorien' (Auswertungen)

 ·  Gepostet: Gestern um 11:14 Uhr  ·  #187683
OK, hier kann ich nicht mehr folgen.

little.yoda

Betreff:

Re: 'Kommentar' hinzufügen zu PDF-Export "Umsätze nach Kategorien' (Auswertungen)

 ·  Gepostet: Gestern um 11:27 Uhr  ·  #187684
Mir geht es wie Olaf.

Ich habe in meinem Beispiel natürlich Kategoriebezeichnungen aus meiner Demodatenbank genommen.

Wenn du diese Kategoriebezeichnungen jetzt gedanklich durch deine "Datev-Kontonummern" ersetzt, bekommst du doch das gewünschte heraus. Oder?

Kategorie (Quelle: Einstellungen/Umsatz-Kategorien/Bezeichnung)
Kommentar / Notiz (Quelle: Einstellungen/Umsatz-Kategorien/Kommentar)
Einnahmen (Summe aller positiven Umsätze)
Ausgaben (Summe aller negativen Umsätze)
Betrag (Einnahme + Ausgaben)

Probiere es einfach mal aus:
Lade dir die aktuellste Version des Reports-Plugin (1.3.1) herunter und füge folgendes als Report hinzu.

Code
{% set startdatum = "2026-01-08" %}
{% set enddatum = "2027-06-30" %}
{# Leer = alle aktiven Konten; sonst IBANs, z. B. ["DE123...", "DE456..."] #}
{% set konto_ibans = [] %}
<!doctype html>
<html lang="de">
<head>
  <meta charset="utf-8">
  <title>Umsatzkategorien</title>
  <style>
    :root {
      color: #202124;
      background: #fff;
      font: 14px/1.35 Arial, sans-serif;
    }

    body {
      margin: 0;
      padding: 34px 42px;
    }

    h1 {
      margin: 0;
      text-align: center;
      font-size: 23px;
      font-weight: 600;
    }

    .subtitle {
      margin: 5px 0 26px;
      text-align: center;
      color: #4b5563;
    }

    table {
      width: 100%;
      border-collapse: collapse;
      font-variant-numeric: tabular-nums;
    }

    th {
      padding: 6px 8px;
      border-bottom: 2px solid #9ca3af;
      text-align: left;
      font-weight: 600;
    }

    td {
      padding: 3px 8px;
      border-bottom: 1px solid #e5e7eb;
    }

    tbody tr.root td {
      padding-top: 8px;
      font-weight: 600;
    }

    .category {
      width: 25%;
      padding-left: calc(8px + var(--depth) * 22px);
    }

    .note {
      width: 30%;
      color: #4b5563;
      white-space: pre-wrap;
      overflow-wrap: anywhere;
    }

    tbody tr.root .note {
      font-weight: 400;
    }

    .amount {
      width: 15%;
      text-align: right;
      white-space: nowrap;
    }

    .empty,
    .error {
      padding: 30px 8px;
      text-align: center;
      color: #6b7280;
    }

    .source {
      display: none;
    }

    .attribution {
      margin: 24px 0 0;
      color: #6b7280;
      font-size: 12px;
      text-align: right;
    }

    .attribution a {
      color: inherit;
    }

    @media print {
      body { padding: 18mm 14mm; }
      thead { display: table-header-group; }
      tr { break-inside: avoid; }
    }
  </style>
</head>
<body>
  <h1>Umsatzkategorien</h1>
  <p class="subtitle">
    Zeitraum: <span id="period"></span>, <span id="accounts-label"></span>
  </p>

  <table aria-label="Summen nach Umsatzkategorie">
    <thead>
      <tr>
        <th>Kategorie</th>
        <th>Notiz</th>
        <th class="amount">Einnahmen</th>
        <th class="amount">Ausgaben</th>
        <th class="amount">Betrag</th>
      </tr>
    </thead>
    <tbody id="result"></tbody>
  </table>

  <p class="attribution">
    Urheber: <a href="https://littleyoda.github.io/" target="_blank"
                 rel="noopener noreferrer">littleyoda</a>
  </p>

  <div class="source" id="configuration"
       data-start="{{ startdatum }}" data-end="{{ enddatum }}">
    {% for iban in konto_ibans %}<i class="selected-iban">{{ iban }}</i>{% endfor %}
  </div>

  <div class="source" id="accounts">
    {% for konto in konten.alle %}
    <i class="account">
      <b class="account-id">{{ konto.id }}</b>
      <span class="account-name">{{ konto.name }}</span>
      <span class="account-iban">{{ konto.iban }}</span>
      <span class="account-active">{{ konto.aktiv }}</span>
    </i>
    {% endfor %}
  </div>

  <div class="source" id="categories">
    {% for kategorie in kategorien %}
    <i class="catalog-category">
      <b class="category-id">{{ kategorie.id }}</b>
      <span class="category-name">{{ kategorie.name }}</span>
      <span class="category-note">{{ kategorie.notiz }}</span>
      <span class="category-skipped">{{ kategorie.skipReportsEffective }}</span>
      <span class="category-order">{{ loop.index0 }}</span>
    </i>
    {% endfor %}
  </div>

  <div class="source" id="transactions">
    {% for umsatz in umsaetze.alle %}
    <div class="transaction">
      <i class="date">{{ umsatz.datum }}</i>
      <i class="account-id">{{ umsatz.konto.id }}</i>
      <i class="value">{{ umsatz.betrag }}</i>
      <div class="path">
        {% for kategorie in umsatz.kategoriePfad %}
        <i class="path-part"><b>{{ kategorie.id }}</b><span>{{ kategorie.name }}</span></i>
        {% endfor %}
      </div>
    </div>
    {% endfor %}
  </div>

  <script>
    (() => {
      const config = document.getElementById("configuration");
      const start = config.dataset.start;
      const end = config.dataset.end;
      const normalizeIban = value => value.replace(/\s+/g, "").toUpperCase();
      const explicitlySelected = [...config.querySelectorAll(".selected-iban")]
        .map(element => normalizeIban(element.textContent));
      const accounts = [...document.querySelectorAll("#accounts .account")].map(element => ({
        id: element.querySelector(".account-id").textContent.trim(),
        name: element.querySelector(".account-name").textContent.trim(),
        iban: normalizeIban(element.querySelector(".account-iban").textContent),
        active: element.querySelector(".account-active").textContent.trim() === "true"
      }));
      const selectedAccounts = explicitlySelected.length
        ? accounts.filter(account => explicitlySelected.includes(account.iban))
        : accounts.filter(account => account.active);
      const selected = new Set(selectedAccounts.map(account => account.id));
      const categories = new Map([...document.querySelectorAll("#categories .catalog-category")]
        .map(element => {
          const text = selector => element.querySelector(selector).textContent.trim();
          return [text(".category-id"), {
            name: text(".category-name"),
            note: text(".category-note"),
            skipped: text(".category-skipped") === "true",
            order: Number(text(".category-order"))
          }];
        }));
      const roots = new Map();

      function child(parent, id, name) {
        const key = id || `name:${name}`;
        if (!parent.children.has(key)) {
          const metadata = categories.get(id);
          parent.children.set(key, {
            name: metadata?.name || name,
            note: metadata?.note || "",
            order: metadata?.order ?? Number.MAX_SAFE_INTEGER,
            income: 0,
            expenses: 0,
            children: new Map()
          });
        }
        return parent.children.get(key);
      }

      function add(node, value) {
        if (value >= 0) node.income += value;
        else node.expenses += value;
      }

      const uncategorized = {
        name: "Nicht zugeordnet", note: "", order: -1,
        income: 0, expenses: 0, children: new Map()
      };
      for (const transaction of document.querySelectorAll("#transactions .transaction")) {
        const date = transaction.querySelector(".date").textContent.trim();
        const accountId = transaction.querySelector(".account-id").textContent.trim();
        if (date < start || date > end || !selected.has(accountId)) continue;

        const value = Number(transaction.querySelector(".value").textContent.trim());
        if (!Number.isFinite(value)) continue;
        const path = [...transaction.querySelectorAll(".path-part")];
        if (!path.length) {
          add(uncategorized, value);
          continue;
        }
        const pathIds = path.map(part => part.querySelector("b").textContent.trim());
        if (pathIds.some(id => categories.get(id)?.skipped)) continue;

        let parent = { children: roots };
        for (const part of path) {
          const node = child(parent,
            part.querySelector("b").textContent.trim(),
            part.querySelector("span").textContent.trim());
          add(node, value);
          parent = node;
        }
      }

      const money = new Intl.NumberFormat("de-DE", {
        minimumFractionDigits: 2,
        maximumFractionDigits: 2
      });
      const date = value => {
        const [year, month, day] = value.split("-");
        return `${day}.${month}.${year}`;
      };
      const rows = [];

      function appendRow(node, depth) {
        const row = document.createElement("tr");
        if (depth === 0) row.className = "root";
        const category = document.createElement("td");
        category.className = "category";
        category.style.setProperty("--depth", depth);
        category.textContent = node.name;
        row.append(category);
        const note = document.createElement("td");
        note.className = "note";
        note.textContent = node.note;
        row.append(note);
        for (const value of [node.income, node.expenses, node.income + node.expenses]) {
          const cell = document.createElement("td");
          cell.className = "amount";
          cell.textContent = money.format(value);
          row.append(cell);
        }
        rows.push(row);
        [...node.children.values()]
          .sort((left, right) => left.order - right.order
            || left.name.localeCompare(right.name, "de", { numeric: true }))
          .forEach(childNode => appendRow(childNode, depth + 1));
      }

      if (uncategorized.income || uncategorized.expenses) appendRow(uncategorized, 0);
      [...roots.values()]
        .sort((left, right) => left.order - right.order
          || left.name.localeCompare(right.name, "de", { numeric: true }))
        .forEach(node => appendRow(node, 0));

      const result = document.getElementById("result");
      if (rows.length) result.append(...rows);
      else result.innerHTML = '<tr><td class="empty" colspan="5">Keine Umsätze für die Auswahl gefunden.</td></tr>';

      document.getElementById("period").textContent = `${date(start)} - ${date(end)}`;
      if (!explicitlySelected.length) {
        document.getElementById("accounts-label").textContent = "alle aktiven Konten";
      } else {
        const labels = selectedAccounts.map(account => account.name);
        const known = new Set(selectedAccounts.map(account => account.iban));
        explicitlySelected
          .filter(iban => !known.has(iban))
          .forEach(iban => labels.push(`IBAN ${iban} (nicht gefunden)`));
        document.getElementById("accounts-label").textContent = labels.join(", ");
      }
    })();
  </script>
</body>
</html>

legis

Betreff:

Re: 'Kommentar' hinzufügen zu PDF-Export "Umsätze nach Kategorien' (Auswertungen)

 ·  Gepostet: Gestern um 11:45 Uhr  ·  #187685
Danke - little.yoda, für Deine Mühe.
Ich hatte mir einfach vorgestellt, die sehr schöne Ausgabe-PDF mit eingerückten Unterkategorien um die eine Spalte zu ergänzen.
Deine Lösung scheint mir recht kompliziert einzubauen und dann aktuell zu halten.
Wenn ich mir die Arbeit mache, könnte es einfacher sein, per Base - Abfragen und Report das ebenso zu gestalten, müßte mir aber die Einrückung für Unterkategorien zurechtbasteln, - alles zuviel Aufwand.
Ich dachte, es sei kein nennenswerter Aufwand, über eine der .properties -Dateien das einstellen zu können.
Ok, - wenn's nicht geht, dann geht es eben nicht...
Vielen Dank Dir und Olaf,
Legis