dolibarr  16.0.1
html.formaccounting.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2013-2016 Florian Henry <florian.henry@open-concept.pro>
3  * Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com>
4  * Copyright (C) 2015 Ari Elbaz (elarifr) <github@accedinfo.com>
5  * Copyright (C) 2016 Marcos García <marcosgdf@gmail.com>
6  * Copyright (C) 2016-2020 Alexandre Spangaro <aspangaro@open-dsi.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
27 require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
28 
29 
33 class FormAccounting extends Form
34 {
35  private $options_cache = array();
36 
40  public $db;
41 
45  public $error = '';
46 
52  public function __construct($db)
53  {
54  $this->db = $db;
55  }
56 
57  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
72  public function select_journal($selectid, $htmlname = 'journal', $nature = 0, $showempty = 0, $select_in = 0, $select_out = 0, $morecss = 'maxwidth300 maxwidthonsmartphone', $usecache = '', $disabledajaxcombo = 0)
73  {
74  // phpcs:enable
75  global $conf, $langs;
76 
77  $out = '';
78 
79  $options = array();
80  if ($usecache && !empty($this->options_cache[$usecache])) {
81  $options = $this->options_cache[$usecache];
82  $selected = $selectid;
83  } else {
84  $sql = "SELECT rowid, code, label, nature, entity, active";
85  $sql .= " FROM ".$this->db->prefix()."accounting_journal";
86  $sql .= " WHERE active = 1";
87  $sql .= " AND entity = ".$conf->entity;
88  if ($nature && is_numeric($nature)) {
89  $sql .= " AND nature = ".((int) $nature);
90  }
91  $sql .= " ORDER BY code";
92 
93  dol_syslog(get_class($this)."::select_journal", LOG_DEBUG);
94  $resql = $this->db->query($sql);
95 
96  if (!$resql) {
97  $this->error = "Error ".$this->db->lasterror();
98  dol_syslog(get_class($this)."::select_journal ".$this->error, LOG_ERR);
99  return -1;
100  }
101 
102  $selected = 0;
103  $langs->load('accountancy');
104  while ($obj = $this->db->fetch_object($resql)) {
105  $label = $obj->code.' - '.$langs->trans($obj->label);
106 
107  $select_value_in = $obj->rowid;
108  $select_value_out = $obj->rowid;
109 
110  // Try to guess if we have found default value
111  if ($select_in == 1) {
112  $select_value_in = $obj->code;
113  }
114  if ($select_out == 1) {
115  $select_value_out = $obj->code;
116  }
117  // Remember guy's we store in database llx_accounting_bookkeeping the code of accounting_journal and not the rowid
118  if ($selectid != '' && $selectid == $select_value_in) {
119  //var_dump("Found ".$selectid." ".$select_value_in);
120  $selected = $select_value_out;
121  }
122 
123  $options[$select_value_out] = $label;
124  }
125  $this->db->free($resql);
126 
127  if ($usecache) {
128  $this->options_cache[$usecache] = $options;
129  }
130  }
131 
132  $out .= Form::selectarray($htmlname, $options, $selected, $showempty, 0, 0, '', 0, 0, 0, '', $morecss, ($disabledajaxcombo ? 0 : 1));
133 
134  return $out;
135  }
136 
137  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
152  public function multi_select_journal($selectedIds = array(), $htmlname = 'journal', $nature = 0, $showempty = 0, $select_in = 0, $select_out = 0, $morecss = '', $usecache = '', $disabledajaxcombo = 0)
153  {
154  // phpcs:enable
155  global $conf, $langs;
156 
157  $out = '';
158 
159  $options = array();
160  if ($usecache && !empty($this->options_cache[$usecache])) {
161  $options = $this->options_cache[$usecache];
162  $selected = $selectedIds;
163  } else {
164  $sql = "SELECT rowid, code, label, nature, entity, active";
165  $sql .= " FROM ".$this->db->prefix()."accounting_journal";
166  $sql .= " WHERE active = 1";
167  $sql .= " AND entity = ".$conf->entity;
168  if ($nature && is_numeric($nature)) {
169  $sql .= " AND nature = ".((int) $nature);
170  }
171  $sql .= " ORDER BY code";
172 
173  dol_syslog(get_class($this)."::multi_select_journal", LOG_DEBUG);
174  $resql = $this->db->query($sql);
175 
176  if (!$resql) {
177  $this->error = "Error ".$this->db->lasterror();
178  dol_syslog(get_class($this)."::multi_select_journal ".$this->error, LOG_ERR);
179  return -1;
180  }
181 
182  $selected = array();
183  $langs->load('accountancy');
184  while ($obj = $this->db->fetch_object($resql)) {
185  $label = $langs->trans($obj->label);
186 
187  $select_value_in = $obj->rowid;
188  $select_value_out = $obj->rowid;
189 
190  // Try to guess if we have found default value
191  if ($select_in == 1) {
192  $select_value_in = $obj->code;
193  }
194  if ($select_out == 1) {
195  $select_value_out = $obj->code;
196  }
197  // Remember guy's we store in database llx_accounting_bookkeeping the code of accounting_journal and not the rowid
198  if (!empty($selectedIds) && in_array($select_value_in, $selectedIds)) {
199  //var_dump("Found ".$selectid." ".$select_value_in);
200  $selected[] = $select_value_out;
201  }
202  $options[$select_value_out] = $label;
203  }
204  $this->db->free($resql);
205 
206  if ($usecache) {
207  $this->options_cache[$usecache] = $options;
208  }
209  }
210 
211  $out .= Form::multiselectarray($htmlname, $options, $selected, $showempty, 0, $morecss, 0, 0, 0, 'code_journal', '', ($disabledajaxcombo ? 0 : 1));
212 
213  return $out;
214  }
215 
216  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
229  public function select_accounting_category($selected = '', $htmlname = 'account_category', $useempty = 0, $maxlen = 0, $help = 1, $allcountries = 0)
230  {
231  // phpcs:enable
232  global $db, $langs, $user, $mysoc;
233 
234  if (empty($mysoc->country_id) && empty($mysoc->country_code) && empty($allcountries)) {
235  dol_print_error('', 'Call to select_accounting_account with mysoc country not yet defined');
236  exit;
237  }
238 
239  if (!empty($mysoc->country_id)) {
240  $sql = "SELECT c.rowid, c.label as type, c.range_account";
241  $sql .= " FROM ".$this->db->prefix()."c_accounting_category as c";
242  $sql .= " WHERE c.active = 1";
243  $sql .= " AND c.category_type = 0";
244  if (empty($allcountries)) {
245  $sql .= " AND c.fk_country = ".((int) $mysoc->country_id);
246  }
247  $sql .= " ORDER BY c.label ASC";
248  } else {
249  $sql = "SELECT c.rowid, c.label as type, c.range_account";
250  $sql .= " FROM ".$this->db->prefix()."c_accounting_category as c, ".$this->db->prefix()."c_country as co";
251  $sql .= " WHERE c.active = 1";
252  $sql .= " AND c.category_type = 0";
253  $sql .= " AND c.fk_country = co.rowid";
254  if (empty($allcountries)) {
255  $sql .= " AND co.code = '".$this->db->escape($mysoc->country_code)."'";
256  }
257  $sql .= " ORDER BY c.label ASC";
258  }
259 
260  dol_syslog(get_class($this).'::'.__METHOD__, LOG_DEBUG);
261  $resql = $this->db->query($sql);
262  if ($resql) {
263  $num = $this->db->num_rows($resql);
264  if ($num) {
265  $out = '<select class="flat minwidth200" id="'.$htmlname.'" name="'.$htmlname.'">';
266  $i = 0;
267 
268  if ($useempty) {
269  $out .= '<option value="0">&nbsp;</option>';
270  }
271  while ($i < $num) {
272  $obj = $this->db->fetch_object($resql);
273  $out .= '<option value="'.$obj->rowid.'"';
274  if ($obj->rowid == $selected) {
275  $out .= ' selected';
276  }
277  $out .= '>';
278  $titletoshow = dol_string_nohtmltag(($maxlen ? dol_trunc($obj->type, $maxlen) : $obj->type).' ('.$obj->range_account.')');
279  $out .= dol_escape_htmltag($titletoshow);
280  $out .= '</option>';
281  $i++;
282  }
283  $out .= '</select>';
284  //if ($user->admin && $help) $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
285  } else {
286  $out = $langs->trans("ErrorNoAccountingCategoryForThisCountry", $mysoc->country_code);
287  }
288  } else {
289  dol_print_error($this->db);
290  }
291 
292  $out .= ajax_combobox($htmlname, array());
293 
294  print $out;
295  }
296 
297  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
305  public function select_bookkeeping_importkey($htmlname = 'importkey', $selectedkey = '')
306  {
307  // phpcs:enable
308  $options = array();
309 
310  $sql = "SELECT DISTINCT import_key FROM ".$this->db->prefix()."accounting_bookkeeping";
311  $sql .= " WHERE entity IN (".getEntity('accountancy').")";
312  $sql .= ' ORDER BY import_key DESC';
313 
314  dol_syslog(get_class($this)."::select_bookkeeping_importkey", LOG_DEBUG);
315  $resql = $this->db->query($sql);
316 
317  if (!$resql) {
318  $this->error = "Error ".$this->db->lasterror();
319  dol_syslog(get_class($this)."::select_bookkeeping_importkey ".$this->error, LOG_ERR);
320  return -1;
321  }
322 
323  while ($obj = $this->db->fetch_object($resql)) {
324  $options[$obj->import_key] = $obj->import_key;
325  }
326 
327  return Form::selectarray($htmlname, $options, $selectedkey);
328  }
329 
330  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
344  public function select_account($selectid, $htmlname = 'account', $showempty = 0, $event = array(), $select_in = 0, $select_out = 0, $morecss = 'minwidth100 maxwidth300 maxwidthonsmartphone', $usecache = '')
345  {
346  // phpcs:enable
347  global $conf, $langs;
348 
349  require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
350 
351  $out = '';
352 
353  $options = array();
354 
355  if ($showempty == 2) {
356  $options['0'] = '--- '.$langs->trans("None").' ---';
357  }
358 
359  if ($usecache && !empty($this->options_cache[$usecache])) {
360  $options = $options + $this->options_cache[$usecache]; // We use + instead of array_merge because we don't want to reindex key from 0
361  $selected = $selectid;
362  } else {
363  $trunclength = empty($conf->global->ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT) ? 50 : $conf->global->ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT;
364 
365  $sql = "SELECT DISTINCT aa.account_number, aa.label, aa.labelshort, aa.rowid, aa.fk_pcg_version";
366  $sql .= " FROM ".$this->db->prefix()."accounting_account as aa";
367  $sql .= " INNER JOIN ".$this->db->prefix()."accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
368  $sql .= " AND asy.rowid = ".((int) $conf->global->CHARTOFACCOUNTS);
369  $sql .= " AND aa.active = 1";
370  $sql .= " AND aa.entity=".$conf->entity;
371  $sql .= " ORDER BY aa.account_number";
372 
373  dol_syslog(get_class($this)."::select_account", LOG_DEBUG);
374  $resql = $this->db->query($sql);
375 
376  if (!$resql) {
377  $this->error = "Error ".$this->db->lasterror();
378  dol_syslog(get_class($this)."::select_account ".$this->error, LOG_ERR);
379  return -1;
380  }
381 
382  $num_rows = $this->db->num_rows($resql);
383 
384  if ($num_rows == 0 && (empty($conf->global->CHARTOFACCOUNTS) || $conf->global->CHARTOFACCOUNTS < 0)) {
385  $langs->load("errors");
386  $showempty = $langs->trans("ErrorYouMustFirstSetupYourChartOfAccount");
387  } else {
388  $selected = $selectid; // selectid can be -1, 0, 123
389  while ($obj = $this->db->fetch_object($resql)) {
390  if (empty($obj->labelshort)) {
391  $labeltoshow = $obj->label;
392  } else {
393  $labeltoshow = $obj->labelshort;
394  }
395 
396  $label = length_accountg($obj->account_number).' - '.$labeltoshow;
397  $label = dol_trunc($label, $trunclength);
398 
399  $select_value_in = $obj->rowid;
400  $select_value_out = $obj->rowid;
401 
402  // Try to guess if we have found default value
403  if ($select_in == 1) {
404  $select_value_in = $obj->account_number;
405  }
406  if ($select_out == 1) {
407  $select_value_out = $obj->account_number;
408  }
409  // Remember guy's we store in database llx_facturedet the rowid of accounting_account and not the account_number
410  // Because same account_number can be share between different accounting_system and do have the same meaning
411  if ($selectid != '' && $selectid == $select_value_in) {
412  //var_dump("Found ".$selectid." ".$select_value_in);
413  $selected = $select_value_out;
414  }
415 
416  $options[$select_value_out] = $label;
417  }
418  }
419 
420  $this->db->free($resql);
421 
422  if ($usecache) {
423  $this->options_cache[$usecache] = $options;
424  unset($this->options_cache[$usecache]['0']);
425  }
426  }
427 
428  $out .= Form::selectarray($htmlname, $options, $selected, ($showempty ? (is_numeric($showempty) ? 1 : $showempty): 0), 0, 0, '', 0, 0, 0, '', $morecss, 1);
429 
430  return $out;
431  }
432 
433  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
445  public function select_auxaccount($selectid, $htmlname = 'account_num_aux', $showempty = 0, $morecss = 'maxwidth250', $usecache = '', $labelhtmlname = '')
446  {
447  // phpcs:enable
448 
449  $aux_account = array();
450 
451  if ($usecache && !empty($this->options_cache[$usecache])) {
452  $aux_account = $aux_account + $this->options_cache[$usecache]; // We use + instead of array_merge because we don't want to reindex key from 0
453  } else {
454  dol_syslog(get_class($this)."::select_auxaccount", LOG_DEBUG);
455 
456  // Auxiliary thirdparties account
457  $sql = "SELECT code_compta, code_compta_fournisseur, nom as name";
458  $sql .= " FROM ".$this->db->prefix()."societe";
459  $sql .= " WHERE entity IN (".getEntity('societe').")";
460  $sql .= " AND (client IN (1,3) OR fournisseur = 1)";
461 
462  $resql = $this->db->query($sql);
463  if ($resql) {
464  while ($obj = $this->db->fetch_object($resql)) {
465  if (!empty($obj->code_compta)) {
466  $aux_account[$obj->code_compta] = $obj->code_compta.' <span class="opacitymedium">('.$obj->name.')</span>';
467  }
468  if (!empty($obj->code_compta_fournisseur)) {
469  $aux_account[$obj->code_compta_fournisseur] = $obj->code_compta_fournisseur.' <span class="opacitymedium">('.$obj->name.')</span>';
470  }
471  }
472  } else {
473  $this->error = "Error ".$this->db->lasterror();
474  dol_syslog(get_class($this)."::select_auxaccount ".$this->error, LOG_ERR);
475  return -1;
476  }
477 
478  ksort($aux_account);
479 
480  $this->db->free($resql);
481 
482  // Auxiliary user account
483  $sql = "SELECT DISTINCT accountancy_code, lastname, firstname ";
484  $sql .= " FROM ".$this->db->prefix()."user";
485  $sql .= " WHERE entity IN (".getEntity('user').")";
486  $sql .= " ORDER BY accountancy_code";
487 
488  $resql = $this->db->query($sql);
489  if ($resql) {
490  while ($obj = $this->db->fetch_object($resql)) {
491  if (!empty($obj->accountancy_code)) {
492  $aux_account[$obj->accountancy_code] = $obj->accountancy_code.' <span class="opacitymedium">('.dolGetFirstLastname($obj->firstname, $obj->lastname).')</span>';
493  }
494  }
495  } else {
496  $this->error = "Error ".$this->db->lasterror();
497  dol_syslog(get_class($this)."::select_auxaccount ".$this->error, LOG_ERR);
498  return -1;
499  }
500  $this->db->free($resql);
501 
502  if ($usecache) {
503  $this->options_cache[$usecache] = $aux_account;
504  }
505  }
506 
507  // Build select
508  $out = '';
509  $out .= Form::selectarray($htmlname, $aux_account, $selectid, ($showempty ? (is_numeric($showempty) ? 1 : $showempty): 0), 0, 0, '', 0, 0, 0, '', $morecss, 1);
510  //automatic filling if we give the name of the subledger_label input
511  if (!empty($conf->use_javascript_ajax) && !empty($labelhtmlname)) {
512  $out .= '<script>
513  jQuery(document).ready(() => {
514  $("#'.$htmlname.'").on("select2:select", function(e) {
515  var regExp = /\(([^)]+)\)/;
516  const match = regExp.exec(e.params.data.text);
517  $(\'input[name="'.dol_escape_js($labelhtmlname).'"]\').val(match[1]);
518  });
519  });
520 
521  </script>';
522  }
523 
524  return $out;
525  }
526 
527  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
537  public function selectyear_accountancy_bookkepping($selected = '', $htmlname = 'yearid', $useempty = 0, $output_format = 'html')
538  {
539  // phpcs:enable
540  global $conf;
541 
542  $out_array = array();
543 
544  $sql = "SELECT DISTINCT date_format(doc_date, '%Y') as dtyear";
545  $sql .= " FROM ".$this->db->prefix()."accounting_bookkeeping";
546  $sql .= " WHERE entity IN (".getEntity('accountancy').")";
547  $sql .= " ORDER BY date_format(doc_date, '%Y')";
548  dol_syslog(__METHOD__, LOG_DEBUG);
549  $resql = $this->db->query($sql);
550 
551  if (!$resql) {
552  $this->error = "Error ".$this->db->lasterror();
553  dol_syslog(__METHOD__.$this->error, LOG_ERR);
554  return -1;
555  }
556  while ($obj = $this->db->fetch_object($resql)) {
557  $out_array[$obj->dtyear] = $obj->dtyear;
558  }
559  $this->db->free($resql);
560 
561  if ($output_format == 'html') {
562  return Form::selectarray($htmlname, $out_array, $selected, $useempty, 0, 0, 'placeholder="aa"');
563  } else {
564  return $out_array;
565  }
566  }
567 }
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto= 'UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
select_accounting_category($selected= '', $htmlname= 'account_category', $useempty=0, $maxlen=0, $help=1, $allcountries=0)
Return list of accounting category.
$conf db
API class for accounts.
Definition: inc.php:41
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
select_auxaccount($selectid, $htmlname= 'account_num_aux', $showempty=0, $morecss= 'maxwidth250', $usecache= '', $labelhtmlname= '')
Return list of auxilary accounts.
selectyear_accountancy_bookkepping($selected= '', $htmlname= 'yearid', $useempty=0, $output_format= 'html')
Return HTML combo list of years existing into book keepping.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags= '', $escapeonlyhtmltags=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields...
Class to manage generation of HTML components Only common components must be here.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete= 'resolve', $idforemptyvalue= '-1')
Convert a html select field into an ajax combobox.
Definition: ajax.lib.php:429
if(isModEnabled('facture')&&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur')&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)&&$user->rights->fournisseur->facture->lire)||(isModEnabled('supplier_invoice')&&$user->rights->supplier_invoice->lire)) if(isModEnabled('don')&&!empty($user->rights->don->lire)) if(isModEnabled('tax')&&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture')&&isModEnabled('commande')&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
Definition: index.php:742
static selectarray($htmlname, $array, $id= '', $show_empty=0, $key_in_label=0, $value_as_key=0, $moreparam= '', $translate=0, $maxlen=0, $disabled=0, $sort= '', $morecss= '', $addjscombo=1, $moreparamonempty= '', $disablebademail=0, $nohtmlescape=0)
Return a HTML select string, built from an array of key+value.
multi_select_journal($selectedIds=array(), $htmlname= 'journal', $nature=0, $showempty=0, $select_in=0, $select_out=0, $morecss= '', $usecache= '', $disabledajaxcombo=0)
Return list of journals with label by nature.
select_journal($selectid, $htmlname= 'journal', $nature=0, $showempty=0, $select_in=0, $select_out=0, $morecss= 'maxwidth300 maxwidthonsmartphone', $usecache= '', $disabledajaxcombo=0)
Return list of journals with label by nature.
Class to manage generation of HTML components for accounting management.
dol_print_error($db= '', $error= '', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
static multiselectarray($htmlname, $array, $selected=array(), $key_in_label=0, $value_as_key=0, $morecss= '', $translate=0, $width=0, $moreattrib= '', $elemtype= '', $placeholder= '', $addjscombo=-1)
Show a multiselect form from an array.
dol_trunc($string, $size=40, $trunc= 'right', $stringencoding= 'UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding &#39;…&#39; if string larger than length. ...
select_bookkeeping_importkey($htmlname= 'importkey', $selectedkey= '')
Return select filter with date of transaction.
length_accountg($account)
Return General accounting account with defined length (used for product and miscellaneous) ...
__construct($db)
Constructor.
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
select_account($selectid, $htmlname= 'account', $showempty=0, $event=array(), $select_in=0, $select_out=0, $morecss= 'minwidth100 maxwidth300 maxwidthonsmartphone', $usecache= '')
Return list of accounts with label by chart of accounts.