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