* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. */ /** * \file htdocs/custom/buchaltungswidget/rentabilitaet_detail.php * \ingroup buchaltungswidget * \brief Detail page for Profitability analysis with full charts and year selection */ // Load Dolibarr environment $res = 0; if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; } $tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; } if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; } if (!$res && file_exists("../main.inc.php")) { $res = @include "../main.inc.php"; } if (!$res && file_exists("../../main.inc.php")) { $res = @include "../../main.inc.php"; } if (!$res && file_exists("../../../main.inc.php")) { $res = @include "../../../main.inc.php"; } if (!$res) { die("Include of main fails"); } require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; // Load translation files $langs->loadLangs(array("buchaltungswidget@buchaltungswidget", "bills", "compta")); // Access control if (!$user->hasRight('facture', 'lire') && !$user->hasRight('fournisseur', 'facture', 'lire')) { accessforbidden(); } // Get parameters $selectedYear = GETPOST('year', 'int'); if (empty($selectedYear)) { $selectedYear = date('Y'); } $currentYear = date('Y'); $years = range($currentYear - 5, $currentYear + 1); /* * View */ $title = $langs->trans("Rentabilitaet"); llxHeader('', $title, '', '', 0, 0, array('/includes/nnnick/chartjs/dist/Chart.min.js'), array('/buchaltungswidget/css/buchaltungswidget.css')); print load_fiche_titre($title, '', 'accountancy'); // Year selector print '
'; print '
'; print '
'; print ''; print ''; print '
'; print '
'; print '
'; // Get data $currentData = getProfitabilityByMonth($db, $selectedYear); $lastYearData = getProfitabilityByMonth($db, $selectedYear - 1); // Charts print '
'; print '
'; print '
'; print '

'.$langs->trans("ProfitMarginTrend").'

'; print '
'; print ''; print '
'; print '
'; print '
'; print '
'; print '
'; print '

'.$langs->trans("PurchasedVsInvoiced").'

'; print '
'; print ''; print '
'; print '
'; print '
'; print '
'; print '
'; // Data table print '
'; print ''; // Header print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; $months = array(1 => 'Januar', 2 => 'Februar', 3 => 'Maerz', 4 => 'April', 5 => 'Mai', 6 => 'Juni', 7 => 'Juli', 8 => 'August', 9 => 'September', 10 => 'Oktober', 11 => 'November', 12 => 'Dezember'); $monthsShort = array(1 => 'Jan', 2 => 'Feb', 3 => 'Mar', 4 => 'Apr', 5 => 'Mai', 6 => 'Jun', 7 => 'Jul', 8 => 'Aug', 9 => 'Sep', 10 => 'Okt', 11 => 'Nov', 12 => 'Dez'); $totalPurchased = 0; $totalInvoiced = 0; $totalPurchasedLast = 0; $totalInvoicedLast = 0; $labels = array(); $purchasedData = array(); $invoicedData = array(); $marginData = array(); $marginLastData = array(); $marginColors = array(); foreach ($months as $m => $name) { $purchased = isset($currentData['purchased'][$m]) ? $currentData['purchased'][$m] : 0; $invoiced = isset($currentData['invoiced'][$m]) ? $currentData['invoiced'][$m] : 0; $grossProfit = $invoiced - $purchased; $margin = ($purchased > 0) ? (($invoiced - $purchased) / $purchased) * 100 : 0; $purchasedLast = isset($lastYearData['purchased'][$m]) ? $lastYearData['purchased'][$m] : 0; $invoicedLast = isset($lastYearData['invoiced'][$m]) ? $lastYearData['invoiced'][$m] : 0; $marginLast = ($purchasedLast > 0) ? (($invoicedLast - $purchasedLast) / $purchasedLast) * 100 : 0; $totalPurchased += $purchased; $totalInvoiced += $invoiced; $totalPurchasedLast += $purchasedLast; $totalInvoicedLast += $invoicedLast; $colorProfit = $grossProfit >= 0 ? 'buchaltung-positive' : 'buchaltung-negative'; $colorMargin = $margin >= 0 ? 'buchaltung-positive' : 'buchaltung-negative'; $colorMarginLast = $marginLast >= 0 ? 'buchaltung-positive' : 'buchaltung-negative'; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; // Chart data $labels[] = $monthsShort[$m]; $purchasedData[] = round($purchased, 2); $invoicedData[] = round($invoiced, 2); $marginData[] = round($margin, 1); $marginLastData[] = round($marginLast, 1); $marginColors[] = $margin >= 0 ? 'rgba(40, 167, 69, 1)' : 'rgba(220, 53, 69, 1)'; } // Total row $totalGrossProfit = $totalInvoiced - $totalPurchased; $totalMargin = ($totalPurchased > 0) ? (($totalInvoiced - $totalPurchased) / $totalPurchased) * 100 : 0; $totalMarginLast = ($totalPurchasedLast > 0) ? (($totalInvoicedLast - $totalPurchasedLast) / $totalPurchasedLast) * 100 : 0; $colorProfit = $totalGrossProfit >= 0 ? 'buchaltung-positive' : 'buchaltung-negative'; $colorMargin = $totalMargin >= 0 ? 'buchaltung-positive' : 'buchaltung-negative'; $colorMarginLast = $totalMarginLast >= 0 ? 'buchaltung-positive' : 'buchaltung-negative'; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print '
'.$langs->trans("Month").''.$langs->trans("MaterialsPurchasedForCustomers").''.$langs->trans("MaterialsServicesInvoiced").''.$langs->trans("GrossProfit").''.$langs->trans("ProfitMargin").''.($selectedYear - 1).' '.$langs->trans("ProfitMargin").'
'.$name.''.price($purchased, 0, $langs, 1, 2, 2, $conf->currency).''.price($invoiced, 0, $langs, 1, 2, 2, $conf->currency).''.price($grossProfit, 0, $langs, 1, 2, 2, $conf->currency).''.number_format($margin, 1, ',', '.').' %'.number_format($marginLast, 1, ',', '.').' %
'.$langs->trans("Total").''.price($totalPurchased, 0, $langs, 1, 2, 2, $conf->currency).''.price($totalInvoiced, 0, $langs, 1, 2, 2, $conf->currency).''.price($totalGrossProfit, 0, $langs, 1, 2, 2, $conf->currency).''.number_format($totalMargin, 1, ',', '.').' %'.number_format($totalMarginLast, 1, ',', '.').' %
'; print '
'; // Productivity rating $rating = getProductivityRating($totalMargin, $langs); print '
'; print '

