dolibarr 18.0.6
balance.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2016 Olivier Geffroy <jeff@jeffinfo.com>
3 * Copyright (C) 2016 Florian Henry <florian.henry@open-concept.pro>
4 * Copyright (C) 2016-2023 Alexandre Spangaro <aspangaro@open-dsi.fr>
5 * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
27// Load Dolibarr environment
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 = ($conf->global->SOCIETE_FISCAL_MONTH_START ? ($conf->global->SOCIETE_FISCAL_MONTH_START) : 1);
104 $year_start = dol_print_date(dol_now(), '%Y');
105 if (dol_print_date(dol_now(), '%m') < $month_start) {
106 $year_start--; // If current month is lower that starting fiscal month, we start last year
107 }
108 $year_end = $year_start + 1;
109 $month_end = $month_start - 1;
110 if ($month_end < 1) {
111 $month_end = 12;
112 $year_end--;
113 }
114 $search_date_start = dol_mktime(0, 0, 0, $month_start, 1, $year_start);
115 $search_date_end = dol_get_last_day($year_end, $month_end);
116 }
117}
118
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('socid'=>$socid);
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
254llxHeader('', $title_page);
255
256
257if ($action != 'export_csv') {
258 // List
259 $nbtotalofrecords = '';
260 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
261 if ($type == 'sub') {
262 $nbtotalofrecords = $object->fetchAllBalance($sortorder, $sortfield, 0, 0, $filter, 'AND', 1);
263 } else {
264 $nbtotalofrecords = $object->fetchAllBalance($sortorder, $sortfield, 0, 0, $filter);
265 }
266
267 if ($nbtotalofrecords < 0) {
268 setEventMessages($object->error, $object->errors, 'errors');
269 }
270 }
271
272 if ($type == 'sub') {
273 $result = $object->fetchAllBalance($sortorder, $sortfield, $limit, $offset, $filter, 'AND', 1);
274 } else {
275 $result = $object->fetchAllBalance($sortorder, $sortfield, $limit, $offset, $filter);
276 }
277
278 if ($result < 0) {
279 setEventMessages($object->error, $object->errors, 'errors');
280 }
281
282 print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">';
283 print '<input type="hidden" name="token" value="'.newToken().'">';
284 print '<input type="hidden" name="action" id="action" value="list">';
285 if ($optioncss != '') {
286 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
287 }
288 print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
289 print '<input type="hidden" name="type" value="'.$type.'">';
290 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
291 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
292 print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
293 print '<input type="hidden" name="page" value="'.$page.'">';
294
295
296 $parameters = array();
297 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
298
299 if ($reshook < 0) {
300 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
301 }
302
303 $newcardbutton = empty($hookmanager->resPrint) ? '' : $hookmanager->resPrint;
304
305 if (empty($reshook)) {
306 $newcardbutton = '<input type="button" id="exportcsvbutton" name="exportcsvbutton" class="butAction" value="'.$langs->trans("Export").' ('.$conf->global->ACCOUNTING_EXPORT_FORMAT.')" />';
307
308 print '<script type="text/javascript">
309 jQuery(document).ready(function() {
310 jQuery("#exportcsvbutton").click(function(event) {
311 event.preventDefault();
312 console.log("Set action to export_csv");
313 jQuery("#action").val("export_csv");
314 jQuery("#searchFormList").submit();
315 jQuery("#action").val("list");
316 });
317 });
318 </script>';
319
320 if ($type == 'sub') {
321 $newcardbutton .= dolGetButtonTitle($langs->trans('AccountBalance')." - ".$langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/balance.php?' . $url_param, '', 1, array('morecss' => 'marginleftonly'));
322 $newcardbutton .= dolGetButtonTitle($langs->trans('AccountBalance')." - ".$langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/balance.php?type=sub&' . $url_param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected'));
323 } else {
324 $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'));
325 $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'));
326 }
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 (!empty($conf->global->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 = (!empty($conf->global->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('arrayfields'=>$arrayfields);
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 (!empty($conf->global->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('arrayfields'=>$arrayfields, '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 (!empty($conf->global->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 for ($i = 0; $i < $nrows; $i++) {
477 $arr = $resql->fetch_array();
478 $opening_balances["'" . $arr['numero_compte'] . "'"] = $arr['opening_balance'];
479 }
480 }
481
482 foreach ($object->lines as $line) {
483 // reset before the fetch (in case of the fetch fails)
484 $accountingaccountstatic->id = 0;
485 $accountingaccountstatic->account_number = '';
486
487 if ($type != 'sub') {
488 $accountingaccountstatic->fetch(null, $line->numero_compte, true);
489 if (!empty($accountingaccountstatic->account_number)) {
490 $accounting_account = $accountingaccountstatic->getNomUrl(0, 1, 1);
491 } else {
492 $accounting_account = length_accountg($line->numero_compte);
493 }
494 }
495
496 $link = '';
497 $total_debit += $line->debit;
498 $total_credit += $line->credit;
499 $opening_balance = isset($opening_balances["'".$line->numero_compte."'"]) ? $opening_balances["'".$line->numero_compte."'"] : 0;
500 $total_opening_balance += $opening_balance;
501
502 $tmparrayforrootaccount = $object->getRootAccount($line->numero_compte);
503 $root_account_description = $tmparrayforrootaccount['label'];
504 $root_account_number = $tmparrayforrootaccount['account_number'];
505
506 //var_dump($tmparrayforrootaccount);
507 //var_dump($accounting_account);
508 //var_dump($accountingaccountstatic);
509 if (empty($accountingaccountstatic->label) && $accountingaccountstatic->id > 0) {
510 $link = '<a class="editfielda reposition" href="' . DOL_URL_ROOT . '/accountancy/admin/card.php?action=update&token=' . newToken() . '&id=' . $accountingaccountstatic->id . '">' . img_edit() . '</a>';
511 } elseif ($accounting_account == 'NotDefined') {
512 $link = '<a href="' . DOL_URL_ROOT . '/accountancy/admin/card.php?action=create&token=' . newToken() . '&accountingaccount=' . length_accountg($line->numero_compte) . '">' . img_edit_add() . '</a>';
513 } elseif (empty($tmparrayforrootaccount['label'])) {
514 // $tmparrayforrootaccount['label'] not defined = the account has not parent with a parent.
515 // This is useless, we should not create a new account when an account has no parent, we must edit it to fix its parent.
516 // 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.
517 // BUG 2: Adding a link to create a new accounting account here is useless because it is not add as parent of the orphelin.
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 }
520
521 if (!empty($show_subgroup)) {
522 // Show accounting account
523 if (empty($displayed_account) || $root_account_number != $displayed_account) {
524 // Show subtotal per accounting account
525 if ($displayed_account != "") {
526 print '<tr class="liste_total">';
527 print '<td class="right">'.$langs->trans("SubTotal").':</td>';
528 if (!empty($conf->global->ACCOUNTANCY_SHOW_OPENING_BALANCE)) {
529 print '<td class="right nowraponall amount">'.price($sous_total_opening_balance).'</td>';
530 }
531 print '<td class="right nowraponall amount">'.price($sous_total_debit).'</td>';
532 print '<td class="right nowraponall amount">'.price($sous_total_credit).'</td>';
533 if (!empty($conf->global->ACCOUNTANCY_SHOW_OPENING_BALANCE)) {
534 print '<td class="right nowraponall amount">'.price(price2num($sous_total_opening_balance + $sous_total_debit - $sous_total_credit)).'</td>';
535 } else {
536 print '<td class="right nowraponall amount">'.price(price2num($sous_total_debit - $sous_total_credit)).'</td>';
537 }
538 print "<td></td>\n";
539 print '</tr>';
540 }
541
542 // Show first line of a break
543 print '<tr class="trforbreak">';
544 print '<td colspan="'.($colspan+1).'" class="tdforbreak">'.$root_account_number.($root_account_description ? ' - '.$root_account_description : '').'</td>';
545 print '</tr>';
546
547 $displayed_account = $root_account_number;
548 $sous_total_debit = 0;
549 $sous_total_credit = 0;
550 $sous_total_opening_balance = 0;
551 }
552 }
553
554 print '<tr class="oddeven">';
555
556 // Action column
557 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
558 print '<td class="center">';
559 print $link;
560 print '</td>';
561 }
562
563 // Accounting account
564 if ($type == 'sub') {
565 print '<td>'.$line->subledger_account.' <span class="opacitymedium">('.$line->subledger_label.')</span></td>';
566 } else {
567 print '<td>'.$accounting_account.'</td>';
568 }
569
570 // Type
571 // TODO Retrieve the type of third party: Customer / Supplier / Employee
572 //if ($type == 'sub') {
573 // print '<td></td>';
574 //}
575
576 if (!empty($conf->global->ACCOUNTANCY_SHOW_OPENING_BALANCE)) {
577 print '<td class="right nowraponall amount">'.price(price2num($opening_balance, 'MT')).'</td>';
578 }
579
580 $urlzoom = '';
581 if ($type == 'sub') {
582 if ($line->subledger_account) {
583 $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);
584 if (GETPOSTISSET('date_startmonth')) {
585 $urlzoom .= '&search_date_startmonth=' . GETPOST('date_startmonth', 'int') . '&search_date_startday=' . GETPOST('date_startday', 'int') . '&search_date_startyear=' . GETPOST('date_startyear', 'int');
586 }
587 if (GETPOSTISSET('date_endmonth')) {
588 $urlzoom .= '&search_date_endmonth=' . GETPOST('date_endmonth', 'int') . '&search_date_endday=' . GETPOST('date_endday', 'int') . '&search_date_endyear=' . GETPOST('date_endyear', 'int');
589 }
590 }
591 } else {
592 if ($line->numero_compte) {
593 $urlzoom = DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?search_accountancy_code_start=' . urlencode($line->numero_compte) . '&search_accountancy_code_end=' . urlencode($line->numero_compte);
594 if (GETPOSTISSET('date_startmonth')) {
595 $urlzoom .= '&search_date_startmonth=' . GETPOST('date_startmonth', 'int') . '&search_date_startday=' . GETPOST('date_startday', 'int') . '&search_date_startyear=' . GETPOST('date_startyear', 'int');
596 }
597 if (GETPOSTISSET('date_endmonth')) {
598 $urlzoom .= '&search_date_endmonth=' . GETPOST('date_endmonth', 'int') . '&search_date_endday=' . GETPOST('date_endday', 'int') . '&search_date_endyear=' . GETPOST('date_endyear', 'int');
599 }
600 }
601 }
602 // Debit
603 print '<td class="right nowraponall amount"><a href="'.$urlzoom.'">'.price(price2num($line->debit, 'MT')).'</a></td>';
604 // Credit
605 print '<td class="right nowraponall amount"><a href="'.$urlzoom.'">'.price(price2num($line->credit, 'MT')).'</a></td>';
606
607 if (!empty($conf->global->ACCOUNTANCY_SHOW_OPENING_BALANCE)) {
608 print '<td class="right nowraponall amount">'.price(price2num($opening_balance + $line->debit - $line->credit, 'MT')).'</td>';
609 } else {
610 print '<td class="right nowraponall amount">'.price(price2num($line->debit - $line->credit, 'MT')).'</td>';
611 }
612
613 // Action column
614 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
615 print '<td class="center">';
616 print $link;
617 print '</td>';
618 }
619
620 print "</tr>\n";
621
622 // Records the sub-total
623 $sous_total_debit += $line->debit;
624 $sous_total_credit += $line->credit;
625 $sous_total_opening_balance += $opening_balance;
626 }
627
628 if (!empty($show_subgroup)) {
629 print '<tr class="liste_total">';
630 // Action column
631 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
632 print "<td></td>\n";
633 }
634 print '<td class="right">'.$langs->trans("SubTotal").':</td>';
635 if (!empty($conf->global->ACCOUNTANCY_SHOW_OPENING_BALANCE)) {
636 print '<td class="right nowraponall amount">'.price(price2num($sous_total_opening_balance, 'MT')).'</td>';
637 }
638 print '<td class="right nowraponall amount">'.price(price2num($sous_total_debit, 'MT')).'</td>';
639 print '<td class="right nowraponall amount">'.price(price2num($sous_total_credit, 'MT')).'</td>';
640 if (!empty($conf->global->ACCOUNTANCY_SHOW_OPENING_BALANCE)) {
641 print '<td class="right nowraponall amount">' . price(price2num($sous_total_opening_balance + $sous_total_debit - $sous_total_credit, 'MT')) . '</td>';
642 } else {
643 print '<td class="right nowraponall amount">' . price(price2num($sous_total_debit - $sous_total_credit, 'MT')) . '</td>';
644 }
645 // Action column
646 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
647 print "<td></td>\n";
648 }
649 print '</tr>';
650 }
651
652 print '<tr class="liste_total">';
653 // Action column
654 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
655 print "<td></td>\n";
656 }
657 print '<td class="right">'.$langs->trans("AccountBalance").':</td>';
658 if (!empty($conf->global->ACCOUNTANCY_SHOW_OPENING_BALANCE)) {
659 print '<td class="nowrap right">'.price(price2num($total_opening_balance, 'MT')).'</td>';
660 }
661 print '<td class="right nowraponall amount">'.price(price2num($total_debit, 'MT')).'</td>';
662 print '<td class="right nowraponall amount">'.price(price2num($total_credit, 'MT')).'</td>';
663 if (!empty($conf->global->ACCOUNTANCY_SHOW_OPENING_BALANCE)) {
664 print '<td class="right nowraponall amount">' . price(price2num($total_opening_balance + $total_debit - $total_credit, 'MT')) . '</td>';
665 } else {
666 print '<td class="right nowraponall amount">' . price(price2num($total_debit - $total_credit, 'MT')) . '</td>';
667 }
668 // Action column
669 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
670 print "<td></td>\n";
671 }
672 print '</tr>';
673
674 $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql);
675 $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
676 print $hookmanager->resPrint;
677
678 print "</table>";
679 print '</form>';
680}
681
682// End of page
683llxFooter();
684$db->close();
length_accountg($account)
Return General accounting account with defined length (used for product and miscellaneous)
length_accounta($accounta)
Return Auxiliary accounting account of thirdparties with defined length.
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Definition wrapper.php:56
llxFooter()
Empty footer.
Definition wrapper.php:70
Class to manage accounting accounts.
Class to manage Ledger (General Ledger and Subledger)
Class to manage generation of HTML components for accounting management.
Class to manage generation of HTML components Only common components must be here.
Classe permettant la generation de composants html autre Only common components are here.
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:597
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
print_liste_field_titre($name, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $disablesortlink=0, $tooltip='', $forcenowrapcolumntitle=0)
Get title line of an array.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='')
Show information for admin users or standard users.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
print_barre_liste($titre, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $hideselectlimit=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
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.