From 60493d0a4774735616feefe769cfe40a74db7921 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur <eldy@destailleur.fr>
Date: Fri, 28 Jul 2017 10:16:17 +0200
Subject: [PATCH] Several fixes (permission, missing method or class) in REST
 APIs

---
 htdocs/api/index.php                          |   1 +
 .../comm/propal/class/api_proposals.class.php | 128 +++---
 htdocs/commande/class/api_orders.class.php    |  20 +-
 .../facture/class/api_invoices.class.php      | 127 ++++--
 htdocs/core/lib/functions2.lib.php            |   2 +-
 .../class/api_supplier_invoices.class.php     | 126 ++++--
 .../fourn/class/api_supplier_orders.class.php | 365 ++++++++++++++++++
 7 files changed, 623 insertions(+), 146 deletions(-)
 create mode 100644 htdocs/fourn/class/api_supplier_orders.class.php

diff --git a/htdocs/api/index.php b/htdocs/api/index.php
index 905d560f9c2..9f734c9e24d 100644
--- a/htdocs/api/index.php
+++ b/htdocs/api/index.php
@@ -238,6 +238,7 @@ if (! empty($reg[1]) && ($reg[1] != 'explorer' || ($reg[2] != '/resources.json'
     {
         $classfile = str_replace('_', '', $module);
         if ($module == 'supplierinvoices') $classfile = 'supplier_invoices';
+        if ($module == 'supplierorders')   $classfile = 'supplier_orders';
         $dir_part_file = dol_buildpath('/'.$moduledirforclass.'/class/api_'.$classfile.'.class.php');
         $classname=ucwords($module);
 
diff --git a/htdocs/comm/propal/class/api_proposals.class.php b/htdocs/comm/propal/class/api_proposals.class.php
index 2f067f46b18..42dbdbf9d2c 100644
--- a/htdocs/comm/propal/class/api_proposals.class.php
+++ b/htdocs/comm/propal/class/api_proposals.class.php
@@ -24,14 +24,14 @@ require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
 /**
  * API class for orders
  *
- * @access protected 
+ * @access protected
  * @class  DolibarrApiAccess {@requires user,external}
  */
 class Proposals extends DolibarrApi
 {
 
     /**
-     * @var array   $FIELDS     Mandatory fields, checked when create and update object 
+     * @var array   $FIELDS     Mandatory fields, checked when create and update object
      */
     static $FIELDS = array(
         'socid'
@@ -56,36 +56,36 @@ class Proposals extends DolibarrApi
      * Get properties of a commercial proposal object
      *
      * Return an array with commercial proposal informations
-     * 
+     *
      * @param       int         $id         ID of commercial proposal
      * @return 	array|mixed data without useless information
 	 *
      * @throws 	RestException
      */
     function get($id)
-    {		
+    {
 		if(! DolibarrApiAccess::$user->rights->propal->lire) {
 			throw new RestException(401);
 		}
-			
+
         $result = $this->propal->fetch($id);
         if( ! $result ) {
             throw new RestException(404, 'Commercial Proposal not found');
         }
-		
+
 		if( ! DolibarrApi::_checkAccessToResource('propal',$this->propal->id)) {
 			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
 		}
-        
+
         $this->propal->fetchObjectLinked();
 		return $this->_cleanObjectDatas($this->propal);
     }
 
     /**
      * List commercial proposals
-     * 
+     *
      * Get a list of commercial proposals
-     * 
+     *
      * @param string	$sortfield	        Sort field
      * @param string	$sortorder	        Sort order
      * @param int		$limit		        Limit for list
@@ -96,12 +96,12 @@ class Proposals extends DolibarrApi
      */
     function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 0, $page = 0, $thirdparty_ids = '', $sqlfilters = '') {
         global $db, $conf;
-        
+
         $obj_ret = array();
 
         // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
         $socids = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : $thirdparty_ids;
-            
+
         // If the internal user must only see his customers, force searching by him
         $search_sale = 0;
         if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) $search_sale = DolibarrApiAccess::$user->id;
@@ -109,7 +109,7 @@ class Proposals extends DolibarrApi
         $sql = "SELECT t.rowid";
         if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects)
         $sql.= " FROM ".MAIN_DB_PREFIX."propal as t";
-        
+
         if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale
 
         $sql.= ' WHERE t.entity IN ('.getEntity('propal').')';
@@ -122,7 +122,7 @@ class Proposals extends DolibarrApi
             $sql .= " AND sc.fk_user = ".$search_sale;
         }
         // Add sql filters
-        if ($sqlfilters) 
+        if ($sqlfilters)
         {
             if (! DolibarrApi::_checkFilters($sqlfilters))
             {
@@ -131,7 +131,7 @@ class Proposals extends DolibarrApi
 	        $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
             $sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
         }
-        
+
         $sql.= $db->order($sortfield, $sortorder);
         if ($limit)	{
             if ($page < 0)
@@ -144,7 +144,7 @@ class Proposals extends DolibarrApi
         }
 
         $result = $db->query($sql);
-        
+
         if ($result)
         {
             $num = $db->num_rows($result);
@@ -195,7 +195,7 @@ class Proposals extends DolibarrApi
         if ($this->propal->create(DolibarrApiAccess::$user) < 0) {
             throw new RestException(500, "Error creating order", array_merge(array($this->propal->error), $this->propal->errors));
         }
-        
+
         return $this->propal->id;
     }
 
@@ -203,21 +203,21 @@ class Proposals extends DolibarrApi
      * Get lines of a commercial proposal
      *
      * @param int   $id             Id of commercial proposal
-     * 
+     *
      * @url	GET {id}/lines
-     * 
-     * @return int 
+     *
+     * @return int
      */
     function getLines($id) {
       if(! DolibarrApiAccess::$user->rights->propal->lire) {
 		  	throw new RestException(401);
 		  }
-        
+
       $result = $this->propal->fetch($id);
       if( ! $result ) {
          throw new RestException(404, 'Commercial Proposal not found');
       }
-		
+
 		  if( ! DolibarrApi::_checkAccessToResource('propal',$this->propal->id)) {
 			  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
       }
@@ -233,22 +233,22 @@ class Proposals extends DolibarrApi
      * Add a line to given commercial proposal
      *
      * @param int   $id             Id of commercial proposal to update
-     * @param array $request_data   Commercial proposal line data   
-     * 
+     * @param array $request_data   Commercial proposal line data
+     *
      * @url	POST {id}/lines
-     * 
-     * @return int 
+     *
+     * @return int
      */
     function postLine($id, $request_data = NULL) {
       if(! DolibarrApiAccess::$user->rights->propal->creer) {
 		  	throw new RestException(401);
 		  }
-        
+
       $result = $this->propal->fetch($id);
       if( ! $result ) {
          throw new RestException(404, 'Commercial Proposal not found');
       }
-		
+
 		  if( ! DolibarrApi::_checkAccessToResource('propal',$this->propal->id)) {
 			  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
       }
@@ -294,22 +294,22 @@ class Proposals extends DolibarrApi
      *
      * @param int   $id             Id of commercial proposal to update
      * @param int   $lineid         Id of line to update
-     * @param array $request_data   Commercial proposal line data   
-     * 
+     * @param array $request_data   Commercial proposal line data
+     *
      * @url	PUT {id}/lines/{lineid}
-     * 
-     * @return object 
+     *
+     * @return object
      */
     function putLine($id, $lineid, $request_data = NULL) {
       if(! DolibarrApiAccess::$user->rights->propal->creer) {
 		  	throw new RestException(401);
 		  }
-        
+
       $result = $this->propal->fetch($id);
       if( ! $result ) {
          throw new RestException(404, 'Proposal not found');
       }
-		
+
 		  if( ! DolibarrApi::_checkAccessToResource('propal',$this->propal->id)) {
 			  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
       }
@@ -352,21 +352,21 @@ class Proposals extends DolibarrApi
      *
      * @param int   $id             Id of commercial proposal to update
      * @param int   $lineid         Id of line to delete
-     * 
+     *
      * @url	DELETE {id}/lines/{lineid}
-     * 
-     * @return int 
+     *
+     * @return int
      */
     function delLine($id, $lineid) {
       if(! DolibarrApiAccess::$user->rights->propal->creer) {
 		  	throw new RestException(401);
 		  }
-        
+
       $result = $this->propal->fetch($id);
       if( ! $result ) {
          throw new RestException(404, 'Proposal not found');
       }
-		
+
 		  if( ! DolibarrApi::_checkAccessToResource('propal',$this->propal->id)) {
 			  throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
       }
@@ -382,20 +382,20 @@ class Proposals extends DolibarrApi
      * Update commercial proposal general fields (won't touch lines of commercial proposal)
      *
      * @param int   $id             Id of commercial proposal to update
-     * @param array $request_data   Datas   
-     * 
-     * @return int 
+     * @param array $request_data   Datas
+     *
+     * @return int
      */
     function put($id, $request_data = NULL) {
       if(! DolibarrApiAccess::$user->rights->propal->creer) {
 		  	throw new RestException(401);
 		  }
-        
+
         $result = $this->propal->fetch($id);
         if( ! $result ) {
             throw new RestException(404, 'Proposal not found');
         }
-		
+
 		if( ! DolibarrApi::_checkAccessToResource('propal',$this->propal->id)) {
 			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
 		}
@@ -403,18 +403,18 @@ class Proposals extends DolibarrApi
             if ($field == 'id') continue;
             $this->propal->$field = $value;
         }
-        
+
         if($this->propal->update($id, DolibarrApiAccess::$user,1,'','','update'))
             return $this->get($id);
-        
+
         return false;
     }
-    
+
     /**
      * Delete commercial proposal
      *
      * @param   int     $id         Commercial proposal ID
-     * 
+     *
      * @return  array
      */
     function delete($id)
@@ -426,32 +426,32 @@ class Proposals extends DolibarrApi
         if( ! $result ) {
             throw new RestException(404, 'Commercial Proposal not found');
         }
-		
+
 		if( ! DolibarrApi::_checkAccessToResource('propal',$this->propal->id)) {
 			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
 		}
-        
+
         if( ! $this->propal->delete(DolibarrApiAccess::$user)) {
             throw new RestException(500, 'Error when delete Commercial Proposal : '.$this->propal->error);
         }
-        
+
         return array(
             'success' => array(
                 'code' => 200,
                 'message' => 'Commercial Proposal deleted'
             )
         );
-        
+
     }
-    
+
     /**
      * Validate a commercial proposal
-     * 
+     *
      * @param   int     $id             Commercial proposal ID
      * @param   int     $notrigger      Use {}
-     * 
+     *
      * @url POST    {id}/validate
-     *  
+     *
      * @return  array
      * FIXME An error 403 is returned if the request has an empty body.
      * Error message: "Forbidden: Content type `text/plain` is not supported."
@@ -469,11 +469,11 @@ class Proposals extends DolibarrApi
         if( ! $result ) {
             throw new RestException(404, 'Commercial Proposal not found');
         }
-		
+
 		if( ! DolibarrApi::_checkAccessToResource('propal',$this->propal->id)) {
 			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
 		}
-        
+
         $result = $this->propal->valid(DolibarrApiAccess::$user, $notrigger);
         if ($result == 0) {
             throw new RestException(500, 'Error nothing done. May be object is already validated');
@@ -481,30 +481,30 @@ class Proposals extends DolibarrApi
         if ($result < 0) {
             throw new RestException(500, 'Error when validating Commercial Proposal: '.$this->propal->error);
         }
-        
+
         return array(
             'success' => array(
                 'code' => 200,
-                'message' => 'Commercial Proposal validated'
+                'message' => 'Commercial Proposal validated (Ref='.$this->propal->ref.')'
             )
         );
     }
-    
+
     /**
      * Validate fields before create or update object
-     * 
+     *
      * @param   array           $data   Array with data to verify
-     * @return  array           
+     * @return  array
      * @throws  RestException
      */
     function _validate($data)
     {
         $propal = array();
-        foreach (Orders::$FIELDS as $field) {
+        foreach (Proposals::$FIELDS as $field) {
             if (!isset($data[$field]))
                 throw new RestException(400, "$field field missing");
             $propal[$field] = $data[$field];
-            
+
         }
         return $propal;
     }
diff --git a/htdocs/commande/class/api_orders.class.php b/htdocs/commande/class/api_orders.class.php
index a1330a7be04..d4b4502d4ed 100644
--- a/htdocs/commande/class/api_orders.class.php
+++ b/htdocs/commande/class/api_orders.class.php
@@ -80,8 +80,8 @@ class Orders extends DolibarrApi
 		return $this->_cleanObjectDatas($this->commande);
     }
 
-    
-   
+
+
     /**
      * List orders
      *
@@ -101,7 +101,7 @@ class Orders extends DolibarrApi
         global $db, $conf;
 
         $obj_ret = array();
-        
+
         // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
         $socids = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : $thirdparty_ids;
 
@@ -125,7 +125,7 @@ class Orders extends DolibarrApi
             $sql .= " AND sc.fk_user = ".$search_sale;
         }
         // Add sql filters
-        if ($sqlfilters) 
+        if ($sqlfilters)
         {
             if (! DolibarrApi::_checkFilters($sqlfilters))
             {
@@ -134,7 +134,7 @@ class Orders extends DolibarrApi
 	        $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
             $sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
         }
-        
+
         $sql.= $db->order($sortfield, $sortorder);
         if ($limit)	{
             if ($page < 0)
@@ -490,7 +490,7 @@ class Orders extends DolibarrApi
         return array(
             'success' => array(
                 'code' => 200,
-                'message' => 'Order validated'
+                'message' => 'Order validated (Ref='.$this->commande->ref.')'
             )
         );
     }
@@ -502,14 +502,14 @@ class Orders extends DolibarrApi
      * @return    array    Array of cleaned object properties
      */
     function _cleanObjectDatas($object) {
-    
+
         $object = parent::_cleanObjectDatas($object);
-    
+
         unset($object->address);
-    
+
         return $object;
     }
-    
+
     /**
      * Validate fields before create or update object
      *
diff --git a/htdocs/compta/facture/class/api_invoices.class.php b/htdocs/compta/facture/class/api_invoices.class.php
index 55304136ed6..f841fc80050 100644
--- a/htdocs/compta/facture/class/api_invoices.class.php
+++ b/htdocs/compta/facture/class/api_invoices.class.php
@@ -22,14 +22,14 @@
 /**
  * API class for invoices
  *
- * @access protected 
+ * @access protected
  * @class  DolibarrApiAccess {@requires user,external}
  */
 class Invoices extends DolibarrApi
 {
     /**
      *
-     * @var array   $FIELDS     Mandatory fields, checked when create and update object 
+     * @var array   $FIELDS     Mandatory fields, checked when create and update object
      */
     static $FIELDS = array(
         'socid'
@@ -54,23 +54,23 @@ class Invoices extends DolibarrApi
      * Get properties of a invoice object
      *
      * Return an array with invoice informations
-     * 
+     *
      * @param 	int 	$id ID of invoice
      * @return 	array|mixed data without useless information
      *
      * @throws 	RestException
      */
     function get($id)
-    {		
+    {
 		if(! DolibarrApiAccess::$user->rights->facture->lire) {
 			throw new RestException(401);
 		}
-			
+
         $result = $this->invoice->fetch($id);
         if( ! $result ) {
             throw new RestException(404, 'Invoice not found');
         }
-		
+
 		if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
 			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
 		}
@@ -80,9 +80,9 @@ class Invoices extends DolibarrApi
 
     /**
      * List invoices
-     * 
+     *
      * Get a list of invoices
-     * 
+     *
      * @param string	$sortfield	      Sort field
      * @param string	$sortorder	      Sort order
      * @param int		$limit		      Limit for list
@@ -96,12 +96,12 @@ class Invoices extends DolibarrApi
      */
     function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 0, $page = 0, $thirdparty_ids='', $status='', $sqlfilters = '') {
         global $db, $conf;
-        
+
         $obj_ret = array();
 
         // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
         $socids = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : $thirdparty_ids;
-        
+
         // If the internal user must only see his customers, force searching by him
         $search_sale = 0;
         if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) $search_sale = DolibarrApiAccess::$user->id;
@@ -109,7 +109,7 @@ class Invoices extends DolibarrApi
         $sql = "SELECT t.rowid";
         if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects)
         $sql.= " FROM ".MAIN_DB_PREFIX."facture as t";
-        
+
         if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale
 
         $sql.= ' WHERE t.entity IN ('.getEntity('facture').')';
@@ -117,7 +117,7 @@ class Invoices extends DolibarrApi
         if ($socids) $sql.= " AND t.fk_soc IN (".$socids.")";
 
         if ($search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc";		// Join for the needed table to filter by sale
-        
+
 		// Filter by status
         if ($status == 'draft')     $sql.= " AND t.fk_statut IN (0)";
         if ($status == 'unpaid')    $sql.= " AND t.fk_statut IN (1)";
@@ -129,7 +129,7 @@ class Invoices extends DolibarrApi
             $sql .= " AND sc.fk_user = ".$search_sale;
         }
         // Add sql filters
-        if ($sqlfilters) 
+        if ($sqlfilters)
         {
             if (! DolibarrApi::_checkFilters($sqlfilters))
             {
@@ -138,7 +138,7 @@ class Invoices extends DolibarrApi
 	        $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
             $sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
         }
-        
+
         $sql.= $db->order($sortfield, $sortorder);
         if ($limit)	{
             if ($page < 0)
@@ -174,10 +174,10 @@ class Invoices extends DolibarrApi
         }
 		return $obj_ret;
     }
-    
+
     /**
      * Create invoice object
-     * 
+     *
      * @param array $request_data   Request datas
      * @return int                  ID of invoice
      */
@@ -188,7 +188,7 @@ class Invoices extends DolibarrApi
 		}
         // Check mandatory fields
         $result = $this->_validate($request_data);
-        
+
         foreach($request_data as $field => $value) {
             $this->invoice->$field = $value;
         }
@@ -203,7 +203,7 @@ class Invoices extends DolibarrApi
             }
             $this->invoice->lines = $lines;
         }*/
-        
+
         if ($this->invoice->create(DolibarrApiAccess::$user) < 0) {
             throw new RestException(500, "Error creating invoice", array_merge(array($this->invoice->error), $this->invoice->errors));
         }
@@ -214,20 +214,20 @@ class Invoices extends DolibarrApi
      * Update invoice
      *
      * @param int   $id             Id of invoice to update
-     * @param array $request_data   Datas   
-     * @return int 
+     * @param array $request_data   Datas
+     * @return int
      */
     function put($id, $request_data = NULL)
     {
         if(! DolibarrApiAccess::$user->rights->facture->creer) {
 			throw new RestException(401);
 		}
-        
+
         $result = $this->invoice->fetch($id);
         if( ! $result ) {
             throw new RestException(404, 'Invoice not found');
         }
-		
+
 		if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
 			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
 		}
@@ -236,13 +236,13 @@ class Invoices extends DolibarrApi
             if ($field == 'id') continue;
             $this->invoice->$field = $value;
         }
-        
+
         if($this->invoice->update($id, DolibarrApiAccess::$user))
             return $this->get ($id);
-        
+
         return false;
     }
-    
+
     /**
      * Delete invoice
      *
@@ -258,16 +258,16 @@ class Invoices extends DolibarrApi
         if( ! $result ) {
             throw new RestException(404, 'Invoice not found');
         }
-		
+
 		if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
 			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
 		}
-        
+
         if( $this->invoice->delete($id) < 0)
         {
             throw new RestException(500);
         }
-        
+
          return array(
             'success' => array(
                 'code' => 200,
@@ -275,13 +275,76 @@ class Invoices extends DolibarrApi
             )
         );
     }
-    
+
+    /**
+     * Validate an order
+     *
+     * @param   int $id             Order ID
+     * @param   int $idwarehouse    Warehouse ID
+     * @param   int $notrigger      1=Does not execute triggers, 0= execute triggers
+     *
+     * @url POST    {id}/validate
+     *
+     * @return  array
+     * FIXME An error 403 is returned if the request has an empty body.
+     * Error message: "Forbidden: Content type `text/plain` is not supported."
+     * Workaround: send this in the body
+     * {
+     *   "idwarehouse": 0,
+     *   "notrigger": 0
+     * }
+     */
+    function validate($id, $idwarehouse=0, $notrigger=0)
+    {
+    	if(! DolibarrApiAccess::$user->rights->facture->creer) {
+    		throw new RestException(401);
+    	}
+    	$result = $this->invoice->fetch($id);
+    	if( ! $result ) {
+    		throw new RestException(404, 'Invoice not found');
+    	}
+
+    	if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
+    		throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
+    	}
+
+    	$result = $this->invoice->validate(DolibarrApiAccess::$user, '', $idwarehouse, $notrigger);
+    	if ($result == 0) {
+    		throw new RestException(500, 'Error nothing done. May be object is already validated');
+    	}
+    	if ($result < 0) {
+    		throw new RestException(500, 'Error when validating Invoice: '.$this->invoice->error);
+    	}
+
+    	return array(
+	    	'success' => array(
+		    	'code' => 200,
+		    	'message' => 'Invoice validated (Ref='.$this->invoice->ref.')'
+	    	)
+    	);
+    }
+
+    /**
+     * Clean sensible object datas
+     *
+     * @param   object  $object    Object to clean
+     * @return    array    Array of cleaned object properties
+     */
+    function _cleanObjectDatas($object) {
+
+    	$object = parent::_cleanObjectDatas($object);
+
+    	unset($object->address);
+
+    	return $object;
+    }
+
     /**
      * Validate fields before create or update object
-     * 
+     *
      * @param array|null    $data       Datas to validate
      * @return array
-     * 
+     *
      * @throws RestException
      */
     function _validate($data)
@@ -294,5 +357,5 @@ class Invoices extends DolibarrApi
         }
         return $invoice;
     }
-    
+
 }
