diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index cecb4fff28a..dc923e4e1dc 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -642,7 +642,7 @@ if (empty($reshook)) { if ($object->statut == $object::STATUS_VALIDATED) { $db->begin(); - $result = $object->cloture($user, GETPOST('statut', 'int'), GETPOST('note_private', 'restricthtml')); + $result = $object->signature($user, GETPOST('statut', 'int'), GETPOST('note_private', 'restricthtml')); if ($result < 0) { setEventMessages($object->error, $object->errors, 'errors'); $error++; diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 3674356af20..c9f736fcfff 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -140,6 +140,16 @@ class Propal extends CommonObject */ public $date_validation; + /** + * @var integer|string $date_signature; + */ + public $date_signature; + + /** + * @var User $user_signature + */ + public $user_signature; + /** * @var integer|string date of the quote; */ @@ -2489,6 +2499,97 @@ class Propal extends CommonObject } } + /** + * Sign the commercial proposal + * + * @param User $user Object user that close + * @param int $statut Status + * @param string $note Complete private note with this note + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, >0 if OK + */ + function signature($user, $statut, $note = '', $notrigger = 0) + { + global $langs,$conf; + + $error = 0; + $now = dol_now(); + + $this->db->begin(); + + $newprivatenote = dol_concatdesc($this->note_private, $note); + + $sql = "UPDATE ".MAIN_DB_PREFIX."propal"; + $sql .= " SET fk_statut = ".$statut.", note_private = '".$this->db->escape($newprivatenote)."', date_signature='".$this->db->idate($now)."', fk_user_signature=".$user->id; + $sql .= " WHERE rowid = ".$this->id; + + $resql = $this->db->query($sql); + if ($resql) { + $modelpdf = $conf->global->PROPALE_ADDON_PDF_ODT_CLOSED ? $conf->global->PROPALE_ADDON_PDF_ODT_CLOSED : $this->model_pdf; + $trigger_name = 'PROPAL_CLOSE_REFUSED'; + + if ($statut == self::STATUS_SIGNED) { + $trigger_name = 'PROPAL_CLOSE_SIGNED'; + $modelpdf = $conf->global->PROPALE_ADDON_PDF_ODT_TOBILL ? $conf->global->PROPALE_ADDON_PDF_ODT_TOBILL:$this->model_pdf; + + // The connected company is classified as a client + $soc=new Societe($this->db); + $soc->id = $this->socid; + $result = $soc->set_as_client(); + + if ($result < 0) { + $this->error=$this->db->lasterror(); + $this->db->rollback(); + return -2; + } + } + + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { + // Define output language + $outputlangs = $langs; + if (!empty($conf->global->MAIN_MULTILANGS)) { + $outputlangs = new Translate("", $conf); + $newlang = (GETPOST('lang_id','aZ09') ? GETPOST('lang_id','aZ09') : $this->thirdparty->default_lang); + $outputlangs->setDefaultLang($newlang); + } + + //$ret=$object->fetch($id); // Reload to get new records + $this->generateDocument($modelpdf, $outputlangs); + } + + if (!$error) { + $this->oldcopy= clone $this; + $this->statut = $statut; + $this->date_signature = $now; + $this->note_private = $newprivatenote; + } + + if (!$notrigger && empty($error)) { + // Call trigger + $result=$this->call_trigger($trigger_name, $user); + if ($result < 0) { + $error++; + } + // End call triggers + } + + if (!$error ) { + $this->db->commit(); + return 1; + } else { + $this->statut = $this->oldcopy->statut; + $this->date_signature = $this->oldcopy->date_signature; + $this->note_private = $this->oldcopy->note_private; + + $this->db->rollback(); + return -1; + } + } else { + $this->error=$this->db->lasterror(); + $this->db->rollback(); + return -1; + } + } /** * Close the commercial proposal @@ -3113,8 +3214,8 @@ class Propal extends CommonObject public function info($id) { $sql = "SELECT c.rowid, "; - $sql .= " c.datec, c.date_valid as datev, c.date_cloture as dateo,"; - $sql .= " c.fk_user_author, c.fk_user_valid, c.fk_user_cloture"; + $sql .= " c.datec, c.date_valid as datev, c.date_signature, c.date_cloture as dateo,"; + $sql .= " c.fk_user_author, c.fk_user_valid, c.fk_user_signature, c.fk_user_cloture"; $sql .= " FROM ".MAIN_DB_PREFIX."propal as c"; $sql .= " WHERE c.rowid = ".((int) $id); @@ -3128,6 +3229,7 @@ class Propal extends CommonObject $this->date_creation = $this->db->jdate($obj->datec); $this->date_validation = $this->db->jdate($obj->datev); + $this->date_signature = $this->db->jdate($obj->date_signature); $this->date_cloture = $this->db->jdate($obj->dateo); $cuser = new User($this->db); @@ -3140,6 +3242,12 @@ class Propal extends CommonObject $this->user_validation = $vuser; } + if ($obj->fk_user_signature) { + $user_signature = new User($this->db); + $user_signature->fetch($obj->fk_user_signature); + $this->user_signature = $user_signature; + } + if ($obj->fk_user_cloture) { $cluser = new User($this->db); $cluser->fetch($obj->fk_user_cloture); diff --git a/htdocs/core/lib/functions2.lib.php b/htdocs/core/lib/functions2.lib.php index 0703df95255..3f7e02b9bad 100644 --- a/htdocs/core/lib/functions2.lib.php +++ b/htdocs/core/lib/functions2.lib.php @@ -507,6 +507,61 @@ function dol_print_object_info($object, $usetable = 0) } } + // User signature + if (!empty($object->user_signature)) { + if ($usetable) { + print ''; + } + print $langs->trans('SignedBy'); + if ($usetable) { + print ''; + } else { + print ': '; + } + if (is_object($object->user_signature)) { + if ($object->user_signature->id) { + print $object->user_signature->getNomUrl(-1, '', 0, 0, 0); + } else { + print $langs->trans('Unknown'); + } + } else { + $userstatic = new User($db); + $userstatic->fetch($object->user_signature); + if ($userstatic->id) { + print $userstatic->getNomUrl(-1, '', 0, 0, 0); + } else { + print $langs->trans('Unknown'); + } + } + if ($usetable) { + print ''; + } else { + print '
'; + } + } + + // Date signature + if (!empty($object->date_signature)) { + if ($usetable) { + print ''; + } + print $langs->trans('DateSigning'); + if ($usetable) { + print ''; + } else { + print ': '; + } + print dol_print_date($object->date_signature, 'dayhour'); + if ($deltadateforuser) { + print ' '.$langs->trans('CurrentHour').'   /   '.dol_print_date($object->date_signature,'dayhour', 'tzuserrel').'  '.$langs->trans('ClientHour'); + } + if ($usetable) { + print ''; + } else { + print '
'; + } + } + // User close if (!empty($object->user_cloture) || !empty($object->user_closing)) { if (isset($object->user_cloture) && !empty($object->user_cloture)) { diff --git a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql index 772f0e51bdf..0c71b94f4f1 100644 --- a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql +++ b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql @@ -282,5 +282,11 @@ DELETE FROM llx_boxes_def WHERE file IN ('box_graph_ticket_by_severity', 'box_ti ALTER TABLE llx_c_ticket_category ADD COLUMN public integer DEFAULT 0; +ALTER TABLE llx_propal ADD COLUMN date_signature datetime AFTER date_valid; +ALTER TABLE llx_propal ADD COLUMN fk_user_signature integer AFTER fk_user_valid; +ALTER TABLE llx_propal ADD CONSTRAINT fk_propal_fk_user_signature FOREIGN KEY (fk_user_signature) REFERENCES llx_user (rowid); +UPDATE llx_propal SET fk_user_signature = fk_user_cloture WHERE fk_user_signature IS NULL AND fk_user_cloture IS NOT NULL; +UPDATE llx_propal SET date_signature = date_cloture WHERE date_signature IS NULL AND date_cloture IS NOT NULL; + diff --git a/htdocs/install/mysql/tables/llx_propal.key.sql b/htdocs/install/mysql/tables/llx_propal.key.sql index 89a0c54ad83..d0265e6fcdf 100644 --- a/htdocs/install/mysql/tables/llx_propal.key.sql +++ b/htdocs/install/mysql/tables/llx_propal.key.sql @@ -24,6 +24,7 @@ ALTER TABLE llx_propal ADD UNIQUE INDEX uk_propal_ref (ref, entity); ALTER TABLE llx_propal ADD INDEX idx_propal_fk_soc (fk_soc); ALTER TABLE llx_propal ADD INDEX idx_propal_fk_user_author (fk_user_author); ALTER TABLE llx_propal ADD INDEX idx_propal_fk_user_valid (fk_user_valid); +ALTER TABLE llx_propal ADD INDEX idx_propal_fk_user_signature (fk_user_signature); ALTER TABLE llx_propal ADD INDEX idx_propal_fk_user_cloture (fk_user_cloture); ALTER TABLE llx_propal ADD INDEX idx_propal_fk_projet (fk_projet); ALTER TABLE llx_propal ADD INDEX idx_propal_fk_account(fk_account); @@ -33,6 +34,7 @@ ALTER TABLE llx_propal ADD INDEX idx_propal_fk_warehouse(fk_warehouse); ALTER TABLE llx_propal ADD CONSTRAINT fk_propal_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe (rowid); ALTER TABLE llx_propal ADD CONSTRAINT fk_propal_fk_user_author FOREIGN KEY (fk_user_author) REFERENCES llx_user (rowid); ALTER TABLE llx_propal ADD CONSTRAINT fk_propal_fk_user_valid FOREIGN KEY (fk_user_valid) REFERENCES llx_user (rowid); +ALTER TABLE llx_propal ADD CONSTRAINT fk_propal_fk_user_signature FOREIGN KEY (fk_user_signature) REFERENCES llx_user (rowid); ALTER TABLE llx_propal ADD CONSTRAINT fk_propal_fk_user_cloture FOREIGN KEY (fk_user_cloture) REFERENCES llx_user (rowid); ALTER TABLE llx_propal ADD CONSTRAINT fk_propal_fk_projet FOREIGN KEY (fk_projet) REFERENCES llx_projet (rowid); --ALTER TABLE llx_propal ADD CONSTRAINT fk_propal_fk_warehouse FOREIGN KEY (fk_warehouse) REFERENCES llx_entrepot(rowid); diff --git a/htdocs/install/mysql/tables/llx_propal.sql b/htdocs/install/mysql/tables/llx_propal.sql index 004bb027d35..7c94086b3b9 100644 --- a/htdocs/install/mysql/tables/llx_propal.sql +++ b/htdocs/install/mysql/tables/llx_propal.sql @@ -37,11 +37,13 @@ create table llx_propal datep date, -- date de la propal fin_validite datetime, -- date de fin de validite date_valid datetime, -- date de validation + date_signature datetime, -- date signature date_cloture datetime, -- date de cloture fk_user_author integer, -- user making creation fk_user_modif integer, -- user making last change fk_user_valid integer, -- user validating - fk_user_cloture integer, -- user closing (signed or not) + fk_user_signature integer, -- user signing (signed or not) + fk_user_cloture integer, -- user closing fk_statut smallint DEFAULT 0 NOT NULL, -- 0=draft, 1=validated, 2=accepted, 3=refused, 4=billed/closed price real DEFAULT 0, -- (obsolete) remise_percent real DEFAULT 0, -- remise globale relative en pourcent (obsolete) diff --git a/htdocs/langs/fr_FR/main.lang b/htdocs/langs/fr_FR/main.lang index 86ba2247682..a8b13c7e914 100644 --- a/htdocs/langs/fr_FR/main.lang +++ b/htdocs/langs/fr_FR/main.lang @@ -278,6 +278,7 @@ DateModificationShort=Date modif. IPModification=Modification IP DateLastModification=Date de dernière modification DateValidation=Date validation +DateSigning=Date signature DateClosing=Date clôture DateDue=Date échéance DateValue=Date valeur diff --git a/htdocs/langs/fr_FR/other.lang b/htdocs/langs/fr_FR/other.lang index 3023cd7216e..a8078129464 100644 --- a/htdocs/langs/fr_FR/other.lang +++ b/htdocs/langs/fr_FR/other.lang @@ -114,6 +114,7 @@ DemoCompanyAll=Société avec de multiples activités (tous les modules principa CreatedBy=Créé par %s ModifiedBy=Modifié par %s ValidatedBy=Validé par %s +SignedBy=Signé par %s ClosedBy=Clôturé par %s CreatedById=Id utilisateur créateur ModifiedById=Id utilisateur du dernier changement