diff --git a/htdocs/api/class/api.class.php b/htdocs/api/class/api.class.php
index e3081d10400..b41bf1cb271 100644
--- a/htdocs/api/class/api.class.php
+++ b/htdocs/api/class/api.class.php
@@ -93,13 +93,31 @@ class DolibarrApi
// Remove linkedObjects. We should already have linkedObjectIds that avoid huge responses
unset($object->linkedObjects);
- unset($object->lignes); // should be lines
+ unset($object->lignes); // should be ->lines
+ unset($object->oldline);
+
+ unset($object->error);
+ unset($object->errors);
+
+ unset($object->ref_previous);
+ unset($object->ref_next);
+ unset($object->ref_int);
+
+ unset($object->projet); // Should be fk_project
+ unset($object->project); // Should be fk_project
+ unset($object->author); // Should be fk_user_author
unset($object->statuts);
unset($object->statuts_short);
unset($object->statuts_logo);
unset($object->statuts_long);
+ unset($object->element);
+ unset($object->fk_element);
+ unset($object->table_element);
+ unset($object->table_element_line);
+ unset($object->picto);
+
// Remove the $oldcopy property because it is not supported by the JSON
// encoder. The following error is generated when trying to serialize
// it: "Error encoding/decoding JSON: Type is not supported"
diff --git a/htdocs/categories/class/api_categories.class.php b/htdocs/categories/class/api_categories.class.php
index 6cb830c2672..d775fd9eff1 100644
--- a/htdocs/categories/class/api_categories.class.php
+++ b/htdocs/categories/class/api_categories.class.php
@@ -151,7 +151,7 @@ class Categories extends DolibarrApi
$obj = $db->fetch_object($result);
$category_static = new Categorie($db);
if($category_static->fetch($obj->rowid)) {
- $obj_ret[] = parent::_cleanObjectDatas($category_static);
+ $obj_ret[] = $this->_cleanObjectDatas($category_static);
}
$i++;
}
@@ -237,7 +237,7 @@ class Categories extends DolibarrApi
$obj = $db->fetch_object($result);
$category_static = new Categorie($db);
if($category_static->fetch($obj->rowid)) {
- $obj_ret[] = parent::_cleanObjectDatas($category_static);
+ $obj_ret[] = $this->_cleanObjectDatas($category_static);
}
$i++;
}
@@ -339,6 +339,26 @@ class Categories extends DolibarrApi
);
}
+
+ /**
+ * Clean sensible object datas
+ *
+ * @param object $object Object to clean
+ * @return array Array of cleaned object properties
+ *
+ * @todo use an array for properties to clean
+ *
+ */
+ function _cleanObjectDatas($object) {
+
+ $object = parent::_cleanObjectDatas($object);
+
+ // Remove the subscriptions because they are handled as a subresource.
+ //unset($object->subscriptions);
+
+ return $object;
+ }
+
/**
* Validate fields before create or update object
*
diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php
index ebaf4922ac2..979f4d4b0d7 100644
--- a/htdocs/core/lib/functions.lib.php
+++ b/htdocs/core/lib/functions.lib.php
@@ -3488,7 +3488,7 @@ function price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerou
* @param string $rounding ''=No rounding
* 'MU'=Round to Max unit price (MAIN_MAX_DECIMALS_UNIT)
* 'MT'=Round to Max for totals with Tax (MAIN_MAX_DECIMALS_TOT)
- * 'MS'=Round to Max Shown (MAIN_MAX_DECIMALS_SHOWN)
+ * 'MS'=Round to Max for stock quantity (MAIN_MAX_DECIMALS_STOCK)
* @param int $alreadysqlnb Put 1 if you know that content is already universal format number
* @return string Amount with universal numeric format (Example: '99.99999') or unchanged text if conversion fails.
*
@@ -3538,7 +3538,7 @@ function price2num($amount,$rounding='',$alreadysqlnb=0)
$nbofdectoround='';
if ($rounding == 'MU') $nbofdectoround=$conf->global->MAIN_MAX_DECIMALS_UNIT;
elseif ($rounding == 'MT') $nbofdectoround=$conf->global->MAIN_MAX_DECIMALS_TOT;
- elseif ($rounding == 'MS') $nbofdectoround=$conf->global->MAIN_MAX_DECIMALS_SHOWN;
+ elseif ($rounding == 'MS') $nbofdectoround=empty($conf->global->MAIN_MAX_DECIMALS_STOCK)?5:$conf->global->MAIN_MAX_DECIMALS_STOCK;
elseif (is_numeric($rounding)) $nbofdectoround=$rounding; // For admin info page
//print "RR".$amount.' - '.$nbofdectoround.'
';
if (dol_strlen($nbofdectoround)) $amount = round($amount,$nbofdectoround); // $nbofdectoround can be 0.
diff --git a/htdocs/product/stock/card.php b/htdocs/product/stock/card.php
index f1097b331b9..1965bf09d60 100644
--- a/htdocs/product/stock/card.php
+++ b/htdocs/product/stock/card.php
@@ -332,7 +332,8 @@ else
// Nb of products
print '
| '.$langs->trans("NumberOfProducts").' | ';
- print empty($calcproducts['nb'])?'0':$calcproducts['nb'];
+ $valtoshow=price2num($calcproducts['nb'], 'MS');
+ print empty($valtoshow)?'0':$valtoshow;
print " |
";
print '';
@@ -485,13 +486,19 @@ else
$productstatic->entity=$objp->entity;
print $productstatic->getNomUrl(1,'stock',16);
print '';
+
+ // Label
print ''.$objp->produit.' | ';
- print ''.$objp->value.' | ';
+ print '';
+ $valtoshow=price2num($objp->value, 'MS');
+ print empty($valtoshow)?'0':$valtoshow;
+ print ' | ';
$totalunit+=$objp->value;
// Price buy PMP
print ''.price(price2num($objp->ppmp,'MU')).' | ';
+
// Total PMP
print ''.price(price2num($objp->ppmp*$objp->value,'MT')).' | ';
$totalvalue+=price2num($objp->ppmp*$objp->value,'MT');
@@ -530,7 +537,10 @@ else
$db->free($resql);
print '| '.$langs->trans("Total").' | ';
- print ''.$totalunit.' | ';
+ print '';
+ $valtoshow=price2num($totalunit, 'MS');
+ print empty($valtoshow)?'0':$valtoshow;
+ print ' | ';
print ' | ';
print ''.price(price2num($totalvalue,'MT')).' | ';
if (empty($conf->global->PRODUIT_MULTIPRICES))
diff --git a/htdocs/product/stock/class/api_stockmovements.class.php b/htdocs/product/stock/class/api_stockmovements.class.php
new file mode 100644
index 00000000000..b3b1f8bd3a5
--- /dev/null
+++ b/htdocs/product/stock/class/api_stockmovements.class.php
@@ -0,0 +1,349 @@
+
+ *
+ * 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 .
+ */
+
+use Luracast\Restler\RestException;
+
+require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
+
+
+/**
+ * API class for stock movements
+ *
+ * @access protected
+ * @class DolibarrApiAccess {@requires user,external}
+ */
+class StockMovements extends DolibarrApi
+{
+ /**
+ * @var array $FIELDS Mandatory fields, checked when create and update object
+ */
+ static $FIELDS = array(
+ 'product_id',
+ 'warehouse_id',
+ 'qty'
+ );
+
+ /**
+ * @var MouvmeentStock $stockmovement {@type MouvementStock}
+ */
+ public $stockmovement;
+
+ /**
+ * Constructor
+ */
+ function __construct()
+ {
+ global $db, $conf;
+ $this->db = $db;
+ $this->stockmovement = new MouvementStock($this->db);
+ }
+
+ /**
+ * Get properties of a stock movement object
+ *
+ * Return an array with stock movement informations
+ *
+ * @param int $id ID of movement
+ * @return array|mixed data without useless information
+ *
+ * @throws RestException
+ */
+ /*
+ function get($id)
+ {
+ if(! DolibarrApiAccess::$user->rights->stock->lire) {
+ throw new RestException(401);
+ }
+
+ $result = $this->stockmovement->fetch($id);
+ if( ! $result ) {
+ throw new RestException(404, 'warehouse not found');
+ }
+
+ if( ! DolibarrApi::_checkAccessToResource('warehouse',$this->stockmovement->id)) {
+ throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
+ }
+
+ return $this->_cleanObjectDatas($this->stockmovement);
+ }*/
+
+ /**
+ * Get a list of stock movement
+ *
+ * @param string $sortfield Sort field
+ * @param string $sortorder Sort order
+ * @param int $limit Limit for list
+ * @param int $page Page number
+ * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.product_id:=:1) and (t.date_creation:<:'20160101')"
+ * @return array Array of warehouse objects
+ *
+ * @throws RestException
+ */
+ function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 0, $page = 0, $sqlfilters = '') {
+ global $db, $conf;
+
+ $obj_ret = array();
+
+ if(! DolibarrApiAccess::$user->rights->stock->lire) {
+ throw new RestException(401);
+ }
+
+ $sql = "SELECT t.rowid";
+ $sql.= " FROM ".MAIN_DB_PREFIX."stock_mouvement as t";
+ //$sql.= ' WHERE t.entity IN ('.getEntity('stock', 1).')';
+ $sql.= ' WHERE 1 = 1';
+ // 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);
+ while ($i < min($num, ($limit <= 0 ? $num : $limit)))
+ {
+ $obj = $db->fetch_object($result);
+ $stockmovement_static = new MouvementStock($db);
+ if($stockmovement_static->fetch($obj->rowid)) {
+ $obj_ret[] = $this->_cleanObjectDatas($stockmovement_static);
+ }
+ $i++;
+ }
+ }
+ else {
+ throw new RestException(503, 'Error when retrieve stock movement list : '.$stockmovement_static->error);
+ }
+ if( ! count($obj_ret)) {
+ throw new RestException(404, 'No stock movement found');
+ }
+ return $obj_ret;
+ }
+
+/*
+ * @param int $product_id Id product id {@min 1}
+ * @param int $warehouse_id Id warehouse {@min 1}
+ * @param float $qty Qty to add (Use negative value for a stock decrease) {@min 0} {@message qty must be higher than 0}
+ * @param string $lot Lot
+ * @param string $movementcode Movement code {@example INV123}
+ * @param string $movementlabel Movement label {@example Inventory number 123}
+ * @param string $price To update AWP (Average Weighted Price) when you make a stock increase (qty must be higher then 0).
+ */
+
+
+ /**
+ * Create stock movement object.
+ * You can use the following message to test this RES API:
+ * { "product_id": 1, "warehouse_id": 1, "qty": 1, "lot": "", "movementcode": "INV123", "movementlabel": "Inventory 123", "price": 0 }
+ *
+ * @param array $request_data Request data
+ * @return int ID of stock movement
+ */
+ //function post($product_id, $warehouse_id, $qty, $lot='', $movementcode='', $movementlabel='', $price=0)
+ function post($request_data = NULL)
+ {
+ if(! DolibarrApiAccess::$user->rights->stock->creer) {
+ throw new RestException(401);
+ }
+
+ // Check mandatory fields
+ //$result = $this->_validate($request_data);
+
+ foreach($request_data as $field => $value) {
+ //$this->stockmovement->$field = $value;
+ if ($field == 'product_id') $product_id = $value;
+ if ($field == 'warehouse_id') $warehouse_id = $value;
+ if ($field == 'qty') $qty = $value;
+ if ($field == 'lot') $lot = $value;
+ if ($field == 'movementcode') $movementcode = $value;
+ if ($field == 'movementlabel') $movementlabel = $value;
+ if ($field == 'price') $price = $value;
+ }
+
+ // Type increase or decrease
+ if ($qty >= 0) $type = 3;
+ else $type = 2;
+
+ if($this->stockmovement->_create(DolibarrApiAccess::$user, $product_id, $warehouse_id, $qty, $type, $price, $movementlabel, $movementcode, '', '', '', $lot) <= 0) {
+ throw new RestException(503, 'Error when create stock movement : '.$this->stockmovement->error);
+ }
+
+ return $this->stockmovement->id;
+ }
+
+ /**
+ * Update stock movement
+ *
+ * @param int $id Id of warehouse to update
+ * @param array $request_data Datas
+ * @return int
+ */
+ /*
+ function put($id, $request_data = NULL)
+ {
+ if(! DolibarrApiAccess::$user->rights->stock->creer) {
+ throw new RestException(401);
+ }
+
+ $result = $this->stockmovement->fetch($id);
+ if( ! $result ) {
+ throw new RestException(404, 'stock movement not found');
+ }
+
+ if( ! DolibarrApi::_checkAccessToResource('stock',$this->stockmovement->id)) {
+ throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
+ }
+
+ foreach($request_data as $field => $value) {
+ $this->stockmovement->$field = $value;
+ }
+
+ if($this->stockmovement->update($id, DolibarrApiAccess::$user))
+ return $this->get ($id);
+
+ return false;
+ }*/
+
+ /**
+ * Delete stock movement
+ *
+ * @param int $id Stock movement ID
+ * @return array
+ */
+ /*
+ function delete($id)
+ {
+ if(! DolibarrApiAccess::$user->rights->stock->supprimer) {
+ throw new RestException(401);
+ }
+ $result = $this->stockmovement->fetch($id);
+ if( ! $result ) {
+ throw new RestException(404, 'stock movement not found');
+ }
+
+ if( ! DolibarrApi::_checkAccessToResource('stock',$this->stockmovement->id)) {
+ throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
+ }
+
+ if (! $this->stockmovement->delete(DolibarrApiAccess::$user)) {
+ throw new RestException(401,'error when delete stock movement');
+ }
+
+ return array(
+ 'success' => array(
+ 'code' => 200,
+ 'message' => 'Warehouse deleted'
+ )
+ );
+ }*/
+
+
+
+ /**
+ * Clean sensible object datas
+ *
+ * @param object $object Object to clean
+ * @return array Array of cleaned object properties
+ *
+ * @todo use an array for properties to clean
+ *
+ */
+ function _cleanObjectDatas($object) {
+
+ $object = parent::_cleanObjectDatas($object);
+
+ // Remove useless data
+ unset($object->civility_id);
+ unset($object->firstname);
+ unset($object->lastname);
+ unset($object->name);
+ unset($object->location_incoterms);
+ unset($object->libelle_incoterms);
+ unset($object->fk_incoterms);
+ unset($object->lines);
+ unset($object->total_ht);
+ unset($object->total_ttc);
+ unset($object->total_tva);
+ unset($object->total_localtax1);
+ unset($object->total_localtax2);
+ unset($object->note);
+ unset($object->note_private);
+ unset($object->note_public);
+ unset($object->shipping_method_id);
+ unset($object->fk_account);
+ unset($object->modelpdf);
+ unset($object->fk_delivery_address);
+ unset($object->cond_reglement);
+ unset($object->cond_reglement_id);
+ unset($object->mode_reglement_id);
+ unset($object->barcode_type_coder);
+ unset($object->barcode_type_label);
+ unset($object->barcode_type_code);
+ unset($object->barcode_type);
+ unset($object->country_code);
+ unset($object->country_id);
+ unset($object->country);
+ unset($object->thirdparty);
+ unset($object->contact);
+ unset($object->contact_id);
+ unset($object->user);
+ unset($object->fk_project);
+ unset($object->project);
+
+ //unset($object->eatby); Filled correctly in read mode
+ //unset($object->sellby); Filled correctly in read mode
+
+ return $object;
+ }
+
+ /**
+ * Validate fields before create or update object
+ *
+ * @param array|null $data Data to validate
+ * @return array
+ *
+ * @throws RestException
+ */
+ function _validate($data)
+ {
+ $stockmovement = array();
+ foreach (Warehouses::$FIELDS as $field) {
+ if (!isset($data[$field]))
+ throw new RestException(400, "$field field missing");
+ $stockmovement[$field] = $data[$field];
+ }
+ return $stockmovement;
+ }
+}
diff --git a/htdocs/product/stock/class/api_warehouses.class.php b/htdocs/product/stock/class/api_warehouses.class.php
index 965baa15c2f..072b4a2d5c2 100644
--- a/htdocs/product/stock/class/api_warehouses.class.php
+++ b/htdocs/product/stock/class/api_warehouses.class.php
@@ -136,7 +136,7 @@ class Warehouses extends DolibarrApi
$obj = $db->fetch_object($result);
$warehouse_static = new Entrepot($db);
if($warehouse_static->fetch($obj->rowid)) {
- $obj_ret[] = parent::_cleanObjectDatas($warehouse_static);
+ $obj_ret[] = $this->_cleanObjectDatas($warehouse_static);
}
$i++;
}
@@ -169,7 +169,7 @@ class Warehouses extends DolibarrApi
foreach($request_data as $field => $value) {
$this->warehouse->$field = $value;
}
- if($this->warehouse->create(DolibarrApiAccess::$user) < 0) {
+ if($this->warehouse->create(DolibarrApiAccess::$user) <= 0) {
throw new RestException(503, 'Error when create warehouse : '.$this->warehouse->error);
}
return $this->warehouse->id;
@@ -193,7 +193,7 @@ class Warehouses extends DolibarrApi
throw new RestException(404, 'warehouse not found');
}
- if( ! DolibarrApi::_checkAccessToResource('warehouse',$this->warehouse->id)) {
+ if( ! DolibarrApi::_checkAccessToResource('stock',$this->warehouse->id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
@@ -223,7 +223,7 @@ class Warehouses extends DolibarrApi
throw new RestException(404, 'warehouse not found');
}
- if( ! DolibarrApi::_checkAccessToResource('warehouse',$this->warehouse->id)) {
+ if( ! DolibarrApi::_checkAccessToResource('stock',$this->warehouse->id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
@@ -239,6 +239,27 @@ class Warehouses extends DolibarrApi
);
}
+
+ /**
+ * Clean sensible object datas
+ *
+ * @param object $object Object to clean
+ * @return array Array of cleaned object properties
+ *
+ * @todo use an array for properties to clean
+ *
+ */
+ function _cleanObjectDatas($object) {
+
+ $object = parent::_cleanObjectDatas($object);
+
+ // Remove the subscriptions because they are handled as a subresource.
+ //unset($object->subscriptions);
+
+ return $object;
+ }
+
+
/**
* Validate fields before create or update object
*
diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php
index 1532f62aa22..dee344b6a5b 100644
--- a/htdocs/product/stock/class/mouvementstock.class.php
+++ b/htdocs/product/stock/class/mouvementstock.class.php
@@ -30,11 +30,32 @@
*/
class MouvementStock extends CommonObject
{
- var $product_id;
- var $entrepot_id;
- var $qty;
- var $type;
+ /**
+ * @var string Id to identify managed objects
+ */
+ public $element = 'stockmouvement';
+ /**
+ * @var string Name of table without prefix where object is stored
+ */
+ public $table_element = 'stock_mouvement';
+
+ public $product_id;
+ public $warehouse_id;
+ public $qty;
+ public $type;
+
+ public $tms = '';
+ public $datem = '';
+ public $price;
+ public $fk_user_author;
+ public $label;
+ public $fk_origin;
+ public $origintype;
+ public $inventorycode;
+ public $batch;
+
+
/**
* Constructor
@@ -46,6 +67,7 @@ class MouvementStock extends CommonObject
$this->db = $db;
}
+
/**
* Add a movement of stock (in one direction only)
*
@@ -54,18 +76,18 @@ class MouvementStock extends CommonObject
* @param int $entrepot_id Id of warehouse
* @param int $qty Qty of movement (can be <0 or >0 depending on parameter type)
* @param int $type Direction of movement:
- * 0=input (stock increase after stock transfert), 1=output (stock decrease after stock transfer),
+ * 0=input (stock increase by a stock transfer), 1=output (stock decrease after by a stock transfer),
* 2=output (stock decrease), 3=input (stock increase)
* Note that qty should be > 0 with 0 or 3, < 0 with 1 or 2.
* @param int $price Unit price HT of product, used to calculate average weighted price (PMP in french). If 0, average weighted price is not changed.
* @param string $label Label of stock movement
* @param string $inventorycode Inventory code
* @param string $datem Force date of movement
- * @param date $eatby eat-by date
- * @param date $sellby sell-by date
+ * @param date $eatby eat-by date. Will be used if lot does not exists yet and will be created.
+ * @param date $sellby sell-by date. Will be used if lot does not exists yet and will be created.
* @param string $batch batch number
* @param boolean $skip_batch If set to true, stock movement is done without impacting batch record
- * @param int $id_product_batch Id product_batch (when skip_batch is flase and we already know which record of product_batch to use)
+ * @param int $id_product_batch Id product_batch (when skip_batch is false and we already know which record of product_batch to use)
* @return int <0 if KO, 0 if fk_product is null, >0 if OK
*/
function _create($user, $fk_product, $entrepot_id, $qty, $type, $price=0, $label='', $inventorycode='', $datem='',$eatby='',$sellby='',$batch='',$skip_batch=false, $id_product_batch=0)
@@ -75,7 +97,7 @@ class MouvementStock extends CommonObject
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
$error = 0;
- dol_syslog(get_class($this)."::_create start userid=$user->id, fk_product=$fk_product, warehouse=$entrepot_id, qty=$qty, type=$type, price=$price, label=$label, inventorycode=$inventorycode, datem=".$datem.", eatby=".$eatby.", sellby=".$sellby.", batch=".$batch.", skip_batch=".$skip_batch);
+ dol_syslog(get_class($this)."::_create start userid=$user->id, fk_product=$fk_product, warehouse_id=$entrepot_id, qty=$qty, type=$type, price=$price, label=$label, inventorycode=$inventorycode, datem=".$datem.", eatby=".$eatby.", sellby=".$sellby.", batch=".$batch.", skip_batch=".$skip_batch);
// Clean parameters
if (empty($price)) $price=0;
@@ -90,7 +112,7 @@ class MouvementStock extends CommonObject
}
if ($sellby < 0)
{
- $this->errors[]='ErrorBadValueForParameterEatBy';
+ $this->errors[]='ErrorBadValueForParameterSellBy';
return -1;
}
@@ -315,7 +337,7 @@ class MouvementStock extends CommonObject
$sql.= " '".$origintype."'";
$sql.= ")";
- dol_syslog(get_class($this)."::_create", LOG_DEBUG);
+ dol_syslog(get_class($this)."::_create insert record into stock_mouvement", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql)
{
@@ -340,7 +362,7 @@ class MouvementStock extends CommonObject
$sql = "SELECT rowid, reel FROM ".MAIN_DB_PREFIX."product_stock";
$sql.= " WHERE fk_entrepot = ".$entrepot_id." AND fk_product = ".$fk_product; // This is a unique key
- dol_syslog(get_class($this)."::_create", LOG_DEBUG);
+ dol_syslog(get_class($this)."::_create check if a record already exists in product_stock", LOG_DEBUG);
$resql=$this->db->query($sql);
if ($resql)
{
@@ -405,7 +427,7 @@ class MouvementStock extends CommonObject
$sql.= " (".$qty.", ".$entrepot_id.", ".$fk_product.")";
}
- dol_syslog(get_class($this)."::_create", LOG_DEBUG);
+ dol_syslog(get_class($this)."::_create update stock value", LOG_DEBUG);
$resql=$this->db->query($sql);
if (! $resql)
{
@@ -444,7 +466,7 @@ class MouvementStock extends CommonObject
$sql.= " stock=(SELECT SUM(ps.reel) FROM ".MAIN_DB_PREFIX."product_stock as ps WHERE ps.fk_product = p.rowid)";
$sql.= " WHERE rowid = ".$fk_product;
- dol_syslog(get_class($this)."::_create", LOG_DEBUG);
+ dol_syslog(get_class($this)."::_create update AWP", LOG_DEBUG);
$resql=$this->db->query($sql);
if (! $resql)
{
@@ -487,6 +509,96 @@ class MouvementStock extends CommonObject
}
}
+
+
+ /**
+ * Load object in memory from the database
+ *
+ * @param int $id Id object
+ *
+ * @return int <0 if KO, 0 if not found, >0 if OK
+ */
+ public function fetch($id)
+ {
+ dol_syslog(__METHOD__, LOG_DEBUG);
+
+ $sql = 'SELECT';
+ $sql .= ' t.rowid,';
+ $sql .= " t.tms,";
+ $sql .= " t.datem,";
+ $sql .= " t.fk_product,";
+ $sql .= " t.fk_entrepot,";
+ $sql .= " t.value,";
+ $sql .= " t.price,";
+ $sql .= " t.type_mouvement,";
+ $sql .= " t.fk_user_author,";
+ $sql .= " t.label,";
+ $sql .= " t.fk_origin,";
+ $sql .= " t.origintype,";
+ $sql .= " t.inventorycode,";
+ $sql .= " t.batch,";
+ $sql .= " t.eatby,";
+ $sql .= " t.sellby";
+ $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
+ $sql.= ' WHERE 1 = 1';
+ //if (null !== $ref) {
+ //$sql .= ' AND t.ref = ' . '\'' . $ref . '\'';
+ //} else {
+ $sql .= ' AND t.rowid = ' . $id;
+ //}
+
+ $resql = $this->db->query($sql);
+ if ($resql) {
+ $numrows = $this->db->num_rows($resql);
+ if ($numrows) {
+ $obj = $this->db->fetch_object($resql);
+
+ $this->id = $obj->rowid;
+
+ $this->product_id = $obj->fk_product;
+ $this->warehouse_id = $obj->fk_entrepot;
+ $this->qty = $obj->value;
+ $this->type = $obj->type_mouvement;
+
+ $this->tms = $this->db->jdate($obj->tms);
+ $this->datem = $this->db->jdate($obj->datem);
+ $this->price = $obj->price;
+ $this->fk_user_author = $obj->fk_user_author;
+ $this->label = $obj->label;
+ $this->fk_origin = $obj->fk_origin;
+ $this->origintype = $obj->origintype;
+ $this->inventorycode = $obj->inventorycode;
+ $this->batch = $obj->batch;
+ $this->eatby = $this->db->jdate($obj->eatby);
+ $this->sellby = $this->db->jdate($obj->sellby);
+ }
+
+ // Retrieve all extrafields for invoice
+ // fetch optionals attributes and labels
+ require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
+ $extrafields=new ExtraFields($this->db);
+ $extralabels=$extrafields->fetch_name_optionals_label($this->table_element,true);
+ $this->fetch_optionals($this->id,$extralabels);
+
+ // $this->fetch_lines();
+
+ $this->db->free($resql);
+
+ if ($numrows) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else {
+ $this->errors[] = 'Error ' . $this->db->lasterror();
+ dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
+
+ return - 1;
+ }
+ }
+
+
+
/**
* Create movement in database for all subproducts
@@ -545,18 +657,18 @@ class MouvementStock extends CommonObject
/**
* Decrease stock for product and subproducts
*
- * @param User $user Object user
- * @param int $fk_product Id product
- * @param int $entrepot_id Warehouse id
- * @param int $qty Quantity
- * @param int $price Price
- * @param string $label Label of stock movement
- * @param string $datem Force date of movement
- * @param date $eatby eat-by date
- * @param date $sellby sell-by date
- * @param string $batch batch number
+ * @param User $user Object user
+ * @param int $fk_product Id product
+ * @param int $entrepot_id Warehouse id
+ * @param int $qty Quantity
+ * @param int $price Price
+ * @param string $label Label of stock movement
+ * @param string $datem Force date of movement
+ * @param date $eatby eat-by date
+ * @param date $sellby sell-by date
+ * @param string $batch batch number
* @param int $id_product_batch Id product_batch
- * @return int <0 if KO, >0 if OK
+ * @return int <0 if KO, >0 if OK
*/
function livraison($user, $fk_product, $entrepot_id, $qty, $price=0, $label='', $datem='', $eatby='', $sellby='', $batch='', $id_product_batch=0)
{
@@ -592,8 +704,10 @@ class MouvementStock extends CommonObject
*
* @param int $id Id of product
* @return int <0 if KO, nb of subproducts if OK
+ * @deprecated A count($product->getChildsArbo($id,1)) is same. No reason to have this in this class.
*/
- function nbOfSubProdcuts($id)
+ /*
+ function nbOfSubProducts($id)
{
$nbSP=0;
@@ -605,7 +719,7 @@ class MouvementStock extends CommonObject
$nbSP=$obj->nb;
}
return $nbSP;
- }
+ }*/
/**
* Count number of product in stock before a specific date
diff --git a/htdocs/product/stock/mouvement.php b/htdocs/product/stock/mouvement.php
index 7d80032e1d9..870c6629054 100644
--- a/htdocs/product/stock/mouvement.php
+++ b/htdocs/product/stock/mouvement.php
@@ -534,7 +534,8 @@ if ($resql)
// Nb of products
print '
| '.$langs->trans("NumberOfProducts").' | ';
- print empty($calcproducts['nb'])?'0':$calcproducts['nb'];
+ $valtoshow=price2num($calcproducts['nb'], 'MS');
+ print empty($valtoshow)?'0':$valtoshow;
print " |
";
print '';