dolibarr  9.0.0
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@inodbox.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) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
12  * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr>
13  * Copyright (C) 2015-2018 Ferran Marcet <fmarcet@2byte.es>
14  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 3 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program. If not, see <http://www.gnu.org/licenses/>.
27  */
28 
35 require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php';
36 require_once DOL_DOCUMENT_ROOT."/core/class/commonobjectline.class.php";
37 require_once DOL_DOCUMENT_ROOT . '/core/lib/price.lib.php';
38 require_once DOL_DOCUMENT_ROOT . '/margin/lib/margins.lib.php';
39 
43 class Contrat extends CommonObject
44 {
48  public $element='contrat';
49 
53  public $table_element='contrat';
54 
58  public $table_element_line='contratdet';
59 
63  public $fk_element='fk_contrat';
64 
68  public $picto='contract';
69 
74  public $ismultientitymanaged = 1;
75 
80  public $restrictiononfksoc = 1;
81 
85  protected $table_ref_field = 'ref';
86 
91  public $ref_customer;
92 
97  public $ref_supplier;
98 
103  public $socid;
104 
105  public $societe; // Objet societe
106 
111  public $statut=0; // 0=Draft,
112 
113  public $product;
114 
118  public $fk_user_author;
119 
125  public $user_author_id;
126 
130  public $user_creation;
131 
135  public $user_cloture;
136 
140  public $date_creation;
141 
145  public $date_modification;
146 
150  public $date_validation;
151 
155  public $date_contrat;
156 
161  public $date_cloture;
162 
163  public $commercial_signature_id;
164  public $commercial_suivi_id;
165 
170  public $fk_projet;
171 
172  public $extraparams=array();
173 
177  public $lines=array();
178 
183  protected $lines_id_index_mapper=array();
184 
185 
191  function __construct($db)
192  {
193  $this->db = $db;
194  }
195 
202  function getNextNumRef($soc)
203  {
204  global $db, $langs, $conf;
205  $langs->load("contracts");
206 
207  if (!empty($conf->global->CONTRACT_ADDON))
208  {
209  $mybool = false;
210 
211  $file = $conf->global->CONTRACT_ADDON.".php";
212  $classname = $conf->global->CONTRACT_ADDON;
213 
214  // Include file with class
215  $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
216 
217  foreach ($dirmodels as $reldir) {
218 
219  $dir = dol_buildpath($reldir."core/modules/contract/");
220 
221  // Load file with numbering class (if found)
222  $mybool|=@include_once $dir.$file;
223  }
224 
225  if (! $mybool)
226  {
227  dol_print_error('',"Failed to include file ".$file);
228  return '';
229  }
230 
231  $obj = new $classname();
232  $numref = $obj->getNextValue($soc,$this);
233 
234  if ( $numref != "")
235  {
236  return $numref;
237  }
238  else
239  {
240  $this->error = $obj->error;
241  dol_print_error($db,get_class($this)."::getNextValue ".$obj->error);
242  return "";
243  }
244  }
245  else
246  {
247  $langs->load("errors");
248  print $langs->trans("Error")." ".$langs->trans("ErrorModuleSetupNotComplete");
249  return "";
250  }
251  }
252 
253  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
264  function active_line($user, $line_id, $date, $date_end='', $comment='')
265  {
266  // phpcs:enable
267  $result = $this->lines[$this->lines_id_index_mapper[$line_id]]->active_line($user, $date, $date_end, $comment);
268  if ($result < 0)
269  {
270  $this->error = $this->lines[$this->lines_id_index_mapper[$line_id]]->error;
271  $this->errors = $this->lines[$this->lines_id_index_mapper[$line_id]]->errors;
272  }
273  return $result;
274  }
275 
276 
277  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
287  function close_line($user, $line_id, $date_end, $comment='')
288  {
289  // phpcs:enable
290  $result=$this->lines[$this->lines_id_index_mapper[$line_id]]->close_line($user, $date_end, $comment);
291  if ($result < 0)
292  {
293  $this->error = $this->lines[$this->lines_id_index_mapper[$line_id]]->error;
294  $this->errors = $this->lines[$this->lines_id_index_mapper[$line_id]]->errors;
295  }
296  return $result;
297  }
298 
299 
310  function activateAll($user, $date_start='', $notrigger=0, $comment='')
311  {
312  if (empty($date_start)) $date_start = dol_now();
313 
314  $this->db->begin();
315 
316  $error=0;
317 
318  // Load lines
319  $this->fetch_lines();
320 
321  foreach($this->lines as $contratline)
322  {
323  // Open lines not already open
324  if ($contratline->statut != ContratLigne::STATUS_OPEN)
325  {
326  $contratline->context = $this->context;
327 
328  $result = $contratline->active_line($user, $date_start, -1, $comment);
329  if ($result < 0)
330  {
331  $error++;
332  $this->error = $contratline->error;
333  $this->errors = $contratline->errors;
334  break;
335  }
336  }
337  }
338 
339  if (! $error && $this->statut == 0)
340  {
341  $result=$this->validate($user, '', $notrigger);
342  if ($result < 0) $error++;
343  }
344 
345  if (! $error)
346  {
347  $this->db->commit();
348  return 1;
349  }
350  else
351  {
352  $this->db->rollback();
353  return -1;
354  }
355  }
356 
366  function closeAll(User $user, $notrigger=0, $comment='')
367  {
368  $this->db->begin();
369 
370  // Load lines
371  $this->fetch_lines();
372 
373  $now = dol_now();
374 
375  $error = 0;
376 
377  foreach($this->lines as $contratline)
378  {
379  // Close lines not already closed
380  if ($contratline->statut != ContratLigne::STATUS_CLOSED)
381  {
382  $contratline->date_cloture=$now;
383  $contratline->fk_user_cloture=$user->id;
384  $contratline->statut=ContratLigne::STATUS_CLOSED;
385  $result=$contratline->close_line($user, $now, $comment, $notrigger);
386  if ($result < 0)
387  {
388  $error++;
389  $this->error = $contratline->error;
390  $this->errors = $contratline->errors;
391  break;
392  }
393  }
394  }
395 
396  if (! $error && $this->statut == 0)
397  {
398  $result=$this->validate($user, '', $notrigger);
399  if ($result < 0) $error++;
400  }
401 
402  if (! $error)
403  {
404  $this->db->commit();
405  return 1;
406  }
407  else
408  {
409  $this->db->rollback();
410  return -1;
411  }
412  }
413 
422  function validate(User $user, $force_number='', $notrigger=0)
423  {
424  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
425  global $langs, $conf;
426 
427  $now=dol_now();
428 
429  $error=0;
430  dol_syslog(get_class($this).'::validate user='.$user->id.', force_number='.$force_number);
431 
432 
433  $this->db->begin();
434 
435  $this->fetch_thirdparty();
436 
437  // A contract is validated so we can move thirdparty to status customer
438  if (empty($conf->global->CONTRACT_DISABLE_AUTOSET_AS_CLIENT_ON_CONTRACT_VALIDATION))
439  {
440  $result=$this->thirdparty->set_as_client();
441  }
442 
443  // Define new ref
444  if ($force_number)
445  {
446  $num = $force_number;
447  }
448  else if (! $error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) // empty should not happened, but when it occurs, the test save life
449  {
450  $num = $this->getNextNumRef($this->thirdparty);
451  }
452  else
453  {
454  $num = $this->ref;
455  }
456  $this->newref = $num;
457 
458  if ($num)
459  {
460  $sql = "UPDATE ".MAIN_DB_PREFIX."contrat SET ref = '".$num."', statut = 1";
461  //$sql.= ", fk_user_valid = ".$user->id.", date_valid = '".$this->db->idate($now)."'";
462  $sql .= " WHERE rowid = ".$this->id . " AND statut = 0";
463 
464  dol_syslog(get_class($this)."::validate", LOG_DEBUG);
465  $resql = $this->db->query($sql);
466  if (! $resql)
467  {
468  dol_print_error($this->db);
469  $error++;
470  $this->error=$this->db->lasterror();
471  }
472 
473  // Trigger calls
474  if (! $error && ! $notrigger)
475  {
476  // Call trigger
477  $result=$this->call_trigger('CONTRACT_VALIDATE',$user);
478  if ($result < 0) { $error++; }
479  // End call triggers
480  }
481 
482  if (! $error)
483  {
484  $this->oldref = $this->ref;
485 
486  // Rename directory if dir was a temporary ref
487  if (preg_match('/^[\(]?PROV/i', $this->ref))
488  {
489  // Rename of object directory ($this->ref = old ref, $num = new ref)
490  // to not lose the linked files
491  $oldref = dol_sanitizeFileName($this->ref);
492  $newref = dol_sanitizeFileName($num);
493  $dirsource = $conf->contract->dir_output.'/'.$oldref;
494  $dirdest = $conf->contract->dir_output.'/'.$newref;
495  if (file_exists($dirsource))
496  {
497  dol_syslog(get_class($this)."::validate rename dir ".$dirsource." into ".$dirdest);
498 
499  if (@rename($dirsource, $dirdest))
500  {
501  dol_syslog("Rename ok");
502  // Rename docs starting with $oldref with $newref
503  $listoffiles=dol_dir_list($conf->contract->dir_output.'/'.$newref, 'files', 1, '^'.preg_quote($oldref,'/'));
504  foreach($listoffiles as $fileentry)
505  {
506  $dirsource=$fileentry['name'];
507  $dirdest=preg_replace('/^'.preg_quote($oldref,'/').'/',$newref, $dirsource);
508  $dirsource=$fileentry['path'].'/'.$dirsource;
509  $dirdest=$fileentry['path'].'/'.$dirdest;
510  @rename($dirsource, $dirdest);
511  }
512  }
513  }
514  }
515  }
516 
517  // Set new ref and define current statut
518  if (! $error)
519  {
520  $this->ref = $num;
521  $this->statut = 1;
522  $this->brouillon = 0;
523  $this->date_validation = $now;
524  }
525  }
526  else
527  {
528  $error++;
529  }
530 
531  if (! $error)
532  {
533  $this->db->commit();
534  return 1;
535  }
536  else
537  {
538  $this->db->rollback();
539  return -1;
540  }
541  }
542 
550  function reopen($user, $notrigger=0)
551  {
552  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
553  global $langs, $conf;
554 
555  $now=dol_now();
556 
557  $error=0;
558  dol_syslog(get_class($this).'::reopen user='.$user->id);
559 
560  $this->db->begin();
561 
562  $this->fetch_thirdparty();
563 
564  $sql = "UPDATE ".MAIN_DB_PREFIX."contrat SET statut = 0";
565  //$sql.= ", fk_user_valid = null, date_valid = null";
566  $sql .= " WHERE rowid = ".$this->id . " AND statut = 1";
567 
568  dol_syslog(get_class($this)."::validate", LOG_DEBUG);
569  $resql = $this->db->query($sql);
570  if (! $resql)
571  {
572  dol_print_error($this->db);
573  $error++;
574  $this->error=$this->db->lasterror();
575  }
576 
577  // Trigger calls
578  if (! $error && ! $notrigger)
579  {
580  // Call trigger
581  $result=$this->call_trigger('CONTRACT_REOPEN',$user);
582  if ($result < 0) {
583  $error++;
584  }
585  // End call triggers
586  }
587 
588  // Set new ref and define current status
589  if (! $error)
590  {
591  $this->statut=0;
592  $this->brouillon=1;
593  $this->date_validation=$now;
594  }
595 
596  if (! $error)
597  {
598  $this->db->commit();
599  return 1;
600  }
601  else
602  {
603  $this->db->rollback();
604  return -1;
605  }
606  }
607 
617  function fetch($id, $ref='', $ref_customer='', $ref_supplier='')
618  {
619  $sql = "SELECT rowid, statut, ref, fk_soc, mise_en_service as datemise,";
620  $sql.= " ref_supplier, ref_customer,";
621  $sql.= " ref_ext,";
622  $sql.= " fk_user_mise_en_service, date_contrat as datecontrat,";
623  $sql.= " fk_user_author, fin_validite, date_cloture,";
624  $sql.= " fk_projet,";
625  $sql.= " fk_commercial_signature, fk_commercial_suivi,";
626  $sql.= " note_private, note_public, model_pdf, extraparams";
627  $sql.= " FROM ".MAIN_DB_PREFIX."contrat";
628  if (! $id) $sql.=" WHERE entity IN (".getEntity('contract').")";
629  else $sql.= " WHERE rowid=".$id;
630  if ($ref_customer)
631  {
632  $sql.= " AND ref_customer = '".$this->db->escape($ref_customer)."'";
633  }
634  if ($ref_supplier)
635  {
636  $sql.= " AND ref_supplier = '".$this->db->escape($ref_supplier)."'";
637  }
638  if ($ref)
639  {
640  $sql.= " AND ref='".$this->db->escape($ref)."'";
641  }
642 
643  dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
644  $resql = $this->db->query($sql);
645  if ($resql)
646  {
647  $obj = $this->db->fetch_object($resql);
648 
649  if ($obj)
650  {
651  $this->id = $obj->rowid;
652  $this->ref = (!isset($obj->ref) || !$obj->ref) ? $obj->rowid : $obj->ref;
653  $this->ref_customer = $obj->ref_customer;
654  $this->ref_supplier = $obj->ref_supplier;
655  $this->ref_ext = $obj->ref_ext;
656  $this->statut = $obj->statut;
657  $this->mise_en_service = $this->db->jdate($obj->datemise);
658 
659  $this->date_contrat = $this->db->jdate($obj->datecontrat);
660  $this->date_creation = $this->db->jdate($obj->datecontrat);
661 
662  $this->fin_validite = $this->db->jdate($obj->fin_validite);
663  $this->date_cloture = $this->db->jdate($obj->date_cloture);
664 
665 
666  $this->user_author_id = $obj->fk_user_author;
667 
668  $this->commercial_signature_id = $obj->fk_commercial_signature;
669  $this->commercial_suivi_id = $obj->fk_commercial_suivi;
670 
671  $this->note_private = $obj->note_private;
672  $this->note_public = $obj->note_public;
673  $this->modelpdf = $obj->model_pdf;
674 
675  $this->fk_projet = $obj->fk_projet; // deprecated
676  $this->fk_project = $obj->fk_projet;
677 
678  $this->socid = $obj->fk_soc;
679  $this->fk_soc = $obj->fk_soc;
680 
681  $this->extraparams = (array) json_decode($obj->extraparams, true);
682 
683  $this->db->free($resql);
684 
685  // Retreive all extrafields
686  // fetch optionals attributes and labels
687  $this->fetch_optionals();
688 
689  // Lines
690  $result=$this->fetch_lines();
691  if ($result < 0)
692  {
693  $this->error=$this->db->lasterror();
694  return -3;
695  }
696 
697  return $this->id;
698  }
699  else
700  {
701  dol_syslog(get_class($this)."::fetch Contract not found");
702  $this->error="Contract not found";
703  return 0;
704  }
705  }
706  else
707  {
708  dol_syslog(get_class($this)."::fetch Error searching contract");
709  $this->error=$this->db->error();
710  return -1;
711  }
712  }
713 
714  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
721  function fetch_lines()
722  {
723  // phpcs:enable
724  $this->nbofserviceswait=0;
725  $this->nbofservicesopened=0;
726  $this->nbofservicesexpired=0;
727  $this->nbofservicesclosed=0;
728 
729  $total_ttc=0;
730  $total_vat=0;
731  $total_ht=0;
732 
733  $now=dol_now();
734 
735  require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
736  $extrafieldsline=new ExtraFields($this->db);
737  $line = new ContratLigne($this->db);
738  $extralabelsline=$extrafieldsline->fetch_name_optionals_label($line->table_element,true);
739 
740  $this->lines=array();
741  $pos = 0;
742 
743  // Selects contract lines related to a product
744  $sql = "SELECT p.label as product_label, p.description as product_desc, p.ref as product_ref,";
745  $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,";
746  $sql.= " d.total_ht,";
747  $sql.= " d.total_tva,";
748  $sql.= " d.total_localtax1,";
749  $sql.= " d.total_localtax2,";
750  $sql.= " d.total_ttc,";
751  $sql.= " d.info_bits, d.fk_product,";
752  $sql.= " d.date_ouverture_prevue, d.date_ouverture,";
753  $sql.= " d.date_fin_validite, d.date_cloture,";
754  $sql.= " d.fk_user_author,";
755  $sql.= " d.fk_user_ouverture,";
756  $sql.= " d.fk_user_cloture,";
757  $sql.= " d.fk_unit";
758  $sql.= " FROM ".MAIN_DB_PREFIX."contratdet as d LEFT JOIN ".MAIN_DB_PREFIX."product as p ON d.fk_product = p.rowid";
759  $sql.= " WHERE d.fk_contrat = ".$this->id;
760  $sql.= " ORDER by d.rowid ASC";
761 
762  dol_syslog(get_class($this)."::fetch_lines", LOG_DEBUG);
763  $result = $this->db->query($sql);
764  if ($result)
765  {
766  $num = $this->db->num_rows($result);
767  $i = 0;
768 
769  while ($i < $num)
770  {
771  $objp = $this->db->fetch_object($result);
772 
773  $line = new ContratLigne($this->db);
774  $line->id = $objp->rowid;
775  $line->ref = $objp->rowid;
776  $line->fk_contrat = $objp->fk_contrat;
777  $line->desc = $objp->description; // Description line
778  $line->qty = $objp->qty;
779  $line->vat_src_code = $objp->vat_src_code ;
780  $line->tva_tx = $objp->tva_tx;
781  $line->localtax1_tx = $objp->localtax1_tx;
782  $line->localtax2_tx = $objp->localtax2_tx;
783  $line->localtax1_type = $objp->localtax1_type;
784  $line->localtax2_type = $objp->localtax2_type;
785  $line->subprice = $objp->subprice;
786  $line->statut = $objp->statut;
787  $line->remise_percent = $objp->remise_percent;
788  $line->price_ht = $objp->price_ht;
789  $line->price = $objp->price_ht; // For backward compatibility
790  $line->total_ht = $objp->total_ht;
791  $line->total_tva = $objp->total_tva;
792  $line->total_localtax1 = $objp->total_localtax1;
793  $line->total_localtax2 = $objp->total_localtax2;
794  $line->total_ttc = $objp->total_ttc;
795  $line->fk_product = (($objp->fk_product > 0)?$objp->fk_product:0);
796  $line->info_bits = $objp->info_bits;
797 
798  $line->fk_fournprice = $objp->fk_fournprice;
799  $marginInfos = getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $line->fk_fournprice, $objp->pa_ht);
800  $line->pa_ht = $marginInfos[0];
801 
802  $line->fk_user_author = $objp->fk_user_author;
803  $line->fk_user_ouverture= $objp->fk_user_ouverture;
804  $line->fk_user_cloture = $objp->fk_user_cloture;
805  $line->fk_unit = $objp->fk_unit;
806 
807  $line->ref = $objp->product_ref; // deprecated
808  $line->product_ref = $objp->product_ref; // Product Ref
809  $line->product_desc = $objp->product_desc; // Product Description
810  $line->product_label = $objp->product_label; // Product Label
811 
812  $line->description = $objp->description;
813 
814  $line->date_start = $this->db->jdate($objp->date_ouverture_prevue);
815  $line->date_start_real = $this->db->jdate($objp->date_ouverture);
816  $line->date_end = $this->db->jdate($objp->date_fin_validite);
817  $line->date_end_real = $this->db->jdate($objp->date_cloture);
818  // For backward compatibility
819  $line->date_ouverture_prevue = $this->db->jdate($objp->date_ouverture_prevue);
820  $line->date_ouverture = $this->db->jdate($objp->date_ouverture);
821  $line->date_fin_validite = $this->db->jdate($objp->date_fin_validite);
822  $line->date_cloture = $this->db->jdate($objp->date_cloture);
823  $line->date_debut_prevue = $this->db->jdate($objp->date_ouverture_prevue);
824  $line->date_debut_reel = $this->db->jdate($objp->date_ouverture);
825  $line->date_fin_prevue = $this->db->jdate($objp->date_fin_validite);
826  $line->date_fin_reel = $this->db->jdate($objp->date_cloture);
827 
828  // Retreive all extrafields for contract
829  // fetch optionals attributes and labels
830  $line->fetch_optionals();
831 
832  $this->lines[$pos] = $line;
833  $this->lines_id_index_mapper[$line->id] = $pos;
834 
835  //dol_syslog("1 ".$line->desc);
836  //dol_syslog("2 ".$line->product_desc);
837 
838  if ($line->statut == ContratLigne::STATUS_INITIAL) $this->nbofserviceswait++;
839  if ($line->statut == ContratLigne::STATUS_OPEN && (empty($line->date_fin_prevue) || $line->date_fin_prevue >= $now)) $this->nbofservicesopened++;
840  if ($line->statut == ContratLigne::STATUS_OPEN && (! empty($line->date_fin_prevue) && $line->date_fin_prevue < $now)) $this->nbofservicesexpired++;
841  if ($line->statut == ContratLigne::STATUS_CLOSED) $this->nbofservicesclosed++;
842 
843  $total_ttc+=$objp->total_ttc; // TODO Not saved into database
844  $total_vat+=$objp->total_tva;
845  $total_ht+=$objp->total_ht;
846 
847  $i++;
848  $pos++;
849  }
850  $this->db->free($result);
851  }
852  else
853  {
854  dol_syslog(get_class($this)."::Fetch Erreur lecture des lignes de contrats liees aux produits");
855  return -3;
856  }
857 
858  $this->nbofservices=count($this->lines);
859  $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
860  $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
861  $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
862 
863  return $this->lines;
864  }
865 
872  function create($user)
873  {
874  global $conf,$langs,$mysoc;
875 
876  // Check parameters
877  $paramsok=1;
878  if ($this->commercial_signature_id <= 0)
879  {
880  $langs->load("commercial");
881  $this->error.=$langs->trans("ErrorFieldRequired",$langs->trans("SalesRepresentativeSignature"));
882  $paramsok=0;
883  }
884  if ($this->commercial_suivi_id <= 0)
885  {
886  $langs->load("commercial");
887  $this->error.=($this->error?"<br>":'');
888  $this->error.=$langs->trans("ErrorFieldRequired",$langs->trans("SalesRepresentativeFollowUp"));
889  $paramsok=0;
890  }
891  if (! $paramsok) return -1;
892 
893 
894  $this->db->begin();
895 
896  $now=dol_now();
897 
898  // Insert contract
899  $sql = "INSERT INTO ".MAIN_DB_PREFIX."contrat (datec, fk_soc, fk_user_author, date_contrat,";
900  $sql.= " fk_commercial_signature, fk_commercial_suivi, fk_projet,";
901  $sql.= " ref, entity, note_private, note_public, ref_customer, ref_supplier, ref_ext)";
902  $sql.= " VALUES ('".$this->db->idate($now)."',".$this->socid.",".$user->id;
903  $sql.= ", ".(dol_strlen($this->date_contrat)!=0 ? "'".$this->db->idate($this->date_contrat)."'" : "NULL");
904  $sql.= ",".($this->commercial_signature_id>0?$this->commercial_signature_id:"NULL");
905  $sql.= ",".($this->commercial_suivi_id>0?$this->commercial_suivi_id:"NULL");
906  $sql.= ",".($this->fk_project>0?$this->fk_project:"NULL");
907  $sql.= ", ".(dol_strlen($this->ref)<=0 ? "null" : "'".$this->db->escape($this->ref)."'");
908  $sql.= ", ".$conf->entity;
909  $sql.= ", ".(!empty($this->note_private)?("'".$this->db->escape($this->note_private)."'"):"NULL");
910  $sql.= ", ".(!empty($this->note_public)?("'".$this->db->escape($this->note_public)."'"):"NULL");
911  $sql.= ", ".(!empty($this->ref_customer)?("'".$this->db->escape($this->ref_customer)."'"):"NULL");
912  $sql.= ", ".(!empty($this->ref_supplier)?("'".$this->db->escape($this->ref_supplier)."'"):"NULL");
913  $sql.= ", ".(!empty($this->ref_ext)?("'".$this->db->escape($this->ref_ext)."'"):"NULL");
914  $sql.= ")";
915  $resql=$this->db->query($sql);
916  if ($resql)
917  {
918  $error=0;
919 
920  $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."contrat");
921 
922  // Load object modContract
923  $module=(! empty($conf->global->CONTRACT_ADDON)?$conf->global->CONTRACT_ADDON:'mod_contract_serpis');
924  if (substr($module, 0, 13) == 'mod_contract_' && substr($module, -3) == 'php')
925  {
926  $module = substr($module, 0, dol_strlen($module)-4);
927  }
928  $result=dol_include_once('/core/modules/contract/'.$module.'.php');
929  if ($result > 0)
930  {
931  $modCodeContract = new $module();
932 
933  if (!empty($modCodeContract->code_auto)) {
934  // Update ref
935  $sql = 'UPDATE '.MAIN_DB_PREFIX."contrat SET ref='(PROV".$this->id.")' WHERE rowid=".$this->id;
936  if ($this->db->query($sql))
937  {
938  if ($this->id)
939  {
940  $this->ref="(PROV".$this->id.")";
941  }
942  }
943  } else {
944  $error++;
945  $this->error='Failed to get PROV number';
946  }
947  }
948 
949  if (! $error && empty($conf->global->MAIN_EXTRAFIELDS_DISABLED))
950  {
951  $result=$this->insertExtraFields();
952  if ($result < 0)
953  {
954  $error++;
955  }
956  }
957 
958  // Insert business contacts ('SALESREPSIGN','contrat')
959  if (! $error)
960  {
961  $result=$this->add_contact($this->commercial_signature_id,'SALESREPSIGN','internal');
962  if ($result < 0) $error++;
963  }
964 
965  // Insert business contacts ('SALESREPFOLL','contrat')
966  if (! $error)
967  {
968  $result=$this->add_contact($this->commercial_suivi_id,'SALESREPFOLL','internal');
969  if ($result < 0) $error++;
970  }
971 
972  if (! $error)
973  {
974  if (! empty($this->linkedObjectsIds) && empty($this->linked_objects)) // To use new linkedObjectsIds instead of old linked_objects
975  {
976  $this->linked_objects = $this->linkedObjectsIds; // TODO Replace linked_objects with linkedObjectsIds
977  }
978 
979  // Add object linked
980  if (! $error && $this->id && is_array($this->linked_objects) && ! empty($this->linked_objects))
981  {
982  foreach($this->linked_objects as $origin => $tmp_origin_id)
983  {
984  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, ...))
985  {
986  foreach($tmp_origin_id as $origin_id)
987  {
988  $ret = $this->add_object_linked($origin, $origin_id);
989  if (! $ret)
990  {
991  $this->error=$this->db->lasterror();
992  $error++;
993  }
994  }
995  }
996  else // Old behaviour, if linked_object has only one link per type, so is something like array('contract'=>id1))
997  {
998  $origin_id = $tmp_origin_id;
999  $ret = $this->add_object_linked($origin, $origin_id);
1000  if (! $ret)
1001  {
1002  $this->error=$this->db->lasterror();
1003  $error++;
1004  }
1005  }
1006  }
1007  }
1008 
1009  if (! $error && $this->id && ! empty($conf->global->MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN) && ! empty($this->origin) && ! empty($this->origin_id)) // Get contact from origin object
1010  {
1011  $originforcontact = $this->origin;
1012  $originidforcontact = $this->origin_id;
1013  if ($originforcontact == 'shipping') // shipment and order share the same contacts. If creating from shipment we take data of order
1014  {
1015  require_once DOL_DOCUMENT_ROOT . '/expedition/class/expedition.class.php';
1016  $exp = new Expedition($db);
1017  $exp->fetch($this->origin_id);
1018  $exp->fetchObjectLinked();
1019  if (count($exp->linkedObjectsIds['commande']) > 0)
1020  {
1021  foreach ($exp->linkedObjectsIds['commande'] as $key => $value)
1022  {
1023  $originforcontact = 'commande';
1024  $originidforcontact = $value->id;
1025  break; // We take first one
1026  }
1027  }
1028  }
1029 
1030  $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";
1031  $sqlcontact.= " WHERE element_id = ".$originidforcontact." AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$originforcontact."'";
1032 
1033  $resqlcontact = $this->db->query($sqlcontact);
1034  if ($resqlcontact)
1035  {
1036  while($objcontact = $this->db->fetch_object($resqlcontact))
1037  {
1038  if ($objcontact->source == 'internal' && in_array($objcontact->code, array('SALESREPSIGN', 'SALESREPFOLL'))) continue; // ignore this, already forced previously
1039 
1040  //print $objcontact->code.'-'.$objcontact->source.'-'.$objcontact->fk_socpeople."\n";
1041  $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
1042  }
1043  }
1044  else dol_print_error($resqlcontact);
1045  }
1046  }
1047 
1048  if (! $error)
1049  {
1050  // Call trigger
1051  $result=$this->call_trigger('CONTRACT_CREATE',$user);
1052  if ($result < 0) { $error++; }
1053  // End call triggers
1054 
1055  if (! $error)
1056  {
1057  $this->db->commit();
1058  return $this->id;
1059  }
1060  else
1061  {
1062  dol_syslog(get_class($this)."::create - 30 - ".$this->error, LOG_ERR);
1063  $this->db->rollback();
1064  return -3;
1065  }
1066  }
1067  else
1068  {
1069  $this->error="Failed to add contract";
1070  dol_syslog(get_class($this)."::create - 20 - ".$this->error, LOG_ERR);
1071  $this->db->rollback();
1072  return -2;
1073  }
1074  }
1075  else
1076  {
1077  $this->error=$langs->trans("UnknownError: ".$this->db->error()." -", LOG_DEBUG);
1078 
1079  $this->db->rollback();
1080  return -1;
1081  }
1082  }
1083 
1084 
1091  function delete($user)
1092  {
1093  global $conf, $langs;
1094  require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
1095 
1096  $error=0;
1097 
1098  $this->db->begin();
1099 
1100  // Call trigger
1101  $result=$this->call_trigger('CONTRACT_DELETE',$user);
1102  if ($result < 0) { $error++; }
1103  // End call triggers
1104 
1105  if (! $error)
1106  {
1107  // Delete linked contacts
1108  $res = $this->delete_linked_contact();
1109  if ($res < 0)
1110  {
1111  dol_syslog(get_class($this)."::delete error", LOG_ERR);
1112  $error++;
1113  }
1114  }
1115 
1116  if (! $error)
1117  {
1118  // Delete linked object
1119  $res = $this->deleteObjectLinked();
1120  if ($res < 0) $error++;
1121  }
1122 
1123  if (! $error)
1124  {
1125  // Delete contratdet_log
1126  /*
1127  $sql = "DELETE cdl";
1128  $sql.= " FROM ".MAIN_DB_PREFIX."contratdet_log as cdl, ".MAIN_DB_PREFIX."contratdet as cd";
1129  $sql.= " WHERE cdl.fk_contratdet=cd.rowid AND cd.fk_contrat=".$this->id;
1130  */
1131  $sql = "SELECT cdl.rowid as cdlrowid ";
1132  $sql.= " FROM ".MAIN_DB_PREFIX."contratdet_log as cdl, ".MAIN_DB_PREFIX."contratdet as cd";
1133  $sql.= " WHERE cdl.fk_contratdet=cd.rowid AND cd.fk_contrat=".$this->id;
1134 
1135  dol_syslog(get_class($this)."::delete contratdet_log", LOG_DEBUG);
1136  $resql=$this->db->query($sql);
1137  if (! $resql)
1138  {
1139  $this->error=$this->db->error();
1140  $error++;
1141  }
1142  $numressql=$this->db->num_rows($resql);
1143  if (! $error && $numressql )
1144  {
1145  $tab_resql=array();
1146  for($i=0;$i<$numressql;$i++)
1147  {
1148  $objresql=$this->db->fetch_object($resql);
1149  $tab_resql[]= $objresql->cdlrowid;
1150  }
1151  $this->db->free($resql);
1152 
1153  $sql= "DELETE FROM ".MAIN_DB_PREFIX."contratdet_log ";
1154  $sql.= " WHERE ".MAIN_DB_PREFIX."contratdet_log.rowid IN (".implode(",",$tab_resql).")";
1155 
1156  dol_syslog(get_class($this)."::delete contratdet_log", LOG_DEBUG);
1157  $resql=$this->db->query($sql);
1158  if (! $resql)
1159  {
1160  $this->error=$this->db->error();
1161  $error++;
1162  }
1163  }
1164  }
1165 
1166  if (! $error)
1167  {
1168  // Delete contratdet
1169  $sql = "DELETE FROM ".MAIN_DB_PREFIX."contratdet";
1170  $sql.= " WHERE fk_contrat=".$this->id;
1171 
1172  dol_syslog(get_class($this)."::delete contratdet", LOG_DEBUG);
1173  $resql=$this->db->query($sql);
1174  if (! $resql)
1175  {
1176  $this->error=$this->db->error();
1177  $error++;
1178  }
1179  }
1180 
1181  if (! $error)
1182  {
1183  // Delete contrat
1184  $sql = "DELETE FROM ".MAIN_DB_PREFIX."contrat";
1185  $sql.= " WHERE rowid=".$this->id;
1186 
1187  dol_syslog(get_class($this)."::delete contrat", LOG_DEBUG);
1188  $resql=$this->db->query($sql);
1189  if (! $resql)
1190  {
1191  $this->error=$this->db->error();
1192  $error++;
1193  }
1194  }
1195 
1196  // Removed extrafields
1197  if (! $error) {
1198  $result=$this->deleteExtraFields();
1199  if ($result < 0)
1200  {
1201  $error++;
1202  dol_syslog(get_class($this)."::delete error -3 ".$this->error, LOG_ERR);
1203  }
1204  }
1205 
1206  if (! $error)
1207  {
1208  // We remove directory
1209  $ref = dol_sanitizeFileName($this->ref);
1210  if ($conf->contrat->dir_output)
1211  {
1212  $dir = $conf->contrat->dir_output . "/" . $ref;
1213  if (file_exists($dir))
1214  {
1215  $res=@dol_delete_dir_recursive($dir);
1216  if (! $res)
1217  {
1218  $this->error='ErrorFailToDeleteDir';
1219  $error++;
1220  }
1221  }
1222  }
1223  }
1224 
1225  if (! $error)
1226  {
1227  $this->db->commit();
1228  return 1;
1229  }
1230  else
1231  {
1232  $this->error=$this->db->lasterror();
1233  $this->db->rollback();
1234  return -1;
1235  }
1236  }
1237 
1245  function update($user, $notrigger=0)
1246  {
1247  global $conf, $langs;
1248  $error=0;
1249 
1250  // Clean parameters
1251  if (empty($this->fk_commercial_signature) && $this->commercial_signature_id > 0) $this->fk_commercial_signature = $this->commercial_signature_id;
1252  if (empty($this->fk_commercial_suivi) && $this->commercial_suivi_id > 0) $this->fk_commercial_suivi = $this->commercial_suivi_id;
1253  if (empty($this->fk_soc) && $this->socid > 0) $this->fk_soc = $this->socid;
1254  if (empty($this->fk_project) && $this->projet > 0) $this->fk_project = $this->projet;
1255 
1256  if (isset($this->ref)) $this->ref=trim($this->ref);
1257  if (isset($this->ref_customer)) $this->ref_customer=trim($this->ref_customer);
1258  if (isset($this->ref_supplier)) $this->ref_supplier=trim($this->ref_supplier);
1259  if (isset($this->ref_ext)) $this->ref_ext=trim($this->ref_ext);
1260  if (isset($this->entity)) $this->entity=trim($this->entity);
1261  if (isset($this->statut)) $this->statut=(int) $this->statut;
1262  if (isset($this->fk_soc)) $this->fk_soc=trim($this->fk_soc);
1263  if (isset($this->fk_commercial_signature)) $this->fk_commercial_signature=trim($this->fk_commercial_signature);
1264  if (isset($this->fk_commercial_suivi)) $this->fk_commercial_suivi=trim($this->fk_commercial_suivi);
1265  if (isset($this->fk_user_mise_en_service)) $this->fk_user_mise_en_service=trim($this->fk_user_mise_en_service);
1266  if (isset($this->fk_user_cloture)) $this->fk_user_cloture=trim($this->fk_user_cloture);
1267  if (isset($this->note_private)) $this->note_private=trim($this->note_private);
1268  if (isset($this->note_public)) $this->note_public=trim($this->note_public);
1269  if (isset($this->import_key)) $this->import_key=trim($this->import_key);
1270  //if (isset($this->extraparams)) $this->extraparams=trim($this->extraparams);
1271 
1272  // Check parameters
1273  // Put here code to add a control on parameters values
1274 
1275  // Update request
1276  $sql = "UPDATE ".MAIN_DB_PREFIX."contrat SET";
1277  $sql.= " ref=".(isset($this->ref)?"'".$this->db->escape($this->ref)."'":"null").",";
1278  $sql.= " ref_customer=".(isset($this->ref_customer)?"'".$this->db->escape($this->ref_customer)."'":"null").",";
1279  $sql.= " ref_supplier=".(isset($this->ref_supplier)?"'".$this->db->escape($this->ref_supplier)."'":"null").",";
1280  $sql.= " ref_ext=".(isset($this->ref_ext)?"'".$this->db->escape($this->ref_ext)."'":"null").",";
1281  $sql.= " entity=".$conf->entity.",";
1282  $sql.= " date_contrat=".(dol_strlen($this->date_contrat)!=0 ? "'".$this->db->idate($this->date_contrat)."'" : 'null').",";
1283  $sql.= " statut=".(isset($this->statut)?$this->statut:"null").",";
1284  $sql.= " mise_en_service=".(dol_strlen($this->mise_en_service)!=0 ? "'".$this->db->idate($this->mise_en_service)."'" : 'null').",";
1285  $sql.= " fin_validite=".(dol_strlen($this->fin_validite)!=0 ? "'".$this->db->idate($this->fin_validite)."'" : 'null').",";
1286  $sql.= " date_cloture=".(dol_strlen($this->date_cloture)!=0 ? "'".$this->db->idate($this->date_cloture)."'" : 'null').",";
1287  $sql.= " fk_soc=".($this->fk_soc > 0 ? $this->fk_soc:"null").",";
1288  $sql.= " fk_projet=".($this->fk_project > 0 ? $this->fk_project:"null").",";
1289  $sql.= " fk_commercial_signature=".(isset($this->fk_commercial_signature)?$this->fk_commercial_signature:"null").",";
1290  $sql.= " fk_commercial_suivi=".(isset($this->fk_commercial_suivi)?$this->fk_commercial_suivi:"null").",";
1291  $sql.= " fk_user_mise_en_service=".(isset($this->fk_user_mise_en_service)?$this->fk_user_mise_en_service:"null").",";
1292  $sql.= " fk_user_cloture=".(isset($this->fk_user_cloture)?$this->fk_user_cloture:"null").",";
1293  $sql.= " note_private=".(isset($this->note_private)?"'".$this->db->escape($this->note_private)."'":"null").",";
1294  $sql.= " note_public=".(isset($this->note_public)?"'".$this->db->escape($this->note_public)."'":"null").",";
1295  $sql.= " import_key=".(isset($this->import_key)?"'".$this->db->escape($this->import_key)."'":"null")."";
1296  //$sql.= " extraparams=".(isset($this->extraparams)?"'".$this->db->escape($this->extraparams)."'":"null")."";
1297  $sql.= " WHERE rowid=".$this->id;
1298 
1299  $this->db->begin();
1300 
1301  $resql = $this->db->query($sql);
1302  if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
1303 
1304  if (! $error && empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($this->array_options) && count($this->array_options)>0)
1305  {
1306  $result=$this->insertExtraFields();
1307  if ($result < 0)
1308  {
1309  $error++;
1310  }
1311  }
1312 
1313  if (! $error && ! $notrigger)
1314  {
1315  // Call triggers
1316  $result=$this->call_trigger('CONTRACT_MODIFY',$user);
1317  if ($result < 0) { $error++; }
1318  // End call triggers
1319  }
1320 
1321  // Commit or rollback
1322  if ($error)
1323  {
1324  foreach($this->errors as $errmsg)
1325  {
1326  dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
1327  $this->error.=($this->error?', '.$errmsg:$errmsg);
1328  }
1329  $this->db->rollback();
1330  return -1*$error;
1331  }
1332  else
1333  {
1334  $this->db->commit();
1335  return 1;
1336  }
1337  }
1338 
1339 
1363  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)
1364  {
1365  global $user, $langs, $conf, $mysoc;
1366  $error=0;
1367 
1368  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");
1369 
1370  // Check parameters
1371  if ($fk_product <= 0 && empty($desc))
1372  {
1373  $this->error="ErrorDescRequiredForFreeProductLines";
1374  return -1;
1375  }
1376 
1377  if ($this->statut >= 0)
1378  {
1379  $this->db->begin();
1380 
1381  // Clean parameters
1382  $pu_ht=price2num($pu_ht);
1383  $pu_ttc=price2num($pu_ttc);
1384  $pa_ht=price2num($pa_ht);
1385  if (!preg_match('/\((.*)\)/', $txtva)) {
1386  $txtva = price2num($txtva); // $txtva can have format '5.0(XXX)' or '5'
1387  }
1388  $txlocaltax1=price2num($txlocaltax1);
1389  $txlocaltax2=price2num($txlocaltax2);
1390  $remise_percent=price2num($remise_percent);
1391  $qty=price2num($qty);
1392  if (empty($qty)) $qty=1;
1393  if (empty($info_bits)) $info_bits=0;
1394  if (empty($pu_ht) || ! is_numeric($pu_ht)) $pu_ht=0;
1395  if (empty($pu_ttc)) $pu_ttc=0;
1396  if (empty($txtva) || ! is_numeric($txtva)) $txtva=0;
1397  if (empty($txlocaltax1) || ! is_numeric($txlocaltax1)) $txlocaltax1=0;
1398  if (empty($txlocaltax2) || ! is_numeric($txlocaltax2)) $txlocaltax2=0;
1399 
1400  if ($price_base_type=='HT')
1401  {
1402  $pu=$pu_ht;
1403  }
1404  else
1405  {
1406  $pu=$pu_ttc;
1407  }
1408 
1409  // Check parameters
1410  if (empty($remise_percent)) $remise_percent=0;
1411 
1412  $localtaxes_type=getLocalTaxesFromRate($txtva, 0, $this->societe, $mysoc);
1413 
1414  // Clean vat code
1415  $vat_src_code='';
1416  if (preg_match('/\((.*)\)/', $txtva, $reg))
1417  {
1418  $vat_src_code = $reg[1];
1419  $txtva = preg_replace('/\s*\(.*\)/', '', $txtva); // Remove code into vatrate.
1420  }
1421 
1422  // Calcul du total TTC et de la TVA pour la ligne a partir de
1423  // qty, pu, remise_percent et txtva
1424  // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
1425  // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
1426 
1427  $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, 1,$mysoc, $localtaxes_type);
1428  $total_ht = $tabprice[0];
1429  $total_tva = $tabprice[1];
1430  $total_ttc = $tabprice[2];
1431  $total_localtax1= $tabprice[9];
1432  $total_localtax2= $tabprice[10];
1433 
1434  $localtax1_type=$localtaxes_type[0];
1435  $localtax2_type=$localtaxes_type[2];
1436 
1437  // TODO A virer
1438  // Anciens indicateurs: $price, $remise (a ne plus utiliser)
1439  $remise = 0;
1440  $price = price2num(round($pu_ht, 2));
1441  if (dol_strlen($remise_percent) > 0)
1442  {
1443  $remise = round(($pu_ht * $remise_percent / 100), 2);
1444  $price = $pu_ht - $remise;
1445  }
1446 
1447  if (empty($pa_ht)) $pa_ht=0;
1448 
1449 
1450  // if buy price not defined, define buyprice as configured in margin admin
1451  if ($this->pa_ht == 0)
1452  {
1453  if (($result = $this->defineBuyPrice($pu_ht, $remise_percent, $fk_product)) < 0)
1454  {
1455  return $result;
1456  }
1457  else
1458  {
1459  $pa_ht = $result;
1460  }
1461  }
1462 
1463  // Insertion dans la base
1464  $sql = "INSERT INTO ".MAIN_DB_PREFIX."contratdet";
1465  $sql.= " (fk_contrat, label, description, fk_product, qty, tva_tx, vat_src_code,";
1466  $sql.= " localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, remise_percent, subprice,";
1467  $sql.= " total_ht, total_tva, total_localtax1, total_localtax2, total_ttc,";
1468  $sql.= " info_bits,";
1469  $sql.= " price_ht, remise, fk_product_fournisseur_price, buy_price_ht";
1470  if ($date_start > 0) { $sql.= ",date_ouverture_prevue"; }
1471  if ($date_end > 0) { $sql.= ",date_fin_validite"; }
1472  $sql.= ", fk_unit";
1473  $sql.= ") VALUES (";
1474  $sql.= $this->id.", '', '" . $this->db->escape($desc) . "',";
1475  $sql.= ($fk_product>0 ? $fk_product : "null").",";
1476  $sql.= " ".$qty.",";
1477  $sql.= " ".$txtva.",";
1478  $sql.= " ".($vat_src_code?"'".$vat_src_code."'":"null").",";
1479  $sql.= " ".$txlocaltax1.",";
1480  $sql.= " ".$txlocaltax2.",";
1481  $sql.= " '".$localtax1_type."',";
1482  $sql.= " '".$localtax2_type."',";
1483  $sql.= " ".price2num($remise_percent).",";
1484  $sql.= " ".price2num($pu_ht).",";
1485  $sql.= " ".price2num($total_ht).",".price2num($total_tva).",".price2num($total_localtax1).",".price2num($total_localtax2).",".price2num($total_ttc).",";
1486  $sql.= " '".$info_bits."',";
1487  $sql.= " ".price2num($price).",".price2num($remise).",";
1488  if (isset($fk_fournprice)) $sql.= ' '.$fk_fournprice.',';
1489  else $sql.= ' null,';
1490  if (isset($pa_ht)) $sql.= ' '.price2num($pa_ht);
1491  else $sql.= ' null';
1492  if ($date_start > 0) { $sql.= ",'".$this->db->idate($date_start)."'"; }
1493  if ($date_end > 0) { $sql.= ",'".$this->db->idate($date_end)."'"; }
1494  $sql.= ", ".($fk_unit?"'".$this->db->escape($fk_unit)."'":"null");
1495  $sql.= ")";
1496 
1497  $resql=$this->db->query($sql);
1498  if ($resql)
1499  {
1500  $contractlineid = $this->db->last_insert_id(MAIN_DB_PREFIX."contratdet");
1501 
1502  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($array_options) && count($array_options)>0) // For avoid conflicts if trigger used
1503  {
1504  $contractline = new ContratLigne($this->db);
1505  $contractline->array_options=$array_options;
1506  $contractline->id=$contractlineid;
1507  $result=$contractline->insertExtraFields();
1508  if ($result < 0)
1509  {
1510  $this->error[]=$contractline->error;
1511  $error++;
1512  }
1513  }
1514 
1515  if (empty($error)) {
1516  // Call trigger
1517  $result=$this->call_trigger('LINECONTRACT_INSERT',$user);
1518  if ($result < 0)
1519  {
1520  $error++;
1521  }
1522  // End call triggers
1523  }
1524 
1525  if ($error)
1526  {
1527  $this->db->rollback();
1528  return -1;
1529  }
1530  else
1531  {
1532  $this->db->commit();
1533  return $contractlineid;
1534  }
1535  }
1536  else
1537  {
1538  $this->db->rollback();
1539  $this->error=$this->db->error()." sql=".$sql;
1540  return -1;
1541  }
1542  }
1543  else
1544  {
1545  dol_syslog(get_class($this)."::addline ErrorTryToAddLineOnValidatedContract", LOG_ERR);
1546  return -2;
1547  }
1548  }
1549 
1573  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)
1574  {
1575  global $user, $conf, $langs, $mysoc;
1576 
1577  $error=0;
1578 
1579  // Clean parameters
1580  $qty=trim($qty);
1581  $desc=trim($desc);
1582  $desc=trim($desc);
1583  $price = price2num($pu);
1584  $tvatx = price2num($tvatx);
1585  $localtax1tx = price2num($localtax1tx);
1586  $localtax2tx = price2num($localtax2tx);
1587  $pa_ht=price2num($pa_ht);
1588  if (empty($fk_fournprice)) $fk_fournprice=0;
1589 
1590  $subprice = $price;
1591  $remise = 0;
1592  if (dol_strlen($remise_percent) > 0)
1593  {
1594  $remise = round(($pu * $remise_percent / 100), 2);
1595  $price = $pu - $remise;
1596  }
1597  else
1598  {
1599  $remise_percent=0;
1600  }
1601 
1602  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");
1603 
1604  $this->db->begin();
1605 
1606  // Calcul du total TTC et de la TVA pour la ligne a partir de
1607  // qty, pu, remise_percent et tvatx
1608  // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
1609  // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
1610 
1611  $localtaxes_type=getLocalTaxesFromRate($tvatx, 0, $this->societe, $mysoc);
1612  $tvatx = preg_replace('/\s*\(.*\)/','',$tvatx); // Remove code into vatrate.
1613 
1614  $tabprice=calcul_price_total($qty, $pu, $remise_percent, $tvatx, $localtax1tx, $localtax2tx, 0, $price_base_type, $info_bits, 1, $mysoc, $localtaxes_type);
1615  $total_ht = $tabprice[0];
1616  $total_tva = $tabprice[1];
1617  $total_ttc = $tabprice[2];
1618  $total_localtax1= $tabprice[9];
1619  $total_localtax2= $tabprice[10];
1620 
1621  $localtax1_type=$localtaxes_type[0];
1622  $localtax2_type=$localtaxes_type[2];
1623 
1624  // TODO A virer
1625  // Anciens indicateurs: $price, $remise (a ne plus utiliser)
1626  $remise = 0;
1627  $price = price2num(round($pu, 2));
1628  if (dol_strlen($remise_percent) > 0)
1629  {
1630  $remise = round(($pu * $remise_percent / 100), 2);
1631  $price = $pu - $remise;
1632  }
1633 
1634  if (empty($pa_ht)) $pa_ht=0;
1635 
1636  // if buy price not defined, define buyprice as configured in margin admin
1637  if ($this->pa_ht == 0)
1638  {
1639  if (($result = $this->defineBuyPrice($pu_ht, $remise_percent)) < 0)
1640  {
1641  return $result;
1642  }
1643  else
1644  {
1645  $pa_ht = $result;
1646  }
1647  }
1648 
1649  $sql = "UPDATE ".MAIN_DB_PREFIX."contratdet set description='".$this->db->escape($desc)."'";
1650  $sql.= ",price_ht='" . price2num($price)."'";
1651  $sql.= ",subprice='" . price2num($subprice)."'";
1652  $sql.= ",remise='" . price2num($remise)."'";
1653  $sql.= ",remise_percent='".price2num($remise_percent)."'";
1654  $sql.= ",qty='".$qty."'";
1655  $sql.= ",tva_tx='". price2num($tvatx)."'";
1656  $sql.= ",localtax1_tx='". price2num($localtax1tx)."'";
1657  $sql.= ",localtax2_tx='". price2num($localtax2tx)."'";
1658  $sql.= ",localtax1_type='".$localtax1_type."'";
1659  $sql.= ",localtax2_type='".$localtax2_type."'";
1660  $sql.= ", total_ht='". price2num($total_ht)."'";
1661  $sql.= ", total_tva='". price2num($total_tva)."'";
1662  $sql.= ", total_localtax1='".price2num($total_localtax1)."'";
1663  $sql.= ", total_localtax2='".price2num($total_localtax2)."'";
1664  $sql.= ", total_ttc='". price2num($total_ttc)."'";
1665  $sql.= ", fk_product_fournisseur_price=".($fk_fournprice > 0 ? $fk_fournprice : "null");
1666  $sql.= ", buy_price_ht='".price2num($pa_ht)."'";
1667  if ($date_start > 0) { $sql.= ",date_ouverture_prevue='".$this->db->idate($date_start)."'"; }
1668  else { $sql.=",date_ouverture_prevue=null"; }
1669  if ($date_end > 0) { $sql.= ",date_fin_validite='".$this->db->idate($date_end)."'"; }
1670  else { $sql.=",date_fin_validite=null"; }
1671  if ($date_debut_reel > 0) { $sql.= ",date_ouverture='".$this->db->idate($date_debut_reel)."'"; }
1672  else { $sql.=",date_ouverture=null"; }
1673  if ($date_fin_reel > 0) { $sql.= ",date_cloture='".$this->db->idate($date_fin_reel)."'"; }
1674  else { $sql.=",date_cloture=null"; }
1675  $sql .= ", fk_unit=".($fk_unit?"'".$this->db->escape($fk_unit)."'":"null");
1676  $sql .= " WHERE rowid = ".$rowid;
1677 
1678  dol_syslog(get_class($this)."::updateline", LOG_DEBUG);
1679  $result = $this->db->query($sql);
1680  if ($result)
1681  {
1682  $result=$this->update_statut($user);
1683  if ($result >= 0)
1684  {
1685 
1686  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($array_options) && count($array_options)>0) // For avoid conflicts if trigger used
1687  {
1688  $contractline = new ContratLigne($this->db);
1689  $contractline->array_options=$array_options;
1690  $contractline->id= $rowid;
1691  $result=$contractline->insertExtraFields();
1692  if ($result < 0)
1693  {
1694  $this->error[]=$contractline->error;
1695  $error++;
1696  }
1697  }
1698 
1699  if (empty($error)) {
1700  // Call trigger
1701  $result=$this->call_trigger('LINECONTRACT_UPDATE',$user);
1702  if ($result < 0)
1703  {
1704  $this->db->rollback();
1705  return -3;
1706  }
1707  // End call triggers
1708 
1709  $this->db->commit();
1710  return 1;
1711  }
1712  }
1713  else
1714  {
1715  $this->db->rollback();
1716  dol_syslog(get_class($this)."::updateline Erreur -2");
1717  return -2;
1718  }
1719  }
1720  else
1721  {
1722  $this->db->rollback();
1723  $this->error=$this->db->error();
1724  dol_syslog(get_class($this)."::updateline Erreur -1");
1725  return -1;
1726  }
1727  }
1728 
1736  function deleteline($idline, User $user)
1737  {
1738  global $conf, $langs;
1739 
1740  $error=0;
1741 
1742  if ($this->statut >= 0)
1743  {
1744 
1745  // Call trigger
1746  $result=$this->call_trigger('LINECONTRACT_DELETE',$user);
1747  if ($result < 0) return -1;
1748  // End call triggers
1749 
1750  $this->db->begin();
1751 
1752  $sql = "DELETE FROM ".MAIN_DB_PREFIX."contratdet";
1753  $sql.= " WHERE rowid=".$idline;
1754 
1755  dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1756  $resql = $this->db->query($sql);
1757  if (! $resql)
1758  {
1759  $this->error="Error ".$this->db->lasterror();
1760  $error++;
1761  }
1762 
1763  if (empty($error)) {
1764  // Remove extrafields
1765  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
1766  {
1767  $contractline = new ContratLigne($this->db);
1768  $contractline->id= $idline;
1769  $result=$contractline->deleteExtraFields();
1770  if ($result < 0)
1771  {
1772  $error++;
1773  $this->error="Error ".get_class($this)."::delete deleteExtraFields error -4 ".$contractline->error;
1774  }
1775  }
1776  }
1777 
1778  if (empty($error)) {
1779  $this->db->commit();
1780  return 1;
1781  } else {
1782  dol_syslog(get_class($this)."::delete ERROR:".$this->error, LOG_ERR);
1783  $this->db->rollback();
1784  return -1;
1785  }
1786  }
1787  else
1788  {
1789  $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
1790  return -2;
1791  }
1792  }
1793 
1794 
1795  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1803  function update_statut($user)
1804  {
1805  // phpcs:enable
1806  dol_syslog(__METHOD__ . " is deprecated", LOG_WARNING);
1807 
1808  // If draft, we keep it (should not happen)
1809  if ($this->statut == 0) return 1;
1810 
1811  // Load $this->lines array
1812  // $this->fetch_lines();
1813 
1814 // $newstatut=1;
1815 // foreach($this->lines as $key => $contractline)
1816 // {
1817 // // if ($contractline) // Loop on each service
1818 // }
1819 
1820  return 1;
1821  }
1822 
1823 
1830  function getLibStatut($mode)
1831  {
1832  return $this->LibStatut($this->statut,$mode);
1833  }
1834 
1835  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
1843  function LibStatut($statut,$mode)
1844  {
1845  // phpcs:enable
1846  global $langs;
1847  $langs->load("contracts");
1848  if ($mode == 0)
1849  {
1850  if ($statut == 0) { return $langs->trans("ContractStatusDraft"); }
1851  elseif ($statut == 1) { return $langs->trans("ContractStatusValidated"); }
1852  elseif ($statut == 2) { return $langs->trans("ContractStatusClosed"); }
1853  }
1854  elseif ($mode == 1)
1855  {
1856  if ($statut == 0) { return $langs->trans("ContractStatusDraft"); }
1857  elseif ($statut == 1) { return $langs->trans("ContractStatusValidated"); }
1858  elseif ($statut == 2) { return $langs->trans("ContractStatusClosed"); }
1859  }
1860  elseif ($mode == 2)
1861  {
1862  if ($statut == 0) { return img_picto($langs->trans('ContractStatusDraft'),'statut0').' '.$langs->trans("ContractStatusDraft"); }
1863  elseif ($statut == 1) { return img_picto($langs->trans('ContractStatusValidated'),'statut4').' '.$langs->trans("ContractStatusValidated"); }
1864  elseif ($statut == 2) { return img_picto($langs->trans('ContractStatusClosed'),'statut6').' '.$langs->trans("ContractStatusClosed"); }
1865  }
1866  elseif ($mode == 3)
1867  {
1868  if ($statut == 0) { return img_picto($langs->trans('ContractStatusDraft'),'statut0'); }
1869  elseif ($statut == 1) { return img_picto($langs->trans('ContractStatusValidated'),'statut4'); }
1870  elseif ($statut == 2) { return img_picto($langs->trans('ContractStatusClosed'),'statut6'); }
1871  }
1872  elseif ($mode == 4 || $mode == 6 || $mode == 7)
1873  {
1874  $text='';
1875  if ($mode == 4)
1876  {
1877  $text ='<span class="hideonsmartphone">';
1878  $text.=($this->nbofserviceswait+$this->nbofservicesopened+$this->nbofservicesexpired+$this->nbofservicesclosed);
1879  $text.=' '.$langs->trans("Services");
1880  $text.=': &nbsp; &nbsp; ';
1881  $text.='</span>';
1882  }
1883  $text.=($mode == 7?'<div class="inline-block">':'');
1884  $text.=($mode != 7 || $this->nbofserviceswait > 0) ? ($this->nbofserviceswait.ContratLigne::LibStatut(0,3,-1,'class="paddingleft2 inline-block valigntextbottom"')).(($mode != 7 || $this->nbofservicesopened || $this->nbofservicesexpired || $this->nbofservicesclosed)?' &nbsp; ':'') : '';
1885  $text.=($mode == 7?'</div><div class="inline-block">':'');
1886  $text.=($mode != 7 || $this->nbofservicesopened > 0) ? ($this->nbofservicesopened.ContratLigne::LibStatut(4,3,0,'class="paddingleft2 inline-block valigntextbottom"')).(($mode != 7 || $this->nbofservicesexpired || $this->nbofservicesclosed)?' &nbsp; ':'') : '';
1887  $text.=($mode == 7?'</div><div class="inline-block">':'');
1888  $text.=($mode != 7 || $this->nbofservicesexpired > 0) ? ($this->nbofservicesexpired.ContratLigne::LibStatut(4,3,1,'class="paddingleft2 inline-block valigntextbottom"')).(($mode != 7 || $this->nbofservicesclosed)?' &nbsp; ':'') : '';
1889  $text.=($mode == 7?'</div><div class="inline-block">':'');
1890  $text.=($mode != 7 || $this->nbofservicesclosed > 0) ? ($this->nbofservicesclosed.ContratLigne::LibStatut(5,3,-1,'class="paddingleft2 inline-block valigntextbottom"')) : '';
1891  $text.=($mode == 7?'</div>':'');
1892  return $text;
1893  }
1894  elseif ($mode == 5)
1895  {
1896  if ($statut == 0) { return $langs->trans("ContractStatusDraft").' '.img_picto($langs->trans('ContractStatusDraft'),'statut0'); }
1897  elseif ($statut == 1) { return $langs->trans("ContractStatusValidated").' '.img_picto($langs->trans('ContractStatusValidated'),'statut4'); }
1898  elseif ($statut == 2) { return $langs->trans("ContractStatusClosed").' '.img_picto($langs->trans('ContractStatusClosed'),'statut6'); }
1899  }
1900  }
1901 
1902 
1912  function getNomUrl($withpicto=0, $maxlength=0, $notooltip=0, $save_lastsearch_value=-1)
1913  {
1914  global $conf, $langs, $user;
1915 
1916  $result='';
1917 
1918  $url = DOL_URL_ROOT.'/contrat/card.php?id='.$this->id;
1919 
1920  //if ($option !== 'nolink')
1921  //{
1922  // Add param to save lastsearch_values or not
1923  $add_save_lastsearch_values=($save_lastsearch_value == 1 ? 1 : 0);
1924  if ($save_lastsearch_value == -1 && preg_match('/list\.php/',$_SERVER["PHP_SELF"])) $add_save_lastsearch_values=1;
1925  if ($add_save_lastsearch_values) $url.='&save_lastsearch_values=1';
1926  //}
1927 
1928  $label = '';
1929 
1930  if ($user->rights->contrat->lire) {
1931  $label = '<u>'.$langs->trans("ShowContract").'</u>';
1932  $label .= '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
1933  $label .= '<br><b>'.$langs->trans('RefCustomer').':</b> '.($this->ref_customer ? $this->ref_customer : $this->ref_client);
1934  $label .= '<br><b>'.$langs->trans('RefSupplier').':</b> '.$this->ref_supplier;
1935  if (!empty($this->total_ht)) {
1936  $label .= '<br><b>'.$langs->trans('AmountHT').':</b> '.price($this->total_ht, 0, $langs, 0, -1, -1, $conf->currency);
1937  }
1938  if (!empty($this->total_tva)) {
1939  $label .= '<br><b>'.$langs->trans('VAT').':</b> '.price($this->total_tva, 0, $langs, 0, -1, -1, $conf->currency);
1940  }
1941  if (!empty($this->total_ttc)) {
1942  $label .= '<br><b>'.$langs->trans('AmountTTC').':</b> '.price($this->total_ttc, 0, $langs, 0, -1, -1, $conf->currency);
1943  }
1944  }
1945 
1946  $linkclose='';
1947  if (empty($notooltip) && $user->rights->contrat->lire)
1948  {
1949  if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
1950  {
1951  $label=$langs->trans("ShowOrder");
1952  $linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"';
1953  }
1954  $linkclose.= ' title="'.dol_escape_htmltag($label, 1).'"';
1955  $linkclose.=' class="classfortooltip"';
1956  }
1957 
1958  $linkstart = '<a href="'.$url.'"';
1959  $linkstart.=$linkclose.'>';
1960  $linkend='</a>';
1961 
1962  $result .= $linkstart;
1963  if ($withpicto) $result.=img_object(($notooltip?'':$label), $this->picto, ($notooltip?(($withpicto != 2) ? 'class="paddingright"' : ''):'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip?0:1);
1964  if ($withpicto != 2) $result.= $this->ref;
1965  $result .= $linkend;
1966 
1967  return $result;
1968  }
1969 
1976  function info($id)
1977  {
1978  $sql = "SELECT c.rowid, c.ref, c.datec, c.date_cloture,";
1979  $sql.= " c.tms as date_modification,";
1980  $sql.= " fk_user_author, fk_user_cloture";
1981  $sql.= " FROM ".MAIN_DB_PREFIX."contrat as c";
1982  $sql.= " WHERE c.rowid = ".$id;
1983 
1984  $result=$this->db->query($sql);
1985  if ($result)
1986  {
1987  if ($this->db->num_rows($result))
1988  {
1989  $obj = $this->db->fetch_object($result);
1990 
1991  $this->id = $obj->rowid;
1992 
1993  if ($obj->fk_user_author) {
1994  $cuser = new User($this->db);
1995  $cuser->fetch($obj->fk_user_author);
1996  $this->user_creation = $cuser;
1997  }
1998 
1999  if ($obj->fk_user_cloture) {
2000  $cuser = new User($this->db);
2001  $cuser->fetch($obj->fk_user_cloture);
2002  $this->user_cloture = $cuser;
2003  }
2004  $this->ref = (! $obj->ref) ? $obj->rowid : $obj->ref;
2005  $this->date_creation = $this->db->jdate($obj->datec);
2006  $this->date_modification = $this->db->jdate($obj->date_modification);
2007  $this->date_cloture = $this->db->jdate($obj->date_cloture);
2008  }
2009 
2010  $this->db->free($result);
2011  }
2012  else
2013  {
2014  dol_print_error($this->db);
2015  }
2016  }
2017 
2018  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2025  function array_detail($statut=-1)
2026  {
2027  // phpcs:enable
2028  $tab=array();
2029 
2030  $sql = "SELECT cd.rowid";
2031  $sql.= " FROM ".MAIN_DB_PREFIX."contratdet as cd";
2032  $sql.= " WHERE fk_contrat =".$this->id;
2033  if ($statut >= 0) $sql.= " AND statut = '$statut'";
2034 
2035  dol_syslog(get_class($this)."::array_detail()", LOG_DEBUG);
2036  $resql=$this->db->query($sql);
2037  if ($resql)
2038  {
2039  $num=$this->db->num_rows($resql);
2040  $i=0;
2041  while ($i < $num)
2042  {
2043  $obj = $this->db->fetch_object($resql);
2044  $tab[$i]=$obj->rowid;
2045  $i++;
2046  }
2047  return $tab;
2048  }
2049  else
2050  {
2051  $this->error=$this->db->error();
2052  return -1;
2053  }
2054  }
2055 
2062  function getListOfContracts($option='all')
2063  {
2064  $tab=array();
2065 
2066  $sql = "SELECT c.rowid, c.ref";
2067  $sql.= " FROM ".MAIN_DB_PREFIX."contrat as c";
2068  $sql.= " WHERE fk_soc =".$this->socid;
2069  if ($option == 'others') $sql.= " AND c.rowid != ".$this->id;
2070 
2071  dol_syslog(get_class($this)."::getOtherContracts()", LOG_DEBUG);
2072  $resql=$this->db->query($sql);
2073  if ($resql)
2074  {
2075  $num=$this->db->num_rows($resql);
2076  $i=0;
2077  while ($i < $num)
2078  {
2079  $obj = $this->db->fetch_object($resql);
2080  $contrat=new Contrat($this->db);
2081  $contrat->fetch($obj->rowid);
2082  $tab[]=$contrat;
2083  $i++;
2084  }
2085  return $tab;
2086  }
2087  else
2088  {
2089  $this->error=$this->db->error();
2090  return -1;
2091  }
2092  }
2093 
2094 
2095  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2103  function load_board($user,$mode)
2104  {
2105  // phpcs:enable
2106  global $conf, $langs;
2107 
2108  $this->from = " FROM ".MAIN_DB_PREFIX."contrat as c";
2109  $this->from.= ", ".MAIN_DB_PREFIX."contratdet as cd";
2110  $this->from.= ", ".MAIN_DB_PREFIX."societe as s";
2111  if (!$user->rights->societe->client->voir && !$user->societe_id) $this->from.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
2112 
2113  if ($mode == 'inactives')
2114  {
2115  $sql = "SELECT cd.rowid, cd.date_ouverture_prevue as datefin";
2116  $sql.= $this->from;
2117  $sql.= " WHERE c.statut = 1";
2118  $sql.= " AND c.rowid = cd.fk_contrat";
2119  $sql.= " AND cd.statut = 0";
2120  }
2121  elseif ($mode == 'expired')
2122  {
2123  $sql = "SELECT cd.rowid, cd.date_fin_validite as datefin";
2124  $sql.= $this->from;
2125  $sql.= " WHERE c.statut = 1";
2126  $sql.= " AND c.rowid = cd.fk_contrat";
2127  $sql.= " AND cd.statut = 4";
2128  $sql.= " AND cd.date_fin_validite < '".$this->db->idate(time())."'";
2129  }
2130  $sql.= " AND c.fk_soc = s.rowid";
2131  $sql.= " AND c.entity = ".$conf->entity;
2132  if ($user->societe_id) $sql.=" AND c.fk_soc = ".$user->societe_id;
2133  if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " AND c.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id;
2134  $resql=$this->db->query($sql);
2135  if ($resql)
2136  {
2137  $langs->load("contracts");
2138  $now=dol_now();
2139 
2140  if ($mode == 'inactives') {
2141  $warning_delay = $conf->contrat->services->inactifs->warning_delay;
2142  $label = $langs->trans("BoardNotActivatedServices");
2143  $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&amp;leftmenu=contracts&amp;mode=0';
2144  } else {
2145  $warning_delay = $conf->contrat->services->expires->warning_delay;
2146  $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&amp;leftmenu=contracts&amp;mode=4&amp;filter=expired';
2147  $label = $langs->trans("BoardRunningServices");
2148  }
2149 
2150  $response = new WorkboardResponse();
2151  $response->warning_delay = $warning_delay/60/60/24;
2152  $response->label = $label;
2153  $response->url = $url;
2154  $response->img = img_object('',"contract");
2155 
2156  while ($obj=$this->db->fetch_object($resql))
2157  {
2158  $response->nbtodo++;
2159 
2160  if ($obj->datefin && $this->db->jdate($obj->datefin) < ($now - $warning_delay)) {
2161  $response->nbtodolate++;
2162  }
2163  }
2164 
2165  return $response;
2166  }
2167  else
2168  {
2169  dol_print_error($this->db);
2170  $this->error=$this->db->error();
2171  return -1;
2172  }
2173  }
2174 
2175  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2181  function load_state_board()
2182  {
2183  // phpcs:enable
2184  global $conf, $user;
2185 
2186  $this->nb=array();
2187  $clause = "WHERE";
2188 
2189  $sql = "SELECT count(c.rowid) as nb";
2190  $sql.= " FROM ".MAIN_DB_PREFIX."contrat as c";
2191  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON c.fk_soc = s.rowid";
2192  if (!$user->rights->societe->client->voir && !$user->societe_id)
2193  {
2194  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON s.rowid = sc.fk_soc";
2195  $sql.= " WHERE sc.fk_user = " .$user->id;
2196  $clause = "AND";
2197  }
2198  $sql.= " ".$clause." c.entity = ".$conf->entity;
2199 
2200  $resql=$this->db->query($sql);
2201  if ($resql)
2202  {
2203  while ($obj=$this->db->fetch_object($resql))
2204  {
2205  $this->nb["Contracts"]=$obj->nb;
2206  }
2207  $this->db->free($resql);
2208  return 1;
2209  }
2210  else
2211  {
2212  dol_print_error($this->db);
2213  $this->error=$this->db->error();
2214  return -1;
2215  }
2216  }
2217 
2218 
2219  /* gestion des contacts d'un contrat */
2220 
2227  {
2228  return $this->getIdContact('external','BILLING');
2229  }
2230 
2237  {
2238  return $this->getIdContact('external','SERVICE');
2239  }
2240 
2241 
2249  function initAsSpecimen()
2250  {
2251  global $user,$langs,$conf;
2252 
2253  // Load array of products prodids
2254  $num_prods = 0;
2255  $prodids = array();
2256  $sql = "SELECT rowid";
2257  $sql.= " FROM ".MAIN_DB_PREFIX."product";
2258  $sql.= " WHERE entity IN (".getEntity('product').")";
2259  $sql.= " AND tosell = 1";
2260  $resql = $this->db->query($sql);
2261  if ($resql)
2262  {
2263  $num_prods = $this->db->num_rows($resql);
2264  $i = 0;
2265  while ($i < $num_prods)
2266  {
2267  $i++;
2268  $row = $this->db->fetch_row($resql);
2269  $prodids[$i] = $row[0];
2270  }
2271  }
2272 
2273  // Initialise parametres
2274  $this->id=0;
2275  $this->specimen=1;
2276 
2277  $this->ref = 'SPECIMEN';
2278  $this->ref_customer = 'SPECIMENCUST';
2279  $this->ref_supplier = 'SPECIMENSUPP';
2280  $this->socid = 1;
2281  $this->statut= 0;
2282  $this->date_creation = (dol_now() - 3600 * 24 * 7);
2283  $this->date_contrat = dol_now();
2284  $this->commercial_signature_id = 1;
2285  $this->commercial_suivi_id = 1;
2286  $this->note_private='This is a comment (private)';
2287  $this->note_public='This is a comment (public)';
2288  $this->fk_projet = 0;
2289  // Lines
2290  $nbp = 5;
2291  $xnbp = 0;
2292  while ($xnbp < $nbp)
2293  {
2294  $line=new ContratLigne($this->db);
2295  $line->qty=1;
2296  $line->subprice=100;
2297  $line->price=100;
2298  $line->tva_tx=19.6;
2299  $line->remise_percent=10;
2300  $line->total_ht=90;
2301  $line->total_ttc=107.64; // 90 * 1.196
2302  $line->total_tva=17.64;
2303  $line->date_start = dol_now() - 500000;
2304  $line->date_start_real = dol_now() - 200000;
2305  $line->date_end = dol_now() + 500000;
2306  $line->date_end_real = dol_now() - 100000;
2307  if ($num_prods > 0)
2308  {
2309  $prodid = mt_rand(1, $num_prods);
2310  $line->fk_product=$prodids[$prodid];
2311  }
2312  $this->lines[$xnbp]=$line;
2313  $xnbp++;
2314  }
2315  }
2316 
2322  function getLinesArray()
2323  {
2324  return $this->fetch_lines();
2325  }
2326 
2327 
2339  public function generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
2340  {
2341  global $conf,$langs;
2342 
2343  $langs->load("contracts");
2344 
2345  if (! dol_strlen($modele)) {
2346 
2347  $modele = 'strato';
2348 
2349  if ($this->modelpdf) {
2350  $modele = $this->modelpdf;
2351  } elseif (! empty($conf->global->CONTRACT_ADDON_PDF)) {
2352  $modele = $conf->global->CONTRACT_ADDON_PDF;
2353  }
2354  }
2355 
2356  $modelpath = "core/modules/contract/doc/";
2357 
2358  return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
2359  }
2360 
2369  public static function replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
2370  {
2371  $tables = array(
2372  'contrat'
2373  );
2374 
2375  return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
2376  }
2377 
2385  function createFromClone($socid = 0, $notrigger=0)
2386  {
2387  global $db, $user, $langs, $conf, $hookmanager, $extrafields;
2388 
2389  dol_include_once('/projet/class/project.class.php');
2390 
2391  $error = 0;
2392 
2393  $this->fetch($this->id);
2394 
2395  // Load dest object
2396  $clonedObj = clone $this;
2397  $clonedObj->socid = $socid;
2398 
2399  $this->db->begin();
2400 
2401  $objsoc = new Societe($this->db);
2402 
2403  $objsoc->fetch($clonedObj->socid);
2404 
2405  // Clean data
2406  $clonedObj->statut = 0;
2407  // Clean extrafields
2408  if (is_array($clonedObj->array_options) && count($clonedObj->array_options) > 0)
2409  {
2410  $extrafields->fetch_name_optionals_label($this->element);
2411  foreach($clonedObj->array_options as $key => $option)
2412  {
2413  $shortkey = preg_replace('/options_/', '', $key);
2414  //var_dump($shortkey); var_dump($extrafields->attributes[$this->element]['unique'][$shortkey]);
2415  if (! empty($extrafields->attributes[$this->element]['unique'][$shortkey]))
2416  {
2417  //var_dump($key); var_dump($clonedObj->array_options[$key]); exit;
2418  unset($clonedObj->array_options[$key]);
2419  }
2420  }
2421  }
2422 
2423  if (empty($conf->global->CONTRACT_ADDON) || ! is_readable(DOL_DOCUMENT_ROOT . "/core/modules/contract/" . $conf->global->CONTRACT_ADDON . ".php")) {
2424  $this->error = 'ErrorSetupNotComplete';
2425  dol_syslog($this->error);
2426  return - 1;
2427  }
2428 
2429  // Set ref
2430  require_once DOL_DOCUMENT_ROOT . "/core/modules/contract/" . $conf->global->CONTRACT_ADDON . '.php';
2431  $obj = $conf->global->CONTRACT_ADDON;
2432  $modContract = new $obj();
2433  $clonedObj->ref = $modContract->getNextValue($objsoc, $clonedObj);
2434 
2435  // get extrafields so they will be clone
2436  foreach ($this->lines as $line) {
2437  $line->fetch_optionals($line->id);
2438  }
2439 
2440  // Create clone
2441  $clonedObj->context['createfromclone'] = 'createfromclone';
2442  $result = $clonedObj->create($user);
2443  if ($result < 0) {
2444  $error ++;
2445  $this->error = $clonedObj->error;
2446  $this->errors[] = $clonedObj->error;
2447  } else {
2448  // copy external contacts if same company
2449  if ($this->socid == $clonedObj->socid) {
2450  if ($clonedObj->copy_linked_contact($this, 'external') < 0) {
2451  $error++;
2452  }
2453  }
2454  }
2455 
2456  if (! $error) {
2457  foreach ( $this->lines as $line ) {
2458  $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);
2459  if ($result < 0) {
2460  $error ++;
2461  $this->error = $clonedObj->error;
2462  $this->errors[] = $clonedObj->error;
2463  }
2464  }
2465  }
2466 
2467  if (! $error) {
2468  // Hook of thirdparty module
2469  if (is_object($hookmanager)) {
2470  $parameters = array (
2471  'objFrom' => $this,
2472  'clonedObj' => $clonedObj
2473  );
2474  $action = '';
2475  $reshook = $hookmanager->executeHooks('createFrom', $parameters, $clonedObj, $action); // Note that $action and $object may have been modified by some hooks
2476  if ($reshook < 0)
2477  $error ++;
2478  }
2479  }
2480 
2481  unset($clonedObj->context['createfromclone']);
2482 
2483  // End
2484  if (! $error) {
2485  $this->db->commit();
2486  return $clonedObj->id;
2487  } else {
2488  $this->db->rollback();
2489  return - 1;
2490  }
2491  }
2492 }
2493 
2494 
2499 {
2503  public $element='contratdet';
2504 
2508  public $table_element='contratdet';
2509 
2513  public $id;
2514 
2518  public $ref;
2519 
2520  public $tms;
2521 
2525  public $fk_contrat;
2526 
2530  public $fk_product;
2531 
2532  public $statut; // 0 inactive, 4 active, 5 closed
2533  public $type; // 0 for product, 1 for service
2534 
2539  public $label;
2540 
2545  public $libelle;
2546 
2550  public $description;
2551 
2552  public $product_ref;
2553  public $product_label;
2554 
2555  public $date_commande;
2556 
2557  public $date_start; // date start planned
2558  public $date_start_real; // date start real
2559  public $date_end; // date end planned
2560  public $date_end_real; // date end real
2561  // For backward compatibility
2562  public $date_ouverture_prevue; // date start planned
2563  public $date_ouverture; // date start real
2564  public $date_fin_validite; // date end planned
2565  public $date_cloture; // date end real
2566  public $tva_tx;
2567  public $localtax1_tx;
2568  public $localtax2_tx;
2569  public $localtax1_type; // Local tax 1 type
2570  public $localtax2_type; // Local tax 2 type
2571  public $qty;
2572  public $remise_percent;
2573  public $remise;
2574 
2578  public $fk_remise_except;
2579 
2580  public $subprice; // Unit price HT
2581 
2587  public $price;
2588 
2589  public $price_ht;
2590 
2591  public $total_ht;
2592  public $total_tva;
2593  public $total_localtax1;
2594  public $total_localtax2;
2595  public $total_ttc;
2596 
2600  public $fk_fournprice;
2601 
2602  public $pa_ht;
2603 
2604  public $info_bits;
2605 
2609  public $fk_user_author;
2610 
2614  public $fk_user_ouverture;
2615 
2619  public $fk_user_cloture;
2620 
2621  public $commentaire;
2622 
2623  const STATUS_INITIAL = 0;
2624  const STATUS_OPEN = 4;
2625  const STATUS_CLOSED = 5;
2626 
2627 
2628 
2634  function __construct($db)
2635  {
2636  $this->db = $db;
2637  }
2638 
2639 
2646  function getLibStatut($mode)
2647  {
2648  return $this->LibStatut($this->statut,$mode,((! empty($this->date_fin_validite))?($this->date_fin_validite < dol_now()?1:0):-1));
2649  }
2650 
2651  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
2661  static function LibStatut($statut,$mode,$expired=-1,$moreatt='')
2662  {
2663  // phpcs:enable
2664  global $langs;
2665  $langs->load("contracts");
2666  if ($mode == 0)
2667  {
2668  if ($statut == self::STATUS_INITIAL) { return $langs->trans("ServiceStatusInitial"); }
2669  elseif ($statut == self::STATUS_OPEN && $expired == -1) { return $langs->trans("ServiceStatusRunning"); }
2670  elseif ($statut == self::STATUS_OPEN && $expired == 0) { return $langs->trans("ServiceStatusNotLate"); }
2671  elseif ($statut == self::STATUS_OPEN && $expired == 1) { return $langs->trans("ServiceStatusLate"); }
2672  elseif ($statut == self::STATUS_CLOSED) { return $langs->trans("ServiceStatusClosed"); }
2673  }
2674  elseif ($mode == 1)
2675  {
2676  if ($statut == self::STATUS_INITIAL) { return $langs->trans("ServiceStatusInitial"); }
2677  elseif ($statut == self::STATUS_OPEN && $expired == -1) { return $langs->trans("ServiceStatusRunning"); }
2678  elseif ($statut == self::STATUS_OPEN && $expired == 0) { return $langs->trans("ServiceStatusNotLateShort"); }
2679  elseif ($statut == self::STATUS_OPEN && $expired == 1) { return $langs->trans("ServiceStatusLateShort"); }
2680  elseif ($statut == self::STATUS_CLOSED) { return $langs->trans("ServiceStatusClosed"); }
2681  }
2682  elseif ($mode == 2)
2683  {
2684  if ($statut == self::STATUS_INITIAL) { return img_picto($langs->trans('ServiceStatusInitial'),'statut0').' '.$langs->trans("ServiceStatusInitial"); }
2685  elseif ($statut == self::STATUS_OPEN && $expired == -1) { return img_picto($langs->trans('ServiceStatusRunning'),'statut4').' '.$langs->trans("ServiceStatusRunning"); }
2686  elseif ($statut == self::STATUS_OPEN && $expired == 0) { return img_picto($langs->trans('ServiceStatusNotLate'),'statut4').' '.$langs->trans("ServiceStatusNotLateShort"); }
2687  elseif ($statut == self::STATUS_OPEN && $expired == 1) { return img_picto($langs->trans('ServiceStatusLate'),'statut3').' '.$langs->trans("ServiceStatusLateShort"); }
2688  elseif ($statut == self::STATUS_CLOSED) { return img_picto($langs->trans('ServiceStatusClosed'),'statut6') .' '.$langs->trans("ServiceStatusClosed"); }
2689  }
2690  elseif ($mode == 3)
2691  {
2692  if ($statut == self::STATUS_INITIAL) { return img_picto($langs->trans('ServiceStatusInitial'),'statut0',$moreatt); }
2693  elseif ($statut == self::STATUS_OPEN && $expired == -1) { return img_picto($langs->trans('ServiceStatusRunning'),'statut4',$moreatt); }
2694  elseif ($statut == self::STATUS_OPEN && $expired == 0) { return img_picto($langs->trans('ServiceStatusNotLate'),'statut4',$moreatt); }
2695  elseif ($statut == self::STATUS_OPEN && $expired == 1) { return img_picto($langs->trans('ServiceStatusLate'),'statut3',$moreatt); }
2696  elseif ($statut == self::STATUS_CLOSED) { return img_picto($langs->trans('ServiceStatusClosed'),'statut6',$moreatt); }
2697  }
2698  elseif ($mode == 4)
2699  {
2700  if ($statut == self::STATUS_INITIAL) { return img_picto($langs->trans('ServiceStatusInitial'),'statut0').' '.$langs->trans("ServiceStatusInitial"); }
2701  elseif ($statut == self::STATUS_OPEN && $expired == -1) { return img_picto($langs->trans('ServiceStatusRunning'),'statut4').' '.$langs->trans("ServiceStatusRunning"); }
2702  elseif ($statut == self::STATUS_OPEN && $expired == 0) { return img_picto($langs->trans('ServiceStatusNotLate'),'statut4').' '.$langs->trans("ServiceStatusNotLate"); }
2703  elseif ($statut == self::STATUS_OPEN && $expired == 1) { return img_picto($langs->trans('ServiceStatusLate'),'statut3').' '.$langs->trans("ServiceStatusLate"); }
2704  elseif ($statut == self::STATUS_CLOSED) { return img_picto($langs->trans('ServiceStatusClosed'),'statut6') .' '.$langs->trans("ServiceStatusClosed"); }
2705  }
2706  elseif ($mode == 5)
2707  {
2708  if ($statut == self::STATUS_INITIAL) { return $langs->trans("ServiceStatusInitial").' '.img_picto($langs->trans('ServiceStatusInitial'),'statut0'); }
2709  elseif ($statut == self::STATUS_OPEN && $expired == -1) { return $langs->trans("ServiceStatusRunning").' '.img_picto($langs->trans('ServiceStatusRunning'),'statut4'); }
2710  elseif ($statut == self::STATUS_OPEN && $expired == 0) { return $langs->trans("ServiceStatusNotLateShort").' '.img_picto($langs->trans('ServiceStatusNotLateShort'),'statut4'); }
2711  elseif ($statut == self::STATUS_OPEN && $expired == 1) { return $langs->trans("ServiceStatusLateShort").' '.img_picto($langs->trans('ServiceStatusLate'),'statut3'); }
2712  elseif ($statut == self::STATUS_CLOSED) { return $langs->trans("ServiceStatusClosed").' '.img_picto($langs->trans('ServiceStatusClosed'),'statut6'); }
2713  }
2714  }
2715 
2723  function getNomUrl($withpicto=0,$maxlength=0)
2724  {
2725  global $langs;
2726 
2727  $result='';
2728  $label=$langs->trans("ShowContractOfService").': '.$this->label;
2729  if (empty($label)) $label=$this->description;
2730 
2731  $link = '<a href="'.DOL_URL_ROOT.'/contrat/card.php?id='.$this->fk_contrat.'" title="'.dol_escape_htmltag($label, 1).'" class="classfortooltip">';
2732  $linkend='</a>';
2733 
2734  $picto='service';
2735  if ($this->type == 0) $picto='product';
2736 
2737  if ($withpicto) $result.=($link.img_object($label, $picto, 'class="classfortooltip"').$linkend);
2738  if ($withpicto && $withpicto != 2) $result.=' ';
2739  if ($withpicto != 2) $result.=$link.($this->product_ref?$this->product_ref.' ':'').($this->label?$this->label:$this->description).$linkend;
2740  return $result;
2741  }
2742 
2750  function fetch($id, $ref='')
2751  {
2752 
2753  // Check parameters
2754  if (empty($id) && empty($ref)) return -1;
2755 
2756  $sql = "SELECT";
2757  $sql.= " t.rowid,";
2758 
2759  $sql.= " t.tms,";
2760  $sql.= " t.fk_contrat,";
2761  $sql.= " t.fk_product,";
2762  $sql.= " t.statut,";
2763  $sql.= " t.label,"; // This field is not used. Only label of product
2764  $sql.= " p.ref as product_ref,";
2765  $sql.= " p.label as product_label,";
2766  $sql.= " p.description as product_desc,";
2767  $sql.= " p.fk_product_type as product_type,";
2768  $sql.= " t.description,";
2769  $sql.= " t.date_commande,";
2770  $sql.= " t.date_ouverture_prevue as date_ouverture_prevue,";
2771  $sql.= " t.date_ouverture as date_ouverture,";
2772  $sql.= " t.date_fin_validite as date_fin_validite,";
2773  $sql.= " t.date_cloture as date_cloture,";
2774  $sql.= " t.tva_tx,";
2775  $sql.= " t.vat_src_code,";
2776  $sql.= " t.localtax1_tx,";
2777  $sql.= " t.localtax2_tx,";
2778  $sql.= " t.localtax1_type,";
2779  $sql.= " t.localtax2_type,";
2780  $sql.= " t.qty,";
2781  $sql.= " t.remise_percent,";
2782  $sql.= " t.remise,";
2783  $sql.= " t.fk_remise_except,";
2784  $sql.= " t.subprice,";
2785  $sql.= " t.price_ht,";
2786  $sql.= " t.total_ht,";
2787  $sql.= " t.total_tva,";
2788  $sql.= " t.total_localtax1,";
2789  $sql.= " t.total_localtax2,";
2790  $sql.= " t.total_ttc,";
2791  $sql.= " t.fk_product_fournisseur_price as fk_fournprice,";
2792  $sql.= " t.buy_price_ht as pa_ht,";
2793  $sql.= " t.info_bits,";
2794  $sql.= " t.fk_user_author,";
2795  $sql.= " t.fk_user_ouverture,";
2796  $sql.= " t.fk_user_cloture,";
2797  $sql.= " t.commentaire,";
2798  $sql.= " t.fk_unit";
2799  $sql.= " FROM ".MAIN_DB_PREFIX."contratdet as t LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = t.fk_product";
2800  if ($id) $sql.= " WHERE t.rowid = ".$id;
2801  if ($ref) $sql.= " WHERE t.rowid = '".$this->db->escape($ref)."'";
2802 
2803  dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
2804  $resql=$this->db->query($sql);
2805  if ($resql)
2806  {
2807  if ($this->db->num_rows($resql))
2808  {
2809  $obj = $this->db->fetch_object($resql);
2810 
2811  $this->id = $obj->rowid;
2812  $this->ref = $obj->rowid;
2813 
2814  $this->tms = $this->db->jdate($obj->tms);
2815  $this->fk_contrat = $obj->fk_contrat;
2816  $this->fk_product = $obj->fk_product;
2817  $this->statut = $obj->statut;
2818  $this->product_ref = $obj->product_ref;
2819  $this->product_label = $obj->product_label;
2820  $this->product_description = $obj->product_description;
2821  $this->product_type = $obj->product_type;
2822  $this->label = $obj->label; // deprecated. We do not use this field. Only ref and label of product, and description of contract line
2823  $this->description = $obj->description;
2824  $this->date_commande = $this->db->jdate($obj->date_commande);
2825 
2826  $this->date_start = $this->db->jdate($obj->date_ouverture_prevue);
2827  $this->date_start_real = $this->db->jdate($obj->date_ouverture);
2828  $this->date_end = $this->db->jdate($obj->date_fin_validite);
2829  $this->date_end_real = $this->db->jdate($obj->date_cloture);
2830  // For backward compatibility
2831  $this->date_ouverture_prevue = $this->db->jdate($obj->date_ouverture_prevue);
2832  $this->date_ouverture = $this->db->jdate($obj->date_ouverture);
2833  $this->date_fin_validite = $this->db->jdate($obj->date_fin_validite);
2834  $this->date_cloture = $this->db->jdate($obj->date_cloture);
2835 
2836  $this->tva_tx = $obj->tva_tx;
2837  $this->vat_src_code = $obj->vat_src_code;
2838  $this->localtax1_tx = $obj->localtax1_tx;
2839  $this->localtax2_tx = $obj->localtax2_tx;
2840  $this->localtax1_type = $obj->localtax1_type;
2841  $this->localtax2_type = $obj->localtax2_type;
2842  $this->qty = $obj->qty;
2843  $this->remise_percent = $obj->remise_percent;
2844  $this->remise = $obj->remise;
2845  $this->fk_remise_except = $obj->fk_remise_except;
2846  $this->subprice = $obj->subprice;
2847  $this->price_ht = $obj->price_ht;
2848  $this->total_ht = $obj->total_ht;
2849  $this->total_tva = $obj->total_tva;
2850  $this->total_localtax1 = $obj->total_localtax1;
2851  $this->total_localtax2 = $obj->total_localtax2;
2852  $this->total_ttc = $obj->total_ttc;
2853  $this->info_bits = $obj->info_bits;
2854  $this->fk_user_author = $obj->fk_user_author;
2855  $this->fk_user_ouverture = $obj->fk_user_ouverture;
2856  $this->fk_user_cloture = $obj->fk_user_cloture;
2857  $this->commentaire = $obj->commentaire;
2858  $this->fk_fournprice = $obj->fk_fournprice;
2859  $marginInfos = getMarginInfos($obj->subprice, $obj->remise_percent, $obj->tva_tx, $obj->localtax1_tx, $obj->localtax2_tx, $this->fk_fournprice, $obj->pa_ht);
2860  $this->pa_ht = $marginInfos[0];
2861  $this->fk_unit = $obj->fk_unit;
2862  }
2863  $this->db->free($resql);
2864 
2865  return 1;
2866  }
2867  else
2868  {
2869  $this->error="Error ".$this->db->lasterror();
2870  return -1;
2871  }
2872  }
2873 
2874 
2882  function update($user, $notrigger=0)
2883  {
2884  global $conf, $langs, $mysoc;
2885 
2886  $error=0;
2887 
2888  // Clean parameters
2889  $this->fk_contrat = (int) $this->fk_contrat;
2890  $this->fk_product = (int) $this->fk_product;
2891  $this->statut = (int) $this->statut;
2892  $this->label=trim($this->label);
2893  $this->description=trim($this->description);
2894  $this->vat_src_code=trim($this->vat_src_code);
2895  $this->tva_tx=trim($this->tva_tx);
2896  $this->localtax1_tx=trim($this->localtax1_tx);
2897  $this->localtax2_tx=trim($this->localtax2_tx);
2898  $this->qty=trim($this->qty);
2899  $this->remise_percent=trim($this->remise_percent);
2900  $this->remise=trim($this->remise);
2901  $this->fk_remise_except = (int) $this->fk_remise_except;
2902  $this->subprice=price2num($this->subprice);
2903  $this->price_ht=price2num($this->price_ht);
2904  $this->total_ht=trim($this->total_ht);
2905  $this->total_tva=trim($this->total_tva);
2906  $this->total_localtax1=trim($this->total_localtax1);
2907  $this->total_localtax2=trim($this->total_localtax2);
2908  $this->total_ttc=trim($this->total_ttc);
2909  $this->info_bits=trim($this->info_bits);
2910  $this->fk_user_author = (int) $this->fk_user_author;
2911  $this->fk_user_ouverture = (int) $this->fk_user_ouverture;
2912  $this->fk_user_cloture = (int) $this->fk_user_cloture;
2913  $this->commentaire=trim($this->commentaire);
2914  //if (empty($this->subprice)) $this->subprice = 0;
2915  if (empty($this->price_ht)) $this->price_ht = 0;
2916  if (empty($this->total_ht)) $this->total_ht = 0;
2917  if (empty($this->total_tva)) $this->total_tva = 0;
2918  if (empty($this->total_ttc)) $this->total_ttc = 0;
2919  if (empty($this->localtax1_tx)) $this->localtax1_tx = 0;
2920  if (empty($this->localtax2_tx)) $this->localtax2_tx = 0;
2921  if (empty($this->remise_percent)) $this->remise_percent = 0;
2922  // For backward compatibility
2923  if (empty($this->date_start)) $this->date_start=$this->date_ouverture_prevue;
2924  if (empty($this->date_start_real)) $this->date_start=$this->date_ouverture;
2925  if (empty($this->date_end)) $this->date_start=$this->date_fin_validite;
2926  if (empty($this->date_end_real)) $this->date_start=$this->date_cloture;
2927 
2928 
2929  // Check parameters
2930  // Put here code to add control on parameters values
2931 
2932  // Calcul du total TTC et de la TVA pour la ligne a partir de
2933  // qty, pu, remise_percent et txtva
2934  // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
2935  // la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
2936  $localtaxes_type = getLocalTaxesFromRate($this->txtva, 0, $this->societe, $mysoc);
2937 
2938  $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);
2939  $this->total_ht = $tabprice[0];
2940  $this->total_tva = $tabprice[1];
2941  $this->total_ttc = $tabprice[2];
2942  $this->total_localtax1= $tabprice[9];
2943  $this->total_localtax2= $tabprice[10];
2944 
2945  if (empty($this->pa_ht)) $this->pa_ht=0;
2946 
2947  // if buy price not defined, define buyprice as configured in margin admin
2948  if ($this->pa_ht == 0)
2949  {
2950  if (($result = $this->defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product)) < 0)
2951  {
2952  return $result;
2953  }
2954  else
2955  {
2956  $this->pa_ht = $result;
2957  }
2958  }
2959 
2960 
2961  $this->db->begin();
2962 
2963  $this->oldcopy = new ContratLigne($this->db);
2964  $this->oldcopy->fetch($this->id);
2965 
2966  // Update request
2967  $sql = "UPDATE ".MAIN_DB_PREFIX."contratdet SET";
2968  $sql.= " fk_contrat=".$this->fk_contrat.",";
2969  $sql.= " fk_product=".($this->fk_product?"'".$this->db->escape($this->fk_product)."'":'null').",";
2970  $sql.= " statut=".$this->statut.",";
2971  $sql.= " label='".$this->db->escape($this->label)."',";
2972  $sql.= " description='".$this->db->escape($this->description)."',";
2973  $sql.= " date_commande=".($this->date_commande!=''?"'".$this->db->idate($this->date_commande)."'":"null").",";
2974  $sql.= " date_ouverture_prevue=".($this->date_ouverture_prevue!=''?"'".$this->db->idate($this->date_ouverture_prevue)."'":"null").",";
2975  $sql.= " date_ouverture=".($this->date_ouverture!=''?"'".$this->db->idate($this->date_ouverture)."'":"null").",";
2976  $sql.= " date_fin_validite=".($this->date_fin_validite!=''?"'".$this->db->idate($this->date_fin_validite)."'":"null").",";
2977  $sql.= " date_cloture=".($this->date_cloture!=''?"'".$this->db->idate($this->date_cloture)."'":"null").",";
2978  $sql.= " vat_src_code='".$this->db->escape($this->vat_src_code)."',";
2979  $sql.= " tva_tx=".price2num($this->tva_tx).",";
2980  $sql.= " localtax1_tx=".price2num($this->localtax1_tx).",";
2981  $sql.= " localtax2_tx=".price2num($this->localtax2_tx).",";
2982  $sql.= " qty=".price2num($this->qty).",";
2983  $sql.= " remise_percent=".price2num($this->remise_percent).",";
2984  $sql.= " remise=".($this->remise?price2num($this->remise):"null").",";
2985  $sql.= " fk_remise_except=".($this->fk_remise_except > 0?$this->fk_remise_except:"null").",";
2986  $sql.= " subprice=".($this->subprice != '' ? $this->subprice : "null").",";
2987  $sql.= " price_ht=".($this->price_ht != '' ? $this->price_ht : "null").",";
2988  $sql.= " total_ht=".$this->total_ht.",";
2989  $sql.= " total_tva=".$this->total_tva.",";
2990  $sql.= " total_localtax1=".$this->total_localtax1.",";
2991  $sql.= " total_localtax2=".$this->total_localtax2.",";
2992  $sql.= " total_ttc=".$this->total_ttc.",";
2993  $sql.= " fk_product_fournisseur_price=".(!empty($this->fk_fournprice)?$this->fk_fournprice:"NULL").",";
2994  $sql.= " buy_price_ht='".price2num($this->pa_ht)."',";
2995  $sql.= " info_bits='".$this->db->escape($this->info_bits)."',";
2996  $sql.= " fk_user_author=".($this->fk_user_author >= 0?$this->fk_user_author:"NULL").",";
2997  $sql.= " fk_user_ouverture=".($this->fk_user_ouverture > 0?$this->fk_user_ouverture:"NULL").",";
2998  $sql.= " fk_user_cloture=".($this->fk_user_cloture > 0?$this->fk_user_cloture:"NULL").",";
2999  $sql.= " commentaire='".$this->db->escape($this->commentaire)."',";
3000  $sql.= " fk_unit=".(!$this->fk_unit ? 'NULL' : $this->fk_unit);
3001  $sql.= " WHERE rowid=".$this->id;
3002 
3003  dol_syslog(get_class($this)."::update", LOG_DEBUG);
3004  $resql = $this->db->query($sql);
3005  if (! $resql)
3006  {
3007  $this->error="Error ".$this->db->lasterror();
3008  $error++;
3009  }
3010 
3011  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($this->array_options) && count($this->array_options)>0) // For avoid conflicts if trigger used
3012  {
3013  $result=$this->insertExtraFields();
3014  if ($result < 0)
3015  {
3016  $error++;
3017  }
3018  }
3019 
3020  // If we change a planned date (start or end), sync dates for all services
3021  if (! $error && ! empty($conf->global->CONTRACT_SYNC_PLANNED_DATE_OF_SERVICES))
3022  {
3023  if ($this->date_ouverture_prevue != $this->oldcopy->date_ouverture_prevue)
3024  {
3025  $sql ='UPDATE '.MAIN_DB_PREFIX.'contratdet SET';
3026  $sql.= " date_ouverture_prevue = ".($this->date_ouverture_prevue!=''?"'".$this->db->idate($this->date_ouverture_prevue)."'":"null");
3027  $sql.= " WHERE fk_contrat = ".$this->fk_contrat;
3028 
3029  $resql = $this->db->query($sql);
3030  if (! $resql)
3031  {
3032  $error++;
3033  $this->error="Error ".$this->db->lasterror();
3034  }
3035  }
3036  if ($this->date_fin_validite != $this->oldcopy->date_fin_validite)
3037  {
3038  $sql ='UPDATE '.MAIN_DB_PREFIX.'contratdet SET';
3039  $sql.= " date_fin_validite = ".($this->date_fin_validite!=''?"'".$this->db->idate($this->date_fin_validite)."'":"null");
3040  $sql.= " WHERE fk_contrat = ".$this->fk_contrat;
3041 
3042  $resql = $this->db->query($sql);
3043  if (! $resql)
3044  {
3045  $error++;
3046  $this->error="Error ".$this->db->lasterror();
3047  }
3048  }
3049  }
3050 
3051  if (! $error && ! $notrigger) {
3052  // Call trigger
3053  $result=$this->call_trigger('LINECONTRACT_UPDATE', $user);
3054  if ($result < 0) {
3055  $error++;
3056  $this->db->rollback();
3057  }
3058  // End call triggers
3059  }
3060 
3061  if (! $error)
3062  {
3063  $this->db->commit();
3064  return 1;
3065  } else {
3066  $this->db->rollback();
3067  $this->errors[]=$this->error;
3068  return -1;
3069  }
3070  }
3071 
3072 
3073  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
3080  function update_total()
3081  {
3082  // phpcs:enable
3083  $this->db->begin();
3084 
3085  // Mise a jour ligne en base
3086  $sql = "UPDATE ".MAIN_DB_PREFIX."contratdet SET";
3087  $sql.= " total_ht=".price2num($this->total_ht,'MT')."";
3088  $sql.= ",total_tva=".price2num($this->total_tva,'MT')."";
3089  $sql.= ",total_localtax1=".price2num($this->total_localtax1,'MT')."";
3090  $sql.= ",total_localtax2=".price2num($this->total_localtax2,'MT')."";
3091  $sql.= ",total_ttc=".price2num($this->total_ttc,'MT')."";
3092  $sql.= " WHERE rowid = ".$this->id;
3093 
3094  dol_syslog(get_class($this)."::update_total", LOG_DEBUG);
3095 
3096  $resql=$this->db->query($sql);
3097  if ($resql)
3098  {
3099  $this->db->commit();
3100  return 1;
3101  }
3102  else
3103  {
3104  $this->error=$this->db->error();
3105  $this->db->rollback();
3106  return -2;
3107  }
3108  }
3109 
3110 
3117  public function insert($notrigger = 0)
3118  {
3119  global $conf, $user;
3120 
3121  // Insertion dans la base
3122  $sql = "INSERT INTO ".MAIN_DB_PREFIX."contratdet";
3123  $sql.= " (fk_contrat, label, description, fk_product, qty, vat_src_code, tva_tx,";
3124  $sql.= " localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, remise_percent, subprice,";
3125  $sql.= " total_ht, total_tva, total_localtax1, total_localtax2, total_ttc,";
3126  $sql.= " info_bits,";
3127  $sql.= " price_ht, remise, fk_product_fournisseur_price, buy_price_ht";
3128  if ($this->date_ouverture_prevue > 0) { $sql.= ",date_ouverture_prevue"; }
3129  if ($this->date_fin_validite > 0) { $sql.= ",date_fin_validite"; }
3130  $sql.= ") VALUES ($this->fk_contrat, '', '" . $this->db->escape($this->description) . "',";
3131  $sql.= ($this->fk_product>0 ? $this->fk_product : "null").",";
3132  $sql.= " '".$this->db->escape($this->qty)."',";
3133  $sql.= " '".$this->db->escape($this->vat_src_code)."',";
3134  $sql.= " '".$this->db->escape($this->tva_tx)."',";
3135  $sql.= " '".$this->db->escape($this->localtax1_tx)."',";
3136  $sql.= " '".$this->db->escape($this->localtax2_tx)."',";
3137  $sql.= " '".$this->db->escape($this->localtax1_type)."',";
3138  $sql.= " '".$this->db->escape($this->localtax2_type)."',";
3139  $sql.= " ".price2num($this->remise_percent).",".price2num($this->subprice).",";
3140  $sql.= " ".price2num($this->total_ht).",".price2num($this->total_tva).",".price2num($this->total_localtax1).",".price2num($this->total_localtax2).",".price2num($this->total_ttc).",";
3141  $sql.= " '".$this->db->escape($this->info_bits)."',";
3142  $sql.= " ".price2num($this->price_ht).",".price2num($this->remise).",";
3143  if ($this->fk_fournprice > 0) $sql.= ' '.$this->fk_fournprice.',';
3144  else $sql.= ' null,';
3145  if ($this->pa_ht > 0) $sql.= ' '.price2num($this->pa_ht);
3146  else $sql.= ' null';
3147  if ($this->date_ouverture > 0) { $sql.= ",'".$this->db->idate($this->date_ouverture)."'"; }
3148  if ($this->date_cloture > 0) { $sql.= ",'".$this->db->idate($this->date_cloture)."'"; }
3149  $sql.= ")";
3150 
3151  dol_syslog(get_class($this)."::insert", LOG_DEBUG);
3152 
3153  $resql=$this->db->query($sql);
3154  if ($resql)
3155  {
3156  $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'contratdet');
3157 
3158  // Insert of extrafields
3159  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($this->array_options) && count($this->array_options)>0) // For avoid conflicts if trigger used
3160  {
3161  $result = $this->insertExtraFields();
3162  if ($result < 0)
3163  {
3164  $this->db->rollback();
3165  return -1;
3166  }
3167  }
3168 
3169  if (!$notrigger)
3170  {
3171  // Call trigger
3172  $result = $this->call_trigger('LINECONTRACT_INSERT', $user);
3173  if ($result < 0) {
3174  $this->db->rollback();
3175  return -1;
3176  }
3177  // End call triggers
3178  }
3179 
3180  $this->db->commit();
3181  return 1;
3182  }
3183  else
3184  {
3185  $this->db->rollback();
3186  $this->error=$this->db->error()." sql=".$sql;
3187  return -1;
3188  }
3189  }
3190 
3191  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
3201  function active_line($user, $date, $date_end = '', $comment = '')
3202  {
3203  // phpcs:enable
3204  global $langs, $conf;
3205 
3206  $error = 0;
3207 
3208  $this->db->begin();
3209 
3210  $sql = "UPDATE " . MAIN_DB_PREFIX . "contratdet SET statut = ".ContratLigne::STATUS_OPEN.",";
3211  $sql .= " date_ouverture = " . (dol_strlen($date) != 0 ? "'" . $this->db->idate($date) . "'" : "null") . ",";
3212  if ($date_end >= 0) $sql .= " date_fin_validite = " . (dol_strlen($date_end) != 0 ? "'" . $this->db->idate($date_end) . "'" : "null") . ",";
3213  $sql .= " fk_user_ouverture = " . $user->id . ",";
3214  $sql .= " date_cloture = null,";
3215  $sql .= " commentaire = '" . $this->db->escape($comment) . "'";
3216  $sql .= " WHERE rowid = " . $this->id . " AND (statut = ".ContratLigne::STATUS_INITIAL." OR statut = ".ContratLigne::STATUS_CLOSED.")";
3217 
3218  dol_syslog(get_class($this) . "::active_line", LOG_DEBUG);
3219  $resql = $this->db->query($sql);
3220  if ($resql) {
3221  // Call trigger
3222  $result = $this->call_trigger('LINECONTRACT_ACTIVATE', $user);
3223  if ($result < 0) $error++;
3224  // End call triggers
3225 
3226  if (! $error)
3227  {
3228  $this->statut = ContratLigne::STATUS_OPEN;
3229  $this->date_ouverture = $date;
3230  $this->date_fin_validite = $date_end;
3231  $this->fk_user_ouverture = $user->id;
3232  $this->date_cloture = null;
3233  $this->commentaire = $comment;
3234 
3235  $this->db->commit();
3236  return 1;
3237  }
3238  else
3239  {
3240  $this->db->rollback();
3241  return -1;
3242  }
3243  } else {
3244  $this->error = $this->db->lasterror();
3245  $this->db->rollback();
3246  return -1;
3247  }
3248  }
3249 
3250  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
3260  function close_line($user, $date_end, $comment = '', $notrigger=0)
3261  {
3262  // phpcs:enable
3263  global $langs, $conf;
3264 
3265  // Update object
3266  $this->date_cloture = $date_end;
3267  $this->fk_user_cloture = $user->id;
3268  $this->commentaire = $comment;
3269 
3270  $error = 0;
3271 
3272  // statut actif : 4
3273 
3274  $this->db->begin();
3275 
3276  $sql = "UPDATE " . MAIN_DB_PREFIX . "contratdet SET statut = ".ContratLigne::STATUS_CLOSED.",";
3277  $sql .= " date_cloture = '" . $this->db->idate($date_end) . "',";
3278  $sql .= " fk_user_cloture = " . $user->id . ",";
3279  $sql .= " commentaire = '" . $this->db->escape($comment) . "'";
3280  $sql .= " WHERE rowid = " . $this->id . " AND statut = ".ContratLigne::STATUS_OPEN;
3281 
3282  $resql = $this->db->query($sql);
3283  if ($resql)
3284  {
3285  if (! $notrigger)
3286  {
3287  // Call trigger
3288  $result = $this->call_trigger('LINECONTRACT_CLOSE', $user);
3289  if ($result < 0) {
3290  $error++;
3291  $this->db->rollback();
3292  return -1;
3293  }
3294  // End call triggers
3295  }
3296 
3297  $this->db->commit();
3298  return 1;
3299  } else {
3300  $this->error = $this->db->lasterror();
3301  $this->db->rollback();
3302  return -1;
3303  }
3304  }
3305 }
static replaceThirdparty(DoliDB $db, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
print $object label
hash of file content (md5_file(dol_osencode($destfull))
Definition: edit.php:153
initAsSpecimen()
Initialise an instance with random values.
info($id)
Charge les informations d&#39;ordre info dans l&#39;objet contrat.
getIdContact($source, $code, $status=0)
Return id of contacts for a source and a contact code.
print
Draft customers invoices.
Definition: index.php:91
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:1053
getMarginInfos($pvht, $remise_percent, $tva_tx, $localtax1_tx, $localtax2_tx, $fk_pa, $paht)
Return an array with margins information of a line.
deleteObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $rowid='')
Delete all links between an object $this.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
close_line($user, $date_end, $comment='', $notrigger=0)
Close a contract line.
</td >< td class="liste_titre" align="right"></td ></tr >< tr class="liste_titre">< input type="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< tr class="oddeven">< td >< input type="checkbox" class="check" name="' . $i . '"' . $disabled . '></td >< td >< input type="checkbox" class="check" name="choose'.$i.'"></td >< td class="nowrap"></td >< td >< input type="hidden" name="desc' . $i . '" value="' . dol_escape_htmltag($objp-> description
Only used if Module[ID]Desc translation string is not found.
Definition: replenish.php:573
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
getIdServiceContact()
Return id des contacts clients de prestation.
closeAll(User $user, $notrigger=0, $comment='')
Close all lines of a contract.
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:41
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.
update($user, $notrigger=0)
Update object into database.
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)
active_line($user, $date, $date_end='', $comment='')
Activate a contract line.
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.
type
Definition: viewcat.php:284
__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.
if(! function_exists('dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
static LibStatut($statut, $mode, $expired=-1, $moreatt='')
Return label of a contract line status.
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.
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:1273
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_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0)
Scan a directory and return a list of files/directories.
Definition: files.lib.php:59
dol_now($mode='gmt')
Return date for now.
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.
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
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.
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.
insert($notrigger=0)
Inserts a contrat line into database.
activateAll($user, $date_start='', $notrigger=0, $comment='')
Open all lines of a contract.
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.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='')
Show picto whatever it&#39;s its name (generic function)
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 &#39;...
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, ...)
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
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)