PageRenderTime 45ms CodeModel.GetById 4ms RepoModel.GetById 0ms app.codeStats 1ms

/htdocs/contrat/class/contrat.class.php

https://bitbucket.org/speedealing/speedealing
PHP | 1990 lines | 1421 code | 236 blank | 333 comment | 320 complexity | 8c4a3f14839347a78face6de42f6b3d7 MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.1, GPL-3.0, MIT

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /* Copyright (C) 2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2004-2012 Destailleur Laurent <eldy@users.sourceforge.net>
  4. * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@capnetworks.com>
  5. * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
  6. * Copyright (C) 2008 Raphael Bertrand (Resultic) <raphael.bertrand@resultic.fr>
  7. * Copyright (C) 2010-2011 Juanjo Menent <jmenent@2byte.es>
  8. * Copyright (C) 2011 Herve Prot <herve.prot@symeos.com>
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. */
  23. /**
  24. * \file htdocs/contrat/class/contrat.class.php
  25. * \ingroup contrat
  26. * \brief File of class to manage contracts
  27. */
  28. require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
  29. /**
  30. * Class to manage contracts
  31. */
  32. class Contrat extends CommonObject
  33. {
  34. public $element='contrat';
  35. public $table_element='contrat';
  36. public $table_element_line='contratdet';
  37. public $fk_element='fk_contrat';
  38. var $id;
  39. var $ref;
  40. var $socid;
  41. var $societe; // Objet societe
  42. var $statut=0; // 0=Draft,
  43. var $product;
  44. var $user_author;
  45. var $date_creation;
  46. var $date_validation;
  47. var $date_contrat;
  48. var $date_cloture;
  49. var $commercial_signature_id;
  50. var $commercial_suivi_id;
  51. var $note; // deprecated
  52. var $note_private;
  53. var $note_public;
  54. var $fk_projet;
  55. var $extraparams=array();
  56. var $lines=array();
  57. /**
  58. * Constructor
  59. *
  60. * @param DoliDB $db Database handler
  61. */
  62. function __construct($db = '')
  63. {
  64. $this->db = $db;
  65. }
  66. /**
  67. * Return next contract ref
  68. *
  69. * @param Societe $soc objet society
  70. * @return string free reference for contract
  71. */
  72. function getNextNumRef($soc)
  73. {
  74. global $db, $langs, $conf;
  75. $langs->load("contract");
  76. $dir = DOL_DOCUMENT_ROOT . "/core/modules/contract";
  77. if (empty($conf->global->CONTRACT_ADDON))
  78. {
  79. $conf->global->CONTRACT_ADDON='mod_contract_serpis';
  80. }
  81. $file = $conf->global->CONTRACT_ADDON.".php";
  82. // Chargement de la classe de numerotation
  83. $classname = $conf->global->CONTRACT_ADDON;
  84. $result=include_once $dir.'/'.$file;
  85. if ($result)
  86. {
  87. $obj = new $classname();
  88. $numref = "";
  89. $numref = $obj->getNextValue($soc,$this);
  90. if ( $numref != "")
  91. {
  92. return $numref;
  93. }
  94. else
  95. {
  96. dol_print_error($db,get_class($this)."::getNextValue ".$obj->error);
  97. return "";
  98. }
  99. }
  100. else
  101. {
  102. print $langs->trans("Error")." ".$langs->trans("Error_CONTRACT_ADDON_NotDefined");
  103. return "";
  104. }
  105. }
  106. /**
  107. * Activate a contract line
  108. *
  109. * @param User $user Objet User qui active le contrat
  110. * @param int $line_id Id de la ligne de detail a activer
  111. * @param timestamp $date Date d'ouverture
  112. * @param timestamp $date_end Date fin prevue
  113. * @param string $comment A comment typed by user
  114. * @return int <0 if KO, >0 if OK
  115. */
  116. function active_line($user, $line_id, $date, $date_end='', $comment='')
  117. {
  118. global $langs,$conf;
  119. $error=0;
  120. $this->db->begin();
  121. $sql = "UPDATE ".MAIN_DB_PREFIX."contratdet SET statut = 4,";
  122. $sql.= " date_ouverture = ".(dol_strlen($date)!=0?"'".$this->db->idate($date)."'":"null").",";
  123. $sql.= " date_fin_validite = ".(dol_strlen($date_end)!=0?"'".$this->db->idate($date_end)."'":"null").",";
  124. $sql.= " fk_user_ouverture = ".$user->id.",";
  125. $sql.= " date_cloture = null,";
  126. $sql.= " commentaire = '".$this->db->escape($comment)."'";
  127. $sql.= " WHERE rowid = ".$line_id . " AND (statut = 0 OR statut = 3 OR statut = 5)";
  128. dol_syslog(get_class($this)."::active_line sql=".$sql);
  129. $resql = $this->db->query($sql);
  130. if ($resql)
  131. {
  132. // Appel des triggers
  133. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  134. $interface=new Interfaces($this->db);
  135. $result=$interface->run_triggers('CONTRACT_SERVICE_ACTIVATE',$this,$user,$langs,$conf);
  136. if ($result < 0) { $error++; $this->errors=$interface->errors; }
  137. // Fin appel triggers
  138. $this->db->commit();
  139. return 1;
  140. }
  141. else
  142. {
  143. $this->error=$this->db->lasterror();
  144. dol_syslog(get_class($this)."::active_line error ".$this->error, LOG_ERR);
  145. $this->db->rollback();
  146. return -1;
  147. }
  148. }
  149. /**
  150. * Close a contract line
  151. *
  152. * @param User $user Objet User qui active le contrat
  153. * @param int $line_id Id de la ligne de detail a activer
  154. * @param timestamp $date_end Date fin
  155. * @param string $comment A comment typed by user
  156. * @return int <0 if KO, >0 if OK
  157. */
  158. function close_line($user, $line_id, $date_end, $comment='')
  159. {
  160. global $langs,$conf;
  161. $error=0;
  162. // statut actif : 4
  163. $this->db->begin();
  164. $sql = "UPDATE ".MAIN_DB_PREFIX."contratdet SET statut = 5,";
  165. $sql.= " date_cloture = '".$this->db->idate($date_end)."',";
  166. $sql.= " fk_user_cloture = ".$user->id.",";
  167. $sql.= " commentaire = '".$this->db->escape($comment)."'";
  168. $sql.= " WHERE rowid = ".$line_id . " AND statut = 4";
  169. $resql = $this->db->query($sql);
  170. if ($resql)
  171. {
  172. // Appel des triggers
  173. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  174. $interface=new Interfaces($this->db);
  175. $result=$interface->run_triggers('CONTRACT_SERVICE_CLOSE',$this,$user,$langs,$conf);
  176. if ($result < 0) { $error++; $this->errors=$interface->errors; }
  177. // Fin appel triggers
  178. $this->db->commit();
  179. return 1;
  180. }
  181. else
  182. {
  183. $this->error=$this->db->lasterror();
  184. dol_syslog(get_class($this)."::close_line error ".$this->error, LOG_ERR);
  185. $this->db->rollback();
  186. return -1;
  187. }
  188. }
  189. /**
  190. * Close all lines of a contract
  191. *
  192. * @param User $user Object User making action
  193. * @return void
  194. */
  195. function cloture($user)
  196. {
  197. $this->db->begin();
  198. // Load lines
  199. $this->fetch_lines();
  200. $ok=true;
  201. foreach($this->lines as $contratline)
  202. {
  203. // Close line not already closed
  204. if ($contratline->statut != 5)
  205. {
  206. $contratline->date_cloture=dol_now();
  207. $contratline->fk_user_cloture=$user->id;
  208. $contratline->statut='5';
  209. $result=$contratline->update($user);
  210. if ($result < 0)
  211. {
  212. $ok=false;
  213. break;
  214. }
  215. }
  216. }
  217. if ($this->statut == 0)
  218. {
  219. $result=$this->validate($user);
  220. if ($result < 0) $ok=false;
  221. }
  222. if ($ok)
  223. {
  224. $this->db->commit();
  225. }
  226. else
  227. {
  228. dol_print_error($this->db,'Error in cloture function');
  229. $this->db->rollback();
  230. }
  231. }
  232. /**
  233. * Validate a contract
  234. *
  235. * @param User $user Objet User
  236. * @return int <0 if KO, >0 if OK
  237. */
  238. function validate($user)
  239. {
  240. global $langs, $conf;
  241. $error=0;
  242. $sql = "UPDATE ".MAIN_DB_PREFIX."contrat SET statut = 1";
  243. $sql .= " WHERE rowid = ".$this->id . " AND statut = 0";
  244. $resql = $this->db->query($sql);
  245. if ($resql)
  246. {
  247. // Appel des triggers
  248. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  249. $interface=new Interfaces($this->db);
  250. $result=$interface->run_triggers('CONTRACT_VALIDATE',$this,$user,$langs,$conf);
  251. if ($result < 0) { $error++; $this->errors=$interface->errors; }
  252. // Fin appel triggers
  253. return 1;
  254. }
  255. else
  256. {
  257. $this->error=$this->db->error();
  258. return -1;
  259. }
  260. }
  261. /**
  262. * Load a contract from database
  263. *
  264. * @param int $id Id of contract to load
  265. * @param string $ref Ref
  266. * @return int <0 if KO, id of contract if OK
  267. */
  268. function fetch($id,$ref='')
  269. {
  270. $sql = "SELECT rowid, statut, ref, fk_soc, mise_en_service as datemise,";
  271. $sql.= " fk_user_mise_en_service, date_contrat as datecontrat,";
  272. $sql.= " fk_user_author,";
  273. $sql.= " fk_projet,";
  274. $sql.= " fk_commercial_signature, fk_commercial_suivi,";
  275. $sql.= " note as note_private, note_public, extraparams";
  276. $sql.= " FROM ".MAIN_DB_PREFIX."contrat";
  277. if ($ref)
  278. {
  279. $sql.= " WHERE ref='".$ref."'";
  280. $sql.= " AND entity IN (".getEntity('contract').")";
  281. }
  282. else $sql.= " WHERE rowid=".$id;
  283. dol_syslog(get_class($this)."::fetch sql=".$sql, LOG_DEBUG);
  284. $resql = $this->db->query($sql);
  285. if ($resql)
  286. {
  287. $result = $this->db->fetch_array($resql);
  288. if ($result)
  289. {
  290. $this->id = $result["rowid"];
  291. $this->ref = (!isset($result["ref"]) || !$result["ref"]) ? $result["rowid"] : $result["ref"];
  292. $this->statut = $result["statut"];
  293. $this->mise_en_service = $this->db->jdate($result["datemise"]);
  294. $this->date_contrat = $this->db->jdate($result["datecontrat"]);
  295. $this->user_author_id = $result["fk_user_author"];
  296. $this->commercial_signature_id = $result["fk_commercial_signature"];
  297. $this->commercial_suivi_id = $result["fk_commercial_suivi"];
  298. $this->note = $result["note_private"]; // deprecated
  299. $this->note_private = $result["note_private"];
  300. $this->note_public = $result["note_public"];
  301. $this->fk_projet = $result["fk_projet"]; // deprecated
  302. $this->fk_project = $result["fk_projet"];
  303. $this->socid = $result["fk_soc"];
  304. $this->fk_soc = $result["fk_soc"];
  305. $this->extraparams = (array) json_decode($result["extraparams"], true);
  306. $this->db->free($resql);
  307. return $this->id;
  308. }
  309. else
  310. {
  311. dol_syslog(get_class($this)."::Fetch Erreur contrat non trouve");
  312. $this->error="Contract not found";
  313. return -2;
  314. }
  315. }
  316. else
  317. {
  318. dol_syslog(get_class($this)."::Fetch Erreur lecture contrat");
  319. $this->error=$this->db->error();
  320. return -1;
  321. }
  322. }
  323. /**
  324. * Load lignes array into this->lines
  325. *
  326. * @return Array Return array of contract lines
  327. */
  328. function fetch_lines()
  329. {
  330. $this->nbofserviceswait=0;
  331. $this->nbofservicesopened=0;
  332. $this->nbofservicesexpired=0;
  333. $this->nbofservicesclosed=0;
  334. $total_ttc=0;
  335. $total_vat=0;
  336. $total_ht=0;
  337. $now=dol_now();
  338. $this->lines=array();
  339. // Selectionne les lignes contrats liees a un produit
  340. $sql = "SELECT p.label, p.description as product_desc, p.ref,";
  341. $sql.= " d.rowid, d.fk_contrat, d.statut, d.description, d.price_ht, d.tva_tx, d.localtax1_tx, d.localtax2_tx, d.qty, d.remise_percent, d.subprice,";
  342. $sql.= " d.total_ht,";
  343. $sql.= " d.total_tva,";
  344. $sql.= " d.total_localtax1,";
  345. $sql.= " d.total_localtax2,";
  346. $sql.= " d.total_ttc,";
  347. $sql.= " d.info_bits, d.fk_product,";
  348. $sql.= " d.date_ouverture_prevue, d.date_ouverture,";
  349. $sql.= " d.date_fin_validite, d.date_cloture,";
  350. $sql.= " d.fk_user_author,";
  351. $sql.= " d.fk_user_ouverture,";
  352. $sql.= " d.fk_user_cloture";
  353. $sql.= " FROM ".MAIN_DB_PREFIX."contratdet as d, ".MAIN_DB_PREFIX."product as p";
  354. $sql.= " WHERE d.fk_contrat = ".$this->id ." AND d.fk_product = p.rowid";
  355. $sql.= " ORDER by d.rowid ASC";
  356. dol_syslog(get_class($this)."::fetch_lines sql=".$sql);
  357. $result = $this->db->query($sql);
  358. if ($result)
  359. {
  360. $num = $this->db->num_rows($result);
  361. $i = 0;
  362. while ($i < $num)
  363. {
  364. $objp = $this->db->fetch_object($result);
  365. $line = new ContratLigne($this->db);
  366. $line->id = $objp->rowid;
  367. $line->ref = $objp->rowid;
  368. $line->fk_contrat = $objp->fk_contrat;
  369. $line->desc = $objp->description; // Description ligne
  370. $line->qty = $objp->qty;
  371. $line->tva_tx = $objp->tva_tx;
  372. $line->localtax1_tx = $objp->localtax1_tx;
  373. $line->localtax2_tx = $objp->localtax2_tx;
  374. $line->subprice = $objp->subprice;
  375. $line->statut = $objp->statut;
  376. $line->remise_percent = $objp->remise_percent;
  377. $line->price_ht = $objp->price_ht;
  378. $line->price = $objp->price_ht; // For backward compatibility
  379. $line->total_ht = $objp->total_ht;
  380. $line->total_tva = $objp->total_tva;
  381. $line->total_localtax1 = $objp->total_localtax1;
  382. $line->total_localtax2 = $objp->total_localtax2;
  383. $line->total_ttc = $objp->total_ttc;
  384. $line->fk_product = $objp->fk_product;
  385. $line->info_bits = $objp->info_bits;
  386. $line->fk_user_author = $objp->fk_user_author;
  387. $line->fk_user_ouverture= $objp->fk_user_ouverture;
  388. $line->fk_user_cloture = $objp->fk_user_cloture;
  389. $line->ref = $objp->ref;
  390. $line->libelle = $objp->label; // Label produit
  391. $line->label = $objp->label; // For backward compatibility
  392. $line->product_desc = $objp->product_desc; // Description produit
  393. $line->description = $objp->description;
  394. $line->date_ouverture_prevue = $this->db->jdate($objp->date_ouverture_prevue);
  395. $line->date_ouverture = $this->db->jdate($objp->date_ouverture);
  396. $line->date_fin_validite = $this->db->jdate($objp->date_fin_validite);
  397. $line->date_cloture = $this->db->jdate($objp->date_cloture);
  398. // For backward compatibility
  399. $line->date_debut_prevue = $this->db->jdate($objp->date_ouverture_prevue);
  400. $line->date_debut_reel = $this->db->jdate($objp->date_ouverture);
  401. $line->date_fin_prevue = $this->db->jdate($objp->date_fin_validite);
  402. $line->date_fin_reel = $this->db->jdate($objp->date_cloture);
  403. $this->lines[] = $line;
  404. //dol_syslog("1 ".$line->desc);
  405. //dol_syslog("2 ".$line->product_desc);
  406. if ($line->statut == 0) $this->nbofserviceswait++;
  407. if ($line->statut == 4 && (empty($line->date_fin_prevue) || $line->date_fin_prevue >= $now)) $this->nbofservicesopened++;
  408. if ($line->statut == 4 && $line->date_fin_prevue < $now) $this->nbofservicesexpired++;
  409. if ($line->statut == 5) $this->nbofservicesclosed++;
  410. $total_ttc+=$objp->total_ttc; // TODO Not saved into database
  411. $total_vat+=$objp->total_tva;
  412. $total_ht+=$objp->total_ht;
  413. $i++;
  414. }
  415. $this->db->free($result);
  416. }
  417. else
  418. {
  419. dol_syslog(get_class($this)."::Fetch Erreur lecture des lignes de contrats liees aux produits");
  420. return -3;
  421. }
  422. // Selectionne les lignes contrat liees a aucun produit
  423. $sql = "SELECT d.rowid, d.fk_contrat, d.statut, d.qty, d.description, d.price_ht, d.tva_tx, d.localtax1_tx, d.localtax2_tx, d.rowid, d.remise_percent, d.subprice,";
  424. $sql.= " d.total_ht,";
  425. $sql.= " d.total_tva,";
  426. $sql.= " d.total_localtax1,";
  427. $sql.= " d.total_localtax2,";
  428. $sql.= " d.total_ttc,";
  429. $sql.= " d.info_bits, d.fk_product,";
  430. $sql.= " d.date_ouverture_prevue, d.date_ouverture,";
  431. $sql.= " d.date_fin_validite, d.date_cloture,";
  432. $sql.= " d.fk_user_author,";
  433. $sql.= " d.fk_user_ouverture,";
  434. $sql.= " d.fk_user_cloture";
  435. $sql.= " FROM ".MAIN_DB_PREFIX."contratdet as d";
  436. $sql.= " WHERE d.fk_contrat = ".$this->id;
  437. $sql.= " AND (d.fk_product IS NULL OR d.fk_product = 0)"; // fk_product = 0 gardee pour compatibilitee
  438. $result = $this->db->query($sql);
  439. if ($result)
  440. {
  441. $num = $this->db->num_rows($result);
  442. $i = 0;
  443. while ($i < $num)
  444. {
  445. $objp = $this->db->fetch_object($result);
  446. $line = new ContratLigne($this->db);
  447. $line->id = $objp->rowid;
  448. $line->fk_contrat = $objp->fk_contrat;
  449. $line->libelle = $objp->description;
  450. $line->desc = $objp->description;
  451. $line->qty = $objp->qty;
  452. $line->statut = $objp->statut;
  453. $line->ref = $objp->ref;
  454. $line->tva_tx = $objp->tva_tx;
  455. $line->localtax1_tx = $objp->localtax1_tx;
  456. $line->localtax2_tx = $objp->localtax2_tx;
  457. $line->subprice = $objp->subprice;
  458. $line->remise_percent = $objp->remise_percent;
  459. $line->price_ht = $objp->price_ht;
  460. $line->price = $objp->price; // For backward compatibility
  461. $line->total_ht = $objp->total_ht;
  462. $line->total_tva = $objp->total_tva;
  463. $line->total_localtax1= $objp->total_localtax1;
  464. $line->total_localtax2= $objp->total_localtax2;
  465. $line->total_ttc = $objp->total_ttc;
  466. $line->fk_product = 0;
  467. $line->info_bits = $objp->info_bits;
  468. $line->fk_user_author = $objp->fk_user_author;
  469. $line->fk_user_ouverture= $objp->fk_user_ouverture;
  470. $line->fk_user_cloture = $objp->fk_user_cloture;
  471. $line->description = $objp->description;
  472. $line->date_ouverture_prevue = $this->db->jdate($objp->date_ouverture_prevue);
  473. $line->date_ouverture = $this->db->jdate($objp->date_ouverture);
  474. $line->date_fin_validite = $this->db->jdate($objp->date_fin_validite);
  475. $line->date_cloture = $this->db->jdate($objp->date_cloture);
  476. // For backward compatibility
  477. $line->date_debut_prevue = $this->db->jdate($objp->date_ouverture_prevue);
  478. $line->date_debut_reel = $this->db->jdate($objp->date_ouverture);
  479. $line->date_fin_prevue = $this->db->jdate($objp->date_fin_validite);
  480. $line->date_fin_reel = $this->db->jdate($objp->date_cloture);
  481. if ($line->statut == 0) $this->nbofserviceswait++;
  482. if ($line->statut == 4 && (empty($line->date_fin_prevue) || $line->date_fin_prevue >= $now)) $this->nbofservicesopened++;
  483. if ($line->statut == 4 && $line->date_fin_prevue < $now) $this->nbofservicesexpired++;
  484. if ($line->statut == 5) $this->nbofservicesclosed++;
  485. $this->lines[] = $line;
  486. $total_ttc+=$objp->total_ttc;
  487. $total_vat+=$objp->total_tva;
  488. $total_ht+=$objp->total_ht;
  489. $i++;
  490. }
  491. $this->db->free($result);
  492. }
  493. else
  494. {
  495. dol_syslog(get_class($this)."::Fetch Erreur lecture des lignes de contrat non liees aux produits");
  496. $this->error=$this->db->error();
  497. return -2;
  498. }
  499. $this->nbofservices=count($this->lines);
  500. $this->total_ttc = price2num($total_ttc); // TODO For the moment value is false as value is not stored in database for line linked to products
  501. $this->total_vat = price2num($total_vat); // TODO For the moment value is false as value is not stored in database for line linked to products
  502. $this->total_ht = price2num($total_ht); // TODO For the moment value is false as value is not stored in database for line linked to products
  503. return $this->lines;
  504. }
  505. /**
  506. * Create a contract into database
  507. *
  508. * @param User $user User that create
  509. * @return int <0 if KO, id of contract if OK
  510. */
  511. function create($user)
  512. {
  513. global $conf,$langs,$mysoc;
  514. // Check parameters
  515. $paramsok=1;
  516. if ($this->commercial_signature_id <= 0)
  517. {
  518. $langs->load("commercial");
  519. $this->error.=$langs->trans("ErrorFieldRequired",$langs->trans("SalesRepresentativeSignature"));
  520. $paramsok=0;
  521. }
  522. if ($this->commercial_suivi_id <= 0)
  523. {
  524. $langs->load("commercial");
  525. $this->error.=($this->error?"<br>":'');
  526. $this->error.=$langs->trans("ErrorFieldRequired",$langs->trans("SalesRepresentativeFollowUp"));
  527. $paramsok=0;
  528. }
  529. if (! $paramsok) return -1;
  530. $this->db->begin();
  531. $now=dol_now();
  532. // Insert contract
  533. $sql = "INSERT INTO ".MAIN_DB_PREFIX."contrat (datec, fk_soc, fk_user_author, date_contrat,";
  534. $sql.= " fk_commercial_signature, fk_commercial_suivi, fk_projet,";
  535. $sql.= " ref, entity)";
  536. $sql.= " VALUES (".$this->db->idate($now).",".$this->socid.",".$user->id;
  537. $sql.= ",".$this->db->idate($this->date_contrat);
  538. $sql.= ",".($this->commercial_signature_id>0?$this->commercial_signature_id:"NULL");
  539. $sql.= ",".($this->commercial_suivi_id>0?$this->commercial_suivi_id:"NULL");
  540. $sql.= ",".($this->fk_projet>0?$this->fk_projet:"NULL");
  541. $sql.= ", ".(dol_strlen($this->ref)<=0 ? "null" : "'".$this->ref."'");
  542. $sql.= ", ".$conf->entity;
  543. $sql.= ")";
  544. $resql=$this->db->query($sql);
  545. if ($resql)
  546. {
  547. $error=0;
  548. $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."contrat");
  549. // Insert contacts commerciaux ('SALESREPSIGN','contrat')
  550. $result=$this->add_contact($this->commercial_signature_id,'SALESREPSIGN','internal');
  551. if ($result < 0) $error++;
  552. // Insert contacts commerciaux ('SALESREPFOLL','contrat')
  553. $result=$this->add_contact($this->commercial_suivi_id,'SALESREPFOLL','internal');
  554. if ($result < 0) $error++;
  555. if (! $error)
  556. {
  557. // Appel des triggers
  558. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  559. $interface=new Interfaces($this->db);
  560. $result=$interface->run_triggers('CONTRACT_CREATE',$this,$user,$langs,$conf);
  561. if ($result < 0) { $error++; $this->errors=$interface->errors; }
  562. // Fin appel triggers
  563. if (! $error)
  564. {
  565. $this->db->commit();
  566. return $this->id;
  567. }
  568. else
  569. {
  570. $this->error=$interface->error;
  571. dol_syslog(get_class($this)."::create - 30 - ".$this->error, LOG_ERR);
  572. $this->db->rollback();
  573. return -3;
  574. }
  575. }
  576. else
  577. {
  578. $this->error="Failed to add contact";
  579. dol_syslog(get_class($this)."::create - 20 - ".$this->error, LOG_ERR);
  580. $this->db->rollback();
  581. return -2;
  582. }
  583. }
  584. else
  585. {
  586. $this->error=$langs->trans("UnknownError: ".$this->db->error()." - sql=".$sql);
  587. dol_syslog(get_class($this)."::create - 10 - ".$this->error, LOG_ERR);
  588. $this->db->rollback();
  589. return -1;
  590. }
  591. }
  592. /**
  593. * Supprime l'objet de la base
  594. *
  595. * @param User $user Utilisateur qui supprime
  596. * @return int < 0 si erreur, > 0 si ok
  597. */
  598. function delete($user)
  599. {
  600. global $conf, $langs;
  601. $error=0;
  602. $this->db->begin();
  603. if (! $error)
  604. {
  605. // Delete linked contacts
  606. $res = $this->delete_linked_contact();
  607. if ($res < 0)
  608. {
  609. dol_syslog(get_class($this)."::delete error", LOG_ERR);
  610. $error++;
  611. }
  612. }
  613. if (! $error)
  614. {
  615. // Delete contratdet_log
  616. /*
  617. $sql = "DELETE cdl";
  618. $sql.= " FROM ".MAIN_DB_PREFIX."contratdet_log as cdl, ".MAIN_DB_PREFIX."contratdet as cd";
  619. $sql.= " WHERE cdl.fk_contratdet=cd.rowid AND cd.fk_contrat=".$this->id;
  620. */
  621. $sql = "SELECT cdl.rowid as cdlrowid ";
  622. $sql.= " FROM ".MAIN_DB_PREFIX."contratdet_log as cdl, ".MAIN_DB_PREFIX."contratdet as cd";
  623. $sql.= " WHERE cdl.fk_contratdet=cd.rowid AND cd.fk_contrat=".$this->id;
  624. dol_syslog(get_class($this)."::delete contratdet_log sql=".$sql, LOG_DEBUG);
  625. $resql=$this->db->query($sql);
  626. if (! $resql)
  627. {
  628. $this->error=$this->db->error();
  629. $error++;
  630. }
  631. $numressql=$this->db->num_rows($resql);
  632. if (! $error && $numressql )
  633. {
  634. $tab_resql=array();
  635. for($i=0;$i<$numressql;$i++)
  636. {
  637. $objresql=$this->db->fetch_object($resql);
  638. $tab_resql[]= $objresql->cdlrowid;
  639. }
  640. $this->db->free($resql);
  641. $sql= "DELETE FROM ".MAIN_DB_PREFIX."contratdet_log ";
  642. $sql.= " WHERE ".MAIN_DB_PREFIX."contratdet_log.rowid IN (".implode(",",$tab_resql).")";
  643. dol_syslog(get_class($this)."::delete contratdet_log sql=".$sql, LOG_DEBUG);
  644. $resql=$this->db->query($sql);
  645. if (! $resql)
  646. {
  647. $this->error=$this->db->error();
  648. $error++;
  649. }
  650. }
  651. }
  652. if (! $error)
  653. {
  654. // Delete contratdet
  655. $sql = "DELETE FROM ".MAIN_DB_PREFIX."contratdet";
  656. $sql.= " WHERE fk_contrat=".$this->id;
  657. dol_syslog(get_class($this)."::delete contratdet sql=".$sql, LOG_DEBUG);
  658. $resql=$this->db->query($sql);
  659. if (! $resql)
  660. {
  661. $this->error=$this->db->error();
  662. $error++;
  663. }
  664. }
  665. if (! $error)
  666. {
  667. // Delete contrat
  668. $sql = "DELETE FROM ".MAIN_DB_PREFIX."contrat";
  669. $sql.= " WHERE rowid=".$this->id;
  670. dol_syslog(get_class($this)."::delete contrat sql=".$sql);
  671. $resql=$this->db->query($sql);
  672. if (! $resql)
  673. {
  674. $this->error=$this->db->error();
  675. $error++;
  676. }
  677. }
  678. if (! $error)
  679. {
  680. // Appel des triggers
  681. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  682. $interface=new Interfaces($this->db);
  683. $result=$interface->run_triggers('CONTRACT_DELETE',$this,$user,$langs,$conf);
  684. if ($result < 0) {
  685. $error++; $this->errors=$interface->errors;
  686. }
  687. // Fin appel triggers
  688. }
  689. if (! $error)
  690. {
  691. // We remove directory
  692. $ref = dol_sanitizeFileName($this->ref);
  693. if ($conf->contrat->dir_output)
  694. {
  695. $dir = $conf->contrat->dir_output . "/" . $ref;
  696. if (file_exists($dir))
  697. {
  698. $res=@dol_delete_dir_recursive($dir);
  699. if (! $res)
  700. {
  701. $this->error='ErrorFailToDeleteDir';
  702. $error++;
  703. }
  704. }
  705. }
  706. }
  707. if (! $error)
  708. {
  709. $this->db->commit();
  710. return 1;
  711. }
  712. else
  713. {
  714. $this->error=$this->db->error();
  715. dol_syslog(get_class($this)."::delete ERROR ".$this->error, LOG_ERR);
  716. $this->db->rollback();
  717. return -1;
  718. }
  719. }
  720. /**
  721. * Ajoute une ligne de contrat en base
  722. *
  723. * @param string $desc Description de la ligne
  724. * @param float $pu_ht Prix unitaire HT
  725. * @param int $qty Quantite
  726. * @param float $txtva Taux tva
  727. * @param float $txlocaltax1 Local tax 1 rate
  728. * @param float $txlocaltax2 Local tax 2 rate
  729. * @param int $fk_product Id produit
  730. * @param float $remise_percent Pourcentage de remise de la ligne
  731. * @param timestamp $date_start Date de debut prevue
  732. * @param timestamp $date_end Date de fin prevue
  733. * @param float $price_base_type HT or TTC
  734. * @param float $pu_ttc Prix unitaire TTC
  735. * @param int $info_bits Bits de type de lignes
  736. * @return int <0 si erreur, >0 si ok
  737. */
  738. function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1, $txlocaltax2, $fk_product, $remise_percent, $date_start, $date_end, $price_base_type='HT', $pu_ttc=0, $info_bits=0)
  739. {
  740. global $user, $langs, $conf;
  741. dol_syslog(get_class($this)."::addline $desc, $pu_ht, $qty, $txtva, $txlocaltax1, $txlocaltax2, $fk_product, $remise_percent, $date_start, $date_end, $price_base_type, $pu_ttc, $info_bits");
  742. if ($this->statut >= 0)
  743. {
  744. $this->db->begin();
  745. // Clean parameters
  746. $remise_percent=price2num($remise_percent);
  747. $qty=price2num($qty);
  748. if (! $qty) $qty=1;
  749. if (! $info_bits) $info_bits=0;
  750. if (! $pu_ht) $pu_ht=0;
  751. if (! $pu_ttc) $pu_ttc=0;
  752. $pu_ht=price2num($pu_ht);
  753. $pu_ttc=price2num($pu_ttc);
  754. $txtva=price2num($txtva);
  755. $txlocaltax1=price2num($txlocaltax1);
  756. $txlocaltax2=price2num($txlocaltax2);
  757. if ($price_base_type=='HT')
  758. {
  759. $pu=$pu_ht;
  760. }
  761. else
  762. {
  763. $pu=$pu_ttc;
  764. }
  765. // Calcul du total TTC et de la TVA pour la ligne a partir de
  766. // qty, pu, remise_percent et txtva
  767. // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
  768. // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
  769. $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits);
  770. $total_ht = $tabprice[0];
  771. $total_tva = $tabprice[1];
  772. $total_ttc = $tabprice[2];
  773. $total_localtax1= $tabprice[9];
  774. $total_localtax2= $tabprice[10];
  775. // TODO A virer
  776. // Anciens indicateurs: $price, $remise (a ne plus utiliser)
  777. $remise = 0;
  778. $price = price2num(round($pu_ht, 2));
  779. if (dol_strlen($remise_percent) > 0)
  780. {
  781. $remise = round(($pu_ht * $remise_percent / 100), 2);
  782. $price = $pu_ht - $remise;
  783. }
  784. // Insertion dans la base
  785. $sql = "INSERT INTO ".MAIN_DB_PREFIX."contratdet";
  786. $sql.= " (fk_contrat, label, description, fk_product, qty, tva_tx,";
  787. $sql.= " localtax1_tx, localtax2_tx, remise_percent, subprice,";
  788. $sql.= " total_ht, total_tva, total_localtax1, total_localtax2, total_ttc,";
  789. $sql.= " info_bits,";
  790. $sql.= " price_ht, remise"; // TODO A virer
  791. if ($date_start > 0) { $sql.= ",date_ouverture_prevue"; }
  792. if ($date_end > 0) { $sql.= ",date_fin_validite"; }
  793. $sql.= ") VALUES ($this->id, '', '" . $this->db->escape($desc) . "',";
  794. $sql.= ($fk_product>0 ? $fk_product : "null").",";
  795. $sql.= " '".$qty."',";
  796. $sql.= " '".$txtva."',";
  797. $sql.= " '".$txlocaltax1."',";
  798. $sql.= " '".$txlocaltax2."',";
  799. $sql.= " ".price2num($remise_percent).",".price2num($pu_ht).",";
  800. $sql.= " ".price2num($total_ht).",".price2num($total_tva).",".price2num($total_localtax1).",".price2num($total_localtax2).",".price2num($total_ttc).",";
  801. $sql.= " '".$info_bits."',";
  802. $sql.= " ".price2num($price).",".price2num($remise); // TODO A virer
  803. if ($date_start > 0) { $sql.= ",'".$this->db->idate($date_start)."'"; }
  804. if ($date_end > 0) { $sql.= ",'".$this->db->idate($date_end)."'"; }
  805. $sql.= ")";
  806. dol_syslog(get_class($this)."::addline sql=".$sql);
  807. $resql=$this->db->query($sql);
  808. if ($resql)
  809. {
  810. $result=$this->update_statut($user);
  811. if ($result > 0)
  812. {
  813. $this->db->commit();
  814. return 1;
  815. }
  816. else
  817. {
  818. dol_syslog("Error sql=$sql, error=".$this->error,LOG_ERR);
  819. $this->db->rollback();
  820. return -1;
  821. }
  822. }
  823. else
  824. {
  825. $this->db->rollback();
  826. $this->error=$this->db->error()." sql=".$sql;
  827. dol_syslog(get_class($this)."::addline ".$this->error,LOG_ERR);
  828. return -1;
  829. }
  830. }
  831. else
  832. {
  833. dol_syslog(get_class($this)."::addline ErrorTryToAddLineOnValidatedContract", LOG_ERR);
  834. return -2;
  835. }
  836. }
  837. /**
  838. * Mets a jour une ligne de contrat
  839. *
  840. * @param int $rowid Id de la ligne de facture
  841. * @param string $desc Description de la ligne
  842. * @param float $pu Prix unitaire
  843. * @param int $qty Quantite
  844. * @param float $remise_percent Pourcentage de remise de la ligne
  845. * @param timestamp $date_start Date de debut prevue
  846. * @param timestamp $date_end Date de fin prevue
  847. * @param float $tvatx Taux TVA
  848. * @param float $localtax1tx Local tax 1 rate
  849. * @param float $localtax2tx Local tax 2 rate
  850. * @param timestamp $date_debut_reel Date de debut reelle
  851. * @param timestamp $date_fin_reel Date de fin reelle
  852. * @param float $price_base_type HT or TTC
  853. * @param int $info_bits Bits de type de lignes
  854. * @return int < 0 si erreur, > 0 si ok
  855. */
  856. function updateline($rowid, $desc, $pu, $qty, $remise_percent, $date_start, $date_end, $tvatx, $localtax1tx=0, $localtax2tx=0, $date_debut_reel='', $date_fin_reel='', $price_base_type='HT', $info_bits=0)
  857. {
  858. global $user, $conf, $langs;
  859. // Nettoyage parametres
  860. $qty=trim($qty);
  861. $desc=trim($desc);
  862. $desc=trim($desc);
  863. $price = price2num($pu);
  864. $tvatx = price2num($tvatx);
  865. $localtax1tx = price2num($localtax1tx);
  866. $localtax2tx = price2num($localtax2tx);
  867. $subprice = $price;
  868. $remise = 0;
  869. if (dol_strlen($remise_percent) > 0)
  870. {
  871. $remise = round(($pu * $remise_percent / 100), 2);
  872. $price = $pu - $remise;
  873. }
  874. else
  875. {
  876. $remise_percent=0;
  877. }
  878. dol_syslog(get_class($this)."::updateline $rowid, $desc, $pu, $qty, $remise_percent, $date_start, $date_end, $date_debut_reel, $date_fin_reel, $tvatx, $localtax1tx, $localtax2tx, $price_base_type, $info_bits");
  879. $this->db->begin();
  880. // Calcul du total TTC et de la TVA pour la ligne a partir de
  881. // qty, pu, remise_percent et txtva
  882. // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
  883. // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
  884. $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $localtaxtx1, $txlocaltaxtx2, 0, $price_base_type, $info_bits);
  885. $total_ht = $tabprice[0];
  886. $total_tva = $tabprice[1];
  887. $total_ttc = $tabprice[2];
  888. $total_localtax1= $tabprice[9];
  889. $total_localtax2= $tabprice[10];
  890. // TODO A virer
  891. // Anciens indicateurs: $price, $remise (a ne plus utiliser)
  892. $remise = 0;
  893. $price = price2num(round($pu_ht, 2));
  894. if (dol_strlen($remise_percent) > 0)
  895. {
  896. $remise = round(($pu_ht * $remise_percent / 100), 2);
  897. $price = $pu_ht - $remise;
  898. }
  899. $sql = "UPDATE ".MAIN_DB_PREFIX."contratdet set description='".$this->db->escape($desc)."'";
  900. $sql.= ",price_ht='" . price2num($price)."'";
  901. $sql.= ",subprice='" . price2num($subprice)."'";
  902. $sql.= ",remise='" . price2num($remise)."'";
  903. $sql.= ",remise_percent='".price2num($remise_percent)."'";
  904. $sql.= ",qty='".$qty."'";
  905. $sql.= ",tva_tx='". price2num($tvatx)."'";
  906. $sql.= ",localtax1_tx='". price2num($localtax1tx)."'";
  907. $sql.= ",localtax2_tx='". price2num($localtax2tx)."'";
  908. $sql.= ", total_ht='". price2num($total_ht)."'";
  909. $sql.= ", total_tva='". price2num($total_tva)."'";
  910. $sql.= ", total_localtax1='".price2num($total_localtax1)."'";
  911. $sql.= ", total_localtax2='".price2num($total_localtax2)."'";
  912. $sql.= ", total_ttc='". price2num($total_ttc)."'";
  913. if ($date_start > 0) { $sql.= ",date_ouverture_prevue='".$this->db->idate($date_start)."'"; }
  914. else { $sql.=",date_ouverture_prevue=null"; }
  915. if ($date_end > 0) { $sql.= ",date_fin_validite='".$this->db->idate($date_end)."'"; }
  916. else { $sql.=",date_fin_validite=null"; }
  917. if ($date_debut_reel > 0) { $sql.= ",date_ouverture='".$this->db->idate($date_debut_reel)."'"; }
  918. else { $sql.=",date_ouverture=null"; }
  919. if ($date_fin_reel > 0) { $sql.= ",date_cloture='".$this->db->idate($date_fin_reel)."'"; }
  920. else { $sql.=",date_cloture=null"; }
  921. $sql .= " WHERE rowid = ".$rowid;
  922. dol_syslog(get_class($this)."::updateline sql=".$sql);
  923. $result = $this->db->query($sql);
  924. if ($result)
  925. {
  926. $result=$this->update_statut($user);
  927. if ($result >= 0)
  928. {
  929. $this->db->commit();
  930. return 1;
  931. }
  932. else
  933. {
  934. $this->db->rollback();
  935. dol_syslog(get_class($this)."::updateligne Erreur -2");
  936. return -2;
  937. }
  938. }
  939. else
  940. {
  941. $this->db->rollback();
  942. $this->error=$this->db->error();
  943. dol_syslog(get_class($this)."::updateligne Erreur -1");
  944. return -1;
  945. }
  946. }
  947. /**
  948. * Delete a contract line
  949. *
  950. * @param int $idline Id of line to delete
  951. * @param User $user User that delete
  952. * @return int >0 if OK, <0 if KO
  953. */
  954. function deleteline($idline,$user)
  955. {
  956. global $conf, $langs;
  957. $error=0;
  958. if ($this->statut >= 0)
  959. {
  960. $sql = "DELETE FROM ".MAIN_DB_PREFIX."contratdet";
  961. $sql.= " WHERE rowid=".$idline;
  962. dol_syslog(get_class($this)."::delete sql=".$sql);
  963. $resql = $this->db->query($sql);
  964. if (! $resql)
  965. {
  966. $this->error="Error ".$this->db->lasterror();
  967. dol_syslog(get_class($this)."::delete ".$this->error, LOG_ERR);
  968. return -1;
  969. }
  970. // Appel des triggers
  971. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  972. $interface=new Interfaces($this->db);
  973. $result=$interface->run_triggers('CONTRACTLINE_DELETE',$this,$user,$langs,$conf);
  974. if ($result < 0) { $error++; $this->errors=$interface->errors; }
  975. // Fin appel triggers
  976. return 1;
  977. }
  978. else
  979. {
  980. return -2;
  981. }
  982. }
  983. /**
  984. * Update statut of contract according to services
  985. *
  986. * @param User $user Object user
  987. * @return int <0 if KO, >0 if OK
  988. */
  989. function update_statut($user)
  990. {
  991. // If draft, we keep it (should not happen)
  992. if ($this->statut == 0) return 1;
  993. // Load $this->lines array
  994. // $this->fetch_lines();
  995. $newstatut=1;
  996. foreach($this->lines as $key => $contractline)
  997. {
  998. // if ($contractline) // Loop on each service
  999. }
  1000. return 1;
  1001. }
  1002. /**
  1003. * Return label of a contract status
  1004. *
  1005. * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Long label of all services, 5=Libelle court + Picto, 6=Picto of all services
  1006. * @return string Label
  1007. */
  1008. function getLibStatut($mode)
  1009. {
  1010. return $this->LibStatut($this->statut,$mode);
  1011. }
  1012. /**
  1013. * Renvoi label of a given contrat status
  1014. *
  1015. * @param int $statut Status id
  1016. * @param int $mode 0=Long label, 1=Short label, 2=Picto + Libelle court, 3=Picto, 4=Picto + Long label of all services, 5=Libelle court + Picto, 6=Picto of all services
  1017. * @return string Label
  1018. */
  1019. function LibStatut($statut,$mode)
  1020. {
  1021. global $langs;
  1022. $langs->load("contracts");
  1023. if ($mode == 0)
  1024. {
  1025. if ($statut == 0) { return $langs->trans("ContractStatusDraft"); }
  1026. if ($statut == 1) { return $langs->trans("ContractStatusValidated"); }
  1027. if ($statut == 2) { return $langs->trans("ContractStatusClosed"); }
  1028. }
  1029. if ($mode == 1)
  1030. {
  1031. if ($statut == 0) { return $langs->trans("ContractStatusDraft"); }
  1032. if ($statut == 1) { return $langs->trans("ContractStatusValidated"); }
  1033. if ($statut == 2) { return $langs->trans("ContractStatusClosed"); }
  1034. }
  1035. if ($mode == 2)
  1036. {
  1037. if ($statut == 0) { return img_picto($langs->trans('ContractStatusDraft'),'statut0').' '.$langs->trans("ContractStatusDraft"); }
  1038. if ($statut == 1) { return img_picto($langs->trans('ContractStatusValidated'),'statut4').' '.$langs->trans("ContractStatusValidated"); }
  1039. if ($statut == 2) { return img_picto($langs->trans('ContractStatusClosed'),'statut6').' '.$langs->trans("ContractStatusClosed"); }
  1040. }
  1041. if ($mode == 3)
  1042. {
  1043. if ($statut == 0) { return img_picto($langs->trans('ContractStatusDraft'),'statut0'); }
  1044. if ($statut == 1) { return img_picto($langs->trans('ContractStatusValidated'),'statut4'); }
  1045. if ($statut == 2) { return img_picto($langs->trans('ContractStatusClosed'),'statut6'); }
  1046. }
  1047. if ($mode == 4 || $mode == 6)
  1048. {
  1049. $line=new ContratLigne($this->db);
  1050. $text='';
  1051. if ($mode == 4)
  1052. {
  1053. $text=($this->nbofserviceswait+$this->nbofservicesopened+$this->nbofservicesexpired+$this->nbofservicesclosed);
  1054. $text.=' '.$langs->trans("Services");
  1055. $text.=': &nbsp; &nbsp; ';
  1056. }
  1057. $text.=$this->nbofserviceswait.' '.$line->LibStatut(0,3).' &nbsp; ';
  1058. $text.=$this->nbofservicesopened.' '.$line->LibStatut(4,3,0).' &nbsp; ';
  1059. $text.=$this->nbofservicesexpired.' '.$line->LibStatut(4,3,1).' &nbsp; ';
  1060. $text.=$this->nbofservicesclosed.' '.$line->LibStatut(5,3);
  1061. return $text;
  1062. }
  1063. if ($mode == 5)
  1064. {
  1065. if ($statut == 0) { return $langs->trans("ContractStatusDraft").' '.img_picto($langs->trans('ContractStatusDraft'),'statut0'); }
  1066. if ($statut == 1) { return $langs->trans("ContractStatusValidated").' '.img_picto($langs->trans('ContractStatusValidated'),'statut4'); }
  1067. if ($statut == 2) { return $langs->trans("ContractStatusClosed").' '.img_picto($langs->trans('ContractStatusClosed'),'statut6'); }
  1068. }
  1069. }
  1070. /**
  1071. * Renvoie nom clicable (avec eventuellement le picto)
  1072. *
  1073. * @param int $withpicto 0=Pas de picto, 1=Inclut le picto dans le lien, 2=Picto seul
  1074. * @param int $maxlength Max length of ref
  1075. * @return string Chaine avec URL
  1076. */
  1077. function getNomUrl($withpicto=0,$maxlength=0)
  1078. {
  1079. global $langs;
  1080. $result='';
  1081. $lien = '<a href="'.DOL_URL_ROOT.'/contrat/fiche.php?id='.$this->id.'">';
  1082. $lienfin='</a>';
  1083. $picto='contract';
  1084. $label=$langs->trans("ShowContract").': '.$this->ref;
  1085. if ($withpicto) $result.=($lien.img_object($label,$picto).$lienfin);
  1086. if ($withpicto && $withpicto != 2) $result.=' ';
  1087. if ($withpicto != 2) $result.=$lien.($maxlength?dol_trunc($this->ref,$maxlength):$this->ref).$lienfin;
  1088. return $result;
  1089. }
  1090. /**
  1091. * Charge les informations d'ordre info dans l'objet contrat
  1092. *
  1093. * @param int $id id du contrat a charger
  1094. * @return void
  1095. */
  1096. function info($id)
  1097. {
  1098. $sql = "SELECT c.rowid, c.ref, c.datec, c.date_cloture,";
  1099. $sql.= " c.tms as date_modification,";
  1100. $sql.= " fk_user_author, fk_user_cloture";
  1101. $sql.= " FROM ".MAIN_DB_PREFIX."contrat as c";
  1102. $sql.= " WHERE c.rowid = ".$id;
  1103. $result=$this->db->query($sql);
  1104. if ($result)
  1105. {
  1106. if ($this->db->num_rows($result))
  1107. {
  1108. $obj = $this->db->fetch_object($result);
  1109. $this->id = $obj->rowid;
  1110. if ($obj->fk_user_author) {
  1111. $cuser = new User($this->db);
  1112. $cuser->fetch($obj->fk_user_author);
  1113. $this->user_creation = $cuser;
  1114. }
  1115. if ($obj->fk_user_cloture) {
  1116. $cuser = new User($this->db);
  1117. $cuser->fetch($obj->fk_user_cloture);
  1118. $this->user_cloture = $cuser;
  1119. }
  1120. $this->ref = (! $obj->ref) ? $obj->rowid : $obj->ref;
  1121. $this->date_creation = $this->db->jdate($obj->datec);
  1122. $this->date_modification = $this->db->jdate($obj->date_modification);
  1123. $this->date_cloture = $this->db->jdate($obj->date_cloture);
  1124. }
  1125. $this->db->free($result);
  1126. }
  1127. else
  1128. {
  1129. dol_print_error($this->db);
  1130. }
  1131. }
  1132. /**
  1133. * Return list of line rowid
  1134. *
  1135. * @param int $statut Status of lines to get
  1136. * @return array Array of line's rowid
  1137. */
  1138. function array_detail($statut=-1)
  1139. {
  1140. $tab=array();
  1141. $sql = "SELECT cd.rowid";
  1142. $sql.= " FROM ".MAIN_DB_PREFIX."contratdet as cd";
  1143. $sql.= " WHERE fk_contrat =".$this->id;
  1144. if ($statut >= 0) $sql.= " AND statut = '$statut'";
  1145. dol_syslog(get_class($this)."::array_detail() sql=".$sql,LOG_DEBUG);
  1146. $resql=$this->db->query($sql);
  1147. if ($resql)
  1148. {
  1149. $num=$this->db->num_rows($resql);
  1150. $i=0;
  1151. while ($i < $num)
  1152. {
  1153. $obj = $this->db->fetch_object($resql);
  1154. $tab[$i]=$obj->rowid;
  1155. $i++;
  1156. }
  1157. return $tab;
  1158. }
  1159. else
  1160. {
  1161. $this->error=$this->db->error();
  1162. return -1;
  1163. }
  1164. }
  1165. /**
  1166. * Return list of other contracts for same company than current contract
  1167. *
  1168. * @param string $option 'all' or 'others'
  1169. * @return array Array of contracts id
  1170. */
  1171. function getListOfContracts($option='all')
  1172. {
  1173. $tab=array();
  1174. $sql = "SELECT c.rowid, c.ref";
  1175. $sql.= " FROM ".MAIN_DB_PREFIX."contrat as c";
  1176. $sql.= " WHERE fk_soc =".$this->socid;
  1177. if ($option == 'others') $sql.= " AND c.rowid != ".$this->id;
  1178. dol_syslog(get_class($this)."::getOtherContracts() sql=".$sql,LOG_DEBUG);
  1179. $resql=$this->db->query($sql);
  1180. if ($resql)
  1181. {
  1182. $num=$this->db->num_rows($resql);
  1183. $i=0;
  1184. while ($i < $num)
  1185. {
  1186. $obj = $this->db->fetch_object($resql);
  1187. $contrat=new Contrat($this->db);
  1188. $contrat->fetch($obj->rowid);
  1189. $tab[]=$contrat;
  1190. $i++;
  1191. }
  1192. return $tab;
  1193. }
  1194. else
  1195. {
  1196. $this->error=$this->db->error();
  1197. return -1;
  1198. }
  1199. }
  1200. /**
  1201. * Load indicators for dashboard (this->nbtodo and this->nbtodolate)
  1202. *
  1203. * @param User $user Objet user
  1204. * @param string $mode "inactive" pour services a activer, "expired" pour services expires
  1205. * @return int <0 if KO, >0 if OK
  1206. */
  1207. function load_board($user,$mode)
  1208. {
  1209. global $conf, $user;
  1210. $now=dol_now();
  1211. $this->nbtodo=$this->nbtodolate=0;
  1212. $this->from = " FROM ".MAIN_DB_PREFIX."contrat as c";
  1213. $this->from.= ", ".MAIN_DB_PREFIX."contratdet as cd";
  1214. $this->from.= ", ".MAIN_DB_PREFIX."societe as s";
  1215. if (!$user->rights->societe->client->voir && !$user->societe_id) $this->from.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
  1216. if ($mode == 'inactives')
  1217. {
  1218. $sql = "SELECT cd.rowid, cd.date_ouverture_prevue as datefin";
  1219. $sql.= $this->from;
  1220. $sql.= " WHERE c.statut = 1";
  1221. $sql.= " AND c.rowid = cd.fk_contrat";
  1222. $sql.= " AND cd.statut = 0";
  1223. }
  1224. if ($mode == 'expired')
  1225. {
  1226. $sql = "SELECT cd.rowid, cd.date_fin_validite as datefin";
  1227. $sql.= $this->from;
  1228. $sql.= " WHERE c.statut = 1";
  1229. $sql.= " AND c.rowid = cd.fk_contrat";
  1230. $sql.= " AND cd.statut = 4";
  1231. $sql.= " AND cd.date_fin_validite < '".$this->db->idate(time())."'";
  1232. }
  1233. $sql.= " AND c.fk_soc = s.rowid";
  1234. $sql.= " AND c.entity = ".$conf->entity;
  1235. if ($user->societe_id) $sql.=" AND c.fk_soc = ".$user->societe_id;
  1236. if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " AND c.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id;
  1237. $resql=$this->db->query($sql);
  1238. if ($resql)
  1239. {
  1240. while ($obj=$this->db->fetch_object($resql))
  1241. {
  1242. $this->nbtodo++;
  1243. if ($mode == 'inactives')
  1244. if ($obj->datefin && $this->db->jdate($obj->datefin) < ($now - $conf->contrat->services->inactifs->warning_delay)) $this->nbtodolate++;
  1245. if ($mode == 'expired')
  1246. if ($obj->datefin && $this->db->jdate($obj->datefin) < ($now - $conf->contrat->services->expires->warning_delay)) $this->nbtodolate++;
  1247. }
  1248. return 1;
  1249. }
  1250. else
  1251. {
  1252. dol_print_error($this->db);
  1253. $this->error=$this->db->error();
  1254. return -1;
  1255. }
  1256. }
  1257. /**
  1258. * Charge indicateurs this->nb de tableau de bord
  1259. *
  1260. * @return int <0 si ko, >0 si ok
  1261. */
  1262. function load_state_board()
  1263. {
  1264. global $conf, $user;
  1265. $this->nb=array();
  1266. $clause = "WHERE";
  1267. $sql = "SELECT count(c.rowid) as nb";
  1268. $sql.= " FROM ".MAIN_DB_PREFIX."contrat as c";
  1269. $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON c.fk_soc = s.rowid";
  1270. if (!$user->rights->contrat->activer && !$user->societe_id)
  1271. {
  1272. $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON s.rowid = sc.fk_soc";
  1273. $sql.= " WHERE sc.fk_user = " .$user->id;
  1274. $clause = "AND";
  1275. }
  1276. $sql.= " ".$clause." c.entity = ".$conf->entity;
  1277. $resql=$this->db->query($sql);
  1278. if ($resql)
  1279. {
  1280. while ($obj=$this->db->fetch_object($resql))
  1281. {
  1282. $this->nb["Contracts"]=$obj->nb;
  1283. }
  1284. return 1;
  1285. }
  1286. else
  1287. {
  1288. dol_print_error($this->db);
  1289. $this->error=$this->db->error();
  1290. return -1;
  1291. }
  1292. }
  1293. /* gestion des contacts d'un contrat */
  1294. /**
  1295. * Return id des contacts clients de facturation
  1296. *
  1297. * @return array Liste des id contacts facturation
  1298. */
  1299. function getIdBillingContact()
  1300. {
  1301. return $this->getIdContact('external','BILLING');
  1302. }
  1303. /**
  1304. * Return id des contacts clients de prestation
  1305. *
  1306. * @return array Liste des id contacts prestation
  1307. */
  1308. function getIdServiceContact()
  1309. {
  1310. return $this->getIdContact('external','SERVICE');
  1311. }
  1312. /**
  1313. * Initialise an instance with random values.
  1314. * Used to build previews or test instances.
  1315. * id must be 0 if object instance is a specimen.
  1316. *
  1317. * @return void
  1318. */
  1319. function initAsSpecimen()
  1320. {
  1321. global $user,$langs,$conf;
  1322. $prodids = array();
  1323. $sql = "SELECT rowid";
  1324. $sql.= " FROM ".MAIN_DB_PREFIX."product";
  1325. $sql.= " WHERE entity IN (".getEntity('product', 1).")";
  1326. $sql.= " AND tosell = 1";
  1327. $resql = $this->db->query($sql);
  1328. if ($resql)
  1329. {
  1330. $num_prods = $this->db->num_rows($resql);
  1331. $i = 0;
  1332. while ($i < $num_prods)
  1333. {
  1334. $i++;
  1335. $row = $this->db->fetch_row($resql);
  1336. $prodids[$i] = $row[0];
  1337. }
  1338. }
  1339. // Initialise parametres
  1340. $this->id=0;
  1341. $this->specimen=1;
  1342. $this->ref = 'DOLIBARR';
  1343. $this->socid = 1;
  1344. $this->statut= 0;
  1345. $this->date_contrat = dol_now();
  1346. $this->commercial_signature_id = 1;
  1347. $this->commercial_suivi_id = 1;
  1348. $this->note='This is a comment (private)';
  1349. $this->note='This is a comment (public)';
  1350. $this->fk_projet = 0;
  1351. // Lines
  1352. $nbp = 5;
  1353. $xnbp = 0;
  1354. while ($xnbp < $nbp)
  1355. {
  1356. $line=new ContratLigne($this->db);
  1357. $line->desc=$langs->trans("Description")." ".$xnbp;
  1358. $line->qty=1;
  1359. $line->subprice=100;
  1360. $line->price=100;
  1361. $line->tva_tx=19.6;
  1362. $line->remise_percent=10;
  1363. $line->total_ht=90;
  1364. $line->total_ttc=107.64; // 90 * 1.196
  1365. $line->total_tva=17.64;
  1366. $prodid = rand(1, $num_prods);
  1367. $line->fk_product=$prodids[$prodid];
  1368. $this->lines[$xnbp]=$line;
  1369. $xnbp++;
  1370. }
  1371. $this->amount_ht = $xnbp*100;
  1372. $this->total_ht = $xnbp*100;
  1373. $this->total_tva = $xnbp*19.6;
  1374. $this->total_ttc = $xnbp*119.6;
  1375. }
  1376. }
  1377. /**
  1378. * Classe permettant la gestion des lignes de contrats
  1379. */
  1380. class ContratLigne
  1381. {
  1382. var $db; //!< To store db handler
  1383. var $error; //!< To return error code (or message)
  1384. var $errors=array(); //!< To return several error codes (or messages)
  1385. //var $element='contratdet'; //!< Id that identify managed objects
  1386. //var $table_element='contratdet'; //!< Name of table without prefix where object is stored
  1387. var $id;
  1388. var $ref;
  1389. var $tms;
  1390. var $fk_contrat;
  1391. var $fk_product;
  1392. var $statut; // 0 inactive, 4 active, 5 closed
  1393. var $label;
  1394. var $description;
  1395. var $date_commande;
  1396. var $date_ouverture_prevue; // date start planned
  1397. var $date_ouverture; // date start real
  1398. var $date_fin_validite; // date end planned
  1399. var $date_cloture; // date end real
  1400. var $tva_tx;
  1401. var $localtax1_tx;
  1402. var $localtax2_tx;
  1403. var $qty;
  1404. var $remise_percent;
  1405. var $remise;
  1406. var $fk_remise_except;
  1407. var $subprice; // Unit price HT
  1408. var $price_ht;
  1409. var $total_ht;
  1410. var $total_tva;
  1411. var $total_localtax1;
  1412. var $total_localtax2;
  1413. var $total_ttc;
  1414. var $info_bits;
  1415. var $fk_user_author;
  1416. var $fk_user_ouverture;
  1417. var $fk_user_cloture;
  1418. var $commentaire;
  1419. /**
  1420. * Constructor
  1421. *
  1422. * @param DoliDb $db Database handler
  1423. */
  1424. function __construct($db = '')
  1425. {
  1426. $this->db = $db;
  1427. }
  1428. /**
  1429. * Return label of this contract line status
  1430. *
  1431. * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
  1432. * @return string Libelle
  1433. */
  1434. function getLibStatut($mode)
  1435. {
  1436. return $this->LibStatut($this->statut,$mode,(isset($this->date_fin_validite)?($this->date_fin_validite < dol_now()?1:0):-1));
  1437. }
  1438. /**
  1439. * Return label of a contract line status
  1440. *
  1441. * @param int $statut Id statut
  1442. * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
  1443. * @param int $expired 0=Not expired, 1=Expired, -1=Both or unknown
  1444. * @return string Libelle
  1445. */
  1446. function LibStatut($statut,$mode,$expired=-1)
  1447. {
  1448. global $langs;
  1449. $langs->load("contracts");
  1450. if ($mode == 0)
  1451. {
  1452. if ($statut == 0) { return $langs->trans("ServiceStatusInitial"); }
  1453. if ($statut == 4 && $expired == -1) { return $langs->trans("ServiceStatusRunning"); }
  1454. if ($statut == 4 && $expired == 0) { return $langs->trans("ServiceStatusNotLate"); }
  1455. if ($statut == 4 && $expired == 1) { return $langs->trans("ServiceStatusLate"); }
  1456. if ($statut == 5) { return $langs->trans("ServiceStatusClosed"); }
  1457. }
  1458. if ($mode == 1)
  1459. {
  1460. if ($statut == 0) { return $langs->trans("ServiceStatusInitial"); }
  1461. if ($statut == 4 && $expired == -1) { return $langs->trans("ServiceStatusRunning"); }
  1462. if ($statut == 4 && $expired == 0) { return $langs->trans("ServiceStatusNotLateShort"); }
  1463. if ($statut == 4 && $expired == 1) { return $langs->trans("ServiceStatusLateShort"); }
  1464. if ($statut == 5) { return $langs->trans("Serviā€¦

Large files files are truncated, but you can click here to view the full file