diff --git a/htdocs/core/tpl/objectline_title.tpl.php b/htdocs/core/tpl/objectline_title.tpl.php
index 157e24f64b9..4d6fd5d0d75 100644
--- a/htdocs/core/tpl/objectline_title.tpl.php
+++ b/htdocs/core/tpl/objectline_title.tpl.php
@@ -83,7 +83,7 @@ print '
'.$langs->trans('ReductionShort').' | situation_cycle_ref) {
print '' . $langs->trans('Progress') . ' | ';
- print '' . $langs->trans('TotalHT100Short') . ' | ';
+ print '' . $form->textwithpicto($langs->trans('TotalHT100Short'), $langs->trans('UnitPriceXQtyLessDiscount')) . ' | ';
}
if ($usemargins && ! empty($conf->margin->enabled) && empty($user->socid))
diff --git a/htdocs/install/mysql/migration/repair.sql b/htdocs/install/mysql/migration/repair.sql
index 24d077654da..b21429a4d1b 100644
--- a/htdocs/install/mysql/migration/repair.sql
+++ b/htdocs/install/mysql/migration/repair.sql
@@ -491,8 +491,13 @@ UPDATE llx_accounting_bookkeeping set date_creation = tms where date_creation IS
-- UPDATE llx_facturedet_rec set label = NULL WHERE label IS NOT NULL;
+
UPDATE llx_facturedet SET situation_percent = 100 WHERE situation_percent IS NULL AND fk_prev_id IS NULL;
+-- Test inconsistency of data into situation invoices: If it differs, it may be the total_ht that is wrong and situation_percent that is good.
+-- select f.rowid, f.type, qty, subprice, situation_percent, total_ht, total_ttc, total_tva, multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc, (situation_percent / 100 * subprice * qty * (1 - (fd.remise_percent / 100)))
+-- from llx_facturedet as fd, llx_facture as f where fd.fk_facture = f.rowid AND (total_ht - situation_percent / 100 * subprice * qty * (1 - (fd.remise_percent / 100))) > 0.01 and f.type = 5;
+
-- Note to make all deposit as payed when there is already a discount generated from it.
--drop table tmp_invoice_deposit_mark_as_available;
@@ -501,6 +506,7 @@ UPDATE llx_facturedet SET situation_percent = 100 WHERE situation_percent IS NUL
+
-- Note to migrate from old counter aquarium to new one
-- drop table tmp;
-- create table tmp select rowid, code_client, concat(substr(code_client, 1, 6),'-0',substr(code_client, 8, 5)) as code_client2 from llx_societe where code_client like 'CU____-____';
diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang
index 6e26ecb6835..ac521ad8102 100644
--- a/htdocs/langs/en_US/bills.lang
+++ b/htdocs/langs/en_US/bills.lang
@@ -574,3 +574,4 @@ AutoFillDateTo=Set end date for service line with next invoice date
AutoFillDateToShort=Set end date
MaxNumberOfGenerationReached=Max number of gen. reached
BILL_DELETEInDolibarr=Invoice deleted
+UnitPriceXQtyLessDiscount=Unit price x Qty - Discount
diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php
index 5802ad20e56..a5e1c197f8b 100644
--- a/htdocs/projet/class/project.class.php
+++ b/htdocs/projet/class/project.class.php
@@ -34,27 +34,27 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
class Project extends CommonObject
{
- /**
+ /**
* @var string ID to identify managed object
*/
public $element = 'project';
- /**
+ /**
* @var string Name of table without prefix where object is stored
*/
public $table_element = 'projet';
- /**
+ /**
* @var int Name of subtable line
*/
public $table_element_line = 'projet_task';
- /**
+ /**
* @var int Name of field date
*/
public $table_element_date;
- /**
+ /**
* @var int Field with ID of parent key if this field has a parent
*/
public $fk_element = 'fk_projet';
@@ -63,19 +63,19 @@ class Project extends CommonObject
* 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
* @var int
*/
- public $ismultientitymanaged = 1;
+ public $ismultientitymanaged = 1;
- /**
- * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
- */
- public $picto = 'projectpub';
+ /**
+ * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
+ */
+ public $picto = 'projectpub';
- /**
- * {@inheritdoc}
- */
- protected $table_ref_field = 'ref';
+ /**
+ * {@inheritdoc}
+ */
+ protected $table_ref_field = 'ref';
- /**
+ /**
* @var string description
*/
public $description;
@@ -83,41 +83,41 @@ class Project extends CommonObject
/**
* @var string
*/
- public $title;
+ public $title;
- public $date_start;
- public $date_end;
- public $date_close;
+ public $date_start;
+ public $date_end;
+ public $date_close;
- public $socid; // To store id of thirdparty
- public $thirdparty_name; // To store name of thirdparty (defined only in some cases)
+ public $socid; // To store id of thirdparty
+ public $thirdparty_name; // To store name of thirdparty (defined only in some cases)
- public $user_author_id; //!< Id of project creator. Not defined if shared project.
+ public $user_author_id; //!< Id of project creator. Not defined if shared project.
- /**
- * @var int user close id
- */
- public $fk_user_close;
+ /**
+ * @var int user close id
+ */
+ public $fk_user_close;
- /**
- * @var int user close id
- */
+ /**
+ * @var int user close id
+ */
public $user_close_id;
- public $public; //!< Tell if this is a public or private project
- public $budget_amount;
- public $usage_bill_time; // Is the time spent on project must be invoiced or not
+ public $public; //!< Tell if this is a public or private project
+ public $budget_amount;
+ public $usage_bill_time; // Is the time spent on project must be invoiced or not
- public $statuts_short;
- public $statuts_long;
+ public $statuts_short;
+ public $statuts_long;
- public $statut; // 0=draft, 1=opened, 2=closed
- public $opp_status; // opportunity status, into table llx_c_lead_status
+ public $statut; // 0=draft, 1=opened, 2=closed
+ public $opp_status; // opportunity status, into table llx_c_lead_status
public $opp_percent; // opportunity probability
- public $oldcopy;
+ public $oldcopy;
- public $weekWorkLoad; // Used to store workload details of a projet
- public $weekWorkLoadPerTask; // Used to store workload details of tasks of a projet
+ public $weekWorkLoad; // Used to store workload details of a projet
+ public $weekWorkLoadPerTask; // Used to store workload details of tasks of a projet
/**
* @var int Creation date
@@ -196,406 +196,406 @@ class Project extends CommonObject
);
- /**
- * Constructor
- *
- * @param DoliDB $db Database handler
- */
- public function __construct($db)
- {
- $this->db = $db;
+ /**
+ * Constructor
+ *
+ * @param DoliDB $db Database handler
+ */
+ public function __construct($db)
+ {
+ $this->db = $db;
- $this->statuts_short = array(0 => 'Draft', 1 => 'Opened', 2 => 'Closed');
- $this->statuts_long = array(0 => 'Draft', 1 => 'Opened', 2 => 'Closed');
- }
+ $this->statuts_short = array(0 => 'Draft', 1 => 'Opened', 2 => 'Closed');
+ $this->statuts_long = array(0 => 'Draft', 1 => 'Opened', 2 => 'Closed');
+ }
- /**
- * Create a project into database
- *
- * @param User $user User making creation
- * @param int $notrigger Disable triggers
- * @return int <0 if KO, id of created project if OK
- */
- public function create($user, $notrigger = 0)
- {
- global $conf, $langs;
+ /**
+ * Create a project into database
+ *
+ * @param User $user User making creation
+ * @param int $notrigger Disable triggers
+ * @return int <0 if KO, id of created project if OK
+ */
+ public function create($user, $notrigger = 0)
+ {
+ global $conf, $langs;
- $error = 0;
- $ret = 0;
+ $error = 0;
+ $ret = 0;
- $now = dol_now();
+ $now = dol_now();
- // Clean parameters
- $this->note_private = dol_substr($this->note_private, 0, 65535);
- $this->note_public = dol_substr($this->note_public, 0, 65535);
+ // Clean parameters
+ $this->note_private = dol_substr($this->note_private, 0, 65535);
+ $this->note_public = dol_substr($this->note_public, 0, 65535);
- // Check parameters
- if (!trim($this->ref))
- {
- $this->error = 'ErrorFieldsRequired';
- dol_syslog(get_class($this)."::create error -1 ref null", LOG_ERR);
- return -1;
- }
- if (!empty($conf->global->PROJECT_THIRDPARTY_REQUIRED) && !($this->socid > 0))
- {
- $this->error = 'ErrorFieldsRequired';
- dol_syslog(get_class($this)."::create error -1 thirdparty not defined and option PROJECT_THIRDPARTY_REQUIRED is set", LOG_ERR);
- return -1;
- }
+ // Check parameters
+ if (!trim($this->ref))
+ {
+ $this->error = 'ErrorFieldsRequired';
+ dol_syslog(get_class($this)."::create error -1 ref null", LOG_ERR);
+ return -1;
+ }
+ if (!empty($conf->global->PROJECT_THIRDPARTY_REQUIRED) && !($this->socid > 0))
+ {
+ $this->error = 'ErrorFieldsRequired';
+ dol_syslog(get_class($this)."::create error -1 thirdparty not defined and option PROJECT_THIRDPARTY_REQUIRED is set", LOG_ERR);
+ return -1;
+ }
- // Create project
- $this->db->begin();
+ // Create project
+ $this->db->begin();
- $sql = "INSERT INTO ".MAIN_DB_PREFIX."projet (";
- $sql .= "ref";
- $sql .= ", title";
- $sql .= ", description";
- $sql .= ", fk_soc";
- $sql .= ", fk_user_creat";
- $sql .= ", fk_statut";
- $sql .= ", fk_opp_status";
- $sql .= ", opp_percent";
- $sql .= ", public";
- $sql .= ", datec";
- $sql .= ", dateo";
- $sql .= ", datee";
- $sql .= ", opp_amount";
- $sql .= ", budget_amount";
- $sql .= ", usage_opportunity";
- $sql .= ", usage_task";
- $sql .= ", usage_bill_time";
- $sql .= ", usage_organize_event";
- $sql .= ", note_private";
- $sql .= ", note_public";
- $sql .= ", entity";
- $sql .= ") VALUES (";
- $sql .= "'".$this->db->escape($this->ref)."'";
- $sql .= ", '".$this->db->escape($this->title)."'";
- $sql .= ", '".$this->db->escape($this->description)."'";
- $sql .= ", ".($this->socid > 0 ? $this->socid : "null");
- $sql .= ", ".$user->id;
- $sql .= ", ".(is_numeric($this->statut) ? $this->statut : '0');
- $sql .= ", ".((is_numeric($this->opp_status) && $this->opp_status > 0) ? $this->opp_status : 'NULL');
- $sql .= ", ".(is_numeric($this->opp_percent) ? $this->opp_percent : 'NULL');
- $sql .= ", ".($this->public ? 1 : 0);
- $sql .= ", '".$this->db->idate($now)."'";
- $sql .= ", ".($this->date_start != '' ? "'".$this->db->idate($this->date_start)."'" : 'null');
- $sql .= ", ".($this->date_end != '' ? "'".$this->db->idate($this->date_end)."'" : 'null');
- $sql .= ", ".(strcmp($this->opp_amount, '') ? price2num($this->opp_amount) : 'null');
- $sql .= ", ".(strcmp($this->budget_amount, '') ? price2num($this->budget_amount) : 'null');
- $sql .= ", ".($this->usage_opportunity ? 1 : 0);
- $sql .= ", ".($this->usage_task ? 1 : 0);
- $sql .= ", ".($this->usage_bill_time ? 1 : 0);
- $sql .= ", ".($this->usage_organize_event ? 1 : 0);
- $sql .= ", ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : 'null');
- $sql .= ", ".($this->note_public ? "'".$this->db->escape($this->note_public)."'" : 'null');
- $sql .= ", ".$conf->entity;
- $sql .= ")";
+ $sql = "INSERT INTO ".MAIN_DB_PREFIX."projet (";
+ $sql .= "ref";
+ $sql .= ", title";
+ $sql .= ", description";
+ $sql .= ", fk_soc";
+ $sql .= ", fk_user_creat";
+ $sql .= ", fk_statut";
+ $sql .= ", fk_opp_status";
+ $sql .= ", opp_percent";
+ $sql .= ", public";
+ $sql .= ", datec";
+ $sql .= ", dateo";
+ $sql .= ", datee";
+ $sql .= ", opp_amount";
+ $sql .= ", budget_amount";
+ $sql .= ", usage_opportunity";
+ $sql .= ", usage_task";
+ $sql .= ", usage_bill_time";
+ $sql .= ", usage_organize_event";
+ $sql .= ", note_private";
+ $sql .= ", note_public";
+ $sql .= ", entity";
+ $sql .= ") VALUES (";
+ $sql .= "'".$this->db->escape($this->ref)."'";
+ $sql .= ", '".$this->db->escape($this->title)."'";
+ $sql .= ", '".$this->db->escape($this->description)."'";
+ $sql .= ", ".($this->socid > 0 ? $this->socid : "null");
+ $sql .= ", ".$user->id;
+ $sql .= ", ".(is_numeric($this->statut) ? $this->statut : '0');
+ $sql .= ", ".((is_numeric($this->opp_status) && $this->opp_status > 0) ? $this->opp_status : 'NULL');
+ $sql .= ", ".(is_numeric($this->opp_percent) ? $this->opp_percent : 'NULL');
+ $sql .= ", ".($this->public ? 1 : 0);
+ $sql .= ", '".$this->db->idate($now)."'";
+ $sql .= ", ".($this->date_start != '' ? "'".$this->db->idate($this->date_start)."'" : 'null');
+ $sql .= ", ".($this->date_end != '' ? "'".$this->db->idate($this->date_end)."'" : 'null');
+ $sql .= ", ".(strcmp($this->opp_amount, '') ? price2num($this->opp_amount) : 'null');
+ $sql .= ", ".(strcmp($this->budget_amount, '') ? price2num($this->budget_amount) : 'null');
+ $sql .= ", ".($this->usage_opportunity ? 1 : 0);
+ $sql .= ", ".($this->usage_task ? 1 : 0);
+ $sql .= ", ".($this->usage_bill_time ? 1 : 0);
+ $sql .= ", ".($this->usage_organize_event ? 1 : 0);
+ $sql .= ", ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : 'null');
+ $sql .= ", ".($this->note_public ? "'".$this->db->escape($this->note_public)."'" : 'null');
+ $sql .= ", ".$conf->entity;
+ $sql .= ")";
- dol_syslog(get_class($this)."::create", LOG_DEBUG);
- $resql = $this->db->query($sql);
- if ($resql)
- {
- $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."projet");
- $ret = $this->id;
+ dol_syslog(get_class($this)."::create", LOG_DEBUG);
+ $resql = $this->db->query($sql);
+ if ($resql)
+ {
+ $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."projet");
+ $ret = $this->id;
- if (!$notrigger)
- {
- // Call trigger
- $result = $this->call_trigger('PROJECT_CREATE', $user);
- if ($result < 0) { $error++; }
- // End call triggers
- }
- }
- else
- {
- $this->error = $this->db->lasterror();
- $this->errno = $this->db->lasterrno();
- $error++;
- }
+ if (!$notrigger)
+ {
+ // Call trigger
+ $result = $this->call_trigger('PROJECT_CREATE', $user);
+ if ($result < 0) { $error++; }
+ // End call triggers
+ }
+ }
+ else
+ {
+ $this->error = $this->db->lasterror();
+ $this->errno = $this->db->lasterrno();
+ $error++;
+ }
- // Update extrafield
- if (!$error) {
- if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
- {
- $result = $this->insertExtraFields();
- if ($result < 0)
- {
- $error++;
- }
- }
- }
+ // Update extrafield
+ if (!$error) {
+ if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
+ {
+ $result = $this->insertExtraFields();
+ if ($result < 0)
+ {
+ $error++;
+ }
+ }
+ }
- if (!$error && !empty($conf->global->MAIN_DISABLEDRAFTSTATUS))
- {
- $res = $this->setValid($user);
- if ($res < 0) $error++;
- }
+ if (!$error && !empty($conf->global->MAIN_DISABLEDRAFTSTATUS))
+ {
+ $res = $this->setValid($user);
+ if ($res < 0) $error++;
+ }
- if (!$error)
- {
- $this->db->commit();
- return $ret;
- }
- else
- {
- $this->db->rollback();
- return -1;
- }
- }
+ if (!$error)
+ {
+ $this->db->commit();
+ return $ret;
+ }
+ else
+ {
+ $this->db->rollback();
+ return -1;
+ }
+ }
- /**
- * Update a project
- *
- * @param User $user User object of making update
- * @param int $notrigger 1=Disable all triggers
- * @return int <=0 if KO, >0 if OK
- */
- public function update($user, $notrigger = 0)
- {
- global $langs, $conf;
+ /**
+ * Update a project
+ *
+ * @param User $user User object of making update
+ * @param int $notrigger 1=Disable all triggers
+ * @return int <=0 if KO, >0 if OK
+ */
+ public function update($user, $notrigger = 0)
+ {
+ global $langs, $conf;
- $error = 0;
+ $error = 0;
- // Clean parameters
- $this->title = trim($this->title);
- $this->description = trim($this->description);
+ // Clean parameters
+ $this->title = trim($this->title);
+ $this->description = trim($this->description);
if ($this->opp_amount < 0) $this->opp_amount = '';
if ($this->opp_percent < 0) $this->opp_percent = '';
- if ($this->date_end && $this->date_end < $this->date_start)
- {
- $this->error = $langs->trans("ErrorDateEndLowerThanDateStart");
- $this->errors[] = $this->error;
- $this->db->rollback();
- dol_syslog(get_class($this)."::update error -3 ".$this->error, LOG_ERR);
- return -3;
- }
+ if ($this->date_end && $this->date_end < $this->date_start)
+ {
+ $this->error = $langs->trans("ErrorDateEndLowerThanDateStart");
+ $this->errors[] = $this->error;
+ $this->db->rollback();
+ dol_syslog(get_class($this)."::update error -3 ".$this->error, LOG_ERR);
+ return -3;
+ }
- if (dol_strlen(trim($this->ref)) > 0)
- {
- $this->db->begin();
+ if (dol_strlen(trim($this->ref)) > 0)
+ {
+ $this->db->begin();
- $sql = "UPDATE ".MAIN_DB_PREFIX."projet SET";
- $sql .= " ref='".$this->db->escape($this->ref)."'";
- $sql .= ", title = '".$this->db->escape($this->title)."'";
- $sql .= ", description = '".$this->db->escape($this->description)."'";
- $sql .= ", fk_soc = ".($this->socid > 0 ? $this->socid : "null");
- $sql .= ", fk_statut = ".$this->statut;
- $sql .= ", fk_opp_status = ".((is_numeric($this->opp_status) && $this->opp_status > 0) ? $this->opp_status : 'null');
+ $sql = "UPDATE ".MAIN_DB_PREFIX."projet SET";
+ $sql .= " ref='".$this->db->escape($this->ref)."'";
+ $sql .= ", title = '".$this->db->escape($this->title)."'";
+ $sql .= ", description = '".$this->db->escape($this->description)."'";
+ $sql .= ", fk_soc = ".($this->socid > 0 ? $this->socid : "null");
+ $sql .= ", fk_statut = ".$this->statut;
+ $sql .= ", fk_opp_status = ".((is_numeric($this->opp_status) && $this->opp_status > 0) ? $this->opp_status : 'null');
$sql .= ", opp_percent = ".((is_numeric($this->opp_percent) && $this->opp_percent != '') ? $this->opp_percent : 'null');
- $sql .= ", public = ".($this->public ? 1 : 0);
- $sql .= ", datec=".($this->date_c != '' ? "'".$this->db->idate($this->date_c)."'" : 'null');
- $sql .= ", dateo=".($this->date_start != '' ? "'".$this->db->idate($this->date_start)."'" : 'null');
- $sql .= ", datee=".($this->date_end != '' ? "'".$this->db->idate($this->date_end)."'" : 'null');
- $sql .= ", date_close=".($this->date_close != '' ? "'".$this->db->idate($this->date_close)."'" : 'null');
- $sql .= ", fk_user_close=".($this->fk_user_close > 0 ? $this->fk_user_close : "null");
- $sql .= ", opp_amount = ".(strcmp($this->opp_amount, '') ? price2num($this->opp_amount) : "null");
- $sql .= ", budget_amount = ".(strcmp($this->budget_amount, '') ? price2num($this->budget_amount) : "null");
- $sql .= ", fk_user_modif = ".$user->id;
- $sql .= ", usage_opportunity = ".($this->usage_opportunity ? 1 : 0);
- $sql .= ", usage_task = ".($this->usage_task ? 1 : 0);
- $sql .= ", usage_bill_time = ".($this->usage_bill_time ? 1 : 0);
- $sql .= ", usage_organize_event = ".($this->usage_organize_event ? 1 : 0);
- $sql .= " WHERE rowid = ".$this->id;
+ $sql .= ", public = ".($this->public ? 1 : 0);
+ $sql .= ", datec=".($this->date_c != '' ? "'".$this->db->idate($this->date_c)."'" : 'null');
+ $sql .= ", dateo=".($this->date_start != '' ? "'".$this->db->idate($this->date_start)."'" : 'null');
+ $sql .= ", datee=".($this->date_end != '' ? "'".$this->db->idate($this->date_end)."'" : 'null');
+ $sql .= ", date_close=".($this->date_close != '' ? "'".$this->db->idate($this->date_close)."'" : 'null');
+ $sql .= ", fk_user_close=".($this->fk_user_close > 0 ? $this->fk_user_close : "null");
+ $sql .= ", opp_amount = ".(strcmp($this->opp_amount, '') ? price2num($this->opp_amount) : "null");
+ $sql .= ", budget_amount = ".(strcmp($this->budget_amount, '') ? price2num($this->budget_amount) : "null");
+ $sql .= ", fk_user_modif = ".$user->id;
+ $sql .= ", usage_opportunity = ".($this->usage_opportunity ? 1 : 0);
+ $sql .= ", usage_task = ".($this->usage_task ? 1 : 0);
+ $sql .= ", usage_bill_time = ".($this->usage_bill_time ? 1 : 0);
+ $sql .= ", usage_organize_event = ".($this->usage_organize_event ? 1 : 0);
+ $sql .= " WHERE rowid = ".$this->id;
- dol_syslog(get_class($this)."::update", LOG_DEBUG);
- $resql = $this->db->query($sql);
- if ($resql)
- {
- // Update extrafield
- if (!$error)
- {
- if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
- {
- $result = $this->insertExtraFields();
- if ($result < 0)
- {
- $error++;
- }
- }
- }
+ dol_syslog(get_class($this)."::update", LOG_DEBUG);
+ $resql = $this->db->query($sql);
+ if ($resql)
+ {
+ // Update extrafield
+ if (!$error)
+ {
+ if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
+ {
+ $result = $this->insertExtraFields();
+ if ($result < 0)
+ {
+ $error++;
+ }
+ }
+ }
- if (!$error && !$notrigger)
- {
- // Call trigger
- $result = $this->call_trigger('PROJECT_MODIFY', $user);
- if ($result < 0) { $error++; }
- // End call triggers
- }
+ if (!$error && !$notrigger)
+ {
+ // Call trigger
+ $result = $this->call_trigger('PROJECT_MODIFY', $user);
+ if ($result < 0) { $error++; }
+ // End call triggers
+ }
- if (!$error && (is_object($this->oldcopy) && $this->oldcopy->ref !== $this->ref))
- {
- // We remove directory
- if ($conf->projet->dir_output)
- {
- $olddir = $conf->projet->dir_output."/".dol_sanitizeFileName($this->oldcopy->ref);
- $newdir = $conf->projet->dir_output."/".dol_sanitizeFileName($this->ref);
- if (file_exists($olddir))
- {
+ if (!$error && (is_object($this->oldcopy) && $this->oldcopy->ref !== $this->ref))
+ {
+ // We remove directory
+ if ($conf->projet->dir_output)
+ {
+ $olddir = $conf->projet->dir_output."/".dol_sanitizeFileName($this->oldcopy->ref);
+ $newdir = $conf->projet->dir_output."/".dol_sanitizeFileName($this->ref);
+ if (file_exists($olddir))
+ {
include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
$res = @rename($olddir, $newdir);
if (!$res)
- {
- $langs->load("errors");
+ {
+ $langs->load("errors");
$this->error = $langs->trans('ErrorFailToRenameDir', $olddir, $newdir);
- $error++;
- }
- }
- }
- }
- if (!$error)
- {
- $this->db->commit();
- $result = 1;
- }
- else
+ $error++;
+ }
+ }
+ }
+ }
+ if (!$error)
{
- $this->db->rollback();
- $result = -1;
- }
- }
- else
+ $this->db->commit();
+ $result = 1;
+ }
+ else
+ {
+ $this->db->rollback();
+ $result = -1;
+ }
+ }
+ else
{
- $this->error = $this->db->lasterror();
- $this->errors[] = $this->error;
- $this->db->rollback();
- if ($this->db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS')
- {
- $result = -4;
- }
- else
- {
- $result = -2;
- }
- dol_syslog(get_class($this)."::update error ".$result." ".$this->error, LOG_ERR);
- }
- }
- else
- {
- dol_syslog(get_class($this)."::update ref null");
- $result = -1;
- }
+ $this->error = $this->db->lasterror();
+ $this->errors[] = $this->error;
+ $this->db->rollback();
+ if ($this->db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS')
+ {
+ $result = -4;
+ }
+ else
+ {
+ $result = -2;
+ }
+ dol_syslog(get_class($this)."::update error ".$result." ".$this->error, LOG_ERR);
+ }
+ }
+ else
+ {
+ dol_syslog(get_class($this)."::update ref null");
+ $result = -1;
+ }
- return $result;
- }
+ return $result;
+ }
- /**
- * Get object from database
- *
- * @param int $id Id of object to load
- * @param string $ref Ref of project
- * @return int >0 if OK, 0 if not found, <0 if KO
- */
- public function fetch($id, $ref = '')
- {
- global $conf;
+ /**
+ * Get object from database
+ *
+ * @param int $id Id of object to load
+ * @param string $ref Ref of project
+ * @return int >0 if OK, 0 if not found, <0 if KO
+ */
+ public function fetch($id, $ref = '')
+ {
+ global $conf;
- if (empty($id) && empty($ref)) return -1;
+ if (empty($id) && empty($ref)) return -1;
- $sql = "SELECT rowid, ref, title, description, public, datec, opp_amount, budget_amount,";
- $sql .= " tms, dateo, datee, date_close, fk_soc, fk_user_creat, fk_user_modif, fk_user_close, fk_statut, fk_opp_status, opp_percent,";
- $sql .= " note_private, note_public, model_pdf, usage_opportunity, usage_task, usage_bill_time, usage_organize_event, entity";
- $sql .= " FROM ".MAIN_DB_PREFIX."projet";
- if (!empty($id))
- {
- $sql .= " WHERE rowid=".$id;
- }
- elseif (!empty($ref))
- {
- $sql .= " WHERE ref='".$this->db->escape($ref)."'";
- $sql .= " AND entity IN (".getEntity('project').")";
- }
+ $sql = "SELECT rowid, ref, title, description, public, datec, opp_amount, budget_amount,";
+ $sql .= " tms, dateo, datee, date_close, fk_soc, fk_user_creat, fk_user_modif, fk_user_close, fk_statut, fk_opp_status, opp_percent,";
+ $sql .= " note_private, note_public, model_pdf, usage_opportunity, usage_task, usage_bill_time, usage_organize_event, entity";
+ $sql .= " FROM ".MAIN_DB_PREFIX."projet";
+ if (!empty($id))
+ {
+ $sql .= " WHERE rowid=".$id;
+ }
+ elseif (!empty($ref))
+ {
+ $sql .= " WHERE ref='".$this->db->escape($ref)."'";
+ $sql .= " AND entity IN (".getEntity('project').")";
+ }
- dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
- $resql = $this->db->query($sql);
- if ($resql)
- {
- $num_rows = $this->db->num_rows($resql);
+ dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
+ $resql = $this->db->query($sql);
+ if ($resql)
+ {
+ $num_rows = $this->db->num_rows($resql);
- if ($num_rows)
- {
- $obj = $this->db->fetch_object($resql);
+ if ($num_rows)
+ {
+ $obj = $this->db->fetch_object($resql);
- $this->id = $obj->rowid;
- $this->ref = $obj->ref;
- $this->title = $obj->title;
- $this->description = $obj->description;
- $this->date_c = $this->db->jdate($obj->datec);
- $this->datec = $this->db->jdate($obj->datec); // TODO deprecated
- $this->date_m = $this->db->jdate($obj->tms);
- $this->datem = $this->db->jdate($obj->tms); // TODO deprecated
- $this->date_start = $this->db->jdate($obj->dateo);
- $this->date_end = $this->db->jdate($obj->datee);
- $this->date_close = $this->db->jdate($obj->date_close);
- $this->note_private = $obj->note_private;
- $this->note_public = $obj->note_public;
- $this->socid = $obj->fk_soc;
- $this->user_author_id = $obj->fk_user_creat;
- $this->user_modification_id = $obj->fk_user_modif;
- $this->user_close_id = $obj->fk_user_close;
- $this->public = $obj->public;
- $this->statut = $obj->fk_statut;
- $this->opp_status = $obj->fk_opp_status;
- $this->opp_amount = $obj->opp_amount;
- $this->opp_percent = $obj->opp_percent;
- $this->budget_amount = $obj->budget_amount;
- $this->modelpdf = $obj->model_pdf;
- $this->usage_opportunity = (int) $obj->usage_opportunity;
- $this->usage_task = (int) $obj->usage_task;
- $this->usage_bill_time = (int) $obj->usage_bill_time;
- $this->usage_organize_event = (int) $obj->usage_organize_event;
- $this->entity = $obj->entity;
+ $this->id = $obj->rowid;
+ $this->ref = $obj->ref;
+ $this->title = $obj->title;
+ $this->description = $obj->description;
+ $this->date_c = $this->db->jdate($obj->datec);
+ $this->datec = $this->db->jdate($obj->datec); // TODO deprecated
+ $this->date_m = $this->db->jdate($obj->tms);
+ $this->datem = $this->db->jdate($obj->tms); // TODO deprecated
+ $this->date_start = $this->db->jdate($obj->dateo);
+ $this->date_end = $this->db->jdate($obj->datee);
+ $this->date_close = $this->db->jdate($obj->date_close);
+ $this->note_private = $obj->note_private;
+ $this->note_public = $obj->note_public;
+ $this->socid = $obj->fk_soc;
+ $this->user_author_id = $obj->fk_user_creat;
+ $this->user_modification_id = $obj->fk_user_modif;
+ $this->user_close_id = $obj->fk_user_close;
+ $this->public = $obj->public;
+ $this->statut = $obj->fk_statut;
+ $this->opp_status = $obj->fk_opp_status;
+ $this->opp_amount = $obj->opp_amount;
+ $this->opp_percent = $obj->opp_percent;
+ $this->budget_amount = $obj->budget_amount;
+ $this->modelpdf = $obj->model_pdf;
+ $this->usage_opportunity = (int) $obj->usage_opportunity;
+ $this->usage_task = (int) $obj->usage_task;
+ $this->usage_bill_time = (int) $obj->usage_bill_time;
+ $this->usage_organize_event = (int) $obj->usage_organize_event;
+ $this->entity = $obj->entity;
- $this->db->free($resql);
+ $this->db->free($resql);
- // Retreive all extrafield
- // fetch optionals attributes and labels
- $this->fetch_optionals();
+ // Retreive all extrafield
+ // fetch optionals attributes and labels
+ $this->fetch_optionals();
- return 1;
- }
+ return 1;
+ }
- $this->db->free($resql);
+ $this->db->free($resql);
- return 0;
- }
- else
- {
- $this->error = $this->db->lasterror();
- return -1;
- }
- }
+ return 0;
+ }
+ else
+ {
+ $this->error = $this->db->lasterror();
+ return -1;
+ }
+ }
- // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
- /**
- * Return list of elements for type, linked to a project
- *
- * @param string $type 'propal','order','invoice','order_supplier','invoice_supplier',...
- * @param string $tablename name of table associated of the type
- * @param string $datefieldname name of date field for filter
- * @param int $dates Start date
- * @param int $datee End date
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ /**
+ * Return list of elements for type, linked to a project
+ *
+ * @param string $type 'propal','order','invoice','order_supplier','invoice_supplier',...
+ * @param string $tablename name of table associated of the type
+ * @param string $datefieldname name of date field for filter
+ * @param int $dates Start date
+ * @param int $datee End date
* @param string $projectkey Equivalent key to fk_projet for actual type
- * @return mixed Array list of object ids linked to project, < 0 or string if error
- */
- public function get_element_list($type, $tablename, $datefieldname = '', $dates = '', $datee = '', $projectkey = 'fk_projet')
- {
- // phpcs:enable
- $elements = array();
+ * @return mixed Array list of object ids linked to project, < 0 or string if error
+ */
+ public function get_element_list($type, $tablename, $datefieldname = '', $dates = '', $datee = '', $projectkey = 'fk_projet')
+ {
+ // phpcs:enable
+ $elements = array();
- if ($this->id <= 0) return $elements;
+ if ($this->id <= 0) return $elements;
- $ids = $this->id;
+ $ids = $this->id;
if ($type == 'agenda')
- {
- $sql = "SELECT id as rowid FROM ".MAIN_DB_PREFIX."actioncomm WHERE fk_project IN (".$ids.") AND entity IN (".getEntity('agenda').")";
- }
- elseif ($type == 'expensereport')
{
- $sql = "SELECT ed.rowid FROM ".MAIN_DB_PREFIX."expensereport as e, ".MAIN_DB_PREFIX."expensereport_det as ed WHERE e.rowid = ed.fk_expensereport AND e.entity IN (".getEntity('expensereport').") AND ed.fk_projet IN (".$ids.")";
+ $sql = "SELECT id as rowid FROM ".MAIN_DB_PREFIX."actioncomm WHERE fk_project IN (".$ids.") AND entity IN (".getEntity('agenda').")";
}
- elseif ($type == 'project_task')
+ elseif ($type == 'expensereport')
+ {
+ $sql = "SELECT ed.rowid FROM ".MAIN_DB_PREFIX."expensereport as e, ".MAIN_DB_PREFIX."expensereport_det as ed WHERE e.rowid = ed.fk_expensereport AND e.entity IN (".getEntity('expensereport').") AND ed.fk_projet IN (".$ids.")";
+ }
+ elseif ($type == 'project_task')
{
$sql = "SELECT DISTINCT pt.rowid FROM ".MAIN_DB_PREFIX."projet_task as pt WHERE pt.fk_projet IN (".$ids.")";
}
@@ -607,18 +607,18 @@ class Project extends CommonObject
{
$sql = 'SELECT ms.rowid, ms.fk_user_author as fk_user FROM '.MAIN_DB_PREFIX."stock_mouvement as ms, ".MAIN_DB_PREFIX."entrepot as e WHERE e.rowid = ms.fk_entrepot AND e.entity IN (".getEntity('stock').") AND ms.origintype = 'project' AND ms.fk_origin IN (".$ids.") AND ms.type_mouvement = 1";
}
- elseif ($type == 'loan')
- {
- $sql = 'SELECT l.rowid, l.fk_user_author as fk_user FROM '.MAIN_DB_PREFIX."loan as l WHERE l.entity IN (".getEntity('loan').") AND l.fk_projet IN (".$ids.")";
- }
- else
+ elseif ($type == 'loan')
{
- $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX.$tablename." WHERE ".$projectkey." IN (".$ids.") AND entity IN (".getEntity($type).")";
- }
+ $sql = 'SELECT l.rowid, l.fk_user_author as fk_user FROM '.MAIN_DB_PREFIX."loan as l WHERE l.entity IN (".getEntity('loan').") AND l.fk_projet IN (".$ids.")";
+ }
+ else
+ {
+ $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX.$tablename." WHERE ".$projectkey." IN (".$ids.") AND entity IN (".getEntity($type).")";
+ }
- if($dates > 0 && $type == 'loan'){
- $sql .= " AND (dateend > '".$this->db->idate($dates)."' OR dateend IS NULL)";
- }
+ if($dates > 0 && $type == 'loan'){
+ $sql .= " AND (dateend > '".$this->db->idate($dates)."' OR dateend IS NULL)";
+ }
elseif ($dates > 0 && ($type != 'project_task')) // For table project_taks, we want the filter on date apply on project_time_spent table
{
if (empty($datefieldname) && !empty($this->table_element_date)) $datefieldname = $this->table_element_date;
@@ -626,10 +626,10 @@ class Project extends CommonObject
$sql .= " AND (".$datefieldname." >= '".$this->db->idate($dates)."' OR ".$datefieldname." IS NULL)";
}
- if($datee > 0 && $type == 'loan'){
- $sql .= " AND (datestart < '".$this->db->idate($datee)."' OR datestart IS NULL)";
- }
- elseif ($datee > 0 && ($type != 'project_task')) // For table project_taks, we want the filter on date apply on project_time_spent table
+ if($datee > 0 && $type == 'loan'){
+ $sql .= " AND (datestart < '".$this->db->idate($datee)."' OR datestart IS NULL)";
+ }
+ elseif ($datee > 0 && ($type != 'project_task')) // For table project_taks, we want the filter on date apply on project_time_spent table
{
if (empty($datefieldname) && !empty($this->table_element_date)) $datefieldname = $this->table_element_date;
if (empty($datefieldname)) return 'Error this object has no date field defined';
@@ -637,94 +637,94 @@ class Project extends CommonObject
}
if (!$sql) return -1;
- //print $sql;
- dol_syslog(get_class($this)."::get_element_list", LOG_DEBUG);
- $result = $this->db->query($sql);
- if ($result)
- {
- $nump = $this->db->num_rows($result);
- if ($nump)
- {
- $i = 0;
- while ($i < $nump)
- {
- $obj = $this->db->fetch_object($result);
+ //print $sql;
+ dol_syslog(get_class($this)."::get_element_list", LOG_DEBUG);
+ $result = $this->db->query($sql);
+ if ($result)
+ {
+ $nump = $this->db->num_rows($result);
+ if ($nump)
+ {
+ $i = 0;
+ while ($i < $nump)
+ {
+ $obj = $this->db->fetch_object($result);
- $elements[$i] = $obj->rowid.(empty($obj->fk_user) ? '' : '_'.$obj->fk_user);
+ $elements[$i] = $obj->rowid.(empty($obj->fk_user) ? '' : '_'.$obj->fk_user);
- $i++;
- }
- $this->db->free($result);
- }
+ $i++;
+ }
+ $this->db->free($result);
+ }
- /* Return array even if empty*/
- return $elements;
- }
- else
- {
- dol_print_error($this->db);
- }
- }
+ /* Return array even if empty*/
+ return $elements;
+ }
+ else
+ {
+ dol_print_error($this->db);
+ }
+ }
- /**
- * Delete a project from database
- *
- * @param User $user User
- * @param int $notrigger Disable triggers
- * @return int <0 if KO, 0 if not possible, >0 if OK
- */
- public function delete($user, $notrigger = 0)
- {
- global $langs, $conf;
- require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
+ /**
+ * Delete a project from database
+ *
+ * @param User $user User
+ * @param int $notrigger Disable triggers
+ * @return int <0 if KO, 0 if not possible, >0 if OK
+ */
+ public function delete($user, $notrigger = 0)
+ {
+ global $langs, $conf;
+ require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
- $error = 0;
+ $error = 0;
- $this->db->begin();
+ $this->db->begin();
- if (!$error)
- {
- // Delete linked contacts
- $res = $this->delete_linked_contact();
- if ($res < 0)
- {
- $this->error = 'ErrorFailToDeleteLinkedContact';
- //$error++;
- $this->db->rollback();
- return 0;
- }
- }
+ if (!$error)
+ {
+ // Delete linked contacts
+ $res = $this->delete_linked_contact();
+ if ($res < 0)
+ {
+ $this->error = 'ErrorFailToDeleteLinkedContact';
+ //$error++;
+ $this->db->rollback();
+ return 0;
+ }
+ }
- // Set fk_projet into elements to null
- $listoftables = array(
- 'propal'=>'fk_projet', 'commande'=>'fk_projet', 'facture'=>'fk_projet',
- 'supplier_proposal'=>'fk_projet', 'commande_fournisseur'=>'fk_projet', 'facture_fourn'=>'fk_projet',
- 'expensereport_det'=>'fk_projet', 'contrat'=>'fk_projet', 'fichinter'=>'fk_projet', 'don'=>'fk_projet',
- 'actioncomm'=>'fk_project'
- );
- foreach ($listoftables as $key => $value)
- {
- $sql = "UPDATE ".MAIN_DB_PREFIX.$key." SET ".$value." = NULL where ".$value." = ".$this->id;
- $resql = $this->db->query($sql);
- if (!$resql)
- {
- $this->errors[] = $this->db->lasterror();
- $error++;
- break;
- }
- }
+ // Set fk_projet into elements to null
+ $listoftables = array(
+ 'propal'=>'fk_projet', 'commande'=>'fk_projet', 'facture'=>'fk_projet',
+ 'supplier_proposal'=>'fk_projet', 'commande_fournisseur'=>'fk_projet', 'facture_fourn'=>'fk_projet',
+ 'expensereport_det'=>'fk_projet', 'contrat'=>'fk_projet', 'fichinter'=>'fk_projet', 'don'=>'fk_projet',
+ 'actioncomm'=>'fk_project'
+ );
+ foreach ($listoftables as $key => $value)
+ {
+ $sql = "UPDATE ".MAIN_DB_PREFIX.$key." SET ".$value." = NULL where ".$value." = ".$this->id;
+ $resql = $this->db->query($sql);
+ if (!$resql)
+ {
+ $this->errors[] = $this->db->lasterror();
+ $error++;
+ break;
+ }
+ }
- // Remove linked categories.
- if (!$error) {
- $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_project";
- $sql .= " WHERE fk_project = ".$this->id;
+ // Remove linked categories.
+ if (!$error) {
+ $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_project";
+ $sql .= " WHERE fk_project = ".$this->id;
- $result = $this->db->query($sql);
- if (!$result) {
- $error++;
- $this->errors[] = $this->db->lasterror();
- }
- }
+ $result = $this->db->query($sql);
+ if (!$result) {
+ $error++;
+ $this->errors[] = $this->db->lasterror();
+ }
+ }
// Fetch tasks
$this->getLinesArray($user);
@@ -754,575 +754,577 @@ class Project extends CommonObject
- // Delete project
- if (!$error)
- {
- $sql = "DELETE FROM ".MAIN_DB_PREFIX."projet";
- $sql .= " WHERE rowid=".$this->id;
+ // Delete project
+ if (!$error)
+ {
+ $sql = "DELETE FROM ".MAIN_DB_PREFIX."projet";
+ $sql .= " WHERE rowid=".$this->id;
- $resql = $this->db->query($sql);
- if (!$resql)
- {
- $this->errors[] = $langs->trans("CantRemoveProject");
- $error++;
- }
- }
+ $resql = $this->db->query($sql);
+ if (!$resql)
+ {
+ $this->errors[] = $langs->trans("CantRemoveProject");
+ $error++;
+ }
+ }
- if (!$error)
- {
- $sql = "DELETE FROM ".MAIN_DB_PREFIX."projet_extrafields";
- $sql .= " WHERE fk_object=".$this->id;
+ if (!$error)
+ {
+ $sql = "DELETE FROM ".MAIN_DB_PREFIX."projet_extrafields";
+ $sql .= " WHERE fk_object=".$this->id;
- $resql = $this->db->query($sql);
- if (!$resql)
- {
- $this->errors[] = $this->db->lasterror();
- $error++;
- }
- }
+ $resql = $this->db->query($sql);
+ if (!$resql)
+ {
+ $this->errors[] = $this->db->lasterror();
+ $error++;
+ }
+ }
- if (empty($error)) {
- // We remove directory
- $projectref = dol_sanitizeFileName($this->ref);
- if ($conf->projet->dir_output) {
- $dir = $conf->projet->dir_output."/".$projectref;
- if (file_exists($dir)) {
- $res = @dol_delete_dir_recursive($dir);
- if (!$res) {
- $this->errors[] = 'ErrorFailToDeleteDir';
- $error++;
- }
- }
- }
+ if (empty($error)) {
+ // We remove directory
+ $projectref = dol_sanitizeFileName($this->ref);
+ if ($conf->projet->dir_output) {
+ $dir = $conf->projet->dir_output."/".$projectref;
+ if (file_exists($dir)) {
+ $res = @dol_delete_dir_recursive($dir);
+ if (!$res) {
+ $this->errors[] = 'ErrorFailToDeleteDir';
+ $error++;
+ }
+ }
+ }
- if (!$notrigger)
- {
- // Call trigger
- $result = $this->call_trigger('PROJECT_DELETE', $user);
+ if (!$notrigger)
+ {
+ // Call trigger
+ $result = $this->call_trigger('PROJECT_DELETE', $user);
- if ($result < 0) {
- $error++;
- }
- // End call triggers
- }
- }
+ if ($result < 0) {
+ $error++;
+ }
+ // End call triggers
+ }
+ }
- if (empty($error))
- {
- $this->db->commit();
- return 1;
- }
- else
- {
- foreach ($this->errors as $errmsg)
- {
+ if (empty($error))
+ {
+ $this->db->commit();
+ return 1;
+ }
+ else
+ {
+ foreach ($this->errors as $errmsg)
+ {
dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
$this->error .= ($this->error ? ', '.$errmsg : $errmsg);
}
- dol_syslog(get_class($this)."::delete ".$this->error, LOG_ERR);
- $this->db->rollback();
- return -1;
- }
- }
+ dol_syslog(get_class($this)."::delete ".$this->error, LOG_ERR);
+ $this->db->rollback();
+ return -1;
+ }
+ }
- /**
- * Delete tasks with no children first, then task with children recursively
- *
- * @param User $user User
- * @return int <0 if KO, 1 if OK
- */
- public function deleteTasks($user)
- {
- $countTasks = count($this->lines);
- $deleted = false;
- if ($countTasks)
- {
- foreach ($this->lines as $task)
- {
- if ($task->hasChildren() <= 0) { // If there is no children (or error to detect them)
- $deleted = true;
- $ret = $task->delete($user);
- if ($ret <= 0)
- {
- $this->errors[] = $this->db->lasterror();
- return -1;
- }
- }
- }
- }
- $this->getLinesArray($user);
- if ($deleted && count($this->lines) < $countTasks)
- {
- if (count($this->lines)) $this->deleteTasks($this->lines);
- }
-
- return 1;
- }
-
- /**
- * Validate a project
- *
- * @param User $user User that validate
- * @param int $notrigger 1=Disable triggers
- * @return int <0 if KO, >0 if OK
- */
- public function setValid($user, $notrigger = 0)
- {
- global $langs, $conf;
-
- $error = 0;
-
- if ($this->statut != 1)
- {
- // Check parameters
- if (preg_match('/^'.preg_quote($langs->trans("CopyOf").' ').'/', $this->title))
- {
- $this->error = $langs->trans("ErrorFieldFormat", $langs->transnoentities("Label")).'. '.$langs->trans('RemoveString', $langs->transnoentitiesnoconv("CopyOf"));
- return -1;
- }
-
- $this->db->begin();
-
- $sql = "UPDATE ".MAIN_DB_PREFIX."projet";
- $sql .= " SET fk_statut = 1";
- $sql .= " WHERE rowid = ".$this->id;
- $sql .= " AND entity = ".$conf->entity;
-
- dol_syslog(get_class($this)."::setValid", LOG_DEBUG);
- $resql = $this->db->query($sql);
- if ($resql)
- {
- // Call trigger
- if (empty($notrigger))
- {
- $result = $this->call_trigger('PROJECT_VALIDATE', $user);
- if ($result < 0) { $error++; }
- // End call triggers
- }
-
- if (!$error)
- {
- $this->statut = 1;
- $this->db->commit();
- return 1;
- }
- else
- {
- $this->db->rollback();
- $this->error = join(',', $this->errors);
- dol_syslog(get_class($this)."::setValid ".$this->error, LOG_ERR);
- return -1;
- }
- }
- else
- {
- $this->db->rollback();
- $this->error = $this->db->lasterror();
- return -1;
- }
- }
- }
-
- /**
- * Close a project
- *
- * @param User $user User that close project
- * @return int <0 if KO, 0 if already closed, >0 if OK
- */
- public function setClose($user)
- {
- global $langs, $conf;
-
- $now = dol_now();
-
- $error = 0;
-
- if ($this->statut != 2)
- {
- $this->db->begin();
-
- $sql = "UPDATE ".MAIN_DB_PREFIX."projet";
- $sql .= " SET fk_statut = 2, fk_user_close = ".$user->id.", date_close = '".$this->db->idate($now)."'";
- $sql .= " WHERE rowid = ".$this->id;
- $sql .= " AND entity = ".$conf->entity;
- $sql .= " AND fk_statut = 1";
-
- if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES))
- {
- // TODO What to do if fk_opp_status is not code 'WON' or 'LOST'
- }
-
- dol_syslog(get_class($this)."::setClose", LOG_DEBUG);
- $resql = $this->db->query($sql);
- if ($resql)
- {
- // Call trigger
- $result = $this->call_trigger('PROJECT_CLOSE', $user);
- if ($result < 0) { $error++; }
- // End call triggers
-
- if (!$error)
- {
- $this->statut = 2;
- $this->db->commit();
- return 1;
- }
- else
- {
- $this->db->rollback();
- $this->error = join(',', $this->errors);
- dol_syslog(get_class($this)."::setClose ".$this->error, LOG_ERR);
- return -1;
- }
- }
- else
- {
- $this->db->rollback();
- $this->error = $this->db->lasterror();
- return -1;
- }
- }
-
- return 0;
- }
-
- /**
- * Return status label of object
- *
- * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
- * @return string Label
- */
- public function getLibStatut($mode = 0)
- {
- return $this->LibStatut($this->statut, $mode);
- }
-
- // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
- /**
- * Renvoi status label for a status
- *
- * @param int $status id status
- * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
- * @return string Label
- */
- public function LibStatut($status, $mode = 0)
- {
- // phpcs:enable
- global $langs;
-
- $statustrans = array(
- 0 => 'status0',
- 1 => 'status4',
- 2 => 'status6',
- );
-
- $statusClass = 'status0';
- if (!empty($statustrans[$status])) {
- $statusClass = $statustrans[$status];
- }
-
- return dolGetStatus($langs->trans($this->statuts_long[$status]), $langs->trans($this->statuts_short[$status]), '', $statusClass, $mode);
- }
-
- /**
- * Return clicable name (with picto eventually)
- *
- * @param int $withpicto 0=No picto, 1=Include picto into link, 2=Only picto
- * @param string $option Variant ('', 'nolink')
- * @param int $addlabel 0=Default, 1=Add label into string, >1=Add first chars into string
- * @param string $moreinpopup Text to add into popup
- * @param string $sep Separator between ref and label if option addlabel is set
- * @param int $notooltip 1=Disable tooltip
- * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
- * @return string String with URL
- */
- public function getNomUrl($withpicto = 0, $option = '', $addlabel = 0, $moreinpopup = '', $sep = ' - ', $notooltip = 0, $save_lastsearch_value = -1)
- {
- global $conf, $langs, $user, $hookmanager;
-
- if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips
-
- $result = '';
-
- $label = '';
- if ($option != 'nolink') $label = ''.$langs->trans("ShowProject").'';
- $label .= ($label ? '
' : '').''.$langs->trans('Ref').': '.$this->ref; // The space must be after the : to not being explode when showing the title in img_picto
- $label .= ($label ? '
' : '').''.$langs->trans('Label').': '.$this->title; // The space must be after the : to not being explode when showing the title in img_picto
- if (!empty($this->thirdparty_name))
- $label .= ($label ? '
' : '').''.$langs->trans('ThirdParty').': '.$this->thirdparty_name; // The space must be after the : to not being explode when showing the title in img_picto
- if (!empty($this->dateo))
- $label .= ($label ? '
' : '').''.$langs->trans('DateStart').': '.dol_print_date($this->dateo, 'day'); // The space must be after the : to not being explode when showing the title in img_picto
- if (!empty($this->datee))
- $label .= ($label ? '
' : '').''.$langs->trans('DateEnd').': '.dol_print_date($this->datee, 'day'); // The space must be after the : to not being explode when showing the title in img_picto
- if ($moreinpopup) $label .= '
'.$moreinpopup;
-
- $url = '';
- if ($option != 'nolink')
- {
- if (preg_match('/\.php$/', $option)) {
- $url = dol_buildpath($option, 1).'?id='.$this->id;
- }
- elseif ($option == 'task')
- {
- $url = DOL_URL_ROOT.'/projet/tasks.php?id='.$this->id;
- }
- else
- {
- $url = DOL_URL_ROOT.'/projet/card.php?id='.$this->id;
- }
- // Add param to save lastsearch_values or not
- $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
- if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) $add_save_lastsearch_values = 1;
- if ($add_save_lastsearch_values) $url .= '&save_lastsearch_values=1';
- }
-
- $linkclose = '';
- if (empty($notooltip) && $user->rights->projet->lire)
- {
- if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
- {
- $label = $langs->trans("ShowProject");
- $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
- }
- $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
- $linkclose .= ' class="classfortooltip"';
-
- /*
- $hookmanager->initHooks(array('projectdao'));
- $parameters=array('id'=>$this->id);
- // Note that $action and $object may have been modified by some hooks
- $reshook=$hookmanager->executeHooks('getnomurltooltip',$parameters,$this,$action);
- if ($reshook > 0)
- $linkclose = $hookmanager->resPrint;
- */
+ /**
+ * Delete tasks with no children first, then task with children recursively
+ *
+ * @param User $user User
+ * @return int <0 if KO, 1 if OK
+ */
+ public function deleteTasks($user)
+ {
+ $countTasks = count($this->lines);
+ $deleted = false;
+ if ($countTasks)
+ {
+ foreach ($this->lines as $task)
+ {
+ if ($task->hasChildren() <= 0) { // If there is no children (or error to detect them)
+ $deleted = true;
+ $ret = $task->delete($user);
+ if ($ret <= 0)
+ {
+ $this->errors[] = $this->db->lasterror();
+ return -1;
+ }
+ }
+ }
+ }
+ $this->getLinesArray($user);
+ if ($deleted && count($this->lines) < $countTasks)
+ {
+ if (count($this->lines)) $this->deleteTasks($this->lines);
}
- $picto = 'projectpub';
- if (!$this->public) $picto = 'project';
+ return 1;
+ }
- $linkstart = '';
- $linkend = '';
+ /**
+ * Validate a project
+ *
+ * @param User $user User that validate
+ * @param int $notrigger 1=Disable triggers
+ * @return int <0 if KO, >0 if OK
+ */
+ public function setValid($user, $notrigger = 0)
+ {
+ global $langs, $conf;
- $result .= $linkstart;
- if ($withpicto) $result .= img_object(($notooltip ? '' : $label), $picto, ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
- if ($withpicto != 2) $result .= $this->ref;
- $result .= $linkend;
- if ($withpicto != 2) $result .= (($addlabel && $this->title) ? $sep.dol_trunc($this->title, ($addlabel > 1 ? $addlabel : 0)) : '');
+ $error = 0;
- global $action;
- $hookmanager->initHooks(array('projectdao'));
- $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
- $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
- if ($reshook > 0) $result = $hookmanager->resPrint;
- else $result .= $hookmanager->resPrint;
-
- return $result;
- }
-
- /**
- * Initialise an instance with random values.
- * Used to build previews or test instances.
- * id must be 0 if object instance is a specimen.
- *
- * @return void
- */
- public function initAsSpecimen()
- {
- global $user, $langs, $conf;
-
- $now = dol_now();
-
- // Initialise parameters
- $this->id = 0;
- $this->ref = 'SPECIMEN';
- $this->specimen = 1;
- $this->socid = 1;
- $this->date_c = $now;
- $this->date_m = $now;
- $this->date_start = $now;
- $this->date_end = $now + (3600 * 24 * 365);
- $this->note_public = 'SPECIMEN';
- $this->fk_ele = 20000;
- $this->opp_amount = 20000;
- $this->budget_amount = 10000;
-
- $this->usage_opportunity = 1;
- $this->usage_task = 1;
- $this->usage_bill_time = 1;
- $this->usage_organize_event = 1;
-
- /*
- $nbp = mt_rand(1, 9);
- $xnbp = 0;
- while ($xnbp < $nbp)
- {
- $line = new Task($this->db);
- $line->fk_project = 0;
- $line->label = $langs->trans("Label") . " " . $xnbp;
- $line->description = $langs->trans("Description") . " " . $xnbp;
-
- $this->lines[]=$line;
- $xnbp++;
- }
- */
- }
-
- /**
- * Check if user has permission on current project
- *
- * @param User $user Object user to evaluate
- * @param string $mode Type of permission we want to know: 'read', 'write'
- * @return int >0 if user has permission, <0 if user has no permission
- */
- public function restrictedProjectArea($user, $mode = 'read')
- {
- // To verify role of users
- $userAccess = 0;
- if (($mode == 'read' && !empty($user->rights->projet->all->lire)) || ($mode == 'write' && !empty($user->rights->projet->all->creer)) || ($mode == 'delete' && !empty($user->rights->projet->all->supprimer)))
- {
- $userAccess = 1;
- }
- elseif ($this->public && (($mode == 'read' && !empty($user->rights->projet->lire)) || ($mode == 'write' && !empty($user->rights->projet->creer)) || ($mode == 'delete' && !empty($user->rights->projet->supprimer))))
- {
- $userAccess = 1;
- }
- else
+ if ($this->statut != 1)
{
- foreach (array('internal', 'external') as $source)
- {
- $userRole = $this->liste_contact(4, $source);
- $num = count($userRole);
+ // Check parameters
+ if (preg_match('/^'.preg_quote($langs->trans("CopyOf").' ').'/', $this->title))
+ {
+ $this->error = $langs->trans("ErrorFieldFormat", $langs->transnoentities("Label")).'. '.$langs->trans('RemoveString', $langs->transnoentitiesnoconv("CopyOf"));
+ return -1;
+ }
- $nblinks = 0;
- while ($nblinks < $num)
- {
- if ($source == 'internal' && preg_match('/^PROJECT/', $userRole[$nblinks]['code']) && $user->id == $userRole[$nblinks]['id'])
- {
- if ($mode == 'read' && $user->rights->projet->lire) $userAccess++;
- if ($mode == 'write' && $user->rights->projet->creer) $userAccess++;
- if ($mode == 'delete' && $user->rights->projet->supprimer) $userAccess++;
- }
- $nblinks++;
- }
- }
- //if (empty($nblinks)) // If nobody has permission, we grant creator
- //{
- // if ((!empty($this->user_author_id) && $this->user_author_id == $user->id))
- // {
- // $userAccess = 1;
- // }
- //}
- }
+ $this->db->begin();
- return ($userAccess ? $userAccess : -1);
- }
+ $sql = "UPDATE ".MAIN_DB_PREFIX."projet";
+ $sql .= " SET fk_statut = 1";
+ $sql .= " WHERE rowid = ".$this->id;
+ $sql .= " AND entity = ".$conf->entity;
- /**
- * Return array of projects a user has permission on, is affected to, or all projects
- *
- * @param User $user User object
- * @param int $mode 0=All project I have permission on (assigned to me or public), 1=Projects assigned to me only, 2=Will return list of all projects with no test on contacts
- * @param int $list 0=Return array, 1=Return string list
- * @param int $socid 0=No filter on third party, id of third party
- * @param string $filter additionnal filter on project (statut, ref, ...)
- * @return array or string Array of projects id, or string with projects id separated with "," if list is 1
- */
- public function getProjectsAuthorizedForUser($user, $mode = 0, $list = 0, $socid = 0, $filter = '')
- {
- $projects = array();
- $temp = array();
+ dol_syslog(get_class($this)."::setValid", LOG_DEBUG);
+ $resql = $this->db->query($sql);
+ if ($resql)
+ {
+ // Call trigger
+ if (empty($notrigger))
+ {
+ $result = $this->call_trigger('PROJECT_VALIDATE', $user);
+ if ($result < 0) { $error++; }
+ // End call triggers
+ }
- $sql = "SELECT ".(($mode == 0 || $mode == 1) ? "DISTINCT " : "")."p.rowid, p.ref";
- $sql.= " FROM " . MAIN_DB_PREFIX . "projet as p";
- if ($mode == 0)
- {
- $sql.= " LEFT JOIN " . MAIN_DB_PREFIX . "element_contact as ec ON ec.element_id = p.rowid";
- }
- elseif ($mode == 1)
- {
- $sql.= ", " . MAIN_DB_PREFIX . "element_contact as ec";
- }
- elseif ($mode == 2)
- {
- // No filter. Use this if user has permission to see all project
- }
- $sql.= " WHERE p.entity IN (".getEntity('project').")";
- // Internal users must see project he is contact to even if project linked to a third party he can't see.
- //if ($socid || ! $user->rights->societe->client->voir) $sql.= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")";
- if ($socid > 0) $sql.= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = " . $socid . ")";
+ if (!$error)
+ {
+ $this->statut = 1;
+ $this->db->commit();
+ return 1;
+ }
+ else
+ {
+ $this->db->rollback();
+ $this->error = join(',', $this->errors);
+ dol_syslog(get_class($this)."::setValid ".$this->error, LOG_ERR);
+ return -1;
+ }
+ }
+ else
+ {
+ $this->db->rollback();
+ $this->error = $this->db->lasterror();
+ return -1;
+ }
+ }
+ }
- // Get id of types of contacts for projects (This list never contains a lot of elements)
- $listofprojectcontacttype=array();
- $sql2 = "SELECT ctc.rowid, ctc.code FROM ".MAIN_DB_PREFIX."c_type_contact as ctc";
- $sql2.= " WHERE ctc.element = '" . $this->db->escape($this->element) . "'";
- $sql2.= " AND ctc.source = 'internal'";
- $resql = $this->db->query($sql2);
- if ($resql)
- {
- while($obj = $this->db->fetch_object($resql))
- {
- $listofprojectcontacttype[$obj->rowid]=$obj->code;
- }
- }
- else dol_print_error($this->db);
- if (count($listofprojectcontacttype) == 0) $listofprojectcontacttype[0]='0'; // To avoid syntax error if not found
+ /**
+ * Close a project
+ *
+ * @param User $user User that close project
+ * @return int <0 if KO, 0 if already closed, >0 if OK
+ */
+ public function setClose($user)
+ {
+ global $langs, $conf;
- if ($mode == 0)
- {
- $sql.= " AND ( p.public = 1";
- $sql.= " OR ( ec.fk_c_type_contact IN (".join(',', array_keys($listofprojectcontacttype)).")";
- $sql.= " AND ec.fk_socpeople = ".$user->id.")";
- $sql.= " )";
- }
- elseif ($mode == 1)
- {
- $sql.= " AND ec.element_id = p.rowid";
- $sql.= " AND (";
- $sql.= " ( ec.fk_c_type_contact IN (".join(',', array_keys($listofprojectcontacttype)).")";
- $sql.= " AND ec.fk_socpeople = ".$user->id.")";
- $sql.= " )";
- }
- elseif ($mode == 2)
- {
- // No filter. Use this if user has permission to see all project
- }
+ $now = dol_now();
+
+ $error = 0;
+
+ if ($this->statut != self::STATUS_CLOSED)
+ {
+ $this->db->begin();
+
+ $sql = "UPDATE ".MAIN_DB_PREFIX."projet";
+ $sql .= " SET fk_statut = ".self::STATUS_CLOSED.", fk_user_close = ".$user->id.", date_close = '".$this->db->idate($now)."'";
+ $sql .= " WHERE rowid = ".$this->id;
+ $sql .= " AND fk_statut = ".self::STATUS_VALIDATED;
+
+ if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES))
+ {
+ // TODO What to do if fk_opp_status is not code 'WON' or 'LOST'
+ }
+
+ dol_syslog(get_class($this)."::setClose", LOG_DEBUG);
+ $resql = $this->db->query($sql);
+ if ($resql)
+ {
+ // Call trigger
+ $result = $this->call_trigger('PROJECT_CLOSE', $user);
+ if ($result < 0) { $error++; }
+ // End call triggers
+
+ if (!$error)
+ {
+ $this->statut = 2;
+ $this->db->commit();
+ return 1;
+ }
+ else
+ {
+ $this->db->rollback();
+ $this->error = join(',', $this->errors);
+ dol_syslog(get_class($this)."::setClose ".$this->error, LOG_ERR);
+ return -1;
+ }
+ }
+ else
+ {
+ $this->db->rollback();
+ $this->error = $this->db->lasterror();
+ return -1;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Return status label of object
+ *
+ * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
+ * @return string Label
+ */
+ public function getLibStatut($mode = 0)
+ {
+ return $this->LibStatut($this->statut, $mode);
+ }
+
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ /**
+ * Renvoi status label for a status
+ *
+ * @param int $status id status
+ * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
+ * @return string Label
+ */
+ public function LibStatut($status, $mode = 0)
+ {
+ // phpcs:enable
+ global $langs;
+
+ $statustrans = array(
+ 0 => 'status0',
+ 1 => 'status4',
+ 2 => 'status6',
+ );
+
+ $statusClass = 'status0';
+ if (!empty($statustrans[$status])) {
+ $statusClass = $statustrans[$status];
+ }
+
+ return dolGetStatus($langs->trans($this->statuts_long[$status]), $langs->trans($this->statuts_short[$status]), '', $statusClass, $mode);
+ }
+
+ /**
+ * Return clicable name (with picto eventually)
+ *
+ * @param int $withpicto 0=No picto, 1=Include picto into link, 2=Only picto
+ * @param string $option Variant ('', 'nolink')
+ * @param int $addlabel 0=Default, 1=Add label into string, >1=Add first chars into string
+ * @param string $moreinpopup Text to add into popup
+ * @param string $sep Separator between ref and label if option addlabel is set
+ * @param int $notooltip 1=Disable tooltip
+ * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
+ * @return string String with URL
+ */
+ public function getNomUrl($withpicto = 0, $option = '', $addlabel = 0, $moreinpopup = '', $sep = ' - ', $notooltip = 0, $save_lastsearch_value = -1)
+ {
+ global $conf, $langs, $user, $hookmanager;
+
+ if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips
+
+ $result = '';
+
+ $label = '';
+ if ($option != 'nolink') $label = ''.$langs->trans("ShowProject").'';
+ $label .= ($label ? '
' : '').''.$langs->trans('Ref').': '.$this->ref; // The space must be after the : to not being explode when showing the title in img_picto
+ $label .= ($label ? '
' : '').''.$langs->trans('Label').': '.$this->title; // The space must be after the : to not being explode when showing the title in img_picto
+ if (!empty($this->thirdparty_name)) {
+ $label .= ($label ? '
' : '').''.$langs->trans('ThirdParty').': '.$this->thirdparty_name; // The space must be after the : to not being explode when showing the title in img_picto
+ }
+ if (!empty($this->dateo)) {
+ $label .= ($label ? '
' : '').''.$langs->trans('DateStart').': '.dol_print_date($this->dateo, 'day'); // The space must be after the : to not being explode when showing the title in img_picto
+ }
+ if (!empty($this->datee)) {
+ $label .= ($label ? '
' : '').''.$langs->trans('DateEnd').': '.dol_print_date($this->datee, 'day'); // The space must be after the : to not being explode when showing the title in img_picto
+ }
+ if ($moreinpopup) $label .= '
'.$moreinpopup;
+
+ $url = '';
+ if ($option != 'nolink')
+ {
+ if (preg_match('/\.php$/', $option)) {
+ $url = dol_buildpath($option, 1).'?id='.$this->id;
+ }
+ elseif ($option == 'task')
+ {
+ $url = DOL_URL_ROOT.'/projet/tasks.php?id='.$this->id;
+ }
+ else
+ {
+ $url = DOL_URL_ROOT.'/projet/card.php?id='.$this->id;
+ }
+ // Add param to save lastsearch_values or not
+ $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
+ if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) $add_save_lastsearch_values = 1;
+ if ($add_save_lastsearch_values) $url .= '&save_lastsearch_values=1';
+ }
+
+ $linkclose = '';
+ if (empty($notooltip) && $user->rights->projet->lire)
+ {
+ if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
+ {
+ $label = $langs->trans("ShowProject");
+ $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
+ }
+ $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
+ $linkclose .= ' class="classfortooltip"';
+
+ /*
+ $hookmanager->initHooks(array('projectdao'));
+ $parameters=array('id'=>$this->id);
+ // Note that $action and $object may have been modified by some hooks
+ $reshook=$hookmanager->executeHooks('getnomurltooltip',$parameters,$this,$action);
+ if ($reshook > 0)
+ $linkclose = $hookmanager->resPrint;
+ */
+ }
+
+ $picto = 'projectpub';
+ if (!$this->public) $picto = 'project';
+
+ $linkstart = '';
+ $linkend = '';
+
+ $result .= $linkstart;
+ if ($withpicto) $result .= img_object(($notooltip ? '' : $label), $picto, ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
+ if ($withpicto != 2) $result .= $this->ref;
+ $result .= $linkend;
+ if ($withpicto != 2) $result .= (($addlabel && $this->title) ? $sep.dol_trunc($this->title, ($addlabel > 1 ? $addlabel : 0)) : '');
+
+ global $action;
+ $hookmanager->initHooks(array('projectdao'));
+ $parameters = array('id'=>$this->id, 'getnomurl'=>$result);
+ $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
+ if ($reshook > 0) $result = $hookmanager->resPrint;
+ else $result .= $hookmanager->resPrint;
+
+ return $result;
+ }
+
+ /**
+ * Initialise an instance with random values.
+ * Used to build previews or test instances.
+ * id must be 0 if object instance is a specimen.
+ *
+ * @return void
+ */
+ public function initAsSpecimen()
+ {
+ global $user, $langs, $conf;
+
+ $now = dol_now();
+
+ // Initialise parameters
+ $this->id = 0;
+ $this->ref = 'SPECIMEN';
+ $this->specimen = 1;
+ $this->socid = 1;
+ $this->date_c = $now;
+ $this->date_m = $now;
+ $this->date_start = $now;
+ $this->date_end = $now + (3600 * 24 * 365);
+ $this->note_public = 'SPECIMEN';
+ $this->fk_ele = 20000;
+ $this->opp_amount = 20000;
+ $this->budget_amount = 10000;
+
+ $this->usage_opportunity = 1;
+ $this->usage_task = 1;
+ $this->usage_bill_time = 1;
+ $this->usage_organize_event = 1;
+
+ /*
+ $nbp = mt_rand(1, 9);
+ $xnbp = 0;
+ while ($xnbp < $nbp)
+ {
+ $line = new Task($this->db);
+ $line->fk_project = 0;
+ $line->label = $langs->trans("Label") . " " . $xnbp;
+ $line->description = $langs->trans("Description") . " " . $xnbp;
+
+ $this->lines[]=$line;
+ $xnbp++;
+ }
+ */
+ }
+
+ /**
+ * Check if user has permission on current project
+ *
+ * @param User $user Object user to evaluate
+ * @param string $mode Type of permission we want to know: 'read', 'write'
+ * @return int >0 if user has permission, <0 if user has no permission
+ */
+ public function restrictedProjectArea($user, $mode = 'read')
+ {
+ // To verify role of users
+ $userAccess = 0;
+ if (($mode == 'read' && !empty($user->rights->projet->all->lire)) || ($mode == 'write' && !empty($user->rights->projet->all->creer)) || ($mode == 'delete' && !empty($user->rights->projet->all->supprimer)))
+ {
+ $userAccess = 1;
+ }
+ elseif ($this->public && (($mode == 'read' && !empty($user->rights->projet->lire)) || ($mode == 'write' && !empty($user->rights->projet->creer)) || ($mode == 'delete' && !empty($user->rights->projet->supprimer))))
+ {
+ $userAccess = 1;
+ }
+ else
+ {
+ foreach (array('internal', 'external') as $source)
+ {
+ $userRole = $this->liste_contact(4, $source);
+ $num = count($userRole);
+
+ $nblinks = 0;
+ while ($nblinks < $num)
+ {
+ if ($source == 'internal' && preg_match('/^PROJECT/', $userRole[$nblinks]['code']) && $user->id == $userRole[$nblinks]['id'])
+ {
+ if ($mode == 'read' && $user->rights->projet->lire) $userAccess++;
+ if ($mode == 'write' && $user->rights->projet->creer) $userAccess++;
+ if ($mode == 'delete' && $user->rights->projet->supprimer) $userAccess++;
+ }
+ $nblinks++;
+ }
+ }
+ //if (empty($nblinks)) // If nobody has permission, we grant creator
+ //{
+ // if ((!empty($this->user_author_id) && $this->user_author_id == $user->id))
+ // {
+ // $userAccess = 1;
+ // }
+ //}
+ }
+
+ return ($userAccess ? $userAccess : -1);
+ }
+
+ /**
+ * Return array of projects a user has permission on, is affected to, or all projects
+ *
+ * @param User $user User object
+ * @param int $mode 0=All project I have permission on (assigned to me or public), 1=Projects assigned to me only, 2=Will return list of all projects with no test on contacts
+ * @param int $list 0=Return array, 1=Return string list
+ * @param int $socid 0=No filter on third party, id of third party
+ * @param string $filter additionnal filter on project (statut, ref, ...)
+ * @return array or string Array of projects id, or string with projects id separated with "," if list is 1
+ */
+ public function getProjectsAuthorizedForUser($user, $mode = 0, $list = 0, $socid = 0, $filter = '')
+ {
+ $projects = array();
+ $temp = array();
+
+ $sql = "SELECT ".(($mode == 0 || $mode == 1) ? "DISTINCT " : "")."p.rowid, p.ref";
+ $sql.= " FROM " . MAIN_DB_PREFIX . "projet as p";
+ if ($mode == 0)
+ {
+ $sql.= " LEFT JOIN " . MAIN_DB_PREFIX . "element_contact as ec ON ec.element_id = p.rowid";
+ }
+ elseif ($mode == 1)
+ {
+ $sql.= ", " . MAIN_DB_PREFIX . "element_contact as ec";
+ }
+ elseif ($mode == 2)
+ {
+ // No filter. Use this if user has permission to see all project
+ }
+ $sql.= " WHERE p.entity IN (".getEntity('project').")";
+ // Internal users must see project he is contact to even if project linked to a third party he can't see.
+ //if ($socid || ! $user->rights->societe->client->voir) $sql.= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")";
+ if ($socid > 0) $sql.= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = " . $socid . ")";
+
+ // Get id of types of contacts for projects (This list never contains a lot of elements)
+ $listofprojectcontacttype=array();
+ $sql2 = "SELECT ctc.rowid, ctc.code FROM ".MAIN_DB_PREFIX."c_type_contact as ctc";
+ $sql2.= " WHERE ctc.element = '" . $this->db->escape($this->element) . "'";
+ $sql2.= " AND ctc.source = 'internal'";
+ $resql = $this->db->query($sql2);
+ if ($resql)
+ {
+ while($obj = $this->db->fetch_object($resql))
+ {
+ $listofprojectcontacttype[$obj->rowid]=$obj->code;
+ }
+ }
+ else dol_print_error($this->db);
+ if (count($listofprojectcontacttype) == 0) $listofprojectcontacttype[0]='0'; // To avoid syntax error if not found
+
+ if ($mode == 0)
+ {
+ $sql.= " AND ( p.public = 1";
+ $sql.= " OR ( ec.fk_c_type_contact IN (".join(',', array_keys($listofprojectcontacttype)).")";
+ $sql.= " AND ec.fk_socpeople = ".$user->id.")";
+ $sql.= " )";
+ }
+ elseif ($mode == 1)
+ {
+ $sql.= " AND ec.element_id = p.rowid";
+ $sql.= " AND (";
+ $sql.= " ( ec.fk_c_type_contact IN (".join(',', array_keys($listofprojectcontacttype)).")";
+ $sql.= " AND ec.fk_socpeople = ".$user->id.")";
+ $sql.= " )";
+ }
+ elseif ($mode == 2)
+ {
+ // No filter. Use this if user has permission to see all project
+ }
$sql.= $filter;
- //print $sql;
+ //print $sql;
- $resql = $this->db->query($sql);
- if ($resql)
- {
- $num = $this->db->num_rows($resql);
- $i = 0;
- while ($i < $num)
- {
- $row = $this->db->fetch_row($resql);
- $projects[$row[0]] = $row[1];
- $temp[] = $row[0];
- $i++;
- }
+ $resql = $this->db->query($sql);
+ if ($resql)
+ {
+ $num = $this->db->num_rows($resql);
+ $i = 0;
+ while ($i < $num)
+ {
+ $row = $this->db->fetch_row($resql);
+ $projects[$row[0]] = $row[1];
+ $temp[] = $row[0];
+ $i++;
+ }
- $this->db->free($resql);
+ $this->db->free($resql);
- if ($list)
- {
- if (empty($temp)) return '0';
- $result = implode(',', $temp);
- return $result;
- }
- }
- else
- {
- dol_print_error($this->db);
- }
+ if ($list)
+ {
+ if (empty($temp)) return '0';
+ $result = implode(',', $temp);
+ return $result;
+ }
+ }
+ else
+ {
+ dol_print_error($this->db);
+ }
- return $projects;
- }
+ return $projects;
+ }
- /**
- * Load an object from its id and create a new one in database
+ /**
+ * Load an object from its id and create a new one in database
*
* @param User $user User making the clone
* @param int $fromid Id of object to clone
@@ -1330,14 +1332,14 @@ class Project extends CommonObject
* @param bool $clone_task Clone task of project
* @param bool $clone_project_file Clone file of project
* @param bool $clone_task_file Clone file of task (if task are copied)
- * @param bool $clone_note Clone note of project
- * @param bool $move_date Move task date on clone
- * @param integer $notrigger No trigger flag
- * @param int $newthirdpartyid New thirdparty id
+ * @param bool $clone_note Clone note of project
+ * @param bool $move_date Move task date on clone
+ * @param integer $notrigger No trigger flag
+ * @param int $newthirdpartyid New thirdparty id
* @return int New id of clone
*/
- public function createFromClone(User $user, $fromid, $clone_contact = false, $clone_task = true, $clone_project_file = false, $clone_task_file = false, $clone_note = true, $move_date = true, $notrigger = 0, $newthirdpartyid = 0)
- {
+ public function createFromClone(User $user, $fromid, $clone_contact = false, $clone_task = true, $clone_project_file = false, $clone_task_file = false, $clone_note = true, $move_date = true, $notrigger = 0, $newthirdpartyid = 0)
+ {
global $langs, $conf;
$error = 0;
@@ -1363,40 +1365,40 @@ class Project extends CommonObject
$clone_project->id = 0;
if ($move_date) {
- $clone_project->date_start = $now;
- if (!(empty($clone_project->date_end)))
- {
- $clone_project->date_end = $clone_project->date_end + ($now - $orign_dt_start);
- }
+ $clone_project->date_start = $now;
+ if (!(empty($clone_project->date_end)))
+ {
+ $clone_project->date_end = $clone_project->date_end + ($now - $orign_dt_start);
+ }
}
- $clone_project->datec = $now;
+ $clone_project->datec = $now;
- if (!$clone_note)
- {
- $clone_project->note_private = '';
- $clone_project->note_public = '';
- }
+ if (!$clone_note)
+ {
+ $clone_project->note_private = '';
+ $clone_project->note_public = '';
+ }
//Generate next ref
$defaultref = '';
- $obj = empty($conf->global->PROJECT_ADDON) ? 'mod_project_simple' : $conf->global->PROJECT_ADDON;
- // Search template files
- $file = ''; $classname = ''; $filefound = 0;
- $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
- foreach ($dirmodels as $reldir)
- {
- $file = dol_buildpath($reldir."core/modules/project/".$obj.'.php', 0);
- if (file_exists($file))
- {
- $filefound = 1;
- dol_include_once($reldir."core/modules/project/".$obj.'.php');
- $modProject = new $obj;
- $defaultref = $modProject->getNextValue(is_object($clone_project->thirdparty) ? $clone_project->thirdparty : null, $clone_project);
- break;
- }
- }
- if (is_numeric($defaultref) && $defaultref <= 0) $defaultref = '';
+ $obj = empty($conf->global->PROJECT_ADDON) ? 'mod_project_simple' : $conf->global->PROJECT_ADDON;
+ // Search template files
+ $file = ''; $classname = ''; $filefound = 0;
+ $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
+ foreach ($dirmodels as $reldir)
+ {
+ $file = dol_buildpath($reldir."core/modules/project/".$obj.'.php', 0);
+ if (file_exists($file))
+ {
+ $filefound = 1;
+ dol_include_once($reldir."core/modules/project/".$obj.'.php');
+ $modProject = new $obj;
+ $defaultref = $modProject->getNextValue(is_object($clone_project->thirdparty) ? $clone_project->thirdparty : null, $clone_project);
+ break;
+ }
+ }
+ if (is_numeric($defaultref) && $defaultref <= 0) $defaultref = '';
$clone_project->ref = $defaultref;
$clone_project->title = $langs->trans("CopyOf").' '.$clone_project->title;
@@ -1417,14 +1419,14 @@ class Project extends CommonObject
$clone_project_id = $clone_project->id;
//Note Update
- if (!$clone_note)
- {
- $clone_project->note_private = '';
- $clone_project->note_public = '';
- }
- else
- {
- $this->db->begin();
+ if (!$clone_note)
+ {
+ $clone_project->note_private = '';
+ $clone_project->note_public = '';
+ }
+ else
+ {
+ $this->db->begin();
$res = $clone_project->update_note(dol_html_entity_decode($clone_project->note_public, ENT_QUOTES), '_public');
if ($res < 0)
{
@@ -1449,7 +1451,7 @@ class Project extends CommonObject
{
$this->db->commit();
}
- }
+ }
//Duplicate contact
if ($clone_contact)
@@ -1526,44 +1528,44 @@ class Project extends CommonObject
$tab_conv_child_parent=array();
// Loop on each task, to clone it
- foreach ($tasksarray as $tasktoclone)
- {
+ foreach ($tasksarray as $tasktoclone)
+ {
$result_clone = $taskstatic->createFromClone($user, $tasktoclone->id, $clone_project_id, $tasktoclone->fk_parent, $move_date, true, false, $clone_task_file, true, false);
if ($result_clone <= 0)
- {
- $this->error .= $result_clone->error;
+ {
+ $this->error .= $result_clone->error;
$error++;
- }
- else
- {
- $new_task_id = $result_clone;
- $taskstatic->fetch($tasktoclone->id);
+ }
+ else
+ {
+ $new_task_id = $result_clone;
+ $taskstatic->fetch($tasktoclone->id);
- //manage new parent clone task id
- // if the current task has child we store the original task id and the equivalent clone task id
+ //manage new parent clone task id
+ // if the current task has child we store the original task id and the equivalent clone task id
if (($taskstatic->hasChildren()) && !array_key_exists($tasktoclone->id, $tab_conv_child_parent))
{
$tab_conv_child_parent[$tasktoclone->id] = $new_task_id;
}
- }
- }
+ }
+ }
- //Parse all clone node to be sure to update new parent
- $tasksarray = $taskstatic->getTasksArray(0, 0, $clone_project_id, $socid, 0);
- foreach ($tasksarray as $task_cloned)
- {
- $taskstatic->fetch($task_cloned->id);
- if ($taskstatic->fk_task_parent != 0)
- {
- $taskstatic->fk_task_parent = $tab_conv_child_parent[$taskstatic->fk_task_parent];
- }
- $res = $taskstatic->update($user, $notrigger);
- if ($result_clone <= 0)
- {
- $this->error .= $taskstatic->error;
+ //Parse all clone node to be sure to update new parent
+ $tasksarray = $taskstatic->getTasksArray(0, 0, $clone_project_id, $socid, 0);
+ foreach ($tasksarray as $task_cloned)
+ {
+ $taskstatic->fetch($task_cloned->id);
+ if ($taskstatic->fk_task_parent != 0)
+ {
+ $taskstatic->fk_task_parent = $tab_conv_child_parent[$taskstatic->fk_task_parent];
+ }
+ $res = $taskstatic->update($user, $notrigger);
+ if ($result_clone <= 0)
+ {
+ $this->error .= $taskstatic->error;
$error++;
- }
- }
+ }
+ }
}
}
@@ -1580,17 +1582,17 @@ class Project extends CommonObject
dol_syslog(get_class($this)."::createFromClone nbError: ".$error." error : ".$this->error, LOG_ERR);
return -1;
}
- }
+ }
- /**
+ /**
* Shift project task date from current date to delta
*
* @param integer $old_project_dt_start Old project start date
* @return int 1 if OK or < 0 if KO
*/
- public function shiftTaskDate($old_project_dt_start)
- {
+ public function shiftTaskDate($old_project_dt_start)
+ {
global $user, $langs, $conf;
$error=0;
@@ -1603,65 +1605,65 @@ class Project extends CommonObject
$tasksarray=$taskstatic->getTasksArray(0, 0, $this->id, $socid, 0);
- foreach ($tasksarray as $tasktoshiftdate)
- {
- $to_update=false;
- // Fetch only if update of date will be made
- if ((!empty($tasktoshiftdate->date_start)) || (!empty($tasktoshiftdate->date_end)))
- {
- //dol_syslog(get_class($this)."::shiftTaskDate to_update", LOG_DEBUG);
- $to_update=true;
- $task = new Task($this->db);
- $result = $task->fetch($tasktoshiftdate->id);
- if (!$result)
- {
- $error++;
- $this->error.=$task->error;
- }
- }
+ foreach ($tasksarray as $tasktoshiftdate)
+ {
+ $to_update=false;
+ // Fetch only if update of date will be made
+ if ((!empty($tasktoshiftdate->date_start)) || (!empty($tasktoshiftdate->date_end)))
+ {
+ //dol_syslog(get_class($this)."::shiftTaskDate to_update", LOG_DEBUG);
+ $to_update=true;
+ $task = new Task($this->db);
+ $result = $task->fetch($tasktoshiftdate->id);
+ if (!$result)
+ {
+ $error++;
+ $this->error.=$task->error;
+ }
+ }
//print "$this->date_start + $tasktoshiftdate->date_start - $old_project_dt_start";exit;
- //Calcultate new task start date with difference between old proj start date and origin task start date
- if (!empty($tasktoshiftdate->date_start))
- {
+ //Calcultate new task start date with difference between old proj start date and origin task start date
+ if (!empty($tasktoshiftdate->date_start))
+ {
$task->date_start = $this->date_start + ($tasktoshiftdate->date_start - $old_project_dt_start);
- }
+ }
- //Calcultate new task end date with difference between origin proj end date and origin task end date
- if (!empty($tasktoshiftdate->date_end))
- {
+ //Calcultate new task end date with difference between origin proj end date and origin task end date
+ if (!empty($tasktoshiftdate->date_end))
+ {
$task->date_end = $this->date_start + ($tasktoshiftdate->date_end - $old_project_dt_start);
- }
+ }
if ($to_update)
{
- $result = $task->update($user);
- if (!$result)
- {
- $error++;
- $this->error .= $task->error;
- }
+ $result = $task->update($user);
+ if (!$result)
+ {
+ $error++;
+ $this->error .= $task->error;
+ }
}
- }
- if ($error != 0)
- {
- return -1;
- }
- return $result;
+ }
+ if ($error != 0)
+ {
+ return -1;
+ }
+ return $result;
}
- // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Associate element to a project
*
* @param string $tableName Table of the element to update
* @param int $elementSelectId Key-rowid of the line of the element to update
* @return int 1 if OK or < 0 if KO
- */
+ */
public function update_element($tableName, $elementSelectId)
{
- // phpcs:enable
+ // phpcs:enable
$sql = "UPDATE ".MAIN_DB_PREFIX.$tableName;
if ($tableName == "actioncomm")
@@ -1685,19 +1687,19 @@ class Project extends CommonObject
}
}
- // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Associate element to a project
*
* @param string $tableName Table of the element to update
* @param int $elementSelectId Key-rowid of the line of the element to update
* @param string $projectfield The column name that stores the link with the project
- *
+ *
* @return int 1 if OK or < 0 if KO
*/
public function remove_element($tableName, $elementSelectId, $projectfield = 'fk_projet')
{
- // phpcs:enable
+ // phpcs:enable
$sql = "UPDATE ".MAIN_DB_PREFIX.$tableName;
if ($tableName == "actioncomm")
@@ -1761,130 +1763,130 @@ class Project extends CommonObject
* @param int $userid Time spent by a particular user
* @return int <0 if OK, >0 if KO
*/
- public function loadTimeSpent($datestart, $taskid = 0, $userid = 0)
- {
- $error=0;
+ public function loadTimeSpent($datestart, $taskid = 0, $userid = 0)
+ {
+ $error=0;
- $this->weekWorkLoad=array();
- $this->weekWorkLoadPerTask=array();
+ $this->weekWorkLoad=array();
+ $this->weekWorkLoadPerTask=array();
- if (empty($datestart)) dol_print_error('', 'Error datestart parameter is empty');
+ if (empty($datestart)) dol_print_error('', 'Error datestart parameter is empty');
- $sql = "SELECT ptt.rowid as taskid, ptt.task_duration, ptt.task_date, ptt.task_datehour, ptt.fk_task";
- $sql.= " FROM ".MAIN_DB_PREFIX."projet_task_time AS ptt, ".MAIN_DB_PREFIX."projet_task as pt";
- $sql.= " WHERE ptt.fk_task = pt.rowid";
- $sql.= " AND pt.fk_projet = ".$this->id;
- $sql.= " AND (ptt.task_date >= '".$this->db->idate($datestart)."' ";
- $sql.= " AND ptt.task_date <= '".$this->db->idate(dol_time_plus_duree($datestart, 1, 'w') - 1)."')";
- if ($taskid) $sql.= " AND ptt.fk_task=".$taskid;
- if (is_numeric($userid)) $sql.= " AND ptt.fk_user=".$userid;
+ $sql = "SELECT ptt.rowid as taskid, ptt.task_duration, ptt.task_date, ptt.task_datehour, ptt.fk_task";
+ $sql.= " FROM ".MAIN_DB_PREFIX."projet_task_time AS ptt, ".MAIN_DB_PREFIX."projet_task as pt";
+ $sql.= " WHERE ptt.fk_task = pt.rowid";
+ $sql.= " AND pt.fk_projet = ".$this->id;
+ $sql.= " AND (ptt.task_date >= '".$this->db->idate($datestart)."' ";
+ $sql.= " AND ptt.task_date <= '".$this->db->idate(dol_time_plus_duree($datestart, 1, 'w') - 1)."')";
+ if ($taskid) $sql.= " AND ptt.fk_task=".$taskid;
+ if (is_numeric($userid)) $sql.= " AND ptt.fk_user=".$userid;
- //print $sql;
- $resql=$this->db->query($sql);
- if ($resql)
- {
- $daylareadyfound=array();
+ //print $sql;
+ $resql=$this->db->query($sql);
+ if ($resql)
+ {
+ $daylareadyfound=array();
- $num = $this->db->num_rows($resql);
- $i = 0;
- // Loop on each record found, so each couple (project id, task id)
+ $num = $this->db->num_rows($resql);
+ $i = 0;
+ // Loop on each record found, so each couple (project id, task id)
while ($i < $num)
- {
- $obj=$this->db->fetch_object($resql);
- $day=$this->db->jdate($obj->task_date); // task_date is date without hours
+ {
+ $obj=$this->db->fetch_object($resql);
+ $day=$this->db->jdate($obj->task_date); // task_date is date without hours
if (empty($daylareadyfound[$day]))
- {
+ {
$this->weekWorkLoad[$day] = $obj->task_duration;
$this->weekWorkLoadPerTask[$day][$obj->fk_task] = $obj->task_duration;
}
else
- {
+ {
$this->weekWorkLoad[$day] += $obj->task_duration;
$this->weekWorkLoadPerTask[$day][$obj->fk_task] += $obj->task_duration;
}
- $daylareadyfound[$day]=1;
- $i++;
+ $daylareadyfound[$day]=1;
+ $i++;
}
- $this->db->free($resql);
- return 1;
- }
- else
- {
- $this->error = "Error ".$this->db->lasterror();
- dol_syslog(get_class($this)."::fetch ".$this->error, LOG_ERR);
- return -1;
- }
- }
+ $this->db->free($resql);
+ return 1;
+ }
+ else
+ {
+ $this->error = "Error ".$this->db->lasterror();
+ dol_syslog(get_class($this)."::fetch ".$this->error, LOG_ERR);
+ return -1;
+ }
+ }
- // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
- /**
- * Load indicators for dashboard (this->nbtodo and this->nbtodolate)
- *
- * @param User $user Objet user
- * @return WorkboardResponse|int <0 if KO, WorkboardResponse if OK
- */
- public function load_board($user)
- {
- // phpcs:enable
- global $conf, $langs;
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ /**
+ * Load indicators for dashboard (this->nbtodo and this->nbtodolate)
+ *
+ * @param User $user Objet user
+ * @return WorkboardResponse|int <0 if KO, WorkboardResponse if OK
+ */
+ public function load_board($user)
+ {
+ // phpcs:enable
+ global $conf, $langs;
- // For external user, no check is done on company because readability is managed by public status of project and assignement.
- //$socid=$user->socid;
+ // For external user, no check is done on company because readability is managed by public status of project and assignement.
+ //$socid=$user->socid;
$projectsListId = null;
- if (!$user->rights->projet->all->lire) $projectsListId = $this->getProjectsAuthorizedForUser($user, 0, 1);
+ if (!$user->rights->projet->all->lire) $projectsListId = $this->getProjectsAuthorizedForUser($user, 0, 1);
- $sql = "SELECT p.rowid, p.fk_statut as status, p.fk_opp_status, p.datee as datee";
- $sql .= " FROM (".MAIN_DB_PREFIX."projet as p";
- $sql .= ")";
- $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid";
- // For external user, no check is done on company permission because readability is managed by public status of project and assignement.
- //if (! $user->rights->societe->client->voir && ! $socid) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON sc.fk_soc = s.rowid";
- $sql .= " WHERE p.fk_statut = 1";
- $sql .= " AND p.entity IN (".getEntity('project').')';
- if (!empty($projectsListId)) $sql .= " AND p.rowid IN (".$projectsListId.")";
- // No need to check company, as filtering of projects must be done by getProjectsAuthorizedForUser
- //if ($socid || ! $user->rights->societe->client->voir) $sql.= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")";
- // For external user, no check is done on company permission because readability is managed by public status of project and assignement.
- //if (! $user->rights->societe->client->voir && ! $socid) $sql.= " AND ((s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id.") OR (s.rowid IS NULL))";
+ $sql = "SELECT p.rowid, p.fk_statut as status, p.fk_opp_status, p.datee as datee";
+ $sql .= " FROM (".MAIN_DB_PREFIX."projet as p";
+ $sql .= ")";
+ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid";
+ // For external user, no check is done on company permission because readability is managed by public status of project and assignement.
+ //if (! $user->rights->societe->client->voir && ! $socid) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON sc.fk_soc = s.rowid";
+ $sql .= " WHERE p.fk_statut = 1";
+ $sql .= " AND p.entity IN (".getEntity('project').')';
+ if (!empty($projectsListId)) $sql .= " AND p.rowid IN (".$projectsListId.")";
+ // No need to check company, as filtering of projects must be done by getProjectsAuthorizedForUser
+ //if ($socid || ! $user->rights->societe->client->voir) $sql.= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")";
+ // For external user, no check is done on company permission because readability is managed by public status of project and assignement.
+ //if (! $user->rights->societe->client->voir && ! $socid) $sql.= " AND ((s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id.") OR (s.rowid IS NULL))";
- //print $sql;
- $resql = $this->db->query($sql);
- if ($resql)
- {
- $project_static = new Project($this->db);
+ //print $sql;
+ $resql = $this->db->query($sql);
+ if ($resql)
+ {
+ $project_static = new Project($this->db);
- $response = new WorkboardResponse();
- $response->warning_delay = $conf->projet->warning_delay / 60 / 60 / 24;
- $response->label = $langs->trans("OpenedProjects");
- $response->labelShort = $langs->trans("Opened");
- if ($user->rights->projet->all->lire) $response->url = DOL_URL_ROOT.'/projet/list.php?search_status=1&mainmenu=project';
- else $response->url = DOL_URL_ROOT.'/projet/list.php?search_project_user=-1&search_status=1&mainmenu=project';
- $response->img = img_object('', "projectpub");
+ $response = new WorkboardResponse();
+ $response->warning_delay = $conf->projet->warning_delay / 60 / 60 / 24;
+ $response->label = $langs->trans("OpenedProjects");
+ $response->labelShort = $langs->trans("Opened");
+ if ($user->rights->projet->all->lire) $response->url = DOL_URL_ROOT.'/projet/list.php?search_status=1&mainmenu=project';
+ else $response->url = DOL_URL_ROOT.'/projet/list.php?search_project_user=-1&search_status=1&mainmenu=project';
+ $response->img = img_object('', "projectpub");
- // This assignment in condition is not a bug. It allows walking the results.
- while ($obj = $this->db->fetch_object($resql))
- {
- $response->nbtodo++;
+ // This assignment in condition is not a bug. It allows walking the results.
+ while ($obj = $this->db->fetch_object($resql))
+ {
+ $response->nbtodo++;
- $project_static->statut = $obj->status;
- $project_static->opp_status = $obj->opp_status;
- $project_static->datee = $this->db->jdate($obj->datee);
+ $project_static->statut = $obj->status;
+ $project_static->opp_status = $obj->opp_status;
+ $project_static->datee = $this->db->jdate($obj->datee);
- if ($project_static->hasDelay()) {
- $response->nbtodolate++;
- }
- }
+ if ($project_static->hasDelay()) {
+ $response->nbtodolate++;
+ }
+ }
- return $response;
- }
- else
- {
- $this->error = $this->db->error();
- return -1;
- }
- }
+ return $response;
+ }
+ else
+ {
+ $this->error = $this->db->error();
+ return -1;
+ }
+ }
/**
@@ -1905,7 +1907,7 @@ class Project extends CommonObject
}
- // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
+ // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
* Charge indicateurs this->nb pour le tableau de bord
*
@@ -1913,37 +1915,37 @@ class Project extends CommonObject
*/
public function load_state_board()
{
- // phpcs:enable
- global $user;
+ // phpcs:enable
+ global $user;
- $this->nb = array();
+ $this->nb = array();
- $sql = "SELECT count(p.rowid) as nb";
- $sql .= " FROM ".MAIN_DB_PREFIX."projet as p";
- $sql .= " WHERE";
- $sql .= " p.entity IN (".getEntity('project').")";
+ $sql = "SELECT count(p.rowid) as nb";
+ $sql .= " FROM ".MAIN_DB_PREFIX."projet as p";
+ $sql .= " WHERE";
+ $sql .= " p.entity IN (".getEntity('project').")";
if (!$user->rights->projet->all->lire)
{
$projectsListId = $this->getProjectsAuthorizedForUser($user, 0, 1);
$sql .= "AND p.rowid IN (".$projectsListId.")";
}
- $resql = $this->db->query($sql);
- if ($resql)
- {
- while ($obj = $this->db->fetch_object($resql))
- {
- $this->nb["projects"] = $obj->nb;
- }
- $this->db->free($resql);
- return 1;
- }
- else
- {
- dol_print_error($this->db);
- $this->error = $this->db->error();
- return -1;
- }
+ $resql = $this->db->query($sql);
+ if ($resql)
+ {
+ while ($obj = $this->db->fetch_object($resql))
+ {
+ $this->nb["projects"] = $obj->nb;
+ }
+ $this->db->free($resql);
+ return 1;
+ }
+ else
+ {
+ dol_print_error($this->db);
+ $this->error = $this->db->error();
+ return -1;
+ }
}
@@ -1954,14 +1956,14 @@ class Project extends CommonObject
*/
public function hasDelay()
{
- global $conf;
+ global $conf;
- if (!($this->statut == self::STATUS_VALIDATED)) return false;
- if (!$this->datee && !$this->date_end) return false;
+ if (!($this->statut == self::STATUS_VALIDATED)) return false;
+ if (!$this->datee && !$this->date_end) return false;
- $now = dol_now();
+ $now = dol_now();
- return ($this->datee ? $this->datee : $this->date_end) < ($now - $conf->projet->warning_delay);
+ return ($this->datee ? $this->datee : $this->date_end) < ($now - $conf->projet->warning_delay);
}
@@ -1973,43 +1975,43 @@ class Project extends CommonObject
*/
public function info($id)
{
- $sql = 'SELECT c.rowid, datec as datec, tms as datem,';
- $sql .= ' date_close as datecloture,';
- $sql .= ' fk_user_creat as fk_user_author, fk_user_close as fk_use_cloture';
- $sql .= ' FROM '.MAIN_DB_PREFIX.'projet as c';
- $sql .= ' WHERE c.rowid = '.$id;
- $result = $this->db->query($sql);
- if ($result)
- {
- if ($this->db->num_rows($result))
- {
- $obj = $this->db->fetch_object($result);
- $this->id = $obj->rowid;
- if ($obj->fk_user_author)
- {
- $cuser = new User($this->db);
- $cuser->fetch($obj->fk_user_author);
- $this->user_creation = $cuser;
- }
+ $sql = 'SELECT c.rowid, datec as datec, tms as datem,';
+ $sql .= ' date_close as datecloture,';
+ $sql .= ' fk_user_creat as fk_user_author, fk_user_close as fk_use_cloture';
+ $sql .= ' FROM '.MAIN_DB_PREFIX.'projet as c';
+ $sql .= ' WHERE c.rowid = '.$id;
+ $result = $this->db->query($sql);
+ if ($result)
+ {
+ if ($this->db->num_rows($result))
+ {
+ $obj = $this->db->fetch_object($result);
+ $this->id = $obj->rowid;
+ if ($obj->fk_user_author)
+ {
+ $cuser = new User($this->db);
+ $cuser->fetch($obj->fk_user_author);
+ $this->user_creation = $cuser;
+ }
- if ($obj->fk_user_cloture)
- {
- $cluser = new User($this->db);
- $cluser->fetch($obj->fk_user_cloture);
- $this->user_cloture = $cluser;
- }
+ if ($obj->fk_user_cloture)
+ {
+ $cluser = new User($this->db);
+ $cluser->fetch($obj->fk_user_cloture);
+ $this->user_cloture = $cluser;
+ }
- $this->date_creation = $this->db->jdate($obj->datec);
- $this->date_modification = $this->db->jdate($obj->datem);
- $this->date_cloture = $this->db->jdate($obj->datecloture);
- }
+ $this->date_creation = $this->db->jdate($obj->datec);
+ $this->date_modification = $this->db->jdate($obj->datem);
+ $this->date_cloture = $this->db->jdate($obj->datecloture);
+ }
- $this->db->free($result);
- }
- else
- {
- dol_print_error($this->db);
- }
+ $this->db->free($result);
+ }
+ else
+ {
+ dol_print_error($this->db);
+ }
}
/**
@@ -2020,7 +2022,7 @@ class Project extends CommonObject
* Existing categories are left untouch.
*
* @param int[]|int $categories Category or categories IDs
- * @return void
+ * @return void
*/
public function setCategories($categories)
{
@@ -2079,9 +2081,9 @@ class Project extends CommonObject
*/
public function getLinesArray($user)
{
- require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
- $taskstatic = new Task($this->db);
+ require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
+ $taskstatic = new Task($this->db);
- $this->lines = $taskstatic->getTasksArray(0, $user, $this->id, 0, 0);
+ $this->lines = $taskstatic->getTasksArray(0, $user, $this->id, 0, 0);
}
}