dolibarr  7.0.0-beta
contrat.class.php
Go to the documentation of this 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-2014 Regis Houssin <regis.houssin@capnetworks.com>
5  * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
6  * Copyright (C) 2008 Raphael Bertrand <raphael.bertrand@resultic.fr>
7  * Copyright (C) 2010-2016 Juanjo Menent <jmenent@2byte.es>
8  * Copyright (C) 2013 Christophe Battarel <christophe.battarel@altairis.fr>
9  * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
10  * Copyright (C) 2014-2015 Marcos GarcĂ­a <marcosgdf@gmail.com>
11  * Copyright (C) 2015-2017 Ferran Marcet <fmarcet@2byte.es>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program. If not, see <http://www.gnu.org/licenses/>.
25  */
26 
33 require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php';
34 require_once DOL_DOCUMENT_ROOT."/core/class/commonobjectline.class.php";
35 require_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php';
36 require_once DOL_DOCUMENT_ROOT . '/margin/lib/margins.lib.php';
37 
41 class Contrat extends CommonObject
42 {
43  public $element='contrat';
44  public $table_element='contrat';
45  public $table_element_line='contratdet';
46  public $fk_element='fk_contrat';
47  public $picto='contract';
52  public $ismultientitymanaged = 1;
57  public $restrictiononfksoc = 1;
58 
62  protected $table_ref_field = 'ref';
63 
68  var $ref_customer;
69 
74  var $ref_supplier;
75 
80  var $socid;
81  var $societe; // Objet societe
82 
87  var $statut=0; // 0=Draft,
88  var $product;
89 
93  public $fk_user_author;
94 
100  public $user_author_id;
101 
105  public $user_creation;
106 
110  public $user_cloture;
111 
115  var $date_creation;
116 
120  public $date_modification;
121 
125  var $date_validation;
126 
130  var $date_contrat;
131 
136  var $date_cloture;
137 
138  var $commercial_signature_id;
139  var $commercial_suivi_id;
140 
146 
147  var $extraparams=array();
148 
152  var $lines=array();
153 
158  protected $lines_id_index_mapper=array();
159 
160 
166  function __construct($db)
167  {
168  $this->db = $db;
169  }
170 
177  function getNextNumRef($soc)
178  {
179  global $db, $langs, $conf;
180  $langs->load("contracts");
181 
182  if (!empty($conf->global->CONTRACT_ADDON))
183  {
184  $mybool = false;
185 
186  $file = $conf->global->CONTRACT_ADDON.".php";
187  $classname = $conf->global->CONTRACT_ADDON;
188 
189  // Include file with class
190  $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
191 
192  foreach ($dirmodels as $reldir) {
193 
194  $dir = dol_buildpath($reldir."core/modules/contract/");
195 
196  // Load file with numbering class (if found)
197  $mybool|=@include_once $dir.$file;
198  }
199 
200  if (! $mybool)
201  {
202  dol_print_error('',"Failed to include file ".$file);
203  return '';
204  }
205 
206  $obj = new $classname();
207  $numref = $obj->getNextValue($soc,$this);
208 
209  if ( $numref != "")
210  {
211  return $numref;
212  }
213  else
214  {
215  $this->error = $obj->error;
216  dol_print_error($db,get_class($this)."::getNextValue ".$obj->error);
217  return "";
218  }
219  }
220  else
221  {
222  $langs->load("errors");
223  print $langs->trans("Error")." ".$langs->trans("ErrorModuleSetupNotComplete");
224  return "";
225  }
226  }
227 
238  function active_line($user, $line_id, $date, $date_end='', $comment='')
239  {
240  return $this->lines[$this->lines_id_index_mapper[$line_id]]->active_line($user, $date, $date_end, $comment);
241  }
242 
243 
253  function close_line($user, $line_id, $date_end, $comment='')
254  {
255  return $this->lines[$this->lines_id_index_mapper[$line_id]]->close_line($user, $date_end, $comment);
256  }
257 
258 
266  function activateAll($user, $date_start='')
267  {
268  if (empty($date_start)) $date_start = dol_now();
269 
270  $this->db->begin();
271 
272  // Load lines
273  $this->fetch_lines();
274 
275  $ok=true;
276  foreach($this->lines as $contratline)
277  {
278  // Open lines not already open
279  if ($contratline->statut != 4)
280  {
281  $result = $contratline->active_line($user, $date_start, -1);
282  if ($result < 0)
283  {
284  $ok=false;
285  break;
286  }
287  }
288  }
289 
290  if ($this->statut == 0)
291  {
292  $result=$this->validate($user);
293  if ($result < 0) $ok=false;
294  }
295 
296  if ($ok)
297  {
298  $this->db->commit();
299  return 1;
300  }
301  else
302  {
303  dol_print_error($this->db,'Error in activateAll function');
304  $this->db->rollback();
305  return -1;
306  }
307  }
308 
316  function closeAll(User $user, $notrigger=0)
317  {
318  $this->db->begin();
319 
320  // Load lines
321  $this->fetch_lines();
322 
323  $now = dol_now();
324 
325  $ok=true;
326  foreach($this->lines as $contratline)
327  {
328  // Close lines not already closed
329  if ($contratline->statut != 5)
330  {
331  $contratline->date_cloture=$now;
332  $contratline->fk_user_cloture=$user->id;
333  $contratline->statut='5';
334  $result=$contratline->update($user);
335  if ($result < 0)
336  {
337  $ok=false;
338  break;
339  }
340  }
341  }
342 
343  if ($this->statut == 0)
344  {
345  $result=$this->validate($user, '', $notrigger);
346  if ($result < 0) $ok=false;
347  }
348 
349  if ($ok)
350  {
351  $this->db->commit();
352  return 1;
353  }
354  else
355  {
356  dol_print_error($this->db,'Error in closeAll function');
357  $this->db->rollback();
358  return -1;
359  }
360  }
361 
370  function validate(User $user, $force_number='', $notrigger=0)
371  {
372  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
373  global $langs, $conf;
374 
375  $now=dol_now();
376 
377  $error=0;
378  dol_syslog(get_class($this).'::validate user='.$user->id.', force_number='.$force_number);
379 
380 
381  $this->db->begin();
382 
383  $this->fetch_thirdparty();
384 
385  // A contract is validated so we can move thirdparty to status customer
386  $result=$this->thirdparty->set_as_client();
387 
388  // Define new ref
389  if (! $error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) // empty should not happened, but when it occurs, the test save life
390  {
391  $num = $this->getNextNumRef($this->thirdparty);
392  }
393  else
394  {
395  $num = $this->ref;
396  }
397  $this->newref = $num;
398 
399  if ($num)
400  {
401  $sql = "UPDATE ".MAIN_DB_PREFIX."contrat SET ref = '".$num."', statut = 1";
402  //$sql.= ", fk_user_valid = ".$user->id.", date_valid = '".$this->db->idate($now)."'";
403  $sql .= " WHERE rowid = ".$this->id . " AND statut = 0";
404 
405  dol_syslog(get_class($this)."::validate", LOG_DEBUG);
406  $resql = $this->db->query($sql);
407  if (! $resql)
408  {
409  dol_print_error($this->db);
410  $error++;
411  $this->error=$this->db->lasterror();
412  }
413 
414  // Trigger calls
415  if (! $error && ! $notrigger)
416  {
417  // Call trigger
418  $result=$this->call_trigger('CONTRACT_VALIDATE',$user);
419  if ($result < 0) { $error++; }
420  // End call triggers
421  }
422 
423  if (! $error)
424  {
425  $this->oldref = $this->ref;
426 
427  // Rename directory if dir was a temporary ref
428  if (preg_match('/^[\(]?PROV/i', $this->ref))
429  {
430  // Rename of object directory ($this->ref = old ref, $num = new ref)
431  // to not lose the linked files
432  $oldref = dol_sanitizeFileName($this->ref);
433  $newref = dol_sanitizeFileName($num);
434  $dirsource = $conf->contract->dir_output.'/'.$oldref;
435  $dirdest = $conf->contract->dir_output.'/'.$newref;
436  if (file_exists($dirsource))
437  {
438  dol_syslog(get_class($this)."::validate rename dir ".$dirsource." into ".$dirdest);
439 
440  if (@rename($dirsource, $dirdest))
441  {
442  dol_syslog("Rename ok");
443  // Rename docs starting with $oldref with $newref
444  $listoffiles=dol_dir_list($conf->contract->dir_output.'/'.$newref, 'files', 1, '^'.preg_quote($oldref,'/'));
445  foreach($listoffiles as $fileentry)
446  {
447  $dirsource=$fileentry['name'];
448  $dirdest=preg_replace('/^'.preg_quote($oldref,'/').'/',$newref, $dirsource);
449  $dirsource=$fileentry['path'].'/'.$dirsource;
450  $dirdest=$fileentry['path'].'/'.$dirdest;
451  @rename($dirsource, $dirdest);
452  }
453  }
454  }
455  }
456  }
457 
458  // Set new ref and define current statut
459  if (! $error)
460  {
461  $this->ref = $num;
462  $this->statut = 1;
463  $this->brouillon = 0;
464  $this->date_validation = $now;
465  }
466  }
467  else
468  {
469  $error++;
470  }
471 
472  if (! $error)
473  {
474  $this->db->commit();
475  return 1;
476  }
477  else
478  {
479  $this->db->rollback();
480  return -1;
481  }
482 
483  }
484 
492  function reopen($user, $notrigger=0)
493  {
494  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
495  global $langs, $conf;
496 
497  $now=dol_now();
498 
499  $error=0;
500  dol_syslog(get_class($this).'::reopen user='.$user->id);
501 
502  $this->db->begin();
503 
504  $this->fetch_thirdparty();
505 
506  $sql = "UPDATE ".MAIN_DB_PREFIX."contrat SET statut = 0";
507  //$sql.= ", fk_user_valid = null, date_valid = null";
508  $sql .= " WHERE rowid = ".$this->id . " AND statut = 1";
509 
510  dol_syslog(get_class($this)."::validate", LOG_DEBUG);
511  $resql = $this->db->query($sql);
512  if (! $resql)
513  {
514  dol_print_error($this->db);
515  $error++;
516  $this->error=$this->db->lasterror();
517  }
518 
519  // Trigger calls
520  if (! $error && ! $notrigger)
521  {
522  // Call trigger
523  $result=$this->call_trigger('CONTRACT_REOPEN',$user);
524  if ($result < 0) {
525  $error++;
526  }
527  // End call triggers
528  }
529 
530  // Set new ref and define current statut
531  if (! $error)
532  {
533  $this->statut=0;
534  $this->brouillon=1;
535  $this->date_validation=$now;
536  }
537 
538  if (! $error)
539  {
540  $this->db->commit();
541  return 1;
542  }
543  else
544  {
545  $this->db->rollback();
546  return -1;
547  }
548  }
549 
559  function fetch($id, $ref='', $ref_customer='', $ref_supplier='')
560  {
561  $sql = "SELECT rowid, statut, ref, fk_soc, mise_en_service as datemise,";
562  $sql.= " ref_supplier, ref_customer,";
563  $sql.= " ref_ext,";
564  $sql.= " fk_user_mise_en_service, date_contrat as datecontrat,";
565  $sql.= " fk_user_author, fin_validite, date_cloture,";
566  $sql.= " fk_projet,";
567  $sql.= " fk_commercial_signature, fk_commercial_suivi,";
568  $sql.= " note_private, note_public, model_pdf, extraparams";
569  $sql.= " FROM ".MAIN_DB_PREFIX."contrat";
570  if (! $id) $sql.=" WHERE entity IN (".getEntity('contract').")";
571  else $sql.= " WHERE rowid=".$id;
572  if ($ref_customer)
573  {
574  $sql.= " AND ref_customer = '".$this->db->escape($ref_customer)."'";
575  }
576  if ($ref_supplier)
577  {
578  $sql.= " AND ref_supplier = '".$this->db->escape($ref_supplier)."'";
579  }
580  if ($ref)
581  {
582  $sql.= " AND ref='".$this->db->escape($ref)."'";
583  }
584 
585  dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
586  $resql = $this->db->query($sql);
587  if ($resql)
588  {
589  $result = $this->db->fetch_array($resql);
590 
591  if ($result)
592  {
593  $this->id = $result["rowid"];
594  $this->ref = (!isset($result["ref"]) || !$result["ref"]) ? $result["rowid"] : $result["ref"];
595  $this->ref_customer = $result["ref_customer"];
596  $this->ref_supplier = $result["ref_supplier"];
597  $this->ref_ext = $result["ref_ext"];
598  $this->statut = $result["statut"];
599  $this->mise_en_service = $this->db->jdate($result["datemise"]);
600 
601  $this->date_contrat = $this->db->jdate($result["datecontrat"]);
602  $this->date_creation = $this->db->jdate($result["datecontrat"]);
603 
604  $this->fin_validite = $this->db->jdate($result["fin_validite"]);
605  $this->date_cloture = $this->db->jdate($result["date_cloture"]);
606 
607 
608  $this->user_author_id = $result["fk_user_author"];
609 
610  $this->commercial_signature_id = $result["fk_commercial_signature"];
611  $this->commercial_suivi_id = $result["fk_commercial_suivi"];
612 
613  $this->note_private = $result["note_private"];
614  $this->note_public = $result["note_public"];
615  $this->modelpdf = $result["model_pdf"];
616 
617  $this->fk_projet = $result["fk_projet"]; // deprecated
618  $this->fk_project = $result["fk_projet"];
619 
620  $this->socid = $result["fk_soc"];
621  $this->fk_soc = $result["fk_soc"];
622 
623  $this->extraparams = (array) json_decode($result["extraparams"], true);
624 
625  $this->db->free($resql);
626 
627  // Retreive all extrafield for thirdparty
628  // fetch optionals attributes and labels
629  require_once(DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php');
630  $extrafields=new ExtraFields($this->db);
631  $extralabels=$extrafields->fetch_name_optionals_label($this->table_element,true);
632  $this->fetch_optionals($this->id,$extralabels);
633 
634  /*
635  * Lines
636  */
637 
638  $this->lines = array();
639 
640  $result=$this->fetch_lines();
641  if ($result < 0)
642  {
643  $this->error=$this->db->lasterror();
644  return -3;
645  }
646 
647  return $this->id;
648  }
649  else
650  {
651  dol_syslog(get_class($this)."::Fetch Erreur contrat non trouve");
652  $this->error="Contract not found";
653  return 0;
654  }
655  }
656  else
657  {
658  dol_syslog(get_class($this)."::Fetch Erreur lecture contrat");
659  $this->error=$this->db->error();
660  return -1;
661  }
662 
663  }
664 
670  function fetch_lines()
671  {
672  $this->nbofserviceswait=0;
673  $this->nbofservicesopened=0;
674  $this->nbofservicesexpired=0;
675  $this->nbofservicesclosed=0;
676 
677  $total_ttc=0;
678  $total_vat=0;
679  $total_ht=0;
680 
681  $now=dol_now();
682 
683  require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
684  $extrafieldsline=new ExtraFields($this->db);
685  $line = new ContratLigne($this->db);
686  $extralabelsline=$extrafieldsline->fetch_name_optionals_label($line->table_element,true);
687 
688  $this->lines=array();
689  $pos = 0;
690 
691  // Selectionne les lignes contrats liees a un produit
692  $sql = "SELECT p.label as product_label, p.description as product_desc, p.ref as product_ref,";
693  $sql.= " d.rowid, d.fk_contrat, d.statut, d.description, d.price_ht, d.vat_src_code, d.tva_tx, d.localtax1_tx, d.localtax2_tx, d.localtax1_type, d.localtax2_type, d.qty, d.remise_percent, d.subprice, d.fk_product_fournisseur_price as fk_fournprice, d.buy_price_ht as pa_ht,";
694  $sql.= " d.total_ht,";
695  $sql.= " d.total_tva,";
696  $sql.= " d.total_localtax1,";
697  $sql.= " d.total_localtax2,";
698  $sql.= " d.total_ttc,";
699  $sql.= " d.info_bits, d.fk_product,";
700  $sql.= " d.date_ouverture_prevue, d.date_ouverture,";
701  $sql.= " d.date_fin_validite, d.date_cloture,";
702  $sql.= " d.fk_user_author,";
703  $sql.= " d.fk_user_ouverture,";
704  $sql.= " d.fk_user_cloture,";
705  $sql.= " d.fk_unit";
706  $sql.= " FROM ".MAIN_DB_PREFIX."contratdet as d LEFT JOIN ".MAIN_DB_PREFIX."product as p ON d.fk_product = p.rowid";
707  $sql.= " WHERE d.fk_contrat = ".$this->id;
708  $sql.= " ORDER by d.rowid ASC";
709 
710  dol_syslog(get_class($this)."::fetch_lines", LOG_DEBUG);
711  $result = $this->db->query($sql);
712  if ($result)
713  {
714  $num = $this->db->num_rows($result);
715  $i = 0;
716 
717  while ($i < $num)
718  {
719  $objp = $this->db->fetch_object($result);
720 
721  $line = new ContratLigne($this->db);
722  $line->id = $objp->rowid;
723  $line->ref = $objp->rowid;
724  $line->fk_contrat = $objp->fk_contrat;
725  $line->desc = $objp->description; // Description ligne
726  $line->qty = $objp->qty;
727  $line->vat_src_code = $objp->vat_src_code ;
728  $line->tva_tx = $objp->tva_tx;
729  $line->localtax1_tx = $objp->localtax1_tx;
730  $line->localtax2_tx = $objp->localtax2_tx;
731  $line->localtax1_type = $objp->localtax1_type;
732  $line->localtax2_type = $objp->localtax2_type;
733  $line->subprice = $objp->subprice;
734  $line->statut = $objp->statut;
735  $line->remise_percent = $objp->remise_percent;
736  $line->price_ht = $objp->price_ht;
737  $line->price = $objp->price_ht; // For backward compatibility
738  $line->total_ht = $objp->total_ht;
739  $line->total_tva = $objp->total_tva;
740  $line->total_localtax1 = $objp->total_localtax1;
741  $line->total_localtax2 = $objp->total_localtax2;
742  $line->total_ttc = $objp->total_ttc;
743  $line->fk_product = (($objp->fk_product > 0)?$objp->fk_product:0);
744  $line->info_bits = $objp->info_bits;
745 
746  $line->fk_fournprice = $objp->fk_fournprice;
747  $marginInfos = getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
748  $line->pa_ht = $marginInfos[0];
749 
750  $line->fk_user_author = $objp->fk_user_author;
751  $line->fk_user_ouverture= $objp->fk_user_ouverture;
752  $line->fk_user_cloture = $objp->fk_user_cloture;
753  $line->fk_unit = $objp->fk_unit;
754 
755  $line->ref = $objp->product_ref; // deprecated
756  if (empty($objp->fk_product))
757  {
758  $line->label = ''; // deprecated
759  $line->libelle = $objp->description; // deprecated
760  }
761  else
762  {
763  $line->label = $objp->product_label; // deprecated
764  $line->libelle = $objp->product_label; // deprecated
765  }
766  $line->product_ref = $objp->product_ref; // Ref product
767  $line->product_desc = $objp->product_desc; // Description product
768  $line->product_label = $objp->product_label; // Label product
769 
770  $line->description = $objp->description;
771 
772  $line->date_start = $this->db->jdate($objp->date_ouverture_prevue);
773  $line->date_start_real = $this->db->jdate($objp->date_ouverture);
774  $line->date_end = $this->db->jdate($objp->date_fin_validite);
775  $line->date_end_real = $this->db->jdate($objp->date_cloture);
776  // For backward compatibility
777  $line->date_ouverture_prevue = $this->db->jdate($objp->date_ouverture_prevue);
778  $line->date_ouverture = $this->db->jdate($objp->date_ouverture);
779  $line->date_fin_validite = $this->db->jdate($objp->date_fin_validite);
780  $line->date_cloture = $this->db->jdate($objp->date_cloture);
781  $line->date_debut_prevue = $this->db->jdate($objp->date_ouverture_prevue);
782  $line->date_debut_reel = $this->db->jdate($objp->date_ouverture);
783  $line->date_fin_prevue = $this->db->jdate($objp->date_fin_validite);
784  $line->date_fin_reel = $this->db->jdate($objp->date_cloture);
785 
786  // Retreive all extrafield for contract
787  // fetch optionals attributes and labels
788  $line->fetch_optionals($line->id,$extralabelsline);
789 
790  $this->lines[$pos] = $line;
791  $this->lines_id_index_mapper[$line->id] = $pos;
792 
793  //dol_syslog("1 ".$line->desc);
794  //dol_syslog("2 ".$line->product_desc);
795 
796  if ($line->statut == 0) $this->nbofserviceswait++;
797  if ($line->statut == 4 && (empty($line->date_fin_prevue) || $line->date_fin_prevue >= $now)) $this->nbofservicesopened++;
798  if ($line->statut == 4 && (! empty($line->date_fin_prevue) && $line->date_fin_prevue < $now)) $this->nbofservicesexpired++;
799  if ($line->statut == 5) $this->nbofservicesclosed++;
800 
801  $total_ttc+=$objp->total_ttc; // TODO Not saved into database
802  $total_vat+=$objp->total_tva;
803  $total_ht+=$objp->total_ht;
804 
805  $i++;
806  $pos++;
807  }
808  $this->db->free($result);
809  }
810  else
811  {
812  dol_syslog(get_class($this)."::Fetch Erreur lecture des lignes de contrats liees aux produits");
813  return -3;
814  }
815 
816  $this->nbofservices=count($this->lines);
817  $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
818  $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
819  $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
820 
821  return $this->lines;
822  }
823 
830  function create($user)
831  {
832  global $conf,$langs,$mysoc;
833 
834  // Check parameters
835  $paramsok=1;
836  if ($this->commercial_signature_id <= 0)
837  {
838  $langs->load("commercial");
839  $this->error.=$langs->trans("ErrorFieldRequired",$langs->trans("SalesRepresentativeSignature"));
840  $paramsok=0;
841  }
842  if ($this->commercial_suivi_id <= 0)
843  {
844  $langs->load("commercial");
845  $this->error.=($this->error?"<br>":'');
846  $this->error.=$langs->trans("ErrorFieldRequired",$langs->trans("SalesRepresentativeFollowUp"));
847  $paramsok=0;
848  }
849  if (! $paramsok) return -1;
850 
851 
852  $this->db->begin();
853 
854  $now=dol_now();
855 
856  // Insert contract
857  $sql = "INSERT INTO ".MAIN_DB_PREFIX."contrat (datec, fk_soc, fk_user_author, date_contrat,";
858  $sql.= " fk_commercial_signature, fk_commercial_suivi, fk_projet,";
859  $sql.= " ref, entity, note_private, note_public, ref_customer, ref_supplier, ref_ext)";
860  $sql.= " VALUES ('".$this->db->idate($now)."',".$this->socid.",".$user->id;
861  $sql.= ", ".(dol_strlen($this->date_contrat)!=0 ? "'".$this->db->idate($this->date_contrat)."'" : "NULL");
862  $sql.= ",".($this->commercial_signature_id>0?$this->commercial_signature_id:"NULL");
863  $sql.= ",".($this->commercial_suivi_id>0?$this->commercial_suivi_id:"NULL");
864  $sql.= ",".($this->fk_project>0?$this->fk_project:"NULL");
865  $sql.= ", ".(dol_strlen($this->ref)<=0 ? "null" : "'".$this->db->escape($this->ref)."'");
866  $sql.= ", ".$conf->entity;
867  $sql.= ", ".(!empty($this->note_private)?("'".$this->db->escape($this->note_private)."'"):"NULL");
868  $sql.= ", ".(!empty($this->note_public)?("'".$this->db->escape($this->note_public)."'"):"NULL");
869  $sql.= ", ".(!empty($this->ref_customer)?("'".$this->db->escape($this->ref_customer)."'"):"NULL");
870  $sql.= ", ".(!empty($this->ref_supplier)?("'".$this->db->escape($this->ref_supplier)."'"):"NULL");
871  $sql.= ", ".(!empty($this->ref_ext)?("'".$this->db->escape($this->ref_ext)."'"):"NULL");
872  $sql.= ")";
873  $resql=$this->db->query($sql);
874  if ($resql)
875  {
876  $error=0;
877 
878  $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."contrat");
879 
880 
881  // Load object modContract
882  $module=(! empty($conf->global->CONTRACT_ADDON)?$conf->global->CONTRACT_ADDON:'mod_contract_serpis');
883  if (substr($module, 0, 13) == 'mod_contract_' && substr($module, -3) == 'php')
884  {
885  $module = substr($module, 0, dol_strlen($module)-4);
886  }
887  $result=dol_include_once('/core/modules/contract/'.$module.'.php');
888  if ($result > 0)
889  {
890  $modCodeContract = new $module();
891  }
892 
893  if (!empty($modCodeContract->code_auto)) {
894  // Mise a jour ref
895  $sql = 'UPDATE '.MAIN_DB_PREFIX."contrat SET ref='(PROV".$this->id.")' WHERE rowid=".$this->id;
896  if ($this->db->query($sql))
897  {
898  if ($this->id)
899  {
900  $this->ref="(PROV".$this->id.")";
901  }
902  }
903  }
904 
905  if (! $error)
906  {
907  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
908  {
909  $result=$this->insertExtraFields();
910  if ($result < 0)
911  {
912  $error++;
913  }
914  }
915  }
916 
917  // Insert contacts commerciaux ('SALESREPSIGN','contrat')
918  if (! $error)
919  {
920  $result=$this->add_contact($this->commercial_signature_id,'SALESREPSIGN','internal');
921  if ($result < 0) $error++;
922  }
923 
924  // Insert contacts commerciaux ('SALESREPFOLL','contrat')
925  if (! $error)
926  {
927  $result=$this->add_contact($this->commercial_suivi_id,'SALESREPFOLL','internal');
928  if ($result < 0) $error++;
929  }
930 
931  if (! $error)
932  {
933  if (! empty($this->linkedObjectsIds) && empty($this->linked_objects)) // To use new linkedObjectsIds instead of old linked_objects
934  {
935  $this->linked_objects = $this->linkedObjectsIds; // TODO Replace linked_objects with linkedObjectsIds
936  }
937 
938  // Add object linked
939  if (! $error && $this->id && is_array($this->linked_objects) && ! empty($this->linked_objects))
940  {
941  foreach($this->linked_objects as $origin => $tmp_origin_id)
942  {
943  if (is_array($tmp_origin_id)) // New behaviour, if linked_object can have several links per type, so is something like array('contract'=>array(id1, id2, ...))
944  {
945  foreach($tmp_origin_id as $origin_id)
946  {
947  $ret = $this->add_object_linked($origin, $origin_id);
948  if (! $ret)
949  {
950  $this->error=$this->db->lasterror();
951  $error++;
952  }
953  }
954  }
955  else // Old behaviour, if linked_object has only one link per type, so is something like array('contract'=>id1))
956  {
957  $origin_id = $tmp_origin_id;
958  $ret = $this->add_object_linked($origin, $origin_id);
959  if (! $ret)
960  {
961  $this->error=$this->db->lasterror();
962  $error++;
963  }
964  }
965  }
966  }
967 
968  if (! $error && $this->id && ! empty($conf->global->MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN) && ! empty($this->origin) && ! empty($this->origin_id)) // Get contact from origin object
969  {
970  $originforcontact = $this->origin;
971  $originidforcontact = $this->origin_id;
972  if ($originforcontact == 'shipping') // shipment and order share the same contacts. If creating from shipment we take data of order
973  {
974  require_once DOL_DOCUMENT_ROOT . '/expedition/class/expedition.class.php';
975  $exp = new Expedition($db);
976  $exp->fetch($this->origin_id);
977  $exp->fetchObjectLinked();
978  if (count($exp->linkedObjectsIds['commande']) > 0)
979  {
980  foreach ($exp->linkedObjectsIds['commande'] as $key => $value)
981  {
982  $originforcontact = 'commande';
983  $originidforcontact = $value->id;
984  break; // We take first one
985  }
986  }
987  }
988 
989  $sqlcontact = "SELECT ctc.code, ctc.source, ec.fk_socpeople FROM ".MAIN_DB_PREFIX."element_contact as ec, ".MAIN_DB_PREFIX."c_type_contact as ctc";
990  $sqlcontact.= " WHERE element_id = ".$originidforcontact." AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$originforcontact."'";
991 
992  $resqlcontact = $this->db->query($sqlcontact);
993  if ($resqlcontact)
994  {
995  while($objcontact = $this->db->fetch_object($resqlcontact))
996  {
997  if ($objcontact->source == 'internal' && in_array($objcontact->code, array('SALESREPSIGN', 'SALESREPFOLL'))) continue; // ignore this, already forced previously
998 
999  //print $objcontact->code.'-'.$objcontact->source.'-'.$objcontact->fk_socpeople."\n";
1000  $this->add_contact($objcontact->fk_socpeople, $objcontact->code, $objcontact->source); // May failed because of duplicate key or because code of contact type does not exists for new object
1001  }
1002  }
1003  else dol_print_error($resqlcontact);
1004  }
1005  }
1006 
1007  if (! $error)
1008  {
1009  // Call trigger
1010  $result=$this->call_trigger('CONTRACT_CREATE',$user);
1011  if ($result < 0) { $error++; }
1012  // End call triggers
1013 
1014  if (! $error)
1015  {
1016  $this->db->commit();
1017  return $this->id;
1018  }
1019  else
1020  {
1021  dol_syslog(get_class($this)."::create - 30 - ".$this->error, LOG_ERR);
1022  $this->db->rollback();
1023  return -3;
1024  }
1025  }
1026  else
1027  {
1028  $this->error="Failed to add contact";
1029  dol_syslog(get_class($this)."::create - 20 - ".$this->error, LOG_ERR);
1030  $this->db->rollback();
1031  return -2;
1032  }
1033  }
1034  else
1035  {
1036  $this->error=$langs->trans("UnknownError: ".$this->db->error()." -", LOG_DEBUG);
1037 
1038  $this->db->rollback();
1039  return -1;
1040  }
1041  }
1042 
1043 
1050  function delete($user)
1051  {
1052  global $conf, $langs;
1053  require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
1054 
1055  $error=0;
1056 
1057  $this->db->begin();
1058 
1059  // Call trigger
1060  $result=$this->call_trigger('CONTRACT_DELETE',$user);
1061  if ($result < 0) { $error++; }
1062  // End call triggers
1063 
1064  if (! $error)
1065  {
1066  // Delete linked contacts
1067  $res = $this->delete_linked_contact();
1068  if ($res < 0)
1069  {
1070  dol_syslog(get_class($this)."::delete error", LOG_ERR);
1071  $error++;
1072  }
1073  }
1074 
1075  if (! $error)
1076  {
1077  // Delete linked object
1078  $res = $this->deleteObjectLinked();
1079  if ($res < 0) $error++;
1080  }
1081 
1082  if (! $error)
1083  {
1084  // Delete contratdet_log
1085  /*
1086  $sql = "DELETE cdl";
1087  $sql.= " FROM ".MAIN_DB_PREFIX."contratdet_log as cdl, ".MAIN_DB_PREFIX."contratdet as cd";
1088  $sql.= " WHERE cdl.fk_contratdet=cd.rowid AND cd.fk_contrat=".$this->id;
1089  */
1090  $sql = "SELECT cdl.rowid as cdlrowid ";
1091  $sql.= " FROM ".MAIN_DB_PREFIX."contratdet_log as cdl, ".MAIN_DB_PREFIX."contratdet as cd";
1092  $sql.= " WHERE cdl.fk_contratdet=cd.rowid AND cd.fk_contrat=".$this->id;
1093 
1094  dol_syslog(get_class($this)."::delete contratdet_log", LOG_DEBUG);
1095  $resql=$this->db->query($sql);
1096  if (! $resql)
1097  {
1098  $this->error=$this->db->error();
1099  $error++;
1100  }
1101  $numressql=$this->db->num_rows($resql);
1102  if (! $error && $numressql )
1103  {
1104  $tab_resql=array();
1105  for($i=0;$i<$numressql;$i++)
1106  {
1107  $objresql=$this->db->fetch_object($resql);
1108  $tab_resql[]= $objresql->cdlrowid;
1109  }
1110  $this->db->free($resql);
1111 
1112  $sql= "DELETE FROM ".MAIN_DB_PREFIX."contratdet_log ";
1113  $sql.= " WHERE ".MAIN_DB_PREFIX."contratdet_log.rowid IN (".implode(",",$tab_resql).")";
1114 
1115  dol_syslog(get_class($this)."::delete contratdet_log", LOG_DEBUG);
1116  $resql=$this->db->query($sql);
1117  if (! $resql)
1118  {
1119  $this->error=$this->db->error();
1120  $error++;
1121  }
1122  }
1123  }
1124 
1125  if (! $error)
1126  {
1127  // Delete contratdet
1128  $sql = "DELETE FROM ".MAIN_DB_PREFIX."contratdet";
1129  $sql.= " WHERE fk_contrat=".$this->id;
1130 
1131  dol_syslog(get_class($this)."::delete contratdet", LOG_DEBUG);
1132  $resql=$this->db->query($sql);
1133  if (! $resql)
1134  {
1135  $this->error=$this->db->error();
1136  $error++;
1137  }
1138  }
1139 
1140  if (! $error)
1141  {
1142  // Delete contrat
1143  $sql = "DELETE FROM ".MAIN_DB_PREFIX."contrat";
1144  $sql.= " WHERE rowid=".$this->id;
1145 
1146  dol_syslog(get_class($this)."::delete contrat", LOG_DEBUG);
1147  $resql=$this->db->query($sql);
1148  if (! $resql)
1149  {
1150  $this->error=$this->db->error();
1151  $error++;
1152  }
1153  }
1154 
1155  // Removed extrafields
1156  if (! $error) {
1157  $result=$this->deleteExtraFields();
1158  if ($result < 0)
1159  {
1160  $error++;
1161  dol_syslog(get_class($this)."::delete error -3 ".$this->error, LOG_ERR);
1162  }
1163  }
1164 
1165  if (! $error)
1166  {
1167  // We remove directory
1168  $ref = dol_sanitizeFileName($this->ref);
1169  if ($conf->contrat->dir_output)
1170  {
1171  $dir = $conf->contrat->dir_output . "/" . $ref;
1172  if (file_exists($dir))
1173  {
1174  $res=@dol_delete_dir_recursive($dir);
1175  if (! $res)
1176  {
1177  $this->error='ErrorFailToDeleteDir';
1178  $error++;
1179  }
1180  }
1181  }
1182  }
1183 
1184  if (! $error)
1185  {
1186  $this->db->commit();
1187  return 1;
1188  }
1189  else
1190  {
1191  $this->error=$this->db->lasterror();
1192  $this->db->rollback();
1193  return -1;
1194  }
1195  }
1196 
1204  function update($user=null, $notrigger=0)
1205  {
1206  global $conf, $langs;
1207  $error=0;
1208 
1209  // Clean parameters
1210  if (empty($this->fk_commercial_signature) && $this->commercial_signature_id > 0) $this->fk_commercial_signature = $this->commercial_signature_id;
1211  if (empty($this->fk_commercial_suivi) && $this->commercial_suivi_id > 0) $this->fk_commercial_suivi = $this->commercial_suivi_id;
1212  if (empty($this->fk_soc) && $this->socid > 0) $this->fk_soc = $this->socid;
1213  if (empty($this->fk_project) && $this->projet > 0) $this->fk_project = $this->projet;
1214 
1215  if (isset($this->ref)) $this->ref=trim($this->ref);
1216  if (isset($this->ref_customer)) $this->ref_customer=trim($this->ref_customer);
1217  if (isset($this->ref_supplier)) $this->ref_supplier=trim($this->ref_supplier);
1218  if (isset($this->ref_ext)) $this->ref_ext=trim($this->ref_ext);
1219  if (isset($this->entity)) $this->entity=trim($this->entity);
1220  if (isset($this->statut)) $this->statut=(int) $this->statut;
1221  if (isset($this->fk_soc)) $this->fk_soc=trim($this->fk_soc);
1222  if (isset($this->fk_commercial_signature)) $this->fk_commercial_signature=trim($this->fk_commercial_signature);
1223  if (isset($this->fk_commercial_suivi)) $this->fk_commercial_suivi=trim($this->fk_commercial_suivi);
1224  if (isset($this->fk_user_mise_en_service)) $this->fk_user_mise_en_service=trim($this->fk_user_mise_en_service);
1225  if (isset($this->fk_user_cloture)) $this->fk_user_cloture=trim($this->fk_user_cloture);
1226  if (isset($this->note_private)) $this->note_private=trim($this->note_private);
1227  if (isset($this->note_public)) $this->note_public=trim($this->note_public);
1228  if (isset($this->import_key)) $this->import_key=trim($this->import_key);
1229  //if (isset($this->extraparams)) $this->extraparams=trim($this->extraparams);
1230 
1231  // Check parameters
1232  // Put here code to add a control on parameters values
1233 
1234  // Update request
1235  $sql = "UPDATE ".MAIN_DB_PREFIX."contrat SET";
1236  $sql.= " ref=".(isset($this->ref)?"'".$this->db->escape($this->ref)."'":"null").",";
1237  $sql.= " ref_customer=".(isset($this->ref_customer)?"'".$this->db->escape($this->ref_customer)."'":"null").",";
1238  $sql.= " ref_supplier=".(isset($this->ref_supplier)?"'".$this->db->escape($this->ref_supplier)."'":"null").",";
1239  $sql.= " ref_ext=".(isset($this->ref_ext)?"'".$this->db->escape($this->ref_ext)."'":"null").",";
1240  $sql.= " entity=".$conf->entity.",";
1241  $sql.= " date_contrat=".(dol_strlen($this->date_contrat)!=0 ? "'".$this->db->idate($this->date_contrat)."'" : 'null').",";
1242  $sql.= " statut=".(isset($this->statut)?$this->statut:"null").",";
1243  $sql.= " mise_en_service=".(dol_strlen($this->mise_en_service)!=0 ? "'".$this->db->idate($this->mise_en_service)."'" : 'null').",";
1244  $sql.= " fin_validite=".(dol_strlen($this->fin_validite)!=0 ? "'".$this->db->idate($this->fin_validite)."'" : 'null').",";
1245  $sql.= " date_cloture=".(dol_strlen($this->date_cloture)!=0 ? "'".$this->db->idate($this->date_cloture)."'" : 'null').",";
1246  $sql.= " fk_soc=".($this->fk_soc > 0 ? $this->fk_soc:"null").",";
1247  $sql.= " fk_projet=".($this->fk_project > 0 ? $this->fk_project:"null").",";
1248  $sql.= " fk_commercial_signature=".(isset($this->fk_commercial_signature)?$this->fk_commercial_signature:"null").",";
1249  $sql.= " fk_commercial_suivi=".(isset($this->fk_commercial_suivi)?$this->fk_commercial_suivi:"null").",";
1250  $sql.= " fk_user_mise_en_service=".(isset($this->fk_user_mise_en_service)?$this->fk_user_mise_en_service:"null").",";
1251  $sql.= " fk_user_cloture=".(isset($this->fk_user_cloture)?$this->fk_user_cloture:"null").",";
1252  $sql.= " note_private=".(isset($this->note_private)?"'".$this->db->escape($this->note_private)."'":"null").",";
1253  $sql.= " note_public=".(isset($this->note_public)?"'".$this->db->escape($this->note_public)."'":"null").",";
1254  $sql.= " import_key=".(isset($this->import_key)?"'".$this->db->escape($this->import_key)."'":"null")."";
1255  //$sql.= " extraparams=".(isset($this->extraparams)?"'".$this->db->escape($this->extraparams)."'":"null")."";
1256  $sql.= " WHERE rowid=".$this->id;
1257 
1258  $this->db->begin();
1259 
1260  $resql = $this->db->query($sql);
1261  if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
1262 
1263  if (! $error)
1264  {
1265  if (! $notrigger)
1266  {
1267  // Uncomment this and change MYOBJECT to your own tag if you
1268  // want this action calls a trigger.
1269 
1271  //$result=$this->call_trigger('MYOBJECT_MODIFY',$user);
1272  //if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
1274  }
1275  }
1276 
1277  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($this->array_options) && count($this->array_options)>0) // For avoid conflicts if trigger used
1278  {
1279  $result=$this->insertExtraFields();
1280  if ($result < 0)
1281  {
1282  $error++;
1283  }
1284  }
1285 
1286  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($this->array_options) && count($this->array_options)>0) // For avoid conflicts if trigger used
1287  {
1288  $result=$this->insertExtraFields();
1289  if ($result < 0)
1290  {
1291  $error++;
1292  }
1293  }
1294 
1295  // Commit or rollback
1296  if ($error)
1297  {
1298  foreach($this->errors as $errmsg)
1299  {
1300  dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
1301  $this->error.=($this->error?', '.$errmsg:$errmsg);
1302  }
1303  $this->db->rollback();
1304  return -1*$error;
1305  }
1306  else
1307  {
1308  $this->db->commit();
1309  return 1;
1310  }
1311  }
1312 
1313 
1337  function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1, $txlocaltax2, $fk_product, $remise_percent, $date_start, $date_end, $price_base_type='HT', $pu_ttc=0.0, $info_bits=0, $fk_fournprice=null, $pa_ht = 0,$array_options=0, $fk_unit = null, $rang=0)
1338  {
1339  global $user, $langs, $conf, $mysoc;
1340 
1341  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, $rang");
1342 
1343  // Check parameters
1344  if ($fk_product <= 0 && empty($desc))
1345  {
1346  $this->error="DescRequiredForFreeProductLines";
1347  return -1;
1348  }
1349 
1350  if ($this->statut >= 0)
1351  {
1352  $this->db->begin();
1353 
1354  // Clean parameters
1355  $pu_ht=price2num($pu_ht);
1356  $pu_ttc=price2num($pu_ttc);
1357  $pa_ht=price2num($pa_ht);
1358  $txtva=price2num($txtva);
1359  $txlocaltax1=price2num($txlocaltax1);
1360  $txlocaltax2=price2num($txlocaltax2);
1361  $remise_percent=price2num($remise_percent);
1362  $qty=price2num($qty);
1363  if (empty($qty)) $qty=1;
1364  if (empty($info_bits)) $info_bits=0;
1365  if (empty($pu_ht) || ! is_numeric($pu_ht)) $pu_ht=0;
1366  if (empty($pu_ttc)) $pu_ttc=0;
1367  if (empty($txtva) || ! is_numeric($txtva)) $txtva=0;
1368  if (empty($txlocaltax1) || ! is_numeric($txlocaltax1)) $txlocaltax1=0;
1369  if (empty($txlocaltax2) || ! is_numeric($txlocaltax2)) $txlocaltax2=0;
1370 
1371  if ($price_base_type=='HT')
1372  {
1373  $pu=$pu_ht;
1374  }
1375  else
1376  {
1377  $pu=$pu_ttc;
1378  }
1379 
1380  // Check parameters
1381  if (empty($remise_percent)) $remise_percent=0;
1382 
1383  // Calcul du total TTC et de la TVA pour la ligne a partir de
1384  // qty, pu, remise_percent et txtva
1385  // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
1386  // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
1387 
1388  $localtaxes_type=getLocalTaxesFromRate($txtva, 0, $this->societe, $mysoc);
1389 
1390  // Clean vat code
1391  $vat_src_code='';
1392  if (preg_match('/\((.*)\)/', $txtva, $reg))
1393  {
1394  $vat_src_code = $reg[1];
1395  $txtva = preg_replace('/\s*\(.*\)/', '', $txtva); // Remove code into vatrate.
1396  }
1397 
1398  $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, 1,$mysoc, $localtaxes_type);
1399  $total_ht = $tabprice[0];
1400  $total_tva = $tabprice[1];
1401  $total_ttc = $tabprice[2];
1402  $total_localtax1= $tabprice[9];
1403  $total_localtax2= $tabprice[10];
1404 
1405  $localtax1_type=$localtaxes_type[0];
1406  $localtax2_type=$localtaxes_type[2];
1407 
1408  // TODO A virer
1409  // Anciens indicateurs: $price, $remise (a ne plus utiliser)
1410  $remise = 0;
1411  $price = price2num(round($pu_ht, 2));
1412  if (dol_strlen($remise_percent) > 0)
1413  {
1414  $remise = round(($pu_ht * $remise_percent / 100), 2);
1415  $price = $pu_ht - $remise;
1416  }
1417 
1418  if (empty($pa_ht)) $pa_ht=0;
1419 
1420 
1421  // if buy price not defined, define buyprice as configured in margin admin
1422  if ($this->pa_ht == 0)
1423  {
1424  if (($result = $this->defineBuyPrice($pu_ht, $remise_percent, $fk_product)) < 0)
1425  {
1426  return $result;
1427  }
1428  else
1429  {
1430  $pa_ht = $result;
1431  }
1432  }
1433 
1434  // Insertion dans la base
1435  $sql = "INSERT INTO ".MAIN_DB_PREFIX."contratdet";
1436  $sql.= " (fk_contrat, label, description, fk_product, qty, tva_tx, vat_src_code,";
1437  $sql.= " localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, remise_percent, subprice,";
1438  $sql.= " total_ht, total_tva, total_localtax1, total_localtax2, total_ttc,";
1439  $sql.= " info_bits,";
1440  $sql.= " price_ht, remise, fk_product_fournisseur_price, buy_price_ht";
1441  if ($date_start > 0) { $sql.= ",date_ouverture_prevue"; }
1442  if ($date_end > 0) { $sql.= ",date_fin_validite"; }
1443  $sql.= ", fk_unit";
1444  $sql.= ") VALUES (";
1445  $sql.= $this->id.", '', '" . $this->db->escape($desc) . "',";
1446  $sql.= ($fk_product>0 ? $fk_product : "null").",";
1447  $sql.= " ".$qty.",";
1448  $sql.= " ".$txtva.",";
1449  $sql.= " ".($vat_src_code?"'".$vat_src_code."'":"null").",";
1450  $sql.= " ".$txlocaltax1.",";
1451  $sql.= " ".$txlocaltax2.",";
1452  $sql.= " '".$localtax1_type."',";
1453  $sql.= " '".$localtax2_type."',";
1454  $sql.= " ".price2num($remise_percent).",";
1455  $sql.= " ".price2num($pu_ht).",";
1456  $sql.= " ".price2num($total_ht).",".price2num($total_tva).",".price2num($total_localtax1).",".price2num($total_localtax2).",".price2num($total_ttc).",";
1457  $sql.= " '".$info_bits."',";
1458  $sql.= " ".price2num($price).",".price2num($remise).",";
1459  if (isset($fk_fournprice)) $sql.= ' '.$fk_fournprice.',';
1460  else $sql.= ' null,';
1461  if (isset($pa_ht)) $sql.= ' '.price2num($pa_ht);
1462  else $sql.= ' null';
1463  if ($date_start > 0) { $sql.= ",'".$this->db->idate($date_start)."'"; }
1464  if ($date_end > 0) { $sql.= ",'".$this->db->idate($date_end)."'"; }
1465  $sql.= ", ".($fk_unit?"'".$this->db->escape($fk_unit)."'":"null");
1466  $sql.= ")";
1467 
1468  $resql=$this->db->query($sql);
1469  if ($resql)
1470  {
1471  $contractlineid = $this->db->last_insert_id(MAIN_DB_PREFIX."contratdet");
1472 
1473  $result=$this->update_statut($user);
1474  if ($result > 0)
1475  {
1476 
1477  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($array_options) && count($array_options)>0) // For avoid conflicts if trigger used
1478  {
1479  $contractline = new ContratLigne($this->db);
1480  $contractline->array_options=$array_options;
1481  $contractline->id=$contractlineid;
1482  $result=$contractline->insertExtraFields();
1483  if ($result < 0)
1484  {
1485  $this->error[]=$contractline->error;
1486  $error++;
1487  }
1488  }
1489 
1490  if (empty($error)) {
1491  // Call trigger
1492  $result=$this->call_trigger('LINECONTRACT_INSERT',$user);
1493  if ($result < 0)
1494  {
1495  $error++;
1496  }
1497  // End call triggers
1498  }
1499 
1500  if ($error)
1501  {
1502  $this->db->rollback();
1503  return -1;
1504  }
1505  else
1506  {
1507  $this->db->commit();
1508  return $contractlineid;
1509  }
1510  }
1511  else
1512  {
1513  $this->db->rollback();
1514  return -1;
1515  }
1516  }
1517  else
1518  {
1519  $this->db->rollback();
1520  $this->error=$this->db->error()." sql=".$sql;
1521  return -1;
1522  }
1523  }
1524  else
1525  {
1526  dol_syslog(get_class($this)."::addline ErrorTryToAddLineOnValidatedContract", LOG_ERR);
1527  return -2;
1528  }
1529  }
1530 
1554  function updateline($rowid, $desc, $pu, $qty, $remise_percent, $date_start, $date_end, $tvatx, $localtax1tx=0.0, $localtax2tx=0.0, $date_debut_reel='', $date_fin_reel='', $price_base_type='HT', $info_bits=0, $fk_fournprice=null, $pa_ht = 0,$array_options=0, $fk_unit = null)
1555  {
1556  global $user, $conf, $langs, $mysoc;
1557 
1558  // Clean parameters
1559  $qty=trim($qty);
1560  $desc=trim($desc);
1561  $desc=trim($desc);
1562  $price = price2num($pu);
1563  $tvatx = price2num($tvatx);
1564  $localtax1tx = price2num($localtax1tx);
1565  $localtax2tx = price2num($localtax2tx);
1566  $pa_ht=price2num($pa_ht);
1567  if (empty($fk_fournprice)) $fk_fournprice=0;
1568 
1569  $subprice = $price;
1570  $remise = 0;
1571  if (dol_strlen($remise_percent) > 0)
1572  {
1573  $remise = round(($pu * $remise_percent / 100), 2);
1574  $price = $pu - $remise;
1575  }
1576  else
1577  {
1578  $remise_percent=0;
1579  }
1580 
1581  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");
1582 
1583  $this->db->begin();
1584 
1585  // Calcul du total TTC et de la TVA pour la ligne a partir de
1586  // qty, pu, remise_percent et tvatx
1587  // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
1588  // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
1589 
1590  $localtaxes_type=getLocalTaxesFromRate($tvatx, 0, $this->societe, $mysoc);
1591  $tvatx = preg_replace('/\s*\(.*\)/','',$tvatx); // Remove code into vatrate.
1592 
1593  $tabprice=calcul_price_total($qty, $pu, $remise_percent, $tvatx, $localtax1tx, $localtax2tx, 0, $price_base_type, $info_bits, 1, $mysoc, $localtaxes_type);
1594  $total_ht = $tabprice[0];
1595  $total_tva = $tabprice[1];
1596  $total_ttc = $tabprice[2];
1597  $total_localtax1= $tabprice[9];
1598  $total_localtax2= $tabprice[10];
1599 
1600  $localtax1_type=$localtaxes_type[0];
1601  $localtax2_type=$localtaxes_type[2];
1602 
1603  // TODO A virer
1604  // Anciens indicateurs: $price, $remise (a ne plus utiliser)
1605  $remise = 0;
1606  $price = price2num(round($pu, 2));
1607  if (dol_strlen($remise_percent) > 0)
1608  {
1609  $remise = round(($pu * $remise_percent / 100), 2);
1610  $price = $pu - $remise;
1611  }
1612 
1613  if (empty($pa_ht)) $pa_ht=0;
1614 
1615  // if buy price not defined, define buyprice as configured in margin admin
1616  if ($this->pa_ht == 0)
1617  {
1618  if (($result = $this->defineBuyPrice($pu_ht, $remise_percent)) < 0)
1619  {
1620  return $result;
1621  }
1622  else
1623  {
1624  $pa_ht = $result;
1625  }
1626  }
1627 
1628  $sql = "UPDATE ".MAIN_DB_PREFIX."contratdet set description='".$this->db->escape($desc)."'";
1629  $sql.= ",price_ht='" . price2num($price)."'";
1630  $sql.= ",subprice='" . price2num($subprice)."'";
1631  $sql.= ",remise='" . price2num($remise)."'";
1632  $sql.= ",remise_percent='".price2num($remise_percent)."'";
1633  $sql.= ",qty='".$qty."'";
1634  $sql.= ",tva_tx='". price2num($tvatx)."'";
1635  $sql.= ",localtax1_tx='". price2num($localtax1tx)."'";
1636  $sql.= ",localtax2_tx='". price2num($localtax2tx)."'";
1637  $sql.= ",localtax1_type='".$localtax1_type."'";
1638  $sql.= ",localtax2_type='".$localtax2_type."'";
1639  $sql.= ", total_ht='". price2num($total_ht)."'";
1640  $sql.= ", total_tva='". price2num($total_tva)."'";
1641  $sql.= ", total_localtax1='".price2num($total_localtax1)."'";
1642  $sql.= ", total_localtax2='".price2num($total_localtax2)."'";
1643  $sql.= ", total_ttc='". price2num($total_ttc)."'";
1644  $sql.= ", fk_product_fournisseur_price=".($fk_fournprice > 0 ? $fk_fournprice : "null");
1645  $sql.= ", buy_price_ht='".price2num($pa_ht)."'";
1646  if ($date_start > 0) { $sql.= ",date_ouverture_prevue='".$this->db->idate($date_start)."'"; }
1647  else { $sql.=",date_ouverture_prevue=null"; }
1648  if ($date_end > 0) { $sql.= ",date_fin_validite='".$this->db->idate($date_end)."'"; }
1649  else { $sql.=",date_fin_validite=null"; }
1650  if ($date_debut_reel > 0) { $sql.= ",date_ouverture='".$this->db->idate($date_debut_reel)."'"; }
1651  else { $sql.=",date_ouverture=null"; }
1652  if ($date_fin_reel > 0) { $sql.= ",date_cloture='".$this->db->idate($date_fin_reel)."'"; }
1653  else { $sql.=",date_cloture=null"; }
1654  $sql .= ", fk_unit=".($fk_unit?"'".$this->db->escape($fk_unit)."'":"null");
1655  $sql .= " WHERE rowid = ".$rowid;
1656 
1657  dol_syslog(get_class($this)."::updateline", LOG_DEBUG);
1658  $result = $this->db->query($sql);
1659  if ($result)
1660  {
1661  $result=$this->update_statut($user);
1662  if ($result >= 0)
1663  {
1664 
1665  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($array_options) && count($array_options)>0) // For avoid conflicts if trigger used
1666  {
1667  $contractline = new ContratLigne($this->db);
1668  $contractline->array_options=$array_options;
1669  $contractline->id= $rowid;
1670  $result=$contractline->insertExtraFields();
1671  if ($result < 0)
1672  {
1673  $this->error[]=$contractline->error;
1674  $error++;
1675  }
1676  }
1677 
1678  if (empty($error)) {
1679  // Call trigger
1680  $result=$this->call_trigger('LINECONTRACT_UPDATE',$user);
1681  if ($result < 0)
1682  {
1683  $this->db->rollback();
1684  return -3;
1685  }
1686  // End call triggers
1687 
1688  $this->db->commit();
1689  return 1;
1690  }
1691  }
1692  else
1693  {
1694  $this->db->rollback();
1695  dol_syslog(get_class($this)."::updateligne Erreur -2");
1696  return -2;
1697  }
1698  }
1699  else
1700  {
1701  $this->db->rollback();
1702  $this->error=$this->db->error();
1703  dol_syslog(get_class($this)."::updateligne Erreur -1");
1704  return -1;
1705  }
1706  }
1707 
1715  function deleteline($idline, User $user)
1716  {
1717  global $conf, $langs;
1718 
1719  $error=0;
1720 
1721  if ($this->statut >= 0)
1722  {
1723 
1724  // Call trigger
1725  $result=$this->call_trigger('LINECONTRACT_DELETE',$user);
1726  if ($result < 0) return -1;
1727  // End call triggers
1728 
1729  $this->db->begin();
1730 
1731  $sql = "DELETE FROM ".MAIN_DB_PREFIX."contratdet";
1732  $sql.= " WHERE rowid=".$idline;
1733 
1734  dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1735  $resql = $this->db->query($sql);
1736  if (! $resql)
1737  {
1738  $this->error="Error ".$this->db->lasterror();
1739  $error++;
1740  }
1741 
1742  if (empty($error)) {
1743  // Remove extrafields
1744  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
1745  {
1746  $contractline = new ContratLigne($this->db);
1747  $contractline->id= $idline;
1748  $result=$contractline->deleteExtraFields();
1749  if ($result < 0)
1750  {
1751  $error++;
1752  $this->error="Error ".get_class($this)."::delete deleteExtraFields error -4 ".$contractline->error;
1753  }
1754  }
1755  }
1756 
1757  if (empty($error)) {
1758  $this->db->commit();
1759  return 1;
1760  } else {
1761  dol_syslog(get_class($this)."::delete ERROR:".$this->error, LOG_ERR);
1762  $this->db->rollback();
1763  return -1;
1764  }
1765  }
1766  else
1767  {
1768  $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
1769  return -2;
1770  }
1771  }
1772 
1773 
1781  function update_statut($user)
1782  {
1783  dol_syslog(__METHOD__ . " is deprecated", LOG_WARNING);
1784 
1785  // If draft, we keep it (should not happen)
1786  if ($this->statut == 0) return 1;
1787 
1788  // Load $this->lines array
1789  // $this->fetch_lines();
1790 
1791 // $newstatut=1;
1792 // foreach($this->lines as $key => $contractline)
1793 // {
1794 // // if ($contractline) // Loop on each service
1795 // }
1796 
1797  return 1;
1798  }
1799 
1800 
1807  function getLibStatut($mode)
1808  {
1809  return $this->LibStatut($this->statut,$mode);
1810  }
1811 
1819  function LibStatut($statut,$mode)
1820  {
1821  global $langs;
1822  $langs->load("contracts");
1823  if ($mode == 0)
1824  {
1825  if ($statut == 0) { return $langs->trans("ContractStatusDraft"); }
1826  if ($statut == 1) { return $langs->trans("ContractStatusValidated"); }
1827  if ($statut == 2) { return $langs->trans("ContractStatusClosed"); }
1828  }
1829  if ($mode == 1)
1830  {
1831  if ($statut == 0) { return $langs->trans("ContractStatusDraft"); }
1832  if ($statut == 1) { return $langs->trans("ContractStatusValidated"); }
1833  if ($statut == 2) { return $langs->trans("ContractStatusClosed"); }
1834  }
1835  if ($mode == 2)
1836  {
1837  if ($statut == 0) { return img_picto($langs->trans('ContractStatusDraft'),'statut0').' '.$langs->trans("ContractStatusDraft"); }
1838  if ($statut == 1) { return img_picto($langs->trans('ContractStatusValidated'),'statut4').' '.$langs->trans("ContractStatusValidated"); }
1839  if ($statut == 2) { return img_picto($langs->trans('ContractStatusClosed'),'statut6').' '.$langs->trans("ContractStatusClosed"); }
1840  }
1841  if ($mode == 3)
1842  {
1843  if ($statut == 0) { return img_picto($langs->trans('ContractStatusDraft'),'statut0'); }
1844  if ($statut == 1) { return img_picto($langs->trans('ContractStatusValidated'),'statut4'); }
1845  if ($statut == 2) { return img_picto($langs->trans('ContractStatusClosed'),'statut6'); }
1846  }
1847  if ($mode == 4 || $mode == 6 || $mode == 7)
1848  {
1849  $line=new ContratLigne($this->db);
1850  $text='';
1851  if ($mode == 4)
1852  {
1853  $text ='<span class="hideonsmartphone">';
1854  $text.=($this->nbofserviceswait+$this->nbofservicesopened+$this->nbofservicesexpired+$this->nbofservicesclosed);
1855  $text.=' '.$langs->trans("Services");
1856  $text.=': &nbsp; &nbsp; ';
1857  $text.='</span>';
1858  }
1859  $text.=($mode == 7?'<div class="inline-block">':'');
1860  $text.=($mode != 7 || $this->nbofserviceswait > 0) ? ($this->nbofserviceswait.$line->LibStatut(0,3,-1,'class="paddingleft2 inline-block valigntextbottom"')).(($mode != 7 || $this->nbofservicesopened || $this->nbofservicesexpired || $this->nbofservicesclosed)?' &nbsp; ':'') : '';
1861  $text.=($mode == 7?'</div><div class="inline-block">':'');
1862  $text.=($mode != 7 || $this->nbofservicesopened > 0) ? ($this->nbofservicesopened.$line->LibStatut(4,3,0,'class="paddingleft2 inline-block valigntextbottom"')).(($mode != 7 || $this->nbofservicesexpired || $this->nbofservicesclosed)?' &nbsp; ':'') : '';
1863  $text.=($mode == 7?'</div><div class="inline-block">':'');
1864  $text.=($mode != 7 || $this->nbofservicesexpired > 0) ? ($this->nbofservicesexpired.$line->LibStatut(4,3,1,'class="paddingleft2 inline-block valigntextbottom"')).(($mode != 7 || $this->nbofservicesclosed)?' &nbsp; ':'') : '';
1865  $text.=($mode == 7?'</div><div class="inline-block">':'');
1866  $text.=($mode != 7 || $this->nbofservicesclosed > 0) ? ($this->nbofservicesclosed.$line->LibStatut(5,3,-1,'class="paddingleft2 inline-block valigntextbottom"')) : '';
1867  $text.=($mode == 7?'</div>':'');
1868  return $text;
1869  }
1870  if ($mode == 5)
1871  {
1872  if ($statut == 0) { return $langs->trans("ContractStatusDraft").' '.img_picto($langs->trans('ContractStatusDraft'),'statut0'); }
1873  if ($statut == 1) { return $langs->trans("ContractStatusValidated").' '.img_picto($langs->trans('ContractStatusValidated'),'statut4'); }
1874  if ($statut == 2) { return $langs->trans("ContractStatusClosed").' '.img_picto($langs->trans('ContractStatusClosed'),'statut6'); }
1875  }
1876  }
1877 
1878 
1888  function getNomUrl($withpicto=0, $maxlength=0, $notooltip=0, $save_lastsearch_value=-1)
1889  {
1890  global $conf, $langs, $user;
1891 
1892  $result='';
1893 
1894  $url = DOL_URL_ROOT.'/contrat/card.php?id='.$this->id;
1895 
1896  //if ($option !== 'nolink')
1897  //{
1898  // Add param to save lastsearch_values or not
1899  $add_save_lastsearch_values=($save_lastsearch_value == 1 ? 1 : 0);
1900  if ($save_lastsearch_value == -1 && preg_match('/list\.php/',$_SERVER["PHP_SELF"])) $add_save_lastsearch_values=1;
1901  if ($add_save_lastsearch_values) $url.='&save_lastsearch_values=1';
1902  //}
1903 
1904  $label = '';
1905 
1906  if ($user->rights->contrat->lire) {
1907  $label = '<u>'.$langs->trans("ShowContract").'</u>';
1908  $label .= '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
1909  $label .= '<br><b>'.$langs->trans('RefCustomer').':</b> '.($this->ref_customer ? $this->ref_customer : $this->ref_client);
1910  $label .= '<br><b>'.$langs->trans('RefSupplier').':</b> '.$this->ref_supplier;
1911  if (!empty($this->total_ht)) {
1912  $label .= '<br><b>'.$langs->trans('AmountHT').':</b> '.price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
1913  }
1914  if (!empty($this->total_tva)) {
1915  $label .= '<br><b>'.$langs->trans('VAT').':</b> '.price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
1916  }
1917  if (!empty($this->total_ttc)) {
1918  $label .= '<br><b>'.$langs->trans('AmountTTC').':</b> '.price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
1919  }
1920  }
1921 
1922  $linkclose='';
1923  if (empty($notooltip) && $user->rights->contrat->lire)
1924  {
1925  if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
1926  {
1927  $label=$langs->trans("ShowOrder");
1928  $linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"';
1929  }
1930  $linkclose.= ' title="'.dol_escape_htmltag($label, 1).'"';
1931  $linkclose.=' class="classfortooltip"';
1932  }
1933 
1934  $linkstart = '<a href="'.$url.'"';
1935  $linkstart.=$linkclose.'>';
1936  $linkend='</a>';
1937 
1938  $result .= $linkstart;
1939  if ($withpicto) $result.=img_object(($notooltip?'':$label), $this->picto, ($notooltip?(($withpicto != 2) ? 'class="paddingright"' : ''):'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip?0:1);
1940  if ($withpicto != 2) $result.= $this->ref;
1941  $result .= $linkend;
1942 
1943  return $result;
1944  }
1945 
1952  function info($id)
1953  {
1954  $sql = "SELECT c.rowid, c.ref, c.datec, c.date_cloture,";
1955  $sql.= " c.tms as date_modification,";
1956  $sql.= " fk_user_author, fk_user_cloture";
1957  $sql.= " FROM ".MAIN_DB_PREFIX."contrat as c";
1958  $sql.= " WHERE c.rowid = ".$id;
1959 
1960  $result=$this->db->query($sql);
1961  if ($result)
1962  {
1963  if ($this->db->num_rows($result))
1964  {
1965  $obj = $this->db->fetch_object($result);
1966 
1967  $this->id = $obj->rowid;
1968 
1969  if ($obj->fk_user_author) {
1970  $cuser = new User($this->db);
1971  $cuser->fetch($obj->fk_user_author);
1972  $this->user_creation = $cuser;
1973  }
1974 
1975  if ($obj->fk_user_cloture) {
1976  $cuser = new User($this->db);
1977  $cuser->fetch($obj->fk_user_cloture);
1978  $this->user_cloture = $cuser;
1979  }
1980  $this->ref = (! $obj->ref) ? $obj->rowid : $obj->ref;
1981  $this->date_creation = $this->db->jdate($obj->datec);
1982  $this->date_modification = $this->db->jdate($obj->date_modification);
1983  $this->date_cloture = $this->db->jdate($obj->date_cloture);
1984  }
1985 
1986  $this->db->free($result);
1987 
1988  }
1989  else
1990  {
1991  dol_print_error($this->db);
1992  }
1993  }
1994 
2001  function array_detail($statut=-1)
2002  {
2003  $tab=array();
2004 
2005  $sql = "SELECT cd.rowid";
2006  $sql.= " FROM ".MAIN_DB_PREFIX."contratdet as cd";
2007  $sql.= " WHERE fk_contrat =".$this->id;
2008  if ($statut >= 0) $sql.= " AND statut = '$statut'";
2009 
2010  dol_syslog(get_class($this)."::array_detail()", LOG_DEBUG);
2011  $resql=$this->db->query($sql);
2012  if ($resql)
2013  {
2014  $num=$this->db->num_rows($resql);
2015  $i=0;
2016  while ($i < $num)
2017  {
2018  $obj = $this->db->fetch_object($resql);
2019  $tab[$i]=$obj->rowid;
2020  $i++;
2021  }
2022  return $tab;
2023  }
2024  else
2025  {
2026  $this->error=$this->db->error();
2027  return -1;
2028  }
2029  }
2030 
2037  function getListOfContracts($option='all')
2038  {
2039  $tab=array();
2040 
2041  $sql = "SELECT c.rowid, c.ref";
2042  $sql.= " FROM ".MAIN_DB_PREFIX."contrat as c";
2043  $sql.= " WHERE fk_soc =".$this->socid;
2044  if ($option == 'others') $sql.= " AND c.rowid != ".$this->id;
2045 
2046  dol_syslog(get_class($this)."::getOtherContracts()", LOG_DEBUG);
2047  $resql=$this->db->query($sql);
2048  if ($resql)
2049  {
2050  $num=$this->db->num_rows($resql);
2051  $i=0;
2052  while ($i < $num)
2053  {
2054  $obj = $this->db->fetch_object($resql);
2055  $contrat=new Contrat($this->db);
2056  $contrat->fetch($obj->rowid);
2057  $tab[]=$contrat;
2058  $i++;
2059  }
2060  return $tab;
2061  }
2062  else
2063  {
2064  $this->error=$this->db->error();
2065  return -1;
2066  }
2067  }
2068 
2069 
2077  function load_board($user,$mode)
2078  {
2079  global $conf, $langs;
2080 
2081  $this->from = " FROM ".MAIN_DB_PREFIX."contrat as c";
2082  $this->from.= ", ".MAIN_DB_PREFIX."contratdet as cd";
2083  $this->from.= ", ".MAIN_DB_PREFIX."societe as s";
2084  if (!$user->rights->societe->client->voir && !$user->societe_id) $this->from.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
2085 
2086  if ($mode == 'inactives')
2087  {
2088  $sql = "SELECT cd.rowid, cd.date_ouverture_prevue as datefin";
2089  $sql.= $this->from;
2090  $sql.= " WHERE c.statut = 1";
2091  $sql.= " AND c.rowid = cd.fk_contrat";
2092  $sql.= " AND cd.statut = 0";
2093  }
2094  if ($mode == 'expired')
2095  {
2096  $sql = "SELECT cd.rowid, cd.date_fin_validite as datefin";
2097  $sql.= $this->from;
2098  $sql.= " WHERE c.statut = 1";
2099  $sql.= " AND c.rowid = cd.fk_contrat";
2100  $sql.= " AND cd.statut = 4";
2101  $sql.= " AND cd.date_fin_validite < '".$this->db->idate(time())."'";
2102  }
2103  $sql.= " AND c.fk_soc = s.rowid";
2104  $sql.= " AND c.entity = ".$conf->entity;
2105  if ($user->societe_id) $sql.=" AND c.fk_soc = ".$user->societe_id;
2106  if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " AND c.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id;
2107  $resql=$this->db->query($sql);
2108  if ($resql)
2109  {
2110  $langs->load("contracts");
2111  $now=dol_now();
2112 
2113  if ($mode == 'inactives') {
2114  $warning_delay = $conf->contrat->services->inactifs->warning_delay;
2115  $label = $langs->trans("BoardNotActivatedServices");
2116  $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&amp;leftmenu=contracts&amp;mode=0';
2117  } else {
2118  $warning_delay = $conf->contrat->services->expires->warning_delay;
2119  $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&amp;leftmenu=contracts&amp;mode=4&amp;filter=expired';
2120  $label = $langs->trans("BoardRunningServices");
2121  }
2122 
2123  $response = new WorkboardResponse();
2124  $response->warning_delay = $warning_delay/60/60/24;
2125  $response->label = $label;
2126  $response->url = $url;
2127  $response->img = img_object('',"contract");
2128 
2129  while ($obj=$this->db->fetch_object($resql))
2130  {
2131  $response->nbtodo++;
2132 
2133  if ($obj->datefin && $this->db->jdate($obj->datefin) < ($now - $warning_delay)) {
2134  $response->nbtodolate++;
2135  }
2136  }
2137 
2138  return $response;
2139  }
2140  else
2141  {
2142  dol_print_error($this->db);
2143  $this->error=$this->db->error();
2144  return -1;
2145  }
2146  }
2147 
2153  function load_state_board()
2154  {
2155  global $conf, $user;
2156 
2157  $this->nb=array();
2158  $clause = "WHERE";
2159 
2160  $sql = "SELECT count(c.rowid) as nb";
2161  $sql.= " FROM ".MAIN_DB_PREFIX."contrat as c";
2162  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON c.fk_soc = s.rowid";
2163  if (!$user->rights->societe->client->voir && !$user->societe_id)
2164  {
2165  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON s.rowid = sc.fk_soc";
2166  $sql.= " WHERE sc.fk_user = " .$user->id;
2167  $clause = "AND";
2168  }
2169  $sql.= " ".$clause." c.entity = ".$conf->entity;
2170 
2171  $resql=$this->db->query($sql);
2172  if ($resql)
2173  {
2174  while ($obj=$this->db->fetch_object($resql))
2175  {
2176  $this->nb["Contracts"]=$obj->nb;
2177  }
2178  $this->db->free($resql);
2179  return 1;
2180  }
2181  else
2182  {
2183  dol_print_error($this->db);
2184  $this->error=$this->db->error();
2185  return -1;
2186  }
2187  }
2188 
2189 
2190  /* gestion des contacts d'un contrat */
2191 
2198  {
2199  return $this->getIdContact('external','BILLING');
2200  }
2201 
2208  {
2209  return $this->getIdContact('external','SERVICE');
2210  }
2211 
2212 
2220  function initAsSpecimen()
2221  {
2222  global $user,$langs,$conf;
2223 
2224  // Load array of products prodids
2225  $num_prods = 0;
2226  $prodids = array();
2227  $sql = "SELECT rowid";
2228  $sql.= " FROM ".MAIN_DB_PREFIX."product";
2229  $sql.= " WHERE entity IN (".getEntity('product').")";
2230  $sql.= " AND tosell = 1";
2231  $resql = $this->db->query($sql);
2232  if ($resql)
2233  {
2234  $num_prods = $this->db->num_rows($resql);
2235  $i = 0;
2236  while ($i < $num_prods)
2237  {
2238  $i++;
2239  $row = $this->db->fetch_row($resql);
2240  $prodids[$i] = $row[0];
2241  }
2242  }
2243 
2244  // Initialise parametres
2245  $this->id=0;
2246  $this->specimen=1;
2247 
2248  $this->ref = 'SPECIMEN';
2249  $this->ref_customer = 'SPECIMENCUST';
2250  $this->ref_supplier = 'SPECIMENSUPP';
2251  $this->socid = 1;
2252  $this->statut= 0;
2253  $this->date_creation = (dol_now() - 3600 * 24 * 7);
2254  $this->date_contrat = dol_now();
2255  $this->commercial_signature_id = 1;
2256  $this->commercial_suivi_id = 1;
2257  $this->note_private='This is a comment (private)';
2258  $this->note_public='This is a comment (public)';
2259  $this->fk_projet = 0;
2260  // Lines
2261  $nbp = 5;
2262  $xnbp = 0;
2263  while ($xnbp < $nbp)
2264  {
2265  $line=new ContratLigne($this->db);
2266  $line->qty=1;
2267  $line->subprice=100;
2268  $line->price=100;
2269  $line->tva_tx=19.6;
2270  $line->remise_percent=10;
2271  $line->total_ht=90;
2272  $line->total_ttc=107.64; // 90 * 1.196
2273  $line->total_tva=17.64;
2274  $line->date_start = dol_now() - 500000;
2275  $line->date_start_real = dol_now() - 200000;
2276  $line->date_end = dol_now() + 500000;
2277  $line->date_end_real = dol_now() - 100000;
2278  if ($num_prods > 0)
2279  {
2280  $prodid = mt_rand(1, $num_prods);
2281  $line->fk_product=$prodids[$prodid];
2282  }
2283  $this->lines[$xnbp]=$line;
2284  $xnbp++;
2285  }
2286  }
2287 
2293  function getLinesArray()
2294  {
2295  return $this->fetch_lines();
2296  }
2297 
2298 
2309  public function generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
2310  {
2311  global $conf,$langs;
2312 
2313  $langs->load("contracts");
2314 
2315  if (! dol_strlen($modele)) {
2316 
2317  $modele = 'strato';
2318 
2319  if ($this->modelpdf) {
2320  $modele = $this->modelpdf;
2321  } elseif (! empty($conf->global->CONTRACT_ADDON_PDF)) {
2322  $modele = $conf->global->CONTRACT_ADDON_PDF;
2323  }
2324  }
2325 
2326  $modelpath = "core/modules/contract/doc/";
2327 
2328  return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
2329  }
2330 
2339  public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
2340  {
2341  $tables = array(
2342  'contrat'
2343  );
2344 
2345  return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
2346  }
2347 
2355  function createFromClone($socid = 0, $notrigger=0) {
2356  global $db, $user, $langs, $conf, $hookmanager;
2357 
2358  dol_include_once('/projet/class/project.class.php');
2359 
2360  $this->context['createfromclone'] = 'createfromclone';
2361 
2362  $error = 0;
2363 
2364  $this->fetch($this->id);
2365  // Load dest object
2366  $clonedObj = clone $this;
2367  $clonedObj->socid = $socid;
2368 
2369  $this->db->begin();
2370 
2371  $objsoc = new Societe($this->db);
2372 
2373  $objsoc->fetch($clonedObj->socid);
2374 
2375  // $clonedObj->id=0;
2376  $clonedObj->statut = 0;
2377 
2378  if (empty($conf->global->CONTRACT_ADDON) || ! is_readable(DOL_DOCUMENT_ROOT . "/core/modules/contract/" . $conf->global->CONTRACT_ADDON . ".php")) {
2379  $this->error = 'ErrorSetupNotComplete';
2380  dol_syslog($this->error);
2381  return - 1;
2382  }
2383 
2384  // Set ref
2385  require_once DOL_DOCUMENT_ROOT . "/core/modules/contract/" . $conf->global->CONTRACT_ADDON . '.php';
2386  $obj = $conf->global->CONTRACT_ADDON;
2387  $modContract = new $obj();
2388  $clonedObj->ref = $modContract->getNextValue($objsoc, $clonedObj);
2389 
2390  // get extrafields so they will be clone
2391  foreach ( $this->lines as $line ) {
2392  $line->fetch_optionals($line->rowid);
2393  }
2394 
2395  // Create clone
2396  $result = $clonedObj->create($user);
2397  if ($result < 0) {
2398  $error ++;
2399  $this->error = $clonedObj->error;
2400  $this->errors[] = $clonedObj->error;
2401  } else {
2402  // copy external contacts if same company
2403  if ($this->socid == $clonedObj->socid) {
2404  if ($clonedObj->copy_linked_contact($this, 'external') < 0) {
2405  $error++;
2406  }
2407  }
2408  }
2409 
2410  if (! $error) {
2411  foreach ( $this->lines as $line ) {
2412  $result = $clonedObj->addline($line->desc, $line->subprice, $line->qty, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, $line->fk_product, $line->remise_percent, $line->date_ouverture, $line->date_cloture, 'HT', 0, $line->info_bits, $line->fk_fournprice, $line->pa_ht, $line->array_options, $line->fk_unit);
2413  if ($result < 0) {
2414  $error ++;
2415  $this->error = $clonedObj->error;
2416  $this->errors[] = $clonedObj->error;
2417  }
2418  }
2419  }
2420 
2421  if (! $error) {
2422  // Hook of thirdparty module
2423  if (is_object($hookmanager)) {
2424  $parameters = array (
2425  'objFrom' => $this,
2426  'clonedObj' => $clonedObj
2427  );
2428  $action = '';
2429  $reshook = $hookmanager->executeHooks('createFrom', $parameters, $clonedObj, $action); // Note that $action and $object may have been modified by some hooks
2430  if ($reshook < 0)
2431  $error ++;
2432  }
2433 
2434  }
2435 
2436  if (! $notrigger && empty($error))
2437  {
2438  // Call trigger
2439  $clonedObj->old_copy=$this;
2440  $result = $clonedObj->call_trigger('CONTRACT_CLONE', $user);
2441  if ($result < 0) {
2442  $error ++;
2443  }
2444  // End call triggers
2445  }
2446 
2447  unset($this->context['createfromclone']);
2448 
2449  // End
2450  if (! $error) {
2451  $this->db->commit();
2452  return $clonedObj->id;
2453  } else {
2454  $this->db->rollback();
2455  return - 1;
2456  }
2457  }
2458 }
2459 
2460 
2465 {
2466  public $element='contratdet';
2467  public $table_element='contratdet';
2468 
2469  var $id;
2470  var $ref;
2471  var $tms;
2472 
2473  var $fk_contrat;
2474  var $fk_product;
2475  var $statut; // 0 inactive, 4 active, 5 closed
2476  var $type; // 0 for product, 1 for service
2477  var $label;
2483  public $libelle;
2484 
2485  var $description;
2486 
2487  var $product_ref;
2488  var $product_label;
2489 
2490  var $date_commande;
2491 
2492  var $date_start; // date start planned
2493  var $date_start_real; // date start real
2494  var $date_end; // date end planned
2495  var $date_end_real; // date end real
2496  // For backward compatibility
2497  var $date_ouverture_prevue; // date start planned
2498  var $date_ouverture; // date start real
2499  var $date_fin_validite; // date end planned
2500  var $date_cloture; // date end real
2501  var $tva_tx;
2502  var $localtax1_tx;
2503  var $localtax2_tx;
2504  var $localtax1_type; // Local tax 1 type
2505  var $localtax2_type; // Local tax 2 type
2506  var $qty;
2507  var $remise_percent;
2508  var $remise;
2509  var $fk_remise_except;
2510 
2511  var $subprice; // Unit price HT
2512 
2518  public $price;
2519 
2520  var $price_ht;
2521 
2522  var $total_ht;
2523  var $total_tva;
2524  var $total_localtax1;
2525  var $total_localtax2;
2526  var $total_ttc;
2527 
2528  var $fk_fournprice;
2529  var $pa_ht;
2530 
2531  var $info_bits;
2532  var $fk_user_author;
2533  var $fk_user_ouverture;
2534  var $fk_user_cloture;
2535  var $commentaire;
2536 
2537 
2543  function __construct($db)
2544  {
2545  $this->db = $db;
2546  }
2547 
2548 
2555  function getLibStatut($mode)
2556  {
2557  return $this->LibStatut($this->statut,$mode,((! empty($this->date_fin_validite))?($this->date_fin_validite < dol_now()?1:0):-1));
2558  }
2559 
2569  function LibStatut($statut,$mode,$expired=-1,$moreatt='')
2570  {
2571  global $langs;
2572  $langs->load("contracts");
2573  if ($mode == 0)
2574  {
2575  if ($statut == 0) { return $langs->trans("ServiceStatusInitial"); }
2576  if ($statut == 4 && $expired == -1) { return $langs->trans("ServiceStatusRunning"); }
2577  if ($statut == 4 && $expired == 0) { return $langs->trans("ServiceStatusNotLate"); }
2578  if ($statut == 4 && $expired == 1) { return $langs->trans("ServiceStatusLate"); }
2579  if ($statut == 5) { return $langs->trans("ServiceStatusClosed"); }
2580  }
2581  if ($mode == 1)
2582  {
2583  if ($statut == 0) { return $langs->trans("ServiceStatusInitial"); }
2584  if ($statut == 4 && $expired == -1) { return $langs->trans("ServiceStatusRunning"); }
2585  if ($statut == 4 && $expired == 0) { return $langs->trans("ServiceStatusNotLateShort"); }
2586  if ($statut == 4 && $expired == 1) { return $langs->trans("ServiceStatusLateShort"); }
2587  if ($statut == 5) { return $langs->trans("ServiceStatusClosed"); }
2588  }
2589  if ($mode == 2)
2590  {
2591  if ($statut == 0) { return img_picto($langs->trans('ServiceStatusInitial'),'statut0').' '.$langs->trans("ServiceStatusInitial"); }
2592  if ($statut == 4 && $expired == -1) { return img_picto($langs->trans('ServiceStatusRunning'),'statut4').' '.$langs->trans("ServiceStatusRunning"); }
2593  if ($statut == 4 && $expired == 0) { return img_picto($langs->trans('ServiceStatusNotLate'),'statut4').' '.$langs->trans("ServiceStatusNotLateShort"); }
2594  if ($statut == 4 && $expired == 1) { return img_picto($langs->trans('ServiceStatusLate'),'statut3').' '.$langs->trans("ServiceStatusLateShort"); }
2595  if ($statut == 5) { return img_picto($langs->trans('ServiceStatusClosed'),'statut6') .' '.$langs->trans("ServiceStatusClosed"); }
2596  }
2597  if ($mode == 3)
2598  {
2599  if ($statut == 0) { return img_picto($langs->trans('ServiceStatusInitial'),'statut0',$moreatt); }
2600  if ($statut == 4 && $expired == -1) { return img_picto($langs->trans('ServiceStatusRunning'),'statut4',$moreatt); }
2601  if ($statut == 4 && $expired == 0) { return img_picto($langs->trans('ServiceStatusNotLate'),'statut4',$moreatt); }
2602  if ($statut == 4 && $expired == 1) { return img_picto($langs->trans('ServiceStatusLate'),'statut3',$moreatt); }
2603  if ($statut == 5) { return img_picto($langs->trans('ServiceStatusClosed'),'statut6',$moreatt); }
2604  }
2605  if ($mode == 4)
2606  {
2607  if ($statut == 0) { return img_picto($langs->trans('ServiceStatusInitial'),'statut0').' '.$langs->trans("ServiceStatusInitial"); }
2608  if ($statut == 4 && $expired == -1) { return img_picto($langs->trans('ServiceStatusRunning'),'statut4').' '.$langs->trans("ServiceStatusRunning"); }
2609  if ($statut == 4 && $expired == 0) { return img_picto($langs->trans('ServiceStatusNotLate'),'statut4').' '.$langs->trans("ServiceStatusNotLate"); }
2610  if ($statut == 4 && $expired == 1) { return img_picto($langs->trans('ServiceStatusLate'),'statut3').' '.$langs->trans("ServiceStatusLate"); }
2611  if ($statut == 5) { return img_picto($langs->trans('ServiceStatusClosed'),'statut6') .' '.$langs->trans("ServiceStatusClosed"); }
2612  }
2613  if ($mode == 5)
2614  {
2615  if ($statut == 0) { return $langs->trans("ServiceStatusInitial").' '.img_picto($langs->trans('ServiceStatusInitial'),'statut0'); }
2616  if ($statut == 4 && $expired == -1) { return $langs->trans("ServiceStatusRunning").' '.img_picto($langs->trans('ServiceStatusRunning'),'statut4'); }
2617  if ($statut == 4 && $expired == 0) { return $langs->trans("ServiceStatusNotLateShort").' '.img_picto($langs->trans('ServiceStatusNotLateShort'),'statut4'); }
2618  if ($statut == 4 && $expired == 1) { return $langs->trans("ServiceStatusLateShort").' '.img_picto($langs->trans('ServiceStatusLate'),'statut3'); }
2619  if ($statut == 5) { return $langs->trans("ServiceStatusClosed").' '.img_picto($langs->trans('ServiceStatusClosed'),'statut6'); }
2620  }
2621  }
2622 
2630  function getNomUrl($withpicto=0,$maxlength=0)
2631  {
2632  global $langs;
2633 
2634  $result='';
2635  $label=$langs->trans("ShowContractOfService").': '.$this->label;
2636  if (empty($label)) $label=$this->description;
2637 
2638  $link = '<a href="'.DOL_URL_ROOT.'/contrat/card.php?id='.$this->fk_contrat.'" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip">';
2639  $linkend='</a>';
2640 
2641  $picto='service';
2642  if ($this->type == 0) $picto='product';
2643 
2644  if ($withpicto) $result.=($link.img_object($label, $picto, 'class="classfortooltip"').$linkend);
2645  if ($withpicto && $withpicto != 2) $result.=' ';
2646  if ($withpicto != 2) $result.=$link.($this->product_ref?$this->product_ref.' ':'').($this->label?$this->label:$this->description).$linkend;
2647  return $result;
2648  }
2649 
2657  function fetch($id, $ref='')
2658  {
2659 
2660  // Check parameters
2661  if (empty($id) && empty($ref)) return -1;
2662 
2663  $sql = "SELECT";
2664  $sql.= " t.rowid,";
2665 
2666  $sql.= " t.tms,";
2667  $sql.= " t.fk_contrat,";
2668  $sql.= " t.fk_product,";
2669  $sql.= " t.statut,";
2670  $sql.= " t.label,"; // This field is not used. Only label of product
2671  $sql.= " p.ref as product_ref,";
2672  $sql.= " p.label as product_label,";
2673  $sql.= " p.description as product_desc,";
2674  $sql.= " p.fk_product_type as product_type,";
2675  $sql.= " t.description,";
2676  $sql.= " t.date_commande,";
2677  $sql.= " t.date_ouverture_prevue as date_ouverture_prevue,";
2678  $sql.= " t.date_ouverture as date_ouverture,";
2679  $sql.= " t.date_fin_validite as date_fin_validite,";
2680  $sql.= " t.date_cloture as date_cloture,";
2681  $sql.= " t.tva_tx,";
2682  $sql.= " t.vat_src_code,";
2683  $sql.= " t.localtax1_tx,";
2684  $sql.= " t.localtax2_tx,";
2685  $sql.= " t.localtax1_type,";
2686  $sql.= " t.localtax2_type,";
2687  $sql.= " t.qty,";
2688  $sql.= " t.remise_percent,";
2689  $sql.= " t.remise,";
2690  $sql.= " t.fk_remise_except,";
2691  $sql.= " t.subprice,";
2692  $sql.= " t.price_ht,";
2693  $sql.= " t.total_ht,";
2694  $sql.= " t.total_tva,";
2695  $sql.= " t.total_localtax1,";
2696  $sql.= " t.total_localtax2,";
2697  $sql.= " t.total_ttc,";
2698  $sql.= " t.fk_product_fournisseur_price as fk_fournprice,";
2699  $sql.= " t.buy_price_ht as pa_ht,";
2700  $sql.= " t.info_bits,";
2701  $sql.= " t.fk_user_author,";
2702  $sql.= " t.fk_user_ouverture,";
2703  $sql.= " t.fk_user_cloture,";
2704  $sql.= " t.commentaire,";
2705  $sql.= " t.fk_unit";
2706  $sql.= " FROM ".MAIN_DB_PREFIX."contratdet as t LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = t.fk_product";
2707  if ($id) $sql.= " WHERE t.rowid = ".$id;
2708  if ($ref) $sql.= " WHERE t.rowid = '".$this->db->escape($ref)."'";
2709 
2710  dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
2711  $resql=$this->db->query($sql);
2712  if ($resql)
2713  {
2714  if ($this->db->num_rows($resql))
2715  {
2716  $obj = $this->db->fetch_object($resql);
2717 
2718  $this->id = $obj->rowid;
2719  $this->ref = $obj->rowid;
2720 
2721  $this->tms = $this->db->jdate($obj->tms);
2722  $this->fk_contrat = $obj->fk_contrat;
2723  $this->fk_product = $obj->fk_product;
2724  $this->statut = $obj->statut;
2725  $this->product_ref = $obj->product_ref;
2726  $this->product_label = $obj->product_label;
2727  $this->product_description = $obj->product_description;
2728  $this->product_type = $obj->product_type;
2729  $this->label = $obj->label; // deprecated. We do not use this field. Only ref and label of product, and description of contract line
2730  $this->description = $obj->description;
2731  $this->date_commande = $this->db->jdate($obj->date_commande);
2732 
2733  $this->date_start = $this->db->jdate($obj->date_ouverture_prevue);
2734  $this->date_start_real = $this->db->jdate($obj->date_ouverture);
2735  $this->date_end = $this->db->jdate($obj->date_fin_validite);
2736  $this->date_end_real = $this->db->jdate($obj->date_cloture);
2737  // For backward compatibility
2738  $this->date_ouverture_prevue = $this->db->jdate($obj->date_ouverture_prevue);
2739  $this->date_ouverture = $this->db->jdate($obj->date_ouverture);
2740  $this->date_fin_validite = $this->db->jdate($obj->date_fin_validite);
2741  $this->date_cloture = $this->db->jdate($obj->date_cloture);
2742 
2743  $this->tva_tx = $obj->tva_tx;
2744  $this->vat_src_code = $obj->vat_src_code;
2745  $this->localtax1_tx = $obj->localtax1_tx;
2746  $this->localtax2_tx = $obj->localtax2_tx;
2747  $this->localtax1_type = $obj->localtax1_type;
2748  $this->localtax2_type = $obj->localtax2_type;
2749  $this->qty = $obj->qty;
2750  $this->remise_percent = $obj->remise_percent;
2751  $this->remise = $obj->remise;
2752  $this->fk_remise_except = $obj->fk_remise_except;
2753  $this->subprice = $obj->subprice;
2754  $this->price_ht = $obj->price_ht;
2755  $this->total_ht = $obj->total_ht;
2756  $this->total_tva = $obj->total_tva;
2757  $this->total_localtax1 = $obj->total_localtax1;
2758  $this->total_localtax2 = $obj->total_localtax2;
2759  $this->total_ttc = $obj->total_ttc;
2760  $this->info_bits = $obj->info_bits;
2761  $this->fk_user_author = $obj->fk_user_author;
2762  $this->fk_user_ouverture = $obj->fk_user_ouverture;
2763  $this->fk_user_cloture = $obj->fk_user_cloture;
2764  $this->commentaire = $obj->commentaire;
2765  $this->fk_fournprice = $obj->fk_fournprice;
2766  $marginInfos = getMarginInfos($obj->subprice, $obj->remise_percent, $obj->tva_tx, $obj->localtax1_tx, $obj->localtax2_tx, $this->fk_fournprice, $obj->pa_ht);
2767  $this->pa_ht = $marginInfos[0];
2768  $this->fk_unit = $obj->fk_unit;
2769 
2770  }
2771  $this->db->free($resql);
2772 
2773  return 1;
2774  }
2775  else
2776  {
2777  $this->error="Error ".$this->db->lasterror();
2778  return -1;
2779  }
2780  }
2781 
2782 
2790  function update($user, $notrigger=0)
2791  {
2792  global $conf, $langs, $mysoc;
2793 
2794  $error=0;
2795 
2796  // Clean parameters
2797  $this->fk_contrat=trim($this->fk_contrat);
2798  $this->fk_product=trim($this->fk_product);
2799  $this->statut=(int) $this->statut;
2800  $this->label=trim($this->label);
2801  $this->description=trim($this->description);
2802  $this->vat_src_code=trim($this->vat_src_code);
2803  $this->tva_tx=trim($this->tva_tx);
2804  $this->localtax1_tx=trim($this->localtax1_tx);
2805  $this->localtax2_tx=trim($this->localtax2_tx);
2806  $this->qty=trim($this->qty);
2807  $this->remise_percent=trim($this->remise_percent);
2808  $this->remise=trim($this->remise);
2809  $this->fk_remise_except=trim($this->fk_remise_except);
2810  $this->subprice=price2num($this->subprice);
2811  $this->price_ht=price2num($this->price_ht);
2812  $this->total_ht=trim($this->total_ht);
2813  $this->total_tva=trim($this->total_tva);
2814  $this->total_localtax1=trim($this->total_localtax1);
2815  $this->total_localtax2=trim($this->total_localtax2);
2816  $this->total_ttc=trim($this->total_ttc);
2817  $this->info_bits=trim($this->info_bits);
2818  $this->fk_user_author=trim($this->fk_user_author);
2819  $this->fk_user_ouverture=trim($this->fk_user_ouverture);
2820  $this->fk_user_cloture=trim($this->fk_user_cloture);
2821  $this->commentaire=trim($this->commentaire);
2822  //if (empty($this->subprice)) $this->subprice = 0;
2823  if (empty($this->price_ht)) $this->price_ht = 0;
2824  if (empty($this->total_ht)) $this->total_ht = 0;
2825  if (empty($this->total_tva)) $this->total_tva = 0;
2826  if (empty($this->total_ttc)) $this->total_ttc = 0;
2827  if (empty($this->localtax1_tx)) $this->localtax1_tx = 0;
2828  if (empty($this->localtax2_tx)) $this->localtax2_tx = 0;
2829  if (empty($this->remise_percent)) $this->remise_percent = 0;
2830  // For backward compatibility
2831  if (empty($this->date_start)) $this->date_start=$this->date_ouverture_prevue;
2832  if (empty($this->date_start_real)) $this->date_start=$this->date_ouverture;
2833  if (empty($this->date_end)) $this->date_start=$this->date_fin_validite;
2834  if (empty($this->date_end_real)) $this->date_start=$this->date_cloture;
2835 
2836 
2837  // Check parameters
2838  // Put here code to add control on parameters values
2839 
2840  // Calcul du total TTC et de la TVA pour la ligne a partir de
2841  // qty, pu, remise_percent et txtva
2842  // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
2843  // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
2844  $localtaxes_type = getLocalTaxesFromRate($this->txtva, 0, $this->societe, $mysoc);
2845 
2846  $tabprice=calcul_price_total($this->qty, $this->price_ht, $this->remise_percent, $this->tva_tx, $this->localtax1_tx, $this->localtax2_tx, 0, 'HT', 0, 1, $mysoc, $localtaxes_type);
2847  $this->total_ht = $tabprice[0];
2848  $this->total_tva = $tabprice[1];
2849  $this->total_ttc = $tabprice[2];
2850  $this->total_localtax1= $tabprice[9];
2851  $this->total_localtax2= $tabprice[10];
2852 
2853  if (empty($this->pa_ht)) $this->pa_ht=0;
2854 
2855  // if buy price not defined, define buyprice as configured in margin admin
2856  if ($this->pa_ht == 0)
2857  {
2858  if (($result = $this->defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product)) < 0)
2859  {
2860  return $result;
2861  }
2862  else
2863  {
2864  $this->pa_ht = $result;
2865  }
2866  }
2867 
2868 
2869  $this->db->begin();
2870 
2871  // Update request
2872  $sql = "UPDATE ".MAIN_DB_PREFIX."contratdet SET";
2873  $sql.= " fk_contrat=".$this->fk_contrat.",";
2874  $sql.= " fk_product=".($this->fk_product?"'".$this->db->escape($this->fk_product)."'":'null').",";
2875  $sql.= " statut=".$this->statut.",";
2876  $sql.= " label='".$this->db->escape($this->label)."',";
2877  $sql.= " description='".$this->db->escape($this->description)."',";
2878  $sql.= " date_commande=".($this->date_commande!=''?"'".$this->db->idate($this->date_commande)."'":"null").",";
2879  $sql.= " date_ouverture_prevue=".($this->date_ouverture_prevue!=''?"'".$this->db->idate($this->date_ouverture_prevue)."'":"null").",";
2880  $sql.= " date_ouverture=".($this->date_ouverture!=''?"'".$this->db->idate($this->date_ouverture)."'":"null").",";
2881  $sql.= " date_fin_validite=".($this->date_fin_validite!=''?"'".$this->db->idate($this->date_fin_validite)."'":"null").",";
2882  $sql.= " date_cloture=".($this->date_cloture!=''?"'".$this->db->idate($this->date_cloture)."'":"null").",";
2883  $sql.= " vat_src_code='".$this->db->escape($this->vat_src_code)."',";
2884  $sql.= " tva_tx=".price2num($this->tva_tx).",";
2885  $sql.= " localtax1_tx=".price2num($this->localtax1_tx).",";
2886  $sql.= " localtax2_tx=".price2num($this->localtax2_tx).",";
2887  $sql.= " qty=".price2num($this->qty).",";
2888  $sql.= " remise_percent=".price2num($this->remise_percent).",";
2889  $sql.= " remise=".($this->remise?price2num($this->remise):"null").",";
2890  $sql.= " fk_remise_except=".($this->fk_remise_except > 0?$this->fk_remise_except:"null").",";
2891  $sql.= " subprice=".($this->subprice != '' ? $this->subprice : "null").",";
2892  $sql.= " price_ht=".($this->price_ht != '' ? $this->price_ht : "null").",";
2893  $sql.= " total_ht=".$this->total_ht.",";
2894  $sql.= " total_tva=".$this->total_tva.",";
2895  $sql.= " total_localtax1=".$this->total_localtax1.",";
2896  $sql.= " total_localtax2=".$this->total_localtax2.",";
2897  $sql.= " total_ttc=".$this->total_ttc.",";
2898  $sql.= " fk_product_fournisseur_price=".(!empty($this->fk_fournprice)?$this->fk_fournprice:"NULL").",";
2899  $sql.= " buy_price_ht='".price2num($this->pa_ht)."',";
2900  $sql.= " info_bits='".$this->db->escape($this->info_bits)."',";
2901  $sql.= " fk_user_author=".($this->fk_user_author >= 0?$this->fk_user_author:"NULL").",";
2902  $sql.= " fk_user_ouverture=".($this->fk_user_ouverture > 0?$this->fk_user_ouverture:"NULL").",";
2903  $sql.= " fk_user_cloture=".($this->fk_user_cloture > 0?$this->fk_user_cloture:"NULL").",";
2904  $sql.= " commentaire='".$this->db->escape($this->commentaire)."',";
2905  $sql.= " fk_unit=".(!$this->fk_unit ? 'NULL' : $this->fk_unit);
2906  $sql.= " WHERE rowid=".$this->id;
2907 
2908  dol_syslog(get_class($this)."::update", LOG_DEBUG);
2909  $resql = $this->db->query($sql);
2910  if ($resql)
2911  {
2912  $contrat=new Contrat($this->db);
2913  $contrat->fetch($this->fk_contrat);
2914  $result=$contrat->update_statut($user);
2915  }
2916  else
2917  {
2918  $this->error="Error ".$this->db->lasterror();
2919  $error++;
2920  //return -1;
2921  }
2922 
2923  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($this->array_options) && count($this->array_options)>0) // For avoid conflicts if trigger used
2924  {
2925 
2926  $result=$this->insertExtraFields();
2927  if ($result < 0)
2928  {
2929  $error++;
2930  }
2931  }
2932 
2933  if (empty($error)) {
2934  if (! $notrigger)
2935  {
2936  // Call trigger
2937  $result=$this->call_trigger('LINECONTRACT_UPDATE',$user);
2938  if ($result < 0) { $error++; $this->db->rollback(); return -1; }
2939  // End call triggers
2940  }
2941  }
2942 
2943  if (empty($error)) {
2944  $this->db->commit();
2945  return 1;
2946  } else {
2947  $this->db->rollback();
2948  $this->errors[]=$this->error;
2949  return -1;
2950  }
2951  }
2952 
2953 
2960  function update_total()
2961  {
2962  $this->db->begin();
2963 
2964  // Mise a jour ligne en base
2965  $sql = "UPDATE ".MAIN_DB_PREFIX."contratdet SET";
2966  $sql.= " total_ht=".price2num($this->total_ht,'MT')."";
2967  $sql.= ",total_tva=".price2num($this->total_tva,'MT')."";
2968  $sql.= ",total_localtax1=".price2num($this->total_localtax1,'MT')."";
2969  $sql.= ",total_localtax2=".price2num($this->total_localtax2,'MT')."";
2970  $sql.= ",total_ttc=".price2num($this->total_ttc,'MT')."";
2971  $sql.= " WHERE rowid = ".$this->id;
2972 
2973  dol_syslog(get_class($this)."::update_total", LOG_DEBUG);
2974 
2975  $resql=$this->db->query($sql);
2976  if ($resql)
2977  {
2978  $this->db->commit();
2979  return 1;
2980  }
2981  else
2982  {
2983  $this->error=$this->db->error();
2984  $this->db->rollback();
2985  return -2;
2986  }
2987  }
2988 
2989 
2996  public function insert($notrigger = 0)
2997  {
2998  global $user;
2999 
3000  // Insertion dans la base
3001  $sql = "INSERT INTO ".MAIN_DB_PREFIX."contratdet";
3002  $sql.= " (fk_contrat, label, description, fk_product, qty, vat_src_code, tva_tx,";
3003  $sql.= " localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, remise_percent, subprice,";
3004  $sql.= " total_ht, total_tva, total_localtax1, total_localtax2, total_ttc,";
3005  $sql.= " info_bits,";
3006  $sql.= " price_ht, remise, fk_product_fournisseur_price, buy_price_ht";
3007  if ($this->date_ouverture_prevue > 0) { $sql.= ",date_ouverture_prevue"; }
3008  if ($this->date_fin_validite > 0) { $sql.= ",date_fin_validite"; }
3009  $sql.= ") VALUES ($this->fk_contrat, '', '" . $this->db->escape($this->description) . "',";
3010  $sql.= ($this->fk_product>0 ? $this->fk_product : "null").",";
3011  $sql.= " '".$this->db->escape($this->qty)."',";
3012  $sql.= " '".$this->db->escape($this->vat_src_code)."',";
3013  $sql.= " '".$this->db->escape($this->tva_tx)."',";
3014  $sql.= " '".$this->db->escape($this->localtax1_tx)."',";
3015  $sql.= " '".$this->db->escape($this->localtax2_tx)."',";
3016  $sql.= " '".$this->db->escape($this->localtax1_type)."',";
3017  $sql.= " '".$this->db->escape($this->localtax2_type)."',";
3018  $sql.= " ".price2num($this->remise_percent).",".price2num($this->subprice).",";
3019  $sql.= " ".price2num($this->total_ht).",".price2num($this->total_tva).",".price2num($this->total_localtax1).",".price2num($this->total_localtax2).",".price2num($this->total_ttc).",";
3020  $sql.= " '".$this->db->escape($this->info_bits)."',";
3021  $sql.= " ".price2num($this->price_ht).",".price2num($this->remise).",";
3022  if ($this->fk_fournprice > 0) $sql.= ' '.$this->fk_fournprice.',';
3023  else $sql.= ' null,';
3024  if ($this->pa_ht > 0) $sql.= ' '.price2num($this->pa_ht);
3025  else $sql.= ' null';
3026  if ($this->date_ouverture > 0) { $sql.= ",'".$this->db->idate($this->date_ouverture)."'"; }
3027  if ($this->date_cloture > 0) { $sql.= ",'".$this->db->idate($this->date_cloture)."'"; }
3028  $sql.= ")";
3029 
3030  dol_syslog(get_class($this)."::insert", LOG_DEBUG);
3031 
3032  $resql=$this->db->query($sql);
3033  if ($resql)
3034  {
3035  $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'contratdet');
3036 
3037  // FIXME Missing insert of extrafields
3038 
3039  if (!$notrigger)
3040  {
3041  // Call trigger
3042  $result = $this->call_trigger('LINECONTRACT_INSERT', $user);
3043  if ($result < 0) {
3044  $this->db->rollback();
3045  return -1;
3046  }
3047  // End call triggers
3048  }
3049 
3050  $this->db->commit();
3051  return 1;
3052  }
3053  else
3054  {
3055  $this->db->rollback();
3056  $this->error=$this->db->error()." sql=".$sql;
3057  return -1;
3058  }
3059  }
3060 
3070  function active_line($user, $date, $date_end = '', $comment = '')
3071  {
3072  global $langs, $conf;
3073 
3074  // Update object
3075  $this->date_ouverture = $date;
3076  $this->date_fin_validite = $date_end;
3077  $this->fk_user_ouverture = $user->id;
3078  $this->date_cloture = null;
3079  $this->commentaire = $comment;
3080 
3081  $error = 0;
3082 
3083  $this->db->begin();
3084 
3085  $sql = "UPDATE " . MAIN_DB_PREFIX . "contratdet SET statut = 4,";
3086  $sql .= " date_ouverture = " . (dol_strlen($date) != 0 ? "'" . $this->db->idate($date) . "'" : "null") . ",";
3087  if ($date_end >= 0) $sql .= " date_fin_validite = " . (dol_strlen($date_end) != 0 ? "'" . $this->db->idate($date_end) . "'" : "null") . ",";
3088  $sql .= " fk_user_ouverture = " . $user->id . ",";
3089  $sql .= " date_cloture = null,";
3090  $sql .= " commentaire = '" . $this->db->escape($comment) . "'";
3091  $sql .= " WHERE rowid = " . $this->id . " AND (statut = 0 OR statut = 3 OR statut = 5)";
3092 
3093  dol_syslog(get_class($this) . "::active_line", LOG_DEBUG);
3094  $resql = $this->db->query($sql);
3095  if ($resql) {
3096  // Call trigger
3097  $result = $this->call_trigger('CONTRACT_SERVICE_ACTIVATE', $user);
3098  if ($result < 0) {
3099  $error++;
3100  $this->db->rollback();
3101  return -1;
3102  }
3103  // End call triggers
3104 
3105  $this->db->commit();
3106  return 1;
3107  } else {
3108  $this->error = $this->db->lasterror();
3109  $this->db->rollback();
3110  return -1;
3111  }
3112  }
3113 
3122  function close_line($user, $date_end, $comment = '')
3123  {
3124  global $langs, $conf;
3125 
3126  // Update object
3127  $this->date_cloture = $date_end;
3128  $this->fk_user_cloture = $user->id;
3129  $this->commentaire = $comment;
3130 
3131  $error = 0;
3132 
3133  // statut actif : 4
3134 
3135  $this->db->begin();
3136 
3137  $sql = "UPDATE " . MAIN_DB_PREFIX . "contratdet SET statut = 5,";
3138  $sql .= " date_cloture = '" . $this->db->idate($date_end) . "',";
3139  $sql .= " fk_user_cloture = " . $user->id . ",";
3140  $sql .= " commentaire = '" . $this->db->escape($comment) . "'";
3141  $sql .= " WHERE rowid = " . $this->id . " AND statut = 4";
3142 
3143  $resql = $this->db->query($sql);
3144  if ($resql) {
3145  // Call trigger
3146  $result = $this->call_trigger('CONTRACT_SERVICE_CLOSE', $user);
3147  if ($result < 0) {
3148  $error++;
3149  $this->db->rollback();
3150  return -1;
3151  }
3152  // End call triggers
3153 
3154  $this->db->commit();
3155  return 1;
3156  } else {
3157  $this->error = $this->db->lasterror();
3158  $this->db->rollback();
3159  return -1;
3160  }
3161  }
3162 }
static replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
initAsSpecimen()
Initialise an instance with random values.
info($id)
Charge les informations d'ordre info dans l'objet contrat.
getIdContact($source, $code, $status=0)
Return id of contacts for a source and a contact code.
img_picto($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='')
Show picto whatever it's its name (generic function)
close_line($user, $date_end, $comment= '')
Close a contract line.
getMarginInfos($pvht, $remise_percent, $tva_tx, $localtax1_tx, $localtax2_tx, $fk_pa, $paht)
Return an array with margins information of a line.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Create a document onto disk according to template module.
deleteObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $rowid='')
Delete all links between an object $this.
activateAll($user, $date_start='')
Open all lines of a contract.
</td >< tdclass="liste_titre"align="right"></td ></tr >< trclass="liste_titre">< inputtype="checkbox"onClick="toggle(this)"/> Ref p ref Label p label Duration p duration warehouseinternal SELECT description FROM product_lang WHERE qty< br > qty qty qty StockTooLow img yes disabled img no img no< trclass="oddeven">< td >< inputtype="checkbox"class="check"name="'.$i.'"'.$disabled.'></td >< td >< inputtype="checkbox"class="check"name="choose'.$i.'"></td >< tdclass="nowrap"></td >< td >< inputtype="hidden"name="desc'.$i.'"value="'.dol_escape_htmltag($objp-> description
Only used if Module[ID]Desc translation string is not found.
Definition: replenish.php:554
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
getIdServiceContact()
Return id des contacts clients de prestation.
getLinesArray()
Create an array of order lines.
update_total()
Mise a jour en base des champs total_xxx de ligne Used by migration process.
LibStatut($statut, $mode)
Renvoi label of a given contrat status.
Class to manage Dolibarr users.
Definition: user.class.php:39
Class to manage Dolibarr database access.
Class to manage contracts.
getIdBillingContact()
Return id des contacts clients de facturation.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
create($user)
Create a contract into database.
dol_print_error($db='', $error='', $errors=null)
Affiche message erreur system avec toutes les informations pour faciliter le diagnostic et la remonte...
Classe permettant la gestion des lignes de contrats.
fetch_lines()
Load lines array into this->lines.
fetch_thirdparty($force_thirdparty_id=0)
Load the third party of object, from id $this->socid or $this->fk_soc, into this->thirdparty.
update_statut($user)
Update statut of contract according to services.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields...
getNomUrl($withpicto=0, $maxlength=0)
Return clicable name (with picto eventually)
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="")
Scan a directory and return a list of files/directories.
Definition: files.lib.php:58
Parent class for class inheritance lines of business objects This class is useless for the moment so ...
active_line($user, $line_id, $date, $date_end='', $comment='')
Activate a contract line.
Class to manage standard extra fields.
add_contact($fk_socpeople, $type_contact, $source='external', $notrigger=0)
Add a link between element $this->element and a contact.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='')
Write log message into outputs.
__construct($db)
Constructor.
load_state_board()
Charge indicateurs this->nb de tableau de bord.
Class to manage third parties objects (customers, suppliers, prospects...)
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
closeAll(User $user, $notrigger=0)
Close all lines of a contract.
delete_linked_contact($source='', $code='')
Delete all links between an object $this and all its contacts.
Class to manage shipments.
static commonReplaceThirdparty(DoliDB $db, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
active_line($user, $date, $date_end= '', $comment= '')
Activate a contract line.
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories) ...
Definition: files.lib.php:1234
img_object($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1, $txlocaltax2, $fk_product, $remise_percent, $date_start, $date_end, $price_base_type='HT', $pu_ttc=0.0, $info_bits=0, $fk_fournprice=null, $pa_ht=0, $array_options=0, $fk_unit=null, $rang=0)
Ajoute une ligne de contrat en base.
deleteExtraFields()
Delete all extra fields values for the current object.
array_detail($statut=-1)
Return list of line rowid.
dol_now($mode='gmt')
Return date for now.
LibStatut($statut, $mode, $expired=-1, $moreatt='')
Return label of a contract line status.
deleteline($idline, User $user)
Delete a contract line.
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
reopen($user, $notrigger=0)
Unvalidate a contract.
update($user, $notrigger=0)
Update database for contract line.
getNextNumRef($soc)
Return next contract ref.
defineBuyPrice($unitPrice=0.0, $discountPercent=0.0, $fk_product=0)
Get buy price to use for margin calculation.
updateline($rowid, $desc, $pu, $qty, $remise_percent, $date_start, $date_end, $tvatx, $localtax1tx=0.0, $localtax2tx=0.0, $date_debut_reel='', $date_fin_reel='', $price_base_type='HT', $info_bits=0, $fk_fournprice=null, $pa_ht=0, $array_options=0, $fk_unit=null)
Mets a jour une ligne de contrat.
calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $seller= '', $localtaxes_array='', $progress=100, $multicurrency_tx=1, $pu_devise=0)
Calculate totals (net, vat, ...) of a line.
Definition: price.lib.php:85
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages...
getLibStatut($mode)
Return label of a contract status.
validate(User $user, $force_number='', $notrigger=0)
Validate a contract.
getLibStatut($mode)
Return label of this contract line status.
createFromClone($socid=0, $notrigger=0)
Load an object from its id and create a new one in database.
print
Draft customers invoices.
Definition: index.php:91
update($user=null, $notrigger=0)
Update object into database.
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if(!empty($conf->fournisseur->enabled)&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->societe->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if(!empty($conf->fournisseur->enabled)&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1013
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname='')
Return a prefix to use for this Dolibarr instance, for session/cookie names or email id...
insert($notrigger=0)
Inserts a contrat line into database.
call_trigger($trigger_name, $user)
Call trigger based on this instance.
close_line($user, $line_id, $date_end, $comment='')
Close a contract line.
getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0)
Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
add_object_linked($origin=null, $origin_id=null)
Add objects linked in llx_element_element.
type
Definition: viewcat.php:283
getListOfContracts($option='all')
Return list of other contracts for same company than current contract.
fetch($id, $ref='')
Load object in memory from database.
$table_ref_field
{}
price2num($amount, $rounding='', $alreadysqlnb=0)
Function that return a number with universal decimal format (decimal separator is '...
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
__construct($db)
Constructor.
load_board($user, $mode)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
Parent class of all other business classes (invoices, contracts, proposals, orders, ...)
fetch($id, $ref='', $ref_customer='', $ref_supplier='')
Load a contract from database.
getNomUrl($withpicto=0, $maxlength=0, $notooltip=0, $save_lastsearch_value=-1)
Return clicable name (with picto eventually)