dolibarr 23.0.3
accounting.lib.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com>
3 * Copyright (C) 2013-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
4 * Copyright (C) 2014 Florian Henry <florian.henry@open-concept.pro>
5 * Copyright (C) 2019 Eric Seigne <eric.seigne@cap-rel.fr>
6 * Copyright (C) 2021-2025 Frédéric France <frederic.france@free.fr>
7 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
39function is_empty($var, $allow_false = false, $allow_ws = false)
40{
41 if (is_null($var) || !isset($var) || ($allow_ws == false && trim($var) == "" && !is_bool($var)) || ($allow_false === false && $var === false) || (is_array($var) && empty($var))) {
42 return true;
43 }
44 return false;
45}
46
54{
55 global $langs, $conf;
56
57 $h = 0;
58 $head = array();
59
60 $head[$h][0] = dolBuildUrl(DOL_URL_ROOT.'/accountancy/admin/card.php', ['id' => $object->id]);
61 $head[$h][1] = $langs->trans("AccountAccounting");
62 $head[$h][2] = 'card';
63 $h++;
64
65 // Show more tabs from modules
66 // Entries must be declared in modules descriptor with line
67 // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
68 // $this->tabs = array('entity:-tabname); to remove a tab
69 complete_head_from_modules($conf, $langs, $object, $head, $h, 'accounting_account');
70
71 complete_head_from_modules($conf, $langs, $object, $head, $h, 'accounting_account', 'remove');
72
73 return $head;
74}
75
85function accounting_transaction_prepare_head(BookKeeping $object, $mode = '', $type = '', $backtopage = '/accountancy/bookkeeping/listbyaccount.php')
86{
87 global $langs, $conf;
88
89 $h = 0;
90 $head = array();
91
92 $head[$h][0] = dolBuildUrl(DOL_URL_ROOT.'/accountancy/bookkeeping/card.php', ['piece_num' => $object->piece_num, 'mode' => $mode, 'type' => $type, 'backtopage' => $backtopage]);
93 $head[$h][1] = $langs->trans("Transaction");
94 $head[$h][2] = 'transaction';
95 $h++;
96
97 // Show more tabs from modules
98 // Entries must be declared in modules descriptor with line
99 // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
100 // $this->tabs = array('entity:-tabname); to remove a tab
101 complete_head_from_modules($conf, $langs, $object, $head, $h, 'accounting_transaction');
102
103 complete_head_from_modules($conf, $langs, $object, $head, $h, 'accounting_transaction', 'remove');
104
105 return $head;
106}
107
114function clean_account($account)
115{
116 $account = rtrim($account, "0");
117
118 return $account;
119}
120
127function length_accountg($account)
128{
129 if ($account < 0 || is_empty($account)) {
130 return '';
131 }
132
133 if (getDolGlobalString('ACCOUNTING_MANAGE_ZERO')) {
134 return $account;
135 }
136
137 $g = getDolGlobalInt('ACCOUNTING_LENGTH_GACCOUNT');
138 if (!is_empty($g)) {
139 // Clean parameters
140 $i = strlen($account);
141
142 if ($i >= 1) {
143 while ($i < $g) {
144 $account .= '0';
145 $i++;
146 }
147
148 return $account;
149 } else {
150 return $account;
151 }
152 } else {
153 return $account;
154 }
155}
156
163function length_accounta($accounta)
164{
165 global $conf;
166
167 if ($accounta < 0 || is_empty($accounta)) {
168 return '';
169 }
170
171 if (getDolGlobalString('ACCOUNTING_MANAGE_ZERO')) {
172 return $accounta;
173 }
174
175 $a = getDolGlobalInt('ACCOUNTING_LENGTH_AACCOUNT');
176 if (!is_empty($a)) {
177 // Clean parameters
178 $i = strlen($accounta);
179
180 if ($i >= 1) {
181 while ($i < $a) {
182 $accounta .= '0';
183 $i++;
184 }
185
186 return $accounta;
187 } else {
188 return $accounta;
189 }
190 } else {
191 return $accounta;
192 }
193}
194
204function checkGeneralAccountAllowsAuxiliary($db, $general_account, $auxiliary_account, $general_account_id = 0)
205{
206 global $conf;
207
208 if (empty($auxiliary_account)) return true; // No check needed if no auxiliary account used
209
210 // Build SQL to get general account info based on rowid or account number
211 $sql = "SELECT rowid, account_number, centralized";
212 $sql .= " FROM ".MAIN_DB_PREFIX."accounting_account";
213 $sql .= " WHERE";
214 if ($general_account_id > 0) {
215 $sql .= " rowid = ".((int) $general_account_id);
216 } else {
217 $sql .= " account_number = '".$db->escape($general_account)."'";
218 }
219 $sql .= " AND entity = ". ((int) $conf->entity);
220 $sql .= " AND fk_pcg_version IN (SELECT pcg_version FROM ".MAIN_DB_PREFIX."accounting_system WHERE rowid = ".((int) getDolGlobalInt('CHARTOFACCOUNTS')).")";
221
222 $resql = $db->query($sql);
223 if ($resql) {
224 $obj = $db->fetch_object($resql);
225 if ($obj && empty($obj->centralized)) {
226 // Not a centralized account -> not allowed to use auxiliary
227 return false;
228 }
229 }
230
231 return true;
232}
233
250function journalHead($nom, $variant, $period, $periodlink, $description, $builddate, $exportlink = '', $moreparam = array(), $calcmode = '', $varlink = '', $moreoptions = array())
251{
252 global $langs;
253
254 print "\n\n<!-- start banner journal -->\n";
255
256 if (!is_empty($varlink)) {
257 $varlink = '?'.$varlink;
258 }
259
260 $head = array();
261 $h = 0;
262 $head[$h][0] = $_SERVER["PHP_SELF"].$varlink;
263 $head[$h][1] = $langs->trans("Journalization");
264 $head[$h][2] = 'journal';
265
266 print '<form method="POST" action="'.$_SERVER["PHP_SELF"].$varlink.'">';
267 print '<input type="hidden" name="token" value="'.newToken().'">';
268
269 print dol_get_fiche_head($head, 'journal');
270
271 foreach ($moreparam as $key => $value) {
272 print '<input type="hidden" name="'.$key.'" value="'.$value.'">';
273 }
274 print '<table class="border centpercent tableforfield">';
275
276 // Ligne de titre
277 print '<tr>';
278 print '<td class="titlefieldcreate">'.$langs->trans("Name").'</td>';
279 print '<td colspan="3">';
280 print $nom;
281 print '</td>';
282 print '</tr>';
283
284 // Calculation mode
285 if ($calcmode) {
286 print '<tr>';
287 print '<td>'.$langs->trans("CalculationMode").'</td>';
288 if (!$variant) {
289 print '<td colspan="3">';
290 } else {
291 print '<td>';
292 }
293 print $calcmode;
294 if ($variant) {
295 print '</td><td colspan="2">'.$variant;
296 }
297 print '</td>';
298 print '</tr>';
299 }
300
301 // Ligne de la periode d'analyse du rapport
302 print '<tr>';
303 print '<td>'.$langs->trans("ReportPeriod").'</td>';
304 if (!$periodlink) {
305 print '<td colspan="3">';
306 } else {
307 print '<td>';
308 }
309 if ($period) {
310 print $period;
311 }
312 if ($periodlink) {
313 print '</td><td colspan="2">'.$periodlink;
314 }
315 print '</td>';
316 print '</tr>';
317
318 // Ligne de description
319 print '<tr>';
320 print '<td>'.$langs->trans("ReportDescription").'</td>';
321 print '<td colspan="3">'.$description.'</td>';
322 print '</tr>';
323
324
325 // more options
326 foreach ($moreoptions as $key => $value) {
327 print '<tr>';
328 print '<td>'.$langs->trans($key).'</td>';
329 print '<td colspan="3">'.$value.'</td>';
330 print '</tr>';
331 }
332
333 print '</table>';
334
335 print dol_get_fiche_end();
336
337 print '<div class="center"><input type="submit" class="button" name="submit" value="'.$langs->trans("Refresh").'"></div>';
338
339 print '</form>';
340
341 print "\n<!-- end banner journal -->\n\n";
342}
343
350{
351 global $db;
352
353 $date_start = '';
354 $date_end = '';
355 $pastmonth = 0;
356 $pastmonthyear = 0;
357
358 // Period by default on transfer (0: previous month | 1: current month | 2: fiscal year)
359 $periodbydefaultontransfer = getDolGlobalInt('ACCOUNTING_DEFAULT_PERIOD_ON_TRANSFER', 0);
360 if ($periodbydefaultontransfer == 2) { // fiscal year
361 $sql = "SELECT date_start, date_end FROM ".MAIN_DB_PREFIX."accounting_fiscalyear";
362 $sql .= " WHERE date_start < '".$db->idate(dol_now())."' AND date_end > '".$db->idate(dol_now())."'";
363 $sql .= $db->plimit(1);
364 $res = $db->query($sql);
365 if ($db->num_rows($res) > 0) {
366 $obj = $db->fetch_object($res);
367
368 $date_start = $db->jdate($obj->date_start);
369 $date_end = dol_get_last_hour($db->jdate($obj->date_end));
370 } else {
371 $month_start = getDolGlobalInt('SOCIETE_FISCAL_MONTH_START', 1);
372 $year_start = (int) dol_print_date(dol_now(), '%Y');
373 if ($month_start > (int) dol_print_date(dol_now(), '%m')) {
374 $year_start -= 1;
375 }
376 $year_end = $year_start + 1;
377 $month_end = $month_start - 1;
378 if ($month_end < 1) {
379 $month_end = 12;
380 $year_end--;
381 }
382 $date_start = dol_mktime(0, 0, 0, $month_start, 1, $year_start);
383 $lastday = dol_get_last_day($year_end, $month_end);
384 $date_end = dol_mktime(23, 59, 59, $month_end, (int) dol_print_date($lastday, '%d'), $year_end);
385 }
386 } elseif ($periodbydefaultontransfer == 1) { // current month
387 $year_current = (int) dol_print_date(dol_now('gmt'), "%Y", 'gmt');
388 $pastmonth = (int) dol_print_date(dol_now('gmt'), '%m', 'gmt');
389 $pastmonthyear = $year_current;
390 if ($pastmonth == 0) {
391 $pastmonth = 12;
392 $pastmonthyear--;
393 }
394 } else { // previous month
395 $year_current = (int) dol_print_date(dol_now('gmt'), "%Y", 'gmt');
396 $pastmonth = (int) dol_print_date(dol_now('gmt'), '%m', 'gmt') - 1;
397 $pastmonthyear = $year_current;
398 if ($pastmonth == 0) {
399 $pastmonth = 12;
400 $pastmonthyear--;
401 }
402 }
403 return array(
404 'date_start' => $date_start,
405 'date_end' => $date_end,
406 'pastmonthyear' => $pastmonthyear,
407 'pastmonth' => $pastmonth
408 );
409}
410
421function getCurrentPeriodOfFiscalYear($db, $conf, $from_time = null, $gm = 'tzserver', $withenddateonly = 1)
422{
423 $now = dol_now();
424 $now_arr = dol_getdate($now);
425 if ($from_time === null) {
426 $from_time = $now;
427 } else {
428 $now_arr = dol_getdate($from_time);
429 }
430
431 include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
432
433 // Take the first period found
434 $sql = "SELECT date_start, date_end FROM ".$db->prefix()."accounting_fiscalyear";
435 $sql .= " WHERE date_start <= '".$db->idate($from_time, $gm)."'";
436 if ($withenddateonly) {
437 $sql .= " AND (date_end >= '".$db->idate($from_time, $gm)."')";
438 } else {
439 $sql .= " AND (date_end >= '".$db->idate($from_time, $gm)."' OR date_end IS NULL)";
440 }
441 //$sql .= " AND statut = 0"
442 $sql .= " AND entity IN (".getEntity('accounting_fiscalyear').")";
443 $sql .= $db->order('date_start', 'DESC');
444 $sql .= $db->plimit(1);
445
446 $res = $db->query($sql);
447
448 if ($db->num_rows($res) > 0) {
449 // If found
450 $obj = $db->fetch_object($res);
451
452 $date_start = $db->jdate($obj->date_start, $gm);
453 $date_end = dol_get_last_hour($db->jdate($obj->date_end, $gm), $gm);
454 } else {
455 // If not found, we generate a period
456 $month_start = 1;
457 $conf_fiscal_month_start = getDolGlobalInt('SOCIETE_FISCAL_MONTH_START');
458 if ($conf_fiscal_month_start >= 1 && $conf_fiscal_month_start <= 12) {
459 $month_start = $conf_fiscal_month_start;
460 }
461 $year_start = $now_arr['year'];
462 if ($conf_fiscal_month_start > $now_arr['mon']) {
463 $year_start -= 1;
464 }
465 $year_end = $year_start + 1;
466 $month_end = $month_start - 1;
467 if ($month_end < 1) {
468 $month_end = 12;
469 $year_end--;
470 }
471 $date_start = dol_mktime(0, 0, 0, $month_start, 1, $year_start, $gm);
472 $date_end = dol_get_last_day($year_end, $month_end, $gm);
473 }
474
475 return array(
476 'date_start' => $date_start,
477 'date_end' => $date_end,
478 );
479}
480
489function getNextFiscalYear($db, $after_date, $gm = 'tzserver')
490{
491 // Find the fiscal year that starts strictly after the given date
492 $sql = "SELECT date_start, date_end FROM ".$db->prefix()."accounting_fiscalyear";
493 $sql .= " WHERE date_start > '".$db->idate($after_date, $gm)."'";
494 $sql .= " AND entity IN (".getEntity('accounting_fiscalyear').")";
495 $sql .= $db->order('date_start', 'ASC'); // Get the first one (earliest)
496 $sql .= $db->plimit(1);
497
498 $res = $db->query($sql);
499
500 if ($res && $db->num_rows($res) > 0) {
501 $obj = $db->fetch_object($res);
502
503 $date_start = $db->jdate($obj->date_start, $gm);
504 $date_end = $db->jdate($obj->date_end, $gm); // Without dol_get_last_hour to avoid the bug
505
506 return array(
507 'date_start' => $date_start,
508 'date_end' => $date_end,
509 );
510 }
511
512 return null; // No next fiscal year found
513}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
accounting_transaction_prepare_head(BookKeeping $object, $mode='', $type='', $backtopage='/accountancy/bookkeeping/listbyaccount.php')
Prepare array with list of tabs for accounting transaction.
length_accountg($account)
Return General accounting account with defined length (used for product and miscellaneous)
accounting_prepare_head(AccountingAccount $object)
Prepare array with list of tabs.
getCurrentPeriodOfFiscalYear($db, $conf, $from_time=null, $gm='tzserver', $withenddateonly=1)
Get current period of fiscal year?
journalHead($nom, $variant, $period, $periodlink, $description, $builddate, $exportlink='', $moreparam=array(), $calcmode='', $varlink='', $moreoptions=array())
Show header of a page used to transfer/dispatch data in accounting.
is_empty($var, $allow_false=false, $allow_ws=false)
Check if a value is empty with some options.
getDefaultDatesForTransfer()
Return Default dates for transfer based on periodicity option in accountancy setup.
clean_account($account)
Return accounting account without zero on the right.
length_accounta($accounta)
Return Auxiliary accounting account of thirdparties with defined length.
checkGeneralAccountAllowsAuxiliary($db, $general_account, $auxiliary_account, $general_account_id=0)
Check if a general accounting account allows the use of an auxiliary account.
getNextFiscalYear($db, $after_date, $gm='tzserver')
Get next fiscal year period after a given date.
Class to manage accounting accounts.
Class to manage Ledger (General Ledger and Subledger)
dol_get_last_hour($date, $gm='tzserver')
Return GMT time for last hour of a given GMT date (it replaces hours, min and second part to 23:59:59...
Definition date.lib.php:649
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:622
dol_now($mode='gmt')
Return date for now.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
dolBuildUrl($url, $params=[], $addtoken=false)
Return path of url.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, $mode='add', $filterorigmodule='')
Complete or removed entries into a head array (used to build tabs).
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.