Jump to content

[CLASSE] gestion des prix spécifiques par webservices possible en 1.4.x


Recommended Posts

Salut,

 

Travaillant actuellement sur Prestashop au boulot avec un prestataire, j'ai rencontré quelques obstacles, notamment sur l'alimentation du site par webservices depuis un outil faisant la passerelle entre l'ERP et le site. Le point bloquant était l'alimentation des prix spécifiques par webservices.

Cette fonctionnalité existe dans la v1.5 en cours de développement mais pas dans la 1.4.6.2 utilisée pour le projet.

Et comme j'ai besoin de cette fonctionnalité et qu'on n'est pas prêt de passer à la v1.5 de suite, il fallait bien agir.

 

Et donc, j'ai réussi à le faire. En ajoutant simplement une ligne dans une classe.

La classe en question est WebserviceRequest.php dans le dossier classes.

 

La fonction getResources() ligne 221 contient le listing des méthodes disponibles par webservices et fait référence à des classes mais pas à la classe en question ici : SpecificPrice

 

Il suffit en fait d'ajouter cette ligne, tant qu'à faire, au bon endroit, ligne 250

 

'specific_prices' => array('description' => 'Specific Prices', 'class' => 'SpecificPrice'),

 

ce qui donne ensuite ceci dans le fichier :

...
'products' => array('description' => 'The products','class' => 'Product'),
'specific_prices' => array('description' => 'Specific Prices', 'class' => 'SpecificPrice'),
'states' => array('description' => 'The available states of countries','class' => 'State'),
...

 

Et le tour est joué. Les prix spécifiques apparaissent dans le back office au niveau de la gestion des accès à l'API.

 

Reste juste un petit hic.

Lors d'un GET, les valeurs restées par défaut, à zéro dans la base de données, du genre id_shop, id_country ... ne sont pas renvoyées à zéro dans l'xml reçu mais à vide.

Hors ces champs sont obligatoires.

Il suffit donc de les repousser à zéro par POST ou PUT.

Ne pas oublier, par POST, donc pour créer, de retirer la balise id.

 

Au passage, la passerelle dont j'ai parlé au début de ce message est codée par mes soins en RubyOnRails et utilise deux librairies "gems" bien sympas :

RestClient pour les appels à l'API

CobraVsMongoose pour les transformations xml vers hash ou hash vers xml

avec toutefois quelques trucs et astuces pour le bon fonctionnement de l'ensemble mais qui ne fera pas l'objet de ce post.

 

A bientôt peut-être pour de nouvelles astuces.

  • Like 1
Link to comment
Share on other sites

Pour compléter.

Pour retrouver un ou des prix spécifiques liés à un produit et connaissant l'id du produit (=1 dans mon exemple)

 

- On commence par un GET : http://maboutique/ap..._prices/?filter[id_product]=[1]&display=full

- On récupère un xml mais ce n'est pas celui qu'il faut repousser si je veux mettre à jour mes prix

Exemple d'xml reçu :

<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<specific_prices>
<specific_price>
<id><![CDATA[1]]></id>
<id_product><![CDATA[1]]></id_product>
<id_shop></id_shop>
<id_country></id_country>
<id_group></id_group>
<price><![CDATA[15.000000]]></price>
<from_quantity><![CDATA[1]]></from_quantity>
<reduction><![CDATA[5.99]]></reduction>
<reduction_type><![CDATA[amount]]></reduction_type>
<from><![CDATA[0000-00-00 00:00:00]]></from>
<to><![CDATA[0000-00-00 00:00:00]]></to>
<id_currency><![CDATA[1]]></id_currency>
</specific_price>
</specific_prices>
</prestashop>

 

 

On remarque là que même si je n'ai qu'un seul prix spécifique, celui-ci est encadré par les balises specific_prices

 

- Je recommence mais sans le paramètre display=full

<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<specific_prices>
<specific_price id="1" xlink:href="http://maboutique/api/specific_prices/1"/>
</specific_prices>
</prestashop>

Et j'obtiens la ou les urls de chaque prix spécifique que je peux appeler : http://maboutique/ap...ecific_prices/1

 

- Je boucle donc sur la balise specific_prices pour obtenir mes "specific_price"

- Puis un GET sur chaque url : http://maboutique/ap...ecific_prices/1

