dolibarr 19.0.4
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 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
28require '../../main.inc.php';
29
30// Class
31require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
32require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
33require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
34require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
35require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php';
36require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancyexport.class.php';
37require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
38require_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');
46if ($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');
57if ($search_accountancy_code_start == - 1) {
58 $search_accountancy_code_start = '';
59}
60$search_accountancy_code_end = GETPOST('search_accountancy_code_end', 'alpha');
61if ($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');
71if (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;
77if ($sortorder == "") {
78 $sortorder = "ASC";
79}
80if ($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
92if (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 = getDolGlobalInt('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
119if (!isModEnabled('accounting')) {
121}
122if ($user->socid > 0) {
124}
125if (!$user->hasRight('accounting', 'mouvements', 'lire')) {
127}
128
129/*
130 * Action
131 */
132
133$param = '';
134
135$parameters = array();
136$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
137if ($reshook < 0) {
138 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
139}
140
141if (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 if (!empty($show_subgroup)) {
201 $param .= '&show_subgroup='.urlencode($show_subgroup);
202 }
203
204 // param with type of list
205 $url_param = substr($param, 1); // remove first "&"
206 if (!empty($type)) {
207 $param = '&type=' . $type . $param;
208 }
209}
210
211if ($action == 'export_csv') {
212 $sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV;
213
214 $filename = 'balance';
215 $type_export = 'balance';
216 include DOL_DOCUMENT_ROOT.'/accountancy/tpl/export_journal.tpl.php';
217
218 if ($type == 'sub') {
219 $result = $object->fetchAllBalance($sortorder, $sortfield, $limit, 0, $filter, 'AND', 1);
220 } else {
221 $result = $object->fetchAllBalance($sortorder, $sortfield, $limit, 0, $filter);
222 }
223 if ($result < 0) {
224 setEventMessages($object->error, $object->errors, 'errors');
225 }
226
227 foreach ($object->lines as $line) {
228 if ($type == 'sub') {
229 print '"' . length_accounta($line->subledger_account) . '"' . $sep;
230 print '"' . $line->subledger_label . '"' . $sep;
231 } else {
232 print '"' . length_accountg($line->numero_compte) . '"' . $sep;
233 print '"' . $object->get_compte_desc($line->numero_compte) . '"' . $sep;
234 }
235 print '"'.price($line->debit).'"'.$sep;
236 print '"'.price($line->credit).'"'.$sep;
237 print '"'.price($line->debit - $line->credit).'"'.$sep;
238 print "\n";
239 }
240
241 exit;
242}
243
244/*
245 * View
246 */
247
248if ($type == 'sub') {
249 $title_page = $langs->trans("AccountBalanceSubAccount");
250} else {
251 $title_page = $langs->trans("AccountBalance");
252}
253
254$help_url = 'EN:Module_Double_Entry_Accounting|FR:Module_Comptabilit&eacute;_en_Partie_Double';
255
256llxHeader('', $title_page, $help_url);
257
258
259if ($action != 'export_csv') {
260 // List
261 $nbtotalofrecords = '';
262 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
263 if ($type == 'sub') {
264 $nbtotalofrecords = $object->fetchAllBalance($sortorder, $sortfield, 0, 0, $filter, 'AND', 1);
265 } else {
266 $nbtotalofrecords = $object->fetchAllBalance($sortorder, $sortfield, 0, 0, $filter);
267 }
268
269 if ($nbtotalofrecords < 0) {
270 setEventMessages($object->error, $object->errors, 'errors');
271 }
272 }
273
274 if ($type == 'sub') {
275 $result = $object->fetchAllBalance($sortorder, $sortfield, $limit, $offset, $filter, 'AND', 1);
276 } else {
277 $result = $object->fetchAllBalance($sortorder, $sortfield, $limit, $offset, $filter);
278 }
279
280 if ($result < 0) {
281 setEventMessages($object->error, $object->errors, 'errors');
282 }
283
284 print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">';
285 print '<input type="hidden" name="token" value="'.newToken().'">';
286 print '<input type="hidden" name="action" id="action" value="list">';
287 if ($optioncss != '') {
288 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
289 }
290 print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
291 print '<input type="hidden" name="type" value="'.$type.'">';
292 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
293 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
294 print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
295 print '<input type="hidden" name="page" value="'.$page.'">';
296
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 $nrows = $resql->num_rows;
478 $opening_balances = array();
479 if ($resql) {
480 $nrows = $db->num_rows($resql);
481 for ($i = 0; $i < $nrows; $i++) {
482 $arr = $db->fetch_array($resql);
483 $opening_balances["'" . $arr['numero_compte'] . "'"] = $arr['opening_balance'];
484 }
485 }
486 }
487
488 foreach ($object->lines as $line) {
489 // reset before the fetch (in case of the fetch fails)
490 $accountingaccountstatic->id = 0;
491 $accountingaccountstatic->account_number = '';
492
493 if ($type != 'sub') {
494 $accountingaccountstatic->fetch(null, $line->numero_compte, true);
495 if (!empty($accountingaccountstatic->account_number)) {
496 $accounting_account = $accountingaccountstatic->getNomUrl(0, 1, 1);
497 } else {
498 $accounting_account = length_accountg($line->numero_compte);
499 }
500 }
501
502 $link = '';
503 $total_debit += $line->debit;
504 $total_credit += $line->credit;
505 $opening_balance = isset($opening_balances["'".$line->numero_compte."'"]) ? $opening_balances["'".$line->numero_compte."'"] : 0;
506 $total_opening_balance += $opening_balance;
507
508 $tmparrayforrootaccount = $object->getRootAccount($line->numero_compte);
509 $root_account_description = $tmparrayforrootaccount['label'];
510 $root_account_number = $tmparrayforrootaccount['account_number'];
511
512 //var_dump($tmparrayforrootaccount);
513 //var_dump($accounting_account);
514 //var_dump($accountingaccountstatic);
515 if (empty($accountingaccountstatic->label) && $accountingaccountstatic->id > 0) {
516 $link = '<a class="editfielda reposition" href="' . DOL_URL_ROOT . '/accountancy/admin/card.php?action=update&token=' . newToken() . '&id=' . $accountingaccountstatic->id . '">' . img_edit() . '</a>';
517 } elseif ($accounting_account == 'NotDefined') {
518 $link = '<a href="' . DOL_URL_ROOT . '/accountancy/admin/card.php?action=create&token=' . newToken() . '&accountingaccount=' . length_accountg($line->numero_compte) . '">' . img_edit_add() . '</a>';
519 } elseif (empty($tmparrayforrootaccount['label'])) {
520 // $tmparrayforrootaccount['label'] not defined = the account has not parent with a parent.
521 // This is useless, we should not create a new account when an account has no parent, we must edit it to fix its parent.
522 // 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.
523 // BUG 2: Adding a link to create a new accounting account here is useless because it is not add as parent of the orphelin.
524 //$link = '<a href="' . DOL_URL_ROOT . '/accountancy/admin/card.php?action=create&token=' . newToken() . '&accountingaccount=' . length_accountg($line->numero_compte) . '">' . img_edit_add() . '</a>';
525 }
526
527 if (!empty($show_subgroup)) {
528 // Show accounting account
529 if (empty($displayed_account) || $root_account_number != $displayed_account) {
530 // Show subtotal per accounting account
531 if ($displayed_account != "") {
532 print '<tr class="liste_total">';
533 print '<td class="right">'.$langs->trans("SubTotal").':</td>';
534 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
535 print '<td></td>';
536 }
537 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
538 print '<td class="right nowraponall amount">'.price($sous_total_opening_balance).'</td>';
539 }
540 print '<td class="right nowraponall amount">'.price($sous_total_debit).'</td>';
541 print '<td class="right nowraponall amount">'.price($sous_total_credit).'</td>';
542 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
543 print '<td class="right nowraponall amount">'.price(price2num($sous_total_opening_balance + $sous_total_debit - $sous_total_credit)).'</td>';
544 } else {
545 print '<td class="right nowraponall amount">'.price(price2num($sous_total_debit - $sous_total_credit)).'</td>';
546 }
547 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
548 print "<td></td>\n";
549 }
550 print '</tr>';
551 }
552
553 // Show first line of a break
554 print '<tr class="trforbreak">';
555 print '<td colspan="'.($colspan+1).'" class="tdforbreak">'.$root_account_number.($root_account_description ? ' - '.$root_account_description : '').'</td>';
556 print '</tr>';
557
558 $displayed_account = $root_account_number;
559 $sous_total_debit = 0;
560 $sous_total_credit = 0;
561 $sous_total_opening_balance = 0;
562 }
563 }
564
565 print '<tr class="oddeven">';
566
567 // Action column
568 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
569 print '<td class="center">';
570 print $link;
571 print '</td>';
572 }
573
574 // Accounting account
575 if ($type == 'sub') {
576 print '<td>'.$line->subledger_account.' <span class="opacitymedium">('.$line->subledger_label.')</span></td>';
577 } else {
578 print '<td>'.$accounting_account.'</td>';
579 }
580
581 // Type
582 // TODO Retrieve the type of third party: Customer / Supplier / Employee
583 //if ($type == 'sub') {
584 // print '<td></td>';
585 //}
586
587 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
588 print '<td class="right nowraponall amount">'.price(price2num($opening_balance, 'MT')).'</td>';
589 }
590
591 $urlzoom = '';
592 if ($type == 'sub') {
593 if ($line->subledger_account) {
594 $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);
595 if (GETPOSTISSET('date_startmonth')) {
596 $urlzoom .= '&search_date_startmonth=' . GETPOST('date_startmonth', 'int') . '&search_date_startday=' . GETPOST('date_startday', 'int') . '&search_date_startyear=' . GETPOST('date_startyear', 'int');
597 }
598 if (GETPOSTISSET('date_endmonth')) {
599 $urlzoom .= '&search_date_endmonth=' . GETPOST('date_endmonth', 'int') . '&search_date_endday=' . GETPOST('date_endday', 'int') . '&search_date_endyear=' . GETPOST('date_endyear', 'int');
600 }
601 }
602 } else {
603 if ($line->numero_compte) {
604 $urlzoom = DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?search_accountancy_code_start=' . urlencode($line->numero_compte) . '&search_accountancy_code_end=' . urlencode($line->numero_compte);
605 if (GETPOSTISSET('date_startmonth')) {
606 $urlzoom .= '&search_date_startmonth=' . GETPOST('date_startmonth', 'int') . '&search_date_startday=' . GETPOST('date_startday', 'int') . '&search_date_startyear=' . GETPOST('date_startyear', 'int');
607 }
608 if (GETPOSTISSET('date_endmonth')) {
609 $urlzoom .= '&search_date_endmonth=' . GETPOST('date_endmonth', 'int') . '&search_date_endday=' . GETPOST('date_endday', 'int') . '&search_date_endyear=' . GETPOST('date_endyear', 'int');
610 }
611 }
612 }
613 // Debit
614 print '<td class="right nowraponall amount"><a href="'.$urlzoom.'">'.price(price2num($line->debit, 'MT')).'</a></td>';
615 // Credit
616 print '<td class="right nowraponall amount"><a href="'.$urlzoom.'">'.price(price2num($line->credit, 'MT')).'</a></td>';
617
618 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
619 print '<td class="right nowraponall amount">'.price(price2num($opening_balance + $line->debit - $line->credit, 'MT')).'</td>';
620 } else {
621 print '<td class="right nowraponall amount">'.price(price2num($line->debit - $line->credit, 'MT')).'</td>';
622 }
623
624 // Action column
625 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
626 print '<td class="center">';
627 print $link;
628 print '</td>';
629 }
630
631 print "</tr>\n";
632
633 // Records the sub-total
634 $sous_total_debit += $line->debit;
635 $sous_total_credit += $line->credit;
636 $sous_total_opening_balance += $opening_balance;
637 }
638
639 if (!empty($show_subgroup)) {
640 print '<tr class="liste_total">';
641 // Action column
642 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
643 print "<td></td>\n";
644 }
645 print '<td class="right">'.$langs->trans("SubTotal").':</td>';
646 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
647 print '<td class="right nowraponall amount">'.price(price2num($sous_total_opening_balance, 'MT')).'</td>';
648 }
649 print '<td class="right nowraponall amount">'.price(price2num($sous_total_debit, 'MT')).'</td>';
650 print '<td class="right nowraponall amount">'.price(price2num($sous_total_credit, 'MT')).'</td>';
651 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
652 print '<td class="right nowraponall amount">' . price(price2num($sous_total_opening_balance + $sous_total_debit - $sous_total_credit, 'MT')) . '</td>';
653 } else {
654 print '<td class="right nowraponall amount">' . price(price2num($sous_total_debit - $sous_total_credit, 'MT')) . '</td>';
655 }
656 // Action column
657 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
658 print "<td></td>\n";
659 }
660 print '</tr>';
661 }
662
663 print '<tr class="liste_total">';
664 // Action column
665 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
666 print "<td></td>\n";
667 }
668 print '<td class="right">'.$langs->trans("AccountBalance").':</td>';
669 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
670 print '<td class="nowrap right">'.price(price2num($total_opening_balance, 'MT')).'</td>';
671 }
672 print '<td class="right nowraponall amount">'.price(price2num($total_debit, 'MT')).'</td>';
673 print '<td class="right nowraponall amount">'.price(price2num($total_credit, 'MT')).'</td>';
674 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
675 print '<td class="right nowraponall amount">' . price(price2num($total_opening_balance + $total_debit - $total_credit, 'MT')) . '</td>';
676 } else {
677 print '<td class="right nowraponall amount">' . price(price2num($total_debit - $total_credit, 'MT')) . '</td>';
678 }
679 // Action column
680 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
681 print "<td></td>\n";
682 }
683 print '</tr>';
684
685 $parameters = array();
686 $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
687 print $hookmanager->resPrint;
688
689 print "</table>";
690 print '</form>';
691}
692
693// End of page
694llxFooter();
695$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:55
llxFooter()
Empty footer.
Definition wrapper.php:69
Class to manage accounting accounts.
Class to manage Ledger (General Ledger and Subledger)
Class to manage generation of HTML components for accounting management.
Class to manage generation of HTML components Only common components must be here.
Classe 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
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 a Dolibarr global constant int value.
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 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.
img_edit_add($titlealt='default', $other='')
Show logo +.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
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.