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