Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop
This commit is contained in:
commit
1cb1473948
190
htdocs/core/boxes/box_shipments.php
Normal file
190
htdocs/core/boxes/box_shipments.php
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
<?php
|
||||||
|
/* Copyright (C) 2003-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
|
||||||
|
* Copyright (C) 2004-2009 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||||
|
* Copyright (C) 2005-2009 Regis Houssin <regis.houssin@inodbox.com>
|
||||||
|
* Copyright (C) 2019 Alexandre Spangaro <aspangaro@open-dsi.fr>
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file htdocs/core/boxes/box_shipments.php
|
||||||
|
* \ingroup shipment
|
||||||
|
* \brief Module for generating the display of the shipment box
|
||||||
|
*/
|
||||||
|
|
||||||
|
include_once DOL_DOCUMENT_ROOT.'/core/boxes/modules_boxes.php';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to manage the box to show last shipments
|
||||||
|
*/
|
||||||
|
class box_shipments extends ModeleBoxes
|
||||||
|
{
|
||||||
|
public $boxcode="lastcustomershipments";
|
||||||
|
public $boximg="sending";
|
||||||
|
public $boxlabel="BoxLastCustomerShipments";
|
||||||
|
public $depends = array("expedition");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var DoliDB Database handler.
|
||||||
|
*/
|
||||||
|
public $db;
|
||||||
|
|
||||||
|
public $param;
|
||||||
|
|
||||||
|
public $info_box_head = array();
|
||||||
|
public $info_box_contents = array();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param DoliDB $db Database handler
|
||||||
|
* @param string $param More parameters
|
||||||
|
*/
|
||||||
|
public function __construct($db, $param)
|
||||||
|
{
|
||||||
|
global $user;
|
||||||
|
|
||||||
|
$this->db=$db;
|
||||||
|
|
||||||
|
$this->hidden=! ($user->rights->expedition->lire);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load data for box to show them later
|
||||||
|
*
|
||||||
|
* @param int $max Maximum number of records to load
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function loadBox($max = 5)
|
||||||
|
{
|
||||||
|
global $user, $langs, $conf;
|
||||||
|
$langs->loadLangs(array('orders', 'sendings'));
|
||||||
|
|
||||||
|
$this->max = $max;
|
||||||
|
|
||||||
|
include_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
|
||||||
|
include_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
|
||||||
|
|
||||||
|
$shipmentstatic = new Expedition($this->db);
|
||||||
|
$orderstatic = new Commande($this->db);
|
||||||
|
$societestatic = new Societe($this->db);
|
||||||
|
|
||||||
|
$this->info_box_head = array('text' => $langs->trans("BoxTitleLastCustomerShipments", $max));
|
||||||
|
|
||||||
|
if ($user->rights->expedition->lire)
|
||||||
|
{
|
||||||
|
$sql = "SELECT s.nom as name";
|
||||||
|
$sql.= ", s.rowid as socid";
|
||||||
|
$sql.= ", s.code_client";
|
||||||
|
$sql.= ", s.logo, s.email";
|
||||||
|
$sql.= ", e.ref, e.tms";
|
||||||
|
$sql.= ", e.rowid";
|
||||||
|
$sql.= ", e.ref_customer";
|
||||||
|
$sql.= ", e.fk_statut";
|
||||||
|
$sql.= ", e.fk_user_valid";
|
||||||
|
$sql.= ", c.ref as commande_ref";
|
||||||
|
$sql.= ", c.rowid as commande_id";
|
||||||
|
$sql.= " FROM ".MAIN_DB_PREFIX."expedition as e";
|
||||||
|
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."element_element as el ON e.rowid = el.fk_target AND el.targettype = 'shipping' AND el.sourcetype IN ('commande')";
|
||||||
|
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."commande as c ON el.fk_source = c.rowid AND el.sourcetype IN ('commande') AND el.targettype = 'shipping'";
|
||||||
|
$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = e.fk_soc";
|
||||||
|
if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON e.fk_soc = sc.fk_soc";
|
||||||
|
$sql.= " WHERE e.entity = ".$conf->entity;
|
||||||
|
if (! empty($conf->global->ORDER_BOX_LAST_SHIPMENTS_VALIDATED_ONLY)) $sql.=" AND e.fk_statut = 1";
|
||||||
|
if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " AND sc.fk_user = " .$user->id;
|
||||||
|
else $sql.= " ORDER BY e.date_delivery, e.ref DESC ";
|
||||||
|
$sql.= $this->db->plimit($max, 0);
|
||||||
|
|
||||||
|
$result = $this->db->query($sql);
|
||||||
|
if ($result) {
|
||||||
|
$num = $this->db->num_rows($result);
|
||||||
|
|
||||||
|
$line = 0;
|
||||||
|
|
||||||
|
while ($line < $num) {
|
||||||
|
$objp = $this->db->fetch_object($result);
|
||||||
|
|
||||||
|
$shipmentstatic->id = $objp->rowid;
|
||||||
|
$shipmentstatic->ref = $objp->ref;
|
||||||
|
$shipmentstatic->ref_customer = $objp->ref_customer;
|
||||||
|
|
||||||
|
$orderstatic->id= $objp->commande_id;
|
||||||
|
$orderstatic->ref=$objp->commande_ref;
|
||||||
|
|
||||||
|
$societestatic->id = $objp->socid;
|
||||||
|
$societestatic->name = $objp->name;
|
||||||
|
$societestatic->email = $objp->email;
|
||||||
|
$societestatic->code_client = $objp->code_client;
|
||||||
|
$societestatic->logo = $objp->logo;
|
||||||
|
|
||||||
|
$this->info_box_contents[$line][] = array(
|
||||||
|
'td' => '',
|
||||||
|
'text' => $shipmentstatic->getNomUrl(1),
|
||||||
|
'asis' => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->info_box_contents[$line][] = array(
|
||||||
|
'td' => 'class="tdoverflowmax150 maxwidth150onsmartphone"',
|
||||||
|
'text' => $societestatic->getNomUrl(1),
|
||||||
|
'asis' => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->info_box_contents[$line][] = array(
|
||||||
|
'td' => '',
|
||||||
|
'text' => $orderstatic->getNomUrl(1),
|
||||||
|
'asis' => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->info_box_contents[$line][] = array(
|
||||||
|
'td' => 'class="right" width="18"',
|
||||||
|
'text' => $shipmentstatic->LibStatut($objp->fk_statut, 3),
|
||||||
|
);
|
||||||
|
|
||||||
|
$line++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($num==0) $this->info_box_contents[$line][0] = array('td' => 'class="center"','text'=>$langs->trans("NoRecordedShipments"));
|
||||||
|
|
||||||
|
$this->db->free($result);
|
||||||
|
} else {
|
||||||
|
$this->info_box_contents[0][0] = array(
|
||||||
|
'td' => '',
|
||||||
|
'maxlength'=>500,
|
||||||
|
'text' => ($this->db->error().' sql='.$sql),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->info_box_contents[0][0] = array(
|
||||||
|
'td' => 'class="nohover opacitymedium left"',
|
||||||
|
'text' => $langs->trans("ReadPermissionNotAllowed")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to show box
|
||||||
|
*
|
||||||
|
* @param array $head Array with properties of box title
|
||||||
|
* @param array $contents Array with properties of box lines
|
||||||
|
* @param int $nooutput No print, only return string
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function showBox($head = null, $contents = null, $nooutput = 0)
|
||||||
|
{
|
||||||
|
return parent::showBox($this->info_box_head, $this->info_box_contents, $nooutput);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -133,7 +133,9 @@ class modExpedition extends DolibarrModules
|
|||||||
$r++;
|
$r++;
|
||||||
|
|
||||||
// Boxes
|
// Boxes
|
||||||
$this->boxes = array();
|
$this->boxes = array(
|
||||||
|
0=>array('file'=>'box_shipments.php','enabledbydefaulton'=>'Home'),
|
||||||
|
);
|
||||||
|
|
||||||
// Permissions
|
// Permissions
|
||||||
$this->rights = array();
|
$this->rights = array();
|
||||||
|
|||||||
@ -97,3 +97,6 @@ BoxSuspenseAccount=Count accountancy operation with suspense account
|
|||||||
BoxTitleSuspenseAccount=Number of unallocated lines
|
BoxTitleSuspenseAccount=Number of unallocated lines
|
||||||
NumberOfLinesInSuspenseAccount=Number of line in suspense account
|
NumberOfLinesInSuspenseAccount=Number of line in suspense account
|
||||||
SuspenseAccountNotDefined=Suspense account isn't defined
|
SuspenseAccountNotDefined=Suspense account isn't defined
|
||||||
|
BoxLastCustomerShipments=Last customer shipments
|
||||||
|
BoxTitleLastCustomerShipments=Latest %s customer shipments
|
||||||
|
NoRecordedShipments=No recorded customer shipment
|
||||||
|
|||||||
@ -21,6 +21,10 @@ use Luracast\Restler\RestException;
|
|||||||
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
|
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.'/fourn/class/fournisseur.product.class.php';
|
||||||
require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.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
|
* API class for products
|
||||||
@ -66,15 +70,16 @@ class Products extends DolibarrApi
|
|||||||
*
|
*
|
||||||
* @param int $id ID of product
|
* @param int $id ID of product
|
||||||
* @param int $includestockdata Load also information about stock (slower)
|
* @param int $includestockdata Load also information about stock (slower)
|
||||||
|
* @param bool $includesubproducts Load information about subproducts
|
||||||
* @return array|mixed Data without useless information
|
* @return array|mixed Data without useless information
|
||||||
*
|
*
|
||||||
* @throws 401
|
* @throws 401
|
||||||
* @throws 403
|
* @throws 403
|
||||||
* @throws 404
|
* @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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,18 +89,19 @@ class Products extends DolibarrApi
|
|||||||
*
|
*
|
||||||
* @param string $ref Ref of element
|
* @param string $ref Ref of element
|
||||||
* @param int $includestockdata Load also information about stock (slower)
|
* @param int $includestockdata Load also information about stock (slower)
|
||||||
|
* @param bool $includesubproducts Load information about subproducts
|
||||||
*
|
*
|
||||||
* @return array|mixed Data without useless information
|
* @return array|mixed Data without useless information
|
||||||
*
|
*
|
||||||
* @url GET byRef/{ref}
|
* @url GET ref/{ref}
|
||||||
*
|
*
|
||||||
* @throws 401
|
* @throws 401
|
||||||
* @throws 403
|
* @throws 403
|
||||||
* @throws 404
|
* @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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -105,18 +111,19 @@ class Products extends DolibarrApi
|
|||||||
*
|
*
|
||||||
* @param string $ref_ext Ref_ext of element
|
* @param string $ref_ext Ref_ext of element
|
||||||
* @param int $includestockdata Load also information about stock (slower)
|
* @param int $includestockdata Load also information about stock (slower)
|
||||||
|
* @param bool $includesubproducts Load information about subproducts
|
||||||
*
|
*
|
||||||
* @return array|mixed Data without useless information
|
* @return array|mixed Data without useless information
|
||||||
*
|
*
|
||||||
* @url GET byRefExt/{ref_ext}
|
* @url GET ref_ext/{ref_ext}
|
||||||
*
|
*
|
||||||
* @throws 401
|
* @throws 401
|
||||||
* @throws 403
|
* @throws 403
|
||||||
* @throws 404
|
* @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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -126,18 +133,19 @@ class Products extends DolibarrApi
|
|||||||
*
|
*
|
||||||
* @param string $barcode Barcode of element
|
* @param string $barcode Barcode of element
|
||||||
* @param int $includestockdata Load also information about stock (slower)
|
* @param int $includestockdata Load also information about stock (slower)
|
||||||
|
* @param bool $includesubproducts Load information about subproducts
|
||||||
*
|
*
|
||||||
* @return array|mixed Data without useless information
|
* @return array|mixed Data without useless information
|
||||||
*
|
*
|
||||||
* @url GET byBarcode/{barcode}
|
* @url GET barcode/{barcode}
|
||||||
*
|
*
|
||||||
* @throws 401
|
* @throws 401
|
||||||
* @throws 403
|
* @throws 403
|
||||||
* @throws 404
|
* @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);
|
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
|
* Get categories for a product
|
||||||
@ -696,6 +803,713 @@ class Products extends DolibarrApi
|
|||||||
return $this->_cleanObjectDatas($this->productsupplier);
|
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
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
|
||||||
/**
|
/**
|
||||||
* Clean sensible object datas
|
* Clean sensible object datas
|
||||||
@ -753,13 +1567,14 @@ class Products extends DolibarrApi
|
|||||||
* @param string $ref_ext Ref ext of element
|
* @param string $ref_ext Ref ext of element
|
||||||
* @param string $barcode Barcode of element
|
* @param string $barcode Barcode of element
|
||||||
* @param int $includestockdata Load also information about stock (slower)
|
* @param int $includestockdata Load also information about stock (slower)
|
||||||
|
* @param bool $includesubproducts Load information about subproducts
|
||||||
* @return array|mixed Data without useless information
|
* @return array|mixed Data without useless information
|
||||||
*
|
*
|
||||||
* @throws 401
|
* @throws 401
|
||||||
* @throws 403
|
* @throws 403
|
||||||
* @throws 404
|
* @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)) {
|
if (empty($id) && empty($ref) && empty($ref_ext) && empty($barcode)) {
|
||||||
throw new RestException(400, 'bad value for parameter id, ref, ref_ext or 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();
|
$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);
|
return $this->_cleanObjectDatas($this->product);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -89,7 +89,9 @@ if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)
|
|||||||
{
|
{
|
||||||
$virtualdiffersfromphysical = 1; // According to increase/decrease stock options, virtual and physical stock may differs.
|
$virtualdiffersfromphysical = 1; // According to increase/decrease stock options, virtual and physical stock may differs.
|
||||||
}
|
}
|
||||||
$usevirtualstock = 0;
|
|
||||||
|
$usevirtualstock = !empty($conf->global->STOCK_USE_VIRTUAL_STOCK);
|
||||||
|
if ($mode == 'physical') $usevirtualstock = 0;
|
||||||
if ($mode == 'virtual') $usevirtualstock = 1;
|
if ($mode == 'virtual') $usevirtualstock = 1;
|
||||||
|
|
||||||
$parameters = array();
|
$parameters = array();
|
||||||
|
|||||||
@ -1985,7 +1985,7 @@ class Task extends CommonObject
|
|||||||
$sql .= " WHERE p.entity IN (".getEntity('project', 0).')';
|
$sql .= " WHERE p.entity IN (".getEntity('project', 0).')';
|
||||||
$sql .= " AND p.fk_statut = 1";
|
$sql .= " AND p.fk_statut = 1";
|
||||||
$sql .= " AND t.fk_projet = p.rowid";
|
$sql .= " AND t.fk_projet = p.rowid";
|
||||||
$sql .= " AND t.progress < 100"; // tasks to do
|
$sql .= " AND (t.progress IS NULL OR t.progress < 100)"; // tasks to do
|
||||||
if (!$user->rights->projet->all->lire) $sql .= " AND p.rowid IN (".$projectsListId.")";
|
if (!$user->rights->projet->all->lire) $sql .= " AND p.rowid IN (".$projectsListId.")";
|
||||||
// No need to check company, as filtering of projects must be done by getProjectsAuthorizedForUser
|
// No need to check company, as filtering of projects must be done by getProjectsAuthorizedForUser
|
||||||
//if ($socid || ! $user->rights->societe->client->voir) $sql.= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")";
|
//if ($socid || ! $user->rights->societe->client->voir) $sql.= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")";
|
||||||
|
|||||||
@ -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 Product $product Parent product
|
||||||
* @param array $combinations Attribute and value combinations.
|
* @param array $combinations Attribute and value combinations.
|
||||||
* @param array $variations Price and weight variations
|
* @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
|
* @param bool|float $forced_weightvar If the weight variation is forced
|
||||||
* @return int <0 KO, >0 OK
|
* @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/ProductAttribute.class.php';
|
||||||
require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductAttributeValue.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
|
* Copies all product combinations from the origin product to the destination product
|
||||||
*
|
*
|
||||||
|
* @param User $user Object user
|
||||||
* @param int $origProductId Origin product id
|
* @param int $origProductId Origin product id
|
||||||
* @param Product $destProduct Destination product
|
* @param Product $destProduct Destination product
|
||||||
* @return int >0 OK <0 KO
|
* @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';
|
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(
|
if ($this->createProductCombination(
|
||||||
|
$user,
|
||||||
$destProduct,
|
$destProduct,
|
||||||
$variations,
|
$variations,
|
||||||
array(),
|
array(),
|
||||||
|
|||||||
@ -141,7 +141,7 @@ if ($_POST) {
|
|||||||
|
|
||||||
if (!$prodcomb->fetchByProductCombination2ValuePairs($id, $sanit_features))
|
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)
|
if ($result > 0)
|
||||||
{
|
{
|
||||||
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
|
setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
|
||||||
@ -268,7 +268,7 @@ if ($action === 'confirm_deletecombination') {
|
|||||||
if ($prodstatic->fetch('', $dest_product) > 0) {
|
if ($prodstatic->fetch('', $dest_product) > 0) {
|
||||||
//To prevent from copying to the same product
|
//To prevent from copying to the same product
|
||||||
if ($prodstatic->ref != $object->ref) {
|
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));
|
header('Location: '.dol_buildpath('/variants/combinations.php?id='.$prodstatic->id, 2));
|
||||||
exit();
|
exit();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -110,7 +110,7 @@ if ($_POST)
|
|||||||
$cartesianarray = cartesianArray($adapted_values);
|
$cartesianarray = cartesianArray($adapted_values);
|
||||||
foreach ($cartesianarray as $currcomb)
|
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) {
|
if ($res < 0) {
|
||||||
$error++;
|
$error++;
|
||||||
setEventMessages($combination->error, $combination->errors, 'errors');
|
setEventMessages($combination->error, $combination->errors, 'errors');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user