diff --git a/README.md b/README.md index bd73973..83da735 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # BUCHHALTUNGS-WIDGET / ACCOUNTING WIDGETS FOR [DOLIBARR ERP & CRM](https://www.dolibarr.org) -**Version:** 1.2 +**Version:** 1.3 **Compatibility:** Dolibarr 19.0+ **Author:** Eduard Wisch - Data IT Solution **License:** GPL v3+ @@ -21,23 +21,33 @@ Das Buchhaltungs-Widget Modul erweitert Dolibarr um drei leistungsstarke Dashboa - Aktuelles Quartal hervorgehoben - Farbcodierung: Rot = Zahllast, Gruen = Erstattung - Detailseite mit monatlicher/quartalsweiser Ansicht +- Hilfe-Icon mit Erklaerung der Berechnung -#### 2. Gewinn/Verlust +#### 2. Gewinn/Verlust (Rohertrag) - Kumulierter Gewinn/Verlust im Jahresverlauf -- Beruecksichtigt nur kundenbezogene Materialkosten -- Keine Betriebskosten (Miete, Nebenkosten etc.) +- Berechnung ueber Buchungskonten (wenn vorhanden): + - Einnahmen: Kontenklasse 8xxx (Erloese) + - Materialkosten: Kontenklasse 3xxx (Wareneinsatz) +- Keine Betriebskosten (4xxx) - nur Rohertrag +- Fallback auf Rechnungsdaten wenn keine Buchungen vorhanden - Schaetzung der Einkommensteuer - Farbige Linie: Gruen = Gewinn, Rot = Verlust +- Hilfe-Icon mit Erklaerung der Berechnung -#### 3. Rentabilitaet -- Vergleich: Materialeinkauf vs. Rechnungsstellung +#### 3. Rentabilitaet (Echte Rentabilitaet) +- Zeigt echte Rentabilitaet inkl. ALLER Kosten +- Berechnung ueber Buchungskonten (wenn vorhanden): + - Einnahmen: Kontenklasse 8xxx (Erloese) + - Alle Ausgaben: Kontenklasse 3xxx + 4xxx (Wareneinsatz + Betriebskosten) +- Fallback auf Rechnungsdaten wenn keine Buchungen vorhanden - Gewinnmarge in Prozent - Produktivitaetsbewertung mit 5 Stufen: - - Ausgezeichnet (>50%) - - Gut (30-50%) - - Durchschnittlich (15-30%) - - Niedrig (0-15%) + - Ausgezeichnet (>100%) + - Gut (50-100%) + - Durchschnittlich (20-50%) + - Niedrig (0-20%) - Kritisch (<0%) +- Hilfe-Icon mit Erklaerung der Berechnung ### Zahlungsstatistik (Kundenkarte) @@ -95,23 +105,33 @@ The Accounting Widgets module extends Dolibarr with three powerful dashboard wid - Current quarter highlighted - Color coding: Red = to pay, Green = refund - Detail page with monthly/quarterly view +- Help icon explaining calculation -#### 2. Profit/Loss +#### 2. Profit/Loss (Gross Margin) - Cumulative profit/loss throughout the year -- Only considers customer-related material costs -- Excludes operating costs (rent, utilities, etc.) +- Calculation via accounting accounts (if available): + - Income: Account class 8xxx (Revenue) + - Material costs: Account class 3xxx (Cost of goods) +- No operating costs (4xxx) - gross margin only +- Fallback to invoice data if no bookings exist - Income tax estimation - Colored line: Green = profit, Red = loss +- Help icon explaining calculation -#### 3. Profitability -- Comparison: Material purchases vs. invoiced amounts +#### 3. Profitability (Real Profitability) +- Shows real profitability including ALL costs +- Calculation via accounting accounts (if available): + - Income: Account class 8xxx (Revenue) + - All expenses: Account class 3xxx + 4xxx (Cost of goods + Operating costs) +- Fallback to invoice data if no bookings exist - Profit margin percentage - Productivity rating with 5 levels: - - Excellent (>50%) - - Good (30-50%) - - Average (15-30%) - - Low (0-15%) + - Excellent (>100%) + - Good (50-100%) + - Average (20-50%) + - Low (0-20%) - Critical (<0%) +- Help icon explaining calculation ### Payment Statistics (Customer Card) @@ -157,6 +177,15 @@ The following options can be configured in the admin area: ## Changelog +### Version 1.3 +- Neu: Praezise Berechnung ueber Buchungskonten (SKR03/SKR04) + - Gewinn/Verlust: Kontenklasse 8xxx (Erloese) minus 3xxx (Wareneinsatz) + - Rentabilitaet: Kontenklasse 8xxx minus 3xxx + 4xxx (alle Kosten) +- Neu: Automatischer Fallback auf Rechnungsdaten wenn keine Buchungen vorhanden +- Neu: Hilfe-Icons mit Tooltips bei allen Widgets +- Neu: Dynamisches Chart.js-Laden (Charts funktionieren jetzt auch auf Dashboard ohne vorheriges Laden) +- Fix: Charts wurden nicht angezeigt wenn Chart.js nicht geladen war + ### Version 1.2 - Fix: VAT widget showed paid VAT (input tax) always as 0 (wrong column name in supplier invoice detail table) - Fix: Cancelled invoices (status 3) were included in all financial calculations diff --git a/core/boxes/box_gewinn_verlust.php b/core/boxes/box_gewinn_verlust.php index 3e33337..6818fe7 100755 --- a/core/boxes/box_gewinn_verlust.php +++ b/core/boxes/box_gewinn_verlust.php @@ -44,8 +44,9 @@ class box_gewinn_verlust extends ModeleBoxes $langs->loadLangs(array("buchaltungswidget@buchaltungswidget", "bills", "compta")); + $helpText = $langs->trans("GewinnVerlustHelpText"); $this->info_box_head = array( - 'text' => $langs->trans("GewinnVerlust"), + 'text' => $langs->trans("GewinnVerlust").' '.img_picto($helpText, 'help', 'class="opacitymedium"').'', 'sublink' => dol_buildpath('/buchaltungswidget/gewinn_detail.php', 1), 'subpicto' => 'chart', 'subtext' => $langs->trans("ShowDetails"), @@ -91,12 +92,13 @@ class box_gewinn_verlust extends ModeleBoxes 'td' => 'colspan="4" class="buchaltung-chart-container"', 'text' => ' ', 'asis' => 1, ); @@ -274,8 +291,10 @@ class box_gewinn_verlust extends ModeleBoxes /** * Get income and customer-related expenses by month - * IMPORTANT: Only includes costs related to customer projects (materials for customers), - * NOT company overhead costs + * Uses accounting accounts (Buchungskonten) for precise filtering: + * - Income: Account 8xxx (Erlöse) + * - Material costs: Account 3xxx (Wareneinsatz/Materialkosten) + * Excludes: Operating costs (4xxx), overhead, tools, etc. */ private function getIncomeExpenseByMonth($year) { @@ -286,48 +305,102 @@ class box_gewinn_verlust extends ModeleBoxes 'customer_expenses' => array_fill(1, 12, 0), ); - // Income from customer invoices - $sql = "SELECT MONTH(f.datef) as month, SUM(f.total_ht) as total"; - $sql .= " FROM ".MAIN_DB_PREFIX."facture as f"; - $sql .= " WHERE f.fk_statut IN (1, 2) AND f.entity = ".((int) $conf->entity); - $sql .= " AND YEAR(f.datef) = ".((int) $year); - $sql .= " GROUP BY MONTH(f.datef)"; + // Check if accounting module is active and has data + $useAccounting = $this->hasAccountingData($year); - $resql = $this->db->query($sql); - if ($resql) { - while ($obj = $this->db->fetch_object($resql)) { - $result['income'][$obj->month] = (float) $obj->total; + if ($useAccounting) { + // Income from accounting: Account 8xxx (Erlöse) + $sql = "SELECT MONTH(b.doc_date) as month, ABS(SUM(CASE WHEN b.sens = 'C' THEN b.montant ELSE -b.montant END)) as total"; + $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as b"; + $sql .= " WHERE b.entity = ".((int) $conf->entity); + $sql .= " AND YEAR(b.doc_date) = ".((int) $year); + $sql .= " AND b.numero_compte LIKE '8%'"; // Erlöskonten + $sql .= " GROUP BY MONTH(b.doc_date)"; + + $resql = $this->db->query($sql); + if ($resql) { + while ($obj = $this->db->fetch_object($resql)) { + $result['income'][$obj->month] = (float) $obj->total; + } + $this->db->free($resql); } - $this->db->free($resql); - } - // Customer-related expenses only: - // - Products (materials) for customers (product_type = 0) - // - Services directly for customers - // Exclude: Company overhead, rent, utilities, etc. - $sql = "SELECT MONTH(f.datef) as month, SUM(fd.total_ht) as total"; - $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f"; - $sql .= " INNER JOIN ".MAIN_DB_PREFIX."facture_fourn_det as fd ON fd.fk_facture_fourn = f.rowid"; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = fd.fk_product"; - $sql .= " WHERE f.fk_statut IN (1, 2) AND f.entity = ".((int) $conf->entity); - $sql .= " AND YEAR(f.datef) = ".((int) $year); - // Only include products (materials) - product_type 0 = product, 1 = service - // Also include invoice lines with product linked - $sql .= " AND (fd.fk_product IS NOT NULL AND fd.fk_product > 0)"; - $sql .= " AND (p.fk_product_type = 0 OR fd.product_type = 0)"; // Materials only - $sql .= " GROUP BY MONTH(f.datef)"; + // Material costs from accounting: Account 3xxx (Wareneinsatz) + $sql = "SELECT MONTH(b.doc_date) as month, SUM(CASE WHEN b.sens = 'D' THEN b.montant ELSE -b.montant END) as total"; + $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as b"; + $sql .= " WHERE b.entity = ".((int) $conf->entity); + $sql .= " AND YEAR(b.doc_date) = ".((int) $year); + $sql .= " AND b.numero_compte LIKE '3%'"; // Wareneinsatz/Materialkosten + $sql .= " GROUP BY MONTH(b.doc_date)"; - $resql = $this->db->query($sql); - if ($resql) { - while ($obj = $this->db->fetch_object($resql)) { - $result['customer_expenses'][$obj->month] = (float) $obj->total; + $resql = $this->db->query($sql); + if ($resql) { + while ($obj = $this->db->fetch_object($resql)) { + $result['customer_expenses'][$obj->month] = (float) $obj->total; + } + $this->db->free($resql); + } + } else { + // Fallback: Use invoice data if no accounting entries exist + // Income from customer invoices + $sql = "SELECT MONTH(f.datef) as month, SUM(f.total_ht) as total"; + $sql .= " FROM ".MAIN_DB_PREFIX."facture as f"; + $sql .= " WHERE f.fk_statut IN (1, 2) AND f.entity = ".((int) $conf->entity); + $sql .= " AND YEAR(f.datef) = ".((int) $year); + $sql .= " GROUP BY MONTH(f.datef)"; + + $resql = $this->db->query($sql); + if ($resql) { + while ($obj = $this->db->fetch_object($resql)) { + $result['income'][$obj->month] = (float) $obj->total; + } + $this->db->free($resql); + } + + // Material costs from supplier invoices (products only) + $sql = "SELECT MONTH(f.datef) as month, SUM(fd.total_ht) as total"; + $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f"; + $sql .= " INNER JOIN ".MAIN_DB_PREFIX."facture_fourn_det as fd ON fd.fk_facture_fourn = f.rowid"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = fd.fk_product"; + $sql .= " WHERE f.fk_statut IN (1, 2) AND f.entity = ".((int) $conf->entity); + $sql .= " AND YEAR(f.datef) = ".((int) $year); + $sql .= " AND (fd.fk_product IS NOT NULL AND fd.fk_product > 0)"; + $sql .= " AND (p.fk_product_type = 0 OR fd.product_type = 0)"; + $sql .= " GROUP BY MONTH(f.datef)"; + + $resql = $this->db->query($sql); + if ($resql) { + while ($obj = $this->db->fetch_object($resql)) { + $result['customer_expenses'][$obj->month] = (float) $obj->total; + } + $this->db->free($resql); } - $this->db->free($resql); } return $result; } + /** + * Check if accounting data exists for the given year + */ + private function hasAccountingData($year) + { + global $conf; + + $sql = "SELECT COUNT(*) as cnt FROM ".MAIN_DB_PREFIX."accounting_bookkeeping"; + $sql .= " WHERE entity = ".((int) $conf->entity); + $sql .= " AND YEAR(doc_date) = ".((int) $year); + $sql .= " LIMIT 1"; + + $resql = $this->db->query($sql); + if ($resql) { + $obj = $this->db->fetch_object($resql); + $this->db->free($resql); + return ($obj->cnt > 0); + } + return false; + } + /** * Calculate statistical projection for next year based on trends */ diff --git a/core/boxes/box_rentabilitaet.php b/core/boxes/box_rentabilitaet.php index e2c5946..1e8093a 100755 --- a/core/boxes/box_rentabilitaet.php +++ b/core/boxes/box_rentabilitaet.php @@ -44,8 +44,9 @@ class box_rentabilitaet extends ModeleBoxes $langs->loadLangs(array("buchaltungswidget@buchaltungswidget", "bills", "compta")); + $helpText = $langs->trans("RentabilitaetHelpText"); $this->info_box_head = array( - 'text' => $langs->trans("Rentabilitaet"), + 'text' => $langs->trans("Rentabilitaet").' '.img_picto($helpText, 'help', 'class="opacitymedium"').'', 'sublink' => dol_buildpath('/buchaltungswidget/rentabilitaet_detail.php', 1), 'subpicto' => 'chart', 'subtext' => $langs->trans("ShowDetails"), @@ -86,10 +87,11 @@ class box_rentabilitaet extends ModeleBoxes 'td' => 'colspan="4" class="buchaltung-chart-container"', 'text' => ' ', 'asis' => 1, ); @@ -170,12 +187,12 @@ class box_rentabilitaet extends ModeleBoxes $this->info_box_contents[$line][] = array('td' => 'class="buchaltung-header right buchaltung-future"', 'text' => $nextYear.' *'); $line++; - // Materials purchased (only for customers!) + // All expenses (materials + operating costs) $purchasedLast = array_sum($dataLastYear['purchased']); $purchasedCurrent = array_sum(array_slice($dataCurrentYear['purchased'], 0, $currentMonth, true)); $purchasedProjection = $projectionNextYear['purchased']; - $this->info_box_contents[$line][] = array('td' => 'class="buchaltung-label"', 'text' => $langs->trans("MaterialsPurchasedForCustomers")); + $this->info_box_contents[$line][] = array('td' => 'class="buchaltung-label"', 'text' => $langs->trans("AllExpenses")); $this->info_box_contents[$line][] = array('td' => 'class="right buchaltung-lastyear"', 'text' => price($purchasedLast, 0, $langs, 1, 0, 0, $conf->currency)); $this->info_box_contents[$line][] = array('td' => 'class="right"', 'text' => price($purchasedCurrent, 0, $langs, 1, 0, 0, $conf->currency)); $this->info_box_contents[$line][] = array('td' => 'class="right buchaltung-future"', 'text' => price($purchasedProjection, 0, $langs, 1, 0, 0, $conf->currency)); @@ -238,7 +255,7 @@ class box_rentabilitaet extends ModeleBoxes // Footer note $this->info_box_contents[$line][] = array( 'td' => 'colspan="4" class="buchaltung-footnote"', - 'text' => '* '.$langs->trans("StatisticalProjection").' | '.$langs->trans("OnlyCustomerMaterials").'', + 'text' => '* '.$langs->trans("StatisticalProjection").' | '.$langs->trans("AllCostsIncluded").'', 'asis' => 1, ); } @@ -285,7 +302,10 @@ class box_rentabilitaet extends ModeleBoxes /** * Get profitability data by month - * IMPORTANT: Only materials purchased FOR CUSTOMERS, not general company expenses + * Uses accounting accounts for precise filtering: + * - Income: Account 8xxx (Erlöse) + * - ALL expenses: Account 3xxx (Wareneinsatz) + 4xxx (Betriebskosten) + * This shows REAL profitability including all overhead costs */ private function getProfitabilityByMonth($year) { @@ -296,47 +316,98 @@ class box_rentabilitaet extends ModeleBoxes 'invoiced' => array_fill(1, 12, 0), ); - // Materials purchased FOR CUSTOMERS only (products, not services) - // This should be materials that are resold or used in customer projects - $sql = "SELECT MONTH(f.datef) as month, SUM(fd.total_ht) as total"; - $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f"; - $sql .= " INNER JOIN ".MAIN_DB_PREFIX."facture_fourn_det as fd ON fd.fk_facture_fourn = f.rowid"; - $sql .= " INNER JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = fd.fk_product"; - $sql .= " WHERE f.fk_statut IN (1, 2) AND f.entity = ".((int) $conf->entity); - $sql .= " AND YEAR(f.datef) = ".((int) $year); - // Only products (type 0), not services (type 1) - // And only products that are meant for resale or customer projects - $sql .= " AND p.fk_product_type = 0"; // Products only - $sql .= " AND (p.tobuy = 1 OR p.tosell = 1)"; // Products that are bought/sold - $sql .= " GROUP BY MONTH(f.datef)"; + // Check if accounting module is active and has data + $useAccounting = $this->hasAccountingData($year); - $resql = $this->db->query($sql); - if ($resql) { - while ($obj = $this->db->fetch_object($resql)) { - $result['purchased'][$obj->month] = (float) $obj->total; + if ($useAccounting) { + // Income from accounting: Account 8xxx (Erlöse) + $sql = "SELECT MONTH(b.doc_date) as month, ABS(SUM(CASE WHEN b.sens = 'C' THEN b.montant ELSE -b.montant END)) as total"; + $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as b"; + $sql .= " WHERE b.entity = ".((int) $conf->entity); + $sql .= " AND YEAR(b.doc_date) = ".((int) $year); + $sql .= " AND b.numero_compte LIKE '8%'"; // Erlöskonten + $sql .= " GROUP BY MONTH(b.doc_date)"; + + $resql = $this->db->query($sql); + if ($resql) { + while ($obj = $this->db->fetch_object($resql)) { + $result['invoiced'][$obj->month] = (float) $obj->total; + } + $this->db->free($resql); } - $this->db->free($resql); - } - // All materials and services invoiced to customers - $sql = "SELECT MONTH(f.datef) as month, SUM(fd.total_ht) as total"; - $sql .= " FROM ".MAIN_DB_PREFIX."facture as f"; - $sql .= " INNER JOIN ".MAIN_DB_PREFIX."facturedet as fd ON fd.fk_facture = f.rowid"; - $sql .= " WHERE f.fk_statut IN (1, 2) AND f.entity = ".((int) $conf->entity); - $sql .= " AND YEAR(f.datef) = ".((int) $year); - $sql .= " GROUP BY MONTH(f.datef)"; + // ALL expenses from accounting: Account 3xxx + 4xxx + $sql = "SELECT MONTH(b.doc_date) as month, SUM(CASE WHEN b.sens = 'D' THEN b.montant ELSE -b.montant END) as total"; + $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as b"; + $sql .= " WHERE b.entity = ".((int) $conf->entity); + $sql .= " AND YEAR(b.doc_date) = ".((int) $year); + $sql .= " AND (b.numero_compte LIKE '3%' OR b.numero_compte LIKE '4%')"; // Wareneinsatz + Betriebskosten + $sql .= " GROUP BY MONTH(b.doc_date)"; - $resql = $this->db->query($sql); - if ($resql) { - while ($obj = $this->db->fetch_object($resql)) { - $result['invoiced'][$obj->month] = (float) $obj->total; + $resql = $this->db->query($sql); + if ($resql) { + while ($obj = $this->db->fetch_object($resql)) { + $result['purchased'][$obj->month] = (float) $obj->total; + } + $this->db->free($resql); + } + } else { + // Fallback: Use invoice data if no accounting entries exist + // ALL supplier invoices (all expenses) + $sql = "SELECT MONTH(f.datef) as month, SUM(f.total_ht) as total"; + $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f"; + $sql .= " WHERE f.fk_statut IN (1, 2) AND f.entity = ".((int) $conf->entity); + $sql .= " AND YEAR(f.datef) = ".((int) $year); + $sql .= " GROUP BY MONTH(f.datef)"; + + $resql = $this->db->query($sql); + if ($resql) { + while ($obj = $this->db->fetch_object($resql)) { + $result['purchased'][$obj->month] = (float) $obj->total; + } + $this->db->free($resql); + } + + // All customer invoices (income) + $sql = "SELECT MONTH(f.datef) as month, SUM(f.total_ht) as total"; + $sql .= " FROM ".MAIN_DB_PREFIX."facture as f"; + $sql .= " WHERE f.fk_statut IN (1, 2) AND f.entity = ".((int) $conf->entity); + $sql .= " AND YEAR(f.datef) = ".((int) $year); + $sql .= " GROUP BY MONTH(f.datef)"; + + $resql = $this->db->query($sql); + if ($resql) { + while ($obj = $this->db->fetch_object($resql)) { + $result['invoiced'][$obj->month] = (float) $obj->total; + } + $this->db->free($resql); } - $this->db->free($resql); } return $result; } + /** + * Check if accounting data exists for the given year + */ + private function hasAccountingData($year) + { + global $conf; + + $sql = "SELECT COUNT(*) as cnt FROM ".MAIN_DB_PREFIX."accounting_bookkeeping"; + $sql .= " WHERE entity = ".((int) $conf->entity); + $sql .= " AND YEAR(doc_date) = ".((int) $year); + $sql .= " LIMIT 1"; + + $resql = $this->db->query($sql); + if ($resql) { + $obj = $this->db->fetch_object($resql); + $this->db->free($resql); + return ($obj->cnt > 0); + } + return false; + } + /** * Calculate statistical projection for next year */ diff --git a/core/boxes/box_ust_uebersicht.php b/core/boxes/box_ust_uebersicht.php index 3063341..c8483e1 100755 --- a/core/boxes/box_ust_uebersicht.php +++ b/core/boxes/box_ust_uebersicht.php @@ -50,8 +50,9 @@ class box_ust_uebersicht extends ModeleBoxes $langs->loadLangs(array("buchaltungswidget@buchaltungswidget", "bills", "compta")); + $helpText = $langs->trans("UStUebersichtHelpText"); $this->info_box_head = array( - 'text' => $langs->trans("UStUebersicht"), + 'text' => $langs->trans("UStUebersicht").' '.img_picto($helpText, 'help', 'class="opacitymedium"').'', 'sublink' => dol_buildpath('/buchaltungswidget/ust_detail.php', 1), 'subpicto' => 'chart', 'subtext' => $langs->trans("ShowDetails"), @@ -88,10 +89,11 @@ class box_ust_uebersicht extends ModeleBoxes 'td' => 'colspan="6" class="buchaltung-chart-container"', 'text' => ' ', 'asis' => 1, ); diff --git a/langs/de_DE/buchaltungswidget.lang b/langs/de_DE/buchaltungswidget.lang index 0e56ddb..e107356 100755 --- a/langs/de_DE/buchaltungswidget.lang +++ b/langs/de_DE/buchaltungswidget.lang @@ -45,6 +45,7 @@ MyWidgetDescription = Meine Widget Beschreibung # USt (VAT) Widget # UStUebersicht = Umsatzsteuer-Uebersicht +UStUebersichtHelpText = Zeigt die Umsatzsteuer-Zahllast pro Quartal. Berechnung: Eingenommene USt (Kundenrechnungen) minus gezahlte Vorsteuer (Lieferantenrechnungen). Rot = Zahllast ans Finanzamt, Gruen = Erstattung vom Finanzamt. VATOverview = Umsatzsteuer-Uebersicht VATCollected = Eingenommene USt VATPaid = Gezahlte VSt (Vorsteuer) @@ -62,6 +63,7 @@ VATRefundLegend = Gruen = Erstattung # Gewinn/Verlust Widget # GewinnVerlust = Gewinn / Verlust +GewinnVerlustHelpText = Zeigt den Rohertrag: Einnahmen (Erloeskonten 8xxx) minus Materialkosten (Wareneinsatz Konten 3xxx). Betriebskosten wie Werkzeuge, Fahrzeug, Buero sind NICHT enthalten. Fuer die echte Rentabilitaet inkl. aller Kosten siehe das Rentabilitaets-Widget. IncomeExpenseOverview = Einnahmen / Ausgaben Income = Einnahmen Expenses = Ausgaben @@ -80,10 +82,13 @@ Note = Hinweis # Rentabilitaet Widget # Rentabilitaet = Rentabilitaet +RentabilitaetHelpText = Zeigt die echte Rentabilitaet inkl. ALLER Kosten: Einnahmen (8xxx) minus Wareneinsatz (3xxx) UND Betriebskosten (4xxx wie Werkzeuge, Fahrzeug, Buero, etc.). Die Gewinnmarge zeigt das Verhaeltnis von Gewinn zu Gesamtkosten in Prozent. ProfitabilityAnalysis = Rentabilitaetsanalyse MaterialsPurchased = Eingekaufte Materialien MaterialsPurchasedForCustomers = Eingekaufte Materialien (fuer Kunden) MaterialsServicesInvoiced = In Rechnung gestellt (Leistungen & Material) +AllExpenses = Alle Ausgaben +AllCostsIncluded = Alle Kosten inkl. Betriebsausgaben ProfitMargin = Gewinnmarge GrossProfit = Rohertrag ProfitMarginTrend = Gewinnmarge-Trend