* * 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/gewinn_detail.php * \ingroup buchaltungswidget * \brief Detail page for Profit/Loss 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("GewinnVerlust"); 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 = getIncomeExpenseByMonth($db, $selectedYear); $lastYearData = getIncomeExpenseByMonth($db, $selectedYear - 1); // Main chart - Cumulative profit/loss print '
'; print '
'; print '
'; print '

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

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

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

'; 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'); $totalIncome = 0; $totalExpenses = 0; $cumulative = 0; $cumulativeLast = 0; $labels = array(); $incomeData = array(); $expensesData = array(); $cumulativeData = array(); $cumulativeLastData = array(); $monthlyProfit = array(); foreach ($months as $m => $name) { $income = isset($currentData['income'][$m]) ? $currentData['income'][$m] : 0; $expenses = isset($currentData['customer_expenses'][$m]) ? $currentData['customer_expenses'][$m] : 0; $profit = $income - $expenses; $cumulative += $profit; $incomeLast = isset($lastYearData['income'][$m]) ? $lastYearData['income'][$m] : 0; $expensesLast = isset($lastYearData['customer_expenses'][$m]) ? $lastYearData['customer_expenses'][$m] : 0; $cumulativeLast += ($incomeLast - $expensesLast); $totalIncome += $income; $totalExpenses += $expenses; $colorClass = $profit >= 0 ? 'buchaltung-positive' : 'buchaltung-negative'; $colorCumulative = $cumulative >= 0 ? 'buchaltung-positive' : 'buchaltung-negative'; $colorCumulativeLast = $cumulativeLast >= 0 ? 'buchaltung-positive' : 'buchaltung-negative'; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; // Chart data $labels[] = $monthsShort[$m]; $incomeData[] = round($income, 2); $expensesData[] = round($expenses, 2); $cumulativeData[] = round($cumulative, 2); $cumulativeLastData[] = round($cumulativeLast, 2); $monthlyProfit[] = round($profit, 2); } // Total row $totalProfit = $totalIncome - $totalExpenses; $colorClass = $totalProfit >= 0 ? 'buchaltung-positive' : 'buchaltung-negative'; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print '
'.$langs->trans("Month").''.$langs->trans("Income").''.$langs->trans("CustomerRelatedCosts").''.$langs->trans("ProfitLoss").''.$langs->trans("CumulativeProfit").''.($selectedYear - 1).' '.$langs->trans("CumulativeProfit").'
'.$name.''.price($income, 0, $langs, 1, 2, 2, $conf->currency).''.price($expenses, 0, $langs, 1, 2, 2, $conf->currency).''.price($profit, 0, $langs, 1, 2, 2, $conf->currency).''.price($cumulative, 0, $langs, 1, 2, 2, $conf->currency).''.price($cumulativeLast, 0, $langs, 1, 2, 2, $conf->currency).'
'.$langs->trans("Total").''.price($totalIncome, 0, $langs, 1, 2, 2, $conf->currency).''.price($totalExpenses, 0, $langs, 1, 2, 2, $conf->currency).''.price($totalProfit, 0, $langs, 1, 2, 2, $conf->currency).'
'; print '
'; // Estimated income tax if ($totalProfit > 0) { $estimatedTax = calculateIncomeTax($totalProfit); print '
'; print ''.$langs->trans("EstimatedIncomeTax").': '; print '~'.price($estimatedTax, 0, $langs, 1, 2, 2, $conf->currency).''; print ' ('.$langs->trans("NetAfterTax").': '.price($totalProfit - $estimatedTax, 0, $langs, 1, 2, 2, $conf->currency).')'; print '
'; } // Info box print '
'; print ''.$langs->trans("Note").': '.$langs->trans("CustomerRelatedCostsNote"); print '
'; // Charts JavaScript print ''; llxFooter(); $db->close(); /** * Get income and customer-related expenses by month */ function getIncomeExpenseByMonth($db, $year) { global $conf; $result = array( 'income' => array_fill(1, 12, 0), '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 > 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['income'][$obj->month] = (float) $obj->total; } $db->free($resql); } // Customer-related expenses only (materials for customers) $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 > 0 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 = $db->query($sql); if ($resql) { while ($obj = $db->fetch_object($resql)) { $result['customer_expenses'][$obj->month] = (float) $obj->total; } $db->free($resql); } return $result; } /** * Calculate estimated income tax */ function calculateIncomeTax($profit) { $taxableIncome = max(0, $profit - 11604); if ($taxableIncome <= 0) { return 0; } elseif ($taxableIncome <= 17005) { return $taxableIncome * 0.18; } elseif ($taxableIncome <= 66760) { return $taxableIncome * 0.30; } else { return $taxableIncome * 0.42; } }