dolibarr 24.0.2
balance.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2016 Olivier Geffroy <jeff@jeffinfo.com>
3 * Copyright (C) 2016 Florian Henry <florian.henry@open-concept.pro>
4 * Copyright (C) 2016-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
5 * Copyright (C) 2018-2025 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';
30
31// Class
32require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
33require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
34require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
35require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
36require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php';
37require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancyexport.class.php';
38require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
39require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
40
49// Load translation files required by the page
50$langs->loadLangs(array("accountancy", "compta"));
51
52$action = GETPOST('action', 'aZ09');
53$optioncss = GETPOST('optioncss', 'alpha');
54$type = GETPOST('type', 'alpha');
55if ($type == 'sub') {
56 $context_default = 'balancesubaccountlist';
57} else {
58 $context_default = 'balancelist';
59}
60$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : $context_default;
61$show_subgroup = GETPOST('show_subgroup', 'alpha');
62
63$search_date_start = GETPOSTDATE('date_start', 'getpost', 'auto', 'search_date_start_accountancy');
64$search_date_end = GETPOSTDATE('date_end', 'getpostend', 'auto', 'search_date_end_accountancy');
65
66$search_ledger_code = GETPOST('search_ledger_code', 'array');
67$search_accountancy_code_start = GETPOST('search_accountancy_code_start', 'alpha');
68if ($search_accountancy_code_start == - 1) {
69 $search_accountancy_code_start = '';
70}
71$search_accountancy_code_end = GETPOST('search_accountancy_code_end', 'alpha');
72if ($search_accountancy_code_end == - 1) {
73 $search_accountancy_code_end = '';
74}
75$search_not_reconciled = GETPOST('search_not_reconciled', 'alpha');
76
77// Load variable for pagination
78$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
79$sortfield = GETPOST('sortfield', 'aZ09comma');
80$sortorder = GETPOST('sortorder', 'aZ09comma');
81$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT('page');
82if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
83 // If $page is not defined, or '' or -1 or if we click on clear filters
84 $page = 0;
85}
86$offset = $limit * $page;
87$pageprev = $page - 1;
88$pagenext = $page + 1;
89if ($sortorder == "") {
90 $sortorder = "ASC";
91}
92if ($sortfield == "") {
93 $sortfield = "t.numero_compte";
94}
95
96// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
98$hookmanager->initHooks(array($contextpage)); // Note that conf->hooks_modules contains array
99
100$formaccounting = new FormAccounting($db);
101$form = new Form($db);
102
103if (empty($search_date_start) && empty($search_date_end) && !GETPOSTISSET('formfilteraction')) {
104 $sql = "SELECT date_start, date_end";
105 $sql .= " FROM ".MAIN_DB_PREFIX."accounting_fiscalyear ";
106 if (getDolGlobalInt('ACCOUNTANCY_FISCALYEAR_DEFAULT')) {
107 $sql .= " WHERE rowid = " . getDolGlobalInt('ACCOUNTANCY_FISCALYEAR_DEFAULT');
108 } else {
109 $sql .= " WHERE date_start < '" . $db->idate(dol_now()) . "' and date_end > '" . $db->idate(dol_now()) . "'";
110 }
111 $sql .= $db->plimit(1);
112 $res = $db->query($sql);
113
114 if ($db->num_rows($res) > 0) {
115 $fiscalYear = $db->fetch_object($res);
116 $search_date_start = strtotime($fiscalYear->date_start);
117 $search_date_end = strtotime($fiscalYear->date_end);
118 } else {
119 $month_start = getDolGlobalInt('SOCIETE_FISCAL_MONTH_START', 1);
120 $year_start = (int) dol_print_date(dol_now(), '%Y');
121 if (dol_print_date(dol_now(), '%m') < $month_start) {
122 $year_start--; // If current month is lower that starting fiscal month, we start last year
123 }
124 $year_end = $year_start + 1;
125 $month_end = $month_start - 1;
126 if ($month_end < 1) {
127 $month_end = 12;
128 $year_end--;
129 }
130 $search_date_start = dol_mktime(0, 0, 0, $month_start, 1, $year_start);
131 $search_date_end = dol_get_last_day($year_end, $month_end);
132 }
133}
134
135if (!isModEnabled('accounting')) {
137}
138if ($user->socid > 0) {
140}
141if (!$user->hasRight('accounting', 'mouvements', 'lire')) {
143}
144
145// Permissions
146$permissiontoread = $user->hasRight('accounting', 'mouvements', 'lire');
147$permissiontoadd = $user->hasRight('accounting', 'mouvements', 'creer');
148$permissiontodelete = $user->hasRight('accounting', 'mouvements', 'supprimer');
149$permissiontoexport = $user->hasRight('accounting', 'mouvements', 'export');
150
151
152/*
153 * Action
154 */
155
156$param = '';
157$urlparam = '';
158$parameters = array();
159$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
160if ($reshook < 0) {
161 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
162}
163
164$filter = array();
165
166if (empty($reshook)) {
167 if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
168 $show_subgroup = '';
169 $search_date_start = '';
170 $search_date_end = '';
171 $search_accountancy_code_start = '';
172 $search_accountancy_code_end = '';
173 $search_not_reconciled = '';
174 $search_ledger_code = array();
175 unset($_SESSION['DOLDATE_search_date_start_accountancy_day']);
176 unset($_SESSION['DOLDATE_search_date_start_accountancy_month']);
177 unset($_SESSION['DOLDATE_search_date_start_accountancy_year']);
178 unset($_SESSION['DOLDATE_search_date_end_accountancy_day']);
179 unset($_SESSION['DOLDATE_search_date_end_accountancy_month']);
180 unset($_SESSION['DOLDATE_search_date_end_accountancy_year']);
181 }
182
183 if (!empty($search_date_start)) {
184 $filter['t.doc_date>='] = $search_date_start;
185 $param .= '&date_startmonth=' . GETPOSTINT('date_startmonth') . '&date_startday=' . GETPOSTINT('date_startday') . '&date_startyear=' . GETPOSTINT('date_startyear');
186 }
187 if (!empty($search_date_end)) {
188 $filter['t.doc_date<='] = $search_date_end;
189 $param .= '&date_endmonth=' . GETPOSTINT('date_endmonth') . '&date_endday=' . GETPOSTINT('date_endday') . '&date_endyear=' . GETPOSTINT('date_endyear');
190 }
191 if (!empty($search_accountancy_code_start)) {
192 if ($type == 'sub') {
193 $filter['t.subledger_account>='] = $search_accountancy_code_start;
194 } else {
195 $filter['t.numero_compte>='] = $search_accountancy_code_start;
196 }
197 $param .= '&search_accountancy_code_start=' . urlencode($search_accountancy_code_start);
198 }
199 if (!empty($search_accountancy_code_end)) {
200 if ($type == 'sub') {
201 $filter['t.subledger_account<='] = $search_accountancy_code_end;
202 } else {
203 $filter['t.numero_compte<='] = $search_accountancy_code_end;
204 }
205 $param .= '&search_accountancy_code_end=' . urlencode($search_accountancy_code_end);
206 }
207 if (!empty($search_ledger_code)) {
208 $filter['t.code_journal'] = $search_ledger_code;
209 foreach ($search_ledger_code as $code) {
210 $param .= '&search_ledger_code[]=' . urlencode($code);
211 }
212 }
213 if (!empty($search_not_reconciled)) {
214 $filter['t.reconciled_option'] = $search_not_reconciled;
215 $param .= '&search_not_reconciled='.urlencode($search_not_reconciled);
216 }
217 if (!empty($show_subgroup)) {
218 $param .= '&show_subgroup='.urlencode($show_subgroup);
219 }
220
221 // param with type of list
222 $url_param = substr($param, 1); // remove first "&"
223 if (!empty($type)) {
224 $param = '&type=' . $type . $param;
225 }
226}
227
228if ($action == 'export' && $user->hasRight('accounting', 'mouvements', 'lire')) {
229 $exportType = GETPOST('export_type');
230
231 // An export must contain every account, not only the current page, otherwise the grand totals
232 // are short of the dropped rows. Same as the ledger export in listbyaccount.php.
233 if ($type == 'sub') {
234 $result = $object->fetchAllBalance($sortorder, $sortfield, 0, 0, $filter, 'AND', 1);
235 } else {
236 $result = $object->fetchAllBalance($sortorder, $sortfield, 0, 0, $filter);
237 }
238 if ($result < 0) {
239 setEventMessages($object->error, $object->errors, 'errors');
240 }
241
242 if ($exportType === 'csv') {
243 $sep = getDolGlobalString('ACCOUNTING_EXPORT_SEPARATORCSV');
244 $filename = 'balance'; // Used by the tpl
245 $type_export = 'balance'; // Used by the tpl
246 include DOL_DOCUMENT_ROOT.'/accountancy/tpl/export_journal.tpl.php';
247
248 foreach ($object->lines as $line) {
249 if ($type == 'sub') {
250 print '"' . length_accounta($line->subledger_account) . '"' . $sep;
251 print '"' . $line->subledger_label . '"' . $sep;
252 } else {
253 print '"' . length_accountg($line->numero_compte) . '"' . $sep;
254 print '"' . $object->get_compte_desc($line->numero_compte) . '"' . $sep;
255 }
256 print '"'.price($line->debit).'"'.$sep;
257 print '"'.price($line->credit).'"'.$sep;
258 print '"'.price($line->debit - $line->credit).'"'.$sep;
259 print "\n";
260 }
261 exit;
262 } else {
263 require_once DOL_DOCUMENT_ROOT . '/core/modules/accountancy/doc/pdf_balance.modules.php';
264 $pdf = new pdf_balance($db);
265 $pdf->fromDate = dol_mktime(12, 0, 0, GETPOSTINT('search_date_startmonth'), GETPOSTINT('search_date_startday'), GETPOSTINT('search_date_startyear'));
266 if (empty($pdf->fromDate)) {
267 $pdf->fromDate = dol_mktime(12, 0, 0, GETPOSTINT('date_startmonth'), GETPOSTINT('date_startday'), GETPOSTINT('date_startyear'));
268 }
269 $pdf->toDate = dol_mktime(12, 0, 0, GETPOSTINT('search_date_endmonth'), GETPOSTINT('search_date_endday'), GETPOSTINT('search_date_endyear'));
270 if (empty($pdf->toDate)) {
271 $pdf->toDate = dol_mktime(12, 0, 0, GETPOSTINT('date_endmonth'), GETPOSTINT('date_endday'), GETPOSTINT('date_endyear'));
272 }
273 $pdf->balanceType = $type;
274
275 $result = $pdf->write_file($object, $langs);
276
277 if ($result < 0) {
278 setEventMessage($pdf->error, "errors");
279 } else {
280 // Generated PDF is directly sent to the browser
281 exit;
282 }
283 }
284}
285
286
287/*
288 * View
289 */
290
291if ($type == 'sub') {
292 $title_page = $langs->trans("AccountBalanceSubAccount");
293} else {
294 $title_page = $langs->trans("AccountBalance");
295}
296
297$help_url = 'EN:Module_Double_Entry_Accounting|FR:Module_Comptabilit&eacute;_en_Partie_Double';
298
299llxHeader('', $title_page, $help_url, '', 0, 0, '', '', '', 'mod-accountancy accountancy-consultation page-'.(($type == 'sub') ? 'sub' : '').'balance');
300
301
302if ($action != 'export') {
303 // List
304 $nbtotalofrecords = '';
305 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
306 if ($type == 'sub') {
307 $nbtotalofrecords = $object->fetchAllBalance($sortorder, $sortfield, 0, 0, $filter, 'AND', 1);
308 } else {
309 $nbtotalofrecords = $object->fetchAllBalance($sortorder, $sortfield, 0, 0, $filter);
310 }
311
312 if ($nbtotalofrecords < 0) {
313 setEventMessages($object->error, $object->errors, 'errors');
314 }
315 }
316
317 if ($type == 'sub') {
318 $result = $object->fetchAllBalance($sortorder, $sortfield, $limit, $offset, $filter, 'AND', 1);
319 } else {
320 $result = $object->fetchAllBalance($sortorder, $sortfield, $limit, $offset, $filter);
321 }
322
323 if ($result < 0) {
324 setEventMessages($object->error, $object->errors, 'errors');
325 }
326
327 print '<form method="POST" id="searchFormList" action="'.dolBuildUrl($_SERVER["PHP_SELF"]).'">';
328 print '<input type="hidden" name="token" value="'.newToken().'">';
329 print '<input type="hidden" name="action" id="action" value="list">';
330 print '<input type="hidden" name="export_type" id="export_type" value="">';
331 if ($optioncss != '') {
332 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
333 }
334 print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
335 print '<input type="hidden" name="type" value="'.$type.'">';
336 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
337 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
338 print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
339 print '<input type="hidden" name="page" value="'.$page.'">';
340
341 $url_param = '';
342
343 $parameters = array();
344 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
345
346 if ($reshook < 0) {
347 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
348 }
349
350 $newcardbutton = empty($hookmanager->resPrint) ? '' : $hookmanager->resPrint;
351
352 if (empty($reshook)) {
353 if ($type == 'sub') {
354 $newcardbutton .= dolGetButtonTitle($langs->trans('AccountBalance')." - ".$langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/balance.php?' . $url_param, '', 1, array('morecss' => 'marginleftonly'));
355 $newcardbutton .= dolGetButtonTitle($langs->trans('AccountBalance')." - ".$langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/balance.php?type=sub' . $url_param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected'));
356 } else {
357 $newcardbutton .= dolGetButtonTitle($langs->trans('AccountBalance')." - ".$langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/balance.php?' . $url_param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected'));
358 $newcardbutton .= dolGetButtonTitle($langs->trans('AccountBalance')." - ".$langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/balance.php?type=sub' . $url_param, '', 1, array('morecss' => 'marginleftonly'));
359 }
360
361 $newcardbutton .= dolGetButtonTitle($langs->trans("Export").' (' . getDolGlobalString('ACCOUNTING_EXPORT_FORMAT').')', '', 'fa fa-file-csv paddingleft', $_SERVER['PHP_SELF'], 'exportcsvbutton', $permissiontoexport, array('morecss' => 'marginleftonly'));
362
363 print '<script type="text/javascript">
364 jQuery(document).ready(function() {
365 jQuery("#exportcsvbutton, #exportpdfbutton").click(function(event) {
366 event.preventDefault();
367 const exportType = this.id === "exportcsvbutton" ? "csv" : "pdf";
368 console.log("Set action to export, export_type to " + exportType);
369 jQuery("#action").val("export");
370 jQuery("#export_type").val(exportType);
371 jQuery("#searchFormList").submit();
372 jQuery("#action").val("list");
373 });
374 });
375 </script>';
376
377 $newcardbutton .= dolGetButtonTitle($langs->trans('ExportToPdf'), '', 'fa fa-file-pdf paddingleft', $_SERVER['PHP_SELF'] . '&token=' . newToken(), 'exportpdfbutton', $permissiontoexport, array('morecss' => 'marginleftonly'));
378
379 $newcardbutton .= dolGetButtonTitleSeparator();
380 $newcardbutton .= dolGetButtonTitle($langs->trans('NewAccountingMvt'), '', 'fa fa-plus-circle paddingleft', DOL_URL_ROOT.'/accountancy/bookkeeping/card.php?action=create'.(!empty($type) ? '&type=sub' : '').'&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $permissiontoadd);
381 }
382 if ($contextpage != $_SERVER["PHP_SELF"]) {
383 $param .= '&contextpage='.urlencode($contextpage);
384 }
385 if ($limit > 0 && $limit != $conf->liste_limit) {
386 $param .= '&limit='.((int) $limit);
387 }
388
389 print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $result, $nbtotalofrecords, 'title_accountancy', 0, $newcardbutton, '', $limit, 0, 0, 1);
390
391 $selectedfields = '';
392
393 // Warning to explain why list of record is not consistent with the other list view (missing a lot of lines)
394 if ($type == 'sub') {
395 print info_admin($langs->trans("WarningRecordWithoutSubledgerAreExcluded"));
396 }
397
398 $moreforfilter = '';
399
400 $moreforfilter .= '<div class="divsearchfield">';
401 $moreforfilter .= $langs->trans('DateStart').': ';
402 $moreforfilter .= $form->selectDate($search_date_start ? $search_date_start : -1, 'date_start', 0, 0, 1, '', 1, 0);
403 $moreforfilter .= $langs->trans('DateEnd').': ';
404 $moreforfilter .= $form->selectDate($search_date_end ? $search_date_end : -1, 'date_end', 0, 0, 1, '', 1, 0);
405 $moreforfilter .= '</div>';
406
407 $moreforfilter .= '<div class="divsearchfield">';
408 $moreforfilter .= '<label for="show_subgroup">'.$langs->trans('ShowSubtotalByGroup').'</label>: ';
409 $moreforfilter .= '<input type="checkbox" name="show_subgroup" id="show_subgroup" value="show_subgroup"'.($show_subgroup == 'show_subgroup' ? ' checked' : '').'>';
410 $moreforfilter .= '</div>';
411
412 $moreforfilter .= '<div class="divsearchfield">';
413 $moreforfilter .= $langs->trans("Journals").': ';
414 $moreforfilter .= $formaccounting->multi_select_journal($search_ledger_code, 'search_ledger_code', 0, 1, 1, 1);
415 $moreforfilter .= '</div>';
416
417 //$moreforfilter .= '<br>';
418 $moreforfilter .= '<div class="divsearchfield">';
419 // Accountancy account
420 $moreforfilter .= $langs->trans('AccountAccounting').': ';
421 if ($type == 'sub') {
422 $moreforfilter .= $formaccounting->select_auxaccount($search_accountancy_code_start, 'search_accountancy_code_start', $langs->trans('From'), 'maxwidth200');
423 } else {
424 $moreforfilter .= $formaccounting->select_account($search_accountancy_code_start, 'search_accountancy_code_start', $langs->trans('From'), array(), 1, 1, 'maxwidth200', 'accounts');
425 }
426 $moreforfilter .= ' ';
427 if ($type == 'sub') {
428 $moreforfilter .= $formaccounting->select_auxaccount($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), 'maxwidth200');
429 } else {
430 $moreforfilter .= $formaccounting->select_account($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), array(), 1, 1, 'maxwidth200', 'accounts');
431 }
432 $moreforfilter .= '</div>';
433
434 if (getDolGlobalString('ACCOUNTING_ENABLE_LETTERING')) {
435 $moreforfilter .= '<div class="divsearchfield">';
436 $moreforfilter .= '<label for="notreconciled">'.$langs->trans('NotReconciled').'</label>: ';
437 $moreforfilter .= '<input type="checkbox" name="search_not_reconciled" id="notreconciled" value="notreconciled"'.($search_not_reconciled == 'notreconciled' ? ' checked' : '').'>';
438 $moreforfilter .= '</div>';
439 }
440
441 print '<div class="liste_titre liste_titre_bydiv centpercent">';
442 print $moreforfilter;
443 $parameters = array();
444 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
445 print $hookmanager->resPrint;
446 print '</div>';
447
448
449 $colspan = (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE') ? 5 : 4);
450
451 print '<table class="liste '.($moreforfilter ? "listwithfilterbefore" : "").'">';
452
453 print '<tr class="liste_titre_filter">';
454
455 if ($conf->main_checkbox_left_column) {
456 print '<td class="liste_titre maxwidthsearch">';
457 $searchpicto = $form->showFilterButtons();
458 print $searchpicto;
459 print '</td>';
460 }
461
462 print '<td class="liste_titre" colspan="'.$colspan.'">';
463 print '</td>';
464
465 // Fields from hook
466 $parameters = array();
467 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook
468 print $hookmanager->resPrint;
469
470 // Action column
471 if (!$conf->main_checkbox_left_column) {
472 print '<td class="liste_titre maxwidthsearch">';
473 $searchpicto = $form->showFilterButtons();
474 print $searchpicto;
475 print '</td>';
476 }
477 print '</tr>'."\n";
478
479 print '<tr class="liste_titre">';
480 if ($conf->main_checkbox_left_column) {
481 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
482 }
483 print_liste_field_titre("AccountAccounting", $_SERVER['PHP_SELF'], "t.numero_compte", "", $param, "", $sortfield, $sortorder);
484 // TODO : Retrieve the type of third party: Customer / Supplier / Employee
485 //if ($type == 'sub') {
486 // print_liste_field_titre("Type", $_SERVER['PHP_SELF'], "t.type", "", $param, "", $sortfield, $sortorder);
487 //}
488 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
489 print_liste_field_titre("OpeningBalance", $_SERVER['PHP_SELF'], "", "", $param, 'class="right"', $sortfield, $sortorder);
490 }
491 print_liste_field_titre("AccountingDebit", $_SERVER['PHP_SELF'], "t.debit", "", $param, 'class="right"', $sortfield, $sortorder);
492 print_liste_field_titre("AccountingCredit", $_SERVER['PHP_SELF'], "t.credit", "", $param, 'class="right"', $sortfield, $sortorder);
493 print_liste_field_titre("Balance", $_SERVER["PHP_SELF"], '', '', $param, 'class="right"', $sortfield, $sortorder);
494
495 // Hook fields
496 $parameters = array('param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder);
497 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook
498 print $hookmanager->resPrint;
499 // Action column
500 if (!$conf->main_checkbox_left_column) {
501 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
502 }
503 print '</tr>'."\n";
504
505 $total_debit = 0;
506 $total_credit = 0;
507 $sous_total_debit = 0;
508 $sous_total_credit = 0;
509 $total_opening_balance = 0;
510 $sous_total_opening_balance = 0;
511 $displayed_account = "";
512
513 $accountingaccountstatic = new AccountingAccount($db);
514
515 // TODO Debug - This feature is dangerous, it takes all the entries and adds all the accounts
516 // without time and class limits (Class 6 and 7 accounts ???) and does not take into account the "a-nouveau" journal.
517 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
518 $sql = "SELECT t.numero_compte, (SUM(t.debit) - SUM(t.credit)) as opening_balance";
519 $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as t";
520 $sql .= " WHERE t.entity = " . ((int) $conf->entity); // Never do sharing into accounting features
521 $sql .= " AND t.doc_date < '" . $db->idate($search_date_start) . "'";
522 $sql .= " GROUP BY t.numero_compte";
523
524 $resql = $db->query($sql);
525 $opening_balances = array();
526 if ($resql) {
527 $nrows = $db->num_rows($resql);
528 for ($i = 0; $i < $nrows; $i++) {
529 $arr = $db->fetch_array($resql);
530 if (is_array($arr)) {
531 $opening_balances["'" . $arr['numero_compte'] . "'"] = $arr['opening_balance'];
532 }
533 }
534 } else {
536 }
537 }
538
539 foreach ($object->lines as $line) {
540 // reset before the fetch (in case of the fetch fails)
541 $accountingaccountstatic->id = 0;
542 $accountingaccountstatic->account_number = '';
543 $accounting_account = '';
544
545 if ($type != 'sub') {
546 $accountingaccountstatic->fetch(0, $line->numero_compte, true);
547 if (!empty($accountingaccountstatic->account_number)) {
548 $accounting_account = $accountingaccountstatic->getNomUrl(0, 1, 1);
549 } else {
550 $accounting_account = length_accountg($line->numero_compte);
551 }
552 }
553
554 $link = '';
555 $total_debit += $line->debit;
556 $total_credit += $line->credit;
557 $opening_balance = isset($opening_balances["'".$line->numero_compte."'"]) ? $opening_balances["'".$line->numero_compte."'"] : 0;
558 $total_opening_balance += $opening_balance;
559
560 $tmparrayforrootaccount = $object->getRootAccount($line->numero_compte);
561 $root_account_description = $tmparrayforrootaccount['label'];
562 $root_account_number = $tmparrayforrootaccount['account_number'];
563
564 //var_dump($tmparrayforrootaccount);
565 //var_dump($accounting_account);
566 //var_dump($accountingaccountstatic);
567 if (empty($accountingaccountstatic->label) && $accountingaccountstatic->id > 0) {
568 $link = '<a class="editfielda reposition" href="' . DOL_URL_ROOT . '/accountancy/admin/card.php?action=update&token=' . newToken() . '&id=' . $accountingaccountstatic->id . '">' . img_edit() . '</a>';
569 } elseif ($accounting_account == 'NotDefined') {
570 $link = '<a href="' . DOL_URL_ROOT . '/accountancy/admin/card.php?action=create&token=' . newToken() . '&accountingaccount=' . length_accountg($line->numero_compte) . '">' . img_edit_add() . '</a>';
571 } /* elseif (empty($tmparrayforrootaccount['label'])) {
572 // $tmparrayforrootaccount['label'] not defined = the account has not parent with a parent.
573 // This is useless, we should not create a new account when an account has no parent, we must edit it to fix its parent.
574 // BUG 1: Accounts on level root or level 1 must not have a parent 2 level higher, so should not show a link to create another account.
575 // BUG 2: Adding a link to create a new accounting account here is useless because it is not add as parent of the orphelin.
576 //$link = '<a href="' . DOL_URL_ROOT . '/accountancy/admin/card.php?action=create&token=' . newToken() . '&accountingaccount=' . length_accountg($line->numero_compte) . '">' . img_edit_add() . '</a>';
577 } */
578
579 if (!empty($show_subgroup)) {
580 // Show accounting account
581 if (empty($displayed_account) || $root_account_number != $displayed_account) {
582 // Show subtotal per accounting account
583 if ($displayed_account != "") {
584 print '<tr class="liste_total">';
585 print '<td class="right">'.$langs->trans("SubTotal").':</td>';
586 if ($conf->main_checkbox_left_column) {
587 print '<td></td>';
588 }
589 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
590 print '<td class="right nowraponall amount">'.price($sous_total_opening_balance).'</td>';
591 }
592 print '<td class="right nowraponall amount">'.price($sous_total_debit).'</td>';
593 print '<td class="right nowraponall amount">'.price($sous_total_credit).'</td>';
594 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
595 print '<td class="right nowraponall amount">'.price(price2num($sous_total_opening_balance + $sous_total_debit - $sous_total_credit)).'</td>';
596 } else {
597 print '<td class="right nowraponall amount">'.price(price2num($sous_total_debit - $sous_total_credit)).'</td>';
598 }
599 if (!$conf->main_checkbox_left_column) {
600 print "<td></td>\n";
601 }
602 print '</tr>';
603 }
604
605 // Show first line of a break
606 print '<tr class="trforbreak">';
607 print '<td colspan="'.($colspan + 1).'" class="tdforbreak">'.$root_account_number.($root_account_description ? ' - '.$root_account_description : '').'</td>';
608 print '</tr>';
609
610 $displayed_account = $root_account_number;
611 $sous_total_debit = 0;
612 $sous_total_credit = 0;
613 $sous_total_opening_balance = 0;
614 }
615 }
616
617 print '<tr class="oddeven">';
618
619 // Action column
620 if ($conf->main_checkbox_left_column) {
621 print '<td class="center">';
622 print $link;
623 print '</td>';
624 }
625
626 // Accounting account
627 if ($type == 'sub') {
628 print '<td>'.$line->subledger_account.' <span class="opacitymedium">('.$line->subledger_label.')</span></td>';
629 } else {
630 print '<td>'.$accounting_account.'</td>';
631 }
632
633 // Type
634 // TODO Retrieve the type of third party: Customer / Supplier / Employee
635 //if ($type == 'sub') {
636 // print '<td></td>';
637 //}
638
639 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
640 print '<td class="right nowraponall amount">'.price(price2num($opening_balance, 'MT')).'</td>';
641 }
642
643 $urlzoom = '';
644 if ($type == 'sub') {
645 if ($line->subledger_account) {
646 $urlzoom = DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?type=sub&search_accountancy_code_start=' . urlencode($line->subledger_account) . '&search_accountancy_code_end=' . urlencode($line->subledger_account);
647 if (GETPOSTISSET('date_startmonth')) {
648 $urlzoom .= '&search_date_startmonth=' . GETPOSTINT('date_startmonth') . '&search_date_startday=' . GETPOSTINT('date_startday') . '&search_date_startyear=' . GETPOSTINT('date_startyear');
649 }
650 if (GETPOSTISSET('date_endmonth')) {
651 $urlzoom .= '&search_date_endmonth=' . GETPOSTINT('date_endmonth') . '&search_date_endday=' . GETPOSTINT('date_endday') . '&search_date_endyear=' . GETPOSTINT('date_endyear');
652 }
653 }
654 } else {
655 if ($line->numero_compte) {
656 $urlzoom = DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?search_accountancy_code_start=' . urlencode($line->numero_compte) . '&search_accountancy_code_end=' . urlencode($line->numero_compte);
657 if (GETPOSTISSET('date_startmonth')) {
658 $urlzoom .= '&search_date_startmonth=' . GETPOSTINT('date_startmonth') . '&search_date_startday=' . GETPOSTINT('date_startday') . '&search_date_startyear=' . GETPOSTINT('date_startyear');
659 }
660 if (GETPOSTISSET('date_endmonth')) {
661 $urlzoom .= '&search_date_endmonth=' . GETPOSTINT('date_endmonth') . '&search_date_endday=' . GETPOSTINT('date_endday') . '&search_date_endyear=' . GETPOSTINT('date_endyear');
662 }
663 }
664 }
665 // Debit
666 print '<td class="right nowraponall amount"><a href="'.$urlzoom.'">'.price(price2num($line->debit, 'MT')).'</a></td>';
667 // Credit
668 print '<td class="right nowraponall amount"><a href="'.$urlzoom.'">'.price(price2num($line->credit, 'MT')).'</a></td>';
669
670 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
671 print '<td class="right nowraponall amount">'.price(price2num($opening_balance + $line->debit - $line->credit, 'MT')).'</td>';
672 } else {
673 print '<td class="right nowraponall amount">'.price(price2num($line->debit - $line->credit, 'MT')).'</td>';
674 }
675
676 // Action column
677 if (!$conf->main_checkbox_left_column) {
678 print '<td class="center">';
679 print $link;
680 print '</td>';
681 }
682
683 print "</tr>\n";
684
685 // Records the sub-total
686 $sous_total_debit += $line->debit;
687 $sous_total_credit += $line->credit;
688 $sous_total_opening_balance += $opening_balance;
689 }
690
691 if (!empty($show_subgroup)) {
692 print '<tr class="liste_total">';
693 // Action column
694 if ($conf->main_checkbox_left_column) {
695 print "<td></td>\n";
696 }
697 print '<td class="right">'.$langs->trans("SubTotal").':</td>';
698 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
699 print '<td class="right nowraponall amount">'.price(price2num($sous_total_opening_balance, 'MT')).'</td>';
700 }
701 print '<td class="right nowraponall amount">'.price(price2num($sous_total_debit, 'MT')).'</td>';
702 print '<td class="right nowraponall amount">'.price(price2num($sous_total_credit, 'MT')).'</td>';
703 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
704 print '<td class="right nowraponall amount">' . price(price2num($sous_total_opening_balance + $sous_total_debit - $sous_total_credit, 'MT')) . '</td>';
705 } else {
706 print '<td class="right nowraponall amount">' . price(price2num($sous_total_debit - $sous_total_credit, 'MT')) . '</td>';
707 }
708 // Action column
709 if (!$conf->main_checkbox_left_column) {
710 print "<td></td>\n";
711 }
712 print '</tr>';
713 }
714
715 print '<tr class="liste_total">';
716 // Action column
717 if ($conf->main_checkbox_left_column) {
718 print "<td></td>\n";
719 }
720 print '<td class="right">'.$langs->trans("AccountBalance").':</td>';
721 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
722 print '<td class="nowrap right">'.price(price2num($total_opening_balance, 'MT')).'</td>';
723 }
724 print '<td class="right nowraponall amount">'.price(price2num($total_debit, 'MT')).'</td>';
725 print '<td class="right nowraponall amount">'.price(price2num($total_credit, 'MT')).'</td>';
726 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
727 print '<td class="right nowraponall amount">' . price(price2num($total_opening_balance + $total_debit - $total_credit, 'MT')) . '</td>';
728 } else {
729 print '<td class="right nowraponall amount">' . price(price2num($total_debit - $total_credit, 'MT')) . '</td>';
730 }
731 // Action column
732 if (!$conf->main_checkbox_left_column) {
733 print "<td></td>\n";
734 }
735 print '</tr>';
736
737 // Accounting result
738 if (getDolGlobalString('ACCOUNTING_CLOSURE_ACCOUNTING_GROUPS_USED_FOR_INCOME_STATEMENT')) {
739 print '<tr class="liste_total">';
740 if ($conf->main_checkbox_left_column) {
741 print "<td></td>\n";
742 }
743 print '<td class="right">' . $langs->trans("AccountingResult") . ':</td>';
744 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
745 print '<td></td>';
746 }
747
748 $accountingResult = $object->accountingResult($search_date_start, $search_date_end);
749 if ($accountingResult < 0) {
750 $accountingResultDebit = price(abs((float) price2num($accountingResult, 'MT')));
751 $accountingResultCredit = '';
752 $accountingResultClassCSS = ' error';
753 } else {
754 $accountingResultDebit = '';
755 $accountingResultCredit = price(price2num($accountingResult, 'MT'));
756 $accountingResultClassCSS = ' green';
757 }
758 print '<td class="right nowraponall amount' . $accountingResultClassCSS . '">' . $accountingResultDebit . '</td>';
759 print '<td class="right nowraponall amount' . $accountingResultClassCSS . '">' . $accountingResultCredit . '</td>';
760
761 print '<td></td>';
762 if (!$conf->main_checkbox_left_column) {
763 print "<td></td>\n";
764 }
765 print '</tr>';
766 }
767
768 $parameters = array();
769 $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
770 print $hookmanager->resPrint;
771
772 print "</table>";
773 print '</form>';
774}
775
776// End of page
777llxFooter();
778$db->close();
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
length_accountg($account)
Return General accounting account with defined length (used for product and miscellaneous)
length_accounta($accounta)
Return Auxiliary accounting account of thirdparties with defined length.
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 accounting accounts.
Class to manage Ledger (General Ledger and Subledger)
Class to manage generation of HTML components for accounting management.
Class to manage generation of HTML components Only common components must be here.
Class to build sending documents with model Espadon.
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:639
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
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.
GETPOSTDATE($prefix, $hourTime='', $gm='auto', $saverestore='')
Helper function that combines values of a dolibarr DatePicker (such as Form\selectDate) for year,...
print_liste_field_titre($name, $file="", $field="", $begin="", $param="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
print_barre_liste($title, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $selectlimitsuffix=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
setEventMessage($mesgs, $style='mesgs', $noduplicate=0, $attop=0)
Set event message in dol_events session object.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $disablesortlink=0, $tooltip='', $forcenowrapcolumntitle=0)
Get title line of an array.
dolGetButtonTitleSeparator($moreClass="")
Add space between dolGetButtonTitle.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
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).
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
img_edit_add($titlealt='default', $other='')
Show logo "+".
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='', $textonpictotooltip='', $cssfordropdown='info_admin')
Show information in HTML for admin users or standard users.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.