From 195d6187a3fc8da99cf4fa1313879b3816e8d645 Mon Sep 17 00:00:00 2001
From: florian HENRY <florian.henry@atm-consulting.fr>
Date: Fri, 8 Jul 2016 20:40:25 +0200
Subject: [PATCH] NEW : Uniformize code and correct deal with triggers

---
 htdocs/comm/propal/class/propal.class.php     | 615 ++++++++++++++----
 htdocs/commande/class/commande.class.php      |  49 +-
 htdocs/compta/facture/class/facture.class.php | 157 ++++-
 3 files changed, 647 insertions(+), 174 deletions(-)

diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php
index ffc412fba70..c6e554957b1 100644
--- a/htdocs/comm/propal/class/propal.class.php
+++ b/htdocs/comm/propal/class/propal.class.php
@@ -164,7 +164,7 @@ class Propal extends CommonObject
 	var $multicurrency_total_ht;
 	var $multicurrency_total_tva;
 	var $multicurrency_total_ttc;
-	
+
 	/**
 	 * Draft status
 	 */
@@ -273,7 +273,7 @@ class Propal extends CommonObject
             $line->tva_tx=$tva_tx;
 	        $line->fk_unit=$prod->fk_unit;
 			if ($tva_npr) $line->info_bits = 1;
-			
+
             $this->lines[]=$line;
         }
     }
@@ -444,7 +444,7 @@ class Propal extends CommonObject
 					return -3;
 				}
 			}
-			
+
 			// Calcul du total TTC et de la TVA pour la ligne a partir de
             // qty, pu, remise_percent et txtva
             // TRES IMPORTANT: C'est au moment de l'insertion ligne qu'on doit stocker
@@ -452,7 +452,7 @@ class Propal extends CommonObject
 
             $localtaxes_type=getLocalTaxesFromRate($txtva,0,$this->thirdparty,$mysoc);
             $txtva = preg_replace('/\s*\(.*\)/','',$txtva);  // Remove code into vatrate.
-            
+
             $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $product_type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx);
 
             $total_ht  = $tabprice[0];
@@ -529,7 +529,7 @@ class Propal extends CommonObject
 			$this->line->multicurrency_total_ht 	= $multicurrency_total_ht;
             $this->line->multicurrency_total_tva 	= $multicurrency_total_tva;
             $this->line->multicurrency_total_ttc 	= $multicurrency_total_ttc;
-            
+
             // Mise en option de la ligne
             if (empty($qty) && empty($special_code)) $this->line->special_code=3;
 
@@ -627,7 +627,7 @@ class Propal extends CommonObject
 
             $localtaxes_type=getLocalTaxesFromRate($txtva,0,$this->thirdparty,$mysoc);
             $txtva = preg_replace('/\s*\(.*\)/','',$txtva);  // Remove code into vatrate.
-            
+
             $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $mysoc, $localtaxes_type, 100, $this->multicurrency_tx);
             $total_ht  = $tabprice[0];
             $total_tva = $tabprice[1];
@@ -639,7 +639,7 @@ class Propal extends CommonObject
 			$multicurrency_total_ht  = $tabprice[16];
             $multicurrency_total_tva = $tabprice[17];
             $multicurrency_total_ttc = $tabprice[18];
-			
+
             // Anciens indicateurs: $price, $remise (a ne plus utiliser)
             $price = $pu;
             if ($remise_percent > 0)
@@ -800,7 +800,7 @@ class Propal extends CommonObject
 			$this->fk_multicurrency = 0;
 			$this->multicurrency_tx = 1;
 		}
-		
+
         dol_syslog(get_class($this)."::create");
 
         // Check parameters
@@ -1110,7 +1110,7 @@ class Propal extends CommonObject
                 $clonedObj->cond_reglement_id	= (! empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0);
                 $clonedObj->mode_reglement_id	= (! empty($objsoc->mode_reglement_id) ? $objsoc->mode_reglement_id : 0);
                 $clonedObj->fk_delivery_address	= '';
-            	
+
                 /*if (!empty($conf->projet->enabled))
                 {
                     $project = new Project($db);
@@ -1610,11 +1610,12 @@ class Propal extends CommonObject
     /**
      *  Define proposal date
      *
-     *  @param  User		$user      		Object user that modify
-     *  @param  int			$date			Date
-     *  @return	int         				<0 if KO, >0 if OK
+     *  @param  User		$user      	Object user that modify
+     *  @param  int			$date		Date
+     *  @param  int			$notrigger	1=Does not execute triggers, 0= execuete triggers
+     *  @return	int         			<0 if KO, >0 if OK
      */
