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