diff --git a/htdocs/core/lib/functions2.lib.php b/htdocs/core/lib/functions2.lib.php
index 72f27a16602..181e8a7fe11 100644
--- a/htdocs/core/lib/functions2.lib.php
+++ b/htdocs/core/lib/functions2.lib.php
@@ -2200,7 +2200,7 @@ function getModuleDirForApiClass($module)
     elseif ($module == 'stock' || $module == 'stockmovements' || $module == 'warehouses') {
         $moduledirforclass = 'product/stock';
     }
-    elseif ($module == 'fournisseur' || $module == 'supplierinvoices') {
+    elseif ($module == 'fournisseur' || $module == 'supplierinvoices' || $module == 'supplierorders') {
         $moduledirforclass = 'fourn';
     }
     elseif ($module == 'expensereports') {
diff --git a/htdocs/fourn/class/api_supplier_invoices.class.php b/htdocs/fourn/class/api_supplier_invoices.class.php
index 6f3291518ca..26ae936d5a0 100644
--- a/htdocs/fourn/class/api_supplier_invoices.class.php
+++ b/htdocs/fourn/class/api_supplier_invoices.class.php
@@ -23,14 +23,14 @@ require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
 /**
  * API class for supplier invoices
  *
- * @access protected 
+ * @access protected
  * @class  DolibarrApiAccess {@requires user,external}
  */
 class SupplierInvoices extends DolibarrApi
 {
     /**
      *
-     * @var array   $FIELDS     Mandatory fields, checked when create and update object 
+     * @var array   $FIELDS     Mandatory fields, checked when create and update object
      */
     static $FIELDS = array(
         'socid'
@@ -55,24 +55,24 @@ class SupplierInvoices extends DolibarrApi
      * Get properties of a supplier invoice object
      *
      * Return an array with supplier invoice information
-     * 
+     *
      * @param 	int 	$id ID of supplier invoice
      * @return 	array|mixed data without useless information
      *
      * @throws 	RestException
      */
     function get($id)
-    {		
+    {
 		if(! DolibarrApiAccess::$user->rights->fournisseur->facture->lire) {
 			throw new RestException(401);
 		}
-			
+
         $result = $this->invoice->fetch($id);
         if( ! $result ) {
             throw new RestException(404, 'Supplier invoice not found');
         }
-		
-		if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
+
+		if( ! DolibarrApi::_checkAccessToResource('fournisseur',$this->invoice->id,'facture_fourn','facture')) {
 			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
 		}
 
@@ -81,9 +81,9 @@ class SupplierInvoices extends DolibarrApi
 
     /**
      * List invoices
-     * 
+     *
      * Get a list of supplier invoices
-     * 
+     *
      * @param string	$sortfield	      Sort field
      * @param string	$sortorder	      Sort order
      * @param int		$limit		      Limit for list
@@ -97,12 +97,12 @@ class SupplierInvoices extends DolibarrApi
      */
     function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 0, $page = 0, $thirdparty_ids='', $status='', $sqlfilters = '') {
         global $db, $conf;
-        
+
         $obj_ret = array();
 
         // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
         $socids = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : $thirdparty_ids;
-            
+
         // If the internal user must only see his customers, force searching by him
         $search_sale = 0;
         if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id;
@@ -110,14 +110,14 @@ class SupplierInvoices extends DolibarrApi
         $sql = "SELECT t.rowid";
         if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects)
         $sql.= " FROM ".MAIN_DB_PREFIX."facture_fourn as t";
-        
+
         if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale
 
         $sql.= ' WHERE t.entity IN ('.getEntity('supplier_invoice').')';
         if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= " AND t.fk_soc = sc.fk_soc";
         if ($socids) $sql.= " AND t.fk_soc IN (".$socids.")";
         if ($search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc";		// Join for the needed table to filter by sale
-        
+
 		// Filter by status
         if ($status == 'draft')     $sql.= " AND t.fk_statut IN (0)";
         if ($status == 'unpaid')    $sql.= " AND t.fk_statut IN (1)";
@@ -129,7 +129,7 @@ class SupplierInvoices extends DolibarrApi
             $sql .= " AND sc.fk_user = ".$search_sale;
         }
         // Add sql filters
-        if ($sqlfilters) 
+        if ($sqlfilters)
         {
             if (! DolibarrApi::_checkFilters($sqlfilters))
             {
@@ -138,7 +138,7 @@ class SupplierInvoices extends DolibarrApi
 	        $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
             $sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
         }
-        
+
         $sql.= $db->order($sortfield, $sortorder);
         if ($limit)	{
             if ($page < 0)
@@ -174,10 +174,10 @@ class SupplierInvoices extends DolibarrApi
         }
 		return $obj_ret;
     }
-    
+
     /**
      * Create supplier invoice object
-     * 
+     *
      * @param array $request_data   Request datas
      * @return int  ID of supplier invoice
      */
@@ -188,7 +188,7 @@ class SupplierInvoices extends DolibarrApi
 		}
         // Check mandatory fields
         $result = $this->_validate($request_data);
-        
+
         foreach($request_data as $field => $value) {
             $this->invoice->$field = $value;
         }
@@ -203,7 +203,7 @@ class SupplierInvoices extends DolibarrApi
             }
             $this->invoice->lines = $lines;
         }*/
-        
+
         if ($this->invoice->create(DolibarrApiAccess::$user) < 0) {
             throw new RestException(500, "Error creating order", array_merge(array($this->invoice->error), $this->invoice->errors));
         }
@@ -214,21 +214,21 @@ class SupplierInvoices extends DolibarrApi
      * Update supplier invoice
      *
      * @param int   $id             Id of supplier invoice to update
-     * @param array $request_data   Datas   
-     * @return int 
+     * @param array $request_data   Datas
+     * @return int
      */
     function put($id, $request_data = NULL)
     {
         if(! DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
 			throw new RestException(401);
 		}
-        
+
         $result = $this->invoice->fetch($id);
         if( ! $result ) {
             throw new RestException(404, 'Supplier invoice not found');
         }
-		
-		if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
+
+		if( ! DolibarrApi::_checkAccessToResource('fournisseur',$this->invoice->id,'facture_fourn','facture')) {
 			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
 		}
 
@@ -236,13 +236,13 @@ class SupplierInvoices extends DolibarrApi
             if ($field == 'id') continue;
             $this->invoice->$field = $value;
         }
-        
+
         if($this->invoice->update($id, DolibarrApiAccess::$user))
             return $this->get ($id);
-        
+
         return false;
     }
-    
+
     /**
      * Delete supplier invoice
      *
@@ -258,16 +258,16 @@ class SupplierInvoices extends DolibarrApi
         if( ! $result ) {
             throw new RestException(404, 'Supplier invoice not found');
         }
-		
-		if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) {
+
+		if( ! DolibarrApi::_checkAccessToResource('fournisseur',$this->invoice->id,'facture_fourn','facture')) {
 			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
 		}
-        
+
         if( $this->invoice->delete(DolibarrApiAccess::$user) < 0)
         {
             throw new RestException(500);
         }
-        
+
          return array(
             'success' => array(
                 'code' => 200,
@@ -275,8 +275,56 @@ class SupplierInvoices extends DolibarrApi
             )
         );
     }
-    
-    
+
+
+    /**
+     * Validate an order
+     *
+     * @param   int $id             Order ID
+     * @param   int $idwarehouse    Warehouse ID
+     * @param   int $notrigger      1=Does not execute triggers, 0= execute triggers
+     *
+     * @url POST    {id}/validate
+     *
+     * @return  array
+     * FIXME An error 403 is returned if the request has an empty body.
+     * Error message: "Forbidden: Content type `text/plain` is not supported."
+     * Workaround: send this in the body
+     * {
+     *   "idwarehouse": 0,
+     *   "notrigger": 0
+     * }
+     */
+    function validate($id, $idwarehouse=0, $notrigger=0)
+    {
+    	if(! DolibarrApiAccess::$user->rights->fournisseur->facture->creer) {
+    		throw new RestException(401);
+    	}
+    	$result = $this->invoice->fetch($id);
+    	if( ! $result ) {
+    		throw new RestException(404, 'Invoice not found');
+    	}
+
+		if( ! DolibarrApi::_checkAccessToResource('fournisseur',$this->invoice->id,'facture_fourn','facture')) {
+    		throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
+    	}
+
+    	$result = $this->invoice->validate(DolibarrApiAccess::$user, '', $idwarehouse, $notrigger);
+    	if ($result == 0) {
+    		throw new RestException(500, 'Error nothing done. May be object is already validated');
+    	}
+    	if ($result < 0) {
+    		throw new RestException(500, 'Error when validating Invoice: '.$this->invoice->error);
+    	}
+
+    	return array(
+	    	'success' => array(
+		    	'code' => 200,
+		    	'message' => 'Invoice validated (Ref='.$this->invoice->ref.')'
+	    	)
+    	);
+    }
+
     /**
      * Clean sensible object datas
      *
@@ -284,20 +332,20 @@ class SupplierInvoices extends DolibarrApi
      * @return  array              Array of cleaned object properties
      */
     function _cleanObjectDatas($object) {
-    
+
         $object = parent::_cleanObjectDatas($object);
-    
+
         unset($object->rowid);
-    
+
         return $object;
     }
-    
+
     /**
      * Validate fields before create or update object
-     * 
+     *
      * @param array $data   Datas to validate
      * @return array
-     * 
+     *
      * @throws RestException
      */
     function _validate($data)
diff --git a/htdocs/fourn/class/api_supplier_orders.class.php b/htdocs/fourn/class/api_supplier_orders.class.php
new file mode 100644
index 00000000000..2695727c3ee
--- /dev/null
+++ b/htdocs/fourn/class/api_supplier_orders.class.php
@@ -0,0 +1,365 @@
+<?php
+/* Copyright (C) 2015   Jean-François Ferry     <jfefe@aternatik.fr>
+ * Copyright (C) 2016   Laurent Destailleur     <eldy@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+use Luracast\Restler\RestException;
+
+require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
+
+/**
+ * API class for supplier orders
+ *
+ * @access protected
+ * @class  DolibarrApiAccess {@requires user,external}
+ */
+class SupplierOrders extends DolibarrApi
+{
+    /**
+     *
+     * @var array   $FIELDS     Mandatory fields, checked when create and update object
+     */
+    static $FIELDS = array(
+        'socid'
+    );
+
+    /**
+     * @var CommandeFournisseur $order {@type CommandeFournisseur}
+     */
+    public $order;
+
+    /**
+     * Constructor
+     */
+    function __construct()
+    {
+		global $db, $conf;
+		$this->db = $db;
+        $this->order = new CommandeFournisseur($this->db);
+    }
+
+    /**
+     * Get properties of a supplier order object
+     *
+     * Return an array with supplier order information
+     *
+     * @param 	int 	$id ID of supplier order
+     * @return 	array|mixed data without useless information
+     *
+     * @throws 	RestException
+     */
+    function get($id)
+    {
+		if(! DolibarrApiAccess::$user->rights->fournisseur->commande->lire) {
+			throw new RestException(401);
+		}
+
+        $result = $this->order->fetch($id);
+        if( ! $result ) {
+            throw new RestException(404, 'Supplier order not found');
+        }
+
+		if( ! DolibarrApi::_checkAccessToResource('fournisseur',$this->order->id,'','commande')) {
+			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
+		}
+
+		return $this->_cleanObjectDatas($this->order);
+    }
+
+    /**
+     * List orders
+     *
+     * Get a list of supplier orders
+     *
+     * @param string	$sortfield	      Sort field
+     * @param string	$sortorder	      Sort order
+     * @param int		$limit		      Limit for list
+     * @param int		$page		      Page number
+     * @param string   	$thirdparty_ids	  Thirdparty ids to filter orders of. {@example '1' or '1,2,3'} {@pattern /^[0-9,]*$/i}
+     * @param string	$status		      Filter by order status : draft | validated | approved | running | received_start | received_end | cancelled | refused
+     * @param string    $sqlfilters       Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.datec:<:'20160101')"
+     * @return array                      Array of order objects
+     *
+	 * @throws RestException
+     */
+    function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 0, $page = 0, $thirdparty_ids='', $status='', $sqlfilters = '') {
+        global $db, $conf;
+
+        $obj_ret = array();
+
+        // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
+        $socids = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : $thirdparty_ids;
+
+        // If the internal user must only see his customers, force searching by him
+        $search_sale = 0;
+        if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id;
+
+        $sql = "SELECT t.rowid";
+        if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects)
+        $sql.= " FROM ".MAIN_DB_PREFIX."commande_fournisseur as t";
+
+        if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale
+
+        $sql.= ' WHERE t.entity IN ('.getEntity('supplier_order').')';
+        if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= " AND t.fk_soc = sc.fk_soc";
+        if ($socids) $sql.= " AND t.fk_soc IN (".$socids.")";
+        if ($search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc";		// Join for the needed table to filter by sale
+
+		// Filter by status
+        if ($status == 'draft')     $sql.= " AND t.fk_statut IN (0)";
+        if ($status == 'validated') $sql.= " AND t.fk_statut IN (1)";
+        if ($status == 'approved')  $sql.= " AND t.fk_statut IN (2)";
+        if ($status == 'running')   $sql.= " AND t.fk_statut IN (3)";
+        if ($status == 'received_start') $sql.= " AND t.fk_statut IN (4)";
+        if ($status == 'received_end')   $sql.= " AND t.fk_statut IN (5)";
+        if ($status == 'cancelled') $sql.= " AND t.fk_statut IN (6,7)";
+        if ($status == 'refused')   $sql.= " AND t.fk_statut IN (9)";
+        // Insert sale filter
+        if ($search_sale > 0)
+        {
+            $sql .= " AND sc.fk_user = ".$search_sale;
+        }
+        // Add sql filters
+        if ($sqlfilters)
+        {
+            if (! DolibarrApi::_checkFilters($sqlfilters))
+            {
+                throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
+            }
+	        $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
+            $sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
+        }
+
+        $sql.= $db->order($sortfield, $sortorder);
+        if ($limit)	{
+            if ($page < 0)
+            {
+                $page = 0;
+            }
+            $offset = $limit * $page;
+
+            $sql.= $db->plimit($limit + 1, $offset);
+        }
+
+        $result = $db->query($sql);
+        if ($result)
+        {
+            $i = 0;
+            $num = $db->num_rows($result);
+            $min = min($num, ($limit <= 0 ? $num : $limit));
+            while ($i < $min)
+            {
+                $obj = $db->fetch_object($result);
+                $order_static = new CommandeFournisseur($db);
+                if($order_static->fetch($obj->rowid)) {
+                    $obj_ret[] = $this->_cleanObjectDatas($order_static);
+                }
+                $i++;
+            }
+        }
+        else {
+            throw new RestException(503, 'Error when retrieve supplier order list : '.$db->lasterror());
+        }
+        if( ! count($obj_ret)) {
+            throw new RestException(404, 'No supplier order found');
+        }
+		return $obj_ret;
+    }
+
+    /**
+     * Create supplier order object
+     *
+     * @param array $request_data   Request datas
+     * @return int  ID of supplier order
+     */
+    function post($request_data = NULL)
+    {
+        if(! DolibarrApiAccess::$user->rights->fournisseur->commande->creer) {
+			throw new RestException(401, "Insuffisant rights");
+		}
+        // Check mandatory fields
+        $result = $this->_validate($request_data);
+
+        foreach($request_data as $field => $value) {
+            $this->order->$field = $value;
+        }
+        if(! array_keys($request_data,'date')) {
+            $this->order->date = dol_now();
+        }
+        /* We keep lines as an array
+         if (isset($request_data["lines"])) {
+            $lines = array();
+            foreach ($request_data["lines"] as $line) {
+                array_push($lines, (object) $line);
+            }
+            $this->order->lines = $lines;
+        }*/
+
+        if ($this->order->create(DolibarrApiAccess::$user) < 0) {
+            throw new RestException(500, "Error creating order", array_merge(array($this->order->error), $this->order->errors));
+        }
+        return $this->order->id;
+    }
+
+    /**
+     * Update supplier order
+     *
+     * @param int   $id             Id of supplier order to update
+     * @param array $request_data   Datas
+     * @return int
+     */
+    function put($id, $request_data = NULL)
+    {
+        if(! DolibarrApiAccess::$user->rights->fournisseur->commande->creer) {
+			throw new RestException(401);
+		}
+
+        $result = $this->order->fetch($id);
+        if( ! $result ) {
+            throw new RestException(404, 'Supplier order not found');
+        }
+
+		if( ! DolibarrApi::_checkAccessToResource('fournisseur',$this->order->id,'','commande')) {
+			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
+		}
+
+        foreach($request_data as $field => $value) {
+            if ($field == 'id') continue;
+            $this->order->$field = $value;
+        }
+
+        if($this->order->update($id, DolibarrApiAccess::$user))
+            return $this->get ($id);
+
+        return false;
+    }
+
+    /**
+     * Delete supplier order
+     *
+     * @param int   $id Supplier order ID
+     * @return type
+     */
+    function delete($id)
+    {
+        if(! DolibarrApiAccess::$user->rights->fournisseur->commande->supprimer) {
+			throw new RestException(401);
+		}
+        $result = $this->order->fetch($id);
+        if( ! $result ) {
+            throw new RestException(404, 'Supplier order not found');
+        }
+
+		if( ! DolibarrApi::_checkAccessToResource('fournisseur',$this->order->id,'','commande')) {
+			throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
+		}
+
+        if( $this->order->delete(DolibarrApiAccess::$user) < 0)
+        {
+            throw new RestException(500);
+        }
+
+         return array(
+            'success' => array(
+                'code' => 200,
+                'message' => 'Supplier order deleted'
+            )
+        );
+    }
+
+
+    /**
+     * Validate an order
+     *
+     * @param   int $id             Order ID
+     * @param   int $idwarehouse    Warehouse ID
+     * @param   int $notrigger      1=Does not execute triggers, 0= execute triggers
+     *
+     * @url POST    {id}/validate
+     *
+     * @return  array
+     * FIXME An error 403 is returned if the request has an empty body.
+     * Error message: "Forbidden: Content type `text/plain` is not supported."
+     * Workaround: send this in the body
+     * {
+     *   "idwarehouse": 0,
+     *   "notrigger": 0
+     * }
+     */
+    function validate($id, $idwarehouse=0, $notrigger=0)
+    {
+    	if(! DolibarrApiAccess::$user->rights->fournisseur->commande->creer) {
+    		throw new RestException(401);
+    	}
+    	$result = $this->order->fetch($id);
+    	if( ! $result ) {
+    		throw new RestException(404, 'Order not found');
+    	}
+
+    	if( ! DolibarrApi::_checkAccessToResource('fournisseur',$this->order->id,'','commande')) {
+    		throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
+    	}
+
+    	$result = $this->order->valid(DolibarrApiAccess::$user, $idwarehouse, $notrigger);
+    	if ($result == 0) {
+    		throw new RestException(500, 'Error nothing done. May be object is already validated');
+    	}
+    	if ($result < 0) {
+    		throw new RestException(500, 'Error when validating Order: '.$this->order->error);
+    	}
+
+    	return array(
+	    	'success' => array(
+		    	'code' => 200,
+		    	'message' => 'Order validated (Ref='.$this->order->ref.')'
+	    	)
+    	);
+    }
+
+    /**
+     * Clean sensible object datas
+     *
+     * @param   Object  $object    Object to clean
+     * @return  array              Array of cleaned object properties
+     */
+    function _cleanObjectDatas($object) {
+
+        $object = parent::_cleanObjectDatas($object);
+
+        unset($object->rowid);
+
+        return $object;
+    }
+
+    /**
+     * Validate fields before create or update object
+     *
+     * @param array $data   Datas to validate
+     * @return array
+     *
+     * @throws RestException
+     */
+    function _validate($data)
+    {
+        $order = array();
+        foreach (SupplierOrders::$FIELDS as $field) {
+            if (!isset($data[$field]))
+                throw new RestException(400, "$field field missing");
+            $order[$field] = $data[$field];
+        }
+        return $order;
+    }
+}
-- 
GitLab