dolibarr 20.0.5
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 if (!empty($show_subgroup)) {
203 $param .= '&show_subgroup='.urlencode($show_subgroup);
204 }
205
206 // param with type of list
207 $url_param = substr($param, 1); // remove first "&"
208 if (!empty($type)) {
209 $param = '&type=' . $type . $param;
210 }
211}
212
213if ($action == 'export_csv') {
214 $sep = getDolGlobalString('ACCOUNTING_EXPORT_SEPARATORCSV');
215
216 $filename = 'balance';
217 $type_export = 'balance';
218 include DOL_DOCUMENT_ROOT.'/accountancy/tpl/export_journal.tpl.php';
219
220 if ($type == 'sub') {
221 $result = $object->fetchAllBalance($sortorder, $sortfield, $limit, 0, $filter, 'AND', 1);
222 } else {
223 $result = $object->fetchAllBalance($sortorder, $sortfield, $limit, 0, $filter);
224 }
225 if ($result < 0) {
226 setEventMessages($object->error, $object->errors, 'errors');
227 }
228
229 foreach ($object->lines as $line) {
230 if ($type == 'sub') {
231 print '"' . length_accounta($line->subledger_account) . '"' . $sep;
232 print '"' . $line->subledger_label . '"' . $sep;
233 } else {
234 print '"' . length_accountg($line->numero_compte) . '"' . $sep;
235 print '"' . $object->get_compte_desc($line->numero_compte) . '"' . $sep;
236 }
237 print '"'.price($line->debit).'"'.$sep;
238 print '"'.price($line->credit).'"'.$sep;
239 print '"'.price($line->debit - $line->credit).'"'.$sep;
240 print "\n";
241 }
242
243 exit;
244}
245
246
247/*
248 * View
249 */
250
251if ($type == 'sub') {
252 $title_page = $langs->trans("AccountBalanceSubAccount");
253} else {
254 $title_page = $langs->trans("AccountBalance");
255}
256
257$help_url = 'EN:Module_Double_Entry_Accounting|FR:Module_Comptabilit&eacute;_en_Partie_Double';
258
259llxHeader('', $title_page, $help_url, '', 0, 0, '', '', '', 'mod-accountancy accountancy-consultation page-'.(($type == 'sub') ? 'sub' : '').'balance');
260
261
262if ($action != 'export_csv') {
263 // List
264 $nbtotalofrecords = '';
265 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
266 if ($type == 'sub') {
267 $nbtotalofrecords = $object->fetchAllBalance($sortorder, $sortfield, 0, 0, $filter, 'AND', 1);
268 } else {
269 $nbtotalofrecords = $object->fetchAllBalance($sortorder, $sortfield, 0, 0, $filter);
270 }
271
272 if ($nbtotalofrecords < 0) {
273 setEventMessages($object->error, $object->errors, 'errors');
274 }
275 }
276
277 if ($type == 'sub') {
278 $result = $object->fetchAllBalance($sortorder, $sortfield, $limit, $offset, $filter, 'AND', 1);
279 } else {
280 $result = $object->fetchAllBalance($sortorder, $sortfield, $limit, $offset, $filter);
281 }
282
283 if ($result < 0) {
284 setEventMessages($object->error, $object->errors, 'errors');
285 }
286
287 print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">';
288 print '<input type="hidden" name="token" value="'.newToken().'">';
289 print '<input type="hidden" name="action" id="action" value="list">';
290 if ($optioncss != '') {
291 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
292 }
293 print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
294 print '<input type="hidden" name="type" value="'.$type.'">';
295 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
296 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
297 print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
298 print '<input type="hidden" name="page" value="'.$page.'">';
299
300 $url_param = '';
301
302 $parameters = array();
303 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
304
305 if ($reshook < 0) {
306 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
307 }
308
309 $newcardbutton = empty($hookmanager->resPrint) ? '' : $hookmanager->resPrint;
310
311 if (empty($reshook)) {
312 $newcardbutton = '<input type="button" id="exportcsvbutton" name="exportcsvbutton" class="butAction" value="'.$langs->trans("Export").' (' . getDolGlobalString('ACCOUNTING_EXPORT_FORMAT').')" />';
313
314 print '<script type="text/javascript">
315 jQuery(document).ready(function() {
316 jQuery("#exportcsvbutton").click(function(event) {
317 event.preventDefault();
318 console.log("Set action to export_csv");
319 jQuery("#action").val("export_csv");
320 jQuery("#searchFormList").submit();
321 jQuery("#action").val("list");
322 });
323 });
324 </script>';
325
326 if ($type == 'sub') {
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'));
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 btnTitleSelected'));
329 } else {
330 $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'));
331 $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'));
332 }
333 $newcardbutton .= dolGetButtonTitleSeparator();
334 $newcardbutton .= dolGetButtonTitle($langs->trans('NewAccountingMvt'), '', 'fa fa-plus-circle paddingleft', DOL_URL_ROOT.'/accountancy/bookkeeping/card.php?action=create');
335 }
336 if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
337 $param .= '&contextpage='.urlencode($contextpage);
338 }
339 if ($limit > 0 && $limit != $conf->liste_limit) {
340 $param .= '&limit='.((int) $limit);
341 }
342
343 print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $result, $nbtotalofrecords, 'title_accountancy', 0, $newcardbutton, '', $limit, 0, 0, 1);
344
345 $selectedfields = '';
346
347 // Warning to explain why list of record is not consistent with the other list view (missing a lot of lines)
348 if ($type == 'sub') {
349 print info_admin($langs->trans("WarningRecordWithoutSubledgerAreExcluded"));
350 }
351
352 $moreforfilter = '';
353
354 $moreforfilter .= '<div class="divsearchfield">';
355 $moreforfilter .= $langs->trans('DateStart').': ';
356 $moreforfilter .= $form->selectDate($search_date_start ? $search_date_start : -1, 'date_start', 0, 0, 1, '', 1, 0);
357 $moreforfilter .= $langs->trans('DateEnd').': ';
358 $moreforfilter .= $form->selectDate($search_date_end ? $search_date_end : -1, 'date_end', 0, 0, 1, '', 1, 0);
359 $moreforfilter .= '</div>';
360
361 $moreforfilter .= '<div class="divsearchfield">';
362 $moreforfilter .= '<label for="show_subgroup">'.$langs->trans('ShowSubtotalByGroup').'</label>: ';
363 $moreforfilter .= '<input type="checkbox" name="show_subgroup" id="show_subgroup" value="show_subgroup"'.($show_subgroup == 'show_subgroup' ? ' checked' : '').'>';
364 $moreforfilter .= '</div>';
365
366 $moreforfilter .= '<div class="divsearchfield">';
367 $moreforfilter .= $langs->trans("Journals").': ';
368 $moreforfilter .= $formaccounting->multi_select_journal($search_ledger_code, 'search_ledger_code', 0, 1, 1, 1);
369 $moreforfilter .= '</div>';
370
371 //$moreforfilter .= '<br>';
372 $moreforfilter .= '<div class="divsearchfield">';
373 // Accountancy account
374 $moreforfilter .= $langs->trans('AccountAccounting').': ';
375 if ($type == 'sub') {
376 $moreforfilter .= $formaccounting->select_auxaccount($search_accountancy_code_start, 'search_accountancy_code_start', $langs->trans('From'), 'maxwidth200');
377 } else {
378 $moreforfilter .= $formaccounting->select_account($search_accountancy_code_start, 'search_accountancy_code_start', $langs->trans('From'), array(), 1, 1, 'maxwidth200', 'accounts');
379 }
380 $moreforfilter .= ' ';
381 if ($type == 'sub') {
382 $moreforfilter .= $formaccounting->select_auxaccount($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), 'maxwidth200');
383 } else {
384 $moreforfilter .= $formaccounting->select_account($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), array(), 1, 1, 'maxwidth200', 'accounts');
385 }
386 $moreforfilter .= '</div>';
387
388 if (getDolGlobalString('ACCOUNTING_ENABLE_LETTERING')) {
389 $moreforfilter .= '<div class="divsearchfield">';
390 $moreforfilter .= '<label for="notreconciled">'.$langs->trans('NotReconciled').'</label>: ';
391 $moreforfilter .= '<input type="checkbox" name="search_not_reconciled" id="notreconciled" value="notreconciled"'.($search_not_reconciled == 'notreconciled' ? ' checked' : '').'>';
392 $moreforfilter .= '</div>';
393 }
394
395 if (!empty($moreforfilter)) {
396 print '<div class="liste_titre liste_titre_bydiv centpercent">';
397 print $moreforfilter;
398 $parameters = array();
399 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
400 print $hookmanager->resPrint;
401 print '</div>';
402 }
403
404
405 $colspan = (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE') ? 5 : 4);
406
407 print '<table class="liste '.($moreforfilter ? "listwithfilterbefore" : "").'">';
408
409 print '<tr class="liste_titre_filter">';
410
411 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
412 print '<td class="liste_titre maxwidthsearch">';
413 $searchpicto = $form->showFilterButtons();
414 print $searchpicto;
415 print '</td>';
416 }
417
418 print '<td class="liste_titre" colspan="'.$colspan.'">';
419 print '</td>';
420
421 // Fields from hook
422 $parameters = array();
423 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook
424 print $hookmanager->resPrint;
425
426 // Action column
427 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
428 print '<td class="liste_titre maxwidthsearch">';
429 $searchpicto = $form->showFilterButtons();
430 print $searchpicto;
431 print '</td>';
432 }
433 print '</tr>'."\n";
434
435 print '<tr class="liste_titre">';
436 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
437 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
438 }
439 print_liste_field_titre("AccountAccounting", $_SERVER['PHP_SELF'], "t.numero_compte", "", $param, "", $sortfield, $sortorder);
440 // TODO : Retrieve the type of third party: Customer / Supplier / Employee
441 //if ($type == 'sub') {
442 // print_liste_field_titre("Type", $_SERVER['PHP_SELF'], "t.type", "", $param, "", $sortfield, $sortorder);
443 //}
444 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
445 print_liste_field_titre("OpeningBalance", $_SERVER['PHP_SELF'], "", $param, "", 'class="right"', $sortfield, $sortorder);
446 }
447 print_liste_field_titre("AccountingDebit", $_SERVER['PHP_SELF'], "t.debit", "", $param, 'class="right"', $sortfield, $sortorder);
448 print_liste_field_titre("AccountingCredit", $_SERVER['PHP_SELF'], "t.credit", "", $param, 'class="right"', $sortfield, $sortorder);
449 print_liste_field_titre("Balance", $_SERVER["PHP_SELF"], "", $param, "", 'class="right"', $sortfield, $sortorder);
450
451 // Hook fields
452 $parameters = array('param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder);
453 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook
454 print $hookmanager->resPrint;
455 // Action column
456 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
457 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
458 }
459 print '</tr>'."\n";
460
461 $total_debit = 0;
462 $total_credit = 0;
463 $sous_total_debit = 0;
464 $sous_total_credit = 0;
465 $total_opening_balance = 0;
466 $sous_total_opening_balance = 0;
467 $displayed_account = "";
468
469 $accountingaccountstatic = new AccountingAccount($db);
470
471 // TODO Debug - This feature is dangerous, it takes all the entries and adds all the accounts
472 // without time and class limits (Class 6 and 7 accounts ???) and does not take into account the "a-nouveau" journal.
473 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
474 $sql = "SELECT t.numero_compte, (SUM(t.debit) - SUM(t.credit)) as opening_balance";
475 $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as t";
476 $sql .= " WHERE t.entity = " . $conf->entity; // Never do sharing into accounting features
477 $sql .= " AND t.doc_date < '" . $db->idate($search_date_start) . "'";
478 $sql .= " GROUP BY t.numero_compte";
479
480 $resql = $db->query($sql);
481 $opening_balances = array();
482 if ($resql) {
483 $nrows = $db->num_rows($resql);
484 for ($i = 0; $i < $nrows; $i++) {
485 $arr = $db->fetch_array($resql);
486 if (is_array($arr)) {
487 $opening_balances["'" . $arr['numero_compte'] . "'"] = $arr['opening_balance'];
488 }
489 }
490 } else {
491 dol_print_error($db);
492 }
493 }
494
495 foreach ($object->lines as $line) {
496 // reset before the fetch (in case of the fetch fails)
497 $accountingaccountstatic->id = 0;
498 $accountingaccountstatic->account_number = '';
499 $accounting_account = '';
500
501 if ($type != 'sub') {
502 $accountingaccountstatic->fetch(0, $line->numero_compte, true);
503 if (!empty($accountingaccountstatic->account_number)) {
504 $accounting_account = $accountingaccountstatic->getNomUrl(0, 1, 1);
505 } else {
506 $accounting_account = length_accountg($line->numero_compte);
507 }
508 }
509
510 $link = '';
511 $total_debit += $line->debit;
512 $total_credit += $line->credit;
513 $opening_balance = isset($opening_balances["'".$line->numero_compte."'"]) ? $opening_balances["'".$line->numero_compte."'"] : 0;
514 $total_opening_balance += $opening_balance;
515
516 $tmparrayforrootaccount = $object->getRootAccount($line->numero_compte);
517 $root_account_description = $tmparrayforrootaccount['label'];
518 $root_account_number = $tmparrayforrootaccount['account_number'];
519
520 //var_dump($tmparrayforrootaccount);
521 //var_dump($accounting_account);
522 //var_dump($accountingaccountstatic);
523 if (empty($accountingaccountstatic->label) && $accountingaccountstatic->id > 0) {
524 $link = '<a class="editfielda reposition" href="' . DOL_URL_ROOT . '/accountancy/admin/card.php?action=update&token=' . newToken() . '&id=' . $accountingaccountstatic->id . '">' . img_edit() . '</a>';
525 } elseif ($accounting_account == 'NotDefined') {
526 $link = '<a href="' . DOL_URL_ROOT . '/accountancy/admin/card.php?action=create&token=' . newToken() . '&accountingaccount=' . length_accountg($line->numero_compte) . '">' . img_edit_add() . '</a>';
527 } /* elseif (empty($tmparrayforrootaccount['label'])) {
528 // $tmparrayforrootaccount['label'] not defined = the account has not parent with a parent.
529 // This is useless, we should not create a new account when an account has no parent, we must edit it to fix its parent.
530 // 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.
531 // BUG 2: Adding a link to create a new accounting account here is useless because it is not add as parent of the orphelin.
532 //$link = '<a href="' . DOL_URL_ROOT . '/accountancy/admin/card.php?action=create&token=' . newToken() . '&accountingaccount=' . length_accountg($line->numero_compte) . '">' . img_edit_add() . '</a>';
533 } */
534
535 if (!empty($show_subgroup)) {
536 // Show accounting account
537 if (empty($displayed_account) || $root_account_number != $displayed_account) {
538 // Show subtotal per accounting account
539 if ($displayed_account != "") {
540 print '<tr class="liste_total">';
541 print '<td class="right">'.$langs->trans("SubTotal").':</td>';
542 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
543 print '<td></td>';
544 }
545 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
546 print '<td class="right nowraponall amount">'.price($sous_total_opening_balance).'</td>';
547 }
548 print '<td class="right nowraponall amount">'.price($sous_total_debit).'</td>';
549 print '<td class="right nowraponall amount">'.price($sous_total_credit).'</td>';
550 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
551 print '<td class="right nowraponall amount">'.price(price2num($sous_total_opening_balance + $sous_total_debit - $sous_total_credit)).'</td>';
552 } else {
553 print '<td class="right nowraponall amount">'.price(price2num($sous_total_debit - $sous_total_credit)).'</td>';
554 }
555 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
556 print "<td></td>\n";
557 }
558 print '</tr>';
559 }
560
561 // Show first line of a break
562 print '<tr class="trforbreak">';
563 print '<td colspan="'.($colspan + 1).'" class="tdforbreak">'.$root_account_number.($root_account_description ? ' - '.$root_account_description : '').'</td>';
564 print '</tr>';
565
566 $displayed_account = $root_account_number;
567 $sous_total_debit = 0;
568 $sous_total_credit = 0;
569 $sous_total_opening_balance = 0;
570 }
571 }
572
573 print '<tr class="oddeven">';
574
575 // Action column
576 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
577 print '<td class="center">';
578 print $link;
579 print '</td>';
580 }
581
582 // Accounting account
583 if ($type == 'sub') {
584 print '<td>'.$line->subledger_account.' <span class="opacitymedium">('.$line->subledger_label.')</span></td>';
585 } else {
586 print '<td>'.$accounting_account.'</td>';
587 }
588
589 // Type
590 // TODO Retrieve the type of third party: Customer / Supplier / Employee
591 //if ($type == 'sub') {
592 // print '<td></td>';
593 //}
594
595 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
596 print '<td class="right nowraponall amount">'.price(price2num($opening_balance, 'MT')).'</td>';
597 }
598
599 $urlzoom = '';
600 if ($type == 'sub') {
601 if ($line->subledger_account) {
602 $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);
603 if (GETPOSTISSET('date_startmonth')) {
604 $urlzoom .= '&search_date_startmonth=' . GETPOSTINT('date_startmonth') . '&search_date_startday=' . GETPOSTINT('date_startday') . '&search_date_startyear=' . GETPOSTINT('date_startyear');
605 }
606 if (GETPOSTISSET('date_endmonth')) {
607 $urlzoom .= '&search_date_endmonth=' . GETPOSTINT('date_endmonth') . '&search_date_endday=' . GETPOSTINT('date_endday') . '&search_date_endyear=' . GETPOSTINT('date_endyear');
608 }
609 }
610 } else {
611 if ($line->numero_compte) {
612 $urlzoom = DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?search_accountancy_code_start=' . urlencode($line->numero_compte) . '&search_accountancy_code_end=' . urlencode($line->numero_compte);
613 if (GETPOSTISSET('date_startmonth')) {
614 $urlzoom .= '&search_date_startmonth=' . GETPOSTINT('date_startmonth') . '&search_date_startday=' . GETPOSTINT('date_startday') . '&search_date_startyear=' . GETPOSTINT('date_startyear');
615 }
616 if (GETPOSTISSET('date_endmonth')) {
617 $urlzoom .= '&search_date_endmonth=' . GETPOSTINT('date_endmonth') . '&search_date_endday=' . GETPOSTINT('date_endday') . '&search_date_endyear=' . GETPOSTINT('date_endyear');
618 }
619 }
620 }
621 // Debit
622 print '<td class="right nowraponall amount"><a href="'.$urlzoom.'">'.price(price2num($line->debit, 'MT')).'</a></td>';
623 // Credit
624 print '<td class="right nowraponall amount"><a href="'.$urlzoom.'">'.price(price2num($line->credit, 'MT')).'</a></td>';
625
626 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
627 print '<td class="right nowraponall amount">'.price(price2num($opening_balance + $line->debit - $line->credit, 'MT')).'</td>';
628 } else {
629 print '<td class="right nowraponall amount">'.price(price2num($line->debit - $line->credit, 'MT')).'</td>';
630 }
631
632 // Action column
633 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
634 print '<td class="center">';
635 print $link;
636 print '</td>';
637 }
638
639 print "</tr>\n";
640
641 // Records the sub-total
642 $sous_total_debit += $line->debit;
643 $sous_total_credit += $line->credit;
644 $sous_total_opening_balance += $opening_balance;
645 }
646
647 if (!empty($show_subgroup)) {
648 print '<tr class="liste_total">';
649 // Action column
650 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
651 print "<td></td>\n";
652 }
653 print '<td class="right">'.$langs->trans("SubTotal").':</td>';
654 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
655 print '<td class="right nowraponall amount">'.price(price2num($sous_total_opening_balance, 'MT')).'</td>';
656 }
657 print '<td class="right nowraponall amount">'.price(price2num($sous_total_debit, 'MT')).'</td>';
658 print '<td class="right nowraponall amount">'.price(price2num($sous_total_credit, 'MT')).'</td>';
659 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
660 print '<td class="right nowraponall amount">' . price(price2num($sous_total_opening_balance + $sous_total_debit - $sous_total_credit, 'MT')) . '</td>';
661 } else {
662 print '<td class="right nowraponall amount">' . price(price2num($sous_total_debit - $sous_total_credit, 'MT')) . '</td>';
663 }
664 // Action column
665 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
666 print "<td></td>\n";
667 }
668 print '</tr>';
669 }
670
671 print '<tr class="liste_total">';
672 // Action column
673 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
674 print "<td></td>\n";
675 }
676 print '<td class="right">'.$langs->trans("AccountBalance").':</td>';
677 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
678 print '<td class="nowrap right">'.price(price2num($total_opening_balance, 'MT')).'</td>';
679 }
680 print '<td class="right nowraponall amount">'.price(price2num($total_debit, 'MT')).'</td>';
681 print '<td class="right nowraponall amount">'.price(price2num($total_credit, 'MT')).'</td>';
682 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
683 print '<td class="right nowraponall amount">' . price(price2num($total_opening_balance + $total_debit - $total_credit, 'MT')) . '</td>';
684 } else {
685 print '<td class="right nowraponall amount">' . price(price2num($total_debit - $total_credit, 'MT')) . '</td>';
686 }
687 // Action column
688 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
689 print "<td></td>\n";
690 }
691 print '</tr>';
692
693 // Accounting result
694 if (getDolGlobalString('ACCOUNTING_CLOSURE_ACCOUNTING_GROUPS_USED_FOR_INCOME_STATEMENT')) {
695 print '<tr class="liste_total">';
696 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
697 print "<td></td>\n";
698 }
699 print '<td class="right">' . $langs->trans("AccountingResult") . ':</td>';
700 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
701 print '<td></td>';
702 }
703
704 $accountingResult = $object->accountingResult($search_date_start, $search_date_end);
705 if ($accountingResult < 0) {
706 $accountingResultDebit = price(abs((float) price2num($accountingResult, 'MT')));
707 $accountingResultCredit = '';
708 $accountingResultClassCSS = ' error';
709 } else {
710 $accountingResultDebit = '';
711 $accountingResultCredit = price(price2num($accountingResult, 'MT'));
712 $accountingResultClassCSS = ' green';
713 }
714 print '<td class="right nowraponall amount' . $accountingResultClassCSS . '">' . $accountingResultDebit . '</td>';
715 print '<td class="right nowraponall amount' . $accountingResultClassCSS . '">' . $accountingResultCredit . '</td>';
716
717 print '<td></td>';
718 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
719 print "<td></td>\n";
720 }
721 print '</tr>';
722 }
723
724 $parameters = array();
725 $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
726 print $hookmanager->resPrint;
727
728 print "</table>";
729 print '</form>';
730}
731
732// End of page
733llxFooter();
734$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.