1<?php 2/* Copyright (C) 2008-2012 Laurent Destailleur <eldy@users.sourceforge.net> 3 * Copyright (C) 2008-2012 Regis Houssin <regis.houssin@inodbox.com> 4 * Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es> 5 * Copyright (C) 2017 Rui Strecht <rui.strecht@aliartalentos.com> 6 * Copyright (C) 2020 Open-Dsi <support@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 22/** 23 * \file htdocs/core/class/html.formcompany.class.php 24 * \ingroup core 25 * \brief File of class to build HTML component for third parties management 26 */ 27 28 29/** 30 * Class to build HTML component for third parties management 31 * Only common components are here. 32 */ 33 34require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; 35 36 37/** 38 * Class of forms component to manage companies 39 */ 40class FormCompany extends Form 41{ 42 43 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 44 /** 45 * Return list of labels (translated) of third parties type 46 * 47 * @param int $mode 0=Return id+label, 1=Return code+label 48 * @param string $filter Add a SQL filter to select 49 * @return array Array of types 50 */ 51 public function typent_array($mode = 0, $filter = '') 52 { 53 // phpcs:enable 54 global $langs, $mysoc; 55 56 $effs = array(); 57 58 $sql = "SELECT id, code, libelle"; 59 $sql .= " FROM ".MAIN_DB_PREFIX."c_typent"; 60 $sql .= " WHERE active = 1 AND (fk_country IS NULL OR fk_country = ".(empty($mysoc->country_id) ? '0' : $mysoc->country_id).")"; 61 if ($filter) $sql .= " ".$filter; 62 $sql .= " ORDER by position, id"; 63 dol_syslog(get_class($this).'::typent_array', LOG_DEBUG); 64 $resql = $this->db->query($sql); 65 if ($resql) 66 { 67 $num = $this->db->num_rows($resql); 68 $i = 0; 69 70 while ($i < $num) 71 { 72 $objp = $this->db->fetch_object($resql); 73 if (!$mode) $key = $objp->id; 74 else $key = $objp->code; 75 if ($langs->trans($objp->code) != $objp->code) $effs[$key] = $langs->trans($objp->code); 76 else $effs[$key] = $objp->libelle; 77 if ($effs[$key] == '-') $effs[$key] = ''; 78 $i++; 79 } 80 $this->db->free($resql); 81 } 82 83 return $effs; 84 } 85 86 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 87 /** 88 * Renvoie la liste des types d'effectifs possibles (pas de traduction car nombre) 89 * 90 * @param int $mode 0=renvoi id+libelle, 1=renvoi code+libelle 91 * @param string $filter Add a SQL filter to select 92 * @return array Array of types d'effectifs 93 */ 94 public function effectif_array($mode = 0, $filter = '') 95 { 96 // phpcs:enable 97 $effs = array(); 98 99 $sql = "SELECT id, code, libelle"; 100 $sql .= " FROM ".MAIN_DB_PREFIX."c_effectif"; 101 $sql .= " WHERE active = 1"; 102 if ($filter) $sql .= " ".$filter; 103 $sql .= " ORDER BY id ASC"; 104 dol_syslog(get_class($this).'::effectif_array', LOG_DEBUG); 105 $resql = $this->db->query($sql); 106 if ($resql) 107 { 108 $num = $this->db->num_rows($resql); 109 $i = 0; 110 111 while ($i < $num) 112 { 113 $objp = $this->db->fetch_object($resql); 114 if (!$mode) $key = $objp->id; 115 else $key = $objp->code; 116 117 $effs[$key] = $objp->libelle != '-' ? $objp->libelle : ''; 118 $i++; 119 } 120 $this->db->free($resql); 121 } 122 return $effs; 123 } 124 125 126 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 127 /** 128 * Affiche formulaire de selection des modes de reglement 129 * 130 * @param int $page Page 131 * @param int $selected Id or code preselected 132 * @param string $htmlname Nom du formulaire select 133 * @param int $empty Add empty value in list 134 * @return void 135 */ 136 public function form_prospect_level($page, $selected = '', $htmlname = 'prospect_level_id', $empty = 0) 137 { 138 // phpcs:enable 139 global $user, $langs; 140 141 print '<form method="post" action="'.$page.'">'; 142 print '<input type="hidden" name="action" value="setprospectlevel">'; 143 print '<input type="hidden" name="token" value="'.newToken().'">'; 144 145 dol_syslog(get_class($this).'::form_prospect_level', LOG_DEBUG); 146 $sql = "SELECT code, label"; 147 $sql .= " FROM ".MAIN_DB_PREFIX."c_prospectlevel"; 148 $sql .= " WHERE active > 0"; 149 $sql .= " ORDER BY sortorder"; 150 $resql = $this->db->query($sql); 151 if ($resql) 152 { 153 $options = array(); 154 155 if ($empty) { 156 $options[''] = ''; 157 } 158 159 while ($obj = $this->db->fetch_object($resql)) { 160 $level = $langs->trans($obj->code); 161 162 if ($level == $obj->code) { 163 $level = $langs->trans($obj->label); 164 } 165 166 $options[$obj->code] = $level; 167 } 168 169 print Form::selectarray($htmlname, $options, $selected); 170 } else dol_print_error($this->db); 171 if (!empty($htmlname) && $user->admin) print ' '.info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); 172 print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">'; 173 print '</form>'; 174 } 175 176 /** 177 * Affiche formulaire de selection des niveau de prospection pour les contacts 178 * 179 * @param int $page Page 180 * @param int $selected Id or code preselected 181 * @param string $htmlname Nom du formulaire select 182 * @param int $empty Add empty value in list 183 * @return void 184 */ 185 public function formProspectContactLevel($page, $selected = '', $htmlname = 'prospect_contact_level_id', $empty = 0) 186 { 187 global $user, $langs; 188 189 print '<form method="post" action="'.$page.'">'; 190 print '<input type="hidden" name="action" value="setprospectcontactlevel">'; 191 print '<input type="hidden" name="token" value="'.newToken().'">'; 192 193 dol_syslog(__METHOD__, LOG_DEBUG); 194 $sql = "SELECT code, label"; 195 $sql .= " FROM ".MAIN_DB_PREFIX."c_prospectcontactlevel"; 196 $sql .= " WHERE active > 0"; 197 $sql .= " ORDER BY sortorder"; 198 $resql = $this->db->query($sql); 199 if ($resql) 200 { 201 $options = array(); 202 203 if ($empty) 204 { 205 $options[''] = ''; 206 } 207 208 while ($obj = $this->db->fetch_object($resql)) 209 { 210 $level = $langs->trans($obj->code); 211 212 if ($level == $obj->code) 213 { 214 $level = $langs->trans($obj->label); 215 } 216 217 $options[$obj->code] = $level; 218 } 219 220 print Form::selectarray($htmlname, $options, $selected); 221 } 222 else dol_print_error($this->db); 223 if (!empty($htmlname) && $user->admin) print ' '.info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); 224 print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">'; 225 print '</form>'; 226 } 227 228 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 229 /** 230 * Returns the drop-down list of departments/provinces/cantons for all countries or for a given country. 231 * In the case of an all-country list, the display breaks on the country. 232 * The key of the list is the code (there can be several entries for a given code but in this case, the country field differs). 233 * Thus the links with the departments are done on a department independently of its name. 234 * 235 * @param string $selected Code state preselected 236 * @param int $country_codeid 0=list for all countries, otherwise country code or country rowid to show 237 * @param string $htmlname Id of department 238 * @return void 239 */ 240 public function select_departement($selected = '', $country_codeid = 0, $htmlname = 'state_id') 241 { 242 // phpcs:enable 243 print $this->select_state($selected, $country_codeid, $htmlname); 244 } 245 246 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 247 /** 248 * Returns the drop-down list of departments/provinces/cantons for all countries or for a given country. 249 * In the case of an all-country list, the display breaks on the country. 250 * The key of the list is the code (there can be several entries for a given code but in this case, the country field differs). 251 * Thus the links with the departments are done on a department independently of its name. 252 * 253 * @param int $selected Code state preselected (mus be state id) 254 * @param integer $country_codeid Country code or id: 0=list for all countries, otherwise country code or country rowid to show 255 * @param string $htmlname Id of department. If '', we want only the string with <option> 256 * @return string String with HTML select 257 * @see select_country() 258 */ 259 public function select_state($selected = 0, $country_codeid = 0, $htmlname = 'state_id') 260 { 261 // phpcs:enable 262 global $conf, $langs, $user; 263 264 dol_syslog(get_class($this)."::select_departement selected=".$selected.", country_codeid=".$country_codeid, LOG_DEBUG); 265 266 $langs->load("dict"); 267 268 $out = ''; 269 270 // Serch departements/cantons/province active d'une region et pays actif 271 $sql = "SELECT d.rowid, d.code_departement as code, d.nom as name, d.active, c.label as country, c.code as country_code, r.nom as region_name FROM"; 272 $sql .= " ".MAIN_DB_PREFIX."c_departements as d, ".MAIN_DB_PREFIX."c_regions as r,".MAIN_DB_PREFIX."c_country as c"; 273 $sql .= " WHERE d.fk_region=r.code_region and r.fk_pays=c.rowid"; 274 $sql .= " AND d.active = 1 AND r.active = 1 AND c.active = 1"; 275 if ($country_codeid && is_numeric($country_codeid)) $sql .= " AND c.rowid = '".$this->db->escape($country_codeid)."'"; 276 if ($country_codeid && !is_numeric($country_codeid)) $sql .= " AND c.code = '".$this->db->escape($country_codeid)."'"; 277 $sql .= " ORDER BY c.code, d.code_departement"; 278 279 $result = $this->db->query($sql); 280 if ($result) 281 { 282 if (!empty($htmlname)) $out .= '<select id="'.$htmlname.'" class="flat maxwidth200onsmartphone minwidth300" name="'.$htmlname.'">'; 283 if ($country_codeid) $out .= '<option value="0"> </option>'; 284 $num = $this->db->num_rows($result); 285 $i = 0; 286 dol_syslog(get_class($this)."::select_departement num=".$num, LOG_DEBUG); 287 if ($num) 288 { 289 $country = ''; 290 while ($i < $num) 291 { 292 $obj = $this->db->fetch_object($result); 293 if ($obj->code == '0') // Le code peut etre une chaine 294 { 295 $out .= '<option value="0"> </option>'; 296 } else { 297 if (!$country || $country != $obj->country) 298 { 299 // Affiche la rupture si on est en mode liste multipays 300 if (!$country_codeid && $obj->country_code) 301 { 302 $out .= '<option value="-1" disabled>----- '.$obj->country." -----</option>\n"; 303 $country = $obj->country; 304 } 305 } 306 307 if (!empty($selected) && $selected == $obj->rowid) 308 { 309 $out .= '<option value="'.$obj->rowid.'" selected>'; 310 } else { 311 $out .= '<option value="'.$obj->rowid.'">'; 312 } 313 314 // Si traduction existe, on l'utilise, sinon on prend le libelle par defaut 315 if (!empty($conf->global->MAIN_SHOW_STATE_CODE) && 316 ($conf->global->MAIN_SHOW_STATE_CODE == 1 || $conf->global->MAIN_SHOW_STATE_CODE == 2 || $conf->global->MAIN_SHOW_STATE_CODE === 'all')) { 317 if (!empty($conf->global->MAIN_SHOW_REGION_IN_STATE_SELECT) && $conf->global->MAIN_SHOW_REGION_IN_STATE_SELECT == 1) { 318 $out .= $obj->region_name.' - '.$obj->code.' - '.($langs->trans($obj->code) != $obj->code ? $langs->trans($obj->code) : ($obj->name != '-' ? $obj->name : '')); 319 } else { 320 $out .= $obj->code.' - '.($langs->trans($obj->code) != $obj->code ? $langs->trans($obj->code) : ($obj->name != '-' ? $obj->name : '')); 321 } 322 } else { 323 if (!empty($conf->global->MAIN_SHOW_REGION_IN_STATE_SELECT) && $conf->global->MAIN_SHOW_REGION_IN_STATE_SELECT == 1) { 324 $out .= $obj->region_name.' - '.($langs->trans($obj->code) != $obj->code ? $langs->trans($obj->code) : ($obj->name != '-' ? $obj->name : '')); 325 } else { 326 $out .= ($langs->trans($obj->code) != $obj->code ? $langs->trans($obj->code) : ($obj->name != '-' ? $obj->name : '')); 327 } 328 } 329 330 $out .= '</option>'; 331 } 332 $i++; 333 } 334 } 335 if (!empty($htmlname)) $out .= '</select>'; 336 if (!empty($htmlname) && $user->admin) $out .= ' '.info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); 337 } else { 338 dol_print_error($this->db); 339 } 340 341 // Make select dynamic 342 if (!empty($htmlname)) 343 { 344 include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; 345 $out .= ajax_combobox($htmlname); 346 } 347 348 return $out; 349 } 350 351 352 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 353 /** 354 * Retourne la liste deroulante des regions actives dont le pays est actif 355 * La cle de la liste est le code (il peut y avoir plusieurs entree pour 356 * un code donnee mais dans ce cas, le champ pays et lang differe). 357 * Ainsi les liens avec les regions se font sur une region independemment de son name. 358 * 359 * @param string $selected Preselected value 360 * @param string $htmlname Name of HTML select field 361 * @return void 362 */ 363 public function select_region($selected = '', $htmlname = 'region_id') 364 { 365 // phpcs:enable 366 global $conf, $langs; 367 $langs->load("dict"); 368 369 $sql = "SELECT r.rowid, r.code_region as code, r.nom as label, r.active, c.code as country_code, c.label as country"; 370 $sql .= " FROM ".MAIN_DB_PREFIX."c_regions as r, ".MAIN_DB_PREFIX."c_country as c"; 371 $sql .= " WHERE r.fk_pays=c.rowid AND r.active = 1 and c.active = 1"; 372 $sql .= " ORDER BY c.code, c.label ASC"; 373 374 dol_syslog(get_class($this)."::select_region", LOG_DEBUG); 375 $resql = $this->db->query($sql); 376 if ($resql) 377 { 378 print '<select class="flat" id="'.$htmlname.'" name="'.$htmlname.'">'; 379 $num = $this->db->num_rows($resql); 380 $i = 0; 381 if ($num) 382 { 383 $country = ''; 384 while ($i < $num) 385 { 386 $obj = $this->db->fetch_object($resql); 387 if ($obj->code == 0) { 388 print '<option value="0"> </option>'; 389 } else { 390 if ($country == '' || $country != $obj->country) 391 { 392 // Show break 393 $key = $langs->trans("Country".strtoupper($obj->country_code)); 394 $valuetoshow = ($key != "Country".strtoupper($obj->country_code)) ? $obj->country_code." - ".$key : $obj->country; 395 print '<option value="-1" disabled>----- '.$valuetoshow." -----</option>\n"; 396 $country = $obj->country; 397 } 398 399 if ($selected > 0 && $selected == $obj->code) 400 { 401 print '<option value="'.$obj->code.'" selected>'.$obj->label.'</option>'; 402 } else { 403 print '<option value="'.$obj->code.'">'.$obj->label.'</option>'; 404 } 405 } 406 $i++; 407 } 408 } 409 print '</select>'; 410 print ajax_combobox($htmlname); 411 } else { 412 dol_print_error($this->db); 413 } 414 } 415 416 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 417 /** 418 * Return combo list with people title 419 * 420 * @param string $selected Civility/Title code preselected 421 * @param string $htmlname Name of HTML select combo field 422 * @param string $morecss Add more css on SELECT element 423 * @param int $addjscombo Add js combo 424 * @return string String with HTML select 425 */ 426 public function select_civility($selected = '', $htmlname = 'civility_id', $morecss = 'maxwidth150', $addjscombo = 0) 427 { 428 // phpcs:enable 429 global $conf, $langs, $user; 430 $langs->load("dict"); 431 432 $out = ''; 433 434 $sql = "SELECT rowid, code, label, active FROM ".MAIN_DB_PREFIX."c_civility"; 435 $sql .= " WHERE active = 1"; 436 437 dol_syslog("Form::select_civility", LOG_DEBUG); 438 $resql = $this->db->query($sql); 439 if ($resql) 440 { 441 $out .= '<select class="flat'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.'" id="'.$htmlname.'">'; 442 $out .= '<option value=""> </option>'; 443 $num = $this->db->num_rows($resql); 444 $i = 0; 445 if ($num) 446 { 447 while ($i < $num) 448 { 449 $obj = $this->db->fetch_object($resql); 450 if ($selected == $obj->code) 451 { 452 $out .= '<option value="'.$obj->code.'" selected>'; 453 } else { 454 $out .= '<option value="'.$obj->code.'">'; 455 } 456 // If translation exists, we use it, otherwise, we use tha had coded label 457 $out .= ($langs->trans("Civility".$obj->code) != "Civility".$obj->code ? $langs->trans("Civility".$obj->code) : ($obj->label != '-' ? $obj->label : '')); 458 $out .= '</option>'; 459 $i++; 460 } 461 } 462 $out .= '</select>'; 463 if ($user->admin) $out .= info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); 464 465 if ($addjscombo) { 466 // Enhance with select2 467 include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; 468 $out .= ajax_combobox($htmlname); 469 } 470 } else { 471 dol_print_error($this->db); 472 } 473 474 return $out; 475 } 476 477 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 478 /** 479 * Retourne la liste deroulante des formes juridiques tous pays confondus ou pour un pays donne. 480 * Dans le cas d'une liste tous pays confondu, on affiche une rupture sur le pays. 481 * 482 * @param string $selected Code forme juridique a pre-selectionne 483 * @param mixed $country_codeid 0=liste tous pays confondus, sinon code du pays a afficher 484 * @param string $filter Add a SQL filter on list 485 * @return void 486 * @deprecated Use print xxx->select_juridicalstatus instead 487 * @see select_juridicalstatus() 488 */ 489 public function select_forme_juridique($selected = '', $country_codeid = 0, $filter = '') 490 { 491 // phpcs:enable 492 print $this->select_juridicalstatus($selected, $country_codeid, $filter); 493 } 494 495 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 496 /** 497 * Retourne la liste deroulante des formes juridiques tous pays confondus ou pour un pays donne. 498 * Dans le cas d'une liste tous pays confondu, on affiche une rupture sur le pays 499 * 500 * @param string $selected Preselected code of juridical type 501 * @param int $country_codeid 0=list for all countries, otherwise list only country requested 502 * @param string $filter Add a SQL filter on list 503 * @param string $htmlname HTML name of select 504 * @param string $morecss More CSS 505 * @return string String with HTML select 506 */ 507 public function select_juridicalstatus($selected = '', $country_codeid = 0, $filter = '', $htmlname = 'forme_juridique_code', $morecss = '') 508 { 509 // phpcs:enable 510 global $conf, $langs, $user; 511 $langs->load("dict"); 512 513 $out = ''; 514 515 // On recherche les formes juridiques actives des pays actifs 516 $sql = "SELECT f.rowid, f.code as code , f.libelle as label, f.active, c.label as country, c.code as country_code"; 517 $sql .= " FROM ".MAIN_DB_PREFIX."c_forme_juridique as f, ".MAIN_DB_PREFIX."c_country as c"; 518 $sql .= " WHERE f.fk_pays=c.rowid"; 519 $sql .= " AND f.active = 1 AND c.active = 1"; 520 if ($country_codeid) $sql .= " AND c.code = '".$this->db->escape($country_codeid)."'"; 521 if ($filter) $sql .= " ".$filter; 522 $sql .= " ORDER BY c.code"; 523 524 dol_syslog(get_class($this)."::select_juridicalstatus", LOG_DEBUG); 525 $resql = $this->db->query($sql); 526 if ($resql) 527 { 528 $out .= '<div id="particulier2" class="visible">'; 529 $out .= '<select class="flat minwidth200'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.'" id="'.$htmlname.'">'; 530 if ($country_codeid) $out .= '<option value="0"> </option>'; // When country_codeid is set, we force to add an empty line because it does not appears from select. When not set, we already get the empty line from select. 531 532 $num = $this->db->num_rows($resql); 533 if ($num) 534 { 535 $i = 0; 536 $country = ''; $arraydata = array(); 537 while ($i < $num) 538 { 539 $obj = $this->db->fetch_object($resql); 540 541 if ($obj->code) // We exclude empty line, we will add it later 542 { 543 $labelcountry = (($langs->trans("Country".$obj->country_code) != "Country".$obj->country_code) ? $langs->trans("Country".$obj->country_code) : $obj->country); 544 $labeljs = (($langs->trans("JuridicalStatus".$obj->code) != "JuridicalStatus".$obj->code) ? $langs->trans("JuridicalStatus".$obj->code) : ($obj->label != '-' ? $obj->label : '')); // $obj->label is already in output charset (converted by database driver) 545 $arraydata[$obj->code] = array('code'=>$obj->code, 'label'=>$labeljs, 'label_sort'=>$labelcountry.'_'.$labeljs, 'country_code'=>$obj->country_code, 'country'=>$labelcountry); 546 } 547 $i++; 548 } 549 550 $arraydata = dol_sort_array($arraydata, 'label_sort', 'ASC'); 551 if (empty($country_codeid)) // Introduce empty value (if $country_codeid not empty, empty value was already added) 552 { 553 $arraydata[0] = array('code'=>0, 'label'=>'', 'label_sort'=>'_', 'country_code'=>'', 'country'=>''); 554 } 555 556 foreach ($arraydata as $key => $val) 557 { 558 if (!$country || $country != $val['country']) 559 { 560 // Show break when we are in multi country mode 561 if (empty($country_codeid) && $val['country_code']) 562 { 563 $out .= '<option value="0" disabled class="selectoptiondisabledwhite">----- '.$val['country']." -----</option>\n"; 564 $country = $val['country']; 565 } 566 } 567 568 if ($selected > 0 && $selected == $val['code']) 569 { 570 $out .= '<option value="'.$val['code'].'" selected>'; 571 } else { 572 $out .= '<option value="'.$val['code'].'">'; 573 } 574 // If translation exists, we use it, otherwise we use default label in database 575 $out .= $val['label']; 576 $out .= '</option>'; 577 } 578 } 579 $out .= '</select>'; 580 if ($user->admin) $out .= ' '.info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); 581 582 // Make select dynamic 583 include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; 584 $out .= ajax_combobox($htmlname); 585 586 $out .= '</div>'; 587 } else { 588 dol_print_error($this->db); 589 } 590 591 return $out; 592 } 593 594 595 /** 596 * Output list of third parties. 597 * 598 * @param object $object Object we try to find contacts 599 * @param string $var_id Name of id field 600 * @param string $selected Pre-selected third party 601 * @param string $htmlname Name of HTML form 602 * @param array $limitto Disable answers that are not id in this array list 603 * @param int $forceid This is to force another object id than object->id 604 * @param string $moreparam String with more param to add into url when noajax search is used. 605 * @param string $morecss More CSS on select component 606 * @return int The selected third party ID 607 */ 608 public function selectCompaniesForNewContact($object, $var_id, $selected = '', $htmlname = 'newcompany', $limitto = '', $forceid = 0, $moreparam = '', $morecss = '') 609 { 610 global $conf, $langs; 611 612 if (!empty($conf->use_javascript_ajax) && !empty($conf->global->COMPANY_USE_SEARCH_TO_SELECT)) 613 { 614 // Use Ajax search 615 $minLength = (is_numeric($conf->global->COMPANY_USE_SEARCH_TO_SELECT) ? $conf->global->COMPANY_USE_SEARCH_TO_SELECT : 2); 616 617 $socid = 0; $name = ''; 618 if ($selected > 0) 619 { 620 $tmpthirdparty = new Societe($this->db); 621 $result = $tmpthirdparty->fetch($selected); 622 if ($result > 0) 623 { 624 $socid = $selected; 625 $name = $tmpthirdparty->name; 626 } 627 } 628 629 630 $events = array(); 631 // Add an entry 'method' to say 'yes, we must execute url with param action = method'; 632 // Add an entry 'url' to say which url to execute 633 // Add an entry htmlname to say which element we must change once url is called 634 // Add entry params => array('cssid' => 'attr') to say to remov or add attribute attr if answer of url return 0 or >0 lines 635 // To refresh contacts list on thirdparty list change 636 $events[] = array('method' => 'getContacts', 'url' => dol_buildpath('/core/ajax/contacts.php', 1), 'htmlname' => 'contactid', 'params' => array('add-customer-contact' => 'disabled')); 637 638 if (count($events)) // If there is some ajax events to run once selection is done, we add code here to run events 639 { 640 print '<script type="text/javascript"> 641 jQuery(document).ready(function() { 642 $("#search_'.$htmlname.'").change(function() { 643 var obj = '.json_encode($events).'; 644 $.each(obj, function(key,values) { 645 if (values.method.length) { 646 runJsCodeForEvent'.$htmlname.'(values); 647 } 648 }); 649 650 $(this).trigger("blur"); 651 }); 652 653 // Function used to execute events when search_htmlname change 654 function runJsCodeForEvent'.$htmlname.'(obj) { 655 var id = $("#'.$htmlname.'").val(); 656 var method = obj.method; 657 var url = obj.url; 658 var htmlname = obj.htmlname; 659 var showempty = obj.showempty; 660 console.log("Run runJsCodeForEvent-'.$htmlname.' from selectCompaniesForNewContact id="+id+" method="+method+" showempty="+showempty+" url="+url+" htmlname="+htmlname); 661 $.getJSON(url, 662 { 663 action: method, 664 id: id, 665 htmlname: htmlname 666 }, 667 function(response) { 668 if (response != null) 669 { 670 console.log("Change select#"+htmlname+" with content "+response.value) 671 $.each(obj.params, function(key,action) { 672 if (key.length) { 673 var num = response.num; 674 if (num > 0) { 675 $("#" + key).removeAttr(action); 676 } else { 677 $("#" + key).attr(action, action); 678 } 679 } 680 }); 681 $("select#" + htmlname).html(response.value); 682 } 683 } 684 ); 685 }; 686 }); 687 </script>'; 688 } 689 690 print "\n".'<!-- Input text for third party with Ajax.Autocompleter (selectCompaniesForNewContact) -->'."\n"; 691 print '<input type="text" size="30" id="search_'.$htmlname.'" name="search_'.$htmlname.'" value="'.$name.'" />'; 692 print ajax_autocompleter(($socid ? $socid : -1), $htmlname, DOL_URL_ROOT.'/societe/ajaxcompanies.php', '', $minLength, 0); 693 return $socid; 694 } else { 695 // Search to list thirdparties 696 $sql = "SELECT s.rowid, s.nom as name FROM"; 697 $sql .= " ".MAIN_DB_PREFIX."societe as s"; 698 $sql .= " WHERE s.entity IN (".getEntity('societe').")"; 699 // For ajax search we limit here. For combo list, we limit later 700 if (is_array($limitto) && count($limitto)) 701 { 702 $sql .= " AND s.rowid IN (".join(',', $limitto).")"; 703 } 704 $sql .= " ORDER BY s.nom ASC"; 705 706 $resql = $this->db->query($sql); 707 if ($resql) 708 { 709 print '<select class="flat'.($morecss ? ' '.$morecss : '').'" id="'.$htmlname.'" name="'.$htmlname.'"'; 710 if ($conf->use_javascript_ajax) 711 { 712 $javaScript = "window.location='".$_SERVER['PHP_SELF']."?".$var_id."=".($forceid > 0 ? $forceid : $object->id).$moreparam."&".$htmlname."=' + form.".$htmlname.".options[form.".$htmlname.".selectedIndex].value;"; 713 print ' onChange="'.$javaScript.'"'; 714 } 715 print '>'; 716 $num = $this->db->num_rows($resql); 717 $i = 0; 718 if ($num) 719 { 720 while ($i < $num) 721 { 722 $obj = $this->db->fetch_object($resql); 723 if ($i == 0) $firstCompany = $obj->rowid; 724 $disabled = 0; 725 if (is_array($limitto) && count($limitto) && !in_array($obj->rowid, $limitto)) $disabled = 1; 726 if ($selected > 0 && $selected == $obj->rowid) 727 { 728 print '<option value="'.$obj->rowid.'"'; 729 if ($disabled) print ' disabled'; 730 print ' selected>'.dol_trunc($obj->name, 24).'</option>'; 731 $firstCompany = $obj->rowid; 732 } else { 733 print '<option value="'.$obj->rowid.'"'; 734 if ($disabled) print ' disabled'; 735 print '>'.dol_trunc($obj->name, 24).'</option>'; 736 } 737 $i++; 738 } 739 } 740 print "</select>\n"; 741 print ajax_combobox($htmlname); 742 return $firstCompany; 743 } else { 744 dol_print_error($this->db); 745 return 0; 746 } 747 } 748 } 749 750 /** 751 * Return a select list with types of contacts 752 * 753 * @param object $object Object to use to find type of contact 754 * @param string $selected Default selected value 755 * @param string $htmlname HTML select name 756 * @param string $source Source ('internal' or 'external') 757 * @param string $sortorder Sort criteria ('position', 'code', ...) 758 * @param int $showempty 1=Add en empty line 759 * @param string $morecss Add more css to select component 760 * @return void 761 */ 762 public function selectTypeContact($object, $selected, $htmlname = 'type', $source = 'internal', $sortorder = 'position', $showempty = 0, $morecss = '') 763 { 764 global $user, $langs; 765 766 if (is_object($object) && method_exists($object, 'liste_type_contact')) 767 { 768 $lesTypes = $object->liste_type_contact($source, $sortorder, 0, 1); 769 770 print '<select class="flat valignmiddle'.($morecss ? ' '.$morecss : '').'" name="'.$htmlname.'" id="'.$htmlname.'">'; 771 if ($showempty) print '<option value="0"></option>'; 772 foreach ($lesTypes as $key=>$value) 773 { 774 print '<option value="'.$key.'"'; 775 if ($key == $selected) print ' selected'; 776 print '>'.$value.'</option>'; 777 } 778 print "</select>"; 779 if ($user->admin) print ' '.info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); 780 781 print ajax_combobox($htmlname); 782 783 print "\n"; 784 } 785 } 786 787 /** 788 * showContactRoles on view and edit mode 789 * 790 * @param string $htmlname Html component name and id 791 * @param Contact $contact Contact Obejct 792 * @param string $rendermode view, edit 793 * @param array $selected $key=>$val $val is selected Roles for input mode 794 * @return string String with contacts roles 795 */ 796 public function showRoles($htmlname, Contact $contact, $rendermode = 'view', $selected = array()) 797 { 798 if ($rendermode === 'view') { 799 $toprint = array(); 800 foreach ($contact->roles as $key => $val) { 801 $toprint[] = '<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #bbb;">'.$val['label'].'</li>'; 802 } 803 return '<div class="select2-container-multi-dolibarr" style="width: 90%;" id="'.$htmlname.'"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>'; 804 } 805 806 if ($rendermode === 'edit') 807 { 808 $contactType = $contact->listeTypeContacts('external', '', 1, '', '', 'agenda'); // We exclude agenda as there is no contact on such element 809 if (count($selected) > 0) { 810 $newselected = array(); 811 foreach ($selected as $key=>$val) { 812 if (is_array($val) && array_key_exists('id', $val) && in_array($val['id'], array_keys($contactType))) { 813 $newselected[] = $val['id']; 814 } else { 815 break; 816 } 817 } 818 if (count($newselected) > 0) $selected = $newselected; 819 } 820 return $this->multiselectarray($htmlname, $contactType, $selected); 821 } 822 823 return 'ErrorBadValueForParameterRenderMode'; // Should not happened 824 } 825 826 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 827 /** 828 * Return a select list with zip codes and their town 829 * 830 * @param string $selected Preselected value 831 * @param string $htmlname HTML select name 832 * @param array $fields Array with key of fields to refresh after selection 833 * @param int $fieldsize Field size 834 * @param int $disableautocomplete 1 To disable ajax autocomplete features (browser autocomplete may still occurs) 835 * @param string $moreattrib Add more attribute on HTML input field 836 * @param string $morecss More css 837 * @return string 838 */ 839 public function select_ziptown($selected = '', $htmlname = 'zipcode', $fields = '', $fieldsize = 0, $disableautocomplete = 0, $moreattrib = '', $morecss = '') 840 { 841 // phpcs:enable 842 global $conf; 843 844 $out = ''; 845 846 $size = ''; 847 if (!empty($fieldsize)) $size = 'size="'.$fieldsize.'"'; 848 849 if ($conf->use_javascript_ajax && empty($disableautocomplete)) 850 { 851 $out .= ajax_multiautocompleter($htmlname, $fields, DOL_URL_ROOT.'/core/ajax/ziptown.php')."\n"; 852 $moreattrib .= ' autocomplete="off"'; 853 } 854 $out .= '<input id="'.$htmlname.'" class="maxwidthonsmartphone'.($morecss ? ' '.$morecss : '').'" type="text"'.($moreattrib ? ' '.$moreattrib : '').' name="'.$htmlname.'" '.$size.' value="'.$selected.'">'."\n"; 855 856 return $out; 857 } 858 859 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 860 /** 861 * Return HTML string to use as input of professional id into a HTML page (siren, siret, etc...) 862 * 863 * @param int $idprof 1,2,3,4 (Example: 1=siren,2=siret,3=naf,4=rcs/rm) 864 * @param string $htmlname Name of HTML select 865 * @param string $preselected Default value to show 866 * @param string $country_code FR, IT, ... 867 * @param string $morecss More css 868 * @return string HTML string with prof id 869 */ 870 public function get_input_id_prof($idprof, $htmlname, $preselected, $country_code, $morecss = 'maxwidth100onsmartphone quatrevingtpercent') 871 { 872 // phpcs:enable 873 global $conf, $langs, $hookmanager; 874 875 $formlength = 0; 876 if (empty($conf->global->MAIN_DISABLEPROFIDRULES)) { 877 if ($country_code == 'FR') 878 { 879 if (isset($idprof)) { 880 if ($idprof == 1) $formlength = 9; 881 elseif ($idprof == 2) $formlength = 14; 882 elseif ($idprof == 3) $formlength = 5; // 4 chiffres et 1 lettre depuis janvier 883 elseif ($idprof == 4) $formlength = 32; // No maximum as we need to include a town name in this id 884 } 885 } elseif ($country_code == 'ES') 886 { 887 if ($idprof == 1) $formlength = 9; //CIF/NIF/NIE 9 digits 888 if ($idprof == 2) $formlength = 12; //NASS 12 digits without / 889 if ($idprof == 3) $formlength = 5; //CNAE 5 digits 890 if ($idprof == 4) $formlength = 32; //depend of college 891 } 892 } 893 894 $selected = $preselected; 895 if (!$selected && isset($idprof)) { 896 if ($idprof == 1 && !empty($this->idprof1)) $selected = $this->idprof1; 897 elseif ($idprof == 2 && !empty($this->idprof2)) $selected = $this->idprof2; 898 elseif ($idprof == 3 && !empty($this->idprof3)) $selected = $this->idprof3; 899 elseif ($idprof == 4 && !empty($this->idprof4)) $selected = $this->idprof4; 900 } 901 902 $maxlength = $formlength; 903 if (empty($formlength)) { $formlength = 24; $maxlength = 128; } 904 905 $out = ''; 906 907 // Execute hook getInputIdProf to complete or replace $out 908 $parameters = array('formlength'=>$formlength, 'selected'=>$preselected, 'idprof'=>$idprof, 'htmlname'=>$htmlname, 'country_code'=>$country_code); 909 $reshook = $hookmanager->executeHooks('getInputIdProf', $parameters); 910 if (empty($reshook)) 911 { 912 $out .= '<input type="text" '.($morecss ? 'class="'.$morecss.'" ' : '').'name="'.$htmlname.'" id="'.$htmlname.'" maxlength="'.$maxlength.'" value="'.$selected.'">'; 913 } 914 $out .= $hookmanager->resPrint; 915 916 return $out; 917 } 918 919 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 920 /** 921 * Return a HTML select with localtax values for thirdparties 922 * 923 * @param int $local LocalTax 924 * @param int $selected Preselected value 925 * @param string $htmlname HTML select name 926 * @return void 927 */ 928 public function select_localtax($local, $selected, $htmlname) 929 { 930 // phpcs:enable 931 $tax = get_localtax_by_third($local); 932 933 $num = $this->db->num_rows($tax); 934 $i = 0; 935 if ($num) 936 { 937 $valors = explode(":", $tax); 938 939 if (count($valors) > 1) 940 { 941 //montar select 942 print '<select class="flat" name="'.$htmlname.'" id="'.$htmlname.'">'; 943 while ($i <= (count($valors)) - 1) 944 { 945 if ($selected == $valors[$i]) 946 { 947 print '<option value="'.$valors[$i].'" selected>'; 948 } else { 949 print '<option value="'.$valors[$i].'">'; 950 } 951 print $valors[$i]; 952 print '</option>'; 953 $i++; 954 } 955 print'</select>'; 956 } 957 } 958 } 959 960 /** 961 * Return a HTML select for thirdparty type 962 * 963 * @param int $selected selected value 964 * @param string $htmlname HTML select name 965 * @param string $htmlidname HTML select id 966 * @param string $typeinput HTML output 967 * @param string $morecss More css 968 * @return string HTML string 969 */ 970 public function selectProspectCustomerType($selected, $htmlname = 'client', $htmlidname = 'customerprospect', $typeinput = 'form', $morecss = '') 971 { 972 973 global $conf, $langs; 974 975 $out = '<select class="flat '.$morecss.'" name="'.$htmlname.'" id="'.$htmlidname.'">'; 976 if ($typeinput == 'form') { 977 if ($selected == '' || $selected == '-1') $out .= '<option value="-1"> </option>'; 978 if (empty($conf->global->SOCIETE_DISABLE_PROSPECTS)) { 979 $out .= '<option value="2"'.($selected == 2 ? ' selected' : '').'>'.$langs->trans('Prospect').'</option>'; 980 } 981 if (empty($conf->global->SOCIETE_DISABLE_PROSPECTS) && empty($conf->global->SOCIETE_DISABLE_CUSTOMERS) && empty($conf->global->SOCIETE_DISABLE_PROSPECTSCUSTOMERS)) { 982 $out .= '<option value="3"'.($selected == 3 ? ' selected' : '').'>'.$langs->trans('ProspectCustomer').'</option>'; 983 } 984 if (empty($conf->global->SOCIETE_DISABLE_CUSTOMERS)) { 985 $out .= '<option value="1"'.($selected == 1 ? ' selected' : '').'>'.$langs->trans('Customer').'</option>'; 986 } 987 $out .= '<option value="0"'.((string) $selected == '0' ? ' selected' : '').'>'.$langs->trans('NorProspectNorCustomer').'</option>'; 988 } elseif ($typeinput == 'list') { 989 $out .= '<option value="-1"'.(($selected == '' || $selected == '-1') ? ' selected' : '').'> </option>'; 990 if (empty($conf->global->SOCIETE_DISABLE_PROSPECTS)) { 991 $out .= '<option value="2,3"'.($selected == '2,3' ? ' selected' : '').'>'.$langs->trans('Prospect').'</option>'; 992 } 993 if (empty($conf->global->SOCIETE_DISABLE_CUSTOMERS)) { 994 $out .= '<option value="1,3"'.($selected == '1,3' ? ' selected' : '').'>'.$langs->trans('Customer').'</option>'; 995 } 996 $out .= '<option value="4"'.($selected == '4' ? ' selected' : '').'>'.$langs->trans('Supplier').'</option>'; 997 $out .= '<option value="0"'.($selected == '0' ? ' selected' : '').'>'.$langs->trans('Other').'</option>'; 998 } elseif ($typeinput == 'admin') { 999 if (empty($conf->global->SOCIETE_DISABLE_PROSPECTS) && empty($conf->global->SOCIETE_DISABLE_CUSTOMERS) && empty($conf->global->SOCIETE_DISABLE_PROSPECTSCUSTOMERS)) { 1000 $out .= '<option value="3"'.($selected == 3 ? ' selected' : '').'>'.$langs->trans('ProspectCustomer').'</option>'; 1001 } 1002 if (empty($conf->global->SOCIETE_DISABLE_CUSTOMERS)) { 1003 $out .= '<option value="1"'.($selected == 1 ? ' selected' : '').'>'.$langs->trans('Customer').'</option>'; 1004 } 1005 } 1006 $out .= '</select>'; 1007 $out .= ajax_combobox($htmlidname); 1008 1009 return $out; 1010 } 1011 1012 /** 1013 * Output html select to select third-party type 1014 * 1015 * @param string $page Page 1016 * @param string $selected Id preselected 1017 * @param string $htmlname Name of HTML select 1018 * @param string $filter optional filters criteras 1019 * @param int $nooutput No print output. Return it only. 1020 * @return void|string 1021 */ 1022 public function formThirdpartyType($page, $selected = '', $htmlname = 'socid', $filter = '', $nooutput = 0) 1023 { 1024 // phpcs:enable 1025 global $conf, $langs; 1026 1027 $out = ''; 1028 if ($htmlname != "none") { 1029 $out .= '<form method="post" action="'.$page.'">'; 1030 $out .= '<input type="hidden" name="action" value="set_thirdpartytype">'; 1031 $out .= '<input type="hidden" name="token" value="'.newToken().'">'; 1032 $sortparam = (empty($conf->global->SOCIETE_SORT_ON_TYPEENT) ? 'ASC' : $conf->global->SOCIETE_SORT_ON_TYPEENT); // NONE means we keep sort of original array, so we sort on position. ASC, means next function will sort on label. 1033 $out .= $this->selectarray($htmlname, $this->typent_array(0, $filter), $selected, 0, 0, 0, '', 0, 0, 0, $sortparam, '', 1); 1034 $out .= '<input type="submit" class="button smallpaddingimp valignmiddle" value="'.$langs->trans("Modify").'">'; 1035 $out .= '</form>'; 1036 } else { 1037 if ($selected) { 1038 $arr = $this->typent_array(0); 1039 $typent = $arr[$selected]; 1040 $out .= $typent; 1041 } else { 1042 $out .= " "; 1043 } 1044 } 1045 1046 if ($nooutput) { 1047 return $out; 1048 } else { 1049 print $out; 1050 } 1051 } 1052} 1053