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