40require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobject.class.php';
41require_once DOL_DOCUMENT_ROOT.
'/contrat/class/contratligne.class.php';
42require_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
43require_once DOL_DOCUMENT_ROOT.
'/margin/lib/margins.lib.php';
44require_once DOL_DOCUMENT_ROOT.
'/core/class/commonsignedobject.class.php';
54 use CommonSignedObject;
59 public $element =
'contrat';
64 public $table_element =
'contrat';
69 public $table_element_line =
'contratdet';
74 public $fk_element =
'fk_contrat';
79 public $picto =
'contract';
85 public $restrictiononfksoc = 1;
107 public $ref_supplier;
148 public $fk_user_author;
155 public $user_author_id;
162 public $user_creation;
167 public $user_cloture;
172 public $date_contrat;
177 public $commercial_signature_id;
183 public $fk_commercial_signature;
188 public $commercial_suivi_id;
195 public $fk_commercial_suivi;
200 public $extraparams = array();
205 public $lines = array();
210 public $nbofservices;
214 public $nbofserviceswait;
218 public $nbofservicesopened;
222 public $nbofservicesexpired;
226 public $nbofservicesclosed;
234 protected $lines_id_index_mapper = array();
265 public $fields = array(
266 'rowid' => array(
'type' =>
'integer',
'label' =>
'TechnicalID',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'position' => 10),
267 'ref' => array(
'type' =>
'varchar(50)',
'label' =>
'Ref',
'enabled' => 1,
'visible' => -1,
'showoncombobox' => 1,
'position' => 15,
'searchall' => 1),
268 'ref_ext' => array(
'type' =>
'varchar(255)',
'label' =>
'RefExt',
'enabled' => 1,
'visible' => 0,
'position' => 20),
269 'ref_customer' => array(
'type' =>
'varchar(50)',
'label' =>
'RefCustomer',
'enabled' => 1,
'visible' => -1,
'position' => 25,
'searchall' => 1),
270 'ref_supplier' => array(
'type' =>
'varchar(50)',
'label' =>
'RefSupplier',
'enabled' => 1,
'visible' => -1,
'position' => 26,
'searchall' => 1),
271 'entity' => array(
'type' =>
'integer',
'label' =>
'Entity',
'default' =>
'1',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 30,
'index' => 1),
272 'tms' => array(
'type' =>
'timestamp',
'label' =>
'DateModification',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'position' => 35),
273 'datec' => array(
'type' =>
'datetime',
'label' =>
'DateCreation',
'enabled' => 1,
'visible' => -1,
'position' => 40),
274 'date_contrat' => array(
'type' =>
'datetime',
'label' =>
'Date contrat',
'enabled' => 1,
'visible' => -1,
'position' => 45),
275 'signed_status' => array(
'type' =>
'smallint(6)',
'label' =>
'SignedStatus',
'enabled' => 1,
'visible' => -1,
'position' => 50,
'arrayofkeyval' => array(0 =>
'NoSignature', 1 =>
'SignedSender', 2 =>
'SignedReceiver', 3 =>
'SignedReceiverOnline', 9 =>
'SignedAll')),
276 'fk_soc' => array(
'type' =>
'integer:Societe:societe/class/societe.class.php',
'label' =>
'ThirdParty',
'enabled' =>
'isModEnabled("societe")',
'visible' => -1,
'notnull' => 1,
'position' => 70),
277 'fk_projet' => array(
'type' =>
'integer:Project:projet/class/project.class.php:1:(fk_statut:=:1)',
'label' =>
'Project',
'enabled' =>
"isModEnabled('project')",
'visible' => -1,
'position' => 75),
278 'fk_commercial_signature' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'SaleRepresentative Signature',
'enabled' => 1,
'visible' => -1,
'position' => 80),
279 'fk_commercial_suivi' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'SaleRepresentative follower',
'enabled' => 1,
'visible' => -1,
'position' => 85),
280 'fk_user_author' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserAuthor',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'position' => 90),
281 'note_public' => array(
'type' =>
'html',
'label' =>
'NotePublic',
'enabled' => 1,
'visible' => 0,
'position' => 105,
'searchall' => 1),
282 'note_private' => array(
'type' =>
'html',
'label' =>
'NotePrivate',
'enabled' => 1,
'visible' => 0,
'position' => 110,
'searchall' => 1),
283 'model_pdf' => array(
'type' =>
'varchar(255)',
'label' =>
'Model pdf',
'enabled' => 1,
'visible' => 0,
'position' => 115),
284 'import_key' => array(
'type' =>
'varchar(14)',
'label' =>
'ImportId',
'enabled' => 1,
'visible' => -2,
'position' => 120),
285 'extraparams' => array(
'type' =>
'varchar(255)',
'label' =>
'Extraparams',
'enabled' => 1,
'visible' => -1,
'position' => 125),
286 'fk_user_modif' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserModif',
'enabled' => 1,
'visible' => -2,
'notnull' => -1,
'position' => 135),
287 'last_main_doc' => array(
'type' =>
'varchar(255)',
'label' =>
'Last main doc',
'enabled' => 1,
'visible' => -1,
'position' => 140),
288 'statut' => array(
'type' =>
'smallint(6)',
'label' =>
'Statut',
'enabled' => 1,
'visible' => -1,
'position' => 500,
'notnull' => 1,
'arrayofkeyval' => array(0 =>
'Draft', 1 =>
'Validated', 2 =>
'Closed'))
292 const STATUS_DRAFT = 0;
293 const STATUS_VALIDATED = 1;
294 const STATUS_CLOSED = 2;
305 $this->ismultientitymanaged = 1;
306 $this->isextrafieldmanaged = 1;
315 public function getNextNumRef($soc)
317 global $db, $langs,
$conf;
318 $langs->load(
"contracts");
327 $dirmodels = array_merge(array(
'/'), (array)
$conf->modules_parts[
'models']);
329 foreach ($dirmodels as $reldir) {
333 $mybool = ((bool) @include_once $dir.$file) || $mybool;
341 $obj =
new $classname();
342 '@phan-var-force ModelNumRefContracts $obj';
344 $numref = $obj->getNextValue($soc, $this);
349 $this->error = $obj->error;
354 $langs->load(
"errors");
355 print $langs->trans(
"Error").
" ".$langs->trans(
"ErrorModuleSetupNotComplete", $langs->transnoentitiesnoconv(
"Contract"));
374 $result = $this->lines[$this->lines_id_index_mapper[$line_id]]->active_line($user,
$date_start, $date_end, $comment);
376 $this->error = $this->lines[$this->lines_id_index_mapper[$line_id]]->error;
377 $this->errors = $this->lines[$this->lines_id_index_mapper[$line_id]]->errors;
393 public function close_line($user, $line_id, $date_end, $comment =
'')
396 $result = $this->lines[$this->lines_id_index_mapper[$line_id]]->close_line($user, $date_end, $comment);
398 $this->error = $this->lines[$this->lines_id_index_mapper[$line_id]]->error;
399 $this->errors = $this->lines[$this->lines_id_index_mapper[$line_id]]->errors;
429 foreach ($this->lines as $contratline) {
431 if ($contratline->statut != ContratLigne::STATUS_OPEN) {
432 $contratline->context = $this->context;
434 $result = $contratline->active_line($user,
$date_start, !empty($date_end) ? $date_end : -1, $comment);
443 if (!$error && $this->statut == 0) {
444 $result = $this->
validate($user,
'', $notrigger);
454 $this->db->rollback();
469 public function closeAll(
User $user, $notrigger = 0, $comment =
'', $nofetchlines = 0)
476 if (empty($nofetchlines)) {
484 foreach ($this->lines as $contratline) {
486 if ($contratline->statut != ContratLigne::STATUS_CLOSED) {
487 $contratline->date_end_real = $now;
488 $contratline->date_cloture = $now;
489 $contratline->user_closing_id = $user->id;
490 $contratline->statut = ContratLigne::STATUS_CLOSED;
492 $result = $contratline->close_line($user, $now, $comment, $notrigger);
496 $this->error = $contratline->error.($contratline->error ?
' ('.$this->ref.
')' :
'');
497 $this->errors = $contratline->errors;
503 if (!$error && $this->
status == 0) {
504 $result = $this->
validate($user,
'', $notrigger);
517 $this->db->rollback();
533 public function validate(
User $user, $force_number =
'', $notrigger = 0)
535 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
541 dol_syslog(get_class($this).
'::validate user='.$user->id.
', force_number='.$force_number);
549 if (!
getDolGlobalString(
'CONTRACT_DISABLE_AUTOSET_AS_CLIENT_ON_CONTRACT_VALIDATION') && $this->thirdparty->fournisseur == 0) {
550 $result = $this->thirdparty->setAsCustomer();
555 $num = $force_number;
556 } elseif (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) {
557 $num = $this->getNextNumRef($this->thirdparty);
564 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"contrat SET ref = '".$this->db->escape($num).
"', statut = 1";
565 $sql .=
" WHERE rowid = ".((int) $this->
id).
" AND statut = 0";
567 dol_syslog(get_class($this).
"::validate", LOG_DEBUG);
568 $resql = $this->db->query($sql);
572 $this->error = $this->db->lasterror();
576 if (!$error && !$notrigger) {
578 $result = $this->call_trigger(
'CONTRACT_VALIDATE', $user);
586 $this->oldref = $this->ref;
589 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
591 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files SET filename = CONCAT('".$this->db->escape($this->newref).
"', SUBSTR(filename, ".(strlen($this->
ref) + 1).
")), filepath = 'contract/".$this->db->escape($this->newref).
"'";
592 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'contract/".$this->db->escape($this->
ref).
"' and entity = ".((int)
$conf->entity);
593 $resql = $this->db->query($sql);
596 $this->error = $this->db->lasterror();
598 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files SET filepath = 'contract/".$this->db->escape($this->newref).
"'";
599 $sql .=
" WHERE filepath = 'contract/".$this->db->escape($this->
ref).
"' and entity = ".((int)
$conf->entity);
600 $resql = $this->db->query($sql);
603 $this->error = $this->db->lasterror();
609 $dirsource =
$conf->contract->dir_output.
'/'.$oldref;
610 $dirdest =
$conf->contract->dir_output.
'/'.$newref;
611 if (!$error && file_exists($dirsource)) {
612 dol_syslog(get_class($this).
"::validate rename dir ".$dirsource.
" into ".$dirdest);
614 if (@rename($dirsource, $dirdest)) {
617 $listoffiles =
dol_dir_list(
$conf->contract->dir_output.
'/'.$newref,
'files', 1,
'^'.preg_quote($oldref,
'/'));
618 foreach ($listoffiles as $fileentry) {
619 $dirsource = $fileentry[
'name'];
620 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
621 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
622 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
623 @rename($dirsource, $dirdest);
633 $this->
status = self::STATUS_VALIDATED;
634 $this->statut = self::STATUS_VALIDATED;
635 $this->date_validation = $now;
645 $this->db->rollback();
657 public function reopen($user, $notrigger = 0)
659 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
664 dol_syslog(get_class($this).
'::reopen user='.$user->id);
670 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"contrat SET statut = 0";
672 $sql .=
" WHERE rowid = ".((int) $this->
id).
" AND statut = 1";
674 dol_syslog(get_class($this).
"::validate", LOG_DEBUG);
675 $resql = $this->db->query($sql);
679 $this->error = $this->db->lasterror();
683 if (!$error && !$notrigger) {
685 $result = $this->call_trigger(
'CONTRACT_REOPEN', $user);
694 $this->statut = self::STATUS_DRAFT;
695 $this->
status = self::STATUS_DRAFT;
696 $this->date_validation = $now;
703 $this->db->rollback();
719 public function fetch($id, $ref =
'', $ref_customer =
'', $ref_supplier =
'', $noextrafields = 0, $nolines = 0)
723 $sql =
"SELECT rowid, statut as status, ref, fk_soc as thirdpartyid,";
724 $sql .=
" ref_supplier, ref_customer,";
727 $sql .=
" signed_status,";
728 $sql .=
" date_contrat as datecontrat,";
729 $sql .=
" fk_user_author,";
730 $sql .=
" fk_projet as fk_project,";
731 $sql .=
" fk_commercial_signature, fk_commercial_suivi,";
732 $sql .=
" note_private, note_public, model_pdf, last_main_doc, extraparams";
733 $sql .=
" FROM ".MAIN_DB_PREFIX.
"contrat";
735 $sql .=
" WHERE entity IN (".getEntity(
'contract').
")";
737 $sql .=
" WHERE rowid = ".(int) $id;
740 $sql .=
" AND ref_customer = '".$this->db->escape($ref_customer).
"'";
743 $sql .=
" AND ref_supplier = '".$this->db->escape($ref_supplier).
"'";
746 $sql .=
" AND ref = '".$this->db->escape($ref).
"'";
749 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
751 $resql = $this->db->query($sql);
753 $num = $this->db->num_rows($resql);
755 $this->error =
'Fetch found several records.';
760 $obj = $this->db->fetch_object($resql);
762 $this->
id = $obj->rowid;
763 $this->
ref = (!isset($obj->ref) || !$obj->ref) ? $obj->rowid : $obj->ref;
764 $this->ref_customer = $obj->ref_customer;
765 $this->ref_supplier = $obj->ref_supplier;
766 $this->ref_ext = $obj->ref_ext;
767 $this->entity = $obj->entity;
768 $this->statut = $obj->status;
769 $this->
status = $obj->status;
770 $this->signed_status = $obj->signed_status;
772 $this->date_contrat = $this->db->jdate($obj->datecontrat);
773 $this->date_creation = $this->db->jdate($obj->datecontrat);
775 $this->user_author_id = $obj->fk_user_author;
777 $this->commercial_signature_id = $obj->fk_commercial_signature;
778 $this->commercial_suivi_id = $obj->fk_commercial_suivi;
780 $this->note_private = $obj->note_private;
781 $this->note_public = $obj->note_public;
782 $this->model_pdf = $obj->model_pdf;
784 $this->fk_projet = $obj->fk_project;
785 $this->fk_project = $obj->fk_project;
787 $this->socid = $obj->thirdpartyid;
788 $this->fk_soc = $obj->thirdpartyid;
789 $this->last_main_doc = $obj->last_main_doc;
790 $this->extraparams = (isset($obj->extraparams) ? (array) json_decode($obj->extraparams,
true) :
null);
792 $this->db->free($resql);
796 if (empty($noextrafields)) {
799 $this->error = $this->db->lasterror();
805 if (empty($nolines)) {
806 if ($result >= 0 && !empty($this->table_element_line)) {
809 $this->error = $this->db->lasterror();
817 dol_syslog(get_class($this).
"::fetch Contract failed");
818 $this->error =
"Fetch contract failed";
822 dol_syslog(get_class($this).
"::fetch Contract not found");
823 $this->error =
"Contract not found";
827 dol_syslog(get_class($this).
"::fetch Error searching contract");
828 $this->error = $this->db->error();
843 public function fetch_lines($only_services = 0, $loadalsotranslation = 0, $noextrafields = 0)
846 $this->nbofservices = 0;
847 $this->nbofserviceswait = 0;
848 $this->nbofservicesopened = 0;
849 $this->nbofservicesexpired = 0;
850 $this->nbofservicesclosed = 0;
858 $this->lines = array();
862 $sql =
"SELECT p.label as product_label, p.description as product_desc, p.ref as product_ref, p.fk_product_type as product_type,";
863 $sql .=
" d.rowid, d.fk_contrat, d.statut as status, d.description, d.subprice, d.subprice_ttc, 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.fk_product_fournisseur_price as fk_fournprice, d.buy_price_ht as pa_ht,";
864 $sql .=
" d.total_ht,";
865 $sql .=
" d.total_tva,";
866 $sql .=
" d.total_localtax1,";
867 $sql .=
" d.total_localtax2,";
868 $sql .=
" d.total_ttc,";
869 $sql .=
" d.info_bits, d.fk_product,";
870 $sql .=
" d.date_ouverture_prevue as date_start,";
871 $sql .=
" d.date_ouverture as date_start_real,";
872 $sql .=
" d.date_fin_validite as date_end,";
873 $sql .=
" d.date_cloture as date_end_real,";
874 $sql .=
" d.fk_user_author,";
875 $sql .=
" d.fk_user_ouverture,";
876 $sql .=
" d.fk_user_cloture,";
877 $sql .=
" d.fk_unit,";
878 $sql .=
" d.extraparams,";
879 $sql .=
" d.product_type as type,";
881 $sql .=
" FROM ".MAIN_DB_PREFIX.
"contratdet as d LEFT JOIN ".MAIN_DB_PREFIX.
"product as p ON d.fk_product = p.rowid";
882 $sql .=
" WHERE d.fk_contrat = ".((int) $this->
id);
883 if ($only_services == 1) {
884 $sql .=
" AND d.product_type = 1";
886 $sql .=
" ORDER by d.rang ASC";
888 dol_syslog(get_class($this).
"::fetch_lines", LOG_DEBUG);
889 $result = $this->db->query($sql);
891 $num = $this->db->num_rows($result);
895 $objp = $this->db->fetch_object($result);
899 $line->id = $objp->rowid;
900 $line->ref = $objp->rowid;
901 $line->fk_contrat = $objp->fk_contrat;
902 $line->desc = $objp->description;
903 $line->qty = $objp->qty;
904 $line->vat_src_code = $objp->vat_src_code;
905 $line->tva_tx = $objp->tva_tx;
906 $line->localtax1_tx = $objp->localtax1_tx;
907 $line->localtax2_tx = $objp->localtax2_tx;
908 $line->localtax1_type = $objp->localtax1_type;
909 $line->localtax2_type = $objp->localtax2_type;
910 $line->subprice = $objp->subprice;
911 $line->subprice_ttc = $objp->subprice_ttc;
912 $line->statut = $objp->status;
913 $line->status = $objp->status;
914 $line->remise_percent = $objp->remise_percent;
915 $line->total_ht = $objp->total_ht;
916 $line->total_tva = $objp->total_tva;
917 $line->total_localtax1 = $objp->total_localtax1;
918 $line->total_localtax2 = $objp->total_localtax2;
919 $line->total_ttc = $objp->total_ttc;
920 $line->fk_product = (($objp->fk_product > 0) ? $objp->fk_product : 0);
921 $line->info_bits = $objp->info_bits;
922 $line->type = $objp->type;
924 $line->fk_fournprice = $objp->fk_fournprice;
925 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $objp->fk_fournprice, $objp->pa_ht);
926 $line->pa_ht = $marginInfos[0];
928 $line->fk_user_author = $objp->fk_user_author;
929 $line->fk_user_ouverture = $objp->fk_user_ouverture;
930 $line->fk_user_cloture = $objp->fk_user_cloture;
931 $line->fk_unit = $objp->fk_unit;
933 $line->extraparams = !empty($objp->extraparams) ? (array) json_decode($objp->extraparams,
true) : array();
935 $line->ref = $objp->product_ref;
936 $line->product_ref = $objp->product_ref;
937 $line->product_type = $objp->product_type;
938 $line->product_desc = $objp->product_desc;
939 $line->product_label = $objp->product_label;
941 $line->description = $objp->description;
943 $line->date_start = $this->db->jdate($objp->date_start);
944 $line->date_start_real = $this->db->jdate($objp->date_start_real);
945 $line->date_end = $this->db->jdate($objp->date_end);
946 $line->date_end_real = $this->db->jdate($objp->date_end_real);
957 $line->rang = $objp->rang;
961 if (empty($noextrafields)) {
962 $line->fetch_optionals();
966 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && !empty($objp->fk_product) && !empty($loadalsotranslation)) {
967 $tmpproduct =
new Product($this->db);
968 $tmpproduct->fetch($objp->fk_product);
969 $tmpproduct->getMultiLangs();
971 $line->multilangs = $tmpproduct->multilangs;
974 $this->lines[$pos] = $line;
976 $this->lines_id_index_mapper[$line->id] = $pos;
981 if ($line->statut == ContratLigne::STATUS_INITIAL) {
982 $this->nbofserviceswait++;
984 if ($line->statut == ContratLigne::STATUS_OPEN && (empty($line->date_end) || $line->date_end >= $now)) {
985 $this->nbofservicesopened++;
987 if ($line->statut == ContratLigne::STATUS_OPEN && (!empty($line->date_end) && $line->date_end < $now)) {
988 $this->nbofservicesexpired++;
990 if ($line->statut == ContratLigne::STATUS_CLOSED) {
991 $this->nbofservicesclosed++;
995 $total_ttc += $objp->total_ttc;
996 $total_vat += $objp->total_tva;
997 $total_ht += $objp->total_ht;
1002 $this->db->free($result);
1004 dol_syslog(get_class($this).
"::Fetch Error when reading lines of contracts linked to products");
1009 $this->nbofservices = count($this->lines);
1010 $this->total_ttc = (float)
price2num($total_ttc);
1011 $this->total_tva = (float)
price2num($total_vat);
1012 $this->total_ht = (float)
price2num($total_ht);
1014 return $this->lines;
1024 public function create($user, $notrigger = 0)
1026 global
$conf, $langs;
1030 if ($this->commercial_signature_id <= 0) {
1031 $langs->load(
"commercial");
1032 $this->error .= $langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv(
"SalesRepresentativeSignature"));
1035 if ($this->commercial_suivi_id <= 0) {
1036 $langs->load(
"commercial");
1037 $this->error .= ($this->error ?
"<br>" :
'');
1038 $this->error .= $langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv(
"SalesRepresentativeFollowUp"));
1052 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"contrat (datec, fk_soc, fk_user_author, date_contrat,";
1053 $sql .=
" fk_commercial_signature, fk_commercial_suivi, fk_projet,";
1054 $sql .=
" ref, entity, signed_status, note_private, note_public, ref_customer, ref_supplier, ref_ext)";
1055 $sql .=
" VALUES ('".$this->db->idate($now).
"', ".((int) $this->socid).
", ".((int) $user->id);
1056 $sql .=
", ".(dol_strlen($this->date_contrat) != 0 ?
"'".$this->db->idate($this->date_contrat).
"'" :
"NULL");
1057 $sql .=
",".($this->commercial_signature_id > 0 ? ((int) $this->commercial_signature_id) :
"NULL");
1058 $sql .=
",".($this->commercial_suivi_id > 0 ? ((int) $this->commercial_suivi_id) :
"NULL");
1059 $sql .=
",".($this->fk_project > 0 ? ((int) $this->fk_project) :
"NULL");
1060 $sql .=
", ".(dol_strlen($this->
ref) <= 0 ?
"null" :
"'".$this->db->escape($this->
ref).
"'");
1061 $sql .=
", ".((int) $this->entity);
1062 $sql .=
", ".((int) $this->signed_status);
1063 $sql .=
", ".(!empty($this->note_private) ? (
"'".$this->db->escape($this->note_private).
"'") :
"NULL");
1064 $sql .=
", ".(!empty($this->note_public) ? (
"'".$this->db->escape($this->note_public).
"'") :
"NULL");
1065 $sql .=
", ".(!empty($this->ref_customer) ? (
"'".$this->db->escape($this->ref_customer).
"'") :
"NULL");
1066 $sql .=
", ".(!empty($this->ref_supplier) ? (
"'".$this->db->escape($this->ref_supplier).
"'") :
"NULL");
1067 $sql .=
", ".(!empty($this->ref_ext) ? (
"'".$this->db->escape($this->ref_ext).
"'") :
"NULL");
1069 $resql = $this->db->query($sql);
1074 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
"contrat");
1078 if (substr($module, 0, 13) ==
'mod_contract_' && substr($module, -3) ==
'php') {
1079 $module = substr($module, 0,
dol_strlen($module) - 4);
1083 $modCodeContract =
new $module();
1084 '@phan-var-force ModelNumRefContracts $modCodeContract';
1087 if (!empty($modCodeContract->code_auto)) {
1089 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"contrat SET ref='(PROV".((int) $this->
id).
")' WHERE rowid=".((int) $this->
id);
1090 if ($this->db->query($sql)) {
1092 $this->
ref =
"(PROV".$this->id.
")";
1104 if (!$error && !empty($this->commercial_signature_id)) {
1105 $result = $this->
add_contact($this->commercial_signature_id,
'SALESREPSIGN',
'internal');
1112 if (!$error && !empty($this->commercial_suivi_id)) {
1113 $result = $this->
add_contact($this->commercial_suivi_id,
'SALESREPFOLL',
'internal');
1120 if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) {
1121 $this->linked_objects = $this->linkedObjectsIds;
1125 if ($this->
id && !empty($this->linked_objects) && is_array($this->linked_objects)) {
1126 foreach ($this->linked_objects as $origin => $tmp_origin_id) {
1127 if (is_array($tmp_origin_id)) {
1128 foreach ($tmp_origin_id as $origin_id) {
1131 $this->error = $this->db->lasterror();
1136 $origin_id = $tmp_origin_id;
1139 $this->error = $this->db->lasterror();
1146 if (!$error && $this->
id &&
getDolGlobalString(
'MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN') && !empty($this->origin) && !empty($this->origin_id)) {
1147 $originforcontact = $this->origin;
1148 $originidforcontact = $this->origin_id;
1149 if ($originforcontact ==
'shipping') {
1150 require_once DOL_DOCUMENT_ROOT.
'/expedition/class/expedition.class.php';
1152 $exp->fetch($this->origin_id);
1153 $exp->fetchObjectLinked();
1154 if (count($exp->linkedObjectsIds[
'commande']) > 0) {
1155 foreach ($exp->linkedObjectsIds[
'commande'] as $key => $value) {
1156 $originforcontact =
'commande';
1157 $originidforcontact = $value;
1163 $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";
1164 $sqlcontact .=
" WHERE element_id = ".((int) $originidforcontact).
" AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$this->db->escape($originforcontact).
"'";
1166 $resqlcontact = $this->db->query($sqlcontact);
1167 if ($resqlcontact) {
1168 while ($objcontact = $this->db->fetch_object($resqlcontact)) {
1169 if ($objcontact->source ==
'internal' && in_array($objcontact->code, array(
'SALESREPSIGN',
'SALESREPFOLL'))) {
1173 $this->
add_contact($objcontact->fk_socpeople, $objcontact->code, $objcontact->source);
1181 if (!$error && !$notrigger) {
1183 $result = $this->call_trigger(
'CONTRACT_CREATE', $user);
1191 $this->db->commit();
1194 $this->error =
"Failed to add contract";
1195 dol_syslog(get_class($this).
"::create - 20 - ".$this->error, LOG_ERR);
1196 $this->db->rollback();
1200 $this->error = $langs->trans(
"UnknownError").
": ".$this->db->error();
1201 dol_syslog(get_class($this).
"::create - 10 - ".$this->error, LOG_ERR);
1203 $this->db->rollback();
1215 public function delete($user)
1219 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1226 $result = $this->call_trigger(
'CONTRACT_DELETE', $user);
1236 dol_syslog(get_class($this).
"::delete error", LOG_ERR);
1252 $sql_main_table = MAIN_DB_PREFIX.
'contratdet';
1253 $ef = $sql_main_table.
"_extrafields";
1254 $sql =
"DELETE FROM ".$this->db->sanitize($ef).
" WHERE fk_object IN (SELECT rowid FROM ".$sql_main_table.
" WHERE fk_contrat = ".((int) $this->
id).
")";
1256 dol_syslog(get_class($this).
"::delete contratdet_extrafields", LOG_DEBUG);
1257 $resql = $this->db->query($sql);
1259 $this->error = $this->db->error();
1266 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"contratdet";
1267 $sql .=
" WHERE fk_contrat = ".((int) $this->
id);
1269 dol_syslog(get_class($this).
"::delete contratdet", LOG_DEBUG);
1270 $resql = $this->db->query($sql);
1272 $this->error = $this->db->error();
1290 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"contrat";
1291 $sql .=
" WHERE rowid=".((int) $this->
id);
1293 dol_syslog(get_class($this).
"::delete contrat", LOG_DEBUG);
1294 $resql = $this->db->query($sql);
1296 $this->error = $this->db->error();
1306 dol_syslog(get_class($this).
"::delete error -3 ".$this->error, LOG_ERR);
1313 if ($conf->contrat->dir_output && !empty($ref)) {
1314 $dir =
$conf->contrat->multidir_output[$this->entity].
"/".$ref;
1315 if (file_exists($dir)) {
1318 $this->error =
'ErrorFailToDeleteDir';
1326 $this->db->commit();
1329 $this->error = $this->db->lasterror();
1330 $this->db->rollback();
1342 public function update($user, $notrigger = 0)
1348 if (empty($this->fk_commercial_signature) && $this->commercial_signature_id > 0) {
1349 $this->fk_commercial_signature = $this->commercial_signature_id;
1351 if (empty($this->fk_commercial_suivi) && $this->commercial_suivi_id > 0) {
1352 $this->fk_commercial_suivi = $this->commercial_suivi_id;
1354 if (empty($this->socid) && $this->fk_soc > 0) {
1355 $this->socid = (int) $this->fk_soc;
1358 if (isset($this->
ref)) {
1359 $this->
ref = trim($this->
ref);
1361 if (isset($this->ref_customer)) {
1362 $this->ref_customer = trim($this->ref_customer);
1364 if (isset($this->ref_supplier)) {
1365 $this->ref_supplier = trim($this->ref_supplier);
1367 if (isset($this->ref_ext)) {
1368 $this->ref_ext = trim($this->ref_ext);
1370 if (isset($this->entity)) {
1371 $this->entity = (int) $this->entity;
1373 if (isset($this->
status)) {
1376 if ((
int) $this->socid > 0) {
1377 $this->socid = (int) $this->socid;
1379 if (isset($this->fk_commercial_signature)) {
1380 $this->fk_commercial_signature = (int) $this->fk_commercial_signature;
1382 if (isset($this->fk_commercial_suivi)) {
1383 $this->fk_commercial_suivi = (int) $this->fk_commercial_suivi;
1385 if (isset($this->note_private)) {
1386 $this->note_private = trim($this->note_private);
1388 if (isset($this->note_public)) {
1389 $this->note_public = trim($this->note_public);
1391 if (isset($this->import_key)) {
1392 $this->import_key = trim($this->import_key);
1395 $extraparams = (!empty($this->extraparams) ? json_encode($this->extraparams) :
null);
1396 $extraparams =
dol_trunc($extraparams, 250);
1401 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"contrat SET";
1402 $sql .=
" ref=".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
1403 $sql .=
" ref_customer=".(isset($this->ref_customer) ?
"'".$this->db->escape($this->ref_customer).
"'" :
"null").
",";
1404 $sql .=
" ref_supplier=".(isset($this->ref_supplier) ?
"'".$this->db->escape($this->ref_supplier).
"'" :
"null").
",";
1405 $sql .=
" ref_ext=".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
1406 $sql .=
" entity=".((int)
$conf->entity).
",";
1407 $sql .=
" date_contrat=".(dol_strlen($this->date_contrat) != 0 ?
"'".$this->db->idate($this->date_contrat).
"'" :
'null').
",";
1408 $sql .=
" statut=".(isset($this->statut) ? ((int) $this->statut) : (isset($this->
status) ? ((int) $this->
status) :
"null")).
",";
1409 $sql .=
" fk_soc=".($this->socid > 0 ? ((int) $this->socid) :
"null").
",";
1410 $sql .=
" fk_projet=".($this->fk_project > 0 ? ((int) $this->fk_project) :
"null").
",";
1411 $sql .=
" fk_commercial_signature=".(isset($this->fk_commercial_signature) ? ((int) $this->fk_commercial_signature) :
"null").
",";
1412 $sql .=
" fk_commercial_suivi=".(isset($this->fk_commercial_suivi) ? ((int) $this->fk_commercial_suivi) :
"null").
",";
1413 $sql .=
" note_private=".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
1414 $sql .=
" note_public=".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
1415 $sql .=
" import_key=".(isset($this->import_key) ?
"'".$this->db->escape($this->import_key).
"'" :
"null").
",";
1416 $sql .=
" extraparams=".(isset($extraparams) ?
"'".$this->db->escape($extraparams).
"'" :
"null");
1417 $sql .=
" WHERE rowid=".((int) $this->
id);
1421 $resql = $this->db->query($sql);
1424 $this->errors[] =
"Error ".$this->db->lasterror();
1434 if (!$error && !$notrigger) {
1436 $result = $this->call_trigger(
'CONTRACT_MODIFY', $user);
1445 foreach ($this->errors as $errmsg) {
1446 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
1447 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1449 $this->db->rollback();
1452 $this->db->commit();
1481 public 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 = array(), $fk_unit =
null, $rang = 0)
1483 global $user, $langs,
$mysoc;
1486 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");
1489 if ($fk_product <= 0 && empty($desc)) {
1490 $this->error =
"ErrorDescRequiredForFreeProductLines";
1494 if ($this->
status >= 0) {
1503 if (preg_match(
'/\((.*)\)/', (
string) $txtva, $reg)) {
1504 $vat_src_code = $reg[1];
1505 $txtva = preg_replace(
'/\s*\(.*\)/',
'', (
string) $txtva);
1511 $remise_percent =
price2num($remise_percent);
1516 if (empty($info_bits)) {
1519 if (empty($pu_ht) || !is_numeric($pu_ht)) {
1522 if (empty($pu_ttc)) {
1525 if (empty($txtva) || !is_numeric($txtva)) {
1528 if (empty($txlocaltax1) || !is_numeric($txlocaltax1)) {
1531 if (empty($txlocaltax2) || !is_numeric($txlocaltax2)) {
1535 if ($price_base_type ==
'HT') {
1542 if (empty($remise_percent)) {
1543 $remise_percent = 0;
1550 $langs->load(
"errors");
1551 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
1563 $tabprice =
calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, 1,
$mysoc, $localtaxes_type);
1564 $total_ht = $tabprice[0];
1565 $total_tva = $tabprice[1];
1566 $total_ttc = $tabprice[2];
1567 $total_localtax1 = $tabprice[9];
1568 $total_localtax2 = $tabprice[10];
1569 $pu_ht = $tabprice[3];
1570 $pu_ttc = $tabprice[5];
1572 if (count($localtaxes_type) > 0) {
1573 $localtax1_type = $localtaxes_type[0];
1574 $localtax2_type = $localtaxes_type[2];
1576 $localtax1_type =
"";
1577 $localtax2_type =
"";
1580 if (empty($pa_ht)) {
1587 $result = $this->
defineBuyPrice((
float) $pu_ht, $remise_percent, $fk_product);
1596 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"contratdet";
1597 $sql .=
" (fk_contrat, label, description, fk_product, qty, tva_tx, vat_src_code,";
1598 $sql .=
" localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, remise_percent, subprice, subprice_ttc,";
1599 $sql .=
" total_ht, total_tva, total_localtax1, total_localtax2, total_ttc,";
1600 $sql .=
" info_bits,";
1601 $sql .=
" fk_product_fournisseur_price, buy_price_ht";
1603 $sql .=
",date_ouverture_prevue";
1605 if ($date_end > 0) {
1606 $sql .=
",date_fin_validite";
1608 $sql .=
", fk_unit";
1610 $sql .=
") VALUES (";
1611 $sql .= ((int) $this->
id).
", '', '".$this->db->escape($desc).
"',";
1612 $sql .= ($fk_product > 0 ? ((int) $fk_product) :
"null").
",";
1613 $sql .=
" ".((float) $qty).
",";
1614 $sql .=
" ".((float) $txtva).
",";
1615 $sql .=
" ".($vat_src_code ?
"'".$this->db->escape($vat_src_code).
"'" :
"null").
",";
1616 $sql .=
" ".((float) $txlocaltax1).
",";
1617 $sql .=
" ".((float) $txlocaltax2).
",";
1618 $sql .=
" '".$this->db->escape($localtax1_type).
"',";
1619 $sql .=
" '".$this->db->escape($localtax2_type).
"',";
1620 $sql .=
" ".price2num($remise_percent).
",";
1621 $sql .=
" ".price2num($pu_ht).
",";
1622 $sql .=
" ".($price_base_type ===
'TTC' ? (float)
price2num($pu_ttc) : 0).
",";
1624 $sql .=
" ".((int) $info_bits).
",";
1625 if (isset($fk_fournprice)) {
1626 $sql .=
' '.((int) $fk_fournprice).
',';
1630 if (isset($pa_ht)) {
1631 $sql .=
' '.price2num($pa_ht);
1638 if ($date_end > 0) {
1639 $sql .=
",'".$this->db->idate($date_end).
"'";
1641 $sql .=
", ".($fk_unit ?
"'".$this->db->escape((
string) $fk_unit).
"'" :
"null");
1642 $sql .=
", ".(!empty($rang) ? (int) $rang :
"0");
1645 $resql = $this->db->query($sql);
1647 $contractlineid = $this->db->last_insert_id(MAIN_DB_PREFIX.
"contratdet");
1650 $contractline->array_options = $array_options;
1651 $contractline->id = $contractlineid;
1652 $result = $contractline->insertExtraFields();
1658 if (empty($error)) {
1660 $this->context[
'line_id'] = $contractlineid;
1661 $result = $this->call_trigger(
'LINECONTRACT_INSERT', $user);
1669 $this->db->rollback();
1672 $this->db->commit();
1673 return $contractlineid;
1676 $this->db->rollback();
1677 $this->error = $this->db->error().
" sql=".$sql;
1681 dol_syslog(get_class($this).
"::addline ErrorTryToAddLineOnValidatedContract", LOG_ERR);
1710 public function updateline($rowid, $desc, $pu, $qty, $remise_percent,
$date_start, $date_end, $tvatx, $localtax1tx = 0.0, $localtax2tx = 0.0, $date_start_real =
'', $date_end_real =
'', $price_base_type =
'HT', $info_bits = 0, $fk_fournprice =
null, $pa_ht = 0, $array_options = array(), $fk_unit =
null, $rang = 0)
1712 global $user, $langs,
$mysoc;
1717 $qty = trim((
string) $qty);
1718 $desc = trim($desc);
1719 $desc = trim($desc);
1724 if (empty($fk_fournprice)) {
1732 $langs->load(
"errors");
1733 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
1737 dol_syslog(get_class($this).
"::updateline $rowid, $desc, $pu, $qty, $remise_percent, $date_start, $date_end, $date_start_real, $date_end_real, $tvatx, $localtax1tx, $localtax2tx, $price_base_type, $info_bits, $rang");
1746 $tvatx = preg_replace(
'/\s*\(.*\)/',
'', $tvatx);
1748 $tabprice =
calcul_price_total((
float) $qty, $pu, $remise_percent, (
float)
price2num($tvatx), (
float) $localtax1tx, (
float) $localtax2tx, 0, $price_base_type, $info_bits, 1,
$mysoc, $localtaxes_type);
1749 $total_ht = $tabprice[0];
1750 $total_tva = $tabprice[1];
1751 $total_ttc = $tabprice[2];
1752 $total_localtax1 = $tabprice[9];
1753 $total_localtax2 = $tabprice[10];
1754 $pu_ht = $tabprice[3];
1755 $pu_ttc = $tabprice[5];
1757 $localtax1_type = (empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0]);
1758 $localtax2_type = (empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2]);
1760 if (empty($pa_ht)) {
1774 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"contratdet SET description = '".$this->db->escape($desc).
"'";
1775 $sql .=
",subprice = ".((float)
price2num($pu_ht));
1777 $sql .=
",subprice_ttc = ".($price_base_type ===
'TTC' ? (float)
price2num($pu_ttc) : 0);
1778 $sql .=
",remise_percent = ".((float)
price2num($remise_percent));
1779 $sql .=
",qty = ".((float) $qty);
1780 $sql .=
",tva_tx = ".((float)
price2num($tvatx));
1781 $sql .=
",localtax1_tx = ".((float)
price2num($localtax1tx));
1782 $sql .=
",localtax2_tx = ".((float)
price2num($localtax2tx));
1783 $sql .=
",localtax1_type='".$this->db->escape($localtax1_type).
"'";
1784 $sql .=
",localtax2_type='".$this->db->escape($localtax2_type).
"'";
1785 $sql .=
", total_ht = ".((float)
price2num($total_ht));
1786 $sql .=
", total_tva = ".((float)
price2num($total_tva));
1787 $sql .=
", total_localtax1 = ".((float)
price2num($total_localtax1));
1788 $sql .=
", total_localtax2 = ".((float)
price2num($total_localtax2));
1789 $sql .=
", total_ttc = ".((float)
price2num($total_ttc));
1790 $sql .=
", fk_product_fournisseur_price=".($fk_fournprice > 0 ? ((int) $fk_fournprice) :
"null");
1791 $sql .=
", buy_price_ht = ".((float)
price2num($pa_ht));
1793 $sql .=
",date_ouverture_prevue = '".$this->db->idate(
$date_start).
"'";
1795 $sql .=
",date_ouverture_prevue = null";
1797 if ($date_end > 0) {
1798 $sql .=
",date_fin_validite = '".$this->db->idate($date_end).
"'";
1800 $sql .=
",date_fin_validite = null";
1802 if ($date_start_real > 0) {
1803 $sql .=
",date_ouverture = '".$this->db->idate($date_start_real).
"'";
1805 $sql .=
",date_ouverture = null";
1807 if ($date_end_real > 0) {
1808 $sql .=
",date_cloture = '".$this->db->idate($date_end_real).
"'";
1810 $sql .=
",date_cloture = null";
1812 $sql .=
", fk_unit = ".($fk_unit > 0 ? ((int) $fk_unit) :
"null");
1813 $sql .=
", rang = ".(!empty($rang) ? ((int) $rang) :
"0");
1814 $sql .=
" WHERE rowid = ".((int) $rowid);
1816 dol_syslog(get_class($this).
"::updateline", LOG_DEBUG);
1817 $result = $this->db->query($sql);
1819 if (is_array($array_options) && count($array_options) > 0) {
1821 $contractline->fetch($rowid);
1824 foreach ($array_options as $key => $value) {
1825 $contractline->array_options[$key] = $array_options[$key];
1828 $result = $contractline->insertExtraFields();
1830 $this->errors[] = $contractline->error;
1836 $sqltoupdatecontract =
"UPDATE ".MAIN_DB_PREFIX.
"contrat";
1837 $sqltoupdatecontract .=
" SET denormalized_lower_planned_end_date = (SELECT MIN(date_fin_validite) FROM ".MAIN_DB_PREFIX.
"contratdet as cd WHERE cd.fk_contrat = ".((int) $this->
id).
" AND cd.statut = ".ContratLigne::STATUS_OPEN.
")";
1838 $sqltoupdatecontract .=
" WHERE rowid = ".((int) $this->
id);
1839 $resqltoupdatecontract = $this->db->query($sqltoupdatecontract);
1840 if (!$resqltoupdatecontract) {
1841 $this->error = $this->db->lasterror();
1842 $this->db->rollback();
1846 if (empty($error)) {
1848 $this->context[
'line_id'] = $rowid;
1849 $result = $this->call_trigger(
'LINECONTRACT_MODIFY', $user);
1851 $this->db->rollback();
1856 $this->db->commit();
1859 $this->db->rollback();
1863 $this->db->rollback();
1864 $this->error = $this->db->error();
1865 dol_syslog(get_class($this).
"::updateline Erreur -1");
1881 if ($this->statut >= 0) {
1883 $this->context[
'line_id'] = $idline;
1884 $result = $this->call_trigger(
'LINECONTRACT_DELETE', $user);
1892 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.$this->table_element_line;
1893 $sql .=
" WHERE rowid = ".((int) $idline);
1895 dol_syslog(get_class($this).
"::deleteline", LOG_DEBUG);
1896 $resql = $this->db->query($sql);
1898 $this->error =
"Error ".$this->db->lasterror();
1905 $contractline->id = $idline;
1906 $result = $contractline->deleteExtraFields();
1909 $this->error =
"Error ".get_class($this).
"::deleteline deleteExtraFields error -4 ".$contractline->error;
1913 if (empty($error)) {
1914 $this->db->commit();
1917 dol_syslog(get_class($this).
"::deleteline ERROR:".$this->error, LOG_ERR);
1918 $this->db->rollback();
1922 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
1939 dol_syslog(__METHOD__.
" is deprecated", LOG_WARNING);
1942 if ($this->statut == 0) {
1967 return $this->
LibStatut($this->statut, $mode);
1983 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
1985 $langs->load(
"contracts");
1986 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv(
'ContractStatusDraft');
1987 $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv(
'ContractStatusValidated');
1988 $this->labelStatus[self::STATUS_CLOSED] = $langs->transnoentitiesnoconv(
'ContractStatusClosed');
1989 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv(
'ContractStatusDraft');
1990 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv(
'ContractStatusValidated');
1991 $this->labelStatusShort[self::STATUS_CLOSED] = $langs->transnoentitiesnoconv(
'ContractStatusClosed');
1994 $statusType =
'status'.$status;
1995 if ($status == self::STATUS_VALIDATED) {
1996 $statusType =
'status6';
1999 if ($mode == 4 || $mode == 6 || $mode == 7) {
2002 $text =
'<span class="hideonsmartphone">';
2003 $text .= ($this->nbofserviceswait + $this->nbofservicesopened + $this->nbofservicesexpired + $this->nbofservicesclosed);
2004 $text .=
' '.$langs->trans(
"Services");
2005 $text .=
': ';
2008 $text .= ($mode == 7 ?
'<span class="nowraponall">' :
'');
2009 $text .= ($mode != 7 || $this->nbofserviceswait > 0) ? ($this->nbofserviceswait.ContratLigne::LibStatut(0, 3, -1,
'class="marginleft2"')).(($mode != 7 || $this->nbofservicesopened || $this->nbofservicesexpired || $this->nbofservicesclosed) ?
' ' :
'') :
'';
2010 $text .= ($mode == 7 ?
'</span><span class="nowraponall">' :
'');
2011 $text .= ($mode != 7 || $this->nbofservicesopened > 0) ? ($this->nbofservicesopened.ContratLigne::LibStatut(4, 3, 0,
'class="marginleft2"')).(($mode != 7 || $this->nbofservicesexpired || $this->nbofservicesclosed) ?
' ' :
'') :
'';
2012 $text .= ($mode == 7 ?
'</span><span class="nowraponall">' :
'');
2013 $text .= ($mode != 7 || $this->nbofservicesexpired > 0) ? ($this->nbofservicesexpired.ContratLigne::LibStatut(4, 3, 1,
'class="marginleft2"')).(($mode != 7 || $this->nbofservicesclosed) ?
' ' :
'') :
'';
2014 $text .= ($mode == 7 ?
'</span><span class="nowraponall">' :
'');
2015 $text .= ($mode != 7 || $this->nbofservicesclosed > 0) ? ($this->nbofservicesclosed.ContratLigne::LibStatut(5, 3, -1,
'class="marginleft2"')) :
'';
2016 $text .= ($mode == 7 ?
'</span>' :
'');
2018 $text .= is_null($this->signed_status) ?
'' :
' '.$this->getLibSignedStatus(5);
2022 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status],
'', $statusType, $mode);
2034 global
$conf, $langs, $user;
2036 $langs->load(
'contracts');
2039 $nofetch = !empty($params[
'nofetch']);
2042 return [
'optimize' => $langs->trans(
"ShowContract")];
2044 if ($user->hasRight(
'contrat',
'lire')) {
2045 $datas[
'picto'] =
img_picto(
'', $this->picto).
' <u class="paddingrightonly">'.$langs->trans(
"Contract").
'</u>';
2050 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.($this->
ref ? $this->
ref : $this->id);
2052 $langs->load(
'companies');
2053 if (empty($this->thirdparty)) {
2056 $datas[
'customer'] =
'<br><b>'.$langs->trans(
'Customer').
':</b> '.$this->thirdparty->getNomUrl(1,
'', 0, 1);
2058 $datas[
'refcustomer'] =
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '. $this->ref_customer;
2060 $langs->load(
'project');
2061 if (is_null($this->project) || (is_object($this->project) && $this->project->isEmpty())) {
2063 if ($res > 0 && $this->project instanceof
Project) {
2064 $datas[
'project'] =
'<br><b>'.$langs->trans(
'Project').
':</b> '.$this->project->getNomUrl(1,
'', 0,
'1');
2068 $datas[
'refsupplier'] =
'<br><b>'.$langs->trans(
'RefSupplier').
':</b> '.$this->ref_supplier;
2069 if (!empty($this->total_ht)) {
2070 $datas[
'amountht'] =
'<br><b>'.$langs->trans(
'AmountHT').
':</b> '.
price($this->total_ht, 0, $langs, 0, -1, -1,
$conf->currency);
2072 if (!empty($this->total_tva)) {
2073 $datas[
'vatamount'] =
'<br><b>'.$langs->trans(
'VAT').
':</b> '.
price($this->total_tva, 0, $langs, 0, -1, -1,
$conf->currency);
2075 if (!empty($this->total_ttc)) {
2076 $datas[
'amounttc'] =
'<br><b>'.$langs->trans(
'AmountTTC').
':</b> '.
price($this->total_ttc, 0, $langs, 0, -1, -1,
$conf->currency);
2091 public function getNomUrl($withpicto = 0, $maxlength = 0, $notooltip = 0, $save_lastsearch_value = -1)
2093 global $langs, $user, $hookmanager;
2097 $baseurl = DOL_URL_ROOT .
'/contrat/card.php';
2098 $query = [
'id' => $this->id];
2103 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2104 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
2105 $add_save_lastsearch_values = 1;
2107 if ($add_save_lastsearch_values) {
2108 $query = array_merge($query, [
'save_lastsearch_values' => 1]);
2114 'objecttype' => $this->element,
2117 $classfortooltip =
'classfortooltip';
2120 $classfortooltip =
'classforajaxtooltip';
2121 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
2128 if (empty($notooltip) && $user->hasRight(
'contrat',
'lire')) {
2130 $label = $langs->trans(
"ShowContract");
2131 $linkclose .=
' alt="'.dolPrintHTMLForAttribute($label).
'"';
2133 $linkclose .= ($label ?
' title="'.dolPrintHTMLForAttribute($label).
'"' :
' title="tocomplete"');
2134 $linkclose .= $dataparams.
' class="'.$classfortooltip.
'"';
2136 $linkstart =
'<a href="'.$url.
'"';
2137 $linkstart .= $linkclose.
'>';
2140 $result .= $linkstart;
2142 $result .=
img_object(($notooltip ?
'' : $label), ($this->picto ? $this->picto :
'generic'), (($withpicto != 2) ?
'class="paddingright"' :
''), 0, 0, $notooltip ? 0 : 1);
2144 if ($withpicto != 2) {
2145 $result .= ($this->
ref ? $this->
ref : $this->id);
2147 $result .= $linkend;
2150 $hookmanager->initHooks(array(
'contractdao'));
2151 $parameters = array(
'id' => $this->
id,
'getnomurl' => &$result);
2152 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
2154 $result = $hookmanager->resPrint;
2156 $result .= $hookmanager->resPrint;
2170 $sql =
"SELECT c.rowid, c.ref, c.datec,";
2171 $sql .=
" c.tms as date_modification,";
2172 $sql .=
" fk_user_author";
2173 $sql .=
" FROM ".MAIN_DB_PREFIX.
"contrat as c";
2174 $sql .=
" WHERE c.rowid = ".((int) $id);
2176 $result = $this->db->query($sql);
2178 if ($this->db->num_rows($result)) {
2179 $obj = $this->db->fetch_object($result);
2181 $this->
id = $obj->rowid;
2182 $this->
ref = (!$obj->ref) ? $obj->rowid : $obj->ref;
2184 $this->user_creation_id = $obj->fk_user_author;
2185 $this->date_creation = $this->db->jdate($obj->datec);
2186 $this->date_modification = $this->db->jdate($obj->date_modification);
2189 $this->db->free($result);
2207 $sql =
"SELECT cd.rowid";
2208 $sql .=
" FROM ".MAIN_DB_PREFIX.
"contratdet as cd";
2209 $sql .=
" WHERE fk_contrat =".((int) $this->
id);
2211 $sql .=
" AND statut = ".((int) $status);
2214 dol_syslog(get_class($this).
"::array_detail()", LOG_DEBUG);
2215 $resql = $this->db->query($sql);
2217 $num = $this->db->num_rows($resql);
2220 $obj = $this->db->fetch_object($resql);
2221 $tab[$i] = $obj->rowid;
2226 $this->error = $this->db->error();
2240 public function getListOfContracts($option =
'all', $status = [], $product_categories = [], $line_status = [])
2244 $sql =
"SELECT c.rowid";
2245 $sql .=
" FROM ".MAIN_DB_PREFIX.
"contrat as c";
2246 if (!empty($product_categories) || !empty($line_status)) {
2247 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"contratdet as cd ON cd.fk_contrat = c.rowid";
2249 if (!empty($product_categories)) {
2250 $sql .=
" INNER JOIN ".MAIN_DB_PREFIX.
"categorie_product as cp ON cp.fk_product = cd.fk_product AND cp.fk_categorie IN (".$this->db->sanitize(implode(
', ', $product_categories)).
")";
2252 $sql .=
" WHERE c.fk_soc =".((int) $this->socid);
2253 $sql .= ($option ==
'others') ?
" AND c.rowid <> ".((
int) $this->id) :
"";
2254 $sql .= (!empty($status)) ?
" AND c.statut IN (".$this->db->sanitize(implode(
', ', $status)).
")" :
"";
2255 $sql .= (!empty($line_status)) ?
" AND cd.statut IN (".$this->db->sanitize(implode(
', ', $line_status)).
")" :
"";
2256 $sql .=
" GROUP BY c.rowid";
2258 dol_syslog(get_class($this).
"::getOtherContracts()", LOG_DEBUG);
2259 $resql = $this->db->query($sql);
2261 $num = $this->db->num_rows($resql);
2264 $obj = $this->db->fetch_object($resql);
2265 $contrat =
new Contrat($this->db);
2266 $contrat->fetch($obj->rowid);
2267 $tab[$contrat->id] = $contrat;
2272 $this->error = $this->db->lasterror();
2289 global
$conf, $langs;
2291 $this->from =
" FROM ".MAIN_DB_PREFIX.
"contrat as c";
2292 $this->from .=
", ".MAIN_DB_PREFIX.
"contratdet as cd";
2293 $this->from .=
", ".MAIN_DB_PREFIX.
"societe as s";
2294 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
2295 $this->from .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
2298 if ($mode ==
'inactive') {
2299 $sql =
"SELECT cd.rowid, cd.date_ouverture_prevue as datefin";
2300 $sql .= $this->from;
2301 $sql .=
" WHERE c.statut = 1";
2302 $sql .=
" AND c.rowid = cd.fk_contrat";
2303 $sql .=
" AND cd.statut = 0";
2304 } elseif ($mode ==
'expired') {
2305 $sql =
"SELECT cd.rowid, cd.date_fin_validite as datefin";
2306 $sql .= $this->from;
2307 $sql .=
" WHERE c.statut = 1";
2308 $sql .=
" AND c.rowid = cd.fk_contrat";
2309 $sql .=
" AND cd.statut = 4";
2310 $sql .=
" AND cd.date_fin_validite < '".$this->db->idate(
dol_now()).
"'";
2311 } elseif ($mode ==
'active') {
2312 $sql =
"SELECT cd.rowid, cd.date_fin_validite as datefin";
2313 $sql .= $this->from;
2314 $sql .=
" WHERE c.statut = 1";
2315 $sql .=
" AND c.rowid = cd.fk_contrat";
2316 $sql .=
" AND cd.statut = 4";
2322 $sql .=
" AND c.fk_soc = s.rowid";
2323 $sql .=
" AND c.entity = ".((int)
$conf->entity);
2325 $sql .=
" AND c.fk_soc = ".((int) $user->socid);
2327 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
2328 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
2331 $resql = $this->db->query($sql);
2333 $langs->load(
"contracts");
2336 if ($mode ==
'inactive') {
2337 $warning_delay =
$conf->contract->services->inactifs->warning_delay;
2338 $label = $langs->trans(
"BoardNotActivatedServices");
2339 $labelShort = $langs->trans(
"BoardNotActivatedServicesShort");
2340 $url = DOL_URL_ROOT.
'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_status=0&sortfield=cd.date_fin_validite&sortorder=asc';
2341 $url_late = DOL_URL_ROOT.
'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_status=0&search_option=late';
2342 } elseif ($mode ==
'expired') {
2343 $warning_delay =
$conf->contract->services->expires->warning_delay;
2344 $url = DOL_URL_ROOT.
'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_status=4&filter=expired&sortfield=cd.date_fin_validite&sortorder=asc';
2345 $url_late = DOL_URL_ROOT.
'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_status=4&search_option=late';
2346 $label = $langs->trans(
"BoardExpiredServices");
2347 $labelShort = $langs->trans(
"BoardExpiredServicesShort");
2349 $warning_delay =
$conf->contract->services->expires->warning_delay;
2350 $url = DOL_URL_ROOT.
'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_status=4&sortfield=cd.date_fin_validite&sortorder=asc';
2351 $url_late = DOL_URL_ROOT.
'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_option=late';
2352 $label = $langs->trans(
"BoardRunningServices");
2353 $labelShort = $langs->trans(
"BoardRunningServicesShort");
2357 $response->warning_delay = $warning_delay / 60 / 60 / 24;
2358 $response->label = $label;
2359 $response->labelShort = $labelShort;
2360 $response->url = $url;
2361 $response->url_late = $url_late;
2364 while ($obj = $this->db->fetch_object($resql)) {
2365 $response->nbtodo++;
2367 if ($obj->datefin && $this->db->jdate($obj->datefin) < ($now - $warning_delay)) {
2368 $response->nbtodolate++;
2375 $this->error = $this->db->error();
2387 global
$conf, $user;
2389 $this->nb = array();
2390 $sanitizedclause =
"WHERE";
2392 $sql =
"SELECT count(c.rowid) as nb";
2393 $sql .=
" FROM ".MAIN_DB_PREFIX.
"contrat as c";
2394 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON c.fk_soc = s.rowid";
2395 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
2396 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON s.rowid = sc.fk_soc";
2397 $sql .=
" WHERE sc.fk_user = ".((int) $user->id);
2398 $sanitizedclause =
"AND";
2400 $sql .=
" ".$sanitizedclause.
" c.entity = ".((int)
$conf->entity);
2402 $resql = $this->db->query($sql);
2404 while ($obj = $this->db->fetch_object($resql)) {
2405 $this->nb[
"contracts"] = $obj->nb;
2407 $this->db->free($resql);
2411 $this->error = $this->db->error();
2449 global $user, $langs,
$conf;
2454 $sql =
"SELECT rowid";
2455 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product";
2456 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
2457 $sql .=
" AND tosell = 1";
2458 $sql .= $this->db->plimit(100);
2460 $resql = $this->db->query($sql);
2462 $num_prods = $this->db->num_rows($resql);
2464 while ($i < $num_prods) {
2466 $row = $this->db->fetch_row($resql);
2467 $prodids[$i] = $row[0];
2473 $this->specimen = 1;
2475 $this->
ref =
'SPECIMEN';
2476 $this->ref_customer =
'SPECIMENCUST';
2477 $this->ref_supplier =
'SPECIMENSUPP';
2480 $this->date_creation = (
dol_now() - 3600 * 24 * 7);
2481 $this->date_contrat =
dol_now();
2482 $this->commercial_signature_id = 1;
2483 $this->commercial_suivi_id = 1;
2484 $this->note_private =
'This is a comment (private)';
2485 $this->note_public =
'This is a comment (public)';
2486 $this->fk_project = 0;
2490 while ($xnbp < $nbp) {
2493 $line->subprice = 100;
2494 $line->tva_tx = 19.6;
2495 $line->remise_percent = 10;
2496 $line->total_ht = 90;
2497 $line->total_ttc = 107.64;
2498 $line->total_tva = 17.64;
2499 $line->date_start =
dol_now() - 500000;
2500 $line->date_start_real =
dol_now() - 200000;
2501 $line->date_end =
dol_now() + 500000;
2502 $line->date_end_real =
dol_now() - 100000;
2503 if ($num_prods > 0) {
2504 $prodid = mt_rand(1, $num_prods);
2505 $line->fk_product = $prodids[$prodid];
2507 $this->lines[$xnbp] = $line;
2533 $ticket =
new Ticket($this->db);
2534 $nbTicket = $ticket->fetchAll($user,
'ASC',
't.datec', 0, 0, 0, array(
't.fk_contract' => $this->
id));
2536 return ($nbTicket < 0 ? $nbTicket : $ticket->lines);
2551 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams =
null)
2558 if (!empty($this->model_pdf)) {
2559 $modele = $this->model_pdf;
2565 if (empty($modele)) {
2568 $langs->load(
"contracts");
2569 $outputlangs->load(
"products");
2571 $modelpath =
"core/modules/contract/doc/";
2572 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
2618 public function createFromClone(
User $user, $socid = 0, $notrigger = 0)
2620 global
$db, $langs,
$conf, $hookmanager, $extrafields;
2626 $this->
fetch($this->
id);
2629 $clonedObj = clone $this;
2630 $clonedObj->socid = $socid;
2634 $objsoc =
new Societe($this->db);
2636 $objsoc->fetch($clonedObj->socid);
2639 $clonedObj->statut = 0;
2640 $clonedObj->status = 0;
2642 if (is_array($clonedObj->array_options) && count($clonedObj->array_options) > 0) {
2643 $extrafields->fetch_name_optionals_label($this->table_element);
2644 foreach ($clonedObj->array_options as $key => $option) {
2645 $shortkey = preg_replace(
'/options_/',
'', $key);
2646 if (!empty($extrafields->attributes[$this->element][
'unique'][$shortkey])) {
2647 unset($clonedObj->array_options[$key]);
2653 $this->error =
'ErrorSetupNotComplete';
2659 require_once DOL_DOCUMENT_ROOT.
"/core/modules/contract/" .
getDolGlobalString(
'CONTRACT_ADDON').
'.php';
2661 $modContract =
new $obj();
2662 '@phan-var-force ModelNumRefContracts $modContract';
2664 $clonedObj->ref = $modContract->getNextValue($objsoc, $clonedObj);
2667 foreach ($this->lines as $line) {
2668 $line->fetch_optionals($line->id);
2672 $clonedObj->context[
'createfromclone'] =
'createfromclone';
2673 $result = $clonedObj->create($user);
2679 if ($this->socid == $clonedObj->socid) {
2680 if ($clonedObj->copy_linked_contact($this,
'external') < 0) {
2687 foreach ($this->lines as $line) {
2691 $line_price_base_type = $line->getPriceBaseType();
2692 $result = $clonedObj->addline($line->description, (
float) $line->subprice, $line->qty, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, $line->fk_product, $line->remise_percent, $line->date_start, $line->date_cloture, $line_price_base_type, (
float) $line->subprice_ttc, $line->info_bits, $line->fk_fournprice, $line->pa_ht, $line->array_options, $line->fk_unit, $line->rang);
2702 if (is_object($hookmanager)) {
2703 $parameters = array(
2705 'clonedObj' => $clonedObj
2708 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $clonedObj, $action);
2716 unset($clonedObj->context[
'createfromclone']);
2720 $this->db->commit();
2721 return $clonedObj->id;
2723 $this->db->rollback();
2740 global $langs, $user;
2742 $langs->load(
"agenda");
2752 $contractlineprocessed = array();
2753 $contractignored = array();
2754 $contracterror = array();
2758 $sql =
'SELECT c.rowid, c.ref_customer, cd.rowid as lid, cd.date_fin_validite, p.duration';
2759 $sql .=
' FROM '.MAIN_DB_PREFIX.
'contrat as c, '.MAIN_DB_PREFIX.
'contratdet as cd';
2760 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON p.rowid = cd.fk_product';
2761 $sql .=
' WHERE cd.fk_contrat = c.rowid';
2762 $sql .=
" AND date_format(cd.date_fin_validite, '%Y-%m-%d') <= date_format('".$this->db->idate($enddatetoscan).
"', '%Y-%m-%d')";
2763 $sql .=
" AND cd.statut = 4";
2764 if ($thirdparty_id > 0) {
2765 $sql .=
" AND c.fk_soc = ".((int) $thirdparty_id);
2769 $resql = $this->db->query($sql);
2771 $num = $this->db->num_rows($resql);
2773 include_once DOL_DOCUMENT_ROOT.
'/core/class/html.formmail.class.php';
2774 include_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
2778 $obj = $this->db->fetch_object($resql);
2780 if (!empty($contractlineprocessed[$obj->lid]) || !empty($contractignored[$obj->rowid]) || !empty($contracterror[$obj->rowid])) {
2790 $this->errors[] =
'Failed to load contract with id='.$obj->rowid;
2794 dol_syslog(
"* Process contract line in doRenewalContracts for contract id=".
$object->id.
" ref=".
$object->ref.
" ref_customer=".
$object->ref_customer.
" contract line id=".$obj->lid);
2797 $expirationdate = $this->db->jdate($obj->date_fin_validite);
2798 $duration_value = preg_replace(
'/[^0-9]/',
'', $obj->duration);
2799 $duration_unit = preg_replace(
'/\d/',
'', $obj->duration);
2803 $object->fetchObjectLinked(
null,
'',
null,
'',
'OR', 1,
'sourcetype', 1);
2806 if (isset(
$object->linkedObjects[
'facture']) && is_array(
$object->linkedObjects[
'facture']) && count(
$object->linkedObjects[
'facture']) > 0) {
2808 usort(
$object->linkedObjects[
'facture'], array(
'Contrat',
'contractCmpDate'));
2811 $someinvoicenotpaid = 0;
2812 foreach (
$object->linkedObjects[
'facture'] as $idinvoice => $invoice) {
2817 if (empty($invoice->paye)) {
2818 $someinvoicenotpaid++;
2821 if ($someinvoicenotpaid) {
2822 $this->output .=
'Contract '.$object->ref.
' is qualified for renewal but there is '.$someinvoicenotpaid.
' invoice(s) unpayed so we cancel renewal'.
"\n";
2828 if ($expirationdate && $expirationdate < $enddatetoscan) {
2829 dol_syslog(
"Define the newdate of end of services from expirationdate=".$expirationdate);
2830 $newdate = $expirationdate;
2832 while ($newdate < $enddatetoscan && $protecti < 1000) {
2837 if ($protecti < 1000) {
2843 $errorforlocaltransaction = 0;
2845 $label =
'Renewal of contrat '.$object->ref.
' line '.$obj->lid;
2846 $comment =
'Renew date of contract '.$object->ref.
' line '.$obj->lid.
' by doAutoRenewContracts';
2848 $sqlupdate =
'UPDATE '.MAIN_DB_PREFIX.
"contratdet SET date_fin_validite = '".$this->db->idate($newdate).
"'";
2849 $sqlupdate .=
' WHERE rowid = '.((int) $obj->lid);
2850 $resqlupdate = $this->db->query($sqlupdate);
2852 $contractlineprocessed[$obj->lid] =
$object->ref;
2855 $sqltoupdatecontract =
"UPDATE ".MAIN_DB_PREFIX.
"contrat";
2856 $sqltoupdatecontract .=
" SET denormalized_lower_planned_end_date = (SELECT MIN(date_fin_validite) FROM ".MAIN_DB_PREFIX.
"contratdet as cd WHERE cd.fk_contrat = ".((int)
$object->id).
" AND cd.statut = ".ContratLigne::STATUS_OPEN.
")";
2857 $sqltoupdatecontract .=
" WHERE rowid = ".((int)
$object->id);
2858 $resqltoupdatecontract = $this->db->query($sqltoupdatecontract);
2859 if (!$resqltoupdatecontract) {
2860 $this->error = $this->db->lasterror();
2861 $this->db->rollback();
2865 $actioncode =
'RENEW_CONTRACT';
2870 $actioncomm->type_code =
'AC_OTH_AUTO';
2871 $actioncomm->code =
'AC_'.$actioncode;
2872 $actioncomm->label = $label;
2873 $actioncomm->datep = $now;
2874 $actioncomm->datef = $now;
2875 $actioncomm->percentage = -1;
2876 $actioncomm->socid =
$object->socid;
2877 $actioncomm->authorid = $user->id;
2878 $actioncomm->userownerid = $user->id;
2879 $actioncomm->fk_element =
$object->id;
2880 $actioncomm->elementid =
$object->id;
2881 $actioncomm->elementtype =
'contract';
2882 $actioncomm->note_private = $comment;
2884 $ret = $actioncomm->create($user);
2889 $errorforlocaltransaction++;
2890 $this->error = $this->db->lasterror();
2893 if (! $errorforlocaltransaction) {
2894 $this->db->commit();
2896 $this->db->rollback();
2900 $this->error =
"Bad value for newdate in doAutoRenewContracts - expirationdate=".$expirationdate.
" enddatetoscan=".$enddatetoscan.
" duration_value=".$duration_value.
" duration_unit=".$duration_value;
2909 $this->error = $this->db->lasterror();
2912 $this->output .= count($contractlineprocessed).
' contract line(s) with end date before '.
dol_print_date($enddatetoscan,
'day').
' were renewed'.(count($contractlineprocessed) > 0 ?
' : '.implode(
',', $contractlineprocessed) :
'');
2914 return ($error ? 1 : 0);
2926 if ($a->date == $b->date) {
2927 return strcmp((
string) $a->id, (
string) $b->id);
2929 return ($a->date < $b->date) ? -1 : 1;
2943 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
2945 $return =
'<div class="box-flex-item box-flex-grow-zero">';
2946 $return .=
'<div class="info-box info-box-sm">';
2947 $return .=
'<span class="info-box-icon bg-infobox-action">';
2949 $return .=
'</span>';
2950 $return .=
'<div class="info-box-content">';
2951 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . $this->
getNomUrl() .
'</span>';
2952 if ($selected >= 0) {
2953 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
2955 if (!empty($arraydata[
'thirdparty']) && $arraydata[
'thirdparty'] instanceof
Societe) {
2956 $tmpthirdparty = $arraydata[
'thirdparty'];
2957 '@phan-var-force Societe $tmpthirdparty';
2958 $return .=
'<br><div class="info-box-label inline-block valignmiddle">'.$tmpthirdparty->getNomUrl(1).
'</div>';
2960 $return .=
'<br><span class="opacitymedium valignmiddle">'.$langs->trans(
"DateContract").
' : </span><span class="info-box-label valignmiddle">'.
dol_print_date($this->date_contrat,
'day').
'</span>';
2961 $return .=
'<br><div class="info-box-status valignmiddle">'.$this->getLibStatut(7).
'</div>';
2962 $return .=
'</div>';
2963 $return .=
'</div>';
2964 $return .=
'</div>';
2978 $sql =
"SELECT SUM(cd.qty) as total_qty, SUM(cd.total_ht) as total_ht, SUM(cd.total_tva) as total_tva, SUM(cd.total_ttc) as total_ttc,";
2979 $sql .=
" SUM(cd.total_localtax1) as total_localtax1, SUM(cd.total_localtax2) as total_localtax2";
2980 $sql .=
" FROM ".MAIN_DB_PREFIX.
"contratdet as cd";
2981 $sql .=
" WHERE cd.fk_contrat =".((int) $this->
id);
2983 $sql .=
" AND cd.statut = ".((int) $statut);
2985 $sql .=
" AND cd.date_fin_validite < '".$this->db->idate(
dol_now()).
"'";
2987 $sql .=
" AND cd.date_fin_validite >= '".$this->db->idate(
dol_now()).
"'";
2990 $ret = $this->db->query($sql);
2991 $response = array();
2993 $obj = $this->db->fetch_object($ret);
2994 $response[
'total_qty'] = $obj->total_qty;
2995 $response[
'total_ht'] = $obj->total_ht;
2996 $response[
'total_tva'] = $obj->total_tva;
2997 $response[
'total_localtax1'] = $obj->total_localtax1;
2998 $response[
'total_localtax2'] = $obj->total_localtax2;
2999 $response[
'total_ttc'] = $obj->total_ttc;
3002 $this->error = $this->db->lasterror();
3046 $blockingerrormsg =
'';
3049 $langs->load(
"agenda");
3050 $this->output = $langs->trans(
'ModuleNotEnabled', $langs->transnoentitiesnoconv(
"Contract"));
3058 $listoflinesok = array();
3059 $listoflinesko = array();
3061 $arraydaysbeforeend = explode(
';', $daysbeforeendlist);
3062 foreach ($arraydaysbeforeend as $daysbeforeend) {
3063 dol_syslog(__METHOD__.
' - Process delta = '.$daysbeforeend, LOG_DEBUG);
3065 if (!is_numeric($daysbeforeend)) {
3066 $blockingerrormsg =
"Value for delta is not a numeric value";
3072 $datetosearchfor =
dol_time_plus_duree(
dol_mktime(0, 0, 0, $tmp[
'mon'], $tmp[
'mday'], $tmp[
'year'],
'tzserver'), (
int) $daysbeforeend,
'd');
3073 $datetosearchforend =
dol_time_plus_duree(
dol_mktime(23, 59, 59, $tmp[
'mon'], $tmp[
'mday'], $tmp[
'year'],
'tzserver'), (
int) $daysbeforeend,
'd');
3075 $sql =
"SELECT cd.rowid, cd.fk_contrat";
3076 $sql .=
" FROM ".MAIN_DB_PREFIX.
"contratdet as cd";
3077 $sql .=
" INNER JOIN ".MAIN_DB_PREFIX.
"contrat as c ON c.rowid = cd.fk_contrat";
3078 $sql .=
" WHERE c.entity = ".((int)
$conf->entity);
3079 $sql .=
" AND cd.statut = ".((int) ContratLigne::STATUS_OPEN);
3080 $sql .=
" AND cd.date_fin_validite >= '".$this->db->idate($datetosearchfor).
"'";
3081 $sql .=
" AND cd.date_fin_validite <= '".$this->db->idate($datetosearchforend).
"'";
3082 if ((
int) $fk_product > 0) {
3083 $sql .=
" AND cd.fk_product = ".((int) $fk_product);
3086 $resql = $this->db->query($sql);
3088 $num_rows = $this->db->num_rows($resql);
3090 include_once DOL_DOCUMENT_ROOT.
'/core/class/html.formmail.class.php';
3091 include_once DOL_DOCUMENT_ROOT.
'/contrat/class/contratligne.class.php';
3092 $formmail =
new FormMail($this->db);
3095 while ($i < $num_rows) {
3096 $obj = $this->db->fetch_object($resql);
3099 $contractline->fetch($obj->rowid);
3101 $contractstatic =
new Contrat($this->db);
3102 $contractstatic->fetch($obj->fk_contrat);
3103 $thirdpartyres = $contractstatic->fetch_thirdparty();
3105 if ($thirdpartyres <= 0 || empty($contractstatic->thirdparty->email)) {
3107 $listoflinesko[$contractline->id] = $contractline->id;
3110 $languagecodetouse = (empty($contractstatic->thirdparty->default_lang) ? ($languagefromcountrycode ? $languagefromcountrycode :
$mysoc->default_lang) : $contractstatic->thirdparty->default_lang);
3113 $outputlangs->setDefaultLang($languagecodetouse);
3114 $outputlangs->loadLangs(array(
"main",
"contracts"));
3115 dol_syslog(
"sendReminderForExpiredServices Language for thirdparty id ".$contractstatic->thirdparty->id.
" set to ".$outputlangs->defaultlang.
" mysoc->default_lang=".
$mysoc->default_lang);
3117 $arraydefaultmessage =
null;
3120 if (!empty($labeltouse)) {
3121 $arraydefaultmessage = $formmail->getEMailTemplate($this->db,
'contrat', $user, $outputlangs, 0, 1, $labeltouse);
3124 if (!empty($labeltouse) && is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
3125 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0,
null, $contractstatic);
3127 $substitutionarray[
'__CONTRACT_LINE_LABEL__'] = ($contractline->label ? $contractline->label : $contractline->description);
3128 $substitutionarray[
'__CONTRACT_LINE_DATE_END__'] =
dol_print_date($contractline->date_end,
'day',
'tzuserrel', $outputlangs);
3130 $subject =
make_substitutions($arraydefaultmessage->topic, $substitutionarray, $outputlangs);
3131 $msg =
make_substitutions($arraydefaultmessage->content, $substitutionarray, $outputlangs);
3133 $to = (
string) $contractstatic->thirdparty->email;
3136 $trackid =
'con'.$contractstatic->id;
3137 $moreinheader =
'X-Dolibarr-Info: sendReminderForExpiredServices'.
"\r\n";
3139 include_once DOL_DOCUMENT_ROOT.
'/core/class/CMailFile.class.php';
3140 $cmail =
new CMailFile($subject, $to, $email_from, $msg, array(), array(), array(), $cc,
'', 0, 1,
'',
'', $trackid, $moreinheader);
3141 $result = $cmail->sendfile();
3144 $this->error .= $cmail->error.
' ';
3145 if (!is_null($cmail->errors)) {
3146 $this->errors = array_merge($this->errors, $cmail->errors);
3149 $listoflinesko[$contractline->id] = $contractline->id;
3152 $listoflinesok[$contractline->id] = $contractline->id;
3155 require_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
3158 $actioncomm->type_code =
'AC_OTH_AUTO';
3159 $actioncomm->code =
'AC_EMAIL';
3161 $actioncomm->note_private = $msg;
3162 $actioncomm->fk_project = 0;
3163 $actioncomm->datep = $now;
3164 $actioncomm->datef = $now;
3165 $actioncomm->percentage = -1;
3166 $actioncomm->socid = $contractstatic->thirdparty->id;
3167 $actioncomm->contact_id = 0;
3168 $actioncomm->authorid = $user->id;
3169 $actioncomm->userownerid = $user->id;
3170 $actioncomm->email_msgid = $cmail->msgid;
3171 $actioncomm->email_from = $email_from;
3172 $actioncomm->email_sender =
'';
3173 $actioncomm->email_to = $to;
3174 $actioncomm->email_subject = $subject;
3176 $actioncomm->fk_element = $contractstatic->id;
3177 $actioncomm->elementid = $contractstatic->id;
3178 $actioncomm->elementtype = $contractstatic->element;
3180 $actioncomm->create($user);
3184 $this->error .=
"Can't find email template with label=".$labeltouse.
", to use for the reminding email ";
3187 $listoflinesko[$contractline->id] = $contractline->id;
3196 $this->error = $this->db->lasterror();
3201 if ($blockingerrormsg) {
3202 $this->error = $blockingerrormsg;
3205 $this->output =
'Found '.($nbok + $nbko).
' contract lines to send reminder for.';
3206 $this->output .=
' Sent email successfully for '.$nbok.
' lines';
3208 $this->output .=
' - Canceled for '.$nbko.
' line(s) (no thirdparty email, missing template, or send error)';
if(! $sortfield) if(! $sortorder) $object
Class to manage agenda events (actions)
Class to send emails (with attachments or not) Usage: $mailfile = new CMailFile($subject,...
static getValidAddress($address, $format, $encode=0, $maxnumberofemail=0)
Return a formatted address string for SMTP protocol.
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...
deleteEcmFiles($mode=0)
Delete related files of object in database.
add_object_linked($origin=null, $origin_id=null, $f_user=null, $notrigger=0)
Add an object link into llx_element_element.
defineBuyPrice($unitPrice=0.0, $discountPercent=0.0, $fk_product=0)
Get buy price to use for margin calculation.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
fetchProject()
Load the project with id $this->fk_project into this->project.
fetch_thirdparty($force_thirdparty_id=0)
Load the third party of object, from id $this->socid or $this->fk_soc, into this->thirdparty.
getIdContact($source, $code, $status=0)
Return id of contacts for a source and a contact code.
deleteObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $rowid=0, $f_user=null, $notrigger=0)
Delete all links between an object $this.
setErrorsFromObject($object)
setErrorsFromObject
deleteExtraFields()
Delete all extra fields values for the current object.
static commonReplaceThirdparty(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
static commonReplaceProduct(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a product id with another one.
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
delete_linked_contact($source='', $code='')
Delete all links between an object $this and all its contacts in llx_element_contact.
add_contact($fk_socpeople, $type_contact, $source='external', $notrigger=0)
Add a link between element $this->element and a contact.
static contractCmpDate($a, $b)
Used to sort lines by date.
getTotalizedLines($statut, int $expired)
Return totalized lines.
fetch($id, $ref='', $ref_customer='', $ref_supplier='', $noextrafields=0, $nolines=0)
Load a contract from database.
loadStateBoard()
Load the indicators this->nb for state board.
update_statut($user)
Update statut of contract according to services.
closeAll(User $user, $notrigger=0, $comment='', $nofetchlines=0)
Close all lines of a contract.
updateline($rowid, $desc, $pu, $qty, $remise_percent, $date_start, $date_end, $tvatx, $localtax1tx=0.0, $localtax2tx=0.0, $date_start_real='', $date_end_real='', $price_base_type='HT', $info_bits=0, $fk_fournprice=null, $pa_ht=0, $array_options=array(), $fk_unit=null, $rang=0)
Update a contract line.
getTicketsArray()
Create an array of associated tickets.
setSignedStatus(User $user, int $status=0, int $notrigger=0, $triggercode='')
Set signed status.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
active_line($user, $line_id, $date_start, $date_end='', $comment='')
Activate a contract line.
getTooltipContentArray($params)
getTooltipContentArray
getLinesArray()
Create an array of order lines.
validate(User $user, $force_number='', $notrigger=0)
Validate a contract.
getIdBillingContact()
Return id des contacts clients de facturation.
initAsSpecimen()
Initialise an instance with random values.
close_line($user, $line_id, $date_end, $comment='')
Close a contract line.
reopen($user, $notrigger=0)
Unvalidate a contract.
getKanbanView($option='', $arraydata=null)
Return clickable link of object (with eventually picto)
deleteLine($idline, User $user)
Delete a contract line.
array_detail($status=-1)
Return list of line rowid.
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=array(), $fk_unit=null, $rang=0)
Insert contract line into database.
update($user, $notrigger=0)
Update object into database.
static replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
getListOfContracts($option='all', $status=[], $product_categories=[], $line_status=[])
Return list of other contracts for the same company than current contract.
load_board($user, $mode)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
LibStatut($status, $mode)
Return the label of a given contrat status.
activateAll($user, $date_start='', $notrigger=0, $comment='', $date_end='')
Open all lines of a contract.
__construct($db)
Constructor.
doAutoRenewContracts($thirdparty_id=0, $delayindaysshort=0)
Action executed by scheduler CAN BE A CRON TASK Loop on each contract lines and update the end of dat...
getNomUrl($withpicto=0, $maxlength=0, $notooltip=0, $save_lastsearch_value=-1)
Return clickable name (with picto eventually)
info($id)
Charge les information d'ordre info dans l'objet contrat.
getLibStatut($mode)
Return label of a contract status.
static replaceProduct(DoliDB $db, $origin_id, $dest_id)
Function used to replace a product id with another one.
fetch_lines($only_services=0, $loadalsotranslation=0, $noextrafields=0)
Load lines array into this->lines.
getIdServiceContact()
Return id des contacts clients de prestation.
sendReminderForExpiredServices($daysbeforeendlist='10', $fk_product=0)
Send reminders by email before a running contract service expires.
Class to manage lines of contracts.
Class to manage Dolibarr database access.
const STATUS_DRAFT
Draft status.
Class to manage products or services.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
setSignedStatusCommon(User $user, int $status, int $notrigger=0, string $triggercode='')
Set signed status & call trigger with context message.
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0, $indexdatabase=1, $nolog=0, $level=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories)
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
$date_start
Variables from include:
dol_now($mode='gmt')
Return date for now.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
getLanguageCodeFromCountryCode($countrycode)
Return default language from country code.
setEntity($currentobject)
Set entity id to use when to create an object.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dolBuildUrl($url, $params=[], $addtoken=false, $anchor='')
Return path of url.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
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.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0)
Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
if(!function_exists( 'dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '...' if string larger than length.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
getMarginInfos($pv_ht, $remise_percent, $tva_tx, $localtax1_tx, $localtax2_tx, $fk_pa, $pa_ht)
Return an array with margins information of a line.
Class to generate the form for creating a new ticket.
calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $notused, $price_base_type, $info_bits, $type, $seller=null, $localtaxes_array=[], $progress=100, $multicurrency_tx=1, $pu_devise=0, $multicurrency_code='')
Calculate totals (net, vat, ...) of a line.