-    function set_date($user, $date)
+    function set_date($user, $date, $notrigger=0)
     {
         if (empty($date))
         {
@@ -1625,20 +1626,46 @@ class Propal extends CommonObject
 
         if (! empty($user->rights->propal->creer))
         {
+        	$error=0;
+
+        	$this->db->begin();
+
             $sql = "UPDATE ".MAIN_DB_PREFIX."propal SET datep = '".$this->db->idate($date)."'";
             $sql.= " WHERE rowid = ".$this->id." AND fk_statut = ".self::STATUS_DRAFT;
 
-            dol_syslog(get_class($this)."::set_date", LOG_DEBUG);
-            if ($this->db->query($sql) )
+            dol_syslog(__METHOD__, LOG_DEBUG);
+            $resql=$this->db->query($sql);
+            if (!$resql)
+            {
+            	$this->errors[]=$this->db->error();
+            	$error++;
+            }
+
+            if (! $notrigger && empty($error))
             {
-                $this->date = $date;
+            	// Call trigger
+            	$result=$this->call_trigger('PROPAL_MODIFY',$user);
+            	if ($result < 0) $error++;
+            	// End call triggers
+            }
+
+            if (! $error)
+            {
+            	$this->date = $date;
                 $this->datep = $date;    // deprecated
-                return 1;
+
+            	$this->db->commit();
+            	return 1;
             }
             else
             {
-                $this->error=$this->db->lasterror();
-                return -1;
+            	foreach($this->errors as $errmsg)
+            	{
+            		dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
+            		$this->error.=($this->error?', '.$errmsg:$errmsg);
+            	}
+            	$this->db->rollback();
+            	return -1*$error;
             }
         }
     }
@@ -1646,25 +1673,54 @@ class Propal extends CommonObject
     /**
      *	Define end validity date
      *
-     *	@param		User		$user        		Object user that modify
-     *	@param      int			$date_fin_validite	End of validity date
-     *	@return     int         					<0 if KO, >0 if OK
+     *	@param		User	$user        		Object user that modify
+     *	@param      int		$date_fin_validite	End of validity date
+     *  @param  	int		$notrigger			1=Does not execute triggers, 0= execuete triggers
+     *	@return     int         				<0 if KO, >0 if OK
      */
-    function set_echeance($user, $date_fin_validite)
+    function set_echeance($user, $date_fin_validite, $notrigger=0)
     {
         if (! empty($user->rights->propal->creer))
         {
+        	$error=0;
+
+        	$this->db->begin();
+
             $sql = "UPDATE ".MAIN_DB_PREFIX."propal SET fin_validite = ".($date_fin_validite!=''?"'".$this->db->idate($date_fin_validite)."'":'null');
             $sql.= " WHERE rowid = ".$this->id." AND fk_statut = ".self::STATUS_DRAFT;
-            if ($this->db->query($sql) )
+
+            dol_syslog(__METHOD__, LOG_DEBUG);
+            $resql=$this->db->query($sql);
+            if (!$resql)
             {
-                $this->fin_validite = $date_fin_validite;
-                return 1;
+            	$this->errors[]=$this->db->error();
+            	$error++;
+            }
+
+            if (! $notrigger && empty($error))
+            {
+            	// Call trigger
+            	$result=$this->call_trigger('PROPAL_MODIFY',$user);
+            	if ($result < 0) $error++;
+            	// End call triggers
+            }
+
+            if (! $error)
+            {
+				$this->fin_validite = $date_fin_validite;
+
+            	$this->db->commit();
+            	return 1;
             }
             else
             {
-                $this->error=$this->db->error();
-                return -1;
+            	foreach($this->errors as $errmsg)
+            	{
+            		dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
+            		$this->error.=($this->error?', '.$errmsg:$errmsg);
+            	}
+            	$this->db->rollback();
+            	return -1*$error;
             }
         }
     }
@@ -1672,28 +1728,55 @@ class Propal extends CommonObject
     /**
      *	Set delivery date
      *
-     *	@param      User 		$user        		Object user that modify
-     *	@param      int			$date_livraison     Delivery date
-     *	@return     int         					<0 if ko, >0 if ok
+     *	@param      User 	$user        		Object user that modify
+     *	@param      int		$date_livraison     Delivery date
+     *  @param  	int		$notrigger			1=Does not execute triggers, 0= execuete triggers
+     *	@return     int         				<0 if ko, >0 if ok
      */
-    function set_date_livraison($user, $date_livraison)
+    function set_date_livraison($user, $date_livraison, $notrigger=0)
     {
         if (! empty($user->rights->propal->creer))
         {
+        	$error=0;
+
+        	$this->db->begin();
+
             $sql = "UPDATE ".MAIN_DB_PREFIX."propal ";
             $sql.= " SET date_livraison = ".($date_livraison!=''?"'".$this->db->idate($date_livraison)."'":'null');
             $sql.= " WHERE rowid = ".$this->id;
 
-            if ($this->db->query($sql))
+            dol_syslog(__METHOD__, LOG_DEBUG);
+            $resql=$this->db->query($sql);
+            if (!$resql)
             {
-                $this->date_livraison = $date_livraison;
-                return 1;
+            	$this->errors[]=$this->db->error();
+            	$error++;
+            }
+
+            if (! $notrigger && empty($error))
+            {
+            	// Call trigger
+            	$result=$this->call_trigger('PROPAL_MODIFY',$user);
+            	if ($result < 0) $error++;
+            	// End call triggers
+            }
+
+            if (! $error)
+            {
+            	$this->date_livraison = $date_livraison;
+
+            	$this->db->commit();
+            	return 1;
             }
             else
             {
-                $this->error=$this->db->error();
-                dol_syslog(get_class($this)."::set_date_livraison Erreur SQL");
-                return -1;
+            	foreach($this->errors as $errmsg)
+            	{
+            		dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
+            		$this->error.=($this->error?', '.$errmsg:$errmsg);
+            	}
+            	$this->db->rollback();
+            	return -1*$error;
             }
         }
     }
@@ -1703,26 +1786,53 @@ class Propal extends CommonObject
      *
      *  @param		User	$user		  	Object user that modify
      *  @param      int		$id				Availability id
+     *  @param  	int		$notrigger		1=Does not execute triggers, 0= execuete triggers
      *  @return     int           			<0 if KO, >0 if OK
      */
-    function set_availability($user, $id)
+    function set_availability($user, $id, $notrigger=0)
     {
         if (! empty($user->rights->propal->creer))
         {
+        	$error=0;
+
+        	$this->db->begin();
+
             $sql = "UPDATE ".MAIN_DB_PREFIX."propal ";
             $sql.= " SET fk_availability = '".$id."'";
             $sql.= " WHERE rowid = ".$this->id;
 
-            if ($this->db->query($sql))
+            dol_syslog(__METHOD__, LOG_DEBUG);
+            $resql=$this->db->query($sql);
+            if (!$resql)
             {
-                $this->fk_availability = $id;
-                return 1;
+            	$this->errors[]=$this->db->error();
+            	$error++;
+            }
+
+            if (! $notrigger && empty($error))
+            {
+            	// Call trigger
+            	$result=$this->call_trigger('PROPAL_MODIFY',$user);
+            	if ($result < 0) $error++;
+            	// End call triggers
+            }
+
+            if (! $error)
+            {
+            	$this->fk_availability = $id;
+
+            	$this->db->commit();
+            	return 1;
             }
             else
             {
-                $this->error=$this->db->error();
-                dol_syslog(get_class($this)."::set_availability Erreur SQL");
-                return -1;
+            	foreach($this->errors as $errmsg)
+            	{
+            		dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
+            		$this->error.=($this->error?', '.$errmsg:$errmsg);
+            	}
+            	$this->db->rollback();
+            	return -1*$error;
             }
         }
     }
@@ -1732,26 +1842,53 @@ class Propal extends CommonObject
      *
      *  @param		User	$user		Object user that modify
      *  @param      int		$id			Input reason id
+     *  @param  	int		$notrigger	1=Does not execute triggers, 0= execuete triggers
      *  @return     int           		<0 if KO, >0 if OK
      */
-    function set_demand_reason($user, $id)
+    function set_demand_reason($user, $id, $notrigger=0)
     {
         if (! empty($user->rights->propal->creer))
         {
+        	$error=0;
+
+        	$this->db->begin();
+
             $sql = "UPDATE ".MAIN_DB_PREFIX."propal ";
             $sql.= " SET fk_input_reason = '".$id."'";
             $sql.= " WHERE rowid = ".$this->id;
 
-            if ($this->db->query($sql))
+            dol_syslog(__METHOD__, LOG_DEBUG);
+            $resql=$this->db->query($sql);
+            if (!$resql)
             {
-                $this->fk_input_reason = $id;
-                return 1;
+            	$this->errors[]=$this->db->error();
+            	$error++;
+            }
+
+            if (! $notrigger && empty($error))
+            {
+            	// Call trigger
+            	$result=$this->call_trigger('PROPAL_MODIFY',$user);
+            	if ($result < 0) $error++;
+            	// End call triggers
+            }
+
+            if (! $error)
+            {
+            	$this->fk_input_reason = $id;
+
+            	$this->db->commit();
+            	return 1;
             }
             else
             {
-                $this->error=$this->db->error();
-                dol_syslog(get_class($this)."::set_demand_reason Erreur SQL");
-                return -1;
+            	foreach($this->errors as $errmsg)
+            	{
+            		dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
+            		$this->error.=($this->error?', '.$errmsg:$errmsg);
+            	}
+            	$this->db->rollback();
+            	return -1*$error;
             }
         }
     }
@@ -1761,26 +1898,52 @@ class Propal extends CommonObject
      *
      *  @param      User	$user			Object user that modify
      *  @param      string	$ref_client		Customer reference
+     *  @param  	int		$notrigger		1=Does not execute triggers, 0= execuete triggers
      *  @return     int						<0 if ko, >0 if ok
      */
-    function set_ref_client($user, $ref_client)
+    function set_ref_client($user, $ref_client, $notrigger=0)
     {
         if (! empty($user->rights->propal->creer))
         {
-            dol_syslog('Propale::set_ref_client this->id='.$this->id.', ref_client='.$ref_client);
+            $error=0;
+
+            $this->db->begin();
 
             $sql = 'UPDATE '.MAIN_DB_PREFIX.'propal SET ref_client = '.(empty($ref_client) ? 'NULL' : '\''.$this->db->escape($ref_client).'\'');
             $sql.= ' WHERE rowid = '.$this->id;
-            if ($this->db->query($sql) )
+
+            dol_syslog(__METHOD__.' $this->id='.$this->id.', ref_client='.$ref_client, LOG_DEBUG);
+            $resql=$this->db->query($sql);
+            if (!$resql)
             {
-                $this->ref_client = $ref_client;
-                return 1;
+            	$this->errors[]=$this->db->error();
+            	$error++;
+            }
+
+            if (! $notrigger && empty($error))
+            {
+            	// Call trigger
+            	$result=$this->call_trigger('PROPAL_MODIFY',$user);
+            	if ($result < 0) $error++;
+            	// End call triggers
+            }
+
+            if (! $error)
+            {
+            	$this->ref_client = $ref_client;
+
+            	$this->db->commit();
+            	return 1;
             }
             else
             {
-                $this->error=$this->db->error();
-                dol_syslog('Propale::set_ref_client Erreur '.$this->error.' - '.$sql);
-                return -2;
+            	foreach($this->errors as $errmsg)
+            	{
+            		dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
+            		$this->error.=($this->error?', '.$errmsg:$errmsg);
+            	}
+            	$this->db->rollback();
+            	return -1*$error;
             }
         }
         else
@@ -1793,10 +1956,11 @@ class Propal extends CommonObject
      *	Set an overall discount on the proposal
      *
      *	@param      User	$user       Object user that modify
-     *	@param      double	$remise      Amount discount
+     *	@param      double	$remise     Amount discount
+     *  @param  	int		$notrigger	1=Does not execute triggers, 0= execuete triggers
      *	@return     int         		<0 if ko, >0 if ok
      */
-    function set_remise_percent($user, $remise)
+    function set_remise_percent($user, $remise, $notrigger=0)
     {
         $remise=trim($remise)?trim($remise):0;
 
@@ -1804,19 +1968,46 @@ class Propal extends CommonObject
         {
             $remise = price2num($remise);
 
+            $error=0;
+
+            $this->db->begin();
+
             $sql = "UPDATE ".MAIN_DB_PREFIX."propal SET remise_percent = ".$remise;
             $sql.= " WHERE rowid = ".$this->id." AND fk_statut = ".self::STATUS_DRAFT;
 
-            if ($this->db->query($sql) )
+            dol_syslog(__METHOD__, LOG_DEBUG);
+            $resql=$this->db->query($sql);
+            if (!$resql)
             {
-                $this->remise_percent = $remise;
+            	$this->errors[]=$this->db->error();
+            	$error++;
+            }
+
+            if (! $notrigger && empty($error))
+            {
+            	// Call trigger
+            	$result=$this->call_trigger('PROPAL_MODIFY',$user);
+            	if ($result < 0) $error++;
+            	// End call triggers
+            }
+
+            if (! $error)
+            {
+            	$this->remise_percent = $remise;
                 $this->update_price(1);
-                return 1;
+
+            	$this->db->commit();
+            	return 1;
             }
             else
             {
-                $this->error=$this->db->error();
-                return -1;
+            	foreach($this->errors as $errmsg)
+            	{
+            		dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
+            		$this->error.=($this->error?', '.$errmsg:$errmsg);
+            	}
+            	$this->db->rollback();
+            	return -1*$error;
             }
         }
     }
@@ -1825,11 +2016,12 @@ class Propal extends CommonObject
     /**
      *	Set an absolute overall discount on the proposal
      *
-     *	@param      User	$user        Object user that modify
-     *	@param      double	$remise      Amount discount
+     *	@param      User	$user       Object user that modify
+     *	@param      double	$remise     Amount discount
+     *  @param  	int		$notrigger	1=Does not execute triggers, 0= execuete triggers
      *	@return     int         		<0 if ko, >0 if ok
      */
-    function set_remise_absolue($user, $remise)
+    function set_remise_absolue($user, $remise, $notrigger=0)
     {
         $remise=trim($remise)?trim($remise):0;
 
@@ -1837,20 +2029,47 @@ class Propal extends CommonObject
         {
             $remise = price2num($remise);
 
+            $error=0;
+
+            $this->db->begin();
+
             $sql = "UPDATE ".MAIN_DB_PREFIX."propal ";
             $sql.= " SET remise_absolue = ".$remise;
             $sql.= " WHERE rowid = ".$this->id." AND fk_statut = ".self::STATUS_DRAFT;
 
-            if ($this->db->query($sql) )
+            dol_syslog(__METHOD__, LOG_DEBUG);
+            $resql=$this->db->query($sql);
+            if (!$resql)
+            {
+            	$this->errors[]=$this->db->error();
+            	$error++;
+            }
+
+            if (! $notrigger && empty($error))
+            {
+            	// Call trigger
+            	$result=$this->call_trigger('PROPAL_MODIFY',$user);
+            	if ($result < 0) $error++;
+            	// End call triggers
+            }
+
+            if (! $error)
             {
-                $this->remise_absolue = $remise;
+            	$this->remise_absolue = $remise;
                 $this->update_price(1);
-                return 1;
+
+            	$this->db->commit();
+            	return 1;
             }
             else
             {
-                $this->error=$this->db->error();
-                return -1;
+            	foreach($this->errors as $errmsg)
+            	{
+            		dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
+            		$this->error.=($this->error?', '.$errmsg:$errmsg);
+            	}
+            	$this->db->rollback();
+            	return -1*$error;
             }
         }
     }
@@ -1924,9 +2143,10 @@ class Propal extends CommonObject
      *	@param      User	$user		Object user that close
      *	@param      int		$statut		Statut
      *	@param      string	$note		Comment
+     *  @param		int		$notrigger	1=Does not execute triggers, 0= execuete triggers
      *	@return     int         		<0 if KO, >0 if OK
      */
-    function cloture($user, $statut, $note)
+    function cloture($user, $statut, $note, $notrigger=0)
     {
         global $langs,$conf;
 
@@ -1981,10 +2201,13 @@ class Propal extends CommonObject
 	               $this->generateDocument($modelpdf, $outputlangs);
             }
 
-            // Call trigger
-            $result=$this->call_trigger($trigger_name,$user);
-            if ($result < 0) { $error++; }
-            // End call triggers
+            if (! $notrigger && empty($error))
+            {
+	            // Call trigger
+	            $result=$this->call_trigger($trigger_name,$user);
+	            if ($result < 0) { $error++; }
+	            // End call triggers
+            }
 
             if ( ! $error )
             {
@@ -2010,20 +2233,51 @@ class Propal extends CommonObject
     /**
      *	Class invoiced the Propal
      *
-     *	@return     int     	<0 si ko, >0 si ok
+     *	@param  	User	$user    	Object user
+     *  @param		int		$notrigger	1=Does not execute triggers, 0= execuete triggers
+     *	@return     int     			<0 si ko, >0 si ok
      */
-    function classifyBilled()
+    function classifyBilled(User $user, $notrigger=0)
     {
+    	$error=0;
+
+    	$this->db->begin();
+
         $sql = 'UPDATE '.MAIN_DB_PREFIX.'propal SET fk_statut = '.self::STATUS_BILLED;
         $sql .= ' WHERE rowid = '.$this->id.' AND fk_statut > '.self::STATUS_DRAFT.' ;';
-        if ($this->db->query($sql) )
+
+        dol_syslog(__METHOD__, LOG_DEBUG);
+        $resql=$this->db->query($sql);
+        if (!$resql)
+        {
+        	$this->errors[]=$this->db->error();
+        	$error++;
+        }
+
+        if (! $notrigger && empty($error))
+        {
+        	// Call trigger
+        	$result=$this->call_trigger('PROPAL_MODIFY',$user);
+        	if ($result < 0) $error++;
+        	// End call triggers
+        }
+
+        if (! $error)
         {
         	$this->statut=self::STATUS_BILLED;
-            return 1;
+
+        	$this->db->commit();
+        	return 1;
         }
         else
         {
-            dol_print_error($this->db);
+        	foreach($this->errors as $errmsg)
+        	{
+        		dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
+        		$this->error.=($this->error?', '.$errmsg:$errmsg);
+        	}
+        	$this->db->rollback();
+        	return -1*$error;
         }
     }
 
@@ -2032,7 +2286,7 @@ class Propal extends CommonObject
      *
      *	@return     int     	<0 si ko, >0 si ok
      *  @deprecated
-     * @see classifyBilled()
+     *  @see classifyBilled()
      */
     function classer_facturee()
     {
@@ -2046,22 +2300,51 @@ class Propal extends CommonObject
      *	Set draft status
      *
      *	@param		User	$user		Object user that modify
+     *  @param		int		$notrigger	1=Does not execute triggers, 0= execuete triggers
      *	@return		int					<0 if KO, >0 if OK
      */
-    function set_draft($user)
+    function set_draft($user, $notrigger=0)
     {
+    	$error=0;
+
+    	$this->db->begin();
+
         $sql = "UPDATE ".MAIN_DB_PREFIX."propal SET fk_statut = ".self::STATUS_DRAFT;
         $sql.= " WHERE rowid = ".$this->id;
 
-        if ($this->db->query($sql))
+        dol_syslog(__METHOD__, LOG_DEBUG);
+        $resql=$this->db->query($sql);
+        if (!$resql)
         {
-            $this->statut = self::STATUS_DRAFT;
+        	$this->errors[]=$this->db->error();
+        	$error++;
+        }
+
+        if (! $notrigger && empty($error))
+        {
+        	// Call trigger
+        	$result=$this->call_trigger('PROPAL_MODIFY',$user);
+        	if ($result < 0) $error++;
+        	// End call triggers
+        }
+
+        if (! $error)
+        {
+        	$this->statut = self::STATUS_DRAFT;
             $this->brouillon = 1;
-            return 1;
+
+        	$this->db->commit();
+        	return 1;
         }
         else
         {
-            return -1;
+        	foreach($this->errors as $errmsg)
+        	{
+        		dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
+        		$this->error.=($this->error?', '.$errmsg:$errmsg);
+        	}
+        	$this->db->rollback();
+        	return -1*$error;
         }
     }
 
@@ -2364,32 +2647,61 @@ class Propal extends CommonObject
      *  Change the delivery time
      *
      *  @param	int	$availability_id	Id of new delivery time
+     * 	@param	int	$notrigger			1=Does not execute triggers, 0= execuete triggers
      *  @return int                  	>0 if OK, <0 if KO
      */
-    function availability($availability_id)
+    function availability($availability_id, $notrigger=0)
     {
-        dol_syslog('Propale::availability('.$availability_id.')');
         if ($this->statut >= self::STATUS_DRAFT)
         {
+        	$error=0;
+
+        	$this->db->begin();
+
             $sql = 'UPDATE '.MAIN_DB_PREFIX.'propal';
             $sql .= ' SET fk_availability = '.$availability_id;
             $sql .= ' WHERE rowid='.$this->id;
-            if ( $this->db->query($sql) )
+
+            dol_syslog(__METHOD__.' availability('.$availability_id.')', LOG_DEBUG);
+            $resql=$this->db->query($sql);
+            if (!$resql)
             {
-                $this->availability_id = $availability_id;
-                return 1;
+            	$this->errors[]=$this->db->error();
+            	$error++;
+            }
+
+            if (! $notrigger && empty($error))
+            {
+            	// Call trigger
+            	$result=$this->call_trigger('PROPAL_MODIFY',$user);
+            	if ($result < 0) $error++;
+            	// End call triggers
+            }
+
+            if (! $error)
+            {
+            	$this->availability_id = $availability_id;
+
+            	$this->db->commit();
+            	return 1;
             }
             else
             {
-                dol_syslog('Propale::availability Erreur '.$sql.' - '.$this->db->error());
-                $this->error=$this->db->error();
-                return -1;
+            	foreach($this->errors as $errmsg)
+            	{
+            		dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
+            		$this->error.=($this->error?', '.$errmsg:$errmsg);
+            	}
+            	$this->db->rollback();
+            	return -1*$error;
             }
         }
         else
         {
-            dol_syslog('Propale::availability, etat propale incompatible');
-            $this->error='Etat propale incompatible '.$this->statut;
+        	$error_str='Propal status do not meet requirement '.$this->statut;
+        	dol_syslog(__METHOD__.$error_str, LOG_ERR);
+        	$this->error=$error_str;
+        	$this->errors[]= $this->error;
             return -2;
         }
     }
@@ -2398,32 +2710,61 @@ class Propal extends CommonObject
      *	Change source demand
      *
      *	@param	int $demand_reason_id 	Id of new source demand
+     * 	@param	int	$notrigger			1=Does not execute triggers, 0= execuete triggers
      *	@return int						>0 si ok, <0 si ko
      */
-    function demand_reason($demand_reason_id)
+    function demand_reason($demand_reason_id, $notrigger=0)
     {
-        dol_syslog('Propale::demand_reason('.$demand_reason_id.')');
         if ($this->statut >= self::STATUS_DRAFT)
         {
+        	$error=0;
+
+        	$this->db->begin();
+
             $sql = 'UPDATE '.MAIN_DB_PREFIX.'propal';
             $sql .= ' SET fk_input_reason = '.$demand_reason_id;
             $sql .= ' WHERE rowid='.$this->id;
-            if ( $this->db->query($sql) )
+
+            dol_syslog(__METHOD__.' demand_reason('.$demand_reason_id.')', LOG_DEBUG);
+            $resql=$this->db->query($sql);
+            if (!$resql)
             {
-                $this->demand_reason_id = $demand_reason_id;
-                return 1;
+            	$this->errors[]=$this->db->error();
+            	$error++;
+            }
+
+            if (! $notrigger && empty($error))
+            {
+            	// Call trigger
+            	$result=$this->call_trigger('PROPAL_MODIFY',$user);
+            	if ($result < 0) $error++;
+            	// End call triggers
+            }
+
+            if (! $error)
+            {
+            	$this->demand_reason_id = $demand_reason_id;
+
+            	$this->db->commit();
+            	return 1;
             }
             else
             {
-                dol_syslog('Propale::demand_reason Erreur '.$sql.' - '.$this->db->error());
-                $this->error=$this->db->error();
-                return -1;
+            	foreach($this->errors as $errmsg)
+            	{
+            		dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
+            		$this->error.=($this->error?', '.$errmsg:$errmsg);
+            	}
+            	$this->db->rollback();
+            	return -1*$error;
             }
         }
         else
         {
-            dol_syslog('Propale::demand_reason, etat propale incompatible');
-            $this->error='Etat propale incompatible '.$this->statut;
+        	$error_str='Propal status do not meet requirement '.$this->statut;
+        	dol_syslog(__METHOD__.$error_str, LOG_ERR);
+        	$this->error=$error_str;
+        	$this->errors[]= $this->error;
             return -2;
         }
     }
@@ -2507,21 +2848,21 @@ class Propal extends CommonObject
      */
      function LibStatut($statut,$mode=1)
     {
-	global $langs;
-	$langs->load("propal");
-
-	if ($statut==self::STATUS_DRAFT) $statuttrans='statut0';
-	if ($statut==self::STATUS_VALIDATED) $statuttrans='statut1';
-	if ($statut==self::STATUS_SIGNED) $statuttrans='statut3';
-	if ($statut==self::STATUS_NOTSIGNED) $statuttrans='statut5';
-	if ($statut==self::STATUS_BILLED) $statuttrans='statut6';
-
-	if ($mode == 0)	return $this->labelstatut[$statut];
-	if ($mode == 1)	return $this->labelstatut_short[$statut];
-	if ($mode == 2)	return img_picto($this->labelstatut_short[$statut], $statuttrans).' '.$this->labelstatut_short[$statut];
-	if ($mode == 3)	return img_picto($this->labelstatut[$statut], $statuttrans);
-	if ($mode == 4)	return img_picto($this->labelstatut[$statut],$statuttrans).' '.$this->labelstatut[$statut];
-	if ($mode == 5)	return '<span class="hideonsmartphone">'.$this->labelstatut_short[$statut].' </span>'.img_picto($this->labelstatut_short[$statut],$statuttrans);
+		global $langs;
+		$langs->load("propal");
+
+		if ($statut==self::STATUS_DRAFT) $statuttrans='statut0';
+		if ($statut==self::STATUS_VALIDATED) $statuttrans='statut1';
+		if ($statut==self::STATUS_SIGNED) $statuttrans='statut3';
+		if ($statut==self::STATUS_NOTSIGNED) $statuttrans='statut5';
+		if ($statut==self::STATUS_BILLED) $statuttrans='statut6';
+
+		if ($mode == 0)	return $this->labelstatut[$statut];
+		if ($mode == 1)	return $this->labelstatut_short[$statut];
+		if ($mode == 2)	return img_picto($this->labelstatut_short[$statut], $statuttrans).' '.$this->labelstatut_short[$statut];
+		if ($mode == 3)	return img_picto($this->labelstatut[$statut], $statuttrans);
+		if ($mode == 4)	return img_picto($this->labelstatut[$statut],$statuttrans).' '.$this->labelstatut[$statut];
+		if ($mode == 5)	return '<span class="hideonsmartphone">'.$this->labelstatut_short[$statut].' </span>'.img_picto($this->labelstatut_short[$statut],$statuttrans);
     }
 
 
@@ -2681,7 +3022,7 @@ class Propal extends CommonObject
             	$prodid = mt_rand(1, $num_prods);
             	$line->fk_product=$prodids[$prodid];
             }
-            
+
             $this->lines[$xnbp]=$line;
 
             $this->total_ht       += $line->total_ht;
@@ -2851,7 +3192,7 @@ class Propal extends CommonObject
     function getLinesArray()
     {
         // For other object, here we call fetch_lines. But fetch_lines does not exists on proposal
-        
+
         $sql = 'SELECT pt.rowid, pt.label as custom_label, pt.description, pt.fk_product, pt.fk_remise_except,';
         $sql.= ' pt.qty, pt.tva_tx, pt.remise_percent, pt.subprice, pt.info_bits,';
         $sql.= ' pt.total_ht, pt.total_tva, pt.total_ttc, pt.fk_product_fournisseur_price as fk_fournprice, pt.buy_price_ht as pa_ht, pt.special_code, pt.localtax1_tx, pt.localtax2_tx,';
@@ -2911,7 +3252,7 @@ class Propal extends CommonObject
                 $this->lines[$i]->date_start		= $this->db->jdate($obj->date_start);
                 $this->lines[$i]->date_end			= $this->db->jdate($obj->date_end);
 	            $this->lines[$i]->fk_unit			= $obj->fk_unit;
-				
+
 				// Multicurrency
 				$this->lines[$i]->fk_multicurrency 			= $obj->fk_multicurrency;
 				$this->lines[$i]->multicurrency_code 		= $obj->multicurrency_code;
@@ -3096,7 +3437,7 @@ class PropaleLigne  extends CommonObjectLine
 	var $multicurrency_total_ht;
 	var $multicurrency_total_tva;
 	var $multicurrency_total_ttc;
-	
+
     /**
      * 	Class line Contructor
      *
@@ -3180,7 +3521,7 @@ class PropaleLigne  extends CommonObjectLine
 			$this->multicurrency_total_ht 	= $objp->multicurrency_total_ht;
 			$this->multicurrency_total_tva 	= $objp->multicurrency_total_tva;
 			$this->multicurrency_total_ttc 	= $objp->multicurrency_total_ttc;
-	
+
 			$this->db->free($result);
 
             return 1;
@@ -3206,7 +3547,7 @@ class PropaleLigne  extends CommonObjectLine
         dol_syslog(get_class($this)."::insert rang=".$this->rang);
 
         $pa_ht_isemptystring = (empty($this->pa_ht) && $this->pa_ht == ''); // If true, we can use a default value. If this->pa_ht = '0', we must use '0'.
-        
+
         // Clean parameters
         if (empty($this->tva_tx)) $this->tva_tx=0;
         if (empty($this->localtax1_tx)) $this->localtax1_tx=0;
@@ -3226,7 +3567,7 @@ class PropaleLigne  extends CommonObjectLine
         if (empty($this->pa_ht)) $this->pa_ht=0;
 
        // if buy price not defined, define buyprice as configured in margin admin
-		if ($this->pa_ht == 0 && $pa_ht_isemptystring) 
+		if ($this->pa_ht == 0 && $pa_ht_isemptystring)
 		{
 			if (($result = $this->defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product)) < 0)
 			{
@@ -3391,7 +3732,7 @@ class PropaleLigne  extends CommonObjectLine
         $error=0;
 
         $pa_ht_isemptystring = (empty($this->pa_ht) && $this->pa_ht == ''); // If true, we can use a default value. If this->pa_ht = '0', we must use '0'.
-        
+
         // Clean parameters
         if (empty($this->tva_tx)) $this->tva_tx=0;
         if (empty($this->localtax1_tx)) $this->localtax1_tx=0;
@@ -3413,7 +3754,7 @@ class PropaleLigne  extends CommonObjectLine
 		if (empty($this->pa_ht)) $this->pa_ht=0;
 
 		// if buy price not defined, define buyprice as configured in margin admin
-		if ($this->pa_ht == 0 && $pa_ht_isemptystring) 
+		if ($this->pa_ht == 0 && $pa_ht_isemptystring)
 		{
 			if (($result = $this->defineBuyPrice($this->subprice, $this->remise_percent, $this->fk_product)) < 0)
 			{
@@ -3459,13 +3800,13 @@ class PropaleLigne  extends CommonObjectLine
         $sql.= " , date_start=".(! empty($this->date_start)?"'".$this->db->idate($this->date_start)."'":"null");
         $sql.= " , date_end=".(! empty($this->date_end)?"'".$this->db->idate($this->date_end)."'":"null");
 	    $sql.= " , fk_unit=".(!$this->fk_unit ? 'NULL' : $this->fk_unit);
-		
+
 		// Multicurrency
 		$sql.= " , multicurrency_subprice=".price2num($this->multicurrency_subprice)."";
         $sql.= " , multicurrency_total_ht=".price2num($this->multicurrency_total_ht)."";
         $sql.= " , multicurrency_total_tva=".price2num($this->multicurrency_total_tva)."";
         $sql.= " , multicurrency_total_ttc=".price2num($this->multicurrency_total_ttc)."";
-		
+
         $sql.= " WHERE rowid = ".$this->rowid;
 
         dol_syslog(get_class($this)."::update", LOG_DEBUG);
diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php
index 08fe1f19861..b762ed4de24 100644
--- a/htdocs/commande/class/commande.class.php
+++ b/htdocs/commande/class/commande.class.php
@@ -469,7 +469,7 @@ class Commande extends CommonOrder
 
             if (!$error) {
             	// Call trigger
-            	$result=$this->call_trigger('ORDER_SETDRAFT',$user);
+            	$result=$this->call_trigger('ORDER_UNVALIDATE',$user);
             	if ($result < 0) $error++;
             }
 
@@ -2044,7 +2044,7 @@ class Commande extends CommonOrder
      *
      * 	@param     	User		$user		User qui positionne la remise
      * 	@param     	float		$remise		Discount (percent)
-     * 	@param     	int			$notrigger	Not Trigger
+     * 	@param     	int			$notrigger	1=Does not execute triggers, 0= execuete triggers
      *	@return		int 					<0 if KO, >0 if OK
      */
     function set_remise($user, $remise, $notrigger=0)
@@ -2063,6 +2063,7 @@ class Commande extends CommonOrder
             $sql.= ' SET remise_percent = '.$remise;
             $sql.= ' WHERE rowid = '.$this->id.' AND fk_statut = '.self::STATUS_DRAFT.' ;';
 
+            dol_syslog(__METHOD__, LOG_DEBUG);
             $resql=$this->db->query($sql);
             if (!$resql)
             {
@@ -2105,7 +2106,7 @@ class Commande extends CommonOrder
      *
      * 		@param     	User		$user 		User qui positionne la remise
      * 		@param     	float		$remise		Discount
-     * 		@param     	int			$notrigger	Not Trigger
+     * 		@param     	int			$notrigger	1=Does not execute triggers, 0= execuete triggers
      *		@return		int 					<0 if KO, >0 if OK
      */
     function set_remise_absolue($user, $remise, $notrigger=0)
@@ -2125,7 +2126,6 @@ class Commande extends CommonOrder
             $sql.= ' WHERE rowid = '.$this->id.' AND fk_statut = '.self::STATUS_DRAFT.' ;';
 
             dol_syslog(__METHOD__, LOG_DEBUG);
-
             $resql=$this->db->query($sql);
             if (!$resql)
             {
@@ -2168,14 +2168,13 @@ class Commande extends CommonOrder
      *
      *	@param      User	$user       Object user making change
      *	@param      int		$date		Date
-     * 	@param     	int		$notrigger	Not Trigger
+     * 	@param     	int		$notrigger	1=Does not execute triggers, 0= execuete triggers
      *	@return     int         		<0 if KO, >0 if OK
      */
     function set_date($user, $date, $notrigger=0)
     {
         if ($user->rights->commande->creer)
         {
-
         	$error=0;
 
         	$this->db->begin();
@@ -2229,13 +2228,17 @@ class Commande extends CommonOrder
      *
      *	@param      User	$user        		Objet utilisateur qui modifie
      *	@param      int		$date_livraison     Date de livraison
-     *  @param     	int		$notrigger			Not Trigger
+     *  @param     	int		$notrigger			1=Does not execute triggers, 0= execuete triggers
      *	@return     int         				<0 si ko, >0 si ok
      */
     function set_date_livraison($user, $date_livraison, $notrigger=0)
     {
         if ($user->rights->commande->creer)
         {
+        	$error=0;
+
+        	$this->db->begin();
+
             $sql = "UPDATE ".MAIN_DB_PREFIX."commande";
             $sql.= " SET date_livraison = ".($date_livraison ? "'".$this->db->idate($date_livraison)."'" : 'null');
             $sql.= " WHERE rowid = ".$this->id;
@@ -2285,13 +2288,17 @@ class Commande extends CommonOrder
      *
      *	@param      User	$user		Object user making change
      *	@param      int		$id			If of availability delay
-     *  @param     	int		$notrigger	Not Trigger
+     *  @param     	int		$notrigger	1=Does not execute triggers, 0= execuete triggers
      *	@return     int           		<0 if KO, >0 if OK
      */
     function set_availability($user, $id, $notrigger=0)
     {
         if ($user->rights->commande->creer)
         {
+        	$error=0;
+
+        	$this->db->begin();
+
             $sql = "UPDATE ".MAIN_DB_PREFIX."commande ";
             $sql.= " SET fk_availability = '".$id."'";
             $sql.= " WHERE rowid = ".$this->id;
@@ -2337,13 +2344,18 @@ class Commande extends CommonOrder
      *
      *	@param      User	$user		Object user making change
      *	@param      int		$id			Id of source
-     *  @param     	int		$notrigger	Not Trigger
+     *  @param     	int		$notrigger	1=Does not execute triggers, 0= execuete triggers
      *	@return     int           		<0 if KO, >0 if OK
      */
     function set_demand_reason($user, $id, $notrigger=0)
     {
         if ($user->rights->commande->creer)
         {
+
+        	$error=0;
+
+        	$this->db->begin();
+
             $sql = "UPDATE ".MAIN_DB_PREFIX."commande ";
             $sql.= " SET fk_input_reason = '".$id."'";
             $sql.= " WHERE rowid = ".$this->id;
@@ -2461,7 +2473,7 @@ class Commande extends CommonOrder
      *	Update delivery delay
      *
      *	@param      int		$availability_id	Id du nouveau mode
-     *  @param     	int		$notrigger	Not Trigger
+     *  @param     	int		$notrigger			1=Does not execute triggers, 0= execuete triggers
      *	@return     int         				>0 if OK, <0 if KO
      */
     function availability($availability_id, $notrigger=0)
@@ -2469,6 +2481,10 @@ class Commande extends CommonOrder
         dol_syslog('Commande::availability('.$availability_id.')');
         if ($this->statut >= self::STATUS_DRAFT)
         {
+        	$error=0;
+
+        	$this->db->begin();
+
             $sql = 'UPDATE '.MAIN_DB_PREFIX.'commande';
             $sql .= ' SET fk_availability = '.$availability_id;
             $sql .= ' WHERE rowid='.$this->id;
@@ -2521,7 +2537,7 @@ class Commande extends CommonOrder
      *	Update order demand_reason
      *
      *  @param      int		$demand_reason_id	Id of new demand
-     *  @param     	int		$notrigger			Not Trigger
+     *  @param     	int		$notrigger			1=Does not execute triggers, 0= execuete triggers
      *  @return     int        			 		>0 if ok, <0 if ko
      */
     function demand_reason($demand_reason_id, $notrigger=0)
@@ -2529,6 +2545,10 @@ class Commande extends CommonOrder
         dol_syslog('Commande::demand_reason('.$demand_reason_id.')');
         if ($this->statut >= self::STATUS_DRAFT)
         {
+        	$error=0;
+
+        	$this->db->begin();
+
             $sql = 'UPDATE '.MAIN_DB_PREFIX.'commande';
             $sql .= ' SET fk_input_reason = '.$demand_reason_id;
             $sql .= ' WHERE rowid='.$this->id;
@@ -2582,12 +2602,17 @@ class Commande extends CommonOrder
      *
      *	@param      User	$user           User that make change
      *	@param      string	$ref_client     Customer ref
+     *  @param     	int		$notrigger		1=Does not execute triggers, 0= execuete triggers
      *	@return     int             		<0 if KO, >0 if OK
      */
-    function set_ref_client($user, $ref_client)
+    function set_ref_client($user, $ref_client, $notrigger=0)
     {
         if ($user->rights->commande->creer)
         {
+        	$error=0;
+
+        	$this->db->begin();
+
             $sql = 'UPDATE '.MAIN_DB_PREFIX.'commande SET';
             $sql.= ' ref_client = '.(empty($ref_client) ? 'NULL' : '\''.$this->db->escape($ref_client).'\'');
             $sql.= ' WHERE rowid = '.$this->id;
diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php
index 73127f9a1f2..089729b4440 100644
--- a/htdocs/compta/facture/class/facture.class.php
+++ b/htdocs/compta/facture/class/facture.class.php
@@ -1486,25 +1486,54 @@ class Facture extends CommonInvoice
 	 *	Set customer ref
 	 *
 	 *	@param     	string	$ref_client		Customer ref
+	 *  @param     	int		$notrigger		1=Does not execute triggers, 0= execuete triggers
 	 *	@return		int						<0 if KO, >0 if OK
 	 */
-	function set_ref_client($ref_client)
+	function set_ref_client($ref_client, $notrigger=0)
 	{
+		$error=0;
+
+		$this->db->begin();
+
 		$sql = 'UPDATE '.MAIN_DB_PREFIX.'facture';
 		if (empty($ref_client))
 			$sql .= ' SET ref_client = NULL';
 		else
 			$sql .= ' SET ref_client = \''.$this->db->escape($ref_client).'\'';
 		$sql .= ' WHERE rowid = '.$this->id;
-		if ($this->db->query($sql))
+
+		dol_syslog(__METHOD__.' this->id='.$this->id.', ref_client='.$ref_client, LOG_DEBUG);
+		$resql=$this->db->query($sql);
+		if (!$resql)
+		{
+			$this->errors[]=$this->db->error();
+			$error++;
+		}
+
+		if (! $notrigger && empty($error))
+		{
+			// Call trigger
+			$result=$this->call_trigger('BILL_MODIFY',$user);
+			if ($result < 0) $error++;
+			// End call triggers
+		}
+
+		if (! $error)
 		{
 			$this->ref_client = $ref_client;
+
+			$this->db->commit();
 			return 1;
 		}
 		else
 		{
-			dol_print_error($this->db);
-			return -1;
+			foreach($this->errors as $errmsg)
+			{
+				dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
+				$this->error.=($this->error?', '.$errmsg:$errmsg);
+			}
+			$this->db->rollback();
+			return -1*$error;
 		}
 	}
 
@@ -2070,7 +2099,7 @@ class Facture extends CommonInvoice
     					$i++;
     				}
     				if ($final) {
-    					$this->setFinal();
+    					$this->setFinal($user);
     				}
                 }
 			}
@@ -2760,9 +2789,10 @@ class Facture extends CommonInvoice
 	 *
 	 *	@param     	User	$user		User that set discount
 	 *	@param     	double	$remise		Discount
+	 *  @param     	int		$notrigger	1=Does not execute triggers, 0= execuete triggers
 	 *	@return		int 		<0 if ko, >0 if ok
 	 */
-	function set_remise($user, $remise)
+	function set_remise($user, $remise, $notrigger=0)
 	{
 		// Clean parameters
 		if (empty($remise)) $remise=0;
@@ -2771,21 +2801,48 @@ class Facture extends CommonInvoice
 		{
 			$remise=price2num($remise);
 
+			$error=0;
+
+			$this->db->begin();
+
 			$sql = 'UPDATE '.MAIN_DB_PREFIX.'facture';
 			$sql.= ' SET remise_percent = '.$remise;
 			$sql.= ' WHERE rowid = '.$this->id;
 			$sql.= ' AND fk_statut = '.self::STATUS_DRAFT;
 
-			if ($this->db->query($sql))
+			dol_syslog(__METHOD__, LOG_DEBUG);
+			$resql=$this->db->query($sql);
+			if (!$resql)
+			{
+				$this->errors[]=$this->db->error();
+				$error++;
+			}
+
+			if (! $notrigger && empty($error))
+			{
+				// Call trigger
+				$result=$this->call_trigger('BILL_MODIFY',$user);
+				if ($result < 0) $error++;
+				// End call triggers
+			}
+
+			if (! $error)
 			{
 				$this->remise_percent = $remise;
 				$this->update_price(1);
+
+				$this->db->commit();
 				return 1;
 			}
 			else
 			{
-				$this->error=$this->db->error();
-				return -1;
+				foreach($this->errors as $errmsg)
+				{
+					dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
+					$this->error.=($this->error?', '.$errmsg:$errmsg);
+				}
+				$this->db->rollback();
+				return -1*$error;
 			}
 		}
 	}
@@ -2796,14 +2853,19 @@ class Facture extends CommonInvoice
 	 *
 	 *	@param     	User	$user 		User that set discount
 	 *	@param     	double	$remise		Discount
+	 *  @param     	int		$notrigger	1=Does not execute triggers, 0= execuete triggers
 	 *	@return		int 				<0 if KO, >0 if OK
 	 */
-	function set_remise_absolue($user, $remise)
+	function set_remise_absolue($user, $remise, $notrigger=0)
 	{
 		if (empty($remise)) $remise=0;
 
 		if ($user->rights->facture->creer)
 		{
+			$error=0;
+
+			$this->db->begin();
+
 			$remise=price2num($remise);
 
 			$sql = 'UPDATE '.MAIN_DB_PREFIX.'facture';
@@ -2811,18 +2873,39 @@ class Facture extends CommonInvoice
 			$sql.= ' WHERE rowid = '.$this->id;
 			$sql.= ' AND fk_statut = '.self::STATUS_DRAFT;
 
-			dol_syslog(get_class($this)."::set_remise_absolue", LOG_DEBUG);
+			dol_syslog(__METHOD__, LOG_DEBUG);
+			$resql=$this->db->query($sql);
+			if (!$resql)
+			{
+				$this->errors[]=$this->db->error();
+				$error++;
+			}
 
-			if ($this->db->query($sql))
+			if (! $notrigger && empty($error))
+			{
+				// Call trigger
+				$result=$this->call_trigger('BILL_MODIFY',$user);
+				if ($result < 0) $error++;
+				// End call triggers
+			}
+
+			if (! $error)
 			{
 				$this->remise_absolue = $remise;
 				$this->update_price(1);
+
+				$this->db->commit();
 				return 1;
 			}
 			else
 			{
-				$this->error=$this->db->error();
-				return -1;
+				foreach($this->errors as $errmsg)
+				{
+					dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
+					$this->error.=($this->error?', '.$errmsg:$errmsg);
+				}
+				$this->db->rollback();
+				return -1*$error;
 			}
 		}
 	}
@@ -3818,25 +3901,49 @@ class Facture extends CommonInvoice
 	/**
 	 * Sets the invoice as a final situation
 	 *
-	 * @return int 1 if ok, -1 if error
+	 *  @param  	User	$user    	Object user
+	 *  @param     	int		$notrigger	1=Does not execute triggers, 0= execuete triggers
+	 *	@return		int 				<0 if KO, >0 if OK
 	 */
-	function setFinal()
+	function setFinal(User $user, $notrigger=0)
 	{
+		$error=0;
 
-        $this->db->begin();
+		$this->db->begin();
 
 		$this->situation_final = 1;
-		$sql = 'update ' . MAIN_DB_PREFIX . 'facture set situation_final = ' . $this->situation_final . ' where rowid = ' . $this->id;
-		$resql = $this->db->query($sql);
-		if ($resql) {
-			// FIXME: call triggers MODIFY because we modify invoice
+		$sql = 'UPDATE ' . MAIN_DB_PREFIX . 'facture SET situation_final = ' . $this->situation_final . ' where rowid = ' . $this->id;
+
+		dol_syslog(__METHOD__, LOG_DEBUG);
+		$resql=$this->db->query($sql);
+		if (!$resql)
+		{
+			$this->errors[]=$this->db->error();
+			$error++;
+		}
+
+		if (! $notrigger && empty($error))
+		{
+			// Call trigger
+			$result=$this->call_trigger('BILL_MODIFY',$user);
+			if ($result < 0) $error++;
+			// End call triggers
+		}
+
+		if (! $error)
+		{
 			$this->db->commit();
 			return 1;
-		} else {
-			$this->error = $this->db->lasterror();
-			dol_syslog(get_class($this) . "::update Error setFinal " . $sql, LOG_ERR);
+		}
+		else
+		{
+			foreach($this->errors as $errmsg)
+			{
+				dol_syslog(__METHOD__.' Error: '.$errmsg, LOG_ERR);
+				$this->error.=($this->error?', '.$errmsg:$errmsg);
+			}
 			$this->db->rollback();
-			return -1;
+			return -1*$error;
 		}
 	}
 
-- 
GitLab