'.$langs->trans("ProductivityRating").': '.$rating['text'].'

'; print '

'.$rating['description'].'

'; print '
'; print ''.$langs->trans("Critical").''; print ''.$langs->trans("Low").''; print ''.$langs->trans("Average").''; print ''.$langs->trans("Good").''; print ''.$langs->trans("Excellent").''; print '
'; print '
'; print '
'; // Info box print '
'; print ''.$langs->trans("Note").': '.$langs->trans("OnlyCustomerMaterialsNote"); print '
'; // Charts JavaScript print ''; llxFooter(); $db->close(); /** * Get profitability data by month */ function getProfitabilityByMonth($db, $year) { global $conf; $result = array( 'purchased' => array_fill(1, 12, 0), 'invoiced' => array_fill(1, 12, 0), ); // Materials purchased FOR CUSTOMERS 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 .= " INNER JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = fd.fk_product"; $sql .= " WHERE f.fk_statut > 0 AND f.entity = ".((int) $conf->entity); $sql .= " AND YEAR(f.datef) = ".((int) $year); $sql .= " AND p.fk_product_type = 0"; $sql .= " AND (p.tobuy = 1 OR p.tosell = 1)"; $sql .= " GROUP BY MONTH(f.datef)"; $resql = $db->query($sql); if ($resql) { while ($obj = $db->fetch_object($resql)) { $result['purchased'][$obj->month] = (float) $obj->total; } $db->free($resql); } // All 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 > 0 AND f.entity = ".((int) $conf->entity); $sql .= " AND YEAR(f.datef) = ".((int) $year); $sql .= " GROUP BY MONTH(f.datef)"; $resql = $db->query($sql); if ($resql) { while ($obj = $db->fetch_object($resql)) { $result['invoiced'][$obj->month] = (float) $obj->total; } $db->free($resql); } return $result; } /** * Get productivity rating */ function getProductivityRating($marginPercent, $langs) { if ($marginPercent >= 100) { return array( 'class' => 'rating-excellent', 'text' => $langs->trans("Excellent"), 'description' => $langs->trans("RatingExcellentDesc"), ); } elseif ($marginPercent >= 50) { return array( 'class' => 'rating-good', 'text' => $langs->trans("Good"), 'description' => $langs->trans("RatingGoodDesc"), ); } elseif ($marginPercent >= 20) { return array( 'class' => 'rating-average', 'text' => $langs->trans("Average"), 'description' => $langs->trans("RatingAverageDesc"), ); } elseif ($marginPercent >= 0) { return array( 'class' => 'rating-low', 'text' => $langs->trans("Low"), 'description' => $langs->trans("RatingLowDesc"), ); } else { return array( 'class' => 'rating-critical', 'text' => $langs->trans("Critical"), 'description' => $langs->trans("RatingCriticalDesc"), ); } }