dolibarr 24.0.0-beta
result.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2016-2017 Jamal Elbaz <jamelbaz@gmail.com>
3 * Copyright (C) 2016-2022 Alexandre Spangaro <aspangaro@open-dsi.fr>
4 * Copyright (C) 2018-2020 Laurent Destailleur <eldy@destailleur.fr>
5 * Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
6 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
28// Load Dolibarr environment
29require '../../main.inc.php';
30require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
31require_once DOL_DOCUMENT_ROOT.'/core/lib/report.lib.php';
32require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
33require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
34require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancycategory.class.php';
35require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancyreport.class.php';
36
46// Load translation files required by the page
47$langs->loadLangs(array('compta', 'bills', 'donation', 'salaries', 'accountancy'));
48
49$id_report = GETPOSTINT('id_report');
50if ($id_report <= 0) {
51 $id_report = 1;
52}
53
54$error = 0;
55
56$mesg = '';
57$action = GETPOST('action', 'aZ09');
58$cat_id = GETPOST('account_category');
59$selectcpt = GETPOST('cpt_bk');
60$id = GETPOSTINT('id');
61$rowid = GETPOSTINT('rowid');
62$cancel = GETPOST('cancel', 'alpha');
63$showaccountdetail = GETPOST('showaccountdetail', 'aZ09') ? GETPOST('showaccountdetail', 'aZ09') : 'no';
64
65
66$date_startmonth = GETPOSTINT('date_startmonth');
67$date_startday = GETPOSTINT('date_startday');
68$date_startyear = GETPOSTINT('date_startyear');
69$date_endmonth = GETPOSTINT('date_endmonth');
70$date_endday = GETPOSTINT('date_endday');
71$date_endyear = GETPOSTINT('date_endyear');
72
73$nbofyear = 1;
74
75// Change this to test different cases of setup
76//$conf->global->SOCIETE_FISCAL_MONTH_START = 7;
77
78// Date range
79$year = GETPOSTINT('year'); // year with current month, is the month of the period we must show
80if (empty($year)) {
81 $year_current = (int) dol_print_date(dol_now('gmt'), "%Y", 'gmt');
82 $month_current = (int) dol_print_date(dol_now(), "%m");
83 $year_start = $year_current - ($nbofyear - 1);
84} else {
85 $year_current = $year;
86 $month_current = (int) dol_print_date(dol_now(), "%m");
87 $year_start = $year - ($nbofyear - 1);
88}
89$date_start = dol_mktime(0, 0, 0, $date_startmonth, $date_startday, $date_startyear);
90$date_end = dol_mktime(23, 59, 59, $date_endmonth, $date_endday, $date_endyear);
91
92// We define date_start and date_end
93if (empty($date_start) || empty($date_end)) { // We define date_start and date_end
94 $q = GETPOSTINT("q") ? GETPOSTINT("q") : 0;
95 if ($q == 0) {
96 // We define date_start and date_end
97 $year_end = $year_start + ($nbofyear - 1);
98 $month_start = GETPOSTINT("month") ? GETPOSTINT("month") : getDolGlobalInt('SOCIETE_FISCAL_MONTH_START', 1);
99 $date_startmonth = $month_start;
100 if (!GETPOST('month')) {
101 if (!$year && $month_start > $month_current) {
102 $year_start--;
103 $year_end--;
104 }
105 $month_end = $month_start - 1;
106 if ($month_end < 1) {
107 $month_end = 12;
108 } else {
109 $year_end++;
110 }
111 } else {
112 $month_end = $month_start;
113 }
114 $date_start = dol_get_first_day($year_start, $month_start, false);
115 $date_end = dol_get_last_day($year_end, $month_end, false);
116 }
117 if ($q == 1) {
118 $date_start = dol_get_first_day($year_start, 1, false);
119 $date_end = dol_get_last_day($year_start, 3, false);
120 }
121 if ($q == 2) {
122 $date_start = dol_get_first_day($year_start, 4, false);
123 $date_end = dol_get_last_day($year_start, 6, false);
124 }
125 if ($q == 3) {
126 $date_start = dol_get_first_day($year_start, 7, false);
127 $date_end = dol_get_last_day($year_start, 9, false);
128 }
129 if ($q == 4) {
130 $date_start = dol_get_first_day($year_start, 10, false);
131 $date_end = dol_get_last_day($year_start, 12, false);
132 }
133}
134
135if (($date_start < dol_time_plus_duree($date_end, -1, 'y')) || ($date_start > $date_end)) {
136 $date_end = dol_time_plus_duree($date_start - 1, 1, 'y');
137}
138
139// $date_start and $date_end are defined. We force $start_year and $nbofyear
140$tmps = dol_getdate($date_start);
141$start_year = $tmps['year'];
142$start_month = $tmps['mon'];
143$tmpe = dol_getdate($date_end);
144$year_end = $tmpe['year'];
145$month_end = $tmpe['mon'];
146$nbofyear = ($year_end - $start_year) + 1;
147
148$date_startmonth = $start_month;
149$date_endmonth = $month_end;
150
151$date_start_previous = dol_time_plus_duree($date_start, -1, 'y');
152$date_end_previous = dol_time_plus_duree($date_end, -1, 'y');
153
154//var_dump($date_start." ".$date_end." ".$date_start_previous." ".$date_end_previous." ".$nbofyear);
155
156
157if ($cat_id == 0) {
158 $cat_id = null;
159}
160
161// Define modecompta ('CREANCES-DETTES' or 'RECETTES-DEPENSES' or 'BOOKKEEPING')
162$modecompta = getDolGlobalString('ACCOUNTING_MODE');
163if (isModEnabled('accounting')) {
164 $modecompta = 'BOOKKEEPING';
165}
166if (GETPOST("modecompta", 'alpha')) {
167 $modecompta = GETPOST("modecompta", 'alpha');
168}
169
170$AccCat = new AccountancyCategory($db);
171
172// Security check
173$socid = GETPOSTINT('socid');
174if ($user->socid > 0) {
175 $socid = $user->socid;
176}
177$hookmanager->initHooks(['resultreportlist']);
178if (isModEnabled('comptabilite')) {
179 $result = restrictedArea($user, 'compta', '', '', 'resultat');
180}
181if (isModEnabled('accounting')) {
182 $result = restrictedArea($user, 'accounting', '', '', 'comptarapport');
183}
184
185/*
186 * View
187 */
188
189$months = array(
190 $langs->trans("MonthShort01"),
191 $langs->trans("MonthShort02"),
192 $langs->trans("MonthShort03"),
193 $langs->trans("MonthShort04"),
194 $langs->trans("MonthShort05"),
195 $langs->trans("MonthShort06"),
196 $langs->trans("MonthShort07"),
197 $langs->trans("MonthShort08"),
198 $langs->trans("MonthShort09"),
199 $langs->trans("MonthShort10"),
200 $langs->trans("MonthShort11"),
201 $langs->trans("MonthShort12"),
202);
203
204llxHeader('', $langs->trans('ReportInOut'));
205
206$builddate = 0;
207$name = '';
208$period = '';
209$calcmode = 0;
210$description = '';
211
212$form = new Form($db);
213
214$textprevyear = '<a href="'.$_SERVER["PHP_SELF"].'?year='.($start_year - 1).'&showaccountdetail='.urlencode($showaccountdetail).'">'.img_previous().'</a>';
215$textnextyear = ' &nbsp; <a href="'.$_SERVER["PHP_SELF"].'?year='.($start_year + 1).'&showaccountdetail='.urlencode($showaccountdetail).'">'.img_next().'</a>';
216
217
218// Affiche en-tete de rapport
219if ($modecompta == "CREANCES-DETTES") {
220 $name = $langs->trans("AnnualByAccountDueDebtMode");
221 $calcmode = $langs->trans("CalcModeDebt");
222 $calcmode .= '<br>('.$langs->trans("SeeReportInInputOutputMode", '<a href="'.$_SERVER["PHP_SELF"].'?year='.$start_year.(GETPOST("month") > 0 ? '&month='.GETPOST("month") : '').'&modecompta=RECETTES-DEPENSES">', '</a>').')';
223 if (isModEnabled('accounting')) {
224 $calcmode .= '<br>('.$langs->trans("SeeReportInBookkeepingMode", '<a href="'.$_SERVER["PHP_SELF"].'?year='.$start_year.'&modecompta=BOOKKEEPING">', '</a>').')';
225 }
226 $period = $form->selectDate($date_start, 'date_start', 0, 0, 0, '', 1, 0).' - '.$form->selectDate($date_end, 'date_end', 0, 0, 0, '', 1, 0);
227 //$periodlink='<a href="'.$_SERVER["PHP_SELF"].'?year='.($year-1).'&modecompta='.$modecompta.'">'.img_previous().'</a> <a href="'.$_SERVER["PHP_SELF"].'?year='.($year+1).'&modecompta='.$modecompta.'">'.img_next().'</a>';
228 $description = $langs->trans("RulesResultDue");
229 if (getDolGlobalString('FACTURE_DEPOSITS_ARE_JUST_PAYMENTS')) {
230 $description .= $langs->trans("DepositsAreNotIncluded");
231 } else {
232 $description .= $langs->trans("DepositsAreIncluded");
233 }
234 if (getDolGlobalString('FACTURE_SUPPLIER_DEPOSITS_ARE_JUST_PAYMENTS')) {
235 $description .= $langs->trans("SupplierDepositsAreNotIncluded");
236 }
237 $builddate = dol_now();
238 //$exportlink=$langs->trans("NotYetAvailable");
239} elseif ($modecompta == "RECETTES-DEPENSES") {
240 $name = $langs->trans("AnnualByAccountInputOutputMode");
241 $calcmode = $langs->trans("CalcModePayment");
242 $calcmode .= '<br>('.$langs->trans("SeeReportInDueDebtMode", '<a href="'.$_SERVER["PHP_SELF"].'?year='.$year.(GETPOST("month") > 0 ? '&month='.GETPOST("month") : '').'&modecompta=CREANCES-DETTES">', '</a>').')';
243 if (isModEnabled('accounting')) {
244 $calcmode .= '<br>('.$langs->trans("SeeReportInBookkeepingMode", '<a href="'.$_SERVER["PHP_SELF"].'?year='.$year.'&modecompta=BOOKKEEPING">', '</a>').')';
245 }
246 $period = $form->selectDate($date_start, 'date_start', 0, 0, 0, '', 1, 0).' - '.$form->selectDate($date_end, 'date_end', 0, 0, 0, '', 1, 0);
247 //$periodlink='<a href="'.$_SERVER["PHP_SELF"].'?year='.($year-1).'&modecompta='.$modecompta.'">'.img_previous().'</a> <a href="'.$_SERVER["PHP_SELF"].'?year='.($year+1).'&modecompta='.$modecompta.'">'.img_next().'</a>';
248 $description = $langs->trans("RulesResultInOut");
249 $builddate = dol_now();
250 //$exportlink=$langs->trans("NotYetAvailable");
251} elseif ($modecompta == "BOOKKEEPING") {
252 $accountingreportstatic = new AccountancyReport($db);
253 $accountingreportstatic->fetch($id_report);
254 $reportLabel = '';
255 $reportLabel = $accountingreportstatic->label;
256
257 $name = $langs->trans("ReportInOut").', '.$langs->trans("ByPersonalizedAccountGroups").' '.$reportLabel;
258 $calcmode = $langs->trans("CalcModeBookkeeping");
259 //$calcmode.='<br>('.$langs->trans("SeeReportInDueDebtMode",'<a href="'.$_SERVER["PHP_SELF"].'?year_start='.$year_start.'&modecompta=CREANCES-DETTES">','</a>').')';
260 //$calcmode.='<br>('.$langs->trans("SeeReportInInputOutputMode",'<a href="'.$_SERVER["PHP_SELF"].'?year_start='.$year_start.'&modecompta=RECETTES-DEPENSES">','</a>').')';
261 $period = $form->selectDate($date_start, 'date_start', 0, 0, 0, '', 1, 0).' - '.$form->selectDate($date_end, 'date_end', 0, 0, 0, '', 1, 0);
262 $arraylist = array('no' => $langs->trans("None"), 'yes' => $langs->trans("AccountWithNonZeroValues"), 'all' => $langs->trans("All"));
263 $period .= ' &nbsp; &nbsp; <span class="opacitymedium">'.$langs->trans("DetailBy").'</span> '.$form->selectarray('showaccountdetail', $arraylist, $showaccountdetail, 0);
264 $periodlink = $textprevyear.$textnextyear;
265 $exportlink = '';
266 $description = $langs->trans("RulesResultBookkeepingPersonalized");
267 $description .= ' ('.$langs->trans("SeePageForSetup", DOL_URL_ROOT.'/accountancy/admin/categories_list.php?search_country_id='.$mysoc->country_id.'&mainmenu=accountancy&leftmenu=accountancy_admin', $langs->transnoentitiesnoconv("Accountancy").' / '.$langs->transnoentitiesnoconv("Setup").' / '.$langs->transnoentitiesnoconv("AccountingCategory")).')';
268 $builddate = dol_now();
269}
270
271report_header($name, '', $period, $periodlink ?? '', $description, $builddate, $exportlink ?? '', array('modecompta' => $modecompta, 'action' => ''), $calcmode);
272
273
274if (isModEnabled('accounting') && $modecompta != 'BOOKKEEPING') {
275 print info_admin($langs->trans("WarningReportNotReliable"), 0, 0, '1');
276}
277
278
279$moreforfilter = '';
280
281print '<div class="div-table-responsive">';
282print '<table class="tagtable liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
283
284print '<tr class="liste_titre">';
285print '<th class="liste_titre">'.$langs->trans("AccountingCategory").'</th>';
286print '<th class="liste_titre"></th>';
287print '<th class="liste_titre right">'.$langs->trans("PreviousPeriod").'</th>';
288print '<th class="liste_titre right">'.$langs->trans("SelectedPeriod").'</th>';
289foreach ($months as $k => $v) {
290 if (($k + 1) >= $date_startmonth && (($date_startmonth <= $date_endmonth && ($k + 1) <= $date_endmonth) || ($date_startmonth > $date_endmonth))) {
291 print '<th class="liste_titre right width50">'.$langs->trans('MonthShort'.sprintf("%02d", ($k + 1))).'</th>';
292 }
293}
294if ($date_startmonth > $date_endmonth) {
295 foreach ($months as $k => $v) {
296 if (($k + 1) < $date_startmonth && ($k + 1) <= $date_endmonth) {
297 print '<th class="liste_titre right width50">'.$langs->trans('MonthShort'.sprintf("%02d", ($k + 1))).'</th>';
298 }
299 }
300}
301print '</tr>';
302
303if ($modecompta == 'CREANCES-DETTES') {
304 //if (!empty($date_start) && !empty($date_end))
305 // $sql.= " AND f.datef >= '".$db->idate($date_start)."' AND f.datef <= '".$db->idate($date_end)."'";
306} elseif ($modecompta == "RECETTES-DEPENSES") {
307 //if (!empty($date_start) && !empty($date_end))
308 // $sql.= " AND p.datep >= '".$db->idate($date_start)."' AND p.datep <= '".$db->idate($date_end)."'";
309} elseif ($modecompta == "BOOKKEEPING") {
310 // Get array of all report groups that are active
311 $cats = $AccCat->getCats(-1, 1, $id_report); // WARNING: Computed groups must be after group they include
312 $unactive_cats = $AccCat->getCats(-1, 0, $id_report);
313
314 /*
315 $sql = 'SELECT DISTINCT t.numero_compte as nb FROM '.MAIN_DB_PREFIX.'accounting_bookkeeping as t, '.MAIN_DB_PREFIX.'accounting_account as aa';
316 $sql.= " WHERE t.numero_compte = aa.account_number AND aa.fk_accounting_category = 0";
317 if (!empty($date_start) && !empty($date_end))
318 $sql.= " AND t.doc_date >= '".$db->idate($date_start)."' AND t.doc_date <= '".$db->idate($date_end)."'";
319 if (!empty($month)) {
320 $sql .= " AND MONTH(t.doc_date) = " . ((int) $month);
321 }
322 $resql = $db->query($sql);
323 if ($resql)
324 {
325 $num_rows = $db->num_rows($resql);
326 if ($num_rows) {
327
328 print '<div class="warning">Warning: There is '.$num_rows.' accounts in your ledger table that are not set into a reporting group</div>';
329 $i = 0;
330 //while ($i < $num) {
331 // $obj = $db->fetch_object($resql);
332 // $i++;
333 //}
334 }
335 }
336 else dol_print_error($db);
337 */
338
339 $j = 1;
340 $sommes = array();
341 $totPerAccount = array();
342 if (!is_array($cats) && $cats < 0) {
343 setEventMessages(null, $AccCat->errors, 'errors');
344 } elseif (is_array($cats) && count($cats) == 0) {
345 print '<tr class="liste_total">';
346 print '<td colspan="15">';
347 print '<span class="opacitymedium">';
348 print $langs->trans("ErrorNoAccountingCategoryForThisCountry", $mysoc->country_code, $langs->transnoentitiesnoconv("Accountancy"), $langs->transnoentitiesnoconv("Setup"), $langs->transnoentitiesnoconv("AccountingCategory"));
349 print '</span>';
350 print '</td>';
351 print '</tr>';
352 } elseif (is_array($cats) && count($cats) > 0) {
353 // Loop on each custom group of accounts
354 foreach ($cats as $cat) {
355 if (!empty($cat['category_type'])) {
356 // category calculated
357 // When we enter here, $sommes was filled by group of accounts
358
359 $formula = $cat['formula'];
360
361 print '<tr class="liste_total">';
362
363 // Code and Label
364 print '<td class="liste_total tdoverflowmax100" title="'.dol_escape_htmltag($cat['code']).'">';
365 print dol_escape_htmltag($cat['code']);
366 print '</td><td class="tdoverflowmax250 borderright" title="'.dol_escape_htmltag($cat['label']).'">';
367 print dol_escape_htmltag($cat['label']);
368 print '</td>';
369
370 $vars = array();
371
372 // Unactive categories have a total of 0 to be used in the formula.
373 foreach ($unactive_cats as $un_cat) {
374 $vars[$un_cat['code']] = 0;
375 }
376
377 $code = null;
378
379 // Previous Fiscal year (N-1)
380 foreach ($sommes as $code_idx => $det) {
381 $code = $code_idx;
382 $vars[$code_idx] = empty($det['NP']) ? 0 : $det['NP'];
383 }
384
385 $result = strtr($formula, $vars);
386 $result = str_replace('--', '+', $result);
387
388 if (preg_match('/[a-z]/i', $result)) {
389 $r = 'Error bad formula: '.$result;
390 $rshort = 'Err';
391 print '<td class="liste_total right"><span class="amount" title="'.dol_escape_htmltag($r).'">'.$rshort.'</span></td>';
392 } else {
393 //var_dump($result);
394 //$r = $AccCat->calculate($result);
395 $r = (float) dol_eval((string) $result, 1, 1, '1');
396
397 if (getDolGlobalInt('ACCOUNTANCY_TRUNC_DECIMAL_ON_BALANCE_REPORT')) {
398 print '<td class="liste_total right"><span class="amount">'.price($r, 0, '', 1, 0, 0).'</span></td>';
399 } else {
400 print '<td class="liste_total right"><span class="amount">'.price($r).'</span></td>';
401 }
402 }
403
404 if ($code !== null && !isset($sommes[$code])) {
405 $sommes[$code] = array();
406 }
407 // Year N
408 $code = $cat['code']; // code of categorie ('VTE', 'MAR', ...)
409 if (empty($sommes[$code]['NP'])) {
410 $sommes[$code]['NP'] = $r;
411 } else {
412 $sommes[$code]['NP'] += $r;
413 }
414
415 // Current fiscal year (N)
416 if (!empty($sommes)) {
417 foreach ($sommes as $code_idx => $det) {
418 $code = $code_idx;
419 $vars[$code_idx] = empty($det['N']) ? 0 : $det['N'];
420 }
421 }
422
423 $result = strtr($formula, $vars);
424 $result = str_replace('--', '+', $result);
425
426 //$r = $AccCat->calculate($result);
427 $r = (float) dol_eval((string) $result, 1, 1, '1');
428
429 if (getDolGlobalInt('ACCOUNTANCY_TRUNC_DECIMAL_ON_BALANCE_REPORT')) {
430 print '<td class="liste_total right borderright"><span class="amount">'.price($r, 0, '', 1, 0, 0).'</span></td>';
431 } else {
432 print '<td class="liste_total right borderright"><span class="amount">'.price($r).'</span></td>';
433 }
434 if (empty($sommes[$code]['N'])) {
435 $sommes[$code]['N'] = $r;
436 } else {
437 $sommes[$code]['N'] += $r;
438 }
439
440 // Detail by month
441 foreach ($months as $k => $v) {
442 if (($k + 1) >= $date_startmonth && (($date_startmonth <= $date_endmonth && ($k + 1) <= $date_endmonth) || ($date_startmonth > $date_endmonth))) {
443 foreach ($sommes as $code_idx => $det) {
444 $code = $code_idx;
445 $vars[$code_idx] = empty($det['M'][$k]) ? 0 : $det['M'][$k];
446 }
447 $result = strtr($formula, $vars);
448 $result = str_replace('--', '+', $result);
449
450 //$r = $AccCat->calculate($result);
451 $r = (float) dol_eval((string) $result, 1, 1, '1');
452
453
454 if (getDolGlobalInt('ACCOUNTANCY_TRUNC_DECIMAL_ON_BALANCE_REPORT')) {
455 print '<td class="liste_total right"><span class="amount">'.price($r, 0, '', 1, 0, 0).'</span></td>';
456 } else {
457 print '<td class="liste_total right"><span class="amount">'.price($r).'</span></td>';
458 }
459 if (empty($sommes[$code]['M'][$k])) {
460 $sommes[$code]['M'][$k] = $r;
461 } else {
462 $sommes[$code]['M'][$k] += $r;
463 }
464 }
465 }
466
467 if ($date_startmonth > $date_endmonth) {
468 foreach ($months as $k => $v) {
469 if (($k + 1) < $date_startmonth && ($k + 1) <= $date_endmonth) {
470 foreach ($sommes as $code_idx => $det) {
471 $code = $code_idx;
472 $vars[$code_idx] = empty($det['M'][$k]) ? 0 : $det['M'][$k];
473 }
474 $result = strtr($formula, $vars);
475 $result = str_replace('--', '+', $result);
476
477 //$r = $AccCat->calculate($result);
478 $r = (float) dol_eval((string) $result, 1, 1, '1');
479
480 if (getDolGlobalInt('ACCOUNTANCY_TRUNC_DECIMAL_ON_BALANCE_REPORT')) {
481 print '<td class="liste_total right"><span class="amount">'.price($r, 0, '', 1, 0, 0).'</span></td>';
482 } else {
483 print '<td class="liste_total right"><span class="amount">'.price($r).'</span></td>';
484 }
485 if (empty($sommes[$code]['M'][$k])) {
486 $sommes[$code]['M'][$k] = $r;
487 } else {
488 $sommes[$code]['M'][$k] += $r;
489 }
490 }
491 }
492 }
493
494 print "</tr>\n";
495
496 //var_dump($sommes);
497 } else { // normal category
498 $code = $cat['code']; // Category code we process
499
500 $totCat = array();
501 $totCat['NP'] = 0;
502 $totCat['N'] = 0;
503 $totCat['M'] = array();
504 foreach ($months as $k => $v) {
505 $totCat['M'][$k] = 0;
506 }
507 if (!isset($sommes[$code])) {
508 $sommes[$code] = array();
509 }
510
511 // Set $cpts with array of accounts in the category/group
512 $cpts = $AccCat->getCptsCat((int) $cat['rowid']);
513 // We should loop over empty $cpts array, else the category _code_ is used in the formula, which leads to wrong result if the code is a number.
514 if (empty($cpts)) {
515 $cpts[] = array();
516 }
517
518 $arrayofaccountforfilter = array();
519 foreach ($cpts as $i => $cpt) { // Loop on each account.
520 if (isset($cpt['account_number'])) {
521 $arrayofaccountforfilter[] = $cpt['account_number'];
522 }
523 }
524
525 // N-1
526 if (!empty($arrayofaccountforfilter)) {
527 $return = $AccCat->getSumDebitCredit($arrayofaccountforfilter, $date_start_previous, $date_end_previous, empty($cat['dc']) ? 0 : $cat['dc']);
528 if ($return < 0) {
529 setEventMessages(null, $AccCat->errors, 'errors');
530 $resultNP = 0;
531 } else {
532 foreach ($cpts as $i => $cpt) { // Loop on each account found
533 $resultNP = empty($AccCat->sdcperaccount[$cpt['account_number']]) ? 0 : $AccCat->sdcperaccount[$cpt['account_number']];
534
535 if (empty($totCat['NP'])) {
536 $totCat['NP'] = $resultNP;
537 } else {
538 $totCat['NP'] += $resultNP;
539 }
540 if (empty($sommes[$code]['NP'])) {
541 $sommes[$code]['NP'] = $resultNP;
542 } else {
543 $sommes[$code]['NP'] += $resultNP;
544 }
545 $totPerAccount[$cpt['account_number']]['NP'] = $resultNP;
546 }
547 }
548 }
549
550 // Set value into column N and month M ($totCat)
551 // This make 12 calls for each accountancy account (12 months M)
552 foreach ($cpts as $i => $cpt) { // Loop on each account.
553 // We make 1 loop for each account because we may want detail per account.
554 // @todo Optimize to ask a 'group by' account and a filter with account in (..., ...) in request
555
556 // Each month
557 $resultN = 0;
558 foreach ($months as $k => $v) {
559 $monthtoprocess = $k + 1; // ($k+1) is month 1, 2, ..., 12
560 $yeartoprocess = $start_year;
561 if (($k + 1) < $start_month) {
562 $yeartoprocess++;
563 }
564
565 if (($yeartoprocess == $start_year && ($k + 1) >= $date_startmonth && $k < $date_endmonth) ||
566 ($yeartoprocess == $start_year + 1 && ($k + 1) < $date_startmonth)
567 ) {
568 //var_dump($monthtoprocess.'_'.$yeartoprocess);
569 if (isset($cpt['account_number'])) {
570 $return = $AccCat->getSumDebitCredit((int) $cpt['account_number'], $date_start, $date_end, empty($cat['dc']) ? 0 : $cat['dc'], 'nofilter', $monthtoprocess, $yeartoprocess);
571 if ($return < 0) {
572 setEventMessages(null, $AccCat->errors, 'errors');
573 $resultM = 0;
574 } else {
575 $resultM = $AccCat->sdc;
576 }
577 } else {
578 $resultM = 0;
579 }
580 if (empty($totCat['M'][$k])) {
581 $totCat['M'][$k] = $resultM;
582 } else {
583 $totCat['M'][$k] += $resultM;
584 }
585 if (empty($sommes[$code]['M'][$k])) {
586 $sommes[$code]['M'][$k] = $resultM;
587 } else {
588 $sommes[$code]['M'][$k] += $resultM;
589 }
590 if (isset($cpt['account_number'])) {
591 $totPerAccount[$cpt['account_number']]['M'][$k] = $resultM;
592 }
593
594 $resultN += $resultM;
595 }
596 }
597
598 if (empty($totCat)) {
599 $totCat['N'] = $resultN;
600 } else {
601 $totCat['N'] += $resultN;
602 }
603 if (empty($sommes[$code]['N'])) {
604 $sommes[$code]['N'] = $resultN;
605 } else {
606 $sommes[$code]['N'] += $resultN;
607 }
608 if (isset($cpt['account_number'])) {
609 $totPerAccount[$cpt['account_number']]['N'] = $resultN;
610 }
611 }
612
613
614 // Now output columns for row $code ('VTE', 'MAR', ...)
615
616 print '<tr'.($showaccountdetail != 'no' ? ' class="trforbreak"' : '').'>';
617
618 // Column group
619 print '<td class="tdoverflowmax100" title="'.dol_escape_htmltag($cat['code']).'">';
620 print dol_escape_htmltag($cat['code']);
621 print '</td>';
622
623 // Label of group
624 $labeltoshow = dol_escape_htmltag($cat['label']);
625 if (count($cpts) > 0 && !empty($cpts[0])) { // Show example of 5 first accounting accounts
626 $i = 0;
627 foreach ($cpts as $cpt) {
628 if ($i > 5) {
629 $labeltoshow .= '...)';
630 break;
631 }
632 if ($i > 0) {
633 $labeltoshow .= ', ';
634 } else {
635 $labeltoshow .= ' (';
636 }
637 $labeltoshow .= dol_escape_htmltag($cpt['account_number']);
638 $i++;
639 }
640 if ($i <= 5) {
641 $labeltoshow .= ')';
642 }
643 } else {
644 $labeltoshow .= ' - <span class="warning">'.$langs->trans("GroupIsEmptyCheckSetup").'</span>';
645 }
646 print '<td class="tdoverflowmax250 borderright" title="'.dol_escape_htmltag(dol_string_nohtmltag($labeltoshow)).'">';
647 print $labeltoshow;
648 print '</td>';
649
650 if (getDolGlobalInt('ACCOUNTANCY_TRUNC_DECIMAL_ON_BALANCE_REPORT')) {
651 print '<td class="right"><span class="amount">'.price($totCat['NP'], 0, '', 1, 0, 0).'</span></td>';
652 print '<td class="right borderright"><span class="amount">'.price($totCat['N'], 0, '', 1, 0, 0).'</span></td>';
653 } else {
654 print '<td class="right"><span class="amount">'.price($totCat['NP']).'</span></td>';
655 print '<td class="right borderright"><span class="amount">'.price($totCat['N']).'</span></td>';
656 }
657
658 // Each month
659 foreach ($totCat['M'] as $k => $v) {
660 if (($k + 1) >= $date_startmonth && (($date_startmonth <= $date_endmonth && ($k + 1) <= $date_endmonth) || ($date_startmonth > $date_endmonth))) {
661 if (getDolGlobalInt('ACCOUNTANCY_TRUNC_DECIMAL_ON_BALANCE_REPORT')) {
662 print '<td class="right nowraponall"><span class="amount">'.price($v, 0, '', 1, 0, 0).'</span></td>';
663 } else {
664 print '<td class="right nowraponall"><span class="amount">'.price($v).'</span></td>';
665 }
666 }
667 }
668 if ($date_startmonth > $date_endmonth) {
669 foreach ($totCat['M'] as $k => $v) {
670 if (($k + 1) < $date_startmonth && ($k + 1) <= $date_endmonth) {
671 if (getDolGlobalInt('ACCOUNTANCY_TRUNC_DECIMAL_ON_BALANCE_REPORT')) {
672 print '<td class="right nowraponall"><span class="amount">'.price($v, 0, '', 1, 0, 0).'</span></td>';
673 } else {
674 print '<td class="right nowraponall"><span class="amount">'.price($v).'</span></td>';
675 }
676 }
677 }
678 }
679
680 print "</tr>\n";
681
682 // Loop on detail of all accounts to output the detail
683 if ($showaccountdetail != 'no') {
684 foreach ($cpts as $i => $cpt) {
685 if (isset($cpt['account_number'])) {
686 $resultNP = $totPerAccount[$cpt['account_number']]['NP'];
687 $resultN = $totPerAccount[$cpt['account_number']]['N'];
688 } else {
689 $resultNP = 0;
690 $resultN = 0;
691 }
692
693 if ($showaccountdetail == 'all' || $resultN != 0) {
694 print '<tr>';
695 print '<td></td>';
696
697 if (isset($cpt['account_number'])) {
698 $labeldetail = ' &nbsp; &nbsp; '.length_accountg($cpt['account_number']).' - '.$cpt['account_label'];
699 } else {
700 $labeldetail = '-';
701 }
702
703 print '<td class="tdoverflowmax250 borderright" title="'.dol_escape_htmltag($labeldetail).'">';
704 print dol_escape_htmltag($labeldetail);
705 print '</td>';
706 if (getDolGlobalInt('ACCOUNTANCY_TRUNC_DECIMAL_ON_BALANCE_REPORT')) {
707 print '<td class="right"><span class="amount">'.price($resultNP, 0, '', 1, 0, 0).'</span></td>';
708 print '<td class="right borderright"><span class="amount">'.price($resultN, 0, '', 1, 0, 0).'</span></td>';
709 } else {
710 print '<td class="right"><span class="amount">'.price($resultNP).'</span></td>';
711 print '<td class="right borderright"><span class="amount">'.price($resultN).'</span></td>';
712 }
713
714 // Make one call for each month
715 foreach ($months as $k => $v) {
716 if (($k + 1) >= $date_startmonth && (($date_startmonth <= $date_endmonth && ($k + 1) <= $date_endmonth) || ($date_startmonth > $date_endmonth))) {
717 if (isset($cpt['account_number'])) {
718 $resultM = $totPerAccount[$cpt['account_number']]['M'][$k];
719 } else {
720 $resultM = 0;
721 }
722 print '<td class="right"><span class="amount">'.price($resultM).'</span></td>';
723 }
724 }
725 if ($date_startmonth > $date_endmonth) {
726 foreach ($months as $k => $v) {
727 if (($k + 1) < $date_startmonth && ($k + 1) <= $date_endmonth) {
728 if (isset($cpt['account_number'])) {
729 $resultM = empty($totPerAccount[$cpt['account_number']]['M'][$k]) ? 0 : $totPerAccount[$cpt['account_number']]['M'][$k];
730 } else {
731 $resultM = 0;
732 }
733 print '<td class="right"><span class="amount">'.price($resultM).'</span></td>';
734 }
735 }
736 }
737 print "</tr>\n";
738 }
739 }
740 }
741 }
742 }
743 }
744}
745
746print "</table>";
747print '</div>';
748
749// End of page
750llxFooter();
751$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to manage categories of an accounting account.
Class to manage reports for accounting categories.
Class to manage generation of HTML components Only common components must be here.
global $mysoc
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition date.lib.php:604
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:126
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:623
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
$date_start
Variables from include:
dol_now($mode='gmt')
Return date for now.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='', $textonpictotooltip='')
Show information in HTML for admin users or standard users.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
dol_eval($s, $returnvalue=1, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
img_previous($titlealt='default', $moreatt='')
Show previous logo.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
img_next($titlealt='default', $moreatt='')
Show next logo.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
report_header($reportname, $notused, $period, $periodlink, $description, $builddate, $exportlink='', $moreparam=array(), $calcmode='', $varlink='')
Show header of a report.
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.