<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<specific_price>
<id><![CDATA[1]]></id>
<id_product><![CDATA[1]]></id_product>
<id_shop></id_shop>
<id_country></id_country>
<id_group></id_group>
<price><![CDATA[15.000000]]></price>
<from_quantity><![CDATA[1]]></from_quantity>
<reduction><![CDATA[5.99]]></reduction>
<reduction_type><![CDATA[amount]]></reduction_type>
<from><![CDATA[0000-00-00 00:00:00]]></from>
<to><![CDATA[0000-00-00 00:00:00]]></to>
<id_currency><![CDATA[1]]></id_currency>
</specific_price>
</prestashop>

A noter les champs vides id_shop,id_country et id_group (à zéro "0" dans la base de données = valeur par défaut)

 

Et voilà, c'est ça que je reprend pour faire la mise à jour en ayant au préalable modifié ce qu'il y a à modifier...

Et je refais un PUT

Dans le cas d'une création, je fais un POST sans la balise id et en précisant tous les autres champs comme il se doit.

 

Notamment, id_product et aussi remettre à 0 les champs vides id_shop,id_country, id_group dans mon cas.

<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<specific_price>
<id>1</id>
<id_product>1</id_product>
<id_shop>0></id_shop>
<id_country>0</id_country>
<id_group>0</id_group>
<price>16.000000</price>
<from_quantity>1</from_quantity>
<reduction>4.99</reduction>
<reduction_type>amount</reduction_type>
<from>0000-00-00 00:00:00</from>
<to>0000-00-00 00:00:00</to>
<id_currency>1</id_currency>
</specific_price>
</prestashop>

 

A noter également, dans mon cas, les CDATA ne sont pas réutilisés pour repousser l'information.

L'outil que j'utilise ne les génère pas.

 

J'utilise aussi pour tester mes web-services le plugin POSTMAN du navigateur Google Chrome. Très pratique.

Et j'ai activé les logs sur prestashop dans le fichier config/config.inc.php

/* Debug only */
@ini_set('display_errors', 'on');
define('_PS_DEBUG_SQL_', true);

 

Ce qui parfois me renvoie des informations très utile pour le débogage de mon application et des appels aux web-services.

 

Exemple de retour d'erreur : je m'étais trompé dans l'assignation d'une valeur à un champ

<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<errors>
<error>
<code><![CDATA[85]]></code>
<message><![CDATA[Validation error: "SpecificPrice -> to = amount"]]></message>
</error>
</errors>
</prestashop>

 

Autre point. Lors de la création par POST, si création réussie. Prestashop renvoit l'xml de l'item créé avec son nouvel id.

Très pratique aussi pour enregistrer ce nouvel id si besoin.

 

A+

Edited by patfrat (see edit history)
Link to comment
Share on other sites

Pour info toujours.

Il se peut qu'en modifiant le fichier classes/WebserviceRequest.php, rien ne se passe au niveau de la gestion des web-services.

Ce qui a été mon cas, car le fichier utilisé à la place est placé dans override/classes/WebserviceRequest.php

Link to comment
Share on other sites

Attention ! Pour le moment, je gère parfaitement bien les prix spécifiques par webservices en version 1.4.6.2 ou 1.4.8.2 mais ...

Oui, il y a un mais ... lors de l'appel de la commande par webservice (Order), le prix du produit affiché est faux.

Le prix est le prix spécifique sans la réduction ... en version 1.5, par contre, c'est le prix HT après réduction qui est envoyé.

Et c'est ce prix HT après réduction qu'il faut justement pour une intégration dans un ERP par exemple.

Prix HT réel sous le lequel le produit a été vendu dans la commande !

dès que j'ai une solution, je poste ici !

Link to comment
Share on other sites

  • 4 weeks later...

@Patfrat : Merci pour les info, j'avais justement ça à faire pour mon boulot. Je travaille actuellement en python. Je fait tout en XMLRPC et avec la lib prestapyt et j'envoie tout en dictionnaire(la lib prestapyt converti par la suite le dict en xml..). Si tu veux des infos sur le web service de presta, je poste de temps en temps sur mon blog (http://blog.thomasfossoul.be/categorie/prestashop-2 ...

 

Bav

Link to comment
Share on other sites

@ftom : de rien. Ayant rencontré et résolu "en partie" ce besoin, j'en fais profiter les autres... Bon là, y'a toujours ce problème de prix remonté ensuite dans les commandes par web services qui ne colle pas ! Mystère ....

Link to comment
Share on other sites

Mmm, je vais aussi devoir récupérer les Orders. Pour l'instant, j'ai push les produits avec les prix spécifiques(en fonction de tel ou tel client). Je n'ai pas encore joué avec les discount mais je devrais aussi m'amuser avec ça... Moi je réalise une synchro avec openerp au cas ou :)

