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