From 27217ccccd812f3949db516530880af891023fc9 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur <eldy@destailleur.fr>
Date: Sat, 9 Apr 2016 18:50:22 +0200
Subject: [PATCH] Maxi debug of supplier order workflow. Add trigger
 ORDER_SUPPLIER_CLASSIFY_BILLED Parameter user is added so it is defined into
 triggers.

---
 htdocs/comm/propal/class/propal.class.php     |   3 +-
 htdocs/commande/card.php                      |   2 +-
 htdocs/commande/class/commande.class.php      |   8 +-
 htdocs/commande/orderstoinvoice.php           |   2 +-
 htdocs/core/lib/functions2.lib.php            |  52 ++++++--
 ...e_20_modWorkflow_WorkflowManager.class.php |   6 +-
 ...terface_50_modAgenda_ActionsAuto.class.php |  24 +++-
 .../class/fournisseur.commande.class.php      | 122 +++++++++++-------
 htdocs/fourn/commande/card.php                |  19 ++-
 htdocs/fourn/commande/info.php                |   5 +-
 htdocs/fourn/commande/orderstoinvoice.php     |   8 +-
 .../mysql/data/llx_c_action_trigger.sql       |   1 +
 .../install/mysql/migration/3.9.0-4.0.0.sql   |   1 +
 htdocs/langs/en_US/orders.lang                |   3 +
 14 files changed, 170 insertions(+), 86 deletions(-)

diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php
index 87efc71e332..3a6d88896b9 100644
--- a/htdocs/comm/propal/class/propal.class.php
+++ b/htdocs/comm/propal/class/propal.class.php
@@ -2037,9 +2037,10 @@ class Propal extends CommonObject
      */
     function classer_facturee()
     {
+        global $user;
 		dol_syslog(__METHOD__ . " is deprecated", LOG_WARNING);
 
-    	return $this->classifyBilled();
+    	return $this->classifyBilled($user);
     }
 
     /**
diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php
index f5ba58bbfaa..9b5c29f55db 100644
--- a/htdocs/commande/card.php
+++ b/htdocs/commande/card.php
@@ -466,7 +466,7 @@ if (empty($reshook))
 
 	else if ($action == 'classifybilled' && $user->rights->commande->creer)
 	{
-		$ret=$object->classifyBilled();
+		$ret=$object->classifyBilled($user);
 
 		if ($ret < 0) {
 			setEventMessages($object->error, $object->errors, 'errors');
diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php
index 6e9e988daa0..5c33602ad50 100644
--- a/htdocs/commande/class/commande.class.php
+++ b/htdocs/commande/class/commande.class.php
@@ -2420,9 +2420,10 @@ class Commande extends CommonOrder
 	/**
 	 * Classify the order as invoiced
 	 *
-	 * @return     int     <0 if ko, >0 if ok
+	 * @param      User    $user       Object user making the change
+	 * @return     int                 <0 if KO, >0 if OK
 	 */