Link to comment
Share on other sites

  • 2 weeks later...

Hello .... du nouveau au retour de mes vacances et de bonnes nouvelles.

Le problème du prix pas bon reçu par web-services a été résolu par un consultant Prestashop qui bosse sur mon projet.

Je me permet, pour le remercier, de citer son url : www.nobsod.fr

 

Et donc voici la solution trouver par nobsod :

 

Pour information, la solution se trouvait dans la fonction "getWsOrderRows()" de la classe "Order". J'ai donc surchargé cette fonction, afin de recalculer les prix des produits, en fonction de la remise appliquée. Ci-joint la fonction modifiée.

 

public function getWsOrderRows()
{
/****Modification de la requête pour récupérer plus de champs****/
/*$query = 'SELECT id_order_detail as `id`, `product_id`, `product_price`, `id_order`, `product_attribute_id`, `product_quantity`, `product_name`
FROM `'._DB_PREFIX_.'order_detail`
WHERE id_order = '.(int)$this->id;*/
$query = 'SELECT id_order_detail as `id`, `product_id`, `product_price`, `id_order`, `product_attribute_id`, `product_quantity`, `product_name`, `reduction_percent`, `reduction_amount`, `tax_rate`
FROM `'._DB_PREFIX_.'order_detail`
WHERE id_order = '.(int)$this->id;
/*******************************************/

$result = Db::getInstance()->executeS($query);

/****On parcours chaque produit de la commande, afin de voir s'il bénificie d'une remise, et on met à jour le prix le cas échéant****/
for($iDetail=0 ; $iDetail < count($result) ; $iDetail++){
 $tempFinalPriceHT = $result[$iDetail]['product_price'];
 if ($result[$iDetail]['reduction_amount'] > 0 || $result[$iDetail]['reduction_percent'] > 0){
  ##Récupération du prix initial
  $price = $result[$iDetail]['product_price'];

  ##Initialisation de la réduction, de type "montant"
  $reduction_type = 'amount';
  $reduction = $result[$iDetail]['reduction_amount'];

  ##Si la réduction est plutôt de type "pourcentage"
  if($result[$iDetail]['reduction_percent'] > 0){
$reduction_type = 'percentage';
$reduction = $result[$iDetail]['reduction_percent']  / 100.0; // CORRECTIF pour application correct du pourcentage
  }

  ##Calcul du prix final HT
  $tempFinalPriceHT = ($reduction_type == 'amount') ? ($price - $reduction / (1 + $result[$iDetail]['tax_rate'] / 100)) : ($price - $price * $reduction);

  ##Mise à jour du prix
  $tempFinalPrice = Tools::ps_round($tempFinalPriceHT, 2);
  $result[$iDetail]['product_price'] = $tempFinalPrice;
 }
}
/******************************************************************/

return $result;
}

 

Et c'est résolu ! Merci Nobsod !!!!

Edited by patfrat (see edit history)
Link to comment
Share on other sites

  • 3 weeks later...

Ha la la, sympa le nouveau bug que j'ai eu sur mon prestashop avec mes web-services.

J'explique.

Je gère les produits, stocks et commandes par web-services en lien avec notre ERP.

Et là, chose bizarre, je me retrouvais avec des produits dont le tarifs augmentaient jours après jours et d'autres dont le prix HT était égal au prix TTC.

Tout ça parce que je mets à jour mes stocks tous les jours de la manière suivante :

 

1. j'appelle le produit par web-service sur prestashop

 

2. le fichier reçu, je le modifie sur la quantité pour mettre à jour le stock

Je retire les champs qu'il faut, à savoir :

- id_default_image

- id_default_combination

- position_in_category

- manufacturer_name

- associations => cela aussi parce que ça me faisait sauté toutes les caractéristiques produits sinon ?!?

 

3. je repousse le fichier mis à jour sur quantity

 

Et bien, il faut savoir que le fichier reçu contient le prix TTC et lorsqu'on repousse, le prix donc TTC est considéré comme prix HT !

 

Dans mon cas, sur des produits avec prix spécifiques, pour en revenir à mon post, pas de soucis sur le frontend, le prix spécifique faisait son oeuvre ainsi que dans les commandes. Hors dans le backend se retrouvait toujours le prix TTC spécifique dans le champs prix HT.

Pour mes produits sans prix spécifique, je prenais donc mon prix TTC que je repoussai tous les jours en prix HT sans le savoir ...

