dolibarr 21.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 <alexandre@inovea-conseil.com>
5 * Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
6 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
28// Load Dolibarr environment
29require '../../main.inc.php';
30
31// Class
32require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
33require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
34require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
35require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
36require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php';
37require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancyexport.class.php';
38require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
39require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
40
41// Load translation files required by the page
42$langs->loadLangs(array("accountancy", "compta"));
43
44$action = GETPOST('action', 'aZ09');
45$optioncss = GETPOST('optioncss', 'alpha');
46$type = GETPOST('type', 'alpha');
47if ($type == 'sub') {
48 $context_default = 'balancesubaccountlist';
49} else {
50 $context_default = 'balancelist';
51}
52$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : $context_default;
53$show_subgroup = GETPOST('show_subgroup', 'alpha');
54$search_date_start = dol_mktime(0, 0, 0, GETPOSTINT('date_startmonth'), GETPOSTINT('date_startday'), GETPOSTINT('date_startyear'));
55$search_date_end = dol_mktime(23, 59, 59, GETPOSTINT('date_endmonth'), GETPOSTINT('date_endday'), GETPOSTINT('date_endyear'));
56$search_ledger_code = GETPOST('search_ledger_code', 'array');
57$search_accountancy_code_start = GETPOST('search_accountancy_code_start', 'alpha');
58if ($search_accountancy_code_start == - 1) {
59 $search_accountancy_code_start = '';
60}
61$search_accountancy_code_end = GETPOST('search_accountancy_code_end', 'alpha');
62if ($search_accountancy_code_end == - 1) {
63 $search_accountancy_code_end = '';
64}
65$search_not_reconciled = GETPOST('search_not_reconciled', 'alpha');
66
67// Load variable for pagination
68$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
69$sortfield = GETPOST('sortfield', 'aZ09comma');
70$sortorder = GETPOST('sortorder', 'aZ09comma');
71$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
72if (empty($page) || $page == -1 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha') || (empty($toselect) && $massaction === '0')) {
73 $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;
78if ($sortorder == "") {
79 $sortorder = "ASC";
80}
81if ($sortfield == "") {
82 $sortfield = "t.numero_compte";
83}
84
85// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an 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
93if (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
120if (!isModEnabled('accounting')) {
122}
123if ($user->socid > 0) {
125}
126if (!$user->hasRight('accounting', 'mouvements', 'lire')) {
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
138if ($reshook < 0) {
139 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
140}
141
142if (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
209if ($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
247if ($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
255llxHeader('', $title_page, $help_url, '', 0, 0, '', '', '', 'mod-accountancy accountancy-consultation page-'.(($type == 'sub') ? 'sub' : '').'balance');
256
257
258if ($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
729llxFooter();
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($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
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.
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
llxFooter()
Footer empty.
Definition document.php:107
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).
print_liste_field_titre($name, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $disablesortlink=0, $tooltip='', $forcenowrapcolumntitle=0)
Get title line of an array.
dolGetButtonTitleSeparator($moreClass="")
Add space between dolGetButtonTitle.
print_barre_liste($title, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $hideselectlimit=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_edit_add($titlealt='default', $other='')
Show logo +.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='')
Show information in HTML for admin users or standard users.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.