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