donc une augmentation de tarifs journaliers de 19.6% !!!!!!!!!!!!

 

Je vais finir par écrire une doc sur les web-services prestashop 1.4 si ça continue ^_^

 

donc problème résolu en repoussant le stock + le prix HT quand je mets à jour mon stock ! voilà !

Link to comment
Share on other sites

  • 2 weeks later...

Salut,

 

Moi j'ai un nouveau problème, je récupère pour l'instant toues mes orders, mais je voudrai ne récupèrer que les dernières(les plus récentes) car lorsqu'il y aura plus de 1000 commandes, ça deviendra ingérable...

 

J'ai tenté un filter sur la "date_upd" et sur l'état de la commande self.prestashop.get('orders', options={'display':'full','filter[current_state]':'[15]'}) (en pensant rechanger l'état après les avoirs traitées), mais ça me dit que je ne peut pas faire ce genre de filtre.. Une idée ?

Link to comment
Share on other sites

Moi j'ai un nouveau problème, je récupère pour l'instant toues mes orders, mais je voudrai ne récupèrer que les dernières(les plus récentes) car lorsqu'il y aura plus de 1000 commandes, ça deviendra ingérable...

... Une idée ?

 

Oui, j'ai anticipé sur ce problème dès le départ. C'est assez simple.

Il suffit d'interroger le web-service de la sorte : filter[valid]=[1]

mais pour le moment, ça me remonte aussi les commandes livrées ...

Ce statut valide ou non peut se gérer dans le backoffice sur les statuts des commandes.

après, je ne sais pas si on peut rendre, via une surcharge de code, le current_status filtrable ou pas

Et je ne sais pas si mettre les commandes livrées en "non valide" poserai un problème ou pas !

A essayer.

Link to comment
Share on other sites

Voila ce que j'ai fait :

 

On récupère les 10 dernières commandes, on vérifie si elle n'ont pas déjà étés traitée(pas déjà dans la bdd?), si pas, on re-récupère les 10 dernières suivante, si oui, on stop... Ca marche nickel. Mais ca aurait été plus beau de récupèrer celle en status : nouveau puis de modifier leur statuts en nouveau2 ou quoi.. mais bon...

 

Tu travaille sur quel erp ?

Link to comment
Share on other sites

@ftom

Je récupère mes commandes dans une base de données tampon sous mysql dans laquelle je gère des flags du genre récupérée le et poussée le ... poussée dans une table temporaire de l'ERP qui date un peu (JDEdwards des années 90)

J'utilise un ETL (Talend pour pas le nommer) pour faire çà

Link to comment
Share on other sites

  • 2 weeks later...

pour récuperer les zorder en fonction de la date, j'utilise ça :

$url = $site->getUrlWebservice() . '/api/orders/?display=full&date=1&filter[date_upd]=' . urlencode('>[' . $lastUpdate->format('Y-m-d H:i:s') . ']') . '&filter[valid]=1';

 

ça marche..

Link to comment
Share on other sites

  • 3 weeks later...

@greenled, j'ai testé sur filter[date_upd] ou filter[date_add] et ça ne filtre pas.

J'ai vu également que si on ne mets pas date=1, ça plante, pourquoi ?

 

voilà par exemple ce que j'ai testé

api/orders?filter[valid]=1&filter[date_add]='>[2012-10-10%2019:02:13]'&date=1&display=full

 

et non ...

Link to comment
Share on other sites

Je reviens aussi un peu sur mon post de départ.

J'ai un phénomène bizarre.

Lorsque je poste un prix spécifique, je dois calculer le montant de réduction en TTC.

hors j'ai un autre module, pour faire les ventes flash, qui me demandent une réduction en HT mais dans lequel je dois aussi pousser le montant en TTC sinon le prix final est faux ...

Quel est le vrai comportement des prix spécifiques ? mettre la réduction en HT ou en TTC ?

Edited by patfrat (see edit history)
Link to comment
Share on other sites

  • 3 weeks later...

Pour filtrer sur la date, c'est OK ...

J'ai juste modifié çà comme ceci :

date_upd en date _add et j'ai dû encoder aussi le signe > en %3E

ça roule !

 

api/orders/?display=full&date=1&filter[date_add]=%3E[2012-10-08+18%3A32%3A00]&filter[valid]=1

Link to comment
Share on other sites

  • 2 months later...

toujours dans les web-services ... version de prestashop 1.4.6.2 ...

Je n'arrive pas à associer mes tags au produit !

bien que l'XML envoyé contient les associations tags tag id etc ... avec les bonnes valeurs et que mes tags sont présents dans la base de données ... ben, rien.

Alors j'ai vu que ce bug aurait peut-être été corrigé en 1.4.8.0 ou 1.4.9.0 ? ou pas ?

Pas clair ....

http://forge.prestashop.com/browse/PSCFI-4086

 

Ou qu'on pourrait créer des tags associés aux produits comme on le fait avec les images api/images/products/[id]/ ...

On aurait donc un api/tags/products/[id]/ ... ?

 

Quelqu'un peut m'aider ?

Link to comment
Share on other sites

finalement, je me réponds à moi-même ...

En version 1.4.6.2 de prestashop, il manque des bouts de codes.

J'ai ajouté dans override/classes/Product.php que j'ai déjà la fonction suivante trouvée dans un prestashop 1.4.10

Et ça marche ...

 

public function setWsTags($tags)
{
 Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.'product_tag` WHERE `id_product` = '.(int)($this->id));
 if (count($tags))
 {
	 $query = 'INSERT INTO `'._DB_PREFIX_.'product_tag` (`id_product`, `id_tag`) VALUES';
	 foreach ($tags as $tag)
		 $query .= ' ('.(int)$this->id.', '.(int)$tag['id'].'),';
	 $query = rtrim($query, ',');
    Db::getInstance()->Execute($query);
   }
   return true;
}

 

