Merge pull request #12453 from c3do/patch-3

API New get / add / remove subproducts, attributes and variants
This commit is contained in:
Laurent Destailleur
2019-11-22 14:34:54 +01:00
committed by GitHub
4 changed files with 864 additions and 32 deletions

View File

@@ -21,6 +21,10 @@ use Luracast\Restler\RestException;
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductAttribute.class.php';
require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductAttributeValue.class.php';
require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination.class.php';
require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination2ValuePair.class.php';
/**
* API class for products
@@ -64,17 +68,18 @@ class Products extends DolibarrApi
*
* Return an array with product information.
*
* @param int $id ID of product
* @param int $includestockdata Load also information about stock (slower)
* @param int $id ID of product
* @param int $includestockdata Load also information about stock (slower)
* @param bool $includesubproducts Load information about subproducts
* @return array|mixed Data without useless information
*
* @throws 401
* @throws 403
* @throws 404
*/
public function get($id, $includestockdata = 0)
public function get($id, $includestockdata = 0, $includesubproducts = false)
{
return $this->_fetch($id, '', '', '', $includestockdata);
return $this->_fetch($id, '', '', '', $includestockdata, $includesubproducts);
}
/**
@@ -82,20 +87,21 @@ class Products extends DolibarrApi
*
* Return an array with product information.
*
* @param string $ref Ref of element
* @param int $includestockdata Load also information about stock (slower)
* @param string $ref Ref of element
* @param int $includestockdata Load also information about stock (slower)
* @param bool $includesubproducts Load information about subproducts
*
* @return array|mixed Data without useless information
*
* @url GET byRef/{ref}
* @url GET ref/{ref}
*
* @throws 401
* @throws 403
* @throws 404
*/
public function getByRef($ref, $includestockdata = 0)
public function getByRef($ref, $includestockdata = 0, $includesubproducts = false)
{
return $this->_fetch('', $ref, '', '', $includestockdata);
return $this->_fetch('', $ref, '', '', $includestockdata, $includesubproducts);
}
/**
@@ -103,20 +109,21 @@ class Products extends DolibarrApi
*
* Return an array with product information.
*
* @param string $ref_ext Ref_ext of element
* @param int $includestockdata Load also information about stock (slower)
* @param string $ref_ext Ref_ext of element
* @param int $includestockdata Load also information about stock (slower)
* @param bool $includesubproducts Load information about subproducts
*
* @return array|mixed Data without useless information
*
* @url GET byRefExt/{ref_ext}
* @url GET ref_ext/{ref_ext}
*
* @throws 401
* @throws 403
* @throws 404
*/
public function getByRefExt($ref_ext, $includestockdata = 0)
public function getByRefExt($ref_ext, $includestockdata = 0, $includesubproducts = false)
{
return $this->_fetch('', '', $ref_ext, '', $includestockdata);
return $this->_fetch('', '', $ref_ext, '', $includestockdata, $includesubproducts);
}
/**
@@ -124,20 +131,21 @@ class Products extends DolibarrApi
*
* Return an array with product information.
*
* @param string $barcode Barcode of element
* @param int $includestockdata Load also information about stock (slower)
* @param string $barcode Barcode of element
* @param int $includestockdata Load also information about stock (slower)
* @param bool $includesubproducts Load information about subproducts
*
* @return array|mixed Data without useless information
*
* @url GET byBarcode/{barcode}
* @url GET barcode/{barcode}
*
* @throws 401
* @throws 403
* @throws 404
*/
public function getByBarcode($barcode, $includestockdata = 0)
public function getByBarcode($barcode, $includestockdata = 0, $includesubproducts = false)
{
return $this->_fetch('', '', '', $barcode, $includestockdata);
return $this->_fetch('', '', '', $barcode, $includestockdata, $includesubproducts);
}
/**
@@ -370,6 +378,105 @@ class Products extends DolibarrApi
return $this->product->delete(DolibarrApiAccess::$user);
}
/**
* Get the list of subproducts of the product.
*
* @param int $id Id of parent product/service
* @return array
*
* @throws RestException
* @throws 401
* @throws 404
*
* @url GET {id}/subproducts
*/
public function getSubproducts($id)
{
if(! DolibarrApiAccess::$user->rights->produit->lire) {
throw new RestException(401);
}
if(! DolibarrApi::_checkAccessToResource('product', $id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
$childsArbo = $this->product->getChildsArbo($id, 1);
$keys = ['rowid', 'qty', 'fk_product_type', 'label', 'incdec'];
$childs = [];
foreach ($childsArbo as $values) {
$childs[] = array_combine($keys, $values);
}
return $childs;
}
/**
* Add subproduct.
*
* Link a product/service to a parent product/service
*
* @param int $id Id of parent product/service
* @param int $subproduct_id Id of child product/service
* @param int $qty Quantity
* @param int $incdec 1=Increase/decrease stock of child when parent stock increase/decrease
* @return int
*
* @throws RestException
* @throws 401
* @throws 404
*
* @url POST {id}/subproducts/add
*/
public function addSubproducts($id, $subproduct_id, $qty, $incdec = 1)
{
if(! DolibarrApiAccess::$user->rights->produit->creer) {
throw new RestException(401);
}
if(! DolibarrApi::_checkAccessToResource('product', $id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
$result = $this->product->add_sousproduit($id, $subproduct_id, $qty, $incdec);
if ($result <= 0) {
throw new RestException(500, "Error adding product child");
}
return $result;
}
/**
* Remove subproduct.
*
* Unlink a product/service from a parent product/service
*
* @param int $id Id of parent product/service
* @param int $subproduct_id Id of child product/service
* @return int
*
* @throws RestException
* @throws 401
* @throws 404
*
* @url DELETE {id}/subproducts/remove
*/
public function delSubproducts($id, $subproduct_id)
{
if(! DolibarrApiAccess::$user->rights->produit->creer) {
throw new RestException(401);
}
if(! DolibarrApi::_checkAccessToResource('product', $id)) {
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
$result = $this->product->del_sousproduit($id, $subproduct_id);
if ($result <= 0) {
throw new RestException(500, "Error while removing product child");
}
return $result;
}
/**
* Get categories for a product
@@ -696,6 +803,713 @@ class Products extends DolibarrApi
return $this->_cleanObjectDatas($this->productsupplier);
}
/**
* Get attributes.
*
* @return array
*
* @throws RestException
*
* @url GET attributes
*/
public function getAttributes()
{
if(! DolibarrApiAccess::$user->rights->produit->lire) {
throw new RestException(401);
}
$prodattr = new ProductAttribute($this->db);
return $prodattr->fetchAll();
}
/**
* Get attribute by ID.
*
* @param int $id ID of Attribute
* @return array
*
* @throws RestException
* @throws 401
* @throws 404
*
* @url GET attributes/{id}
*/
public function getAttributeById($id)
{
if(! DolibarrApiAccess::$user->rights->produit->lire) {
throw new RestException(401);
}
$prodattr = new ProductAttribute($this->db);
$result = $prodattr->fetch((int) $id);
if($result < 0) {
throw new RestException(404, "Attribute not found");
}
return $prodattr;
}
/**
* Get attributes by ref.
*
* @param string $ref Reference of Attribute
* @return array
*
* @throws RestException
* @throws 401
*
* @url GET attributes/ref/{ref}
*/
public function getAttributesByRef($ref)
{
if(! DolibarrApiAccess::$user->rights->produit->lire) {
throw new RestException(401);
}
$sql = "SELECT rowid, ref, label, rang FROM ".MAIN_DB_PREFIX."product_attribute WHERE ref LIKE '". trim($ref) ."' AND entity IN (".getEntity('product').")";
$query = $this->db->query($sql);
if (!$this->db->num_rows($query)) {
throw new RestException(404);
}
$result = $this->db->fetch_object($query);
$attr = [];
$attr['id'] = $result->rowid;
$attr['ref'] = $result->ref;
$attr['label'] = $result->label;
$attr['rang'] = $result->rang;
return $attr;
}
/**
* Add attributes.
*
* @param string $ref Reference of Attribute
* @param string $label Label of Attribute
* @return int
*
* @throws RestException
* @throws 401
*
* @url POST attributes
*/
public function addAttributes($ref, $label)
{
if(! DolibarrApiAccess::$user->rights->produit->creer) {
throw new RestException(401);
}
$prodattr = new ProductAttribute($this->db);
$prodattr->label = $label;
$prodattr->ref = $ref;
$resid = $prodattr->create(DolibarrApiAccess::$user);
if ($resid <= 0) {
throw new RestException(500, "Error creating new attribute");
}
return $resid;
}
/**
* Update attributes by id.
*
* @param int $id ID of Attribute
* @param array $request_data Datas
* @return array
*
* @throws RestException
* @throws 401
* @throws 404
*
* @url PUT attributes/{id}
*/
public function putAttributes($id, $request_data = null)
{
if(! DolibarrApiAccess::$user->rights->produit->creer) {
throw new RestException(401);
}
$prodattr = new ProductAttribute($this->db);
$result = $prodattr->fetch((int) $id);
if ($result == 0) {
throw new RestException(404, 'Attribute not found');
} elseif ($result < 0) {
throw new RestException(500, "Error fetching attribute");
}
foreach($request_data as $field => $value) {
if ($field == 'rowid') { continue;
}
$prodattr->$field = $value;
}
if ($prodattr->update(DolibarrApiAccess::$user) > 0) {
$result = $prodattr->fetch((int) $id);
if ($result == 0) {
throw new RestException(404, 'Attribute not found');
} elseif ($result < 0) {
throw new RestException(500, "Error fetching attribute");
} else {
return $prodattr;
}
}
throw new RestException(500, "Error updating attribute");
}
/**
* Delete attributes by id.
*
* @param int $id ID of Attribute
* @return int
*
* @throws RestException
* @throws 401
*
* @url DELETE attributes/{id}
*/
public function deleteAttributes($id)
{
if(! DolibarrApiAccess::$user->rights->produit->supprimer) {
throw new RestException(401);
}
$prodattr = new ProductAttribute($this->db);
$prodattr->id = (int) $id;
$result = $prodattr->delete();
if ($result > 0) {
return 1;
}
throw new RestException(500, "Error deleting attribute");
}
/**
* Get attribute value by id.
*
* @param int $id ID of Attribute value
* @return array
*
* @throws RestException
* @throws 401
*
* @url GET attributes/values/{id}
*/
public function getAttributeValueById($id)
{
if(! DolibarrApiAccess::$user->rights->produit->lire) {
throw new RestException(401);
}
$sql = "SELECT rowid, fk_product_attribute, ref, value FROM ".MAIN_DB_PREFIX."product_attribute_value WHERE rowid = ".(int) $id." AND entity IN (".getEntity('product').")";
$query = $this->db->query($sql);
if (!$query) {
throw new RestException(401);
}
if (!$this->db->num_rows($query)) {
throw new RestException(404, 'Attribute value not found');
}
$result = $this->db->fetch_object($query);
$attrval = [];
$attrval['id'] = $result->rowid;
$attrval['fk_product_attribute'] = $result->fk_product_attribute;
$attrval['ref'] = $result->ref;
$attrval['value'] = $result->value;
return $attrval;
}
/**
* Get attribute value by ref.
*
* @param int $id ID of Attribute value
* @param string $ref Ref of Attribute value
* @return array
*
* @throws RestException
* @throws 401
*
* @url GET attributes/{id}/values/ref/{ref}
*/
public function getAttributeValueByRef($id, $ref)
{
if(! DolibarrApiAccess::$user->rights->produit->lire) {
throw new RestException(401);
}
$sql = "SELECT rowid, fk_product_attribute, ref, value FROM ".MAIN_DB_PREFIX."product_attribute_value WHERE ref LIKE '". trim($ref) ."' AND fk_product_attribute = ". (int) $id ." AND entity IN (".getEntity('product').")";
$query = $this->db->query($sql);
if (!$query) {
throw new RestException(401);
}
if (!$this->db->num_rows($query)) {
throw new RestException(404, 'Attribute value not found');
}
$result = $this->db->fetch_object($query);
$attrval = [];
$attrval['id'] = $result->rowid;
$attrval['fk_product_attribute'] = $result->fk_product_attribute;
$attrval['ref'] = $result->ref;
$attrval['value'] = $result->value;
return $attrval;
}
/**
* Delete attribute value by ref.
*
* @param int $id ID of Attribute
* @param string $ref Ref of Attribute value
* @return int
*
* @throws RestException
* @throws 401
*
* @url DELETE attributes/{id}/values/ref/{ref}
*/
public function deleteAttributeValueByRef($id, $ref)
{
if(! DolibarrApiAccess::$user->rights->produit->supprimer) {
throw new RestException(401);
}
$sql = "DELETE FROM ".MAIN_DB_PREFIX."product_attribute_value WHERE ref LIKE '". trim($ref) ."' AND fk_product_attribute = ". (int) $id;
if ($this->db->query($sql)) {
return 1;
}
throw new RestException(500, "Error deleting attribute value");
}
/**
* Get all values for an attribute id.
*
* @param int $id ID of an Attribute
* @return array
*
* @throws RestException
* @throws 401
*
* @url GET attributes/{id}/values
*/
public function getAttributeValues($id)
{
if(! DolibarrApiAccess::$user->rights->produit->lire) {
throw new RestException(401);
}
$objectval = new ProductAttributeValue($this->db);
return $objectval->fetchAllByProductAttribute((int) $id);
}
/**
* Get all values for an attribute ref.
*
* @param string $ref Ref of an Attribute
* @return array
*
* @throws RestException
* @throws 401
*
* @url GET attributes/ref/{ref}/values
*/
public function getAttributeValuesByRef($ref)
{
if(! DolibarrApiAccess::$user->rights->produit->lire) {
throw new RestException(401);
}
$return = array();
$sql = 'SELECT ';
$sql .= 'v.fk_product_attribute, v.rowid, v.ref, v.value FROM '.MAIN_DB_PREFIX.'product_attribute_value v ';
$sql .= "WHERE v.fk_product_attribute = ( SELECT rowid FROM ".MAIN_DB_PREFIX."product_attribute WHERE ref LIKE '". strtoupper(trim($ref)) ."' LIMIT 1)";
$query = $this->db->query($sql);
while ($result = $this->db->fetch_object($query)) {
$tmp = new ProductAttributeValue($this->db);
$tmp->fk_product_attribute = $result->fk_product_attribute;
$tmp->id = $result->rowid;
$tmp->ref = $result->ref;
$tmp->value = $result->value;
$return[] = $tmp;
}
return $return;
}
/**
* Add attribute value.
*
* @param int $id ID of Attribute
* @param string $ref Reference of Attribute value
* @param string $value Value of Attribute value
* @return int
*
* @throws RestException
* @throws 401
*
* @url POST attributes/{id}/values
*/
public function addAttributeValue($id, $ref, $value)
{
if(! DolibarrApiAccess::$user->rights->produit->creer) {
throw new RestException(401);
}
if (empty($ref) || empty($value)) {
throw new RestException(401);
}
$objectval = new ProductAttributeValue($this->db);
$objectval->fk_product_attribute = $id;
$objectval->ref = $ref;
$objectval->value = $value;
if ($objectval->create(DolibarrApiAccess::$user) > 0) {
return $objectval->id;
}
throw new RestException(500, "Error creating new attribute value");
}
/**
* Update attribute value.
*
* @param int $id ID of Attribute
* @param array $request_data Datas
* @return array
*
* @throws RestException
* @throws 401
*
* @url PUT attributes/values/{id}
*/
public function putAttributeValue($id, $request_data)
{
if(! DolibarrApiAccess::$user->rights->produit->creer) {
throw new RestException(401);
}
$objectval = new ProductAttributeValue($this->db);
$result = $objectval->fetch((int) $id);
if ($result == 0) {
throw new RestException(404, 'Attribute value not found');
} elseif ($result < 0) {
throw new RestException(500, "Error fetching attribute value");
}
foreach($request_data as $field => $value) {
if ($field == 'rowid') { continue;
}
$objectval->$field = $value;
}
if ($objectval->update(DolibarrApiAccess::$user) > 0) {
$result = $objectval->fetch((int) $id);
if ($result == 0) {
throw new RestException(404, 'Attribute not found');
} elseif ($result < 0) {
throw new RestException(500, "Error fetching attribute");
} else {
return $objectval;
}
}
throw new RestException(500, "Error updating attribute");
}
/**
* Delete attribute value by id.
*
* @param int $id ID of Attribute value
* @return int
*
* @throws RestException
* @throws 401
*
* @url DELETE attributes/values/{id}
*/
public function deleteAttributeValueById($id)
{
if(! DolibarrApiAccess::$user->rights->produit->supprimer) {
throw new RestException(401);
}
$objectval = new ProductAttributeValue($this->db);
$objectval->id = (int) $id;
if ($objectval->delete() > 0) {
return 1;
}
throw new RestException(500, "Error deleting attribute value");
}
/**
* Get product variants.
*
* @param int $id ID of Product
* @return array
*
* @throws RestException
* @throws 401
*
* @url GET {id}/variants
*/
public function getVariants($id)
{
if(! DolibarrApiAccess::$user->rights->produit->lire) {
throw new RestException(401);
}
$prodcomb = new ProductCombination($this->db);
$combinations = $prodcomb->fetchAllByFkProductParent((int) $id);
foreach ($combinations as $key => $combination) {
$prodc2vp = new ProductCombination2ValuePair($this->db);
$combinations[$key]->attributes = $prodc2vp->fetchByFkCombination((int) $combination->id);
}
return $combinations;
}
/**
* Get product variants by Product ref.
*
* @param string $ref Ref of Product
* @return array
*
* @throws RestException
* @throws 401
*
* @url GET ref/{ref}/variants
*/
public function getVariantsByProdRef($ref)
{
if(! DolibarrApiAccess::$user->rights->produit->lire) {
throw new RestException(401);
}
$result = $this->product->fetch('', $ref);
if(! $result ) {
throw new RestException(404, 'Product not found');
}
$prodcomb = new ProductCombination($this->db);
$combinations = $prodcomb->fetchAllByFkProductParent((int) $this->product->id);
foreach ($combinations as $key => $combination) {
$prodc2vp = new ProductCombination2ValuePair($this->db);
$combinations[$key]->attributes = $prodc2vp->fetchByFkCombination((int) $combination->id);
}
return $combinations;
}
/**
* Add variant.
*
* "features" is a list of attributes pairs id_attribute=>id_value. Example: array(id_color=>id_Blue, id_size=>id_small, id_option=>id_val_a, ...)
*
* @param int $id ID of Product
* @param float $weight_impact Weight impact of variant
* @param float $price_impact Price impact of variant
* @param bool $price_impact_is_percent Price impact in percent (true or false)
* @param array $features List of attributes pairs id_attribute->id_value. Example: array(id_color=>id_Blue, id_size=>id_small, id_option=>id_val_a, ...)
* @return int
*
* @throws RestException
* @throws 401
* @throws 404
*
* @url POST {id}/variants
*/
public function addVariant($id, $weight_impact, $price_impact, $price_impact_is_percent, $features)
{
if(! DolibarrApiAccess::$user->rights->produit->creer) {
throw new RestException(401);
}
if (empty($id) || empty($features) || !is_array($features)) {
throw new RestException(401);
}
$weight_impact = price2num($weight_impact);
$price_impact = price2num($price_impact);
$prodattr = new ProductAttribute($this->db);
$prodattr_val = new ProductAttributeValue($this->db);
foreach ($features as $id_attr => $id_value) {
if ($prodattr->fetch((int) $id_attr) < 0) {
throw new RestException(401);
}
if ($prodattr_val->fetch((int) $id_value) < 0) {
throw new RestException(401);
}
}
$result = $this->product->fetch((int) $id);
if(! $result ) {
throw new RestException(404, 'Product not found');
}
$prodcomb = new ProductCombination($this->db);
if (! $prodcomb->fetchByProductCombination2ValuePairs($id, $features))
{
$result = $prodcomb->createProductCombination(DolibarrApiAccess::$user, $this->product, $features, array(), $price_impact_is_percent, $price_impact, $weight_impact);
if ($result > 0)
{
return $result;
} else {
throw new RestException(500, "Error creating new product variant");
}
} else {
return $prodcomb->id;
}
}
/**
* Add variant by product ref.
*
* "features" is a list of attributes pairs id_attribute=>id_value. Example: array(id_color=>id_Blue, id_size=>id_small, id_option=>id_val_a, ...)
*
* @param string $ref Ref of Product
* @param float $weight_impact Weight impact of variant
* @param float $price_impact Price impact of variant
* @param bool $price_impact_is_percent Price impact in percent (true or false)
* @param array $features List of attributes pairs id_attribute->id_value. Example: array(id_color=>id_Blue, id_size=>id_small, id_option=>id_val_a, ...)
* @return int
*
* @throws RestException
* @throws 401
* @throws 404
*
* @url POST ref/{ref}/variants
*/
public function addVariantByProductRef($ref, $weight_impact, $price_impact, $price_impact_is_percent, $features)
{
if(! DolibarrApiAccess::$user->rights->produit->creer) {
throw new RestException(401);
}
if (empty($ref) || empty($features) || !is_array($features)) {
throw new RestException(401);
}
$weight_impact = price2num($weight_impact);
$price_impact = price2num($price_impact);
$prodattr = new ProductAttribute($this->db);
$prodattr_val = new ProductAttributeValue($this->db);
foreach ($features as $id_attr => $id_value) {
if ($prodattr->fetch((int) $id_attr) < 0) {
throw new RestException(404);
}
if ($prodattr_val->fetch((int) $id_value) < 0) {
throw new RestException(404);
}
}
$result = $this->product->fetch('', trim($ref));
if(! $result ) {
throw new RestException(404, 'Product not found');
}
$prodcomb = new ProductCombination($this->db);
if (! $prodcomb->fetchByProductCombination2ValuePairs($this->product->id, $features))
{
$result = $prodcomb->createProductCombination(DolibarrApiAccess::$user, $this->product, $features, array(), $price_impact_is_percent, $price_impact, $weight_impact);
if ($result > 0)
{
return $result;
} else {
throw new RestException(500, "Error creating new product variant");
}
} else {
return $prodcomb->id;
}
}
/**
* Put product variants.
*
* @param int $id ID of Variant
* @param array $request_data Datas
* @return int
*
* @throws RestException
* @throws 401
*
* @url PUT variants/{id}
*/
public function putVariant($id, $request_data = null)
{
if(! DolibarrApiAccess::$user->rights->produit->creer) {
throw new RestException(401);
}
$prodcomb = new ProductCombination($this->db);
$prodcomb->fetch((int) $id);
foreach($request_data as $field => $value) {
if ($field == 'rowid') { continue;
}
$prodcomb->$field = $value;
}
$result = $prodcomb->update(DolibarrApiAccess::$user);
if ($result > 0)
{
return 1;
}
throw new RestException(500, "Error editing variant");
}
/**
* Delete product variants.
*
* @param int $id ID of Variant
* @return int
*
* @throws RestException
* @throws 401
*
* @url DELETE variants/{id}
*/
public function deleteVariant($id)
{
if(! DolibarrApiAccess::$user->rights->produit->supprimer) {
throw new RestException(401);
}
$prodcomb = new ProductCombination($this->db);
$prodcomb->id = (int) $id;
$result = $prodcomb->delete(DolibarrApiAccess::$user);
return $result;
if ($result > 0)
{
return 1;
}
throw new RestException(500, "Error deleting variant");
}
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
/**
* Clean sensible object datas
@@ -748,18 +1562,19 @@ class Products extends DolibarrApi
*
* Return an array with product information.
*
* @param int $id ID of product
* @param string $ref Ref of element
* @param string $ref_ext Ref ext of element
* @param string $barcode Barcode of element
* @param int $includestockdata Load also information about stock (slower)
* @return array|mixed Data without useless information
* @param int $id ID of product
* @param string $ref Ref of element
* @param string $ref_ext Ref ext of element
* @param string $barcode Barcode of element
* @param int $includestockdata Load also information about stock (slower)
* @param bool $includesubproducts Load information about subproducts
* @return array|mixed Data without useless information
*
* @throws 401
* @throws 403
* @throws 404
*/
private function _fetch($id, $ref = '', $ref_ext = '', $barcode = '', $includestockdata = 0)
private function _fetch($id, $ref = '', $ref_ext = '', $barcode = '', $includestockdata = 0, $includesubproducts = false)
{
if (empty($id) && empty($ref) && empty($ref_ext) && empty($barcode)) {
throw new RestException(400, 'bad value for parameter id, ref, ref_ext or barcode');
@@ -784,6 +1599,20 @@ class Products extends DolibarrApi
$this->product->load_stock();
}
if ($includesubproducts) {
$childsArbo = $this->product->getChildsArbo($id, 1);
$keys = ['rowid', 'qty', 'fk_product_type', 'label', 'incdec'];
$childs = [];
foreach ($childsArbo as $values) {
$childs[] = array_combine($keys, $values);
}
$this->product->sousprods = $childs;
}
return $this->_cleanObjectDatas($this->product);
}
}

View File

@@ -495,6 +495,7 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1";
* [...]
* )
*
* @param User $user Object user
* @param Product $product Parent product
* @param array $combinations Attribute and value combinations.
* @param array $variations Price and weight variations
@@ -503,9 +504,9 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1";
* @param bool|float $forced_weightvar If the weight variation is forced
* @return int <0 KO, >0 OK
*/
public function createProductCombination(Product $product, array $combinations, array $variations, $price_var_percent = false, $forced_pricevar = false, $forced_weightvar = false)
public function createProductCombination(User $user, Product $product, array $combinations, array $variations, $price_var_percent = false, $forced_pricevar = false, $forced_weightvar = false)
{
global $db, $user, $conf;
global $db, $conf;
require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductAttribute.class.php';
require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductAttributeValue.class.php';
@@ -660,11 +661,12 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1";
/**
* Copies all product combinations from the origin product to the destination product
*
* @param User $user Object user
* @param int $origProductId Origin product id
* @param Product $destProduct Destination product
* @return int >0 OK <0 KO
*/
public function copyAll($origProductId, Product $destProduct)
public function copyAll(User $user, $origProductId, Product $destProduct)
{
require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination2ValuePair.class.php';
@@ -686,6 +688,7 @@ WHERE c.fk_product_parent = ".(int) $productid." AND p.tosell = 1";
}
if ($this->createProductCombination(
$user,
$destProduct,
$variations,
array(),

View File

@@ -141,7 +141,7 @@ if ($_POST) {
if (!$prodcomb->fetchByProductCombination2ValuePairs($id, $sanit_features))
{
$result = $prodcomb->createProductCombination($object, $sanit_features, array(), $price_impact_percent, $price_impact, $weight_impact);
$result = $prodcomb->createProductCombination($user, $object, $sanit_features, array(), $price_impact_percent, $price_impact, $weight_impact);
if ($result > 0)
{
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
@@ -268,7 +268,7 @@ if ($action === 'confirm_deletecombination') {
if ($prodstatic->fetch('', $dest_product) > 0) {
//To prevent from copying to the same product
if ($prodstatic->ref != $object->ref) {
if ($prodcomb->copyAll($object->id, $prodstatic) > 0) {
if ($prodcomb->copyAll($user, $object->id, $prodstatic) > 0) {
header('Location: '.dol_buildpath('/variants/combinations.php?id='.$prodstatic->id, 2));
exit();
} else {

View File

@@ -110,7 +110,7 @@ if ($_POST)
$cartesianarray = cartesianArray($adapted_values);
foreach ($cartesianarray as $currcomb)
{
$res = $combination->createProductCombination($product, $currcomb, $sanitized_values, $price_var_percent);
$res = $combination->createProductCombination($user, $product, $currcomb, $sanitized_values, $price_var_percent);
if ($res < 0) {
$error++;
setEventMessages($combination->error, $combination->errors, 'errors');