PageRenderTime 71ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/htdocs/societe/class/societe.class.php

https://bitbucket.org/speedealing/speedealing
PHP | 2158 lines | 1419 code | 266 blank | 473 comment | 327 complexity | 28e57ede808637fdced1fe78d587c9cd MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.1, GPL-3.0, MIT
  1. <?php
  2. /* Copyright (C) 2002-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2004-2010 Laurent Destailleur <eldy@users.sourceforge.net>
  4. * Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
  5. * Copyright (C) 2003 Brian Fraval <brian@fraval.org>
  6. * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
  7. * Copyright (C) 2005-2013 Regis Houssin <regis.houssin@capnetworks.com>
  8. * Copyright (C) 2008 Patrick Raguin <patrick.raguin@auguria.net>
  9. * Copyright (C) 2010-2011 Juanjo Menent <jmenent@2byte.es>
  10. * Copyright (C) 2010-2013 Herve Prot <herve.prot@symeos.com>
  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 <http://www.gnu.org/licenses/>.
  24. */
  25. require_once DOL_DOCUMENT_ROOT . "/core/class/extrafields.class.php";
  26. /**
  27. * Class to manage third parties objects (customers, suppliers, prospects...)
  28. */
  29. class Societe extends nosqlDocument {
  30. public $element = 'societe';
  31. public $table_element = 'societe';
  32. public $fk_element = 'fk_soc';
  33. protected $childtables = array("propal", "commande", "facture", "contrat", "facture_fourn", "commande_fournisseur"); // To test if we can delete object
  34. protected $ismultientitymanaged = 1; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
  35. var $id;
  36. var $name;
  37. var $nom; // TODO obsolete
  38. var $firstname;
  39. var $particulier;
  40. var $civility_id;
  41. var $address;
  42. var $adresse; // TODO obsolete
  43. var $cp; // TODO obsolete
  44. var $zip;
  45. var $ville; // TODO obsolete
  46. var $town;
  47. var $status; // 0=activity ceased, 1= in activity
  48. var $state_id;
  49. var $state_code;
  50. var $state;
  51. var $departement_id; // deprecated
  52. var $departement_code; // deprecated
  53. var $departement; // deprecated
  54. var $pays_id; // deprecated
  55. var $pays_code; // deprecated
  56. var $pays; // deprecated
  57. var $country_id;
  58. var $country_code;
  59. var $country;
  60. var $tel; // deprecated
  61. var $phone;
  62. var $fax;
  63. var $email;
  64. var $url;
  65. //! barcode
  66. var $barcode; // value
  67. var $barcode_type; // id
  68. var $barcode_type_code; // code (loaded by fetch_barcode)
  69. var $barcode_type_label; // label (loaded by fetch_barcode)
  70. var $barcode_type_coder; // coder (loaded by fetch_barcode)
  71. // 4 professional id (usage depend on country)
  72. var $idprof1; // IdProf1 (Ex: Siren in France)
  73. var $idprof2; // IdProf2 (Ex: Siret in France)
  74. var $idprof3; // IdProf3 (Ex: Ape in France)
  75. var $idprof4; // IdProf4 (Ex: RCS in France)
  76. var $prefix_comm;
  77. var $tva_assuj;
  78. var $tva_intra;
  79. // Local taxes
  80. var $localtax1_assuj;
  81. var $localtax2_assuj;
  82. var $capital;
  83. var $typent_id;
  84. var $typent_code;
  85. var $effectif_id;
  86. var $forme_juridique_code;
  87. var $forme_juridique;
  88. var $remise_percent;
  89. var $mode_reglement_id;
  90. var $cond_reglement_id;
  91. var $remise_client; // TODO obsolete
  92. var $mode_reglement; // TODO obsolete
  93. var $cond_reglement; // TODO obsolete
  94. var $client; // 0=no customer, 1=customer, 2=prospect, 3=customer and prospect
  95. var $prospect; // 0=no prospect, 1=prospect
  96. var $fournisseur; // 0=no supplier, 1=supplier
  97. var $code_client;
  98. var $code_fournisseur;
  99. var $code_compta;
  100. var $code_compta_fournisseur;
  101. var $note;
  102. //! code statut prospect
  103. var $stcomm_id;
  104. var $statut_commercial;
  105. var $price_level;
  106. var $datec;
  107. var $date_update;
  108. var $commercial_id; // Id of sales representative to link (used for thirdparty creation). Not filled by a fetch, because we can have several sales representatives.
  109. var $default_lang;
  110. var $ref_int;
  111. var $import_key;
  112. var $logo;
  113. /**
  114. * Constructor
  115. *
  116. * @param DoliDB $db Database handler
  117. */
  118. public function __construct($db = null) {
  119. parent::__construct($db);
  120. $this->fk_extrafields = new ExtraFields($db);
  121. $this->fk_extrafields->fetch(get_class($this));
  122. $this->commercial_id = new stdClass();
  123. return 1;
  124. }
  125. /**
  126. * Create third party in database
  127. *
  128. * @param User $user Object of user that ask creation
  129. * @return int >= 0 if OK, < 0 if KO
  130. */
  131. function create($user = '') {
  132. global $langs, $conf, $user;
  133. $error = 0;
  134. $this->name = trim($this->name);
  135. $this->name = ucwords($this->name);
  136. if (empty($this->client))
  137. $this->client = 0;
  138. if (empty($this->fournisseur))
  139. $this->fournisseur = 0;
  140. $this->import_key = trim($this->import_key);
  141. // Check parameters
  142. if (!empty($conf->global->SOCIETE_MAIL_REQUIRED) && !isValidEMail($this->email)) {
  143. $langs->load("errors");
  144. $this->error = $langs->trans("ErrorBadEMail", $this->email);
  145. return -1;
  146. }
  147. $now = dol_now();
  148. $this->datec = $now;
  149. // For automatic creation during create action (not used by Dolibarr GUI, can be used by scripts)
  150. if ($this->code_client == -1)
  151. $this->get_codeclient($this->prefix_comm, 0);
  152. if ($this->code_fournisseur == -1)
  153. $this->get_codefournisseur($this->prefix_comm, 1);
  154. // Check more parameters
  155. // If error, this->errors[] is filled
  156. $result = $this->verify();
  157. $staticuser = new User($db);
  158. if ($result >= 0) {
  159. // Ajout du commercial affecte
  160. if ($this->commercial_id->id != '' && $this->commercial_id->id != "-1") {
  161. $this->commercial_id->id = trim($this->commercial_id->id);
  162. $staticuser->load($this->commercial_id->id);
  163. $this->commercial_id->name = $staticuser->name;
  164. }
  165. // si un commercial cree un client il lui est affecte automatiquement
  166. else {
  167. $this->commercial_id->id = $user->id;
  168. $this->commercial_id->name = $user->name;
  169. }
  170. $ret = $this->update('', $user, 0, 1, 1, 'add'); // Record
  171. // si le fournisseur est classe on l'ajoute
  172. $this->AddFournisseurInCategory($this->fournisseur_categorie);
  173. if ($ret >= 0) {
  174. // Appel des triggers
  175. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  176. $interface = new Interfaces($this->db);
  177. $result = $interface->run_triggers('COMPANY_CREATE', $this, $user, $langs, $conf);
  178. if ($result < 0) {
  179. $error++;
  180. $this->errors = $interface->errors;
  181. }
  182. // Fin appel triggers
  183. return $this->id;
  184. } else {
  185. return -3;
  186. }
  187. } else {
  188. return -3;
  189. }
  190. }
  191. /**
  192. * Check properties of third party are ok (like name, third party codes, ...)
  193. *
  194. * @return int 0 if OK, <0 if KO
  195. */
  196. function verify() {
  197. $this->errors = array();
  198. $result = 0;
  199. $this->name = trim($this->name);
  200. if (empty($this->name)) {
  201. $this->errors[] = 'ErrorBadThirdPartyName';
  202. $result = -2;
  203. }
  204. if ($this->codeclient_modifiable()) {
  205. // On ne verifie le code client que si la societe est un client / prospect et que le code est modifiable
  206. // Si il n'est pas modifiable il n'est pas mis a jour lors de l'update
  207. $rescode = $this->check_codeclient();
  208. if ($rescode <> 0) {
  209. if ($rescode == -1) {
  210. $this->errors[] = 'ErrorBadCustomerCodeSyntax';
  211. }
  212. if ($rescode == -2) {
  213. $this->errors[] = 'ErrorCustomerCodeRequired';
  214. }
  215. if ($rescode == -3) {
  216. $this->errors[] = 'ErrorCustomerCodeAlreadyUsed';
  217. }
  218. if ($rescode == -4) {
  219. $this->errors[] = 'ErrorPrefixRequired';
  220. }
  221. $result = -3;
  222. }
  223. }
  224. /* Verify code_client must be unique */
  225. if (!empty($this->code_client)) {
  226. $rescode = $this->getView("code_client", array("key" => $this->code_client));
  227. if (count($rescode->rows) && $rescode->rows[0]->id != $this->id) {
  228. $this->errors[] = 'ErrorCustomerCodeAlreadyUsed';
  229. $result = -3;
  230. }
  231. }
  232. if (!empty($this->fournisseur) && $this->codefournisseur_modifiable()) {
  233. // On ne verifie le code fournisseur que si la societe est un fournisseur et que le code est modifiable
  234. // Si il n'est pas modifiable il n'est pas mis a jour lors de l'update
  235. $rescode = $this->check_codefournisseur();
  236. if ($rescode <> 0) {
  237. if ($rescode == -1) {
  238. $this->errors[] = 'ErrorBadSupplierCodeSyntax';
  239. }
  240. if ($rescode == -2) {
  241. $this->errors[] = 'ErrorSupplierCodeRequired';
  242. }
  243. if ($rescode == -3) {
  244. $this->errors[] = 'ErrorSupplierCodeAlreadyUsed';
  245. }
  246. if ($rescode == -5) {
  247. $this->errors[] = 'ErrorprefixRequired';
  248. }
  249. $result = -3;
  250. }
  251. }
  252. return $result;
  253. }
  254. /**
  255. * Update GPS coordonnate
  256. *
  257. */
  258. function updateGPS() {
  259. global $conf;
  260. // Calcul des coordonnées GPS
  261. if ($conf->map->enabled) {
  262. //Retire le CEDEX de la ville :
  263. $town = strtolower($this->town);
  264. $find = "cedex";
  265. $pos = strpos($town, $find);
  266. if ($pos != false) {
  267. $town = substr($town, 0, $pos);
  268. //print $town;exit;
  269. }
  270. $apiUrl = "http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=" . urlencode($this->address . "," . $this->zip . "," . $town);
  271. $c = curl_init();
  272. curl_setopt($c, CURLOPT_URL, $apiUrl);
  273. curl_setopt($c, CURLOPT_HEADER, false);
  274. curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
  275. // make the call
  276. $json = curl_exec($c);
  277. $response = json_decode($json);
  278. curl_close($c);
  279. if ($response->status == "OK") {
  280. $this->gps = array($response->results[0]->geometry->location->lat,
  281. $response->results[0]->geometry->location->lng);
  282. } else {
  283. unset($this->gps);
  284. }
  285. }
  286. return $this->gps;
  287. }
  288. /**
  289. * Update parameters of third party
  290. *
  291. * @param string $id id societe
  292. * @param User $user Utilisateur qui demande la mise a jour
  293. * @param int $call_trigger 0=non, 1=oui
  294. * @param int $allowmodcodeclient Inclut modif code client et code compta
  295. * @param int $allowmodcodefournisseur Inclut modif code fournisseur et code compta fournisseur
  296. * @param string $action 'create' or 'update'
  297. * @return int <0 if KO, >=0 if OK
  298. */
  299. function update($id, $user = '', $call_trigger = 1, $allowmodcodeclient = 0, $allowmodcodefournisseur = 0, $action = 'update') {
  300. global $langs, $conf, $hookmanager;
  301. require_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php';
  302. $error = 0;
  303. $now = dol_now();
  304. // Clean parameters
  305. $this->id = $id;
  306. $this->name = trim($this->name);
  307. $this->ref_ext = trim($this->ref_ext);
  308. $this->address = trim($this->address);
  309. $this->zip = trim($this->zip);
  310. $this->town = trim($this->town);
  311. $this->state = trim($this->state_id);
  312. $this->country = $this->country_id;
  313. $this->phone = trim($this->phone);
  314. $this->phone = preg_replace("/\s/", "", $this->phone);
  315. $this->phone = preg_replace("/\./", "", $this->phone);
  316. $this->fax = trim($this->fax);
  317. $this->fax = preg_replace("/\s/", "", $this->fax);
  318. $this->fax = preg_replace("/\./", "", $this->fax);
  319. $this->email = trim($this->email);
  320. $this->url = $this->url ? clean_url($this->url, 0) : '';
  321. $this->idprof1 = trim($this->idprof1);
  322. $this->idprof2 = trim($this->idprof2);
  323. $this->idprof3 = trim($this->idprof3);
  324. $this->idprof4 = trim($this->idprof4);
  325. $this->idprof5 = (!empty($this->idprof5) ? trim($this->idprof5) : '');
  326. $this->idprof6 = (!empty($this->idprof6) ? trim($this->idprof6) : '');
  327. $this->prefix_comm = trim($this->prefix_comm);
  328. $this->tva_assuj = trim($this->tva_assuj);
  329. $this->tva_intra = dol_sanitizeFileName($this->tva_intra, '');
  330. $this->tms = $now;
  331. if (empty($this->Status))
  332. $this->Status = $this->fk_extrafields->fields->Status->default;
  333. // Local taxes
  334. $this->localtax1_assuj = trim($this->localtax1_assuj);
  335. $this->localtax2_assuj = trim($this->localtax2_assuj);
  336. $this->capital = price2num(trim($this->capital), 'MT');
  337. if (empty($this->capital))
  338. $this->capital = 0;
  339. $this->effectif_id = trim($this->effectif_id);
  340. $this->forme_juridique_code = trim($this->forme_juridique_code);
  341. //Gencod
  342. $this->barcode = trim($this->barcode);
  343. // For automatic creation
  344. if ($this->code_client == -1)
  345. $this->get_codeclient($this->prefix_comm, 0);
  346. if ($this->code_fournisseur == -1)
  347. $this->get_codefournisseur($this->prefix_comm, 1);
  348. $this->code_compta = trim($this->code_compta);
  349. $this->code_compta_fournisseur = trim($this->code_compta_fournisseur);
  350. // Check parameters
  351. if (!empty($conf->global->SOCIETE_MAIL_REQUIRED) && !isValidEMail($this->email)) {
  352. $langs->load("errors");
  353. $this->error = $langs->trans("ErrorBadEMail", $this->email);
  354. return -1;
  355. }
  356. if (!is_numeric($this->client) && !is_numeric($this->fournisseur)) {
  357. $langs->load("errors");
  358. $this->error = $langs->trans("BadValueForParameterClientOrSupplier");
  359. return -1;
  360. }
  361. $customer = false;
  362. if (!empty($allowmodcodeclient) && !empty($this->client)) {
  363. // Attention get_codecompta peut modifier le code suivant le module utilise
  364. if (empty($this->code_compta)) {
  365. $ret = $this->get_codecompta('customer');
  366. if ($ret < 0)
  367. return -1;
  368. }
  369. $customer = true;
  370. }
  371. $supplier = false;
  372. if (!empty($allowmodcodefournisseur) && !empty($this->fournisseur)) {
  373. // Attention get_codecompta peut modifier le code suivant le module utilise
  374. if (empty($this->code_compta_fournisseur)) {
  375. $ret = $this->get_codecompta('supplier');
  376. if ($ret < 0)
  377. return -1;
  378. }
  379. $supplier = true;
  380. }
  381. // Calcul des coordonnées GPS
  382. $this->updateGPS();
  383. // Check name is required and codes are ok or unique.
  384. // If error, this->errors[] is filled
  385. $result = $this->verify();
  386. if ($result >= 0) {
  387. $resql = $this->record();
  388. if ($resql) {
  389. unset($this->country_code);
  390. unset($this->country);
  391. unset($this->state_code);
  392. unset($this->state);
  393. // Si le fournisseur est classe on l'ajoute
  394. $this->AddFournisseurInCategory($this->fournisseur_categorie);
  395. // Actions on extra fields (by external module or standard code)
  396. $hookmanager->initHooks(array('thirdpartydao'));
  397. $parameters = array('socid' => $this->id);
  398. $reshook = $hookmanager->executeHooks('insertExtraFields', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
  399. if (empty($reshook)) {
  400. $result = $this->insertExtraFields();
  401. if ($result < 0) {
  402. $error++;
  403. }
  404. } else if ($reshook < 0)
  405. $error++;
  406. if (!$error && $call_trigger) {
  407. // Appel des triggers
  408. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  409. $interface = new Interfaces($this->db);
  410. $result = $interface->run_triggers('COMPANY_MODIFY', $this, $user, $langs, $conf);
  411. if ($result < 0) {
  412. $error++;
  413. $this->errors = $interface->errors;
  414. }
  415. // Fin appel triggers
  416. }
  417. if (!$error) {
  418. return 1;
  419. } else {
  420. return -1;
  421. }
  422. } else {
  423. if ($this->db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
  424. // Doublon
  425. $this->error = $langs->trans("ErrorDuplicateField");
  426. $result = -1;
  427. } else {
  428. $this->error = $langs->trans("Error sql=" . $sql);
  429. $result = -2;
  430. }
  431. return $result;
  432. }
  433. } else {
  434. return -3;
  435. }
  436. }
  437. /**
  438. * Delete a third party from database and all its dependencies (contacts, rib...)
  439. *
  440. * @param int $id Id of third party to delete
  441. * @return int <0 if KO, 0 if nothing done, >0 if OK
  442. */
  443. function delete($id) {
  444. global $user, $langs, $conf, $hookmanager;
  445. require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
  446. $error = 0;
  447. // Test if child exists
  448. $objectisused = $this->isObjectUsed($id);
  449. if (empty($objectisused)) {
  450. require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
  451. $static_cat = new Categorie($this->db);
  452. $toute_categs = array();
  453. // Fill $toute_categs array with an array of (type => array of ("Categorie" instance))
  454. if ($this->client || $this->prospect) {
  455. $toute_categs ['societe'] = $static_cat->containing($this->id, 2);
  456. }
  457. if ($this->fournisseur) {
  458. $toute_categs ['fournisseur'] = $static_cat->containing($this->id, 1);
  459. }
  460. // Remove each "Categorie"
  461. foreach ($toute_categs as $type => $categs_type) {
  462. foreach ($categs_type as $cat) {
  463. $cat->del_type($this, $type);
  464. }
  465. }
  466. return parent::delete();
  467. /*
  468. // TODO Supprimer les contacts
  469. // Remove contacts
  470. if (!$error) {
  471. $sql = "DELETE FROM " . MAIN_DB_PREFIX . "socpeople";
  472. $sql.= " WHERE fk_soc = " . $id;
  473. if (!$this->db->query($sql)) {
  474. $error++;
  475. $this->error .= $this->db->lasterror();
  476. }
  477. }
  478. // Update link in member table
  479. if (!$error) {
  480. $sql = "UPDATE " . MAIN_DB_PREFIX . "adherent";
  481. $sql.= " SET fk_soc = NULL WHERE fk_soc = " . $id;
  482. if (!$this->db->query($sql)) {
  483. $error++;
  484. $this->error .= $this->db->lasterror();
  485. }
  486. }
  487. // Remove ban
  488. if (!$error) {
  489. $sql = "DELETE FROM " . MAIN_DB_PREFIX . "societe_rib";
  490. $sql.= " WHERE fk_soc = " . $id;
  491. if (!$this->db->query($sql)) {
  492. $error++;
  493. $this->error = $this->db->lasterror();
  494. }
  495. }
  496. */
  497. // Removed extrafields
  498. //$result=$this->deleteExtraFields($this);
  499. //if ($result < 0) $error++;
  500. if (!$error) {
  501. // Additionnal action by hooks
  502. $hookmanager->initHooks(array('thirdpartydao'));
  503. $parameters = array();
  504. $action = 'delete';
  505. $reshook = $hookmanager->executeHooks('deleteThirdparty', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
  506. if (!empty($hookmanager->error)) {
  507. $error++;
  508. $this->error = $hookmanager->error;
  509. }
  510. }
  511. /*
  512. // Remove third party
  513. if (!$error) {
  514. $sql = "DELETE FROM " . MAIN_DB_PREFIX . "societe";
  515. $sql.= " WHERE rowid = " . $id;
  516. if (!$this->db->query($sql)) {
  517. $error++;
  518. $this->error = $this->db->lasterror();
  519. }
  520. }
  521. */
  522. if (!$error) {
  523. // Appel des triggers
  524. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  525. $interface = new Interfaces($this->db);
  526. $result = $interface->run_triggers('COMPANY_DELETE', $this, $user, $langs, $conf);
  527. if ($result < 0) {
  528. $error++;
  529. $this->errors = $interface->errors;
  530. }
  531. // Fin appel triggers
  532. }
  533. if (!$error) {
  534. $this->db->commit();
  535. // Delete directory
  536. $docdir = $conf->societe->multidir_output[$this->entity] . "/" . $id;
  537. if (file_exists($docdir)) {
  538. dol_delete_dir_recursive($docdir);
  539. }
  540. return 1;
  541. } else {
  542. $this->db->rollback();
  543. return -1;
  544. }
  545. }
  546. }
  547. /**
  548. * Define third party as a customer
  549. *
  550. * @return int <0 if KO, >0 if OK
  551. * @deprecated
  552. */
  553. function set_as_client() {
  554. /*
  555. if ($this->id) {
  556. $newclient = 1;
  557. if ($this->client == 2 || $this->client == 3)
  558. $newclient = 3; //If prospect, we keep prospect tag
  559. $sql = "UPDATE " . MAIN_DB_PREFIX . "societe";
  560. $sql.= " SET client = " . $newclient;
  561. $sql.= " WHERE rowid = " . $this->id;
  562. $resql = $this->db->query($sql);
  563. if ($resql) {
  564. $this->client = $newclient;
  565. return 1;
  566. }
  567. else
  568. return -1;
  569. } */
  570. return 0;
  571. }
  572. /**
  573. * Definit la societe comme un client
  574. *
  575. * @param float $remise Valeur en % de la remise
  576. * @param string $note Note/Motif de modification de la remise
  577. * @param User $user Utilisateur qui definie la remise
  578. * @return int <0 if KO, >0 if OK
  579. */
  580. function set_remise_client($remise, $note, $user) {
  581. global $langs;
  582. // Nettoyage parametres
  583. $note = trim($note);
  584. if (!$note) {
  585. $this->error = $langs->trans("ErrorFieldRequired", $langs->trans("Note"));
  586. return -2;
  587. }
  588. if ($this->id) {
  589. $this->db->begin();
  590. $now = dol_now();
  591. // Positionne remise courante
  592. $sql = "UPDATE " . MAIN_DB_PREFIX . "societe ";
  593. $sql.= " SET remise_client = '" . $remise . "'";
  594. $sql.= " WHERE rowid = " . $this->id . ";";
  595. $resql = $this->db->query($sql);
  596. if (!$resql) {
  597. $this->db->rollback();
  598. $this->error = $this->db->error();
  599. return -1;
  600. }
  601. // Ecrit trace dans historique des remises
  602. $sql = "INSERT INTO " . MAIN_DB_PREFIX . "societe_remise ";
  603. $sql.= " (datec, fk_soc, remise_client, note, fk_user_author)";
  604. $sql.= " VALUES (" . $this->db->idate($now) . ", " . $this->id . ", '" . $remise . "',";
  605. $sql.= " '" . $this->db->escape($note) . "',";
  606. $sql.= " " . $user->id;
  607. $sql.= ")";
  608. $resql = $this->db->query($sql);
  609. if (!$resql) {
  610. $this->db->rollback();
  611. $this->error = $this->db->error();
  612. return -1;
  613. }
  614. $this->db->commit();
  615. return 1;
  616. }
  617. }
  618. /**
  619. * Add a discount for third party
  620. *
  621. * @param float $remise Amount of discount
  622. * @param User $user User adding discount
  623. * @param string $desc Reason of discount
  624. * @param float $tva_tx VAT rate
  625. * @return int <0 if KO, id of discount record if OK
  626. */
  627. function set_remise_except($remise, $user, $desc, $tva_tx = 0) {
  628. global $langs;
  629. // Clean parameters
  630. $remise = price2num($remise);
  631. $desc = trim($desc);
  632. // Check parameters
  633. if (!$remise > 0) {
  634. $this->error = $langs->trans("ErrorWrongValueForParameter", "1");
  635. return -1;
  636. }
  637. if (!$desc) {
  638. $this->error = $langs->trans("ErrorWrongValueForParameter", "3");
  639. return -2;
  640. }
  641. if ($this->id) {
  642. require_once DOL_DOCUMENT_ROOT . '/core/class/discount.class.php';
  643. $discount = new DiscountAbsolute($this->db);
  644. $discount->fk_soc = $this->id;
  645. $discount->amount_ht = price2num($remise, 'MT');
  646. $discount->amount_tva = price2num($remise * $tva_tx / 100, 'MT');
  647. $discount->amount_ttc = price2num($discount->amount_ht + $discount->amount_tva, 'MT');
  648. $discount->tva_tx = price2num($tva_tx, 'MT');
  649. $discount->description = $desc;
  650. $result = $discount->create($user);
  651. if ($result > 0) {
  652. return $result;
  653. } else {
  654. $this->error = $discount->error;
  655. return -3;
  656. }
  657. }
  658. else
  659. return 0;
  660. }
  661. /**
  662. * Renvoie montant TTC des reductions/avoirs en cours disponibles de la societe
  663. *
  664. * @param User $user Filtre sur un user auteur des remises
  665. * @param string $filter Filtre autre
  666. * @param string $maxvalue Filter on max value for discount
  667. * @return int <0 if KO, Credit note amount otherwise
  668. */
  669. function getAvailableDiscounts($user = '', $filter = '', $maxvalue = 0) {
  670. require_once DOL_DOCUMENT_ROOT . '/core/class/discount.class.php';
  671. $discountstatic = new DiscountAbsolute($this->db);
  672. $result = $discountstatic->getAvailableDiscounts($this, $user, $filter, $maxvalue);
  673. if ($result >= 0) {
  674. return $result;
  675. } else {
  676. $this->error = $discountstatic->error;
  677. return -1;
  678. }
  679. }
  680. /**
  681. * Return array of sales representatives
  682. *
  683. * @param User $user Object user
  684. * @return array Array of sales representatives of third party
  685. */
  686. function getSalesRepresentatives($user = '') {
  687. global $conf;
  688. $reparray = array();
  689. $num = count($this->commerciaux);
  690. $i = 0;
  691. if ($num > 0)
  692. foreach ($this->commerciaux as $aRow) {
  693. $reparray[$i]['id'] = $aRow;
  694. $i++;
  695. }
  696. return $reparray;
  697. }
  698. /**
  699. * Set the price level
  700. *
  701. * @param int $price_level Level of price
  702. * @param User $user Use making change
  703. * @return int <0 if KO, >0 if OK
  704. */
  705. function set_price_level($price_level, $user) {
  706. if ($this->id) {
  707. $now = dol_now();
  708. $sql = "UPDATE " . MAIN_DB_PREFIX . "societe ";
  709. $sql .= " SET price_level = '" . $price_level . "'";
  710. $sql .= " WHERE rowid = " . $this->id;
  711. $this->db->query($sql);
  712. $sql = "INSERT INTO " . MAIN_DB_PREFIX . "societe_prices ";
  713. $sql .= " ( datec, fk_soc, price_level, fk_user_author )";
  714. $sql .= " VALUES ('" . $this->db->idate($now) . "'," . $this->id . ",'" . $price_level . "'," . $user->id . ")";
  715. if (!$this->db->query($sql)) {
  716. dol_print_error($this->db);
  717. return -1;
  718. }
  719. return 1;
  720. }
  721. return -1;
  722. }
  723. /**
  724. * Return a link on thirdparty (with picto)
  725. *
  726. * @param int $withpicto Add picto into link (0=No picto, 1=Include picto with link, 2=Picto only)
  727. * @param string $picto Picto name
  728. * @return string String with URL
  729. */
  730. function getNomUrl($withpicto = 0, $picto = null) {
  731. global $conf, $langs;
  732. $result = '';
  733. $name = $this->name;
  734. $slink = '<a href="societe/fiche.php?id=' . $this->id() . '">';
  735. $elink = '</a>';
  736. if ($withpicto)
  737. $result.= ($slink . img_object($langs->trans("ShowCompany") . ': ' . $name, 'company') . $elink);
  738. if ($withpicto && $withpicto != 2)
  739. $result.=' ';
  740. $result.=$slink . $name . $elink;
  741. return $result;
  742. }
  743. /**
  744. * Return full address of third party
  745. *
  746. * @param int $withcountry 1=Add country into address string
  747. * @param string $sep Separator to use to build string
  748. * @return string Full address string
  749. */
  750. function getFullAddress($withcountry = 0, $sep = "\n") {
  751. $ret = '';
  752. if ($withcountry && $this->country_id && (empty($this->country_code) || empty($this->country))) {
  753. require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
  754. $tmparray = getCountry($this->country_id, 'all');
  755. $this->country_code = $tmparray['code'];
  756. $this->country = $tmparray['label'];
  757. }
  758. if (in_array($this->country_code, array('US'))) {
  759. $ret.=($this->address ? $this->address . $sep : '');
  760. $ret.=trim($this->zip . ' ' . $this->town);
  761. if ($withcountry)
  762. $ret.=($this->country ? $sep . $this->country : '');
  763. }
  764. else {
  765. $ret.=($this->address ? $this->address . $sep : '');
  766. $ret.=trim($this->zip . ' ' . $this->town);
  767. if ($withcountry)
  768. $ret.=($this->country ? $sep . $this->country : '');
  769. }
  770. return trim($ret);
  771. }
  772. /**
  773. * Return list of contacts emails existing for third party
  774. *
  775. * @param int $addthirdparty 1=Add also a record for thirdparty email
  776. * @return array Array of contacts emails
  777. */
  778. function thirdparty_and_contact_email_array($addthirdparty = 0) {
  779. global $langs;
  780. $contact_emails = $this->contact_property_array('email');
  781. if ($this->email && $addthirdparty) {
  782. if (empty($this->name))
  783. $this->name = $this->nom;
  784. // TODO: Tester si email non deja present dans tableau contact
  785. $contact_emails['thirdparty'] = $langs->trans("ThirdParty") . ': ' . dol_trunc($this->name, 16) . " &lt;" . $this->email . "&gt;";
  786. }
  787. return $contact_emails;
  788. }
  789. /**
  790. * Return list of contacts mobile phone existing for third party
  791. *
  792. * @return array Array of contacts emails
  793. */
  794. function thirdparty_and_contact_phone_array() {
  795. global $langs;
  796. if (empty($this->phone) && !empty($this->tel))
  797. $this->phone = $this->tel;
  798. $contact_phone = $this->contact_property_array('mobile');
  799. if ($this->phone) {
  800. if (empty($this->name))
  801. $this->name = $this->nom;
  802. // TODO: Tester si tel non deja present dans tableau contact
  803. $contact_phone['thirdparty'] = $langs->trans("ThirdParty") . ': ' . dol_trunc($this->name, 16) . " &lt;" . $this->phone . "&gt;";
  804. }
  805. return $contact_phone;
  806. }
  807. /**
  808. * Return list of contacts emails or mobile existing for third party
  809. *
  810. * @param string $mode 'email' or 'mobile'
  811. * @return array Array of contacts emails or mobile
  812. */
  813. function contact_property_array($mode = 'email') {
  814. $contact_property = array();
  815. $sql = "SELECT rowid, email, phone_mobile, name, firstname";
  816. $sql.= " FROM " . MAIN_DB_PREFIX . "socpeople";
  817. $sql.= " WHERE fk_soc = '" . $this->id . "'";
  818. $resql = $this->db->query($sql);
  819. if ($resql) {
  820. $nump = $this->db->num_rows($resql);
  821. if ($nump) {
  822. $i = 0;
  823. while ($i < $nump) {
  824. $obj = $this->db->fetch_object($resql);
  825. if ($mode == 'email')
  826. $property = $obj->email;
  827. else if ($mode == 'mobile')
  828. $property = $obj->phone_mobile;
  829. $contact_property[$obj->rowid] = trim($obj->firstname . " " . $obj->name) . " &lt;" . $property . "&gt;";
  830. $i++;
  831. }
  832. }
  833. }
  834. else {
  835. dol_print_error($this->db);
  836. }
  837. return $contact_property;
  838. }
  839. /**
  840. * Renvoie la liste des contacts de cette societe
  841. *
  842. * @return array tableau des contacts
  843. */
  844. function contact_array() {
  845. $contacts = array();
  846. $sql = "SELECT rowid, name, firstname FROM " . MAIN_DB_PREFIX . "socpeople WHERE fk_soc = '" . $this->id . "'";
  847. $resql = $this->db->query($sql);
  848. if ($resql) {
  849. $nump = $this->db->num_rows($resql);
  850. if ($nump) {
  851. $i = 0;
  852. while ($i < $nump) {
  853. $obj = $this->db->fetch_object($resql);
  854. $contacts[$obj->rowid] = $obj->firstname . " " . $obj->name;
  855. $i++;
  856. }
  857. }
  858. } else {
  859. dol_print_error($this->db);
  860. }
  861. return $contacts;
  862. }
  863. /**
  864. * Return property of contact from its id
  865. *
  866. * @param int $rowid id of contact
  867. * @param string $mode 'email' or 'mobile'
  868. * @return string email of contact
  869. */
  870. function contact_get_property($rowid, $mode) {
  871. $contact_property = '';
  872. $sql = "SELECT rowid, email, phone_mobile, name, firstname";
  873. $sql.= " FROM " . MAIN_DB_PREFIX . "socpeople";
  874. $sql.= " WHERE rowid = '" . $rowid . "'";
  875. $resql = $this->db->query($sql);
  876. if ($resql) {
  877. $nump = $this->db->num_rows($resql);
  878. if ($nump) {
  879. $obj = $this->db->fetch_object($resql);
  880. if ($mode == 'email')
  881. $contact_property = "$obj->firstname $obj->name <$obj->email>";
  882. else if ($mode == 'mobile')
  883. $contact_property = $obj->phone_mobile;
  884. }
  885. return $contact_property;
  886. }
  887. else {
  888. dol_print_error($this->db);
  889. }
  890. }
  891. /**
  892. * Return bank number property of thirdparty
  893. *
  894. * @return string Bank number
  895. */
  896. function display_rib() {
  897. global $langs;
  898. if ($this->bac->code_banque || $this->bac->code_guichet || $this->bac->number || $this->bac->cle_rib) {
  899. $rib = $this->bac->code_banque . " " . $this->bac->code_guichet . " " . $this->bac->number;
  900. $rib.=($this->bac->cle_rib ? " (" . $this->bac->cle_rib . ")" : "");
  901. } else {
  902. $rib = $langs->trans("NoRIB");
  903. }
  904. return $rib;
  905. }
  906. /**
  907. * Load this->bank_account attribut
  908. *
  909. * @return int 1
  910. */
  911. function load_ban() {
  912. require_once DOL_DOCUMENT_ROOT . '/societe/class/companybankaccount.class.php';
  913. $bac = new CompanyBankAccount($this->db);
  914. $bac->fetch(0, $this->id);
  915. $this->bank_account = $bac;
  916. return 1;
  917. }
  918. /**
  919. * Check bank numbers
  920. *
  921. * @return int <0 if KO, >0 if OK
  922. */
  923. function verif_rib() {
  924. $this->load_ban();
  925. return $this->bank_account->verif();
  926. }
  927. /**
  928. * Attribut un code client a partir du module de controle des codes.
  929. * Return value is stored into this->code_client
  930. *
  931. * @param Societe $objsoc Object thirdparty
  932. * @param int $type Should be 0 to say customer
  933. * @return void
  934. */
  935. function get_codeclient($objsoc = 0, $type = 0) {
  936. global $conf;
  937. if (!empty($conf->global->SOCIETE_CODECLIENT_ADDON)) {
  938. $dirsociete = array_merge(array('/societe/core/models/'), $conf->societe_modules);
  939. foreach ($dirsociete as $dirroot) {
  940. $res = dol_include_once($dirroot . $conf->global->SOCIETE_CODECLIENT_ADDON . '.php');
  941. if ($res)
  942. break;
  943. }
  944. $var = $conf->global->SOCIETE_CODECLIENT_ADDON;
  945. $mod = new $var;
  946. $this->code_client = $mod->getNextValue($objsoc, $type);
  947. $this->prefixCustomerIsRequired = $mod->prefixIsRequired;
  948. }
  949. }
  950. /**
  951. * Attribut un code fournisseur a partir du module de controle des codes.
  952. * Return value is stored into this->code_fournisseur
  953. *
  954. * @param Societe $objsoc Object thirdparty
  955. * @param int $type Should be 1 to say supplier
  956. * @return void
  957. */
  958. function get_codefournisseur($objsoc = 0, $type = 1) {
  959. global $conf;
  960. if (!empty($conf->global->SOCIETE_CODEFOURNISSEUR_ADDON)) {
  961. $dirsociete = array_merge(array('/societe/core/models/'), $conf->societe_modules);
  962. foreach ($dirsociete as $dirroot) {
  963. $res = dol_include_once($dirroot . $conf->global->SOCIETE_FOURNISSEUR_ADDON . '.php');
  964. if ($res)
  965. break;
  966. }
  967. $var = $conf->global->SOCIETE_CODEFOURNISSEUR_ADDON;
  968. $mod = new $var;
  969. $this->code_fournisseur = $mod->getNextValue($objsoc, $type);
  970. }
  971. }
  972. /**
  973. * Verifie si un code client est modifiable en fonction des parametres
  974. * du module de controle des codes.
  975. *
  976. * @return int 0=Non, 1=Oui
  977. */
  978. function codeclient_modifiable() {
  979. global $conf;
  980. if (!empty($conf->global->SOCIETE_CODECLIENT_ADDON)) {
  981. $dirsociete = array_merge(array('/societe/core/models/'), $conf->societe_modules);
  982. foreach ($dirsociete as $dirroot) {
  983. $res = dol_include_once($dirroot . $conf->global->SOCIETE_CODECLIENT_ADDON . '.php');
  984. if ($res)
  985. break;
  986. }
  987. $var = $conf->global->SOCIETE_CODECLIENT_ADDON;
  988. $mod = new $var;
  989. if ($mod->code_modifiable_null && !$this->code_client)
  990. return 1;
  991. if ($mod->code_modifiable_invalide && $this->check_codeclient() < 0)
  992. return 1;
  993. if ($mod->code_modifiable)
  994. return 1; // A mettre en dernier
  995. return 0;
  996. }
  997. else {
  998. return 0;
  999. }
  1000. }
  1001. /**
  1002. * Verifie si un code fournisseur est modifiable dans configuration du module de controle des codes
  1003. *
  1004. * @return int 0=Non, 1=Oui
  1005. */
  1006. function codefournisseur_modifiable() {
  1007. global $conf;
  1008. if (!empty($conf->global->SOCIETE_CODEFOURNISSEUR_ADDON)) {
  1009. $dirsociete = array_merge(array('/societe/core/models/'), $conf->societe_modules);
  1010. foreach ($dirsociete as $dirroot) {
  1011. $res = dol_include_once($dirroot . $conf->global->SOCIETE_CODEFOURNISSEUR_ADDON . '.php');
  1012. if ($res)
  1013. break;
  1014. }
  1015. $var = $conf->global->SOCIETE_CODEFOURNISSEUR_ADDON;
  1016. $mod = new $var;
  1017. if ($mod->code_modifiable_null && !$this->code_fournisseur)
  1018. return 1;
  1019. if ($mod->code_modifiable_invalide && $this->check_codefournisseur() < 0)
  1020. return 1;
  1021. if ($mod->code_modifiable)
  1022. return 1; // A mettre en dernier
  1023. return 0;
  1024. }
  1025. else {
  1026. return 0;
  1027. }
  1028. }
  1029. /**
  1030. * Check customer code
  1031. *
  1032. * @return int 0 if OK
  1033. * -1 ErrorBadCustomerCodeSyntax
  1034. * -2 ErrorCustomerCodeRequired
  1035. * -3 ErrorCustomerCodeAlreadyUsed
  1036. * -4 ErrorPrefixRequired
  1037. */
  1038. function check_codeclient() {
  1039. global $conf;
  1040. if (!empty($conf->global->SOCIETE_CODECLIENT_ADDON)) {
  1041. $dirsociete = array_merge(array('/societe/core/models/'), $conf->societe_modules);
  1042. foreach ($dirsociete as $dirroot) {
  1043. $res = dol_include_once($dirroot . $conf->global->SOCIETE_CODECLIENT_ADDON . '.php');
  1044. if ($res)
  1045. break;
  1046. }
  1047. $var = $conf->global->SOCIETE_CODECLIENT_ADDON;
  1048. $mod = new $var;
  1049. $result = $mod->verif($this->db, $this->code_client, $this, 0);
  1050. return $result;
  1051. }
  1052. else {
  1053. return 0;
  1054. }
  1055. }
  1056. /**
  1057. * Check supplier code
  1058. *
  1059. * @return int 0 if OK
  1060. * -1 ErrorBadCustomerCodeSyntax
  1061. * -2 ErrorCustomerCodeRequired
  1062. * -3 ErrorCustomerCodeAlreadyUsed
  1063. * -4 ErrorPrefixRequired
  1064. */
  1065. function check_codefournisseur() {
  1066. global $conf;
  1067. if (!empty($conf->global->SOCIETE_CODEFOURNISSEUR_ADDON)) {
  1068. $dirsociete = array_merge(array('/societe/core/models/'), $conf->societe_modules);
  1069. foreach ($dirsociete as $dirroot) {
  1070. $res = dol_include_once($dirroot . $conf->global->SOCIETE_CODEFOURNISSEUR_ADDON . '.php');
  1071. if ($res)
  1072. break;
  1073. }
  1074. $var = $conf->global->SOCIETE_CODEFOURNISSEUR_ADDON;
  1075. $mod = new $var;
  1076. $result = $mod->verif($this->db, $this->code_fournisseur, $this, 1);
  1077. return $result;
  1078. }
  1079. else {
  1080. return 0;
  1081. }
  1082. }
  1083. /**
  1084. * Renvoie un code compta, suivant le module de code compta.
  1085. * Peut etre identique a celui saisit ou genere automatiquement.
  1086. * A ce jour seule la generation automatique est implementee
  1087. *
  1088. * @param string $type Type of thirdparty ('customer' or 'supplier')
  1089. * @return string Code compta si ok, 0 si aucun, <0 si ko
  1090. */
  1091. function get_codecompta($type) {
  1092. global $conf;
  1093. if (!empty($conf->global->SOCIETE_CODECOMPTA_ADDON)) {
  1094. $file = '';
  1095. $dirsociete = array_merge(array('/societe/core/models/'), $conf->societe_modules);
  1096. foreach ($dirsociete as $dirroot) {
  1097. if (file_exists(DOL_DOCUMENT_ROOT . '/' . $dirroot . $conf->global->SOCIETE_CODECOMPTA_ADDON . ".php")) {
  1098. $file = $dirroot . $conf->global->SOCIETE_CODECOMPTA_ADDON . ".php";
  1099. break;
  1100. }
  1101. }
  1102. if (!empty($file)) {
  1103. dol_include_once($file);
  1104. $classname = $conf->global->SOCIETE_CODECOMPTA_ADDON;
  1105. $mod = new $classname;
  1106. // Defini code compta dans $mod->code
  1107. $result = $mod->get_code($this->db, $this, $type);
  1108. if ($type == 'customer')
  1109. $this->code_compta = $mod->code;
  1110. else if ($type == 'supplier')
  1111. $this->code_compta_fournisseur = $mod->code;
  1112. return $result;
  1113. }
  1114. else {
  1115. $this->error = 'ErrorAccountancyCodeNotDefined';
  1116. return -1;
  1117. }
  1118. } else {
  1119. if ($type == 'customer')
  1120. $this->code_compta = '';
  1121. else if ($type == 'supplier')
  1122. $this->code_compta_fournisseur = '';
  1123. return 0;
  1124. }
  1125. }
  1126. /**
  1127. * Defini la societe mere pour les filiales
  1128. *
  1129. * @param int $id id compagnie mere a positionner
  1130. * @return int <0 if KO, >0 if OK
  1131. */
  1132. function set_parent($id) {
  1133. if ($this->id) {
  1134. $sql = "UPDATE " . MAIN_DB_PREFIX . "societe ";
  1135. $sql .= " SET parent = " . $id;
  1136. $sql .= " WHERE rowid = " . $this->id . ";";
  1137. if ($this->db->query($sql)) {
  1138. return 1;
  1139. } else {
  1140. return -1;
  1141. }
  1142. }
  1143. }
  1144. /**
  1145. * Supprime la societe mere
  1146. *
  1147. * @param int $id id compagnie mere a effacer
  1148. * @return int <0 if KO, >0 if KO
  1149. */
  1150. function remove_parent($id) {
  1151. if ($this->id) {
  1152. $sql = "UPDATE " . MAIN_DB_PREFIX . "societe ";
  1153. $sql .= " SET parent = null";
  1154. $sql .= " WHERE rowid = " . $this->id . ";";
  1155. if ($this->db->query($sql)) {
  1156. return 1;
  1157. } else {
  1158. return -1;
  1159. }
  1160. }
  1161. }
  1162. /**
  1163. * Returns if a profid sould be verified
  1164. *
  1165. * @param int $idprof 1,2,3,4 (Exemple: 1=siren,2=siret,3=naf,4=rcs/rm)
  1166. * @return boolean true , false
  1167. */
  1168. function id_prof_verifiable($idprof) {
  1169. global $conf;
  1170. switch ($idprof) {
  1171. case 1:
  1172. $ret = (!$conf->global->SOCIETE_IDPROF1_UNIQUE ? false : true);
  1173. break;
  1174. case 2:
  1175. $ret = (!$conf->global->SOCIETE_IDPROF2_UNIQUE ? false : true);
  1176. break;
  1177. case 3:
  1178. $ret = (!$conf->global->SOCIETE_IDPROF3_UNIQUE ? false : true);
  1179. break;
  1180. case 4:
  1181. $ret = (!$conf->global->SOCIETE_IDPROF4_UNIQUE ? false : true);
  1182. break;
  1183. default:
  1184. $ret = false;
  1185. }
  1186. return $ret;
  1187. }
  1188. /**
  1189. * Verify if a profid exists into database for others thirds
  1190. *
  1191. * @param int $idprof 1,2,3,4 (Example: 1=siren,2=siret,3=naf,4=rcs/rm)
  1192. * @param string $value Value of profid
  1193. * @param int $socid Id of society if update
  1194. * @return boolean true if exists, false if not
  1195. */
  1196. function id_prof_exists($idprof, $value, $socid = 0) {
  1197. switch ($idprof) {
  1198. case 1:
  1199. $field = "siren";
  1200. break;
  1201. case 2:
  1202. $field = "siret";
  1203. break;
  1204. case 3:
  1205. $field = "ape";
  1206. break;
  1207. case 4:
  1208. $field = "idprof4";
  1209. break;
  1210. }
  1211. //Verify duplicate entries
  1212. $sql = "SELECT COUNT(*) as idprof FROM " . MAIN_DB_PREFIX . "societe WHERE " . $field . " = '" . $value . "'";
  1213. if ($socid)
  1214. $sql .= " AND rowid <> " . $socid;
  1215. $resql = $this->db->query($sql);
  1216. if ($resql) {
  1217. $nump = $this->db->num_rows($resql);
  1218. $obj = $this->db->fetch_object($resql);
  1219. $count = $obj->idprof;
  1220. } else {
  1221. $count = 0;
  1222. print $this->db->error();
  1223. }
  1224. $this->db->free($resql);
  1225. if ($count > 0)
  1226. return true;
  1227. else
  1228. return false;
  1229. }
  1230. /**
  1231. * Verifie la validite d'un identifiant professionnel en fonction du pays de la societe (siren, siret, ...)
  1232. *
  1233. * @param int $idprof 1,2,3,4 (Exemple: 1=siren,2=siret,3=naf,4=rcs/rm)
  1234. * @param Societe $soc Objet societe
  1235. * @return int <=0 if KO, >0 if OK
  1236. * TODO not in business class
  1237. */
  1238. function id_prof_check($idprof, $soc) {
  1239. global $conf;
  1240. $ok = 1;
  1241. if (!empty($conf->global->MAIN_DISABLEPROFIDRULES))
  1242. return 1;
  1243. // Verifie SIREN si pays FR
  1244. if ($idprof == 1 && $soc->country_code == 'FR') {
  1245. $chaine = trim($this->idprof1);
  1246. $chaine = preg_replace('/(\s)/', '', $chaine);
  1247. if (dol_strlen($chaine) != 9)
  1248. return -1;
  1249. $sum = 0;
  1250. for ($i = 0; $i < 10; $i = $i + 2) {
  1251. $sum = $sum + substr($this->idprof1, (8 - $i), 1);
  1252. }
  1253. for ($i = 1; $i < 9; $i = $i + 2) {
  1254. $ps = 2 * substr($this->idprof1, (8 - $i), 1);
  1255. if ($ps > 9) {
  1256. $ps = substr($ps, 0, 1) + substr($ps, 1, 1);
  1257. }
  1258. $sum = $sum + $ps;
  1259. }
  1260. if (substr($sum, -1) != 0)
  1261. return -1;
  1262. }
  1263. // Verifie SIRET si pays FR
  1264. if ($idprof == 2 && $soc->country_code == 'FR') {
  1265. $chaine = trim($this->idprof2);
  1266. $chaine = preg_replace('/(\s)/', '', $chaine);
  1267. if (dol_strlen($chaine) != 14)
  1268. return -1;
  1269. }
  1270. //Verify CIF/NIF/NIE if pays ES
  1271. //Returns: 1 if NIF ok, 2 if CIF ok, 3 if NIE ok, -1 if NIF bad, -2 if CIF bad, -3 if NIE bad, 0 if unexpected bad
  1272. if ($idprof == 1 && $soc->country_code == 'ES') {
  1273. $string = trim($this->idprof1);
  1274. $string = preg_replace('/(\s)/', '', $string);
  1275. $string = strtoupper($string);
  1276. for ($i = 0; $i < 9; $i++)
  1277. $num[$i] = substr($string, $i, 1);
  1278. //Check format
  1279. if (!preg_match('/((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)/', $string))
  1280. return 0;
  1281. //Check NIF
  1282. if (preg_match('/(^[0-9]{8}[A-Z]{1}$)/', $string))
  1283. if ($num[8] == substr('TRWAGMYFPDXBNJZSQVHLCKE', substr($string, 0, 8) % 23, 1))
  1284. return 1;
  1285. else
  1286. return -1;
  1287. //algorithm checking type code CIF
  1288. $sum = $num[2] + $num[4] + $num[6];
  1289. for ($i = 1; $i < 8; $i += 2)
  1290. $sum += substr((2 * $num[$i]), 0, 1) + substr((2 * $num[$i]), 1, 1);
  1291. $n = 10 - substr($sum, strlen($sum) - 1, 1);
  1292. //Chek special NIF
  1293. if (preg_match('/^[KLM]{1}/', $string))
  1294. if ($num[8] == chr(64 + $n) || $num[8] == substr('TRWAGMYFPDXBNJZSQVHLCKE', substr($string, 1, 8) % 23, 1))
  1295. return 1;
  1296. else
  1297. return -1;
  1298. //Check CIF
  1299. if (preg_match('/^[ABCDEFGHJNPQRSUVW]{1}/', $string))
  1300. if ($num[8] == chr(64 + $n) || $num[8] == substr($n, strlen($n) - 1, 1))
  1301. return 2;
  1302. else
  1303. return -2;
  1304. //Check NIE T
  1305. if (preg_match('/^[T]{1}/', $string))
  1306. if ($num[8] == preg_match('/^[T]{1}[A-Z0-9]{8}$/', $string))
  1307. return 3;
  1308. else
  1309. return -3;
  1310. //Check NIE XYZ
  1311. if (preg_match('/^[XYZ]{1}/', $string))
  1312. if ($num[8] == substr('TRWAGMYFPDXBNJZSQVHLCKE', substr(str_replace(array('X', 'Y', 'Z'), array('0', '1', '2'), $string), 0, 8) % 23, 1))
  1313. return 3;
  1314. else
  1315. return -3;
  1316. //Can not be verified
  1317. return -4;
  1318. }
  1319. return $ok;
  1320. }
  1321. /**
  1322. * Renvoi url de verification d'un identifiant professionnal
  1323. *
  1324. * @param int $idprof 1,2,3,4 (Exemple: 1=siren,2=siret,3=naf,4=rcs/rm)
  1325. * @param Societe $soc Objet societe
  1326. * @return string url ou chaine vide si aucune url connue
  1327. * TODO not in business class
  1328. */
  1329. function id_prof_url($idprof, $soc) {
  1330. global $conf, $langs;
  1331. if (!empty($conf->global->MAIN_DISABLEPROFIDRULES))
  1332. return '';
  1333. $url = '';
  1334. if ($idprof == 1 && $soc->country_code == 'FR')
  1335. $url = 'http://www.societe.com/cgi-bin/recherche?rncs=' . $soc->idprof1;
  1336. if ($idprof == 1 && $soc->country_code == 'GB')
  1337. $url = 'http://www.companieshouse.gov.uk/WebCHeck/findinfolink/';
  1338. if ($idprof == 1 && $soc->country_code == 'ES')
  1339. $url = 'http://www.e-informa.es/servlet/app/portal/ENTP/screen/SProducto/prod/ETIQUETA_EMPRESA/nif/' . $soc->idprof1;
  1340. if ($url)
  1341. return '<a target="_blank" href="' . $url . '">[' . $langs->trans("Check") . ']</a>';
  1342. return '';
  1343. }
  1344. /**
  1345. * Indique si la societe a des projets
  1346. *
  1347. * @return bool true si la societe a des projets, false sinon
  1348. */
  1349. function has_projects() {
  1350. $sql = 'SELECT COUNT(*) as numproj FROM ' . MAIN_DB_PREFIX . 'projet WHERE fk_soc = ' . $this->id;
  1351. $resql = $this->db->query($sql);
  1352. if ($resql) {
  1353. $nump = $this->db->num_rows($resql);
  1354. $obj = $this->db->fetch_object($resql);
  1355. $count = $obj->numproj;
  1356. } else {
  1357. $count = 0;
  1358. print $this->db->error();
  1359. }
  1360. $this->db->free($resql);
  1361. return ($count > 0);
  1362. }
  1363. /**
  1364. * Charge les informations d'ordre info dans l'objet societe
  1365. *
  1366. * @param int $id Id de la societe a charger
  1367. * @return void
  1368. */
  1369. function info($id) {
  1370. $sql = "SELECT s.rowid, s.nom as name, s.datec, s.datea,";
  1371. $sql.= " fk_user_creat, fk_user_modif";
  1372. $sql.= " FROM " . MAIN_DB_PREFIX . "societe as s";
  1373. $sql.= " WHERE s.rowid = " . $id;
  1374. $result = $this->db->query($sql);
  1375. if ($result) {
  1376. if ($this->db->num_rows($result)) {
  1377. $obj = $this->db->fetch_object($result);
  1378. $this->id = $obj->rowid;
  1379. if ($obj->fk_user_creat) {
  1380. $cuser = new User($this->db);
  1381. $cuser->fetch($obj->fk_user_creat);
  1382. $this->user_creation = $cuser;
  1383. }
  1384. if ($obj->fk_user_modif) {
  1385. $muser = new User($this->db);
  1386. $muser->fetch($obj->fk_user_modif);
  1387. $this->user_modification = $muser;
  1388. }
  1389. $this->ref = $obj->name;
  1390. $this->date_creation = $this->db->jdate($obj->datec);
  1391. $this->date_modification = $this->db->jdate($obj->datea);
  1392. }
  1393. $this->db->free($result);
  1394. } else {
  1395. dol_print_error($this->db);
  1396. }
  1397. }
  1398. /**
  1399. * Return if third party is a company (Business) or an end user (Consumer)
  1400. *
  1401. * @return boolean true=is a company, false=a and user
  1402. */
  1403. function isACompany() {
  1404. global $conf;
  1405. // Define if third party is treated as company of not when nature is unknown
  1406. $isacompany = empty($conf->global->MAIN_UNKNOWN_CUSTOMERS_ARE_COMPANIES) ? 0 : 1; // 0 by default
  1407. if (!empty($this->tva_intra))
  1408. $isacompany = 1;
  1409. else if (!empty($this->typent_code) && in_array($this->typent_code, array('TE_PRIVATE')))
  1410. $isacompany = 0;
  1411. else if (!empty($this->typent_code) && in_array($this->typent_code, array('TE_SMALL', 'TE_MEDIUM', 'TE_LARGE')))
  1412. $isacompany = 1;
  1413. return $isacompany;
  1414. }
  1415. /**
  1416. * Charge la liste des categories fournisseurs
  1417. *
  1418. * @return int 0 if success, <> 0 if error
  1419. */
  1420. function LoadSupplierCateg() {
  1421. $this->SupplierCategories = array();
  1422. $sql = "SELECT rowid, label";
  1423. $sql.= " FROM " . MAIN_DB_PREFIX . "categorie";
  1424. $sql.= " WHERE type = 1";
  1425. $resql = $this->db->query($sql);
  1426. if ($resql) {
  1427. while ($obj = $this->db->fetch_object($resql)) {
  1428. $this->SupplierCategories[$obj->rowid] = $obj->label;
  1429. }
  1430. return 0;
  1431. } else {
  1432. return -1;
  1433. }
  1434. }
  1435. /**
  1436. * Charge la liste des categories fournisseurs
  1437. *
  1438. * @param int $categorie_id Id of category
  1439. * @return int 0 if success, <> 0 if error
  1440. */
  1441. function AddFournisseurInCategory($categorie_id) {
  1442. if ($categorie_id > 0) {
  1443. $sql = "INSERT INTO " . MAIN_DB_PREFIX . "categorie_fournisseur (fk_categorie, fk_societe) ";
  1444. $sql.= " VALUES ('" . $categorie_id . "','" . $this->id . "');";
  1445. if ($resql = $this->db->query($sql))
  1446. return 0;
  1447. }
  1448. else {
  1449. return 0;
  1450. }
  1451. return -1;
  1452. }
  1453. /**
  1454. * Create a third party into database from a member object
  1455. *
  1456. * @param Member $member Object member
  1457. * @param string $socname Name of third party to force
  1458. * @return int <0 if KO, id of created account if OK
  1459. */
  1460. function create_from_member($member, $socname = '') {
  1461. global $conf, $user, $langs;
  1462. $name = $socname ? $socname : $member->societe;
  1463. if (empty($name))
  1464. $name = $member->getFullName($langs);
  1465. // Positionne parametres
  1466. $this->nom = $name; // TODO obsolete
  1467. $this->name = $name;
  1468. $this->adresse = $member->adresse; // TODO obsolete
  1469. $this->address = $member->adresse;
  1470. $this->cp = $member->cp; // TODO obsolete
  1471. $this->zip = $member->cp;
  1472. $this->ville = $member->ville; // TODO obsolete
  1473. $this->town = $member->ville;
  1474. $this->pays_code = $member->country_code; // TODO obsolete
  1475. $this->country_code = $member->country_code;
  1476. $this->pays_id = $member->country_id; // TODO obsolete
  1477. $this->country_id = $member->country_id;
  1478. $this->tel = $member->phone; // deprecated
  1479. $this->phone = $member->phone; // Prof phone
  1480. $this->email = $member->email;
  1481. $this->client = 1; // A member is a customer by default
  1482. $this->code_client = -1;
  1483. $this->code_fournisseur = -1;
  1484. $this->db->begin();
  1485. // Cree et positionne $this->id
  1486. $result = $this->create($user);
  1487. if ($result >= 0) {
  1488. $sql = "UPDATE " . MAIN_DB_PREFIX . "adherent";
  1489. $sql.= " SET fk_soc=" . $this->id;
  1490. $sql.= " WHERE rowid=" . $member->id;
  1491. $resql = $this->db->query($sql);
  1492. if ($resql) {
  1493. $this->db->commit();
  1494. return $this->id;
  1495. } else {
  1496. $this->error = $this->db->error();
  1497. $this->db->rollback();
  1498. return -1;
  1499. }
  1500. } else {
  1501. $this->db->rollback();
  1502. return $result;
  1503. }
  1504. }
  1505. /**
  1506. * Initialise an instance with random values.
  1507. * Used to build previews or test instances.
  1508. * id must be 0 if object instance is a specimen.
  1509. *
  1510. * @return void
  1511. */
  1512. function initAsSpecimen() {
  1513. global $user, $langs, $conf, $mysoc;
  1514. $now = dol_now();
  1515. // Initialize parameters
  1516. $this->id = 0;
  1517. $this->name = 'THIRDPARTY SPECIMEN ' . dol_print_date($now, 'dayhourlog');
  1518. $this->specimen = 1;
  1519. $this->zip = '99999';
  1520. $this->town = 'MyTown';
  1521. $this->country_id = 'FR';
  1522. $this->code_client = 'CC-' . dol_print_date($now, 'dayhourlog');
  1523. $this->code_fournisseur = 'SC-' . dol_print_date($now, 'dayhourlog');
  1524. $this->capital = 10000;
  1525. $this->client = 1;
  1526. $this->prospect = 1;
  1527. $this->fournisseur = 1;
  1528. $this->tva_assuj = 1;
  1529. $this->tva_intra = 'EU1234567';
  1530. $this->note = 'This is a comment';
  1531. $this->idprof1 = 'idprof1';
  1532. $this->idprof2 = 'idprof2';
  1533. $this->idprof3 = 'idprof3';
  1534. $this->idprof4 = 'idprof4';
  1535. }
  1536. /**
  1537. * Charge indicateurs this->nb de tableau de bord
  1538. *
  1539. * @return int <0 if KO, >0 if OK
  1540. */
  1541. function load_state_board() {
  1542. global $conf, $user;
  1543. $this->nb = array("customer" => 0, "prospect" => 0, "suspect" => 0);
  1544. $result = $this->getView("count_status", array("group" => "exact"));
  1545. foreach ($result->rows as $aRow) {
  1546. //print_r($aRow);exit;
  1547. $key = $aRow->key;
  1548. $this->nb[$this->fk_status->values->$key->type] = $aRow->value;
  1549. return 1;
  1550. }
  1551. }
  1552. /**
  1553. * Return label of status (activity, closed)
  1554. *
  1555. * @return string Libelle
  1556. */
  1557. function getLibStatus() {
  1558. return $this->LibStatus($this->Status);
  1559. }
  1560. /**
  1561. * Build and get $mysoc object
  1562. *
  1563. * @param Conf $conf Conf object (possibility to use another entity)
  1564. * @return void
  1565. */
  1566. function getMysoc($conf) {
  1567. global $langs;
  1568. $this->id = 0;
  1569. $this->name = (!empty($conf->global->MAIN_INFO_SOCIETE_NOM)) ? $conf->global->MAIN_INFO_SOCIETE_NOM : '';
  1570. $this->nom = $this->name; // deprecated
  1571. $this->address = (!empty($conf->global->MAIN_INFO_SOCIETE_ADRESSE)) ? $conf->global->MAIN_INFO_SOCIETE_ADRESSE : '';
  1572. $this->adresse = $this->address; // deprecated
  1573. $this->zip = (!empty($conf->global->MAIN_INFO_SOCIETE_CP)) ? $conf->global->MAIN_INFO_SOCIETE_CP : '';
  1574. $this->cp = $this->zip; // deprecated
  1575. $this->town = (!empty($conf->global->MAIN_INFO_SOCIETE_VILLE)) ? $conf->global->MAIN_INFO_SOCIETE_VILLE : '';
  1576. $this->ville = $this->town; // deprecated
  1577. $this->state_id = $conf->global->MAIN_INFO_SOCIETE_DEPARTEMENT;
  1578. $this->note = empty($conf->global->MAIN_INFO_SOCIETE_NOTE) ? '' : $conf->global->MAIN_INFO_SOCIETE_NOTE;
  1579. // We define country_id, country_code and country
  1580. $country_id = $country_code = $country_label = '';
  1581. if (!empty($conf->global->MAIN_INFO_SOCIETE_PAYS)) {
  1582. $tmp = explode(':', $conf->global->MAIN_INFO_SOCIETE_PAYS);
  1583. $country_id = $tmp[0];
  1584. if (!empty($tmp[1])) { // If $conf->global->MAIN_INFO_SOCIETE_PAYS is "id:code:label"
  1585. $country_code = $tmp[1];
  1586. $country_label = $tmp[2];
  1587. } else { // For backward compatibility
  1588. include_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
  1589. $country_code = getCountry($country_id, 2, $db); // This need a SQL request, but it's the old feature
  1590. $country_label = getCountry($country_id, 0, $db); // This need a SQL request, but it's the old feature
  1591. }
  1592. }
  1593. $this->pays_id = $country_id; // TODO deprecated
  1594. $this->country_id = $country_id;
  1595. $this->pays_code = $country_code; // TODO deprecated
  1596. $this->country_code = $country_code;
  1597. $this->country = $country_label;
  1598. if (is_object($langs))
  1599. $this->country = ($langs->trans('Country' . $country_code) != 'Country' . $country_code) ? $langs->trans('Country' . $country_code) : $country_label;
  1600. $this->pays = $this->country; // TODO deprecated
  1601. $this->tel = empty($conf->global->MAIN_INFO_SOCIETE_TEL) ? '' : $conf->global->MAIN_INFO_SOCIETE_TEL; // TODO deprecated
  1602. $this->phone = empty($conf->global->MAIN_INFO_SOCIETE_TEL) ? '' : $conf->global->MAIN_INFO_SOCIETE_TEL;
  1603. $this->fax = empty($conf->global->MAIN_INFO_SOCIETE_FAX) ? '' : $conf->global->MAIN_INFO_SOCIETE_FAX;
  1604. $this->url = empty($conf->global->MAIN_INFO_SOCIETE_WEB) ? '' : $conf->global->MAIN_INFO_SOCIETE_WEB;
  1605. // Id prof generiques
  1606. $this->idprof1 = empty($conf->global->MAIN_INFO_SIREN) ? '' : $conf->global->MAIN_INFO_SIREN;
  1607. $this->idprof2 = empty($conf->global->MAIN_INFO_SIRET) ? '' : $conf->global->MAIN_INFO_SIRET;
  1608. $this->idprof3 = empty($conf->global->MAIN_INFO_APE) ? '' : $conf->global->MAIN_INFO_APE;
  1609. $this->idprof4 = empty($conf->global->MAIN_INFO_RCS) ? '' : $conf->global->MAIN_INFO_RCS;
  1610. $this->idprof5 = empty($conf->global->MAIN_INFO_PROFID5) ? '' : $conf->global->MAIN_INFO_PROFID5;
  1611. $this->idprof6 = empty($conf->global->MAIN_INFO_PROFID6) ? '' : $conf->global->MAIN_INFO_PROFID6;
  1612. $this->tva_intra = (!empty($conf->global->MAIN_INFO_TVAINTRA)) ? $conf->global->MAIN_INFO_TVAINTRA : ''; // VAT number, not necessarly INTRA.
  1613. $this->capital = (!empty($conf->global->MAIN_INFO_CAPITAL)) ? $conf->global->MAIN_INFO_CAPITAL : '';
  1614. $this->forme_juridique_code = $conf->global->MAIN_INFO_SOCIETE_FORME_JURIDIQUE;
  1615. $this->email = (!empty($conf->global->MAIN_INFO_SOCIETE_MAIL)) ? $conf->global->MAIN_INFO_SOCIETE_MAIL : '';
  1616. $this->logo = (!empty($conf->global->MAIN_INFO_SOCIETE_LOGO)) ? $conf->global->MAIN_INFO_SOCIETE_LOGO : '';
  1617. $this->logo_small = (!empty($conf->global->MAIN_INFO_SOCIETE_LOGO_SMALL)) ? $conf->global->MAIN_INFO_SOCIETE_LOGO_SMALL : '';
  1618. $this->logo_mini = (!empty($conf->global->MAIN_INFO_SOCIETE_LOGO_MINI)) ? $conf->global->MAIN_INFO_SOCIETE_LOGO_MINI : '';
  1619. // Define if company use vat or not (Do not use conf->global->FACTURE_TVAOPTION anymore)
  1620. $this->tva_assuj = ((isset($conf->global->FACTURE_TVAOPTION) && $conf->global->FACTURE_TVAOPTION == 'franchise') ? 0 : 1);
  1621. // Define if company use local taxes
  1622. $this->localtax1_assuj = ((isset($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION == 'localtax1on') ? 1 : 0);
  1623. $this->localtax2_assuj = ((isset($conf->global->FACTURE_LOCAL_TAX2_OPTION) && $conf->global->FACTURE_LOCAL_TAX2_OPTION == 'localtax2on') ? 1 : 0);
  1624. }
  1625. /*
  1626. * Graph comptes by status
  1627. *
  1628. */
  1629. function graphPieStatus($json = false) {
  1630. global $user, $conf, $langs;
  1631. //$color = array(-1 => "#A51B00", 0 => "#CCC", 1 => "#000", 2 => "#FEF4AE", 3 => "#666", 4 => "#1f17c1", 5 => "#DE7603", 6 => "#D40000", 7 => "#7ac52e", 8 => "#1b651b", 9 => "#66c18c", 10 => "#2e99a0");
  1632. if ($json) { // For Data see viewgraph.php
  1633. $langs->load("companies");
  1634. $params = array('group' => true);
  1635. if ($user->rights->societe->client->voir) { // See ALL
  1636. $params = array('group' => true);
  1637. $result = $this->getView("count_status", $params);
  1638. $filter = false;
  1639. } else {
  1640. $params = array('group' => true, "startkey" => array($user->name), "endkey" => array($user->name, new stdClass()));
  1641. $result = $this->getView("commercial_status", $params);
  1642. $filter = true;
  1643. }
  1644. //print_r($result);
  1645. $i = 0;
  1646. foreach ($result->rows as $aRow) {
  1647. if ($filter)
  1648. $key = $aRow->key[1];
  1649. else
  1650. $key = $aRow->key;
  1651. $label = $langs->trans($this->fk_extrafields->fields->Status->values->$key->label);
  1652. if (empty($label))
  1653. $label = $langs->trans($aRow->key);
  1654. if ($i == 0) { // first element
  1655. $output[$i] = new stdClass();
  1656. $output[$i]->name = $label;
  1657. $output[$i]->y = $aRow->value;
  1658. $output[$i]->sliced = true;
  1659. $output[$i]->selected = true;
  1660. }
  1661. else
  1662. $output[$i] = array($label, $aRow->value);
  1663. $i++;
  1664. }
  1665. return $output;
  1666. } else {
  1667. $total = 0;
  1668. $i = 0;
  1669. ?>
  1670. <div
  1671. id="pie-status" style="min-width: 100px; height: 280px; margin: 0 auto"></div>
  1672. <script type="text/javascript">
  1673. $(document).ready(function() {
  1674. (function($) { // encapsulate jQuery
  1675. $(function() {
  1676. var seriesOptions = [],
  1677. yAxisOptions = [],
  1678. seriesCounter = 0,
  1679. colors = Highcharts.getOptions().colors;
  1680. $.getJSON('<?php echo DOL_URL_ROOT . '/core/ajax/viewgraph.php'; ?>?json=graphPieStatus&class=<?php echo get_class($this); ?>&callback=?', function(data) {
  1681. seriesOptions = data;
  1682. createChart();
  1683. });
  1684. // create the chart when all data is loaded
  1685. function createChart() {
  1686. var chart;
  1687. chart = new Highcharts.Chart({
  1688. chart: {
  1689. renderTo: "pie-status",
  1690. //defaultSeriesType: "bar",
  1691. margin: 0,
  1692. plotBackgroundColor: null,
  1693. plotBorderWidth: null,
  1694. plotShadow: false
  1695. },
  1696. legend: {
  1697. layout: "vertical", backgroundColor: Highcharts.theme.legendBackgroundColor || "#FFFFFF", align: "left", verticalAlign: "bottom", x: 0, y: 20, floating: true, shadow: true,
  1698. enabled: false
  1699. },
  1700. title: {
  1701. text: null
  1702. },
  1703. tooltip: {
  1704. enabled: true,
  1705. pointFormat: '{series.name}: <b>{point.percentage}%</b>',
  1706. percentageDecimals: 2
  1707. },
  1708. navigator: {
  1709. margin: 30
  1710. },
  1711. plotOptions: {
  1712. pie: {
  1713. allowPointSelect: true,
  1714. cursor: 'pointer',
  1715. dataLabels: {
  1716. enabled: true,
  1717. color: '#FFF',
  1718. connectorColor: '#FFF',
  1719. distance: 30,
  1720. formatter: function() {
  1721. return '<b>' + this.point.name + '</b><br> ' + Math.round(this.percentage) + ' %';
  1722. }
  1723. }
  1724. }
  1725. },
  1726. series: [{
  1727. type: "pie",
  1728. name: "<?php echo $langs->trans("Quantity"); ?>",
  1729. size: 100,
  1730. data: seriesOptions
  1731. }]
  1732. });
  1733. }
  1734. });
  1735. })(jQuery);
  1736. });
  1737. </script>
  1738. <?php
  1739. }
  1740. }
  1741. /*
  1742. * Graph comptes by status
  1743. *
  1744. */
  1745. function graphBarStatus($json = false) {
  1746. global $user, $conf, $langs;
  1747. $langs->load("companies");
  1748. if ($json) { // For Data see viewgraph.php
  1749. $keystart[0] = $_GET["name"];
  1750. $keyend[0] = $_GET["name"];
  1751. $keyend[1] = new stdClass();
  1752. $params = array('group' => true, 'group_level' => 2, 'startkey' => $keystart, 'endkey' => $keyend);
  1753. $result = $this->getView("commercial_status", $params);
  1754. foreach ($this->fk_extrafields->fields->Status->values as $key => $aRow) {
  1755. //print_r($aRow);exit;
  1756. $label = $langs->trans($key);
  1757. if ($aRow->enable) {
  1758. $tab[$key] = new stdClass();
  1759. $tab[$key]->label = $label;
  1760. $tab[$key]->value = 0;
  1761. }
  1762. }
  1763. foreach ($result->rows as $aRow) { // Update counters from view
  1764. if (!is_object($tab[$aRow->key[1]]))
  1765. $tab[$aRow->key[1]] = new stdClass();
  1766. if (isset($tab[$aRow->key[1]]->value))
  1767. $tab[$aRow->key[1]]->value = 0;
  1768. $tab[$aRow->key[1]]->value+=$aRow->value;
  1769. }
  1770. foreach ($tab as $aRow)
  1771. $output[] = array($aRow->label, $aRow->value);
  1772. return $output;
  1773. } else {
  1774. $total = 0;
  1775. $i = 0;
  1776. ?>
  1777. <div
  1778. id="bar-status" style="min-width: 100px; height: 280px; margin: 0 auto"></div>
  1779. <script type="text/javascript">
  1780. $(document).ready(function() {
  1781. (function($) { // encapsulate jQuery
  1782. $(function() {
  1783. var seriesOptions = [],
  1784. yAxisOptions = [],
  1785. seriesCounter = 0,
  1786. names = [<?php
  1787. if ($user->rights->societe->client->voir) { // See ALL
  1788. $params = array('group' => true, 'group_level' => 1);
  1789. $result = $this->getView("commercial_status", $params);
  1790. } else {
  1791. $result->rows[0]->key = array($user->name);
  1792. }
  1793. if (count($result->rows)) {
  1794. foreach ($result->rows as $aRow) {
  1795. if ($i == 0)
  1796. echo "'" . $aRow->key[0] . "'";
  1797. else
  1798. echo ",'" . $aRow->key[0] . "'";
  1799. $i++;
  1800. }
  1801. }
  1802. ?>],
  1803. colors = Highcharts.getOptions().colors;
  1804. $.each(names, function(i, name) {
  1805. $.getJSON('<?php echo DOL_URL_ROOT . '/core/ajax/viewgraph.php'; ?>?json=graphBarStatus&class=<?php echo get_class($this); ?>&name=' + name.toString() + '&callback=?', function(data) {
  1806. seriesOptions[i] = {
  1807. name: name,
  1808. data: data
  1809. };
  1810. // As we're loading the data asynchronously, we don't know what order it will arrive. So
  1811. // we keep a counter and create the chart when all the data is loaded.
  1812. seriesCounter++;
  1813. if (seriesCounter == names.length) {
  1814. createChart();
  1815. }
  1816. });
  1817. });
  1818. // create the chart when all data is loaded
  1819. function createChart() {
  1820. var chart;
  1821. chart = new Highcharts.Chart({
  1822. chart: {
  1823. renderTo: 'bar-status',
  1824. defaultSeriesType: "column",
  1825. zoomType: "x",
  1826. marginBottom: 30
  1827. },
  1828. credits: {
  1829. enabled: false
  1830. },
  1831. xAxis: {
  1832. categories: [<?php
  1833. $i = 0;
  1834. foreach ($this->fk_extrafields->fields->Status->values as $key => $aRow) {
  1835. $label = $langs->trans($aRow->label);
  1836. if (empty($label))
  1837. $label = $langs->trans($key);
  1838. if ($aRow->enable) {
  1839. if ($i == 0)
  1840. echo "'" . $label . "'";
  1841. else
  1842. echo ",'" . $label . "'";
  1843. $i++;
  1844. }
  1845. }
  1846. ?>],
  1847. maxZoom: 1
  1848. //labels: {rotation: 90, align: "left"}
  1849. },
  1850. yAxis: {
  1851. title: {text: "Total"},
  1852. allowDecimals: false,
  1853. min: 0
  1854. },
  1855. title: {
  1856. //text: "<?php echo $langs->trans("SalesRepresentatives"); ?>"
  1857. text: null
  1858. },
  1859. legend: {
  1860. layout: 'vertical',
  1861. align: 'right',
  1862. verticalAlign: 'top',
  1863. x: -5,
  1864. y: 5,
  1865. floating: true,
  1866. borderWidth: 1,
  1867. backgroundColor: Highcharts.theme.legendBackgroundColor || '#FFFFFF',
  1868. shadow: true
  1869. },
  1870. tooltip: {
  1871. enabled: true,
  1872. formatter: function() {
  1873. //return this.point.name + ' : ' + this.y;
  1874. return '<b>' + this.x + '</b><br/>' +
  1875. this.series.name + ': ' + this.y;
  1876. }
  1877. },
  1878. series: seriesOptions
  1879. });
  1880. }
  1881. });
  1882. })(jQuery);
  1883. });
  1884. </script>
  1885. <?php
  1886. }
  1887. }
  1888. }
  1889. ?>