Par contre, c'est quand même un peu galère, l'API Prestashop.

Pour créer un produit, il faut :

- créer les features

- créer les tags

- associer features et tags créés précédemment au produit

- envoyer le produit

- créer le prix spécifique (pour faire apparâitre un prix barré)

- pousser les images

- renvoyer le produit en définissant la première image comme étant de couverture ... (pourquoi !)

- etc ....

Fastidieux !

 

Rien que pour les tags, pourquoi ne pas simplement pousser une liste de valeurs séparées par des virgules avec les informations du produits !

 

bon, la plupart du temps, mon outil ne pousse que les informations mises à jour sans les photos qui y sont déjà !

Et je ne me suis pas encore attaqué aux déclinaisons !

Link to comment
Share on other sites

  • 4 months later...

Salut patfrat,

Merci d'avoir posté ta solution pour les prix erroné lors de l'export d'une commande ça ma bien servi ;)

 

Toutefois, je ne sais pas si tu as remarqué mais il y a une erreur de calcul lorsque la réduction est en pourcentage.

 

Lorsque c'est une réduction en pourcentage du calcul comme ceci:

 

$tempFinalPriceHT = [...] $price - $price * $reduction;

 

Si je prend un exemple d'un $price à 0.43€ et une $reduction à 20%

 

0.43 - 0.43 * 20 = - 8.17€

 

il manque la division par par 100 du prix, il faut donc remplacer par :

 

##Calcul du prix final HT
$tempFinalPriceHT = ($reduction_type == 'amount') ? ($price - $reduction / (1 + $result[$iDetail]['tax_rate'] / 100)) : ($price - $price * ($reduction/100));

Link to comment
Share on other sites

  • 1 month later...

Salut patfrat,

Merci d'avoir posté ta solution pour les prix erroné lors de l'export d'une commande ça ma bien servi ;)

 

Toutefois, je ne sais pas si tu as remarqué mais il y a une erreur de calcul lorsque la réduction est en pourcentage.

 

Ha si, ça, je l'avais vu et corrigé aussi sur mon site !

Link to comment
Share on other sites

##Calcul du prix final HT
$tempFinalPriceHT = ($reduction_type == 'amount') ? ($price - $reduction / (1 + $result[$iDetail]['tax_rate'] / 100)) : ($price - $price * ($reduction/100));

 

Pour ma part (je viens de corriger sur mon premier bout de code en page 1) j'ai appliqué la correction plus haut

$reduction = $result[$iDetail]['reduction_percent']  / 100.0;

Edited by patfrat (see edit history)
Link to comment
Share on other sites

  • 1 year later...

Bonjour PrestaShop Apprentice,

 

Vous arrivez à synchroniser openrp et PS1.4? moi avec le dernier connecteur de Akretion, j'ai réussi seulemetn avec le PS 1.5.x mais pas avec 14.x!!

 

 

Si vous avez déjà réaliser cela, s'il vous plait aidez-nous!!

 

 

Merci

Cordialment,

Vitasoa

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...