dolibarr 19.0.3
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
201 // param with type of list
202 $url_param = substr($param, 1); // remove first "&"
203 if (!empty($type)) {
204 $param = '&type=' . $type . $param;
205 }
206}
207
208if ($action == 'export_csv') {
209 $sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV;
210
211 $filename = 'balance';
212 $type_export = 'balance';
213 include DOL_DOCUMENT_ROOT.'/accountancy/tpl/export_journal.tpl.php';
214
215 if ($type == 'sub') {
216 $result = $object->fetchAllBalance($sortorder, $sortfield, $limit, 0, $filter, 'AND', 1);
217 } else {
218 $result = $object->fetchAllBalance($sortorder, $sortfield, $limit, 0, $filter);
219 }
220 if ($result < 0) {
221 setEventMessages($object->error, $object->errors, 'errors');
222 }
223
224 foreach ($object->lines as $line) {
225 if ($type == 'sub') {
226 print '"' . length_accounta($line->subledger_account) . '"' . $sep;
227 print '"' . $line->subledger_label . '"' . $sep;
228 } else {
229 print '"' . length_accountg($line->numero_compte) . '"' . $sep;
230 print '"' . $object->get_compte_desc($line->numero_compte) . '"' . $sep;
231 }
232 print '"'.price($line->debit).'"'.$sep;
233 print '"'.price($line->credit).'"'.$sep;
234 print '"'.price($line->debit - $line->credit).'"'.$sep;
235 print "\n";
236 }
237
238 exit;
239}
240
241/*
242 * View
243 */
244
245if ($type == 'sub') {
246 $title_page = $langs->trans("AccountBalanceSubAccount");
247} else {
248 $title_page = $langs->trans("AccountBalance");
249}
250
251$help_url = 'EN:Module_Double_Entry_Accounting|FR:Module_Comptabilit&eacute;_en_Partie_Double';
252
253llxHeader('', $title_page, $help_url);
254
255
256if ($action != 'export_csv') {
257 // List
258 $nbtotalofrecords = '';
259 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
260 if ($type == 'sub') {
261 $nbtotalofrecords = $object->fetchAllBalance($sortorder, $sortfield, 0, 0, $filter, 'AND', 1);
262 } else {
263 $nbtotalofrecords = $object->fetchAllBalance($sortorder, $sortfield, 0, 0, $filter);
264 }
265
266 if ($nbtotalofrecords < 0) {
267 setEventMessages($object->error, $object->errors, 'errors');
268 }
269 }
270
271 if ($type == 'sub') {
272 $result = $object->fetchAllBalance($sortorder, $sortfield, $limit, $offset, $filter, 'AND', 1);
273 } else {
274 $result = $object->fetchAllBalance($sortorder, $sortfield, $limit, $offset, $filter);
275 }
276
277 if ($result < 0) {
278 setEventMessages($object->error, $object->errors, 'errors');
279 }
280
281 print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">';
282 print '<input type="hidden" name="token" value="'.newToken().'">';
283 print '<input type="hidden" name="action" id="action" value="list">';
284 if ($optioncss != '') {
285 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
286 }
287 print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
288 print '<input type="hidden" name="type" value="'.$type.'">';
289 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
290 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
291 print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
292 print '<input type="hidden" name="page" value="'.$page.'">';
293
294
295 $parameters = array();
296 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
297
298 if ($reshook < 0) {
299 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
300 }
301
302 $newcardbutton = empty($hookmanager->resPrint) ? '' : $hookmanager->resPrint;
303
304 if (empty($reshook)) {
305 $newcardbutton = '<input type="button" id="exportcsvbutton" name="exportcsvbutton" class="butAction" value="'.$langs->trans("Export").' (' . getDolGlobalString('ACCOUNTING_EXPORT_FORMAT').')" />';
306
307 print '<script type="text/javascript">
308 jQuery(document).ready(function() {
309 jQuery("#exportcsvbutton").click(function(event) {
310 event.preventDefault();
311 console.log("Set action to export_csv");
312 jQuery("#action").val("export_csv");
313 jQuery("#searchFormList").submit();
314 jQuery("#action").val("list");
315 });
316 });
317 </script>';
318
319 if ($type == 'sub') {
320 $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'));
321 $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'));
322 } else {
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 btnTitleSelected'));
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'));
325 }
326 $newcardbutton .= dolGetButtonTitleSeparator();
327 $newcardbutton .= dolGetButtonTitle($langs->trans('NewAccountingMvt'), '', 'fa fa-plus-circle paddingleft', DOL_URL_ROOT.'/accountancy/bookkeeping/card.php?action=create');
328 }
329 if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
330 $param .= '&contextpage='.urlencode($contextpage);
331 }
332 if ($limit > 0 && $limit != $conf->liste_limit) {
333 $param .= '&limit='.((int) $limit);
334 }
335
336 print_barre_liste($title_page, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $result, $nbtotalofrecords, 'title_accountancy', 0, $newcardbutton, '', $limit, 0, 0, 1);
337
338 $selectedfields = '';
339
340 // Warning to explain why list of record is not consistent with the other list view (missing a lot of lines)
341 if ($type == 'sub') {
342 print info_admin($langs->trans("WarningRecordWithoutSubledgerAreExcluded"));
343 }
344
345 $moreforfilter = '';
346
347 $moreforfilter .= '<div class="divsearchfield">';
348 $moreforfilter .= $langs->trans('DateStart').': ';
349 $moreforfilter .= $form->selectDate($search_date_start ? $search_date_start : -1, 'date_start', 0, 0, 1, '', 1, 0);
350 $moreforfilter .= $langs->trans('DateEnd').': ';
351 $moreforfilter .= $form->selectDate($search_date_end ? $search_date_end : -1, 'date_end', 0, 0, 1, '', 1, 0);
352 $moreforfilter .= '</div>';
353
354 $moreforfilter .= '<div class="divsearchfield">';
355 $moreforfilter .= '<label for="show_subgroup">'.$langs->trans('ShowSubtotalByGroup').'</label>: ';
356 $moreforfilter .= '<input type="checkbox" name="show_subgroup" id="show_subgroup" value="show_subgroup"'.($show_subgroup == 'show_subgroup' ? ' checked' : '').'>';
357 $moreforfilter .= '</div>';
358
359 $moreforfilter .= '<div class="divsearchfield">';
360 $moreforfilter .= $langs->trans("Journals").': ';
361 $moreforfilter .= $formaccounting->multi_select_journal($search_ledger_code, 'search_ledger_code', 0, 1, 1, 1);
362 $moreforfilter .= '</div>';
363
364 //$moreforfilter .= '<br>';
365 $moreforfilter .= '<div class="divsearchfield">';
366 // Accountancy account
367 $moreforfilter .= $langs->trans('AccountAccounting').': ';
368 if ($type == 'sub') {
369 $moreforfilter .= $formaccounting->select_auxaccount($search_accountancy_code_start, 'search_accountancy_code_start', $langs->trans('From'), 'maxwidth200');
370 } else {
371 $moreforfilter .= $formaccounting->select_account($search_accountancy_code_start, 'search_accountancy_code_start', $langs->trans('From'), array(), 1, 1, 'maxwidth200', 'accounts');
372 }
373 $moreforfilter .= ' ';
374 if ($type == 'sub') {
375 $moreforfilter .= $formaccounting->select_auxaccount($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), 'maxwidth200');
376 } else {
377 $moreforfilter .= $formaccounting->select_account($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), array(), 1, 1, 'maxwidth200', 'accounts');
378 }
379 $moreforfilter .= '</div>';
380
381 if (getDolGlobalString('ACCOUNTING_ENABLE_LETTERING')) {
382 $moreforfilter .= '<div class="divsearchfield">';
383 $moreforfilter .= '<label for="notreconciled">'.$langs->trans('NotReconciled').'</label>: ';
384 $moreforfilter .= '<input type="checkbox" name="search_not_reconciled" id="notreconciled" value="notreconciled"'.($search_not_reconciled == 'notreconciled' ? ' checked' : '').'>';
385 $moreforfilter .= '</div>';
386 }
387
388 if (!empty($moreforfilter)) {
389 print '<div class="liste_titre liste_titre_bydiv centpercent">';
390 print $moreforfilter;
391 $parameters = array();
392 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook
393 print $hookmanager->resPrint;
394 print '</div>';
395 }
396
397
398 $colspan = (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE') ? 5 : 4);
399
400 print '<table class="liste '.($moreforfilter ? "listwithfilterbefore" : "").'">';
401
402 print '<tr class="liste_titre_filter">';
403
404 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
405 print '<td class="liste_titre maxwidthsearch">';
406 $searchpicto = $form->showFilterButtons();
407 print $searchpicto;
408 print '</td>';
409 }
410
411 print '<td class="liste_titre" colspan="'.$colspan.'">';
412 print '</td>';
413
414 // Fields from hook
415 $parameters = array();
416 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook
417 print $hookmanager->resPrint;
418
419 // Action column
420 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
421 print '<td class="liste_titre maxwidthsearch">';
422 $searchpicto = $form->showFilterButtons();
423 print $searchpicto;
424 print '</td>';
425 }
426 print '</tr>'."\n";
427
428 print '<tr class="liste_titre">';
429 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
430 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
431 }
432 print_liste_field_titre("AccountAccounting", $_SERVER['PHP_SELF'], "t.numero_compte", "", $param, "", $sortfield, $sortorder);
433 // TODO : Retrieve the type of third party: Customer / Supplier / Employee
434 //if ($type == 'sub') {
435 // print_liste_field_titre("Type", $_SERVER['PHP_SELF'], "t.type", "", $param, "", $sortfield, $sortorder);
436 //}
437 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
438 print_liste_field_titre("OpeningBalance", $_SERVER['PHP_SELF'], "", $param, "", 'class="right"', $sortfield, $sortorder);
439 }
440 print_liste_field_titre("AccountingDebit", $_SERVER['PHP_SELF'], "t.debit", "", $param, 'class="right"', $sortfield, $sortorder);
441 print_liste_field_titre("AccountingCredit", $_SERVER['PHP_SELF'], "t.credit", "", $param, 'class="right"', $sortfield, $sortorder);
442 print_liste_field_titre("Balance", $_SERVER["PHP_SELF"], "", $param, "", 'class="right"', $sortfield, $sortorder);
443
444 // Hook fields
445 $parameters = array('param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder);
446 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook
447 print $hookmanager->resPrint;
448 // Action column
449 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
450 print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
451 }
452 print '</tr>'."\n";
453
454 $total_debit = 0;
455 $total_credit = 0;
456 $sous_total_debit = 0;
457 $sous_total_credit = 0;
458 $total_opening_balance = 0;
459 $sous_total_opening_balance = 0;
460 $displayed_account = "";
461
462 $accountingaccountstatic = new AccountingAccount($db);
463
464 // TODO Debug - This feature is dangerous, it takes all the entries and adds all the accounts
465 // without time and class limits (Class 6 and 7 accounts ???) and does not take into account the "a-nouveau" journal.
466 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
467 $sql = "SELECT t.numero_compte, (SUM(t.debit) - SUM(t.credit)) as opening_balance";
468 $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as t";
469 $sql .= " WHERE t.entity = " . $conf->entity; // Never do sharing into accounting features
470 $sql .= " AND t.doc_date < '" . $db->idate($search_date_start) . "'";
471 $sql .= " GROUP BY t.numero_compte";
472
473 $resql = $db->query($sql);
474 $nrows = $resql->num_rows;
475 $opening_balances = array();
476 if ($resql) {
477 $nrows = $db->num_rows($resql);
478 for ($i = 0; $i < $nrows; $i++) {
479 $arr = $db->fetch_array($resql);
480 $opening_balances["'" . $arr['numero_compte'] . "'"] = $arr['opening_balance'];
481 }
482 }
483 }
484
485 foreach ($object->lines as $line) {
486 // reset before the fetch (in case of the fetch fails)
487 $accountingaccountstatic->id = 0;
488 $accountingaccountstatic->account_number = '';
489
490 if ($type != 'sub') {
491 $accountingaccountstatic->fetch(null, $line->numero_compte, true);
492 if (!empty($accountingaccountstatic->account_number)) {
493 $accounting_account = $accountingaccountstatic->getNomUrl(0, 1, 1);
494 } else {
495 $accounting_account = length_accountg($line->numero_compte);
496 }
497 }
498
499 $link = '';
500 $total_debit += $line->debit;
501 $total_credit += $line->credit;
502 $opening_balance = isset($opening_balances["'".$line->numero_compte."'"]) ? $opening_balances["'".$line->numero_compte."'"] : 0;
503 $total_opening_balance += $opening_balance;
504
505 $tmparrayforrootaccount = $object->getRootAccount($line->numero_compte);
506 $root_account_description = $tmparrayforrootaccount['label'];
507 $root_account_number = $tmparrayforrootaccount['account_number'];
508
509 //var_dump($tmparrayforrootaccount);
510 //var_dump($accounting_account);
511 //var_dump($accountingaccountstatic);
512 if (empty($accountingaccountstatic->label) && $accountingaccountstatic->id > 0) {
513 $link = '<a class="editfielda reposition" href="' . DOL_URL_ROOT . '/accountancy/admin/card.php?action=update&token=' . newToken() . '&id=' . $accountingaccountstatic->id . '">' . img_edit() . '</a>';
514 } elseif ($accounting_account == 'NotDefined') {
515 $link = '<a href="' . DOL_URL_ROOT . '/accountancy/admin/card.php?action=create&token=' . newToken() . '&accountingaccount=' . length_accountg($line->numero_compte) . '">' . img_edit_add() . '</a>';
516 } elseif (empty($tmparrayforrootaccount['label'])) {
517 // $tmparrayforrootaccount['label'] not defined = the account has not parent with a parent.
518 // This is useless, we should not create a new account when an account has no parent, we must edit it to fix its parent.
519 // 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.
520 // BUG 2: Adding a link to create a new accounting account here is useless because it is not add as parent of the orphelin.
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 }
523
524 if (!empty($show_subgroup)) {
525 // Show accounting account
526 if (empty($displayed_account) || $root_account_number != $displayed_account) {
527 // Show subtotal per accounting account
528 if ($displayed_account != "") {
529 print '<tr class="liste_total">';
530 print '<td class="right">'.$langs->trans("SubTotal").':</td>';
531 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
532 print '<td></td>';
533 }
534 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
535 print '<td class="right nowraponall amount">'.price($sous_total_opening_balance).'</td>';
536 }
537 print '<td class="right nowraponall amount">'.price($sous_total_debit).'</td>';
538 print '<td class="right nowraponall amount">'.price($sous_total_credit).'</td>';
539 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
540 print '<td class="right nowraponall amount">'.price(price2num($sous_total_opening_balance + $sous_total_debit - $sous_total_credit)).'</td>';
541 } else {
542 print '<td class="right nowraponall amount">'.price(price2num($sous_total_debit - $sous_total_credit)).'</td>';
543 }
544 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
545 print "<td></td>\n";
546 }
547 print '</tr>';
548 }
549
550 // Show first line of a break
551 print '<tr class="trforbreak">';
552 print '<td colspan="'.($colspan+1).'" class="tdforbreak">'.$root_account_number.($root_account_description ? ' - '.$root_account_description : '').'</td>';
553 print '</tr>';
554
555 $displayed_account = $root_account_number;
556 $sous_total_debit = 0;
557 $sous_total_credit = 0;
558 $sous_total_opening_balance = 0;
559 }
560 }
561
562 print '<tr class="oddeven">';
563
564 // Action column
565 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
566 print '<td class="center">';
567 print $link;
568 print '</td>';
569 }
570
571 // Accounting account
572 if ($type == 'sub') {
573 print '<td>'.$line->subledger_account.' <span class="opacitymedium">('.$line->subledger_label.')</span></td>';
574 } else {
575 print '<td>'.$accounting_account.'</td>';
576 }
577
578 // Type
579 // TODO Retrieve the type of third party: Customer / Supplier / Employee
580 //if ($type == 'sub') {
581 // print '<td></td>';
582 //}
583
584 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
585 print '<td class="right nowraponall amount">'.price(price2num($opening_balance, 'MT')).'</td>';
586 }
587
588 $urlzoom = '';
589 if ($type == 'sub') {
590 if ($line->subledger_account) {
591 $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);
592 if (GETPOSTISSET('date_startmonth')) {
593 $urlzoom .= '&search_date_startmonth=' . GETPOST('date_startmonth', 'int') . '&search_date_startday=' . GETPOST('date_startday', 'int') . '&search_date_startyear=' . GETPOST('date_startyear', 'int');
594 }
595 if (GETPOSTISSET('date_endmonth')) {
596 $urlzoom .= '&search_date_endmonth=' . GETPOST('date_endmonth', 'int') . '&search_date_endday=' . GETPOST('date_endday', 'int') . '&search_date_endyear=' . GETPOST('date_endyear', 'int');
597 }
598 }
599 } else {
600 if ($line->numero_compte) {
601 $urlzoom = DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?search_accountancy_code_start=' . urlencode($line->numero_compte) . '&search_accountancy_code_end=' . urlencode($line->numero_compte);
602 if (GETPOSTISSET('date_startmonth')) {
603 $urlzoom .= '&search_date_startmonth=' . GETPOST('date_startmonth', 'int') . '&search_date_startday=' . GETPOST('date_startday', 'int') . '&search_date_startyear=' . GETPOST('date_startyear', 'int');
604 }
605 if (GETPOSTISSET('date_endmonth')) {
606 $urlzoom .= '&search_date_endmonth=' . GETPOST('date_endmonth', 'int') . '&search_date_endday=' . GETPOST('date_endday', 'int') . '&search_date_endyear=' . GETPOST('date_endyear', 'int');
607 }
608 }
609 }
610 // Debit
611 print '<td class="right nowraponall amount"><a href="'.$urlzoom.'">'.price(price2num($line->debit, 'MT')).'</a></td>';
612 // Credit
613 print '<td class="right nowraponall amount"><a href="'.$urlzoom.'">'.price(price2num($line->credit, 'MT')).'</a></td>';
614
615 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
616 print '<td class="right nowraponall amount">'.price(price2num($opening_balance + $line->debit - $line->credit, 'MT')).'</td>';
617 } else {
618 print '<td class="right nowraponall amount">'.price(price2num($line->debit - $line->credit, 'MT')).'</td>';
619 }
620
621 // Action column
622 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
623 print '<td class="center">';
624 print $link;
625 print '</td>';
626 }
627
628 print "</tr>\n";
629
630 // Records the sub-total
631 $sous_total_debit += $line->debit;
632 $sous_total_credit += $line->credit;
633 $sous_total_opening_balance += $opening_balance;
634 }
635
636 if (!empty($show_subgroup)) {
637 print '<tr class="liste_total">';
638 // Action column
639 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
640 print "<td></td>\n";
641 }
642 print '<td class="right">'.$langs->trans("SubTotal").':</td>';
643 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
644 print '<td class="right nowraponall amount">'.price(price2num($sous_total_opening_balance, 'MT')).'</td>';
645 }
646 print '<td class="right nowraponall amount">'.price(price2num($sous_total_debit, 'MT')).'</td>';
647 print '<td class="right nowraponall amount">'.price(price2num($sous_total_credit, 'MT')).'</td>';
648 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
649 print '<td class="right nowraponall amount">' . price(price2num($sous_total_opening_balance + $sous_total_debit - $sous_total_credit, 'MT')) . '</td>';
650 } else {
651 print '<td class="right nowraponall amount">' . price(price2num($sous_total_debit - $sous_total_credit, 'MT')) . '</td>';
652 }
653 // Action column
654 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
655 print "<td></td>\n";
656 }
657 print '</tr>';
658 }
659
660 print '<tr class="liste_total">';
661 // Action column
662 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
663 print "<td></td>\n";
664 }
665 print '<td class="right">'.$langs->trans("AccountBalance").':</td>';
666 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
667 print '<td class="nowrap right">'.price(price2num($total_opening_balance, 'MT')).'</td>';
668 }
669 print '<td class="right nowraponall amount">'.price(price2num($total_debit, 'MT')).'</td>';
670 print '<td class="right nowraponall amount">'.price(price2num($total_credit, 'MT')).'</td>';
671 if (getDolGlobalString('ACCOUNTANCY_SHOW_OPENING_BALANCE')) {
672 print '<td class="right nowraponall amount">' . price(price2num($total_opening_balance + $total_debit - $total_credit, 'MT')) . '</td>';
673 } else {
674 print '<td class="right nowraponall amount">' . price(price2num($total_debit - $total_credit, 'MT')) . '</td>';
675 }
676 // Action column
677 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
678 print "<td></td>\n";
679 }
680 print '</tr>';
681
682 $parameters = array();
683 $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
684 print $hookmanager->resPrint;
685
686 print "</table>";
687 print '</form>';
688}
689
690// End of page
691llxFooter();
692$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.