dolibarr 20.0.5
expensereportsjournal.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2007-2010 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2007-2010 Jean Heimburger <jean@tiaris.info>
4 * Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es>
5 * Copyright (C) 2012 Regis Houssin <regis.houssin@inodbox.com>
6 * Copyright (C) 2013-2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
7 * Copyright (C) 2013-2016 Olivier Geffroy <jeff@jeffinfo.com>
8 * Copyright (C) 2013-2016 Florian Henry <florian.henry@open-concept.pro>
9 * Copyright (C) 2018 Frédéric France <frederic.france@free.fr>
10 * Copyright (C) 2018 Eric Seigne <eric.seigne@cap-rel.fr>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <https://www.gnu.org/licenses/>.
24 */
25
31require '../../main.inc.php';
32require_once DOL_DOCUMENT_ROOT.'/core/lib/report.lib.php';
33require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
34require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
35require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
36require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php';
37require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
38require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
39require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
40
41// Load translation files required by the page
42$langs->loadLangs(array("commercial", "compta", "bills", "other", "accountancy", "trips", "errors"));
43
44$id_journal = GETPOSTINT('id_journal');
45$action = GETPOST('action', 'aZ09');
46
47$date_startmonth = GETPOST('date_startmonth');
48$date_startday = GETPOST('date_startday');
49$date_startyear = GETPOST('date_startyear');
50$date_endmonth = GETPOST('date_endmonth');
51$date_endday = GETPOST('date_endday');
52$date_endyear = GETPOST('date_endyear');
53$in_bookkeeping = GETPOST('in_bookkeeping');
54if ($in_bookkeeping == '') {
55 $in_bookkeeping = 'notyet';
56}
57
58$now = dol_now();
59
60$hookmanager->initHooks(array('expensereportsjournal'));
61$parameters = array();
62
63// Security check
64if (!isModEnabled('accounting')) {
66}
67if ($user->socid > 0) {
69}
70if (!$user->hasRight('accounting', 'bind', 'write')) {
72}
73
74$error = 0;
75$errorforinvoice = array();
76
77
78/*
79 * Actions
80 */
81
82$accountingaccount = new AccountingAccount($db);
83
84// Get information of journal
85$accountingjournalstatic = new AccountingJournal($db);
86$accountingjournalstatic->fetch($id_journal);
87$journal = $accountingjournalstatic->code;
88$journal_label = $accountingjournalstatic->label;
89
90$date_start = dol_mktime(0, 0, 0, $date_startmonth, $date_startday, $date_startyear);
91$date_end = dol_mktime(23, 59, 59, $date_endmonth, $date_endday, $date_endyear);
92
93if (empty($date_startmonth)) {
94 // Period by default on transfer
96 $date_start = $dates['date_start'];
97 $pastmonthyear = $dates['pastmonthyear'];
98 $pastmonth = $dates['pastmonth'];
99}
100if (empty($date_endmonth)) {
101 // Period by default on transfer
103 $date_end = $dates['date_end'];
104 $pastmonthyear = $dates['pastmonthyear'];
105 $pastmonth = $dates['pastmonth'];
106}
107
108if (!GETPOSTISSET('date_startmonth') && (empty($date_start) || empty($date_end))) { // We define date_start and date_end, only if we did not submit the form
109 $date_start = dol_get_first_day($pastmonthyear, $pastmonth, false);
110 $date_end = dol_get_last_day($pastmonthyear, $pastmonth, false);
111}
112
113$sql = "SELECT er.rowid, er.ref, er.date_debut as de, er.date_fin as df,";
114$sql .= " erd.rowid as erdid, erd.comments, erd.total_ht, erd.total_tva, erd.total_localtax1, erd.total_localtax2, erd.tva_tx, erd.total_ttc, erd.fk_code_ventilation, erd.vat_src_code, ";
115$sql .= " u.rowid as uid, u.firstname, u.lastname, u.accountancy_code as user_accountancy_account,";
116$sql .= " f.accountancy_code, aa.rowid as fk_compte, aa.account_number as compte, aa.label as label_compte";
117$parameters = array();
118$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook
119$sql .= $hookmanager->resPrint;
120$sql .= " FROM ".MAIN_DB_PREFIX."expensereport_det as erd";
121$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_type_fees as f ON f.id = erd.fk_c_type_fees";
122$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.rowid = erd.fk_code_ventilation";
123$sql .= " JOIN ".MAIN_DB_PREFIX."expensereport as er ON er.rowid = erd.fk_expensereport";
124$sql .= " JOIN ".MAIN_DB_PREFIX."user as u ON u.rowid = er.fk_user_author";
125$parameters = array();
126$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters); // Note that $action and $object may have been modified by hook
127$sql .= $hookmanager->resPrint;
128$sql .= " WHERE er.fk_statut > 0";
129$sql .= " AND erd.fk_code_ventilation > 0";
130$sql .= " AND er.entity IN (".getEntity('expensereport', 0).")"; // We don't share object for accountancy
131if ($date_start && $date_end) {
132 $sql .= " AND er.date_debut >= '".$db->idate($date_start)."' AND er.date_debut <= '".$db->idate($date_end)."'";
133}
134// Define begin binding date
135if (getDolGlobalString('ACCOUNTING_DATE_START_BINDING')) {
136 $sql .= " AND er.date_debut >= '".$db->idate(getDolGlobalString('ACCOUNTING_DATE_START_BINDING'))."'";
137}
138// Already in bookkeeping or not
139if ($in_bookkeeping == 'already') {
140 $sql .= " AND er.rowid IN (SELECT fk_doc FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type='expense_report')";
141}
142if ($in_bookkeeping == 'notyet') {
143 $sql .= " AND er.rowid NOT IN (SELECT fk_doc FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab WHERE ab.doc_type='expense_report')";
144}
145$parameters = array();
146$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook
147$sql .= $hookmanager->resPrint;
148$sql .= " ORDER BY er.date_debut";
149
150dol_syslog('accountancy/journal/expensereportsjournal.php', LOG_DEBUG);
151$result = $db->query($sql);
152if ($result) {
153 $taber = array();
154 $tabht = array();
155 $tabtva = array();
156 $def_tva = array();
157 $tabttc = array();
158 $tablocaltax1 = array();
159 $tablocaltax2 = array();
160 $tabuser = array();
161
162 $num = $db->num_rows($result);
163
164 // Variables
165 $account_salary = getDolGlobalString('ACCOUNTING_ACCOUNT_EXPENSEREPORT', 'NotDefined');
166 $account_vat = getDolGlobalString('ACCOUNTING_VAT_BUY_ACCOUNT', 'NotDefined');
167
168 $i = 0;
169 while ($i < $num) {
170 $obj = $db->fetch_object($result);
171
172 // Controls
173 $compta_user = (!empty($obj->user_accountancy_account)) ? $obj->user_accountancy_account : $account_salary;
174 $compta_fees = $obj->compte;
175
176 $vatdata = getTaxesFromId($obj->tva_tx.($obj->vat_src_code ? ' ('.$obj->vat_src_code.')' : ''), $mysoc, $mysoc, 0);
177 $compta_tva = (!empty($vatdata['accountancy_code_buy']) ? $vatdata['accountancy_code_buy'] : $account_vat);
178 $compta_localtax1 = (!empty($vatdata['accountancy_code_buy']) ? $vatdata['accountancy_code_buy'] : $account_vat);
179 $compta_localtax2 = (!empty($vatdata['accountancy_code_buy']) ? $vatdata['accountancy_code_buy'] : $account_vat);
180
181 // Define array to display all VAT rates that use this accounting account $compta_tva
182 if (price2num($obj->tva_tx) || !empty($obj->vat_src_code)) {
183 $def_tva[$obj->rowid][$compta_tva][vatrate($obj->tva_tx).($obj->vat_src_code ? ' ('.$obj->vat_src_code.')' : '')] = (vatrate($obj->tva_tx).($obj->vat_src_code ? ' ('.$obj->vat_src_code.')' : ''));
184 }
185
186 if (getDolGlobalInt('ACCOUNTANCY_ER_DATE_RECORD')) {
187 $taber[$obj->rowid]["date"] = $db->jdate($obj->df);
188 } else {
189 $taber[$obj->rowid]["date"] = $db->jdate($obj->de);
190 }
191 $taber[$obj->rowid]["ref"] = $obj->ref;
192 $taber[$obj->rowid]["comments"] = $obj->comments;
193 $taber[$obj->rowid]["fk_expensereportdet"] = $obj->erdid;
194
195 // Avoid warnings
196 if (!isset($tabttc[$obj->rowid][$compta_user])) {
197 $tabttc[$obj->rowid][$compta_user] = 0;
198 }
199 if (!isset($tabht[$obj->rowid][$compta_fees])) {
200 $tabht[$obj->rowid][$compta_fees] = 0;
201 }
202 if (!isset($tabtva[$obj->rowid][$compta_tva])) {
203 $tabtva[$obj->rowid][$compta_tva] = 0;
204 }
205 if (!isset($tablocaltax1[$obj->rowid][$compta_localtax1])) {
206 $tablocaltax1[$obj->rowid][$compta_localtax1] = 0;
207 }
208 if (!isset($tablocaltax2[$obj->rowid][$compta_localtax2])) {
209 $tablocaltax2[$obj->rowid][$compta_localtax2] = 0;
210 }
211
212 $tabttc[$obj->rowid][$compta_user] += $obj->total_ttc;
213 $tabht[$obj->rowid][$compta_fees] += $obj->total_ht;
214 $tabtva[$obj->rowid][$compta_tva] += $obj->total_tva;
215 $tablocaltax1[$obj->rowid][$compta_localtax1] += $obj->total_localtax1;
216 $tablocaltax2[$obj->rowid][$compta_localtax2] += $obj->total_localtax2;
217 $tabuser[$obj->rowid] = array(
218 'id' => $obj->uid,
219 'name' => dolGetFirstLastname($obj->firstname, $obj->lastname),
220 'user_accountancy_code' => $obj->user_accountancy_account
221 );
222
223 $i++;
224 }
225} else {
226 dol_print_error($db);
227}
228
229// Load all unbound lines
230$sql = "SELECT fk_expensereport, COUNT(erd.rowid) as nb";
231$sql .= " FROM ".MAIN_DB_PREFIX."expensereport_det as erd";
232$sql .= " WHERE erd.fk_code_ventilation <= 0";
233$sql .= " AND erd.total_ttc <> 0";
234$sql .= " AND fk_expensereport IN (".$db->sanitize(implode(",", array_keys($taber))).")";
235$sql .= " GROUP BY fk_expensereport";
236$resql = $db->query($sql);
237
238$num = $db->num_rows($resql);
239$i = 0;
240while ($i < $num) {
241 $obj = $db->fetch_object($resql);
242 if ($obj->nb > 0) {
243 $errorforinvoice[$obj->fk_expensereport] = 'somelinesarenotbound';
244 }
245 $i++;
246}
247
248// Bookkeeping Write
249if ($action == 'writebookkeeping' && !$error && $user->hasRight('accounting', 'bind', 'write')) {
250 $now = dol_now();
251 $error = 0;
252
253 $accountingaccountexpense = new AccountingAccount($db);
254 $accountingaccountexpense->fetch(null, getDolGlobalString('ACCOUNTING_ACCOUNT_EXPENSEREPORT'), true);
255
256 foreach ($taber as $key => $val) { // Loop on each expense report
257 $errorforline = 0;
258
259 $totalcredit = 0;
260 $totaldebit = 0;
261
262 $db->begin();
263
264 // Error if some lines are not binded/ready to be journalized
265 if (!empty($errorforinvoice[$key]) && $errorforinvoice[$key] == 'somelinesarenotbound') {
266 $error++;
267 $errorforline++;
268 setEventMessages($langs->trans('ErrorInvoiceContainsLinesNotYetBounded', $val['ref']), null, 'errors');
269 }
270
271 // Thirdparty
272 if (!$errorforline) {
273 foreach ($tabttc[$key] as $k => $mt) {
274 if ($mt) {
275 $bookkeeping = new BookKeeping($db);
276 $bookkeeping->doc_date = $val["date"];
277 $bookkeeping->doc_ref = $val["ref"];
278 $bookkeeping->date_creation = $now;
279 $bookkeeping->doc_type = 'expense_report';
280 $bookkeeping->fk_doc = $key;
281 $bookkeeping->fk_docdet = $val["fk_expensereportdet"];
282
283 $bookkeeping->subledger_account = $tabuser[$key]['user_accountancy_code'];
284 $bookkeeping->subledger_label = $tabuser[$key]['name'];
285
286 $bookkeeping->numero_compte = getDolGlobalString('ACCOUNTING_ACCOUNT_EXPENSEREPORT');
287 $bookkeeping->label_compte = $accountingaccountexpense->label;
288
289 $bookkeeping->label_operation = $tabuser[$key]['name'];
290 $bookkeeping->montant = $mt;
291 $bookkeeping->sens = ($mt >= 0) ? 'C' : 'D';
292 $bookkeeping->debit = ($mt <= 0) ? -$mt : 0;
293 $bookkeeping->credit = ($mt > 0) ? $mt : 0;
294 $bookkeeping->code_journal = $journal;
295 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
296 $bookkeeping->fk_user_author = $user->id;
297 $bookkeeping->entity = $conf->entity;
298
299 $totaldebit += $bookkeeping->debit;
300 $totalcredit += $bookkeeping->credit;
301
302 $result = $bookkeeping->create($user);
303 if ($result < 0) {
304 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
305 $error++;
306 $errorforline++;
307 $errorforinvoice[$key] = 'alreadyjournalized';
308 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
309 } else {
310 $error++;
311 $errorforline++;
312 $errorforinvoice[$key] = 'other';
313 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
314 }
315 }
316 }
317 }
318 }
319
320 // Fees
321 if (!$errorforline) {
322 foreach ($tabht[$key] as $k => $mt) {
323 if ($mt) {
324 if (empty($conf->cache['accountingaccountincurrententity'][$k])) {
325 $accountingaccount = new AccountingAccount($db);
326 $accountingaccount->fetch(0, $k, true);
327 $conf->cache['accountingaccountincurrententity'][$k] = $accountingaccount;
328 } else {
329 $accountingaccount = $conf->cache['accountingaccountincurrententity'][$k];
330 }
331
332 $account_label = $accountingaccount->label;
333
334 // get compte id and label
335 if ($accountingaccount->fetch(null, $k, true)) {
336 $bookkeeping = new BookKeeping($db);
337 $bookkeeping->doc_date = $val["date"];
338 $bookkeeping->doc_ref = $val["ref"];
339 $bookkeeping->date_creation = $now;
340 $bookkeeping->doc_type = 'expense_report';
341 $bookkeeping->fk_doc = $key;
342 $bookkeeping->fk_docdet = $val["fk_expensereportdet"];
343
344 $bookkeeping->subledger_account = '';
345 $bookkeeping->subledger_label = '';
346
347 $bookkeeping->numero_compte = $k;
348 $bookkeeping->label_compte = $account_label;
349
350 $bookkeeping->label_operation = $account_label;
351 $bookkeeping->montant = $mt;
352 $bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
353 $bookkeeping->debit = ($mt > 0) ? $mt : 0;
354 $bookkeeping->credit = ($mt <= 0) ? -$mt : 0;
355 $bookkeeping->code_journal = $journal;
356 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
357 $bookkeeping->fk_user_author = $user->id;
358 $bookkeeping->entity = $conf->entity;
359
360 $totaldebit += $bookkeeping->debit;
361 $totalcredit += $bookkeeping->credit;
362
363 $result = $bookkeeping->create($user);
364 if ($result < 0) {
365 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
366 $error++;
367 $errorforline++;
368 $errorforinvoice[$key] = 'alreadyjournalized';
369 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
370 } else {
371 $error++;
372 $errorforline++;
373 $errorforinvoice[$key] = 'other';
374 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
375 }
376 }
377 }
378 }
379 }
380 }
381
382 // VAT
383 if (!$errorforline) {
384 $listoftax = array(0, 1, 2);
385 foreach ($listoftax as $numtax) {
386 $arrayofvat = $tabtva;
387 if ($numtax == 1) {
388 $arrayofvat = $tablocaltax1;
389 }
390 if ($numtax == 2) {
391 $arrayofvat = $tablocaltax2;
392 }
393
394 foreach ($arrayofvat[$key] as $k => $mt) {
395 if ($mt) {
396 if (empty($conf->cache['accountingaccountincurrententity_vat'][$k])) {
397 $accountingaccount = new AccountingAccount($db);
398 $accountingaccount->fetch(0, $k, true);
399 $conf->cache['accountingaccountincurrententity_vat'][$k] = $accountingaccount;
400 } else {
401 $accountingaccount = $conf->cache['accountingaccountincurrententity_vat'][$k];
402 }
403
404 $account_label = $accountingaccount->label;
405
406 // get compte id and label
407 $bookkeeping = new BookKeeping($db);
408 $bookkeeping->doc_date = $val["date"];
409 $bookkeeping->doc_ref = $val["ref"];
410 $bookkeeping->date_creation = $now;
411 $bookkeeping->doc_type = 'expense_report';
412 $bookkeeping->fk_doc = $key;
413 $bookkeeping->fk_docdet = $val["fk_expensereportdet"];
414
415 $bookkeeping->subledger_account = '';
416 $bookkeeping->subledger_label = '';
417
418 $bookkeeping->numero_compte = $k;
419 $bookkeeping->label_compte = $account_label;
420
421 $bookkeeping->label_operation = $langs->trans("VAT").' '.implode(', ', $def_tva[$key][$k]).' %';
422 $bookkeeping->montant = $mt;
423 $bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
424 $bookkeeping->debit = ($mt > 0) ? $mt : 0;
425 $bookkeeping->credit = ($mt <= 0) ? -$mt : 0;
426 $bookkeeping->code_journal = $journal;
427 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
428 $bookkeeping->fk_user_author = $user->id;
429 $bookkeeping->entity = $conf->entity;
430
431 $totaldebit += $bookkeeping->debit;
432 $totalcredit += $bookkeeping->credit;
433
434 $result = $bookkeeping->create($user);
435 if ($result < 0) {
436 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
437 $error++;
438 $errorforline++;
439 $errorforinvoice[$key] = 'alreadyjournalized';
440 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
441 } else {
442 $error++;
443 $errorforline++;
444 $errorforinvoice[$key] = 'other';
445 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
446 }
447 }
448 }
449 }
450 }
451 }
452
453 // Protection against a bug on lines before
454 if (!$errorforline && (price2num($totaldebit, 'MT') != price2num($totalcredit, 'MT'))) {
455 $error++;
456 $errorforline++;
457 $errorforinvoice[$key] = 'amountsnotbalanced';
458 setEventMessages('We tried to insert a non balanced transaction in book for '.$val["ref"].'. Canceled. Surely a bug.', null, 'errors');
459 }
460
461 if (!$errorforline) {
462 $db->commit();
463 } else {
464 $db->rollback();
465
466 if ($error >= 10) {
467 setEventMessages($langs->trans("ErrorTooManyErrorsProcessStopped"), null, 'errors');
468 break; // Break in the foreach
469 }
470 }
471 }
472
473 $tabpay = $taber;
474
475 if (empty($error) && count($tabpay) > 0) {
476 setEventMessages($langs->trans("GeneralLedgerIsWritten"), null, 'mesgs');
477 } elseif (count($tabpay) == $error) {
478 setEventMessages($langs->trans("NoNewRecordSaved"), null, 'warnings');
479 } else {
480 setEventMessages($langs->trans("GeneralLedgerSomeRecordWasNotRecorded"), null, 'warnings');
481 }
482
483 $action = '';
484
485 // Must reload data, so we make a redirect
486 if (count($tabpay) != $error) {
487 $param = 'id_journal='.$id_journal;
488 $param .= '&date_startday='.$date_startday;
489 $param .= '&date_startmonth='.$date_startmonth;
490 $param .= '&date_startyear='.$date_startyear;
491 $param .= '&date_endday='.$date_endday;
492 $param .= '&date_endmonth='.$date_endmonth;
493 $param .= '&date_endyear='.$date_endyear;
494 $param .= '&in_bookkeeping='.$in_bookkeeping;
495
496 header("Location: ".$_SERVER['PHP_SELF'].($param ? '?'.$param : ''));
497 exit;
498 }
499}
500
501
502/*
503 * View
504 */
505
506$form = new Form($db);
507
508$userstatic = new User($db);
509
510// Export
511if ($action == 'exportcsv' && !$error) { // ISO and not UTF8 !
512 $sep = getDolGlobalString('ACCOUNTING_EXPORT_SEPARATORCSV');
513
514 $filename = 'journal';
515 $type_export = 'journal';
516 include DOL_DOCUMENT_ROOT.'/accountancy/tpl/export_journal.tpl.php';
517
518 // CSV header line
519 print '"'.$langs->transnoentitiesnoconv("Date").'"'.$sep;
520 print '"'.$langs->transnoentitiesnoconv("Piece").'"'.$sep;
521 print '"'.$langs->transnoentitiesnoconv("AccountAccounting").'"'.$sep;
522 print '"'.$langs->transnoentitiesnoconv("LabelOperation").'"'.$sep;
523 print '"'.$langs->transnoentitiesnoconv("AccountingDebit").'"'.$sep;
524 print '"'.$langs->transnoentitiesnoconv("AccountingCredit").'"'.$sep;
525 print "\n";
526
527 foreach ($taber as $key => $val) {
528 $date = dol_print_date($val["date"], 'day');
529
530 $userstatic->id = $tabuser[$key]['id'];
531 $userstatic->name = $tabuser[$key]['name'];
532
533 // Fees
534 foreach ($tabht[$key] as $k => $mt) {
535 $accountingaccount = new AccountingAccount($db);
536 $accountingaccount->fetch(null, $k, true);
537 if ($mt) {
538 print '"'.$date.'"'.$sep;
539 print '"'.$val["ref"].'"'.$sep;
540 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
541 print '"'.dol_trunc($accountingaccount->label, 32).'"'.$sep;
542 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
543 print '"'.($mt < 0 ? price(-$mt) : '').'"';
544 print "\n";
545 }
546 }
547
548 // VAT
549 foreach ($tabtva[$key] as $k => $mt) {
550 if ($mt) {
551 print '"'.$date.'"'.$sep;
552 print '"'.$val["ref"].'"'.$sep;
553 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
554 print '"'.dol_trunc($langs->trans("VAT")).'"'.$sep;
555 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
556 print '"'.($mt < 0 ? price(-$mt) : '').'"';
557 print "\n";
558 }
559 }
560
561 // Third party
562 foreach ($tabttc[$key] as $k => $mt) {
563 print '"'.$date.'"'.$sep;
564 print '"'.$val["ref"].'"'.$sep;
565 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
566 print '"'.dol_trunc($userstatic->name).'"'.$sep;
567 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
568 print '"'.($mt >= 0 ? price($mt) : '').'"';
569 }
570 print "\n";
571 }
572}
573
574if (empty($action) || $action == 'view') {
575 $title = $langs->trans("GenerationOfAccountingEntries").' - '.$accountingjournalstatic->getNomUrl(0, 2, 1, '', 1);
576 $help_url ='EN:Module_Double_Entry_Accounting|FR:Module_Comptabilit&eacute;_en_Partie_Double#G&eacute;n&eacute;ration_des_&eacute;critures_en_comptabilit&eacute;';
577 llxHeader('', dol_string_nohtmltag($title), $help_url, '', 0, 0, '', '', '', 'mod-accountancy accountancy-generation page-expensereportsjournal');
578
579 $nom = $title;
580 $nomlink = '';
581 $periodlink = '';
582 $exportlink = '';
583 $builddate = dol_now();
584 $description = $langs->trans("DescJournalOnlyBindedVisible").'<br>';
585
586 $listofchoices = array('notyet'=>$langs->trans("NotYetInGeneralLedger"), 'already'=>$langs->trans("AlreadyInGeneralLedger"));
587 $period = $form->selectDate($date_start ? $date_start : -1, 'date_start', 0, 0, 0, '', 1, 0).' - '.$form->selectDate($date_end ? $date_end : -1, 'date_end', 0, 0, 0, '', 1, 0);
588 $period .= ' - '.$langs->trans("JournalizationInLedgerStatus").' '.$form->selectarray('in_bookkeeping', $listofchoices, $in_bookkeeping, 1);
589
590 $varlink = 'id_journal='.$id_journal;
591
592 journalHead($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => ''), '', $varlink);
593
594 if (getDolGlobalString('ACCOUNTANCY_FISCAL_PERIOD_MODE') != 'blockedonclosed') {
595 // Test that setup is complete (we are in accounting, so test on entity is always on $conf->entity only, no sharing allowed)
596 // Fiscal period test
597 $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_fiscalyear WHERE entity = ".((int) $conf->entity);
598 $resql = $db->query($sql);
599 if ($resql) {
600 $obj = $db->fetch_object($resql);
601 if ($obj->nb == 0) {
602 print '<br><div class="warning">'.img_warning().' '.$langs->trans("TheFiscalPeriodIsNotDefined");
603 $desc = ' : '.$langs->trans("AccountancyAreaDescFiscalPeriod", 4, '{link}');
604 $desc = str_replace('{link}', '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("FiscalPeriod").'</strong>', $desc);
605 print $desc;
606 print '</div>';
607 }
608 } else {
609 dol_print_error($db);
610 }
611 }
612
613 // Button to write into Ledger
614 if (!getDolGlobalString('ACCOUNTING_ACCOUNT_EXPENSEREPORT') || getDolGlobalString('ACCOUNTING_ACCOUNT_EXPENSEREPORT') == '-1') {
615 print '<br><div class="warning">'.img_warning().' '.$langs->trans("SomeMandatoryStepsOfSetupWereNotDone");
616 $desc = ' : '.$langs->trans("AccountancyAreaDescMisc", 4, '{link}');
617 $desc = str_replace('{link}', '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").'</strong>', $desc);
618 print $desc;
619 print '</div>';
620 }
621 print '<br><div class="tabsAction tabsActionNoBottom centerimp">';
622
623 if (getDolGlobalString('ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL') && $in_bookkeeping == 'notyet') {
624 print '<input type="button" class="butAction" name="exportcsv" value="'.$langs->trans("ExportDraftJournal").'" onclick="launch_export();" />';
625 }
626 if (!getDolGlobalString('ACCOUNTING_ACCOUNT_EXPENSEREPORT') || getDolGlobalString('ACCOUNTING_ACCOUNT_EXPENSEREPORT') == '-1') {
627 print '<input type="button" class="butActionRefused classfortooltip" title="'.dol_escape_htmltag($langs->trans("SomeMandatoryStepsOfSetupWereNotDone")).'" value="'.$langs->trans("WriteBookKeeping").'" />';
628 } else {
629 if ($in_bookkeeping == 'notyet') {
630 print '<input type="button" class="butAction" name="writebookkeeping" value="'.$langs->trans("WriteBookKeeping").'" onclick="writebookkeeping();" />';
631 } else {
632 print '<a href="#" class="butActionRefused classfortooltip" name="writebookkeeping">'.$langs->trans("WriteBookKeeping").'</a>';
633 }
634 }
635 print '</div>';
636
637 // TODO Avoid using js. We can use a direct link with $param
638 print '
639 <script type="text/javascript">
640 function launch_export() {
641 $("div.fiche form input[name=\"action\"]").val("exportcsv");
642 $("div.fiche form input[type=\"submit\"]").click();
643 $("div.fiche form input[name=\"action\"]").val("");
644 }
645 function writebookkeeping() {
646 console.log("click on writebookkeeping");
647 $("div.fiche form input[name=\"action\"]").val("writebookkeeping");
648 $("div.fiche form input[type=\"submit\"]").click();
649 $("div.fiche form input[name=\"action\"]").val("");
650 }
651 </script>';
652
653 /*
654 * Show result array
655 */
656 print '<br>';
657
658 $i = 0;
659 print '<div class="div-table-responsive">';
660 print "<table class=\"noborder\" width=\"100%\">";
661 print "<tr class=\"liste_titre\">";
662 print "<td>".$langs->trans("Date")."</td>";
663 print "<td>".$langs->trans("Piece").' ('.$langs->trans("ExpenseReportRef").")</td>";
664 print "<td>".$langs->trans("AccountAccounting")."</td>";
665 print "<td>".$langs->trans("SubledgerAccount")."</td>";
666 print "<td>".$langs->trans("LabelOperation")."</td>";
667 print '<td class="right">'.$langs->trans("AccountingDebit")."</td>";
668 print '<td class="right">'.$langs->trans("AccountingCredit")."</td>";
669 print "</tr>\n";
670
671 $i = 0;
672
673 $expensereportstatic = new ExpenseReport($db);
674 $expensereportlinestatic = new ExpenseReportLine($db);
675
676 foreach ($taber as $key => $val) {
677 $expensereportstatic->id = $key;
678 $expensereportstatic->ref = $val["ref"];
679 $expensereportlinestatic->comments = html_entity_decode(dol_trunc($val["comments"], 32));
680
681 $date = dol_print_date($val["date"], 'day');
682
683 if ($errorforinvoice[$key] == 'somelinesarenotbound') {
684 print '<tr class="oddeven">';
685 print "<!-- Some lines are not bound -->";
686 print "<td>".$date."</td>";
687 print "<td>".$expensereportstatic->getNomUrl(1)."</td>";
688 // Account
689 print "<td>";
690 print '<span class="error">'.$langs->trans('ErrorInvoiceContainsLinesNotYetBoundedShort', $val['ref']).'</span>';
691 print '</td>';
692 // Subledger account
693 print "<td>";
694 print '</td>';
695 print "<td>";
696 print "</td>";
697 print '<td class="right"></td>';
698 print '<td class="right"></td>';
699 print "</tr>";
700
701 $i++;
702 }
703
704 // Fees
705 foreach ($tabht[$key] as $k => $mt) {
706 if (empty($conf->cache['accountingaccountincurrententity'][$k])) {
707 $accountingaccount = new AccountingAccount($db);
708 $accountingaccount->fetch(0, $k, true);
709 $conf->cache['accountingaccountincurrententity'][$k] = $accountingaccount;
710 } else {
711 $accountingaccount = $conf->cache['accountingaccountincurrententity'][$k];
712 }
713
714 if ($mt) {
715 print '<tr class="oddeven">';
716 print "<!-- Fees -->";
717 print "<td>".$date."</td>";
718 print "<td>".$expensereportstatic->getNomUrl(1)."</td>";
719 $userstatic->id = $tabuser[$key]['id'];
720 $userstatic->name = $tabuser[$key]['name'];
721 // Account
722 print "<td>";
723 $accountoshow = length_accountg($k);
724 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
725 print '<span class="error">'.$langs->trans("FeeAccountNotDefined").'</span>';
726 } else {
727 print $accountoshow;
728 }
729 print '</td>';
730 // Subledger account
731 print "<td>";
732 print '</td>';
733 $userstatic->id = $tabuser[$key]['id'];
734 $userstatic->name = $tabuser[$key]['name'];
735 print "<td>".$userstatic->getNomUrl(0, 'user', 16).' - '.$accountingaccount->label."</td>";
736 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
737 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
738 print "</tr>";
739
740 $i++;
741 }
742 }
743
744 // Third party
745 foreach ($tabttc[$key] as $k => $mt) {
746 $userstatic->id = $tabuser[$key]['id'];
747 $userstatic->name = $tabuser[$key]['name'];
748
749 print '<tr class="oddeven">';
750 print "<!-- Thirdparty -->";
751 print "<td>".$date."</td>";
752 print "<td>".$expensereportstatic->getNomUrl(1)."</td>";
753 // Account
754 print "<td>";
755 $accountoshow = length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_EXPENSEREPORT'));
756 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
757 print '<span class="error">'.$langs->trans("MainAccountForUsersNotDefined").'</span>';
758 } else {
759 print $accountoshow;
760 }
761 print "</td>";
762 // Subledger account
763 print "<td>";
764 $accountoshow = length_accounta($k);
765 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
766 print '<span class="error">'.$langs->trans("UserAccountNotDefined").'</span>';
767 } else {
768 print $accountoshow;
769 }
770 print '</td>';
771 print "<td>".$userstatic->getNomUrl(0, 'user', 16).' - '.$langs->trans("SubledgerAccount")."</td>";
772 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
773 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
774 print "</tr>";
775
776 $i++;
777 }
778
779 // VAT
780 $listoftax = array(0, 1, 2);
781 foreach ($listoftax as $numtax) {
782 $arrayofvat = $tabtva;
783 if ($numtax == 1) {
784 $arrayofvat = $tablocaltax1;
785 }
786 if ($numtax == 2) {
787 $arrayofvat = $tablocaltax2;
788 }
789
790 foreach ($arrayofvat[$key] as $k => $mt) {
791 if ($mt) {
792 print '<tr class="oddeven">';
793 print "<!-- VAT -->";
794 print "<td>".$date."</td>";
795 print "<td>".$expensereportstatic->getNomUrl(1)."</td>";
796 // Account
797 print "<td>";
798 $accountoshow = length_accountg($k);
799 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
800 print '<span class="error">'.$langs->trans("VATAccountNotDefined").'</span>';
801 } else {
802 print $accountoshow;
803 }
804 print "</td>";
805 // Subledger account
806 print "<td>";
807 print '</td>';
808 print "<td>".$userstatic->getNomUrl(0, 'user', 16).' - '.$langs->trans("VAT").' '.implode(', ', $def_tva[$key][$k]).' %'.($numtax ? ' - Localtax '.$numtax : '');
809 print "</td>";
810 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
811 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
812 print "</tr>";
813
814 $i++;
815 }
816 }
817 }
818 }
819
820 if (!$i) {
821 $colspan = 7;
822 print '<tr class="oddeven"><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
823 }
824
825 print "</table>";
826 print '</div>';
827
828 // End of page
829 llxFooter();
830}
831$db->close();
length_accountg($account)
Return General accounting account with defined length (used for product and miscellaneous)
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.
getDefaultDatesForTransfer()
Return Default dates for transfer based on periodicity option in accountancy setup.
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 accounting journals.
Class to manage Ledger (General Ledger and Subledger)
Class to manage Trips and Expenses.
Class of expense report details lines.
Class to manage generation of HTML components Only common components must be here.
Class to manage Dolibarr users.
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition date.lib.php:595
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:614
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...
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formatted for view output Used into pdf and HTML pages.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
getTaxesFromId($vatrate, $buyer=null, $seller=null, $firstparamisid=1)
Get tax (VAT) main information from Id.
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_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.