dolibarr 20.0.0
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 // get compte id and label
325 if ($accountingaccount->fetch(null, $k, true)) {
326 $bookkeeping = new BookKeeping($db);
327 $bookkeeping->doc_date = $val["date"];
328 $bookkeeping->doc_ref = $val["ref"];
329 $bookkeeping->date_creation = $now;
330 $bookkeeping->doc_type = 'expense_report';
331 $bookkeeping->fk_doc = $key;
332 $bookkeeping->fk_docdet = $val["fk_expensereportdet"];
333
334 $bookkeeping->subledger_account = '';
335 $bookkeeping->subledger_label = '';
336
337 $bookkeeping->numero_compte = $k;
338 $bookkeeping->label_compte = $accountingaccount->label;
339
340 $bookkeeping->label_operation = $accountingaccount->label;
341 $bookkeeping->montant = $mt;
342 $bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
343 $bookkeeping->debit = ($mt > 0) ? $mt : 0;
344 $bookkeeping->credit = ($mt <= 0) ? -$mt : 0;
345 $bookkeeping->code_journal = $journal;
346 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
347 $bookkeeping->fk_user_author = $user->id;
348 $bookkeeping->entity = $conf->entity;
349
350 $totaldebit += $bookkeeping->debit;
351 $totalcredit += $bookkeeping->credit;
352
353 $result = $bookkeeping->create($user);
354 if ($result < 0) {
355 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
356 $error++;
357 $errorforline++;
358 $errorforinvoice[$key] = 'alreadyjournalized';
359 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
360 } else {
361 $error++;
362 $errorforline++;
363 $errorforinvoice[$key] = 'other';
364 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
365 }
366 }
367 }
368 }
369 }
370 }
371
372 // VAT
373 if (!$errorforline) {
374 $listoftax = array(0, 1, 2);
375 foreach ($listoftax as $numtax) {
376 $arrayofvat = $tabtva;
377 if ($numtax == 1) {
378 $arrayofvat = $tablocaltax1;
379 }
380 if ($numtax == 2) {
381 $arrayofvat = $tablocaltax2;
382 }
383
384 foreach ($arrayofvat[$key] as $k => $mt) {
385 if ($mt) {
386 if (empty($conf->cache['accountingaccountincurrententity'][$k])) {
387 $accountingaccount = new AccountingAccount($db);
388 $accountingaccount->fetch(0, $k, true);
389 $conf->cache['accountingaccountincurrententity'][$k] = $accountingaccount;
390 } else {
391 $accountingaccount = $conf->cache['accountingaccountincurrententity'][$k];
392 }
393
394 $account_label = $accountingaccount->label;
395
396 // get compte id and label
397 $bookkeeping = new BookKeeping($db);
398 $bookkeeping->doc_date = $val["date"];
399 $bookkeeping->doc_ref = $val["ref"];
400 $bookkeeping->date_creation = $now;
401 $bookkeeping->doc_type = 'expense_report';
402 $bookkeeping->fk_doc = $key;
403 $bookkeeping->fk_docdet = $val["fk_expensereportdet"];
404
405 $bookkeeping->subledger_account = '';
406 $bookkeeping->subledger_label = '';
407
408 $bookkeeping->numero_compte = $k;
409 $bookkeeping->label_compte = $account_label;
410
411 $bookkeeping->label_operation = $langs->trans("VAT").' '.implode(', ', $def_tva[$key][$k]).' %';
412 $bookkeeping->montant = $mt;
413 $bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
414 $bookkeeping->debit = ($mt > 0) ? $mt : 0;
415 $bookkeeping->credit = ($mt <= 0) ? -$mt : 0;
416 $bookkeeping->code_journal = $journal;
417 $bookkeeping->journal_label = $langs->transnoentities($journal_label);
418 $bookkeeping->fk_user_author = $user->id;
419 $bookkeeping->entity = $conf->entity;
420
421 $totaldebit += $bookkeeping->debit;
422 $totalcredit += $bookkeeping->credit;
423
424 $result = $bookkeeping->create($user);
425 if ($result < 0) {
426 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
427 $error++;
428 $errorforline++;
429 $errorforinvoice[$key] = 'alreadyjournalized';
430 //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings');
431 } else {
432 $error++;
433 $errorforline++;
434 $errorforinvoice[$key] = 'other';
435 setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors');
436 }
437 }
438 }
439 }
440 }
441 }
442
443 // Protection against a bug on lines before
444 if (!$errorforline && (price2num($totaldebit, 'MT') != price2num($totalcredit, 'MT'))) {
445 $error++;
446 $errorforline++;
447 $errorforinvoice[$key] = 'amountsnotbalanced';
448 setEventMessages('We tried to insert a non balanced transaction in book for '.$val["ref"].'. Canceled. Surely a bug.', null, 'errors');
449 }
450
451 if (!$errorforline) {
452 $db->commit();
453 } else {
454 $db->rollback();
455
456 if ($error >= 10) {
457 setEventMessages($langs->trans("ErrorTooManyErrorsProcessStopped"), null, 'errors');
458 break; // Break in the foreach
459 }
460 }
461 }
462
463 $tabpay = $taber;
464
465 if (empty($error) && count($tabpay) > 0) {
466 setEventMessages($langs->trans("GeneralLedgerIsWritten"), null, 'mesgs');
467 } elseif (count($tabpay) == $error) {
468 setEventMessages($langs->trans("NoNewRecordSaved"), null, 'warnings');
469 } else {
470 setEventMessages($langs->trans("GeneralLedgerSomeRecordWasNotRecorded"), null, 'warnings');
471 }
472
473 $action = '';
474
475 // Must reload data, so we make a redirect
476 if (count($tabpay) != $error) {
477 $param = 'id_journal='.$id_journal;
478 $param .= '&date_startday='.$date_startday;
479 $param .= '&date_startmonth='.$date_startmonth;
480 $param .= '&date_startyear='.$date_startyear;
481 $param .= '&date_endday='.$date_endday;
482 $param .= '&date_endmonth='.$date_endmonth;
483 $param .= '&date_endyear='.$date_endyear;
484 $param .= '&in_bookkeeping='.$in_bookkeeping;
485
486 header("Location: ".$_SERVER['PHP_SELF'].($param ? '?'.$param : ''));
487 exit;
488 }
489}
490
491
492/*
493 * View
494 */
495
496$form = new Form($db);
497
498$userstatic = new User($db);
499
500// Export
501if ($action == 'exportcsv' && !$error) { // ISO and not UTF8 !
502 $sep = getDolGlobalString('ACCOUNTING_EXPORT_SEPARATORCSV');
503
504 $filename = 'journal';
505 $type_export = 'journal';
506 include DOL_DOCUMENT_ROOT.'/accountancy/tpl/export_journal.tpl.php';
507
508 // CSV header line
509 print '"'.$langs->transnoentitiesnoconv("Date").'"'.$sep;
510 print '"'.$langs->transnoentitiesnoconv("Piece").'"'.$sep;
511 print '"'.$langs->transnoentitiesnoconv("AccountAccounting").'"'.$sep;
512 print '"'.$langs->transnoentitiesnoconv("LabelOperation").'"'.$sep;
513 print '"'.$langs->transnoentitiesnoconv("AccountingDebit").'"'.$sep;
514 print '"'.$langs->transnoentitiesnoconv("AccountingCredit").'"'.$sep;
515 print "\n";
516
517 foreach ($taber as $key => $val) {
518 $date = dol_print_date($val["date"], 'day');
519
520 $userstatic->id = $tabuser[$key]['id'];
521 $userstatic->name = $tabuser[$key]['name'];
522
523 // Fees
524 foreach ($tabht[$key] as $k => $mt) {
525 $accountingaccount = new AccountingAccount($db);
526 $accountingaccount->fetch(null, $k, true);
527 if ($mt) {
528 print '"'.$date.'"'.$sep;
529 print '"'.$val["ref"].'"'.$sep;
530 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
531 print '"'.dol_trunc($accountingaccount->label, 32).'"'.$sep;
532 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
533 print '"'.($mt < 0 ? price(-$mt) : '').'"';
534 print "\n";
535 }
536 }
537
538 // VAT
539 foreach ($tabtva[$key] as $k => $mt) {
540 if ($mt) {
541 print '"'.$date.'"'.$sep;
542 print '"'.$val["ref"].'"'.$sep;
543 print '"'.length_accountg(html_entity_decode($k)).'"'.$sep;
544 print '"'.dol_trunc($langs->trans("VAT")).'"'.$sep;
545 print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep;
546 print '"'.($mt < 0 ? price(-$mt) : '').'"';
547 print "\n";
548 }
549 }
550
551 // Third party
552 foreach ($tabttc[$key] as $k => $mt) {
553 print '"'.$date.'"'.$sep;
554 print '"'.$val["ref"].'"'.$sep;
555 print '"'.length_accounta(html_entity_decode($k)).'"'.$sep;
556 print '"'.dol_trunc($userstatic->name).'"'.$sep;
557 print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep;
558 print '"'.($mt >= 0 ? price($mt) : '').'"';
559 }
560 print "\n";
561 }
562}
563
564if (empty($action) || $action == 'view') {
565 $title = $langs->trans("GenerationOfAccountingEntries").' - '.$accountingjournalstatic->getNomUrl(0, 2, 1, '', 1);
566 $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;';
567 llxHeader('', dol_string_nohtmltag($title), $help_url, '', 0, 0, '', '', '', 'mod-accountancy accountancy-generation page-expensereportsjournal');
568
569 $nom = $title;
570 $nomlink = '';
571 $periodlink = '';
572 $exportlink = '';
573 $builddate = dol_now();
574 $description = $langs->trans("DescJournalOnlyBindedVisible").'<br>';
575
576 $listofchoices = array('notyet'=>$langs->trans("NotYetInGeneralLedger"), 'already'=>$langs->trans("AlreadyInGeneralLedger"));
577 $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);
578 $period .= ' - '.$langs->trans("JournalizationInLedgerStatus").' '.$form->selectarray('in_bookkeeping', $listofchoices, $in_bookkeeping, 1);
579
580 $varlink = 'id_journal='.$id_journal;
581
582 journalHead($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => ''), '', $varlink);
583
584 if (getDolGlobalString('ACCOUNTANCY_FISCAL_PERIOD_MODE') != 'blockedonclosed') {
585 // Test that setup is complete (we are in accounting, so test on entity is always on $conf->entity only, no sharing allowed)
586 // Fiscal period test
587 $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."accounting_fiscalyear WHERE entity = ".((int) $conf->entity);
588 $resql = $db->query($sql);
589 if ($resql) {
590 $obj = $db->fetch_object($resql);
591 if ($obj->nb == 0) {
592 print '<br><div class="warning">'.img_warning().' '.$langs->trans("TheFiscalPeriodIsNotDefined");
593 $desc = ' : '.$langs->trans("AccountancyAreaDescFiscalPeriod", 4, '{link}');
594 $desc = str_replace('{link}', '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("FiscalPeriod").'</strong>', $desc);
595 print $desc;
596 print '</div>';
597 }
598 } else {
599 dol_print_error($db);
600 }
601 }
602
603 // Button to write into Ledger
604 if (!getDolGlobalString('ACCOUNTING_ACCOUNT_EXPENSEREPORT') || getDolGlobalString('ACCOUNTING_ACCOUNT_EXPENSEREPORT') == '-1') {
605 print '<br><div class="warning">'.img_warning().' '.$langs->trans("SomeMandatoryStepsOfSetupWereNotDone");
606 $desc = ' : '.$langs->trans("AccountancyAreaDescMisc", 4, '{link}');
607 $desc = str_replace('{link}', '<strong>'.$langs->transnoentitiesnoconv("MenuAccountancy").'-'.$langs->transnoentitiesnoconv("Setup")."-".$langs->transnoentitiesnoconv("MenuDefaultAccounts").'</strong>', $desc);
608 print $desc;
609 print '</div>';
610 }
611 print '<br><div class="tabsAction tabsActionNoBottom centerimp">';
612
613 if (getDolGlobalString('ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL') && $in_bookkeeping == 'notyet') {
614 print '<input type="button" class="butAction" name="exportcsv" value="'.$langs->trans("ExportDraftJournal").'" onclick="launch_export();" />';
615 }
616 if (!getDolGlobalString('ACCOUNTING_ACCOUNT_EXPENSEREPORT') || getDolGlobalString('ACCOUNTING_ACCOUNT_EXPENSEREPORT') == '-1') {
617 print '<input type="button" class="butActionRefused classfortooltip" title="'.dol_escape_htmltag($langs->trans("SomeMandatoryStepsOfSetupWereNotDone")).'" value="'.$langs->trans("WriteBookKeeping").'" />';
618 } else {
619 if ($in_bookkeeping == 'notyet') {
620 print '<input type="button" class="butAction" name="writebookkeeping" value="'.$langs->trans("WriteBookKeeping").'" onclick="writebookkeeping();" />';
621 } else {
622 print '<a href="#" class="butActionRefused classfortooltip" name="writebookkeeping">'.$langs->trans("WriteBookKeeping").'</a>';
623 }
624 }
625 print '</div>';
626
627 // TODO Avoid using js. We can use a direct link with $param
628 print '
629 <script type="text/javascript">
630 function launch_export() {
631 $("div.fiche form input[name=\"action\"]").val("exportcsv");
632 $("div.fiche form input[type=\"submit\"]").click();
633 $("div.fiche form input[name=\"action\"]").val("");
634 }
635 function writebookkeeping() {
636 console.log("click on writebookkeeping");
637 $("div.fiche form input[name=\"action\"]").val("writebookkeeping");
638 $("div.fiche form input[type=\"submit\"]").click();
639 $("div.fiche form input[name=\"action\"]").val("");
640 }
641 </script>';
642
643 /*
644 * Show result array
645 */
646 print '<br>';
647
648 $i = 0;
649 print '<div class="div-table-responsive">';
650 print "<table class=\"noborder\" width=\"100%\">";
651 print "<tr class=\"liste_titre\">";
652 print "<td>".$langs->trans("Date")."</td>";
653 print "<td>".$langs->trans("Piece").' ('.$langs->trans("ExpenseReportRef").")</td>";
654 print "<td>".$langs->trans("AccountAccounting")."</td>";
655 print "<td>".$langs->trans("SubledgerAccount")."</td>";
656 print "<td>".$langs->trans("LabelOperation")."</td>";
657 print '<td class="right">'.$langs->trans("AccountingDebit")."</td>";
658 print '<td class="right">'.$langs->trans("AccountingCredit")."</td>";
659 print "</tr>\n";
660
661 $i = 0;
662
663 $expensereportstatic = new ExpenseReport($db);
664 $expensereportlinestatic = new ExpenseReportLine($db);
665
666 foreach ($taber as $key => $val) {
667 $expensereportstatic->id = $key;
668 $expensereportstatic->ref = $val["ref"];
669 $expensereportlinestatic->comments = html_entity_decode(dol_trunc($val["comments"], 32));
670
671 $date = dol_print_date($val["date"], 'day');
672
673 if ($errorforinvoice[$key] == 'somelinesarenotbound') {
674 print '<tr class="oddeven">';
675 print "<!-- Some lines are not bound -->";
676 print "<td>".$date."</td>";
677 print "<td>".$expensereportstatic->getNomUrl(1)."</td>";
678 // Account
679 print "<td>";
680 print '<span class="error">'.$langs->trans('ErrorInvoiceContainsLinesNotYetBoundedShort', $val['ref']).'</span>';
681 print '</td>';
682 // Subledger account
683 print "<td>";
684 print '</td>';
685 print "<td>";
686 print "</td>";
687 print '<td class="right"></td>';
688 print '<td class="right"></td>';
689 print "</tr>";
690
691 $i++;
692 }
693
694 // Fees
695 foreach ($tabht[$key] as $k => $mt) {
696 if (empty($conf->cache['accountingaccountincurrententity'][$k])) {
697 $accountingaccount = new AccountingAccount($db);
698 $accountingaccount->fetch(0, $k, true);
699 $conf->cache['accountingaccountincurrententity'][$k] = $accountingaccount;
700 } else {
701 $accountingaccount = $conf->cache['accountingaccountincurrententity'][$k];
702 }
703
704 if ($mt) {
705 print '<tr class="oddeven">';
706 print "<!-- Fees -->";
707 print "<td>".$date."</td>";
708 print "<td>".$expensereportstatic->getNomUrl(1)."</td>";
709 $userstatic->id = $tabuser[$key]['id'];
710 $userstatic->name = $tabuser[$key]['name'];
711 // Account
712 print "<td>";
713 $accountoshow = length_accountg($k);
714 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
715 print '<span class="error">'.$langs->trans("FeeAccountNotDefined").'</span>';
716 } else {
717 print $accountoshow;
718 }
719 print '</td>';
720 // Subledger account
721 print "<td>";
722 print '</td>';
723 $userstatic->id = $tabuser[$key]['id'];
724 $userstatic->name = $tabuser[$key]['name'];
725 print "<td>".$userstatic->getNomUrl(0, 'user', 16).' - '.$accountingaccount->label."</td>";
726 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
727 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
728 print "</tr>";
729
730 $i++;
731 }
732 }
733
734 // Third party
735 foreach ($tabttc[$key] as $k => $mt) {
736 $userstatic->id = $tabuser[$key]['id'];
737 $userstatic->name = $tabuser[$key]['name'];
738
739 print '<tr class="oddeven">';
740 print "<!-- Thirdparty -->";
741 print "<td>".$date."</td>";
742 print "<td>".$expensereportstatic->getNomUrl(1)."</td>";
743 // Account
744 print "<td>";
745 $accountoshow = length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_EXPENSEREPORT'));
746 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
747 print '<span class="error">'.$langs->trans("MainAccountForUsersNotDefined").'</span>';
748 } else {
749 print $accountoshow;
750 }
751 print "</td>";
752 // Subledger account
753 print "<td>";
754 $accountoshow = length_accounta($k);
755 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
756 print '<span class="error">'.$langs->trans("UserAccountNotDefined").'</span>';
757 } else {
758 print $accountoshow;
759 }
760 print '</td>';
761 print "<td>".$userstatic->getNomUrl(0, 'user', 16).' - '.$langs->trans("SubledgerAccount")."</td>";
762 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
763 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
764 print "</tr>";
765
766 $i++;
767 }
768
769 // VAT
770 $listoftax = array(0, 1, 2);
771 foreach ($listoftax as $numtax) {
772 $arrayofvat = $tabtva;
773 if ($numtax == 1) {
774 $arrayofvat = $tablocaltax1;
775 }
776 if ($numtax == 2) {
777 $arrayofvat = $tablocaltax2;
778 }
779
780 foreach ($arrayofvat[$key] as $k => $mt) {
781 if ($mt) {
782 print '<tr class="oddeven">';
783 print "<!-- VAT -->";
784 print "<td>".$date."</td>";
785 print "<td>".$expensereportstatic->getNomUrl(1)."</td>";
786 // Account
787 print "<td>";
788 $accountoshow = length_accountg($k);
789 if (($accountoshow == "") || $accountoshow == 'NotDefined') {
790 print '<span class="error">'.$langs->trans("VATAccountNotDefined").'</span>';
791 } else {
792 print $accountoshow;
793 }
794 print "</td>";
795 // Subledger account
796 print "<td>";
797 print '</td>';
798 print "<td>".$userstatic->getNomUrl(0, 'user', 16).' - '.$langs->trans("VAT").' '.implode(', ', $def_tva[$key][$k]).' %'.($numtax ? ' - Localtax '.$numtax : '');
799 print "</td>";
800 print '<td class="right nowraponall amount">'.($mt >= 0 ? price($mt) : '')."</td>";
801 print '<td class="right nowraponall amount">'.($mt < 0 ? price(-$mt) : '')."</td>";
802 print "</tr>";
803
804 $i++;
805 }
806 }
807 }
808 }
809
810 if (!$i) {
811 $colspan = 7;
812 print '<tr class="oddeven"><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
813 }
814
815 print "</table>";
816 print '</div>';
817
818 // End of page
819 llxFooter();
820}
821$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.