Reputation: 61
I'm making a bridging app. to sync product quantities from a warehouse DB with a Prestashop 1.6 Multi-Store cart.
The script just needs to update one product quantity at a time and we have the product "ID" and the "quantity", however, I keep getting the following error returned:
RETURN HTTP BODY
<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<errors>
<error>
<code><![CDATA[93]]></code>
<message><![CDATA[parameter "quantity" not writable. Please remove this attribute of this XML]]></message>
</error>
</errors>
</prestashop>
This comes with: Other error This call to PrestaShop Web Services failed and returned an HTTP status of 400. That means: Bad Request.
XML error code 93 is The table is not present in the descriptor. I thought this was done by including "$opt = array('resource' => 'products');"
The code I'm using to get the XML, change the quantity value, and update is:
function test1($id, $quantity){
$id = (int)$id;
$quantity = (int)$quantity;
try
{
$webService = new PrestaShopWebservice(PS_SHOP_PATH, PS_WS_AUTH_KEY, DEBUG);
$opt = array('resource' => 'products', 'display' => '[id,quantity]');
if (isset($id))
$opt['id'] = $id;
$xml = $webService->get($opt);
$resources = $xml->children()->children();
}
catch (PrestaShopWebserviceException $e)
{
// Dealing with errors
$trace = $e->getTrace();
if ($trace[0]['args'][0] == 404) echo 'Bad ID';
else if ($trace[0]['args'][0] == 401) echo 'Bad auth key';
else echo 'Other error<br />'.$e->getMessage();
}
if (isset($id) && isset($quantity)){
$resources->id = $id;
$resources->quantity = $quantity;
// Call the web service
try
{
$opt = array('resource' => 'products');
$opt['putXml'] = $xml->asXML();
$opt['id'] = $id;
$xml = $webService->edit($opt);
echo "Successfully updated.";
}
catch (PrestaShopWebserviceException $ex)
{
// Here we are dealing with errors
$trace = $ex->getTrace();
if ($trace[0]['args'][0] == 404) echo 'Bad ID';
else if ($trace[0]['args'][0] == 401) echo 'Bad auth key';
else echo 'Other error<br />'.$ex->getMessage();
}
}
}
The initial XML returned that I use to update is:
<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<product id="45" xlink:href="https://www.WEBSITE.com/api/products/45"/>
</prestashop>
The XML that was sent for the Update is:
<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<product id="45" xlink:href="https://www.WEBSITE.com/api/products/45"><id>45</id><quantity>22</quantity></product>
</prestashop>
It seems that the sent XML or something is missing the table reference or something.
I've tried a couple ways all with the same result. Any ideas?
Thanks
Upvotes: 3
Views: 11389
Reputation: 2377
I wanted to share my solution of a product quantity update(in hope to help someone else). It may not be the best solution, but what the hek, it works (for me).
As Jarlaxxe says: The way to edit product quantity is via: api/stock_availables. So in order to geet the stock_availables ID you first need to get productinformation and retrieve stock_availables ID from there, and then put.
$webService = new PrestaShopWebservice('http://yoursite.com', 'LADEDILADEDA-BTW-YOUR-API-KEY-HERE', false);
updateStock(productnumber, quantity);
function updateStock($productID, $quantity){
//First we got the stock_availables ID from the Product ID
try
{
$opt = array('resource' => 'products');
$opt['id'] = $productID;
$xml = $webService->get($opt);
$resources = $xml->children()->children();
$stockID = $resources->associations->stock_availables->stock_availables;
foreach($stockID as $stock){
$stockAVailableID = $stock->id;
}
}
catch (PrestaShopWebserviceException $e)
{
$trace = $e->getTrace();
if ($trace[0]['args'][0] == 404) echo 'Bad ID';
else if ($trace[0]['args'][0] == 401) echo 'Bad auth key';
else echo 'Other error<br />'.$e->getMessage();
}
//Second we get all the stockAvailables resources
try
{
$opt = array('resource' => 'stock_availables');
$opt['id'] = $stockAVailableID;
$xml = $webService->get($opt);
$resources = $xml->children()->children();
}
catch (PrestaShopWebserviceException $e)
{
$trace = $e->getTrace();
if ($trace[0]['args'][0] == 404) echo 'Bad ID';
else if ($trace[0]['args'][0] == 401) echo 'Bad auth key';
else echo 'Other error<br />'.$e->getMessage();
}
//At last we update the quantity with the given value manupulated and all other values original
foreach ($resources as $nodeKey => $node)
{
if($nodeKey == 'quantity'){
unset($node);
$node = $quantity;
}
$resources->$nodeKey = $node;
}
try
{
$opt = array('resource' => 'stock_availables');
$opt['putXml'] = $xml->asXML();
$opt['id'] = $stockAVailableID;
$xml = $webService->edit($opt);
echo "Successfully updated.";
}
catch (PrestaShopWebserviceException $ex)
{
$trace = $ex->getTrace();
if ($trace[0]['args'][0] == 404) echo 'Bad ID';
else if ($trace[0]['args'][0] == 401) echo 'Bad auth key';
else echo 'Other error<br />'.$ex->getMessage();
}
}
Upvotes: 1
Reputation: 31
As you say, the field "quantity" in a product is write-protected, and in the schema "stock_available" you have a quantity field that you can write. Indeed, this is the field you should write.
You don't have to touch the DB; you can update the stock directly through the WS.
The schema "stock_availables" stores the ids of all the combinations of the products you have in your store. This is what the schema has:
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<stock_available>
<id_product required="true" format="isUnsignedId"/>
<id_product_attribute required="true" format="isUnsignedId"/>
<id_shop format="isUnsignedId"/>
<id_shop_group format="isUnsignedId"/>
<quantity required="true" format="isInt"/>
<depends_on_stock required="true" format="isBool"/>
<out_of_stock required="true" format="isInt"/>
</stock_available>
</prestashop>
The id_product_attribute refers to one combination of a product. If this attribute has a zero, it means that the product doesn't have any combination. As I say, this schema stores all the combinations of the products you have (all of them), so if a product has more than one combination, you'll have to look for it.
There are 3 schemas where the quantity field apears: products, combinations and stock_availables. Only the last one is "used". The first one is write protected and the second one, as I could investigate, is not used by the back store.
I hope this can help you and sorry for my poor english.
Upvotes: 2
Reputation: 9856
Here is how u create a product and change the quantity
try{
$webService = new PrestaShopWebservice(PS_SHOP_PATH, PS_WS_AUTH_KEY, DEBUG);
$opt = array('resource' => 'products');
$opt['postXml'] = $new_xml_content;
$xml = $webService->add($opt);
$id = $xml->children()->children()->id;
return $xml;
}
catch (PrestaShopWebserviceException $e)
{
}
getIdStockAvailableAndSet($new_xml->product->id);
function set_product_quantity($ProductId, $StokId, $AttributeId){
$xml = $this->getWebService() -> get(array('url' => PS_SHOP_PATH . '/api/stock_availables?schema=blank'));
$resources = $xml -> children() -> children();
$resources->id = $StokId;
$resources->id_product = $ProductId;
$resources->quantity = 10000000;
$resources->id_shop = 1;
$resources->out_of_stock=1;
$resources->depends_on_stock = 0;
$resources->id_product_attribute=$AttributeId;
try {
$opt = array('resource' => 'stock_availables');
$opt['putXml'] = $xml->asXML();
$opt['id'] = $StokId ;
$xml = $this->getWebService()->edit($opt);
}catch (PrestaShopWebserviceException $ex) {
echo "<b>Error al setear la cantidad ->Error : </b>".$ex->getMessage().'<br>';
}
}
function getIdStockAvailableAndSet($ProductId){
global $webService;
$opt['resource'] = 'products';
$opt['id'] = $ProductId;
$xml = $webService->get($opt);
foreach ($xml->product->associations->stock_availables->stock_available as $item) {
//echo "ID: ".$item->id."<br>";
//echo "Id Attribute: ".$item->id_product_attribute."<br>";
set_product_quantity($ProductId, $item->id, $item->id_product_attribute);
}
}
Upvotes: 1