-	function classifyBilled()
+	function classifyBilled(User $user)
 	{
 		global $conf, $user, $langs;
         $error = 0;
@@ -2476,9 +2477,10 @@ class Commande extends CommonOrder
 	 */
 	function classer_facturee()
 	{
+	    global $user;
 		dol_syslog(__METHOD__ . " is deprecated", LOG_WARNING);
 
-		return $this->classifyBilled();
+		return $this->classifyBilled($user);
 	}
 
 
diff --git a/htdocs/commande/orderstoinvoice.php b/htdocs/commande/orderstoinvoice.php
index ebb9bedca2c..bcbe3ea408e 100644
--- a/htdocs/commande/orderstoinvoice.php
+++ b/htdocs/commande/orderstoinvoice.php
@@ -220,7 +220,7 @@ if (($action == 'create' || $action == 'add') && !$error)
 							{
 								if ($closeOrders)
 								{
-									$objectsrc->classifyBilled();
+									$objectsrc->classifyBilled($user);
 									$objectsrc->setStatut(3);
 								}
 								$lines = $objectsrc->lines;
diff --git a/htdocs/core/lib/functions2.lib.php b/htdocs/core/lib/functions2.lib.php
index 01ebaf7c42c..b4feef3ea0c 100644
--- a/htdocs/core/lib/functions2.lib.php
+++ b/htdocs/core/lib/functions2.lib.php
@@ -234,8 +234,8 @@ function dol_print_object_info($object, $usetable=0)
         else print '<br>';
     }
 
-    // User creation
-    if (! empty($object->user_creation))
+    // User creation (old method using already loaded object and not id is kept for backward compatibility)
+    if (! empty($object->user_creation) || ! empty($object->user_creation_id))
     {
         if ($usetable) print '<tr><td class="titlefield">';
         print $langs->trans("CreatedBy");
@@ -249,7 +249,7 @@ function dol_print_object_info($object, $usetable=0)
         else
         {
             $userstatic=new User($db);
-            $userstatic->fetch($object->user_creation);
+            $userstatic->fetch($object->user_creation_id ? $object->user_creation_id : $object->user_creation);
             if ($userstatic->id) print $userstatic->getNomUrl(1);
         	else print $langs->trans("Unknown");
         }
@@ -270,8 +270,8 @@ function dol_print_object_info($object, $usetable=0)
         else print '<br>';
     }
 
-    // User change
-    if (! empty($object->user_modification))
+    // User change (old method using already loaded object and not id is kept for backward compatibility)
+    if (! empty($object->user_modification) || ! empty($object->user_modification_id))
     {
         if ($usetable) print '<tr><td class="titlefield">';
         print $langs->trans("ModifiedBy");
@@ -285,7 +285,7 @@ function dol_print_object_info($object, $usetable=0)
         else
         {
             $userstatic=new User($db);
-            $userstatic->fetch($object->user_modification);
+            $userstatic->fetch($object->user_modification_id ? $object->user_modification_id : $object->user_modification);
             if ($userstatic->id) print $userstatic->getNomUrl(1);
         	else print $langs->trans("Unknown");
         }
@@ -306,8 +306,8 @@ function dol_print_object_info($object, $usetable=0)
         else print '<br>';
     }
 
-    // User validation
-    if (! empty($object->user_validation))
+    // User validation (old method using already loaded object and not id is kept for backward compatibility)
+    if (! empty($object->user_validation) || ! empty($object->user_validation_id))
     {
         if ($usetable) print '<tr><td class="titlefield">';
         print $langs->trans("ValidatedBy");
@@ -321,7 +321,7 @@ function dol_print_object_info($object, $usetable=0)
         else
         {
             $userstatic=new User($db);
-            $userstatic->fetch($object->user_validation);
+            $userstatic->fetch($object->user_validation_id ? $object->user_validation_id : $object->user_validation);
 			if ($userstatic->id) print $userstatic->getNomUrl(1);
         	else print $langs->trans("Unknown");
         }
@@ -342,8 +342,8 @@ function dol_print_object_info($object, $usetable=0)
         else print '<br>';
     }
 
-    // User approve
-    if (! empty($object->user_approve))
+    // User approve (old method using already loaded object and not id is kept for backward compatibility)
+    if (! empty($object->user_approve) || ! empty($object->user_approve_id))
     {
         if ($usetable) print '<tr><td class="titlefield">';
         print $langs->trans("ApprovedBy");
@@ -357,7 +357,7 @@ function dol_print_object_info($object, $usetable=0)
         else
         {
             $userstatic=new User($db);
-            $userstatic->fetch($object->user_approve);
+            $userstatic->fetch($object->user_approve_id ? $object->user_approve_id : $object->user_approve);
 			if ($userstatic->id) print $userstatic->getNomUrl(1);
         	else print $langs->trans("Unknown");
         }
@@ -378,6 +378,34 @@ function dol_print_object_info($object, $usetable=0)
         else print '<br>';
     }
 
+    // User approve
+    if (! empty($object->user_approve_id2))
+    {
+        if ($usetable) print '<tr><td class="titlefield">';
+        print $langs->trans("ApprovedBy");
+        if ($usetable) print '</td><td>';
+        else print ': ';
+        $userstatic=new User($db);
+        $userstatic->fetch($object->user_approve_id2);
+        if ($userstatic->id) print $userstatic->getNomUrl(1);
+        else print $langs->trans("Unknown");
+        if ($usetable) print '</td></tr>';
+        else print '<br>';
+    }
+    
+    // Date approve
+    if (! empty($object->date_approve2))
+    {
+        if ($usetable) print '<tr><td class="titlefield">';
+        print $langs->trans("DateApprove2");
+        if ($usetable) print '</td><td>';
+        else print ': ';
+        print dol_print_date($object->date_approve2, 'dayhour');
+        if ($deltadateforuser) print ' '.$langs->trans("CurrentHour").' &nbsp; / &nbsp; '.dol_print_date($object->date_approve2+($deltadateforuser*3600),"dayhour").' &nbsp;'.$langs->trans("ClientHour");
+        if ($usetable) print '</td></tr>';
+        else print '<br>';
+    }
+    
     // User close
     if (! empty($object->user_cloture))
     {
diff --git a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php
index b3a50223806..b0b4893d485 100644
--- a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php
+++ b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php
@@ -101,7 +101,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers
 				{
 					foreach($object->linkedObjects['propal'] as $element)
 					{
-						$ret=$element->classifyBilled();
+						$ret=$element->classifyBilled($user);
 					}
 				}
         		return $ret;
@@ -120,7 +120,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers
         		{
         			foreach($object->linkedObjects['commande'] as $element)
         			{
-        				$ret=$element->classifyBilled();
+        				$ret=$element->classifyBilled($user);
         			}
         		}
         		return $ret;
@@ -139,7 +139,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers
         		{
         			foreach($object->linkedObjects['commande'] as $element)
         			{
-        				$ret=$element->classifyBilled();
+        				$ret=$element->classifyBilled($user);
         			}
         		}
         		return $ret;
diff --git a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php
index 3a5717ae660..0a5d4a81ed6 100644
--- a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php
+++ b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php
@@ -485,8 +485,8 @@ class InterfaceActionsAuto extends DolibarrTriggers
         	$langs->load("orders");
 
 			$object->actiontypecode='AC_OTH_AUTO';
-            if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("OrderSubmitedInDolibarr",($object->newref?$object->newref:$object->ref));
-            $object->actionmsg=$langs->transnoentities("OrderSubmitedInDolibarr",($object->newref?$object->newref:$object->ref));
+            if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("SupplierOrderSubmitedInDolibarr",($object->newref?$object->newref:$object->ref));
+            $object->actionmsg=$langs->transnoentities("SupplierOrderSubmitedInDolibarr",($object->newref?$object->newref:$object->ref));
             $object->actionmsg.="\n".$langs->transnoentities("Author").': '.$user->login;
 
             $object->sendtoid=0;
@@ -497,8 +497,8 @@ class InterfaceActionsAuto extends DolibarrTriggers
         	$langs->load("orders");
 
 			$object->actiontypecode='AC_OTH_AUTO';
-            if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("OrderReceivedInDolibarr",($object->newref?$object->newref:$object->ref));
-            $object->actionmsg=$langs->transnoentities("OrderReceivedInDolibarr",($object->newref?$object->newref:$object->ref));
+            if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("SupplierOrderReceivedInDolibarr",($object->newref?$object->newref:$object->ref));
+            $object->actionmsg=$langs->transnoentities("SupplierOrderReceivedInDolibarr",($object->newref?$object->newref:$object->ref));
             $object->actionmsg.="\n".$langs->transnoentities("Author").': '.$user->login;
 
             $object->sendtoid=0;
@@ -519,6 +519,22 @@ class InterfaceActionsAuto extends DolibarrTriggers
 
             // Parameters $object->sendtoid defined by caller
             //$object->sendtoid=0;
+        }
+		elseif ($action == 'ORDER_SUPPLIER_CLASSIFY_BILLED')
+        {
+            $langs->load("other");
+            $langs->load("bills");
+            $langs->load("orders");
+
+            $object->actiontypecode='AC_OTH_AUTO';
+            if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("SupplierOrderClassifiedBilled",$object->ref);
+            if (empty($object->actionmsg))
+            {
+                $object->actionmsg=$langs->transnoentities("SupplierOrderClassifiedBilled",$object->ref);
+                $object->actionmsg.="\n".$langs->transnoentities("Author").': '.$user->login;
+            }
+
+            $object->sendtoid=0;
         }
 		elseif ($action == 'BILL_SUPPLIER_VALIDATE')
         {
diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php
index 2d97ac715e9..e47bf991b34 100644
--- a/htdocs/fourn/class/fournisseur.commande.class.php
+++ b/htdocs/fourn/class/fournisseur.commande.class.php
@@ -492,7 +492,6 @@ class CommandeFournisseur extends CommonOrder
             if (! $error)
             {
                 $result = 1;
-                $this->log($user, 1, time());	// Statut 1
                 $this->statut = 1;
                 $this->ref = $num;
             }
@@ -701,20 +700,43 @@ class CommandeFournisseur extends CommonOrder
 	/**
      *	Class invoiced the supplier order
      *
-     *	@return     int     	<0 si ko, >0 si ok
+     *  @param      User        $user       Object user making the change
+     *	@return     int     	            <0 if KO, >0 if KO
      */
-    function classifyBilled()
+    function classifyBilled(User $user)
     {
+        $this->db->begin();
+        
         $sql = 'UPDATE '.MAIN_DB_PREFIX.'commande_fournisseur SET billed = 1';
         $sql .= ' WHERE rowid = '.$this->id.' AND fk_statut > 0 ';
-        if ($this->db->query($sql) )
+        if ($this->db->query($sql))
         {
-        	$this->billed=1;
-            return 1;
+        	if (! $error)
+        	{
+        	    // Call trigger
+        	    $result=$this->call_trigger('ORDER_SUPPLIER_CLASSIFY_BILLED',$user);
+        	    if ($result < 0) $error++;
+        	    // End call triggers
+        	}
+        	
+        	if (! $error)
+        	{
+        	    $this->billed=1;
+        	     
+        	    $this->db->commit();
+        	    return 1;
+        	}
+        	else
+        	{
+        	    $this->db->rollback();
+                return -1;
+        	}
         }
         else
         {
         	dol_print_error($this->db);
+        	
+        	$this->db->rollback();
 			return -1;
         }
     }
@@ -791,8 +813,6 @@ class CommandeFournisseur extends CommonOrder
 
             if ($this->db->query($sql))
             {
-                $this->log($user, 2, time(), $comment);	// Statut 2
-
             	if (! empty($conf->global->SUPPLIER_ORDER_AUTOADD_USER_CONTACT))
 	            {
 					$result=$this->add_contact($user->id, 'SALESREPFOLL', 'internal', 1);
@@ -897,7 +917,6 @@ class CommandeFournisseur extends CommonOrder
             if ($this->db->query($sql))
             {
                 $result = 0;
-                $this->log($user, 9, time());
 
                 if ($error == 0)
                 {
@@ -956,7 +975,6 @@ class CommandeFournisseur extends CommonOrder
             if ($this->db->query($sql))
             {
                 $result = 0;
-                $this->log($user, $statut, time());
 
 				// Call trigger
 				$result=$this->call_trigger('ORDER_SUPPLIER_CANCEL',$user);
@@ -991,21 +1009,23 @@ class CommandeFournisseur extends CommonOrder
 
 
     /**
-     * 	Send a supplier order to supplier
+     * 	Submit a supplier order to supplier
      *
      * 	@param		User	$user		User making change
      * 	@param		date	$date		Date
      * 	@param		int		$methode	Method
      * 	@param		string	$comment	Comment
-     * 	@return		int			<0 if KO, >0 if OK
+     * 	@return		int			        <0 if KO, >0 if OK
      */
     function commande($user, $date, $methode, $comment='')
     {
         global $langs;
         dol_syslog(get_class($this)."::commande");
-        $result = 0;
+        $error = 0;
         if ($user->rights->fournisseur->commande->commander)
         {
+            $this->db->begin();
+
             $sql = "UPDATE ".MAIN_DB_PREFIX."commande_fournisseur SET fk_statut = 3, fk_input_method=".$methode.", date_commande='".$this->db->idate($date)."'";
             $sql .= " WHERE rowid = ".$this->id;
 
@@ -1015,24 +1035,37 @@ class CommandeFournisseur extends CommonOrder
                 $this->statut = 3;
                 $this->methode_commande_id = $methode;
                 $this->date_commande = $this->db->idate($date);
-                $result = 1;
-                $this->log($user, 3, $date, $comment);
+                
+                // Call trigger
+                $result=$this->call_trigger('ORDER_SUPPLIER_SUBMIT',$user);
+                if ($result < 0) $error++;
+                // End call triggers
             }
             else
             {
+                $error++;
                 $this->error = $this->db->lasterror();
                 $this->errors[] = $this->db->lasterror();
-                $result = -1;
+            }
+            
+            if (! $error)
+            {
+                $this->db->commit();
+            }
+            else
+            {
+                $this->db->rollback();
             }
         }
         else
         {
-            $result = -1;
+            $error++;
             $this->error = $langs->trans('NotAuthorized');
             $this->errors[] = $langs->trans('NotAuthorized');
             dol_syslog(get_class($this)."::commande User not Authorized", LOG_ERR);
         }
-        return $result ;
+
+        return ($error ? -1 : 1);
     }
 
     /**
@@ -1933,9 +1966,22 @@ class CommandeFournisseur extends CommonOrder
                 {
                     $result = 0;
                     $this->statut = $statut;
-                    $result=$this->log($user, $statut, $date, $comment);
 
-                    $this->db->commit();
+                    // Call trigger
+                    $result=$this->call_trigger('ORDER_SUPPLIER_RECEIVE',$user);
+                    if ($result < 0) $error++;
+                    // End call triggers
+                    
+                    if (! $error)
+                    {
+                        $this->db->commit();
+                    }
+                    else
+                    {
+                        $this->db->rollback();
+                        $this->error=$this->db->lasterror();
+                        $result = -1;
+                    }
                 }
                 else
                 {
@@ -2382,36 +2428,12 @@ class CommandeFournisseur extends CommonOrder
             {
                 $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_valid)
-                {
-                    $vuser = new User($this->db);
-                    $vuser->fetch($obj->fk_user_valid);
-                    $this->user_validation = $vuser;
-                }
-                if ($obj->fk_user_modif)
-                {
-                    $muser = new User($this->db);
-                    $muser->fetch($obj->fk_user_modif);
-                    $this->user_modification = $muser;
-                }
-                if ($obj->fk_user_approve)
-                {
-                    $auser = new User($this->db);
-                    $auser->fetch($obj->fk_user_approve);
-                    $this->user_approve = $auser;
-                }
-                if ($obj->fk_user_approve2)
-                {
-                    $a2user = new User($this->db);
-                    $a2user->fetch($obj->fk_user_approve2);
-                    $this->user_approve2 = $a2user;
-                }
+                if ($obj->fk_user_author)   $this->user_creation_id = $obj->fk_user_author; 
+                if ($obj->fk_user_valid)    $this->user_validation_id = $obj->fk_user_valid;
+                if ($obj->fk_user_modif)    $this->user_modification_id =$obj->fk_user_modif;
+                if ($obj->fk_user_approve)  $this->user_approve_id = $obj->fk_user_approve;
+                if ($obj->fk_user_approve2) $this->user_approve_id2 = $obj->fk_user_approve2;
+
                 $this->date_creation     = $this->db->idate($obj->datec);
                 $this->date_modification = $this->db->idate($obj->datem);
                 $this->date_approve      = $this->db->idate($obj->datea);
diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php
index 434d5d632fc..8bff36e159e 100644
--- a/htdocs/fourn/commande/card.php
+++ b/htdocs/fourn/commande/card.php
@@ -205,22 +205,33 @@ if (empty($reshook))
 
 	if ($action == 'reopen')	// no test on permission here, permission to use will depends on status
 	{
-	    if (in_array($object->statut, array(1, 2, 3, 5, 6, 7, 9)) || ($object->statut == 4 && $object->billed))
+	    if (in_array($object->statut, array(1, 2, 3, 4, 5, 6, 7, 9)))
 	    {
 	        if ($object->statut == 1) $newstatus=0;	// Validated->Draft
 	        else if ($object->statut == 2) $newstatus=0;	// Approved->Draft
 	        else if ($object->statut == 3) $newstatus=2;	// Ordered->Approved
-	        else if ($object->statut == 5) $newstatus=4;	// Received->Received partially
+	        else if ($object->statut == 4) $newstatus=3;
+	        else if ($object->statut == 5)
+	        {
+	            //$newstatus=2;    // Ordered
+	            // TODO Can we set it to submited ?
+	            //$newstatus=3;  // Submited
+	            // TODO If there is at least one reception, we can set to Received->Received partially
+	            $newstatus=4;  // Received partially
+	            
+	        }
 	        else if ($object->statut == 6) $newstatus=2;	// Canceled->Approved
 	        else if ($object->statut == 7) $newstatus=3;	// Canceled->Process running
 	        else if ($object->statut == 9) $newstatus=1;	// Refused->Validated
             else $newstatus = 2;
             
+            //print "old status = ".$object->statut.' new status = '.$newstatus;
 	        $db->begin();
 
 	        $result = $object->setStatus($user, $newstatus);
 	        if ($result > 0)
 	        {
+	            // Currently the "Re-open" also remove the billed flag because there is no button "Set unpaid" yet.
 		        $sql = 'UPDATE '.MAIN_DB_PREFIX.'commande_fournisseur';
 	        	$sql.= ' SET billed = 0';
 	        	$sql.= ' WHERE rowid = '.$object->id;
@@ -255,7 +266,7 @@ if (empty($reshook))
 	 */
 	if ($action == 'classifybilled' && $user->rights->fournisseur->commande->creer)
 	{
-		$ret=$object->classifyBilled();
+		$ret=$object->classifyBilled($user);
 		if ($ret < 0) {
 			setEventMessages($object->error, $object->errors, 'errors');
 		}
@@ -2881,7 +2892,7 @@ elseif (! empty($object->id))
 				        }
 				    }
 				}
-				if (in_array($object->statut, array(3, 5, 6, 7, 9)) || ($object->statut == 4 && $object->billed))
+				if (in_array($object->statut, array(3, 4, 5, 6, 7, 9)))
 				{
 					if ($user->rights->fournisseur->commande->commander)
 					{
diff --git a/htdocs/fourn/commande/info.php b/htdocs/fourn/commande/info.php
index 6723beeb44e..c8ed0e73660 100644
--- a/htdocs/fourn/commande/info.php
+++ b/htdocs/fourn/commande/info.php
@@ -120,13 +120,12 @@ if ($id > 0 || ! empty($ref))
 		dol_print_object_info($object, 1);
 		print '</td></tr></table>';
 		
-		
 		print '</div>';
 	}
 	else
 	{
-		/* Commande non trouvee */
-		print "Commande inexistante ou acces refuse";
+		/* Order not found */
+		print "OrderNotFound";
 	}
 }
 
diff --git a/htdocs/fourn/commande/orderstoinvoice.php b/htdocs/fourn/commande/orderstoinvoice.php
index 3f75bca3a35..64f6aa4dff0 100644
--- a/htdocs/fourn/commande/orderstoinvoice.php
+++ b/htdocs/fourn/commande/orderstoinvoice.php
@@ -239,10 +239,10 @@ if (($action == 'create' || $action == 'add') && empty($mesgs)) {
 			
 			foreach($orders_id as $fk_supplier_order) {
 				$supplier_order = new CommandeFournisseur($db);
-				if($supplier_order->fetch($fk_supplier_order)>0 && $supplier_order->statut == 5) {
-					
-					if($supplier_order->classifyBilled()<0) {
-							
+				if ($supplier_order->fetch($fk_supplier_order)>0 && $supplier_order->statut == 5) 
+				{
+					if ($supplier_order->classifyBilled($user) < 0)
+					{
 						$db->rollback();
 						$action = 'create';
 						$_GET["origin"] = $_POST["origin"];
diff --git a/htdocs/install/mysql/data/llx_c_action_trigger.sql b/htdocs/install/mysql/data/llx_c_action_trigger.sql
index 0c7913afd5b..81ce72007ab 100644
--- a/htdocs/install/mysql/data/llx_c_action_trigger.sql
+++ b/htdocs/install/mysql/data/llx_c_action_trigger.sql
@@ -57,6 +57,7 @@ insert into llx_c_action_trigger (code,label,description,elementtype,rang) value
 insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('ORDER_SUPPLIER_RECEIVE','Supplier order request received','Executed when a supplier order is received','order_supplier',12);
 insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('ORDER_SUPPLIER_REFUSE','Supplier order request refused','Executed when a supplier order is refused','order_supplier',13);
 insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('ORDER_SUPPLIER_SENTBYMAIL','Supplier order sent by mail','Executed when a supplier order is sent by mail','order_supplier',14);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('ORDER_SUPPLIER_CLASSIFY_BILLED','Supplier order set billed','Executed when a supplier order is set as billed','order_supplier',14);
 insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BILL_SUPPLIER_VALIDATE','Supplier invoice validated','Executed when a supplier invoice is validated','invoice_supplier',15);
 insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BILL_SUPPLIER_UNVALIDATE','Supplier invoice unvalidated','Executed when a supplier invoice status is set back to draft','invoice_supplier',15);
 insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BILL_SUPPLIER_PAYED','Supplier invoice payed','Executed when a supplier invoice is payed','invoice_supplier',16);
diff --git a/htdocs/install/mysql/migration/3.9.0-4.0.0.sql b/htdocs/install/mysql/migration/3.9.0-4.0.0.sql
index 882c45b7ae3..15de62fb3e8 100644
--- a/htdocs/install/mysql/migration/3.9.0-4.0.0.sql
+++ b/htdocs/install/mysql/migration/3.9.0-4.0.0.sql
@@ -376,6 +376,7 @@ insert into llx_c_action_trigger (code,label,description,elementtype,rang) value
 insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('ORDER_SUPPLIER_CREATE','Supplier order validated','Executed when a supplier order is validated','order_supplier',11);
 insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('ORDER_SUPPLIER_SUBMIT','Supplier order request submited','Executed when a supplier order is approved','order_supplier',12);
 insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('ORDER_SUPPLIER_RECEIVE','Supplier order request received','Executed when a supplier order is received','order_supplier',12);
+insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('ORDER_SUPPLIER_CLASSIFY_BILLED','Supplier order set billed','Executed when a supplier order is set as billed','order_supplier',14);
 
 ALTER TABLE llx_product_fournisseur_price ADD supplier_reputation varchar(10) NULL;
 
diff --git a/htdocs/langs/en_US/orders.lang b/htdocs/langs/en_US/orders.lang
index a402dd54944..d05491e5814 100644
--- a/htdocs/langs/en_US/orders.lang
+++ b/htdocs/langs/en_US/orders.lang
@@ -134,6 +134,9 @@ ConfirmCloneOrder=Are you sure you want to clone this order <b>%s</b> ?
 DispatchSupplierOrder=Receiving supplier order %s
 FirstApprovalAlreadyDone=First approval already done
 SecondApprovalAlreadyDone=Second approval already done
+SupplierOrderReceivedInDolibarr=Supplier order %s received %s
+SupplierOrderSubmitedInDolibarr=Supplier order %s submited
+SupplierOrderClassifiedBilled=Supplier order %s set billed
 ##### Types de contacts #####
 TypeContact_commande_internal_SALESREPFOLL=Representative following-up customer order
 TypeContact_commande_internal_SHIPPING=Representative following-up shipping
-- 
GitLab