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