39require_once DOL_DOCUMENT_ROOT.
'/core/class/commonobject.class.php';
40require_once DOL_DOCUMENT_ROOT.
'/contrat/class/contratligne.class.php';
41require_once DOL_DOCUMENT_ROOT.
'/core/lib/price.lib.php';
42require_once DOL_DOCUMENT_ROOT.
'/margin/lib/margins.lib.php';
43require_once DOL_DOCUMENT_ROOT.
'/core/class/commonsignedobject.class.php';
53 use CommonSignedObject;
58 public $element =
'contrat';
63 public $table_element =
'contrat';
68 public $table_element_line =
'contratdet';
73 public $fk_element =
'fk_contrat';
78 public $picto =
'contract';
84 public $restrictiononfksoc = 1;
106 public $ref_supplier;
112 public $fk_contract_type = 0;
153 public $fk_user_author;
160 public $user_author_id;
167 public $user_creation;
172 public $user_cloture;
177 public $date_contrat;
182 public $commercial_signature_id;
188 public $fk_commercial_signature;
193 public $commercial_suivi_id;
200 public $fk_commercial_suivi;
205 public $extraparams = array();
210 public $lines = array();
215 public $nbofservices;
219 public $nbofserviceswait;
223 public $nbofservicesopened;
227 public $nbofservicesexpired;
231 public $nbofservicesclosed;
239 protected $lines_id_index_mapper = array();
270 public $fields = array(
271 'rowid' => array(
'type' =>
'integer',
'label' =>
'TechnicalID',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'position' => 10),
272 'ref' => array(
'type' =>
'varchar(50)',
'label' =>
'Ref',
'enabled' => 1,
'visible' => -1,
'showoncombobox' => 1,
'position' => 15,
'searchall' => 1),
273 'ref_ext' => array(
'type' =>
'varchar(255)',
'label' =>
'RefExt',
'enabled' => 1,
'visible' => 0,
'position' => 20),
274 'ref_customer' => array(
'type' =>
'varchar(50)',
'label' =>
'RefCustomer',
'enabled' => 1,
'visible' => -1,
'position' => 25,
'searchall' => 1),
275 'ref_supplier' => array(
'type' =>
'varchar(50)',
'label' =>
'RefSupplier',
'enabled' => 1,
'visible' => -1,
'position' => 26,
'searchall' => 1),
276 'fk_contract_type' => array(
'type' =>
'smallint(6)',
'label' =>
'ContractType',
'enabled' => 1,
'visible' => -1,
'position' => 27,
'default' =>
'0',
'arrayofkeyval' => array(0 =>
'CustomerContract', 1 =>
'SupplierContract')),
277 'entity' => array(
'type' =>
'integer',
'label' =>
'Entity',
'default' =>
'1',
'enabled' => 1,
'visible' => -2,
'notnull' => 1,
'position' => 30,
'index' => 1),
278 'tms' => array(
'type' =>
'timestamp',
'label' =>
'DateModification',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'position' => 35),
279 'datec' => array(
'type' =>
'datetime',
'label' =>
'DateCreation',
'enabled' => 1,
'visible' => -1,
'position' => 40),
280 'date_contrat' => array(
'type' =>
'datetime',
'label' =>
'Date contrat',
'enabled' => 1,
'visible' => -1,
'position' => 45),
281 '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')),
282 'fk_soc' => array(
'type' =>
'integer:Societe:societe/class/societe.class.php',
'label' =>
'ThirdParty',
'enabled' =>
'isModEnabled("societe")',
'visible' => -1,
'notnull' => 1,
'position' => 70),
283 'fk_projet' => array(
'type' =>
'integer:Project:projet/class/project.class.php:1:(fk_statut:=:1)',
'label' =>
'Project',
'enabled' =>
"isModEnabled('project')",
'visible' => -1,
'position' => 75),
284 'fk_commercial_signature' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'SaleRepresentative Signature',
'enabled' => 1,
'visible' => -1,
'position' => 80),
285 'fk_commercial_suivi' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'SaleRepresentative follower',
'enabled' => 1,
'visible' => -1,
'position' => 85),
286 'fk_user_author' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserAuthor',
'enabled' => 1,
'visible' => -1,
'notnull' => 1,
'position' => 90),
287 'note_public' => array(
'type' =>
'html',
'label' =>
'NotePublic',
'enabled' => 1,
'visible' => 0,
'position' => 105,
'searchall' => 1),
288 'note_private' => array(
'type' =>
'html',
'label' =>
'NotePrivate',
'enabled' => 1,
'visible' => 0,
'position' => 110,
'searchall' => 1),
289 'model_pdf' => array(
'type' =>
'varchar(255)',
'label' =>
'Model pdf',
'enabled' => 1,
'visible' => 0,
'position' => 115),
290 'import_key' => array(
'type' =>
'varchar(14)',
'label' =>
'ImportId',
'enabled' => 1,
'visible' => -2,
'position' => 120),
291 'extraparams' => array(
'type' =>
'varchar(255)',
'label' =>
'Extraparams',
'enabled' => 1,
'visible' => -1,
'position' => 125),
292 'fk_user_modif' => array(
'type' =>
'integer:User:user/class/user.class.php',
'label' =>
'UserModif',
'enabled' => 1,
'visible' => -2,
'notnull' => -1,
'position' => 135),
293 'last_main_doc' => array(
'type' =>
'varchar(255)',
'label' =>
'Last main doc',
'enabled' => 1,
'visible' => -1,
'position' => 140),
294 'statut' => array(
'type' =>
'smallint(6)',
'label' =>
'Statut',
'enabled' => 1,
'visible' => -1,
'position' => 500,
'notnull' => 1,
'arrayofkeyval' => array(0 =>
'Draft', 1 =>
'Validated', 2 =>
'Closed'))
298 const STATUS_DRAFT = 0;
299 const STATUS_VALIDATED = 1;
300 const STATUS_CLOSED = 2;
311 $this->ismultientitymanaged = 1;
312 $this->isextrafieldmanaged = 1;
321 public function getNextNumRef($soc)
323 global $db, $langs,
$conf;
324 $langs->load(
"contracts");
333 $dirmodels = array_merge(array(
'/'), (array)
$conf->modules_parts[
'models']);
335 foreach ($dirmodels as $reldir) {
339 $mybool = ((bool) @include_once $dir.$file) || $mybool;
343 dol_print_error(
null,
"Failed to include file ".$file);
347 $obj =
new $classname();
348 '@phan-var-force ModelNumRefContracts $obj';
350 $numref = $obj->getNextValue($soc, $this);
355 $this->error = $obj->error;
356 dol_print_error($db, get_class($this).
"::getNextValue ".$obj->error);
360 $langs->load(
"errors");
361 print $langs->trans(
"Error").
" ".$langs->trans(
"ErrorModuleSetupNotComplete", $langs->transnoentitiesnoconv(
"Contract"));
380 $result = $this->lines[$this->lines_id_index_mapper[$line_id]]->active_line($user,
$date_start, $date_end, $comment);
382 $this->error = $this->lines[$this->lines_id_index_mapper[$line_id]]->error;
383 $this->errors = $this->lines[$this->lines_id_index_mapper[$line_id]]->errors;
399 public function close_line($user, $line_id, $date_end, $comment =
'')
402 $result = $this->lines[$this->lines_id_index_mapper[$line_id]]->close_line($user, $date_end, $comment);
404 $this->error = $this->lines[$this->lines_id_index_mapper[$line_id]]->error;
405 $this->errors = $this->lines[$this->lines_id_index_mapper[$line_id]]->errors;
435 foreach ($this->lines as $contratline) {
437 if ($contratline->status != ContratLigne::STATUS_OPEN) {
438 $contratline->context = $this->context;
440 $result = $contratline->active_line($user,
$date_start, !empty($date_end) ? $date_end : -1, $comment);
449 if (!$error && $this->
status == 0) {
450 $result = $this->
validate($user,
'', $notrigger);
460 $this->db->rollback();
475 public function closeAll(
User $user, $notrigger = 0, $comment =
'', $nofetchlines = 0)
482 if (empty($nofetchlines)) {
490 foreach ($this->lines as $contratline) {
492 if ($contratline->status != ContratLigne::STATUS_CLOSED) {
493 $contratline->date_end_real = $now;
494 $contratline->date_cloture = $now;
495 $contratline->user_closing_id = $user->id;
496 $contratline->status = ContratLigne::STATUS_CLOSED;
498 $result = $contratline->close_line($user, $now, $comment, $notrigger);
502 $this->error = $contratline->error.($contratline->error ?
' ('.$this->ref.
')' :
'');
503 $this->errors = $contratline->errors;
509 if (!$error && $this->
status == 0) {
510 $result = $this->
validate($user,
'', $notrigger);
523 $this->db->rollback();
539 public function validate(
User $user, $force_number =
'', $notrigger = 0)
541 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
547 dol_syslog(get_class($this).
'::validate user='.$user->id.
', force_number='.$force_number);
555 if (!
getDolGlobalString(
'CONTRACT_DISABLE_AUTOSET_AS_CLIENT_ON_CONTRACT_VALIDATION') && $this->thirdparty->fournisseur == 0) {
556 $result = $this->thirdparty->setAsCustomer();
561 $num = $force_number;
562 } elseif (preg_match(
'/^[\(]?PROV/i', $this->
ref) || empty($this->
ref)) {
563 $num = $this->getNextNumRef($this->thirdparty);
565 $num = (string) $this->
ref;
570 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"contrat SET ref = '".$this->db->escape($num).
"', statut = 1";
571 $sql .=
" WHERE rowid = ".((int) $this->
id).
" AND statut = 0";
573 dol_syslog(get_class($this).
"::validate", LOG_DEBUG);
574 $resql = $this->db->query($sql);
576 dol_print_error($this->db);
578 $this->error = $this->db->lasterror();
582 if (!$error && !$notrigger) {
584 $result = $this->call_trigger(
'CONTRACT_VALIDATE', $user);
592 $this->oldref = $this->ref;
595 if (preg_match(
'/^[\(]?PROV/i', $this->
ref)) {
597 $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).
"'";
598 $sql .=
" WHERE filename LIKE '".$this->db->escape($this->
ref).
"%' AND filepath = 'contract/".$this->db->escape($this->
ref).
"' and entity = ".((int)
$conf->entity);
599 $resql = $this->db->query($sql);
602 $this->error = $this->db->lasterror();
604 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"ecm_files SET filepath = 'contract/".$this->db->escape($this->newref).
"'";
605 $sql .=
" WHERE filepath = 'contract/".$this->db->escape($this->
ref).
"' and entity = ".((int)
$conf->entity);
606 $resql = $this->db->query($sql);
609 $this->error = $this->db->lasterror();
615 $dirsource =
$conf->contract->dir_output.
'/'.$oldref;
616 $dirdest =
$conf->contract->dir_output.
'/'.$newref;
617 if (!$error && file_exists($dirsource)) {
618 dol_syslog(get_class($this).
"::validate rename dir ".$dirsource.
" into ".$dirdest);
620 if (@rename($dirsource, $dirdest)) {
623 $listoffiles =
dol_dir_list(
$conf->contract->dir_output.
'/'.$newref,
'files', 1,
'^'.preg_quote($oldref,
'/'));
624 foreach ($listoffiles as $fileentry) {
625 $dirsource = $fileentry[
'name'];
626 $dirdest = preg_replace(
'/^'.preg_quote($oldref,
'/').
'/', $newref, $dirsource);
627 $dirsource = $fileentry[
'path'].
'/'.$dirsource;
628 $dirdest = $fileentry[
'path'].
'/'.$dirdest;
629 @rename($dirsource, $dirdest);
639 $this->
status = self::STATUS_VALIDATED;
640 $this->statut = self::STATUS_VALIDATED;
641 $this->date_validation = $now;
651 $this->db->rollback();
663 public function reopen($user, $notrigger = 0)
665 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
670 dol_syslog(get_class($this).
'::reopen user='.$user->id);
676 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"contrat SET statut = 0";
678 $sql .=
" WHERE rowid = ".((int) $this->
id).
" AND statut = 1";
680 dol_syslog(get_class($this).
"::validate", LOG_DEBUG);
681 $resql = $this->db->query($sql);
683 dol_print_error($this->db);
685 $this->error = $this->db->lasterror();
689 if (!$error && !$notrigger) {
691 $result = $this->call_trigger(
'CONTRACT_REOPEN', $user);
700 $this->statut = self::STATUS_DRAFT;
701 $this->
status = self::STATUS_DRAFT;
702 $this->date_validation = $now;
709 $this->db->rollback();
725 public function fetch($id, $ref =
'', $ref_customer =
'', $ref_supplier =
'', $noextrafields = 0, $nolines = 0)
729 $sql =
"SELECT rowid, statut as status, ref, fk_soc as thirdpartyid,";
730 $sql .=
" ref_supplier, ref_customer,";
733 $sql .=
" signed_status,";
734 $sql .=
" date_contrat as datecontrat,";
735 $sql .=
" fk_user_author,";
736 $sql .=
" fk_projet as fk_project,";
737 $sql .=
" fk_commercial_signature, fk_commercial_suivi,";
738 $sql .=
" note_private, note_public, model_pdf, last_main_doc, extraparams, fk_contract_type";
739 $sql .=
" FROM ".MAIN_DB_PREFIX.
"contrat";
741 $sql .=
" WHERE entity IN (".getEntity(
'contract').
")";
743 $sql .=
" WHERE rowid = ".(int) $id;
746 $sql .=
" AND ref_customer = '".$this->db->escape($ref_customer).
"'";
749 $sql .=
" AND ref_supplier = '".$this->db->escape($ref_supplier).
"'";
752 $sql .=
" AND ref = '".$this->db->escape($ref).
"'";
755 dol_syslog(get_class($this).
"::fetch", LOG_DEBUG);
757 $resql = $this->db->query($sql);
759 $num = $this->db->num_rows($resql);
761 $this->error =
'Fetch found several records.';
766 $obj = $this->db->fetch_object($resql);
768 $this->
id = $obj->rowid;
769 $this->
ref = (!isset($obj->ref) || !$obj->ref) ? $obj->rowid : $obj->ref;
770 $this->ref_customer = $obj->ref_customer;
771 $this->ref_supplier = $obj->ref_supplier;
772 $this->ref_ext = $obj->ref_ext;
773 $this->entity = $obj->entity;
774 $this->statut = $obj->status;
775 $this->
status = $obj->status;
776 $this->signed_status = $obj->signed_status;
778 $this->date_contrat = $this->db->jdate($obj->datecontrat);
779 $this->date_creation = $this->db->jdate($obj->datecontrat);
781 $this->user_author_id = $obj->fk_user_author;
783 $this->commercial_signature_id = $obj->fk_commercial_signature;
784 $this->commercial_suivi_id = $obj->fk_commercial_suivi;
786 $this->note_private = $obj->note_private;
787 $this->note_public = $obj->note_public;
788 $this->model_pdf = $obj->model_pdf;
790 $this->fk_projet = $obj->fk_project;
791 $this->fk_project = $obj->fk_project;
793 $this->socid = $obj->thirdpartyid;
794 $this->fk_soc = $obj->thirdpartyid;
795 $this->last_main_doc = $obj->last_main_doc;
796 $this->extraparams = (isset($obj->extraparams) ? (array) json_decode($obj->extraparams,
true) :
null);
797 $this->fk_contract_type = (int) $obj->fk_contract_type;
799 $this->db->free($resql);
803 if (empty($noextrafields)) {
806 $this->error = $this->db->lasterror();
812 if (empty($nolines)) {
813 if ($result >= 0 && !empty($this->table_element_line)) {
816 $this->error = $this->db->lasterror();
824 dol_syslog(get_class($this).
"::fetch Contract failed");
825 $this->error =
"Fetch contract failed";
829 dol_syslog(get_class($this).
"::fetch Contract not found");
830 $this->error =
"Contract not found";
834 dol_syslog(get_class($this).
"::fetch Error searching contract");
835 $this->error = $this->db->error();
850 public function fetch_lines($only_services = 0, $loadalsotranslation = 0, $noextrafields = 0)
853 $this->nbofservices = 0;
854 $this->nbofserviceswait = 0;
855 $this->nbofservicesopened = 0;
856 $this->nbofservicesexpired = 0;
857 $this->nbofservicesclosed = 0;
865 $this->lines = array();
869 $sql =
"SELECT p.label as product_label, p.description as product_desc, p.ref as product_ref, p.fk_product_type as product_type,";
870 $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,";
871 $sql .=
" d.total_ht,";
872 $sql .=
" d.total_tva,";
873 $sql .=
" d.total_localtax1,";
874 $sql .=
" d.total_localtax2,";
875 $sql .=
" d.total_ttc,";
876 $sql .=
" d.info_bits, d.fk_product,";
877 $sql .=
" d.date_ouverture_prevue as date_start,";
878 $sql .=
" d.date_ouverture as date_start_real,";
879 $sql .=
" d.date_fin_validite as date_end,";
880 $sql .=
" d.date_cloture as date_end_real,";
881 $sql .=
" d.fk_user_author,";
882 $sql .=
" d.fk_user_ouverture,";
883 $sql .=
" d.fk_user_cloture,";
884 $sql .=
" d.fk_unit,";
885 $sql .=
" d.extraparams,";
886 $sql .=
" d.product_type as type,";
888 $sql .=
" FROM ".MAIN_DB_PREFIX.
"contratdet as d LEFT JOIN ".MAIN_DB_PREFIX.
"product as p ON d.fk_product = p.rowid";
889 $sql .=
" WHERE d.fk_contrat = ".((int) $this->
id);
890 if ($only_services == 1) {
891 $sql .=
" AND d.product_type = 1";
893 $sql .=
" ORDER by d.rang ASC";
895 dol_syslog(get_class($this).
"::fetch_lines", LOG_DEBUG);
896 $result = $this->db->query($sql);
898 $num = $this->db->num_rows($result);
902 $objp = $this->db->fetch_object($result);
906 $line->id = $objp->rowid;
907 $line->ref = $objp->rowid;
908 $line->fk_contrat = $objp->fk_contrat;
909 $line->desc = $objp->description;
910 $line->qty = $objp->qty;
911 $line->vat_src_code = $objp->vat_src_code;
912 $line->tva_tx = $objp->tva_tx;
913 $line->localtax1_tx = $objp->localtax1_tx;
914 $line->localtax2_tx = $objp->localtax2_tx;
915 $line->localtax1_type = $objp->localtax1_type;
916 $line->localtax2_type = $objp->localtax2_type;
917 $line->subprice = $objp->subprice;
918 $line->subprice_ttc = $objp->subprice_ttc;
919 $line->statut = $objp->status;
920 $line->status = $objp->status;
921 $line->remise_percent = $objp->remise_percent;
922 $line->total_ht = $objp->total_ht;
923 $line->total_tva = $objp->total_tva;
924 $line->total_localtax1 = $objp->total_localtax1;
925 $line->total_localtax2 = $objp->total_localtax2;
926 $line->total_ttc = $objp->total_ttc;
927 $line->fk_product = (($objp->fk_product > 0) ? $objp->fk_product : 0);
928 $line->info_bits = $objp->info_bits;
929 $line->type = $objp->type;
931 $line->fk_fournprice = $objp->fk_fournprice;
932 $marginInfos =
getMarginInfos($objp->subprice, $objp->remise_percent, $objp->tva_tx, $objp->localtax1_tx, $objp->localtax2_tx, $objp->fk_fournprice, $objp->pa_ht);
933 $line->pa_ht = $marginInfos[0];
935 $line->fk_user_author = $objp->fk_user_author;
936 $line->fk_user_ouverture = $objp->fk_user_ouverture;
937 $line->fk_user_cloture = $objp->fk_user_cloture;
938 $line->fk_unit = $objp->fk_unit;
940 $line->extraparams = !empty($objp->extraparams) ? (array) json_decode($objp->extraparams,
true) : array();
942 $line->ref = $objp->product_ref;
943 $line->product_ref = $objp->product_ref;
944 $line->product_type = $objp->product_type;
945 $line->product_desc = $objp->product_desc;
946 $line->product_label = $objp->product_label;
948 $line->description = $objp->description;
950 $line->date_start = $this->db->jdate($objp->date_start);
951 $line->date_start_real = $this->db->jdate($objp->date_start_real);
952 $line->date_end = $this->db->jdate($objp->date_end);
953 $line->date_end_real = $this->db->jdate($objp->date_end_real);
964 $line->rang = $objp->rang;
968 if (empty($noextrafields)) {
969 $line->fetch_optionals();
973 if (
getDolGlobalInt(
'MAIN_MULTILANGS') && !empty($objp->fk_product) && !empty($loadalsotranslation)) {
974 $tmpproduct =
new Product($this->db);
975 $tmpproduct->fetch($objp->fk_product);
976 $tmpproduct->getMultiLangs();
978 $line->multilangs = $tmpproduct->multilangs;
981 $this->lines[$pos] = $line;
983 $this->lines_id_index_mapper[$line->id] = $pos;
988 if ($line->statut == ContratLigne::STATUS_INITIAL) {
989 $this->nbofserviceswait++;
991 if ($line->statut == ContratLigne::STATUS_OPEN && (empty($line->date_end) || $line->date_end >= $now)) {
992 $this->nbofservicesopened++;
994 if ($line->statut == ContratLigne::STATUS_OPEN && (!empty($line->date_end) && $line->date_end < $now)) {
995 $this->nbofservicesexpired++;
997 if ($line->statut == ContratLigne::STATUS_CLOSED) {
998 $this->nbofservicesclosed++;
1002 $total_ttc += $objp->total_ttc;
1003 $total_vat += $objp->total_tva;
1004 $total_ht += $objp->total_ht;
1009 $this->db->free($result);
1011 dol_syslog(get_class($this).
"::Fetch Error when reading lines of contracts linked to products");
1016 $this->nbofservices = count($this->lines);
1017 $this->total_ttc = (float)
price2num($total_ttc);
1018 $this->total_tva = (float)
price2num($total_vat);
1019 $this->total_ht = (float)
price2num($total_ht);
1021 return $this->lines;
1031 public function create($user, $notrigger = 0)
1033 global
$conf, $langs;
1037 if ($this->commercial_signature_id <= 0) {
1038 $langs->load(
"commercial");
1039 $this->error .= $langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv(
"SalesRepresentativeSignature"));
1042 if ($this->commercial_suivi_id <= 0) {
1043 $langs->load(
"commercial");
1044 $this->error .= ($this->error ?
"<br>" :
'');
1045 $this->error .= $langs->trans(
"ErrorFieldRequired", $langs->transnoentitiesnoconv(
"SalesRepresentativeFollowUp"));
1059 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"contrat (datec, fk_soc, fk_user_author, date_contrat,";
1060 $sql .=
" fk_commercial_signature, fk_commercial_suivi, fk_projet,";
1061 $sql .=
" ref, entity, signed_status, note_private, note_public, ref_customer, ref_supplier, ref_ext, fk_contract_type)";
1062 $sql .=
" VALUES ('".$this->db->idate($now).
"', ".((int) $this->socid).
", ".((int) $user->id);
1063 $sql .=
", ".(dol_strlen($this->date_contrat) != 0 ?
"'".$this->db->idate($this->date_contrat).
"'" :
"NULL");
1064 $sql .=
",".($this->commercial_signature_id > 0 ? ((int) $this->commercial_signature_id) :
"NULL");
1065 $sql .=
",".($this->commercial_suivi_id > 0 ? ((int) $this->commercial_suivi_id) :
"NULL");
1066 $sql .=
",".($this->fk_project > 0 ? ((int) $this->fk_project) :
"NULL");
1067 $sql .=
", ".(dol_strlen($this->
ref) <= 0 ?
"null" :
"'".$this->db->escape($this->
ref).
"'");
1068 $sql .=
", ".((int) $this->entity);
1069 $sql .=
", ".((int) $this->signed_status);
1070 $sql .=
", ".(!empty($this->note_private) ? (
"'".$this->db->escape($this->note_private).
"'") :
"NULL");
1071 $sql .=
", ".(!empty($this->note_public) ? (
"'".$this->db->escape($this->note_public).
"'") :
"NULL");
1072 $sql .=
", ".(!empty($this->ref_customer) ? (
"'".$this->db->escape($this->ref_customer).
"'") :
"NULL");
1073 $sql .=
", ".(!empty($this->ref_supplier) ? (
"'".$this->db->escape($this->ref_supplier).
"'") :
"NULL");
1074 $sql .=
", ".(!empty($this->ref_ext) ? (
"'".$this->db->escape($this->ref_ext).
"'") :
"NULL");
1075 $sql .=
", ".((int) $this->fk_contract_type);
1077 $resql = $this->db->query($sql);
1082 $this->
id = $this->db->last_insert_id(MAIN_DB_PREFIX.
"contrat");
1086 if (substr($module, 0, 13) ==
'mod_contract_' && substr($module, -3) ==
'php') {
1087 $module = substr($module, 0,
dol_strlen($module) - 4);
1091 $modCodeContract =
new $module();
1092 '@phan-var-force ModelNumRefContracts $modCodeContract';
1095 if (!empty($modCodeContract->code_auto)) {
1097 $sql =
'UPDATE '.MAIN_DB_PREFIX.
"contrat SET ref='(PROV".((int) $this->
id).
")' WHERE rowid=".((int) $this->
id);
1098 if ($this->db->query($sql)) {
1100 $this->
ref =
"(PROV".$this->id.
")";
1112 if (!$error && !empty($this->commercial_signature_id)) {
1113 $result = $this->
add_contact($this->commercial_signature_id,
'SALESREPSIGN',
'internal');
1120 if (!$error && !empty($this->commercial_suivi_id)) {
1121 $result = $this->
add_contact($this->commercial_suivi_id,
'SALESREPFOLL',
'internal');
1128 if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) {
1129 $this->linked_objects = $this->linkedObjectsIds;
1133 if ($this->
id && !empty($this->linked_objects) && is_array($this->linked_objects)) {
1134 foreach ($this->linked_objects as $origin => $tmp_origin_id) {
1135 if (is_array($tmp_origin_id)) {
1136 foreach ($tmp_origin_id as $origin_id) {
1139 $this->error = $this->db->lasterror();
1144 $origin_id = $tmp_origin_id;
1147 $this->error = $this->db->lasterror();
1154 if (!$error && $this->
id &&
getDolGlobalString(
'MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN') && !empty($this->origin) && !empty($this->origin_id)) {
1155 $originforcontact = $this->origin;
1156 $originidforcontact = $this->origin_id;
1157 if ($originforcontact ==
'shipping') {
1158 require_once DOL_DOCUMENT_ROOT.
'/expedition/class/expedition.class.php';
1160 $exp->fetch($this->origin_id);
1161 $exp->fetchObjectLinked();
1162 if (count($exp->linkedObjectsIds[
'commande']) > 0) {
1163 foreach ($exp->linkedObjectsIds[
'commande'] as $key => $value) {
1164 $originforcontact =
'commande';
1165 $originidforcontact = $value;
1171 $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";
1172 $sqlcontact .=
" WHERE element_id = ".((int) $originidforcontact).
" AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$this->db->escape($originforcontact).
"'";
1174 $resqlcontact = $this->db->query($sqlcontact);
1175 if ($resqlcontact) {
1176 while ($objcontact = $this->db->fetch_object($resqlcontact)) {
1177 if ($objcontact->source ==
'internal' && in_array($objcontact->code, array(
'SALESREPSIGN',
'SALESREPFOLL'))) {
1181 $this->
add_contact($objcontact->fk_socpeople, $objcontact->code, $objcontact->source);
1184 dol_print_error($this->db);
1189 if (!$error && !$notrigger) {
1191 $result = $this->call_trigger(
'CONTRACT_CREATE', $user);
1199 $this->db->commit();
1204 if (empty($this->error) && empty($this->errors)) {
1205 $this->error =
"Failed to add contract";
1207 dol_syslog(get_class($this).
"::create - 20 - ".$this->error, LOG_ERR);
1208 $this->db->rollback();
1212 $this->error = $langs->trans(
"UnknownError").
": ".$this->db->error();
1213 dol_syslog(get_class($this).
"::create - 10 - ".$this->error, LOG_ERR);
1215 $this->db->rollback();
1227 public function delete($user)
1231 require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
1238 $result = $this->call_trigger(
'CONTRACT_DELETE', $user);
1248 dol_syslog(get_class($this).
"::delete error", LOG_ERR);
1264 $sql_main_table = MAIN_DB_PREFIX.
'contratdet';
1265 $ef = $sql_main_table.
"_extrafields";
1266 $sql =
"DELETE FROM ".$this->db->sanitize($ef).
" WHERE fk_object IN (SELECT rowid FROM ".$sql_main_table.
" WHERE fk_contrat = ".((int) $this->
id).
")";
1268 dol_syslog(get_class($this).
"::delete contratdet_extrafields", LOG_DEBUG);
1269 $resql = $this->db->query($sql);
1271 $this->error = $this->db->error();
1278 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"contratdet";
1279 $sql .=
" WHERE fk_contrat = ".((int) $this->
id);
1281 dol_syslog(get_class($this).
"::delete contratdet", LOG_DEBUG);
1282 $resql = $this->db->query($sql);
1284 $this->error = $this->db->error();
1302 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.
"contrat";
1303 $sql .=
" WHERE rowid=".((int) $this->
id);
1305 dol_syslog(get_class($this).
"::delete contrat", LOG_DEBUG);
1306 $resql = $this->db->query($sql);
1308 $this->error = $this->db->error();
1318 dol_syslog(get_class($this).
"::delete error -3 ".$this->error, LOG_ERR);
1325 if ($conf->contrat->dir_output && !empty($ref)) {
1326 $dir =
$conf->contrat->multidir_output[$this->entity].
"/".$ref;
1327 if (file_exists($dir)) {
1330 $this->error =
'ErrorFailToDeleteDir';
1338 $this->db->commit();
1341 $this->error = $this->db->lasterror();
1342 $this->db->rollback();
1354 public function update($user, $notrigger = 0)
1360 if (empty($this->fk_commercial_signature) && $this->commercial_signature_id > 0) {
1361 $this->fk_commercial_signature = $this->commercial_signature_id;
1363 if (empty($this->fk_commercial_suivi) && $this->commercial_suivi_id > 0) {
1364 $this->fk_commercial_suivi = $this->commercial_suivi_id;
1366 if (empty($this->socid) && $this->fk_soc > 0) {
1367 $this->socid = (int) $this->fk_soc;
1370 if (isset($this->
ref)) {
1371 $this->
ref = trim($this->
ref);
1373 if (isset($this->ref_customer)) {
1374 $this->ref_customer = trim($this->ref_customer);
1376 if (isset($this->ref_supplier)) {
1377 $this->ref_supplier = trim($this->ref_supplier);
1379 if (isset($this->ref_ext)) {
1380 $this->ref_ext = trim($this->ref_ext);
1382 if (isset($this->entity)) {
1383 $this->entity = (int) $this->entity;
1385 if (isset($this->
status)) {
1388 if ((
int) $this->socid > 0) {
1389 $this->socid = (int) $this->socid;
1391 if (isset($this->fk_commercial_signature)) {
1392 $this->fk_commercial_signature = (int) $this->fk_commercial_signature;
1394 if (isset($this->fk_commercial_suivi)) {
1395 $this->fk_commercial_suivi = (int) $this->fk_commercial_suivi;
1397 if (isset($this->note_private)) {
1398 $this->note_private = trim($this->note_private);
1400 if (isset($this->note_public)) {
1401 $this->note_public = trim($this->note_public);
1403 if (isset($this->import_key)) {
1404 $this->import_key = trim($this->import_key);
1407 $extraparams = (!empty($this->extraparams) ? json_encode($this->extraparams) :
null);
1408 $extraparams =
dol_trunc($extraparams, 250);
1413 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"contrat SET";
1414 $sql .=
" ref=".(isset($this->
ref) ?
"'".$this->db->escape($this->
ref).
"'" :
"null").
",";
1415 $sql .=
" ref_customer=".(isset($this->ref_customer) ?
"'".$this->db->escape($this->ref_customer).
"'" :
"null").
",";
1416 $sql .=
" ref_supplier=".(isset($this->ref_supplier) ?
"'".$this->db->escape($this->ref_supplier).
"'" :
"null").
",";
1417 $sql .=
" ref_ext=".(isset($this->ref_ext) ?
"'".$this->db->escape($this->ref_ext).
"'" :
"null").
",";
1418 $sql .=
" entity=".((int)
$conf->entity).
",";
1419 $sql .=
" date_contrat=".(dol_strlen($this->date_contrat) != 0 ?
"'".$this->db->idate($this->date_contrat).
"'" :
'null').
",";
1420 $sql .=
" statut=".(isset($this->statut) ? ((int) $this->statut) : (isset($this->
status) ? ((int) $this->
status) :
"null")).
",";
1421 $sql .=
" fk_soc=".($this->socid > 0 ? ((int) $this->socid) :
"null").
",";
1422 $sql .=
" fk_projet=".($this->fk_project > 0 ? ((int) $this->fk_project) :
"null").
",";
1423 $sql .=
" fk_commercial_signature=".(isset($this->fk_commercial_signature) ? ((int) $this->fk_commercial_signature) :
"null").
",";
1424 $sql .=
" fk_commercial_suivi=".(isset($this->fk_commercial_suivi) ? ((int) $this->fk_commercial_suivi) :
"null").
",";
1425 $sql .=
" note_private=".(isset($this->note_private) ?
"'".$this->db->escape($this->note_private).
"'" :
"null").
",";
1426 $sql .=
" note_public=".(isset($this->note_public) ?
"'".$this->db->escape($this->note_public).
"'" :
"null").
",";
1427 $sql .=
" import_key=".(isset($this->import_key) ?
"'".$this->db->escape($this->import_key).
"'" :
"null").
",";
1428 $sql .=
" fk_user_modif=".(isset($user->id) ? ((int) $user->id) :
"null").
",";
1429 $sql .=
" extraparams=".(isset($extraparams) ?
"'".$this->db->escape($extraparams).
"'" :
"null");
1430 $sql .=
" WHERE rowid=".((int) $this->
id);
1434 $resql = $this->db->query($sql);
1437 $this->errors[] =
"Error ".$this->db->lasterror();
1447 if (!$error && !$notrigger) {
1449 $result = $this->call_trigger(
'CONTRACT_MODIFY', $user);
1458 foreach ($this->errors as $errmsg) {
1459 dol_syslog(get_class($this).
"::update ".$errmsg, LOG_ERR);
1460 $this->error .= ($this->error ?
', '.$errmsg : $errmsg);
1462 $this->db->rollback();
1465 if (isset($user->id)) {
1466 $this->fk_user_modif = (int) $user->id;
1468 $this->db->commit();
1497 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)
1499 global $user, $langs,
$mysoc;
1502 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");
1505 if ($fk_product <= 0 && empty($desc)) {
1506 $this->error =
"ErrorDescRequiredForFreeProductLines";
1510 if ($this->
status >= 0) {
1519 if (preg_match(
'/\((.*)\)/', (
string) $txtva, $reg)) {
1520 $vat_src_code = $reg[1];
1521 $txtva = preg_replace(
'/\s*\(.*\)/',
'', (
string) $txtva);
1527 $remise_percent =
price2num($remise_percent);
1532 if (empty($info_bits)) {
1535 if (empty($pu_ht) || !is_numeric($pu_ht)) {
1538 if (empty($pu_ttc)) {
1541 if (empty($txtva) || !is_numeric($txtva)) {
1544 if (empty($txlocaltax1) || !is_numeric($txlocaltax1)) {
1547 if (empty($txlocaltax2) || !is_numeric($txlocaltax2)) {
1551 if ($price_base_type ==
'HT') {
1558 if (empty($remise_percent)) {
1559 $remise_percent = 0;
1566 $langs->load(
"errors");
1567 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
1579 $tabprice =
calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, 1,
$mysoc, $localtaxes_type);
1580 $total_ht = $tabprice[0];
1581 $total_tva = $tabprice[1];
1582 $total_ttc = $tabprice[2];
1583 $total_localtax1 = $tabprice[9];
1584 $total_localtax2 = $tabprice[10];
1585 $pu_ht = $tabprice[3];
1586 $pu_ttc = $tabprice[5];
1588 if (count($localtaxes_type) > 0) {
1589 $localtax1_type = $localtaxes_type[0];
1590 $localtax2_type = $localtaxes_type[2];
1592 $localtax1_type =
"";
1593 $localtax2_type =
"";
1596 if (empty($pa_ht)) {
1603 $result = $this->
defineBuyPrice((
float) $pu_ht, $remise_percent, $fk_product, $qty);
1612 $sql =
"INSERT INTO ".MAIN_DB_PREFIX.
"contratdet";
1613 $sql .=
" (fk_contrat, label, description, fk_product, qty, tva_tx, vat_src_code,";
1614 $sql .=
" localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, remise_percent, subprice, subprice_ttc,";
1615 $sql .=
" total_ht, total_tva, total_localtax1, total_localtax2, total_ttc,";
1616 $sql .=
" info_bits,";
1617 $sql .=
" fk_product_fournisseur_price, buy_price_ht";
1619 $sql .=
",date_ouverture_prevue";
1621 if ($date_end > 0) {
1622 $sql .=
",date_fin_validite";
1624 $sql .=
", fk_unit";
1626 $sql .=
") VALUES (";
1627 $sql .= ((int) $this->
id).
", '', '".$this->db->escape($desc).
"',";
1628 $sql .= ($fk_product > 0 ? ((int) $fk_product) :
"null").
",";
1629 $sql .=
" ".((float) $qty).
",";
1630 $sql .=
" ".((float) $txtva).
",";
1631 $sql .=
" ".($vat_src_code ?
"'".$this->db->escape($vat_src_code).
"'" :
"null").
",";
1632 $sql .=
" ".((float) $txlocaltax1).
",";
1633 $sql .=
" ".((float) $txlocaltax2).
",";
1634 $sql .=
" '".$this->db->escape($localtax1_type).
"',";
1635 $sql .=
" '".$this->db->escape($localtax2_type).
"',";
1636 $sql .=
" ".price2num($remise_percent).
",";
1637 $sql .=
" ".price2num($pu_ht).
",";
1638 $sql .=
" ".($price_base_type ===
'TTC' ? (float)
price2num($pu_ttc) : 0).
",";
1640 $sql .=
" ".((int) $info_bits).
",";
1641 if (isset($fk_fournprice)) {
1642 $sql .=
' '.((int) $fk_fournprice).
',';
1646 if (isset($pa_ht)) {
1647 $sql .=
' '.price2num($pa_ht);
1654 if ($date_end > 0) {
1655 $sql .=
",'".$this->db->idate($date_end).
"'";
1657 $sql .=
", ".($fk_unit ?
"'".$this->db->escape((
string) $fk_unit).
"'" :
"null");
1658 $sql .=
", ".(!empty($rang) ? (int) $rang :
"0");
1661 $resql = $this->db->query($sql);
1663 $contractlineid = $this->db->last_insert_id(MAIN_DB_PREFIX.
"contratdet");
1666 $contractline->array_options = $array_options;
1667 $contractline->id = $contractlineid;
1668 $result = $contractline->insertExtraFields();
1674 if (empty($error)) {
1676 $this->context[
'line_id'] = $contractlineid;
1677 $result = $this->call_trigger(
'LINECONTRACT_INSERT', $user);
1685 $this->db->rollback();
1688 $this->db->commit();
1689 return $contractlineid;
1692 $this->db->rollback();
1693 $this->error = $this->db->error().
" sql=".$sql;
1697 dol_syslog(get_class($this).
"::addline ErrorTryToAddLineOnValidatedContract", LOG_ERR);
1726 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)
1728 global $user, $langs,
$mysoc;
1731 $this->error =
'ErrorLineIDDoesNotMatchWithObjectID';
1738 $qty = trim((
string) $qty);
1739 $desc = trim($desc);
1745 if (empty($fk_fournprice)) {
1753 $langs->load(
"errors");
1754 $this->error = $langs->trans(
'ErrorStartDateGreaterEnd');
1758 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");
1767 $tvatx = preg_replace(
'/\s*\(.*\)/',
'', $tvatx);
1769 $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);
1770 $total_ht = $tabprice[0];
1771 $total_tva = $tabprice[1];
1772 $total_ttc = $tabprice[2];
1773 $total_localtax1 = $tabprice[9];
1774 $total_localtax2 = $tabprice[10];
1775 $pu_ht = $tabprice[3];
1776 $pu_ttc = $tabprice[5];
1778 $localtax1_type = (empty($localtaxes_type[0]) ?
'' : $localtaxes_type[0]);
1779 $localtax2_type = (empty($localtaxes_type[2]) ?
'' : $localtaxes_type[2]);
1781 if (empty($pa_ht)) {
1795 $sql =
"UPDATE ".MAIN_DB_PREFIX.
"contratdet SET description = '".$this->db->escape($desc).
"'";
1796 $sql .=
",subprice = ".((float)
price2num($pu_ht));
1798 $sql .=
",subprice_ttc = ".($price_base_type ===
'TTC' ? (float)
price2num($pu_ttc) : 0);
1799 $sql .=
",remise_percent = ".((float)
price2num($remise_percent));
1800 $sql .=
",qty = ".((float) $qty);
1801 $sql .=
",tva_tx = ".((float)
price2num($tvatx));
1802 $sql .=
",localtax1_tx = ".((float)
price2num($localtax1tx));
1803 $sql .=
",localtax2_tx = ".((float)
price2num($localtax2tx));
1804 $sql .=
",localtax1_type='".$this->db->escape($localtax1_type).
"'";
1805 $sql .=
",localtax2_type='".$this->db->escape($localtax2_type).
"'";
1806 $sql .=
", total_ht = ".((float)
price2num($total_ht));
1807 $sql .=
", total_tva = ".((float)
price2num($total_tva));
1808 $sql .=
", total_localtax1 = ".((float)
price2num($total_localtax1));
1809 $sql .=
", total_localtax2 = ".((float)
price2num($total_localtax2));
1810 $sql .=
", total_ttc = ".((float)
price2num($total_ttc));
1811 $sql .=
", fk_product_fournisseur_price=".($fk_fournprice > 0 ? ((int) $fk_fournprice) :
"null");
1812 $sql .=
", buy_price_ht = ".((float)
price2num($pa_ht));
1814 $sql .=
",date_ouverture_prevue = '".$this->db->idate(
$date_start).
"'";
1816 $sql .=
",date_ouverture_prevue = null";
1818 if ($date_end > 0) {
1819 $sql .=
",date_fin_validite = '".$this->db->idate($date_end).
"'";
1821 $sql .=
",date_fin_validite = null";
1823 if ($date_start_real > 0) {
1824 $sql .=
",date_ouverture = '".$this->db->idate($date_start_real).
"'";
1826 $sql .=
",date_ouverture = null";
1828 if ($date_end_real > 0) {
1829 $sql .=
",date_cloture = '".$this->db->idate($date_end_real).
"'";
1831 $sql .=
",date_cloture = null";
1833 $sql .=
", fk_unit = ".($fk_unit > 0 ? ((int) $fk_unit) :
"null");
1834 $sql .=
", rang = ".(!empty($rang) ? ((int) $rang) :
"0");
1835 $sql .=
" WHERE rowid = ".((int) $rowid);
1837 dol_syslog(get_class($this).
"::updateline", LOG_DEBUG);
1838 $result = $this->db->query($sql);
1840 if (is_array($array_options) && count($array_options) > 0) {
1842 $contractline->fetch($rowid);
1845 foreach ($array_options as $key => $value) {
1846 $contractline->array_options[$key] = $array_options[$key];
1849 $result = $contractline->insertExtraFields();
1851 $this->errors[] = $contractline->error;
1857 $sqltoupdatecontract =
"UPDATE ".MAIN_DB_PREFIX.
"contrat";
1858 $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.
")";
1859 $sqltoupdatecontract .=
" WHERE rowid = ".((int) $this->
id);
1860 $resqltoupdatecontract = $this->db->query($sqltoupdatecontract);
1861 if (!$resqltoupdatecontract) {
1862 $this->error = $this->db->lasterror();
1863 $this->db->rollback();
1867 if (empty($error)) {
1869 $this->context[
'line_id'] = $rowid;
1870 $result = $this->call_trigger(
'LINECONTRACT_MODIFY', $user);
1872 $this->db->rollback();
1877 $this->db->commit();
1880 $this->db->rollback();
1884 $this->db->rollback();
1885 $this->error = $this->db->error();
1886 dol_syslog(get_class($this).
"::updateline Erreur -1");
1902 if ($this->statut >= 0) {
1903 if ($this->
id > 0) {
1906 if ($contractline->fetch($idline) <= 0 || (
int) $contractline->fk_contrat !== (
int) $this->id) {
1907 $this->error =
'ErrorLineIDDoesNotMatchWithObjectID';
1913 $this->context[
'line_id'] = $idline;
1914 $result = $this->call_trigger(
'LINECONTRACT_DELETE', $user);
1922 $sql =
"DELETE FROM ".MAIN_DB_PREFIX.$this->table_element_line;
1923 $sql .=
" WHERE rowid = ".((int) $idline);
1925 dol_syslog(get_class($this).
"::deleteline", LOG_DEBUG);
1926 $resql = $this->db->query($sql);
1928 $this->error =
"Error ".$this->db->lasterror();
1935 $contractline->id = $idline;
1936 $result = $contractline->deleteExtraFields();
1939 $this->error =
"Error ".get_class($this).
"::deleteline deleteExtraFields error -4 ".$contractline->error;
1948 $result = $this->
line_order(
true,
'ASC',
false);
1951 $this->error =
"Error ".get_class($this).
"::deleteline line_order error";
1955 if (empty($error)) {
1956 $this->db->commit();
1959 dol_syslog(get_class($this).
"::deleteline ERROR:".$this->error, LOG_ERR);
1960 $this->db->rollback();
1964 $this->error =
'ErrorDeleteLineNotAllowedByObjectStatus';
1981 dol_syslog(__METHOD__.
" is deprecated", LOG_WARNING);
1984 if ($this->statut == 0) {
2009 return $this->
LibStatut($this->statut, $mode);
2025 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
2027 $langs->load(
"contracts");
2028 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv(
'ContractStatusDraft');
2029 $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv(
'ContractStatusValidated');
2030 $this->labelStatus[self::STATUS_CLOSED] = $langs->transnoentitiesnoconv(
'ContractStatusClosed');
2031 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv(
'ContractStatusDraft');
2032 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv(
'ContractStatusValidated');
2033 $this->labelStatusShort[self::STATUS_CLOSED] = $langs->transnoentitiesnoconv(
'ContractStatusClosed');
2036 $statusType =
'status'.$status;
2037 if ($status == self::STATUS_VALIDATED) {
2038 $statusType =
'status6';
2041 if ($mode == 4 || $mode == 6 || $mode == 7) {
2044 $text =
'<span class="hideonsmartphone">';
2045 $text .= ($this->nbofserviceswait + $this->nbofservicesopened + $this->nbofservicesexpired + $this->nbofservicesclosed);
2046 $text .=
' '.$langs->trans(
"Services");
2047 $text .=
': ';
2050 $text .= ($mode == 7 ?
'<span class="nowraponall">' :
'');
2051 $text .= ($mode != 7 || $this->nbofserviceswait > 0) ? ($this->nbofserviceswait.ContratLigne::LibStatut(0, 3, -1,
'class="marginleft2"')).(($mode != 7 || $this->nbofservicesopened || $this->nbofservicesexpired || $this->nbofservicesclosed) ?
' ' :
'') :
'';
2052 $text .= ($mode == 7 ?
'</span><span class="nowraponall">' :
'');
2053 $text .= ($mode != 7 || $this->nbofservicesopened > 0) ? ($this->nbofservicesopened.ContratLigne::LibStatut(4, 3, 0,
'class="marginleft2"')).(($mode != 7 || $this->nbofservicesexpired || $this->nbofservicesclosed) ?
' ' :
'') :
'';
2054 $text .= ($mode == 7 ?
'</span><span class="nowraponall">' :
'');
2055 $text .= ($mode != 7 || $this->nbofservicesexpired > 0) ? ($this->nbofservicesexpired.ContratLigne::LibStatut(4, 3, 1,
'class="marginleft2"')).(($mode != 7 || $this->nbofservicesclosed) ?
' ' :
'') :
'';
2056 $text .= ($mode == 7 ?
'</span><span class="nowraponall">' :
'');
2057 $text .= ($mode != 7 || $this->nbofservicesclosed > 0) ? ($this->nbofservicesclosed.ContratLigne::LibStatut(5, 3, -1,
'class="marginleft2"')) :
'';
2058 $text .= ($mode == 7 ?
'</span>' :
'');
2060 $text .= is_null($this->signed_status) ?
'' :
' '.$this->getLibSignedStatus(5);
2064 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status],
'', $statusType, $mode);
2076 global
$conf, $langs, $user;
2078 $langs->load(
'contracts');
2081 $nofetch = !empty($params[
'nofetch']);
2084 return [
'optimize' => $langs->trans(
"ShowContract")];
2086 if ($user->hasRight(
'contrat',
'lire')) {
2087 $datas[
'picto'] = img_picto(
'', $this->picto).
' <u class="paddingrightonly">'.$langs->trans(
"Contract").
'</u>';
2092 $datas[
'ref'] =
'<br><b>'.$langs->trans(
'Ref').
':</b> '.($this->
ref ? $this->
ref : $this->id);
2094 $langs->load(
'companies');
2095 if (empty($this->thirdparty)) {
2098 $datas[
'customer'] =
'<br><b>'.$langs->trans(
'Customer').
':</b> '.$this->thirdparty->getNomUrl(1,
'', 0, 1);
2100 $datas[
'refcustomer'] =
'<br><b>'.$langs->trans(
'RefCustomer').
':</b> '. $this->ref_customer;
2102 $langs->load(
'project');
2103 if (is_null($this->project) || (is_object($this->project) && empty($this->project->id))) {
2105 if ($res > 0 && $this->project instanceof
Project) {
2106 $datas[
'project'] =
'<br><b>'.$langs->trans(
'Project').
':</b> '.$this->project->getNomUrl(1,
'', 0,
'1');
2110 $datas[
'refsupplier'] =
'<br><b>'.$langs->trans(
'RefSupplier').
':</b> '.$this->ref_supplier;
2111 if (!empty($this->total_ht)) {
2112 $datas[
'amountht'] =
'<br><b>'.$langs->trans(
'AmountHT').
':</b> '.
price($this->total_ht, 0, $langs, 0, -1, -1,
$conf->currency);
2114 if (!empty($this->total_tva)) {
2115 $datas[
'vatamount'] =
'<br><b>'.$langs->trans(
'VAT').
':</b> '.
price($this->total_tva, 0, $langs, 0, -1, -1,
$conf->currency);
2117 if (!empty($this->total_ttc)) {
2118 $datas[
'amounttc'] =
'<br><b>'.$langs->trans(
'AmountTTC').
':</b> '.
price($this->total_ttc, 0, $langs, 0, -1, -1,
$conf->currency);
2133 public function getNomUrl($withpicto = 0, $maxlength = 0, $notooltip = 0, $save_lastsearch_value = -1)
2135 global $langs, $user, $hookmanager;
2139 $baseurl = DOL_URL_ROOT .
'/contrat/card.php';
2140 $query = [
'id' => $this->id];
2145 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2146 if ($save_lastsearch_value == -1 && isset($_SERVER[
"PHP_SELF"]) && preg_match(
'/list\.php/', $_SERVER[
"PHP_SELF"])) {
2147 $add_save_lastsearch_values = 1;
2149 if ($add_save_lastsearch_values) {
2150 $query = array_merge($query, [
'save_lastsearch_values' => 1]);
2156 'objecttype' => $this->element,
2159 $classfortooltip =
'classfortooltip';
2162 $classfortooltip =
'classforajaxtooltip';
2163 $dataparams =
' data-params="'.dol_escape_htmltag(json_encode($params)).
'"';
2170 if (empty($notooltip) && $user->hasRight(
'contrat',
'lire')) {
2172 $label = $langs->trans(
"ShowContract");
2173 $linkclose .=
' alt="'.dolPrintHTMLForAttribute($label).
'"';
2175 $linkclose .= ($label ?
' title="'.dolPrintHTMLForAttribute($label).
'"' :
' title="tocomplete"');
2176 $linkclose .= $dataparams.
' class="'.$classfortooltip.
'"';
2178 $linkstart =
'<a href="'.$url.
'"';
2179 $linkstart .= $linkclose.
'>';
2182 $result .= $linkstart;
2184 $result .= img_object(($notooltip ?
'' : $label), ($this->picto ? $this->picto :
'generic'), (($withpicto != 2) ?
'class="paddingright"' :
''), 0, 0, $notooltip ? 0 : 1);
2186 if ($withpicto != 2) {
2187 $result .= ($this->
ref ? $this->
ref : $this->id);
2189 $result .= $linkend;
2192 $hookmanager->initHooks(array(
'contractdao'));
2193 $parameters = array(
'id' => $this->
id,
'getnomurl' => &$result);
2194 $reshook = $hookmanager->executeHooks(
'getNomUrl', $parameters, $this, $action);
2196 $result = $hookmanager->resPrint;
2198 $result .= $hookmanager->resPrint;
2212 $sql =
"SELECT c.rowid, c.ref, c.datec,";
2213 $sql .=
" c.tms as date_modification,";
2214 $sql .=
" fk_user_author";
2215 $sql .=
" FROM ".MAIN_DB_PREFIX.
"contrat as c";
2216 $sql .=
" WHERE c.rowid = ".((int) $id);
2218 $result = $this->db->query($sql);
2220 if ($this->db->num_rows($result)) {
2221 $obj = $this->db->fetch_object($result);
2223 $this->
id = $obj->rowid;
2224 $this->
ref = (!$obj->ref) ? $obj->rowid : $obj->ref;
2226 $this->user_creation_id = $obj->fk_user_author;
2227 $this->date_creation = $this->db->jdate($obj->datec);
2228 $this->date_modification = $this->db->jdate($obj->date_modification);
2231 $this->db->free($result);
2233 dol_print_error($this->db);
2249 $sql =
"SELECT cd.rowid";
2250 $sql .=
" FROM ".MAIN_DB_PREFIX.
"contratdet as cd";
2251 $sql .=
" WHERE fk_contrat =".((int) $this->
id);
2253 $sql .=
" AND statut = ".((int) $status);
2256 dol_syslog(get_class($this).
"::array_detail()", LOG_DEBUG);
2257 $resql = $this->db->query($sql);
2259 $num = $this->db->num_rows($resql);
2262 $obj = $this->db->fetch_object($resql);
2263 $tab[$i] = $obj->rowid;
2268 $this->error = $this->db->error();
2282 public function getListOfContracts($option =
'all', $status = [], $product_categories = [], $line_status = [])
2286 $sql =
"SELECT c.rowid";
2287 $sql .=
" FROM ".MAIN_DB_PREFIX.
"contrat as c";
2288 if (!empty($product_categories) || !empty($line_status)) {
2289 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"contratdet as cd ON cd.fk_contrat = c.rowid";
2291 if (!empty($product_categories)) {
2292 $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)).
")";
2294 $sql .=
" WHERE c.fk_soc =".((int) $this->socid);
2295 $sql .= ($option ==
'others') ?
" AND c.rowid <> ".((
int) $this->id) :
"";
2296 $sql .= (!empty($status)) ?
" AND c.statut IN (".$this->db->sanitize(implode(
', ', $status)).
")" :
"";
2297 $sql .= (!empty($line_status)) ?
" AND cd.statut IN (".$this->db->sanitize(implode(
', ', $line_status)).
")" :
"";
2298 $sql .=
" GROUP BY c.rowid";
2300 dol_syslog(get_class($this).
"::getOtherContracts()", LOG_DEBUG);
2301 $resql = $this->db->query($sql);
2303 $num = $this->db->num_rows($resql);
2306 $obj = $this->db->fetch_object($resql);
2307 $contrat =
new Contrat($this->db);
2308 $contrat->fetch($obj->rowid);
2309 $tab[$contrat->id] = $contrat;
2314 $this->error = $this->db->lasterror();
2331 global
$conf, $langs;
2333 $this->from =
" FROM ".MAIN_DB_PREFIX.
"contrat as c";
2334 $this->from .=
", ".MAIN_DB_PREFIX.
"contratdet as cd";
2335 $this->from .=
", ".MAIN_DB_PREFIX.
"societe as s";
2336 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
2337 $this->from .=
", ".MAIN_DB_PREFIX.
"societe_commerciaux as sc";
2341 if ($mode ==
'inactive') {
2342 $warning_delay =
$conf->contract->services->inactifs->warning_delay;
2343 $datefield =
'cd.date_ouverture_prevue';
2344 } elseif ($mode ==
'expired' || $mode ==
'active') {
2345 $warning_delay =
$conf->contract->services->expires->warning_delay;
2346 $datefield =
'cd.date_fin_validite';
2354 $sql =
"SELECT COUNT(cd.rowid) as nb,";
2355 $sql .=
" SUM(CASE WHEN ".$this->db->sanitize($datefield).
" IS NOT NULL AND ".$this->db->sanitize($datefield).
" < '".$this->db->idate($now - $warning_delay).
"' THEN 1 ELSE 0 END) as nblate";
2356 if ($mode ==
'inactive') {
2357 $sql .= $this->from;
2358 $sql .=
" WHERE c.statut = 1";
2359 $sql .=
" AND c.rowid = cd.fk_contrat";
2360 $sql .=
" AND cd.statut = 0";
2361 } elseif ($mode ==
'expired') {
2362 $sql .= $this->from;
2363 $sql .=
" WHERE c.statut = 1";
2364 $sql .=
" AND c.rowid = cd.fk_contrat";
2365 $sql .=
" AND cd.statut = 4";
2366 $sql .=
" AND cd.date_fin_validite < '".$this->db->idate($now).
"'";
2368 $sql .= $this->from;
2369 $sql .=
" WHERE c.statut = 1";
2370 $sql .=
" AND c.rowid = cd.fk_contrat";
2371 $sql .=
" AND cd.statut = 4";
2373 $sql .=
" AND c.fk_soc = s.rowid";
2374 $sql .=
" AND c.entity = ".((int)
$conf->entity);
2376 $sql .=
" AND c.fk_soc = ".((int) $user->socid);
2378 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
2379 $sql .=
" AND c.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
2382 $resql = $this->db->query($sql);
2384 $langs->load(
"contracts");
2386 if ($mode ==
'inactive') {
2387 $label = $langs->trans(
"BoardNotActivatedServices");
2388 $labelShort = $langs->trans(
"BoardNotActivatedServicesShort");
2389 $url = DOL_URL_ROOT.
'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_status=0&sortfield=cd.date_fin_validite&sortorder=asc';
2390 $url_late = DOL_URL_ROOT.
'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_status=0&search_option=late';
2391 } elseif ($mode ==
'expired') {
2392 $url = DOL_URL_ROOT.
'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_status=4&filter=expired&sortfield=cd.date_fin_validite&sortorder=asc';
2393 $url_late = DOL_URL_ROOT.
'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_status=4&search_option=late';
2394 $label = $langs->trans(
"BoardExpiredServices");
2395 $labelShort = $langs->trans(
"BoardExpiredServicesShort");
2397 $url = DOL_URL_ROOT.
'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_status=4&sortfield=cd.date_fin_validite&sortorder=asc';
2398 $url_late = DOL_URL_ROOT.
'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&search_option=late';
2399 $label = $langs->trans(
"BoardRunningServices");
2400 $labelShort = $langs->trans(
"BoardRunningServicesShort");
2404 $response->warning_delay = $warning_delay / 60 / 60 / 24;
2405 $response->label = $label;
2406 $response->labelShort = $labelShort;
2407 $response->url = $url;
2408 $response->url_late = $url_late;
2409 $response->img = img_object(
'',
"contract");
2411 $obj = $this->db->fetch_object($resql);
2413 $response->nbtodo = (int) $obj->nb;
2414 $response->nbtodolate = (int) $obj->nblate;
2419 dol_print_error($this->db);
2420 $this->error = $this->db->error();
2432 global
$conf, $user;
2434 $this->nb = array();
2435 $sanitizedclause =
"WHERE";
2437 $sql =
"SELECT count(c.rowid) as nb";
2438 $sql .=
" FROM ".MAIN_DB_PREFIX.
"contrat as c";
2439 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe as s ON c.fk_soc = s.rowid";
2440 if (empty($user->socid) && !$user->hasRight(
'societe',
'client',
'voir')) {
2441 $sql .=
" LEFT JOIN ".MAIN_DB_PREFIX.
"societe_commerciaux as sc ON s.rowid = sc.fk_soc";
2442 $sql .=
" WHERE sc.fk_user = ".((int) $user->id);
2443 $sanitizedclause =
"AND";
2445 $sql .=
" ".$sanitizedclause.
" c.entity = ".((int)
$conf->entity);
2447 $resql = $this->db->query($sql);
2449 while ($obj = $this->db->fetch_object($resql)) {
2450 $this->nb[
"contracts"] = $obj->nb;
2452 $this->db->free($resql);
2455 dol_print_error($this->db);
2456 $this->error = $this->db->error();
2494 global $user, $langs,
$conf;
2499 $sql =
"SELECT rowid";
2500 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product";
2501 $sql .=
" WHERE entity IN (".getEntity(
'product').
")";
2502 $sql .=
" AND tosell = 1";
2503 $sql .= $this->db->plimit(100);
2505 $resql = $this->db->query($sql);
2507 $num_prods = $this->db->num_rows($resql);
2509 while ($i < $num_prods) {
2511 $row = $this->db->fetch_row($resql);
2512 $prodids[$i] = $row[0];
2518 $this->specimen = 1;
2520 $this->
ref =
'SPECIMEN';
2521 $this->ref_customer =
'SPECIMENCUST';
2522 $this->ref_supplier =
'SPECIMENSUPP';
2525 $this->date_creation = (
dol_now() - 3600 * 24 * 7);
2526 $this->date_contrat =
dol_now();
2527 $this->commercial_signature_id = 1;
2528 $this->commercial_suivi_id = 1;
2529 $this->note_private =
'This is a comment (private)';
2530 $this->note_public =
'This is a comment (public)';
2531 $this->fk_project = 0;
2535 while ($xnbp < $nbp) {
2538 $line->subprice = 100;
2539 $line->tva_tx = 19.6;
2540 $line->remise_percent = 10;
2541 $line->total_ht = 90;
2542 $line->total_ttc = 107.64;
2543 $line->total_tva = 17.64;
2544 $line->date_start =
dol_now() - 500000;
2545 $line->date_start_real =
dol_now() - 200000;
2546 $line->date_end =
dol_now() + 500000;
2547 $line->date_end_real =
dol_now() - 100000;
2548 if ($num_prods > 0) {
2549 $prodid = mt_rand(1, $num_prods);
2550 $line->fk_product = $prodids[$prodid];
2552 $this->lines[$xnbp] = $line;
2578 $ticket =
new Ticket($this->db);
2579 $nbTicket = $ticket->fetchAll($user,
'ASC',
't.datec', 0, 0, 0, array(
't.fk_contract' => $this->
id));
2581 return ($nbTicket < 0 ? $nbTicket : $ticket->lines);
2596 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams =
null)
2603 if (!empty($this->model_pdf)) {
2604 $modele = $this->model_pdf;
2610 if (empty($modele)) {
2613 $langs->load(
"contracts");
2614 $outputlangs->load(
"products");
2616 $modelpath =
"core/modules/contract/doc/";
2617 return $this->
commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
2663 public function createFromClone(
User $user, $socid = 0, $notrigger = 0)
2665 global $db, $langs,
$conf, $hookmanager, $extrafields;
2671 $this->
fetch($this->
id);
2674 $clonedObj = clone $this;
2675 $clonedObj->socid = $socid;
2679 $objsoc =
new Societe($this->db);
2681 $objsoc->fetch($clonedObj->socid);
2684 $clonedObj->statut = 0;
2685 $clonedObj->status = 0;
2687 if (is_array($clonedObj->array_options) && count($clonedObj->array_options) > 0) {
2688 $extrafields->fetch_name_optionals_label($this->table_element);
2689 foreach ($clonedObj->array_options as $key => $option) {
2690 $shortkey = preg_replace(
'/options_/',
'', $key);
2691 if (!empty($extrafields->attributes[$this->element][
'unique'][$shortkey])) {
2692 unset($clonedObj->array_options[$key]);
2698 $this->error =
'ErrorSetupNotComplete';
2704 require_once DOL_DOCUMENT_ROOT.
"/core/modules/contract/" .
getDolGlobalString(
'CONTRACT_ADDON').
'.php';
2706 $modContract =
new $obj();
2707 '@phan-var-force ModelNumRefContracts $modContract';
2709 $clonedObj->ref = $modContract->getNextValue($objsoc, $clonedObj);
2712 foreach ($this->lines as $line) {
2713 $line->fetch_optionals($line->id);
2717 $clonedObj->context[
'createfromclone'] =
'createfromclone';
2718 $result = $clonedObj->create($user);
2724 if ($this->socid == $clonedObj->socid) {
2725 if ($clonedObj->copy_linked_contact($this,
'external') < 0) {
2732 foreach ($this->lines as $line) {
2736 $line_price_base_type = $line->getPriceBaseType();
2737 $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);
2747 if (is_object($hookmanager)) {
2748 $parameters = array(
2750 'clonedObj' => $clonedObj
2753 $reshook = $hookmanager->executeHooks(
'createFrom', $parameters, $clonedObj, $action);
2761 unset($clonedObj->context[
'createfromclone']);
2765 $this->db->commit();
2766 return $clonedObj->id;
2768 $this->db->rollback();
2785 global $langs, $user;
2787 $langs->load(
"agenda");
2797 $contractlineprocessed = array();
2798 $contractignored = array();
2799 $contracterror = array();
2803 $sql =
'SELECT c.rowid, c.ref_customer, cd.rowid as lid, cd.date_fin_validite, p.duration';
2804 $sql .=
' FROM '.MAIN_DB_PREFIX.
'contrat as c, '.MAIN_DB_PREFIX.
'contratdet as cd';
2805 $sql .=
' LEFT JOIN '.MAIN_DB_PREFIX.
'product as p ON p.rowid = cd.fk_product';
2806 $sql .=
' WHERE cd.fk_contrat = c.rowid';
2807 $sql .=
" AND date_format(cd.date_fin_validite, '%Y-%m-%d') <= date_format('".$this->db->idate($enddatetoscan).
"', '%Y-%m-%d')";
2808 $sql .=
" AND cd.statut = 4";
2809 if ($thirdparty_id > 0) {
2810 $sql .=
" AND c.fk_soc = ".((int) $thirdparty_id);
2814 $resql = $this->db->query($sql);
2816 $num = $this->db->num_rows($resql);
2818 include_once DOL_DOCUMENT_ROOT.
'/core/class/html.formmail.class.php';
2819 include_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
2823 $obj = $this->db->fetch_object($resql);
2825 if (!empty($contractlineprocessed[$obj->lid]) || !empty($contractignored[$obj->rowid]) || !empty($contracterror[$obj->rowid])) {
2835 $this->errors[] =
'Failed to load contract with id='.$obj->rowid;
2839 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);
2842 $expirationdate = $this->db->jdate($obj->date_fin_validite);
2843 $duration_value = preg_replace(
'/[^0-9]/',
'', $obj->duration);
2844 $duration_unit = preg_replace(
'/\d/',
'', $obj->duration);
2848 $object->fetchObjectLinked(
null,
'',
null,
'',
'OR', 1,
'sourcetype', 1);
2851 if (isset(
$object->linkedObjects[
'facture']) && is_array(
$object->linkedObjects[
'facture']) && count(
$object->linkedObjects[
'facture']) > 0) {
2853 usort(
$object->linkedObjects[
'facture'], array(
'Contrat',
'contractCmpDate'));
2856 $someinvoicenotpaid = 0;
2857 foreach (
$object->linkedObjects[
'facture'] as $idinvoice => $invoice) {
2862 if (empty($invoice->paye)) {
2863 $someinvoicenotpaid++;
2866 if ($someinvoicenotpaid) {
2867 $this->output .=
'Contract '.$object->ref.
' is qualified for renewal but there is '.$someinvoicenotpaid.
' invoice(s) unpayed so we cancel renewal'.
"\n";
2873 if ($expirationdate && $expirationdate < $enddatetoscan) {
2874 dol_syslog(
"Define the newdate of end of services from expirationdate=".$expirationdate);
2875 $newdate = $expirationdate;
2877 while ($newdate < $enddatetoscan && $protecti < 1000) {
2882 if ($protecti < 1000) {
2888 $errorforlocaltransaction = 0;
2890 $label =
'Renewal of contrat '.$object->ref.
' line '.$obj->lid;
2891 $comment =
'Renew date of contract '.$object->ref.
' line '.$obj->lid.
' by doAutoRenewContracts';
2893 $sqlupdate =
'UPDATE '.MAIN_DB_PREFIX.
"contratdet SET date_fin_validite = '".$this->db->idate($newdate).
"'";
2894 $sqlupdate .=
' WHERE rowid = '.((int) $obj->lid);
2895 $resqlupdate = $this->db->query($sqlupdate);
2897 $contractlineprocessed[$obj->lid] =
$object->ref;
2900 $sqltoupdatecontract =
"UPDATE ".MAIN_DB_PREFIX.
"contrat";
2901 $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.
")";
2902 $sqltoupdatecontract .=
" WHERE rowid = ".((int)
$object->id);
2903 $resqltoupdatecontract = $this->db->query($sqltoupdatecontract);
2904 if (!$resqltoupdatecontract) {
2905 $this->error = $this->db->lasterror();
2906 $this->db->rollback();
2910 $actioncode =
'RENEW_CONTRACT';
2915 $actioncomm->type_code =
'AC_OTH_AUTO';
2916 $actioncomm->code =
'AC_'.$actioncode;
2917 $actioncomm->label = $label;
2918 $actioncomm->datep = $now;
2919 $actioncomm->datef = $now;
2920 $actioncomm->percentage = -1;
2921 $actioncomm->socid =
$object->socid;
2922 $actioncomm->authorid = $user->id;
2923 $actioncomm->userownerid = $user->id;
2924 $actioncomm->fk_element =
$object->id;
2925 $actioncomm->elementid =
$object->id;
2926 $actioncomm->elementtype =
'contract';
2927 $actioncomm->note_private = $comment;
2929 $ret = $actioncomm->create($user);
2934 $errorforlocaltransaction++;
2935 $this->error = $this->db->lasterror();
2938 if (! $errorforlocaltransaction) {
2939 $this->db->commit();
2941 $this->db->rollback();
2945 $this->error =
"Bad value for newdate in doAutoRenewContracts - expirationdate=".$expirationdate.
" enddatetoscan=".$enddatetoscan.
" duration_value=".$duration_value.
" duration_unit=".$duration_value;
2954 $this->error = $this->db->lasterror();
2957 $this->output .= count($contractlineprocessed).
' contract line(s) with end date before '.
dol_print_date($enddatetoscan,
'day').
' were renewed'.(count($contractlineprocessed) > 0 ?
' : '.implode(
',', $contractlineprocessed) :
'');
2959 return ($error ? 1 : 0);
2971 if ($a->date == $b->date) {
2972 return strcmp((
string) $a->id, (
string) $b->id);
2974 return ($a->date < $b->date) ? -1 : 1;
2988 $selected = (empty($arraydata[
'selected']) ? 0 : $arraydata[
'selected']);
2990 $return =
'<div class="box-flex-item box-flex-grow-zero">';
2991 $return .=
'<div class="info-box info-box-sm">';
2992 $return .=
'<span class="info-box-icon bg-infobox-action">';
2993 $return .= img_picto(
'', $this->picto);
2994 $return .=
'</span>';
2995 $return .=
'<div class="info-box-content">';
2996 $return .=
'<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . $this->
getNomUrl() .
'</span>';
2997 if ($selected >= 0) {
2998 $return .=
'<input id="cb'.$this->id.
'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->
id.
'"'.($selected ?
' checked="checked"' :
'').
'>';
3000 if (!empty($arraydata[
'thirdparty']) && $arraydata[
'thirdparty'] instanceof
Societe) {
3001 $tmpthirdparty = $arraydata[
'thirdparty'];
3002 '@phan-var-force Societe $tmpthirdparty';
3003 $return .=
'<br><div class="info-box-label inline-block valignmiddle">'.$tmpthirdparty->getNomUrl(1).
'</div>';
3005 $return .=
'<br><span class="opacitymedium valignmiddle">'.$langs->trans(
"DateContract").
' : </span><span class="info-box-label valignmiddle">'.
dol_print_date($this->date_contrat,
'day').
'</span>';
3006 $return .=
'<br><div class="info-box-status valignmiddle">'.$this->getLibStatut(7).
'</div>';
3007 $return .=
'</div>';
3008 $return .=
'</div>';
3009 $return .=
'</div>';
3023 $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,";
3024 $sql .=
" SUM(cd.total_localtax1) as total_localtax1, SUM(cd.total_localtax2) as total_localtax2";
3025 $sql .=
" FROM ".MAIN_DB_PREFIX.
"contratdet as cd";
3026 $sql .=
" WHERE cd.fk_contrat =".((int) $this->
id);
3028 $sql .=
" AND cd.statut = ".((int) $statut);
3030 $sql .=
" AND cd.date_fin_validite < '".$this->db->idate(
dol_now()).
"'";
3032 $sql .=
" AND cd.date_fin_validite >= '".$this->db->idate(
dol_now()).
"'";
3035 $ret = $this->db->query($sql);
3036 $response = array();
3038 $obj = $this->db->fetch_object($ret);
3039 $response[
'total_qty'] = $obj->total_qty;
3040 $response[
'total_ht'] = $obj->total_ht;
3041 $response[
'total_tva'] = $obj->total_tva;
3042 $response[
'total_localtax1'] = $obj->total_localtax1;
3043 $response[
'total_localtax2'] = $obj->total_localtax2;
3044 $response[
'total_ttc'] = $obj->total_ttc;
3046 dol_print_error($this->db);
3047 $this->error = $this->db->lasterror();
3091 $blockingerrormsg =
'';
3094 $langs->load(
"agenda");
3095 $this->output = $langs->trans(
'ModuleNotEnabled', $langs->transnoentitiesnoconv(
"Contract"));
3103 $listoflinesok = array();
3104 $listoflinesko = array();
3106 $arraydaysbeforeend = explode(
';', $daysbeforeendlist);
3107 foreach ($arraydaysbeforeend as $daysbeforeend) {
3108 dol_syslog(__METHOD__.
' - Process delta = '.$daysbeforeend, LOG_DEBUG);
3110 if (!is_numeric($daysbeforeend)) {
3111 $blockingerrormsg =
"Value for delta is not a numeric value";
3117 $datetosearchfor =
dol_time_plus_duree(
dol_mktime(0, 0, 0, $tmp[
'mon'], $tmp[
'mday'], $tmp[
'year'],
'tzserver'), (
int) $daysbeforeend,
'd');
3118 $datetosearchforend =
dol_time_plus_duree(
dol_mktime(23, 59, 59, $tmp[
'mon'], $tmp[
'mday'], $tmp[
'year'],
'tzserver'), (
int) $daysbeforeend,
'd');
3120 $sql =
"SELECT cd.rowid, cd.fk_contrat";
3121 $sql .=
" FROM ".MAIN_DB_PREFIX.
"contratdet as cd";
3122 $sql .=
" INNER JOIN ".MAIN_DB_PREFIX.
"contrat as c ON c.rowid = cd.fk_contrat";
3123 $sql .=
" WHERE c.entity = ".((int)
$conf->entity);
3124 $sql .=
" AND cd.statut = ".((int) ContratLigne::STATUS_OPEN);
3125 $sql .=
" AND cd.date_fin_validite >= '".$this->db->idate($datetosearchfor).
"'";
3126 $sql .=
" AND cd.date_fin_validite <= '".$this->db->idate($datetosearchforend).
"'";
3127 if ((
int) $fk_product > 0) {
3128 $sql .=
" AND cd.fk_product = ".((int) $fk_product);
3131 $resql = $this->db->query($sql);
3133 $num_rows = $this->db->num_rows($resql);
3135 include_once DOL_DOCUMENT_ROOT.
'/core/class/html.formmail.class.php';
3136 include_once DOL_DOCUMENT_ROOT.
'/contrat/class/contratligne.class.php';
3137 $formmail =
new FormMail($this->db);
3140 while ($i < $num_rows) {
3141 $obj = $this->db->fetch_object($resql);
3144 $contractline->fetch($obj->rowid);
3146 $contractstatic =
new Contrat($this->db);
3147 $contractstatic->fetch($obj->fk_contrat);
3148 $thirdpartyres = $contractstatic->fetch_thirdparty();
3150 if ($thirdpartyres <= 0 || empty($contractstatic->thirdparty->email)) {
3152 $listoflinesko[$contractline->id] = $contractline->id;
3155 $languagecodetouse = (empty($contractstatic->thirdparty->default_lang) ? ($languagefromcountrycode ? $languagefromcountrycode :
$mysoc->default_lang) : $contractstatic->thirdparty->default_lang);
3158 $outputlangs->setDefaultLang($languagecodetouse);
3159 $outputlangs->loadLangs(array(
"main",
"contracts"));
3160 dol_syslog(
"sendReminderForExpiredServices Language for thirdparty id ".$contractstatic->thirdparty->id.
" set to ".$outputlangs->defaultlang.
" mysoc->default_lang=".
$mysoc->default_lang);
3162 $arraydefaultmessage =
null;
3165 if (!empty($labeltouse)) {
3166 $arraydefaultmessage = $formmail->getEMailTemplate($this->db,
'contrat', $user, $outputlangs, 0, 1, $labeltouse);
3169 if (!empty($labeltouse) && is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
3170 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0,
null, $contractstatic);
3172 $substitutionarray[
'__CONTRACT_LINE_LABEL__'] = ($contractline->label ? $contractline->label : $contractline->description);
3173 $substitutionarray[
'__CONTRACT_LINE_DATE_END__'] =
dol_print_date($contractline->date_end,
'day',
'tzuserrel', $outputlangs);
3175 $subject =
make_substitutions($arraydefaultmessage->topic, $substitutionarray, $outputlangs);
3176 $msg =
make_substitutions($arraydefaultmessage->content, $substitutionarray, $outputlangs);
3178 $to = (string) $contractstatic->thirdparty->email;
3181 $trackid =
'con'.$contractstatic->id;
3182 $moreinheader =
'X-Dolibarr-Info: sendReminderForExpiredServices'.
"\r\n";
3184 include_once DOL_DOCUMENT_ROOT.
'/core/class/CMailFile.class.php';
3185 $cmail =
new CMailFile($subject, $to, $email_from, $msg, array(), array(), array(), $cc,
'', 0, 1,
'',
'', $trackid, $moreinheader);
3186 $result = $cmail->sendfile();
3189 $this->error .= $cmail->error.
' ';
3190 if (!is_null($cmail->errors)) {
3191 $this->errors = array_merge($this->errors, $cmail->errors);
3194 $listoflinesko[$contractline->id] = $contractline->id;
3197 $listoflinesok[$contractline->id] = $contractline->id;
3200 require_once DOL_DOCUMENT_ROOT.
'/comm/action/class/actioncomm.class.php';
3203 $actioncomm->type_code =
'AC_OTH_AUTO';
3204 $actioncomm->code =
'AC_EMAIL';
3206 $actioncomm->note_private = $msg;
3207 $actioncomm->fk_project = 0;
3208 $actioncomm->datep = $now;
3209 $actioncomm->datef = $now;
3210 $actioncomm->percentage = -1;
3211 $actioncomm->socid = $contractstatic->thirdparty->id;
3212 $actioncomm->contact_id = 0;
3213 $actioncomm->authorid = $user->id;
3214 $actioncomm->userownerid = $user->id;
3215 $actioncomm->email_msgid = $cmail->msgid;
3216 $actioncomm->email_from = $email_from;
3217 $actioncomm->email_sender =
'';
3218 $actioncomm->email_to = $to;
3219 $actioncomm->email_subject = $subject;
3221 $actioncomm->fk_element = $contractstatic->id;
3222 $actioncomm->elementid = $contractstatic->id;
3223 $actioncomm->elementtype = $contractstatic->element;
3225 $actioncomm->create($user);
3229 $this->error .=
"Can't find email template with label=".$labeltouse.
", to use for the reminding email ";
3232 $listoflinesko[$contractline->id] = $contractline->id;
3241 $this->error = $this->db->lasterror();
3246 if ($blockingerrormsg) {
3247 $this->error = $blockingerrormsg;
3250 $this->output =
'Found '.($nbok + $nbko).
' contract lines to send reminder for.';
3251 $this->output .=
' Sent email successfully for '.$nbok.
' lines';
3253 $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...
line_order($renum=false, $rowidorder='ASC', $fk_parent_line=true)
Save a new position (field rang) for details lines.
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.
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
isLineOfObject($lineid)
Check that a line belongs to this object, using $this->table_element_line and $this->fk_element.
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.
defineBuyPrice($unitPrice=0.0, $discountPercent=0.0, $fk_product=0, $qty=0)
Get buy price to use for margin calculation.
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.
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.