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