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