Commandes

Le plugin « commandes » permet de gérer des commandes.

Attention Le plugin ne s’occupe pas de la gestion des paniers, ni des paiements, ni des factures. Pour l’aspect « boutique », voir le post-scriptum.

Ce plugin a été élaboré grâce aux contributions de Matthieu Marcillaud, Rastapopoulos, Yffic, touti, Cyril, et du rédacteur de cet article.

Principe

Le plugin agit sur 2 fronts :
→ d’une part il permet aux utilisateurs de gérer les commandes depuis l’espace privé.
→ d’autre part, il fournit les outils permettants et aux développeurs et aux autres plugins de créer et manipuler des commandes.

Installation et dépendances

Le plugin est repertorié dans le dépôt proposé par défaut : « SPIP-Zone - Plugins ». Aussi, il est installable depuis la page Gestion des plugins, onglet Ajouter des plugins si vous avez activé ce dépôt.

2 dépendances seront installées automatiquement :

  • Saisies
  • API prix : permet de calculer les prix HT et TTC des commandes et de leurs détails.

D’autres plugins sont plus ou moins optionnels, là c’est à vous de voir :

  • Notifications avancées : à installer si on veut bénéficier de l’envoi de notifications par email.
  • Facteur : sans lui, les notifications seront au format texte au lieu d’un joli HTML.
  • Coordonnées : fortement recommandé afin de pouvoir gérer les adresses liées aux commandes (livraison et facturation).
  • Contacts et organisations : peut vous servir à gérer les auteurs/clients des commandes.

Fonctionnement

A l’installation, 2 tables sont créées :

  • La table principale spip_commandes sert à enregistrer les données de base des commandes : l’auteur/client, le numéro de référence, le statut et les dates.
  • La table auxiliaire spip_commandes_details sert à enregistrer les « détails » correspondants aux commandes, c’est à dire tous les éléments à partir desquels on va pouvoir calculer le prix total d’une commande : objets et services commandés, frais annexes, ristournes etc.

En théorie, à chaque commande enregistrée dans la table spip_commandes doit correspondre une ou plusieurs lignes de détails dans la table spip_commandes_details.

La table spip_commandes :
Une commande est un objet éditorial, au même titre que les articles, brèves et cie. Elles ont un auteur (le client), différents statuts et 3 types de dates : date de création, date de paiement & date d’envoi.
La date de création correspond au champ « date », elle est définie à la création de la commande, et n’est pas censée être altérée par la suite.
Le changement d’un statut peut déclencher l’envoi de notifications par email, et la mise à jour de la date s’y rapportant :
→ passer le statut à "payée" met à jour la date de paiement.
→ passer le statut à "envoyée" met à jour la date d’envoi.

composition de la table spip_commandes
id_commande Identifiant unique de la commande
reference Numéro de référence (il ne s’agit pas d’une clé unique).
id_auteur Identifiant de l’auteur/client
statut encours, attente, partiel, paye, envoye, retour_partiel, retour, erreur
date Date de création
date_paiement Date de paiement
date_envoi Date d’envoi
maj Date de la dernière mise à jour

La table spip_commandes_details :
Pour le contenu des commandes, on parle de « détails » : chaque commande est constituée d’une ou plusieurs lignes de détails.
Un détail est tout élément qui participe au prix d’une commande.
On peut distinguer 2 types de détails :

  • Les détails correspondants directement aux objets ou aux services commandés.
  • Les détails « annexes » : il peut s’agir des frais de port, des frais de dossier, des ristournes etc.

Une ligne de détail comprend à minima les champs descriptif et prix_unitaire_ht, le cas échéant complétés par les champs taxe et quantite.
Dans le cas où l’objet commandé est un objet éditorial SPIP, des champs objet et id_objet permettent de l’identifier.

composition de la table spip_commandes_details
id_commandes_detail Identifiant unique du détail (attention au « s » à commandes)
id_commande Identifiant de la commande concernée
descriptif Texte décrivant le détail. S’il s’agit d’un objet éditorial, il peut s’agir de son titre, descriptif ou autre.
quantite Quantité
prix_unitaire_ht Prix Hors Taxe
taxe Taxe (TVA)
statut Statut
objet Type d’objet s’il s’agit d’un objet éditorial
id_objet Identifiant de l’objet s’il s’agit d’un objet éditorial
maj Date de la dernière mise à jour

Exemple des enregistrements en base pour une commande et ses détails

Prenons une commande de 2 objets avec TVA à 20%, comportant des frais de port et une ristourne. Dans la base de donnée, ça nous donne ceci :

1 ligne dans la table spip_commandes

id_commande reference id_auteur statut date date_paiement date_envoi maj
1 xxxxxx 1 encours 2014-05-14 09:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00 2014-05-14 09:00:00

4 lignes dans la table spip_commandes_details

id_commandes

_detail

id_commande descriptif quantite prix

_unitaire_ht

taxe statut objet id_objet maj
1 1 Gibolin 2000 2 8 0.2 produit 1 2014-05-14 09:00:00
2 1 Ripolin 5000 1 12 0.2 produit 2 2014-05-14 09:00:00
3 1 Frais de port 0 4 0 2014-05-14 09:00:00
4 1 Ristourne 0 -2 0 2014-05-14 09:00:00

Boucles et balises

Balises #PRIX et #PRIX_HT

Grâce au plugin API prix, les balises #PRIX et #PRIX_HT permettent d’obtenir automagiquement les prix TTC et HT d’une commande ou d’un de ses détails.

Dans une boucle COMMANDES :

  • #PRIX = somme des prix TTC des détails.
  • #PRIX_HT = somme des prix HT des détails.

Dans une boucle COMMANDES_DETAILS :

  • #PRIX = #QUANTITE * (#PRIX_UNITAIRE_HT + (#TAXE * #PRIX_UNITAIRE_HT))
  • #PRIX_HT = #QUANTITE * #PRIX_UNITAIRE_HT.

Boucles

Exemple minimal de boucle affichant pour chaque commande un résumé de ses détails et son prix total TTC :

<BOUCLE_commandes(COMMANDES)>
<h4>Commande N°#ID_COMMANDE</h4>
<ul><BOUCLE_details(COMMANDES_DETAILS){id_commande}>
<li>[(#QUANTITE) *]#DESCRIPTIF = #PRIX</li>
</BOUCLE_details></ul>
Prix total TTC : #PRIX
</BOUCLE_commandes>

Gestion dans l’espace privé

Configuration
La page de configuration est accessible depuis le menu Configuration > Commandes
On peut y gérer les 3 points suivants :

  • La durée d’expiration des commandes ayant le statut « en cours ». On considère que les commandes restant « en cours » pendant plus d’un certain temps sont des commandes abandonnées : il est inutile de les conserver dans la base.
  • l’activation et le fonctionnement des notifications (cf. plus bas).
  • L’affichage en page d’accueil de la liste des commandes « actives » (cf. plus bas).

Liste des commandes
Une page Commandes est accessible depuis le menu Edition.
L’encart à gauche sert à filtrer les commandes en fonction de leurs états, de leurs dates de création, et des auteurs/clients.
Au niveau de la liste, les commandes ayant le statut « envoyé » sont surlignées en vert, afin de repérer facilement les commandes terminées.

Page de gestion des commandes

Fiche d’une commande
La fiche d’une commande est composé de 3 parties :

  • Le contenu de la commande : il s’agit d’un tableau listant les détails de la commande.
  • Les adresses : si le plugin Coordonnées est installé, sont affichées les adresses associées à la commande, ou à défaut celles associées à l’auteur de la commande.
  • L’auteur/client de la commande : si le plugin Contacts et Organisations est installé, on affiche les infos du contact, sinon des infos sur le client.

A noter : Pour les adresses, il n’est pas nécessaire d’activer l’ajout de coordonnées aux commandes dans les options du plugin Coordonnées.

Fiche d’une commande

Commandes « actives »
Il est possible d’afficher en page d’accueil la liste des commandes « actives ». il s’agit des commandes nécessitant une prise en charge. Pour se faire, il faut activer l’option dans la configuration du plugin, et choisir les statuts correspondants.

Commandes « actives » en page d’accueil

Notifications

Mise en place
On peut activer ’envoi d’emails de notification au vendeur et au client lorsque les commandes acquièrent certains statuts.
Le plugin « Notifications avancées » doît être installé. Le plugin Facteur est également fortement recommandé afin d’envoyer les messages au format HTML.
Rendez vous ensuite sur le formulaire de configuration du plugin pour activer et configurer les notifications.

Personnalisation des emails
Par défaut, les messages envoyés sont spartiates :

Email par défaut envoyé au client

Leurs squelettes sont présents dans le répertoire /notifications du plugin.
Pour chaque type de notification (vendeur & client), il y a 3 variantes :

  • commande_xxx_html.html au format HTML.
  • commande_xxx.html au format texte brut.
  • commande_xxx_court.html au format court, type microblog ou SMS.

Par commodité, ces 6 squelettes incluent tous le même squelette mutualisé, avec différents paramètres pour moduler l’affichage : contenu_commande_mail.html.
Il suffit de surcharger ce squelette pour le personnaliser selon vos besoins.

Si vous avez besoin de 2 squelettes vraiment différents pour les emails vendeur et client, vous pouvez au choix :

  • Faire ça au niveau du squelette contenu_commande_mail.html en jouant sur le paramètre #ENV{qui} :
    [(#ENV{qui}|=={client}|oui)<INCLURE{fond=mon_squelette_mail_client, env}>][(#ENV{qui}|=={vendeur}|oui)<INCLURE{fond=mon_squelette_mail_vendeur, env}>]
  • Ou bien surcharger directement les 6 squelettes clients et vendeurs.

Fonctions utiles

Voici une liste non exhaustive de certaines fonctions, celles qui pourront vous être utiles lors de l’intégration du plugin dans votre projet. Pour les détails (paramètres etc.) et la liste complète, voir le site https://code.spip.net/commandes/.

commandes_fonctions.php
commandes_lister_statuts
Cette fonction retourne les différents statuts des commandes. On peut s’en servir comme filtre dans les squelettes pour obtenir la chaîne de langue d’un statut : [(#STATUT|commandes_lister_statut)]
inc/commandes.php
creer_commande_encours
Crée une commande avec le statut « en cours » pour le visiteur actuel. La commande créée est « vide » : la fonction ne se charge pas de créer les détails. C’est le rôle des plugins tiers (Commandes de paniers par ex.).

A noter : on considère qu’il ne peut y avoir qu’une commande « en cours » par session et par auteur. Si une telle commande est déjà présente dans la session, elle va être supprimée de la base et de la session avant la création de la nouvelle.

Exemple :

$creer_commande = charger_fonction('creer_commande_encours', 'inc/');
$id_commande = $creer_commande;
commandes_supprimer
Permet de supprimer « proprement » une ou plusieurs commandes, en s’occupant également des données associées. Pour chaque commande à supprimer, la fonction effectue les actions suivantes :
-  suppression de la commande
-  suppression de ses détails
-  dissociation de ses adresses liées, et éventuellement suppression si elles se retrouvent orphelines.

Exemple :
$ids_commandes = array(1,2,3);
$supprimer_commandes = charger_fonction('commandes_supprimer', 'inc/');
$supprimer_commandes($ids_commandes);
traiter_notifications_commande
Envoie les notifications par email d’une commande, si les conditions sont réunies. Cette fonction est appelée lors de la création d’une commande, puis à chaque changement de statut.
inc/commandes_reference.php
inc_commandes_reference_dist
Cette fonction retourne une référence unique utilisée pour remplir le champ éponyme lors de la création d’une commande. Il s’agit du temps écoulé depuis le 1er janvier 1970, en secondes.
Elle est destinée à être surchargée pour l’adapter à vos besoins.
action/xxx.php
supprimer_commande
Supprime « proprement » une commande. Fait appel à la fonction commandes_effacer, avec les mêmes effets donc.

Exemple :
#URL_ACTION_AUTEUR{supprimer_commande,#ID_COMMANDE,#SELF}
instituer_commande
Change le statut d’une commandes

Exemple :
#URL_ACTION_AUTEUR{instituer_commande,#ID_COMMANDE-envoye,#SELF}

Pour aller plus loin : « Commandes » au sein du framework e-commerce

Ce plugin fait partie d’un framework dédié au e-commerce, il s’interface notamment avec les plugins suivants :

Il n’y a pas encore de documentation qui traite du framework dans son ensemble, on notera cependant les 2 plugins suivants :

  • Tuto commerce » : tutoriel des briques minimales à mettre en place pour une boutique en ligne.
  • Zcommerce : charger les plugins nécessaires à la création d’une boutique en ligne

Pour un aperçu général de tous les outils destinés au e-commerce, voir l’article Inventaire des outils SPIP pour du e-commerce

Discussion

38 discussions

  • 3

    Sur un site 3.2.19 j’ai fait la mise à jour des plugins commandes (de la version 1.15.13 à 1.19.2) et paniers (de la version : 1.4.0 à 1.7.0),

    mais pas de l’API prix toujours en 1.0.0 (vu les ennuis safehtml décrits sur le forum pour les nouvelles versions).

    Je n’ai pas de customisation de fonctions de prix.

    Mais depuis cette mise à jour (avant les prix sont corrects) la balise #PRIX (tout comme #PRIX_HT) arrondit le prix à l’euro supérieur.
    Par exemple, avec une commande avec dans la table commandes_details d’un seul détail d’une quantité 1, sans taxe, de prix HT 19.91 Euros :

    le résultat dans une BOUCLE_commande est :

    #PRIX* affiche 20 ( tout comme #PRIX_HT*)

    Qu’est-ce qui pourrait bien expliquer cet arrondi après mise à jour ?

    Merci !

    • De mémoire il y a eu un bug d’arrondi à un moment dans le plugin, mais ça a été corrigé de longue date. Il faut passer à une version à jour (la v1.0 a 4 ans !).

      Pour l’histoire du safehtml il y a une solution temporaire, c’est dans un ticket, faut que je retrouve lequel.

    • Ah voilà, pour safehtml c’était là : https://git.spip.net/spip-contrib-extensions/intl/pulls/5#issuecomment-34336

      function filtre_montant_formater($montant, $options=[]) {
      	return filtre_montant_formater_dist($montant, array_merge(['markup'=>false], $options));
      }
      
    • Ok, Tcharlss,

      Merci pour tout ! Je vais donc voir avec le nouvel API prix.

      Cheers!

    Répondre à ce message

  • 3

    Bonjour,

    je souhaite créer une page qui liste l’ensemble des objets commandés (qui dans mon cas sont soit des événements gratuits, événements payants, soit des articles) par auteur ayant effectué une commande.

    De sorte qu’on ait un tableau de type :
    Produit 1 a été commandé / auteur 1,2,3
    Produit 2 a été commandé / auteur 3,69
    Produit 3 a été commandé / auteur 4,2,100
    etc.

    Pourriez-vous m’aider ? Me donner des indications ?
    Grand merci.

    • Bonjour,

      La table spip_commandes_details contient toutes les infos sur les objets commandés.
      De tête, cela pourrait se faire de cette façon (non testé, à adapter/corriger au besoin) :

      <ul>
          <BOUCLE_objets(commandes_details) {fusion objet} {fusion id_objet}>
          <li>
              #OBJET #ID_OBJET a été commandé / auteur
              <BOUCLE_auteurs(commandes_details) {objet} {id_objet} {", "}>#ID_AUTEUR</BOUCLE_auteurs>
          </li>
          </BOUCLE_objets>
      </ul>
    • bonjour et merci pour cette explication. Le résultat que me retourne

      <BOUCLE_auteurs(commandes_details) {objet} {id_objet} {", "}>#ID_AUTEUR</BOUCLE_auteurs> 

      est équivalent à celui que me retourne #ID_OBJET dans la boucle précédente :(

    • Cette solution ne fonctionne pas. Pourriez vous me venir en aide ?

    Répondre à ce message

  • 3

    Il y a une modification de CSS semble-t-il depuis SPIP 3 et donc en SPIP 4 la pagination en

    <nav> 

    du bloc Commandes (et Produits aussi d’ailleurs) sur la page d’accueil de l’admin n’est pas
    reconnue :

    Liste articles OK :

    liste-objets.articles nav.pagination

    Liste produits et commande : pas d’équerre, les items de pagination sont empilés à gauche

    .liste-objets.produits ul.pagination
    .liste-objets.liste-commandes p.pagination

    Merci

    Répondre à ce message

  • 2

    Bonjour, j’ai une petite boutique associative et je souhaite améliorer certaines fonctionnalités, notamment la page « commande_panier » dans laquelle je bloque avec le squelette « inc-panier-description-emplette ».
    -  comment afficher des informations supplémentaires sur des objets qui comportent un prix (par exemple la date et le logo de l’article lié à un événement) ?

    -  si l’événement ne dispose pas d’un prix, j’affiche la date à l’aide de cette boucle :

    <BOUCLE_DATE (EVENEMENTS){id_evenement=#ID_OBJET}><div class="small">Date : #DATE_DEBUT </div>
    </BOUCLE_DATE>

    . En revanche, s’il existe un prix, cela ne fonctionne pas.

    -  je n’arrive pas non plus à afficher le logo de l’article lié à l’événement :(

    • Je ne suis pas sûr d’avoir compris grand chose, ni surtout quel est le rapport spécifique avec le plugin Commandes.

    • desole, de ma faute. le fichier dont je parle (inc-panier-description-emplette) fait parti du plugin paniers (il se trouve dans le dossier formulaires). J’aimerais y ajouter des infos (logo de l’evenement ou de l’article lié à l’événement, etc.., mais je n’y arrive pas

    Répondre à ce message

  • 1

    Bonjour,

    Merci pour ce plugin que j’utilise sur quelques sites.

    Savez-vous s’il va passer sur SPIP 4.0.0 ?

    Merci d’avance

    Répondre à ce message

  • 4

    Bonjour,

    Je me permets de vous demander une petite aide.
    Ce plugin rajoute deux types d’adresse dans le plugin coordonnées.
    Je voudrais rajouter dans le plugin coordonnées des types de numeros tel.
    Donc en m’inspirant de votre commandes_pipelines.php, j’ai repris la fonction commandes_types_coordonnees($liste) et adapté suivant

    function commandes_types_coordonnees($liste) {
    
    	$types_coordonnees = $liste['numero'];
    	if (!$types_numeros or !is_array($types_numeros)) $types_numeros = array();
    
    	// on définit les couples types + chaînes de langue à ajouter
    	$types_numeros_awe = array(
    		'phone' => _T('numeros:type_numero_telephone'), 
    		'star' => _T('numeros:type_numero_etoile'),
    		'home' => _T('numeros:type_numero_principal'),
    		'mobile' => _T('numeros:type_numero_cellulaire'),
    		'wheelchair' => _T('numeros:type_numero_handicap'),
    		'tty' => _T('numeros:type_numero_teletype'),
    		'warning' => _T('numeros:type_numero_urgence'),
    		'fire' => _T('numeros:type_numero_accident')
    	);
    	// on les rajoute à la liste des types des numeros
    	$liste['numero'] = array_merge($types_numeros, $types_numeros_awe);
    	return $liste;
    }

    et malgré de multiples corrections, ma fonction n’est pas efficace
    quelle est mon erreur ?

    Merci

    • Bé… copier le nom d’une fonction qui implémente un pipeline alors que c’est pas du tout comme ça qu’on utilise un pipeline ?

      Le plugin Commandes *implémente* le pipeline « types_coordonnees » fourni par le plugin Coordonnées. Donc si tu veux modifier/augmenter aussi il faut de même l’implémenter *de ton côté* donc surtout pas avec le même nom de fonction.

      https://programmer.spip.net/Qu-est-ce-qu-un-pipeline

    • Bonsoir
      J’ai essayé de suivre tes explications, tjs sans résultat, pas d’erreur de mon plugin, mais toujours pas d’ajout de type de numéros,
      Voici les corrections que j’ai cru comprendre suivant ton message, est-ce la bonne voie ?
      Merci

      function numeros_types_coordonnees($liste) {
      
      	$types_num = $liste['numero'];
      	if (!$types_num or !is_array($types_num)) $types_num = array();
      
      	// on définit les couples types + chaînes de langue à ajouter
      	$types_num_awe = array( 
      		'star' => _T('numeros:type_numero_etoile'),
      		'home' => _T('numeros:type_numero_principal'),
      		'mobile' => _T('numeros:type_numero_cellulaire'),
      		'wheelchair' => _T('numeros:type_numero_handicap'),
      		'tty' => _T('numeros:type_numero_teletype'),
      		'warning' => _T('numeros:type_numero_urgence'),
      		'fire' => _T('numeros:type_numero_accident')
      	);
      	// on les rajoute à la liste des types des adresses
      	$liste['numero'] = array_merge($types_num, $types_num_awe);
      	return $liste;
      }

      le paquet.xml

      <paquet
      	prefix="coordonnees_phone"
      	categorie="divers"
      	version="1.0.0"
      	etat="dev"
      	compatibilite="[3.0.5;3.2.*]"
      	logo="prive/themes/spip/images/add-32.png"
      	meta="conphone"
      >
      	<nom>Coordonnees_phone</nom>
      	<auteur lien="http://www.plandecuques.fr">administrateur</auteur>
      	<auteur>Marc</auteur>
      	<credit lien="http://www.plandecuques.fr/">Félicia</credit>
      	<licence lien="http://www.gnu.org/licenses/gpl-3.0.html">GPL 3</licence>
      	<copyright>2021-2022</copyright>
      	<traduire module="coordonnees_phone" reference="fr" gestionnaire="salvatore" />
      	<pipeline nom="types_coordonnees" inclure="numeros_pipelines.php" />
      	<necessite nom="coordonnees" compatibilite="[3.0.7;[" />
      	<chemin path="squelettes" />
      	<chemin path="" />
      </paquet>
    • Bé non t’as pas suivi la doc :)

      Si ton préfixe c’est « truc » par défaut toutes tes pipelines doivent être préfixés par… le préfixe, donc « truc_ », sauf quand on précise un autre nom de fonction dans l’attribut du XML. Du coup je vois pas pourquoi ta fonction s’appelle « numeros_… ». Faut aussi bien penser à passer dans la page d’admin des plugins à chaque fois qu’on change le XML.

    • Merci,
      en effet je n’avais pas bien lu ton document, et donc pas appréhendé le champ prefix du paquet /o\,
      j’ai bien ajouté mes type d’entrée, mais vu la complexité pour gerer install et desinstall, je me suis penché sur le plugin champs-extras qui sera plus compréhensible pour la maintenance.

    Répondre à ce message

  • 7

    Bonjour, uniquement après la validation d’une commande, je souhaiterai faire apparaitre un lien vers une url exterieure au site sur la page d’un objet - commandé par l’utilisateur - (dans mon cas, un evenement). L’idée est que ce lien ne doit apparaitre sur la page de l’objet que lorsqu’un utilisateur a finalisé sa commande. Il manque des arguments dans ma boucle... Et je seche. Pourriez vous m’aider ?

    <B_commandeok><BOUCLE_commandeok(CONDITION){si #SESSION{id_commande}|oui}> <hr> <a href="[(#VISIO_LIEN)]">Se connecter à la visioconférence</a> </BOUCLE_commandeok></B_commandeok>

    • Bonjour,

      Je ne sais pas ce que tu obtiens avec ta boucle.
      Il faut peut être ajouter un critère de statut de la commande comme :
      <BOUCLE_commande(COMMANDES) {id_commande?} {statut IN paye}>
      et id_auteur ? ??

      dd

    • Ça ne peut pas être #SESSION si ton but c’est qu’illes le retrouvent à tout moment plus tard, même après s’être déconnecté et reconnecté.

      Commence par formuler en phrase ce que tu cherches à sortir, il me semble un truc du genre : « s’il y a un utilisateur connecté (auteur) uniquement, est-ce qu’il y a au moins une commande payée par cet utilisateur connecté qui dans ses détails de commande (commandes_details) contient l’objet XXX ».

      Soit tu peux essayer de faire tout dans la même boucle si t’arrives à trouver la bonne jointure, la bonne combinaison à faire. Soit il faut faire plusieurs boucles.

      Du genre (mais là je fais ça de tête à l’arrache)

      <BOUCLE_commande(COMMANDES_DETAILS commandes)
          {objet=evenement}
          {id_objet=#ID_EVENEMENT}
          {commande.id_auteur=#SESSION{id_auteur}}
          {commande.statut=paye}
      >
    • Bonjour, et merci de votre aide. OUI, c’est bien ca. Je souhaite qu’une personne qui s’est inscrite puisse voir le lien. La boucle indiquée n’a pas fonctionnée. J’ai testé ceci sans plus de succès ;(

      <BOUCLE_commande (COMMANDES){objet=evenement}><BOUCLE_commande_detail(COMMANDES_DETAILS){objet=evenement}
          {id_objet=#ID_EVENEMENT}
          {commande.id_auteur=#SESSION{id_auteur}}
          {commande.statut=paye}>[<hr>	<a href="(#VISIO_LIEN)">Se connecter</a>]</BOUCLE_commande_detail></BOUCLE_commande>

      Si vous avez des idées... JE PRENDS !!!
      Merci bcp.

    • RE-Bonjour,

      après un jus de tomate et un 20h rigolo, je me suis dit que j’allais y retourner. Du coup, grace à votre aide, voici une boucle qui semble donner un résultat pas mal :

      <BOUCLE_commandeautre(COMMANDES) {id_commande?}{id_auteur=#SESSION{id_auteur}}{statut IN paye}><BOUCLE_commandeautredetail(COMMANDES_DETAILS){objet=evenement}{id_objet=#ID_EVENEMENT}>[<hr><a href="(#VISIO_LIEN|unique)">Se connecter à la visio</a>]</BOUCLE_commandeautredetail></BOUCLE_commandeautre>

      Qu’en dites vous ? Ca vous semble bien et correct comme boucle ?
      Ce que je souhaite est très bien résumé par RastaPopoulos, à savoir : qu’un lien (champs extra nommé ici visio_lien) ne s’affiche sur la page événement choisie qu’une fois une commande avec le statut « payée » a été effectué par ce même auteur. Les internautes n’ayant pas commandé cet « article » ne voient pas ce bouton. Les internautes non enregistrés ne voient pas non plus ce bouton. Personne ne doit le voir, si ce n’est que les personnes qui ont effectué la commande de ce produit (événement) et qui ont obtenu le statut « payé ».

    • bé si ça marche… c’est bon ? :)

      Mais en fait moi je te dirais que le plus propre ça serait plutôt d’entourer ton lien d’un #AUTORISERvoir_viso, evenement, #ID_EVENEMENT|oui

      Et ensuite tu fais une autorisation en PHP où tu mets ce que tu veux, donc la même chose, aller tester si la personne a payé au moins une fois. Mais on peut très bien imaginer que ça change, et que c’est soit l’avoir payé dans l’année passé, ou tout autre test plus compliqué. Et tout ça sera regroupé dans une autorisation dédiée. C’est mieux rangé, plus propre à maintenir, et tu peux le réutiliser en plusieurs endroits.

      Après le encore mieux, si t’as rien d’autre qui est sessionné dans ce morceau de squelette, le mieux c’est quand même de faire ton test d’autorisation (ou tout ce qui a rapport avec la session de l’utilisateur) pour une fois dans du PHP dans le squelette (c’est en gros le seul cas où c’est ce qui est recommandé).

      Un truc du genre

      <BOUCLE_evenement(EVENEMENTS) {id_evenement}>
      <?php 
      if (autoriser('voir_visio', 'evenement', #ID_EVENEMENT) {
      ?>
      #MONSUPERLIEN
      <?php
      }
      ?>

      Ça fait que le squelette ne sera pas sessionné et n’aura pas un cache compilé différent par visiteur. C’est seulement à l’exécution finale que ça va tester l’autorisation du visiteur.

    • Toujours + ^^.
      Merci de vous intéresser à mes problématiques. Je vais tester avec #AUTORISER. Et puis j’aimerais aussi que #MONSUPERLIEN soit envoyé par email à ceux qui l’ont commandé ! Alors avant j’étais à la ramasse, avec notifications avancées, je suis sous terre ;( Je vous tiens informé :).

    • Bonsoir à vous deux,

      je n’y arrive pas avec #AUTORISER, mais je pense être bien avec la boucle suivante :

      <BOUCLE_recupliensicommande(COMMANDES) {id_commande?}{id_auteur=#SESSION{id_auteur}}{statut IN paye}><BOUCLE_recupliensicommandedetail(COMMANDES_DETAILS){id_commande?}{objet=evenement}{id_objet=#ID_EVENEMENT}> [<hr><a href="(#VISIO_LIEN|unique)">Se connecter à la visioconférence</a>] </BOUCLE_recupliensicommandedetail></BOUCLE_recupliensicommande>

      En revanche, pour faire envoyer mon super lien (#VISIO_LIEN ; champs extra d’un événement) par email une fois la commande validée, je suis bien à la ramasse... Si des exemples existent... Je continu de chercher.

      Merci !

    Répondre à ce message

  • 4

    Bonjour,

    Le mail « Votre commande » reçue par le client reste en français , même si la commande est passée avec une autre langue (notamment l’anglais « en » qui est bien complet) .
    J’ai copié sous squelettes/notifications une version de contenu_commande_mail.html
    pour y voir #LANG et #ENV{lang}: ça reste toujours « fr ».

    Que faudrait-il ajouter pour avoir un mail dans la bonne langue ?

    (spip 3.2.7 , plugin commandes 1.15.13 notifications avancées 0.4.4 )

    Répondre à ce message

  • 7

    Bonjour à tous,

    Dans un(e tentative de dev de) tunnel de commande, j’utilise ce plugin avec un SPIP 3.2, Produits, Déclinaisons prix, Prix objets, Paniers, Coordonnées, Contacts et Organisations, et Livraisons. J’essaie de comprendre comment tout cela s’articule, et vos messages sont d’une grande aide, mais je bloque depuis quelques jours sur le récap de commande. En me rendant dans l’administration des commandes, je m’aperçois que :
    -  la désignation des déclinaisons produits sont bien prises en compte, mais que la colonne « contenu lié » (ou « Objet ») reste vide ; le prix de la commande est cependant bien incrémenté,
    -  le client est bien lié, avec le n° auteur et le n° contact, mais aucune adresse n’est associée à la commande (alors que j’ai bien créé une adresse de facturation obligatoire et éventuellement une adresse de livraison, avec le plugin Profils),
    -  aucun frais de livraison ne sont mentionnés, alors que j’ai paramétré ces frais et renseigné des dimensions et poids d’articles...

    Bien entendu avec tout ça, le formulaire #adresser_commande ne fonctionne pas non plus, bref !

    Un truc m’échappe c’est sûr, est-ce que ce sont des liaisons qu’il manque quelque part, que je ne m’y suis pas pris correctement, mais quoi où comment, ça je n’en ai pas la moindre idée, après avoir pourtant creusé (à hauteur de mon niveau de compréhension), je m’en remets donc à vos lumières... =)

    • Bonjour,

      aucune adresse n’est associée à la commande (alors que j’ai bien créé une adresse de facturation obligatoire et éventuellement une adresse de livraison, avec le plugin Profils),

      Le plugin Commandes ne reconnaît que 2 sources pour les adresses : soit celles liées directement aux commandes si tu as le plugin Coordonnées, soit celles enregistrées directement dans la commande si tu as le plugin Livraison (il ajoute des champs dans la table spip_commandes).

      Hors via le plugin Profils, tu édites les adresses liées à l’auteur SPIP, elles n’ont aucune association avec la commande. Il te faudrait donc les copier puis les associer à la commande par la suite via un pipeline. Mais quand bien même, ça pose d’autres problèmes, je déconseille d’utiliser Profils pour gérer les adresses d’une commande.

      Et surtout dans ton cas il y a la question des frais de livraison : dans ce cas pas le choix, il faut utiliser le formulaire #adresser_commande pour la saisie des adresses, there is no alternative comme dirait l’autre. C’est par le biais de ce formulaire que les frais sont ajoutés ou mis à jour dans la commande.

      Le truc, c’est que pour l’instant Livraison ne prend pas en compte le plugin Coordonnées : il enregistre les adresses directement dans la commande. Mais elles seront bien visibles dans la fiche de la commande dans le privé.

      Donc au final je dirais : retire les adresses de livraison/facturation de la config du profil utilisé dans ton tunnel, puis utilise le formulaire adresser_commande, et le tout sera joué.

      Voilà, sinon je n’utilise pas les plugins Déclinaisons prix et Prix objets, donc je ne peux en dire plus sur ce sujet.

    • Merci tcharlss !!

      Mais ça veut dire que les clients devront re-remplir l’adresse à chaque commande si je comprends bien... ?
      Est-ce qu’il y aurait un moyen d’injecter ou proposer d’injecter ou lier les adresses (et autres coordonnées) de Coordonnées dans les adresses de Livraison (contenues dans la table Commandes) par un pipeline(, et éventuellement inversement) ?
      Dommage de se heurter à cette « incompatibilité », le plugin Coordonnées est top, et Livraison l’est tout autant (comme tous les autres d’ailleurs, et c’est sincère !!!). À moins de faire le choix d’inclure les frais d’expédition dans le prix des produits, mais je trouve que c’est moins transparent vis-à-vis du client.

      Pour essayer de mieux comprendre (et m’y retrouver), j’ai pris le problème dans l’autre sens et ai recommencé une installation à partir d’un SPIP tout neuf avec API Prix, Commandes, Livraison, Paniers, Produits et Banques et Paiements, en me basant sur le squelette de Cerdic shop-draft. Le tunnel de commande est OK pour le moment, me reste « plus qu’à » comprendre comment ça s’articule avec Déclinaisons prix et Prix objets, et si ça peut aider d’autres rookies comme moi je viendrai compléter (vague impression de submersion entre les différents plugins, Tutocommerce (que je recommande pour comprendre le chainage des ACTIONS, mais qui n’éclaire ni sur l’identification du visiteur [1] ni sur l’étape de livraison), Zcommerce — surtout quand on n’utilise pas les squelettes Z ^_^, shop-draft, etc, alors si ça peut être utile à d’autres !).

      Les conseils, recommandations, trucs et astuces sont bien entendu les bienvenus, et je prends aussi toute piste qui permettrait de lier les coordonnées de Coordonnées et celles de Livraison, et tout retour sur un fonctionnement avec les Déclinaisons. Merci ! =D

    • Mais ça veut dire que les clients devront re-remplir l’adresse à chaque commande si je comprends bien... ?

      Le plugin Livraison a prévu ce cas : les adresses sont pré-remplies avec celles de la commande précédente. Pour la 1re commande je ne sais plus s’il y a un fallback, mais en tout cas dès la 2e c’est pré-rempli à coup sûr.

      je prends aussi toute piste qui permettrait de lier les coordonnées de Coordonnées et celles de Livraison =D

      Pour l’instant la seule option c’est de faire un dérivé du formulaire adresser_commande en le basant sur des coordonnées.
      C’est possible hein, mais si tu veux du simple à implémenter et du maintenu, je conseille de garder le fonctionnement du plugin livraison pour l’instant (et donc pas de coordonnées sur les commandes).

      Il n’empêche que c’est une évolution intéressante, surtout depuis que coordonnées sait gérer les bons formats d’adresses pour tous les pays, mais ça demande un peu de réflexion pour faire ça proprement.

      Tutocommerce (que je recommande pour comprendre le chainage des ACTIONS, mais qui n’éclaire ni sur l’identification du visiteur [1] ni sur l’étape de livraison)

      Oui c’est dans la liste des todos de longue date :D

    • La cité idéale ne s’est pas construite en un jour ! =)

      Grand merci pour les conseils ! Je vais effectivement rester sur du

      simple à implémenter et du maintenu

      je crois que ce sera plus sage, et pertinent ^_^

      Au risque d’être hors sujet, concernant l’identification, et histoire d’être sûre : est-ce suffisant juste avec un système de pages du tunnel ou est-il préférable d’inclure ces pages dans des articles d’une zone restreinte pour plus de sécurité ? Tout est tellement imbriqué que je ne sais pas trop où publier...

    • Je ne sais pas si j’ai bien compris la dernière question, mais généralement dans de l’achat, on peut (on doit pouvoir) tout démarrer en anonyme, c’est seulement à l’une des étapes à l’intérieur du tunnel, que là on demande à soit s’inscrire, soit se connecter et vérifier ses infos, et du coup on se retrouve connecté (pour l’inscription : ajouter le plugin « Connexion à l’inscription »). Et du coup une fois un utilisateur sous la main, on peut enfin générer la vraie commande finale (avant c’est juste un panier temporaire).

    • Bonjour RastaPopoulos,

      pour préciser mon interrogation : j’ai cru voir des pages qui comprenaient « de quoi » (je vais pas me lancer dans de grands discours ornithologiques quand je peine à différencier un corbeau d’un moineau, hein) reconnaître un utilisateur connecté, au moins à l’étape de validation de panier, avec l’inclusion à un moment ou à un autre d’un formulaire d’identification (connexion #LOGIN, #LOGIN_PUBLIC ou inscription #FORMULAIRE_INSCRIPTION).

      Mais ces boucles d’autorisation (? moineau ?), pas forcément bien utilisées car non maîtrisées ( :-) ), sont-elles utilisables telles quelles ou suffisantes en terme de sécurité, ou est-il préférable d’intégrer chaque page comportant des informations personnelles (a priori à partir de commande, livraison, puis les éventuelles pages d’un espace perso), dans autant d’articles répertoriés dans une rubrique qu’on appellerait « Espace perso » (par exemple), gérée par Accès restreint (avec effectivement Connexion à l’inscription, Mot de passe dès l’inscription, la gestion de Profils, etc...) ?
      Suis-je en train d’enfoncer une porte ouverte ou est-ce que j’ai raté une marche ou alors suis-je en train de monter une tour de Babel en chantilly ?

    • Non, c’est dans les squelettes ou des différentes étapes de ton tunnel, que tu dois (si l’étape en question en a besoin…) testé si l’utilisateur est connecté ou pas, et lui dire de se connecter ou s’inscrire si ce n’est pas le cas.

      Typiquement pour le panier ce n’est pas le cas, et après le panier tu rediriges généralement vers une étape « Mes informations » qui si connecté affiche le form de profil, mais si pas connecté, ça afficher le form de connexion et celui d’inscription. Etc.

      Avec tcharlss on a commencé un plugin permettant de faciliter la création de tunnel : https://git.spip.net/spip-contrib-extensions/tunnels

    Répondre à ce message

  • 4

    Sur cette page : ?exec=commandes_detail_edit&reference=2019031300....
    lorsque l’on veut créer et valider un détail de commande le champ descriptif est rouge et n’est pas rempli automatiquement même si l’on a indiqué un Type du contenu SPIP et un Identifiant du contenu SPIP
    (dans mon cas produit et son ID)

    Descriptif (obligatoire)
    Peut être laissé vide si l’on indique un contenu SPIP existant. Dans ce cas le titre du contenu sera utilisé automatiquement.
    • Effectivement si le champ peut être rempli automatiquement, il ne devrait pas être obligatoire.

      Après en enlevant l’obligation pour tester, je ne reproduis pas l’erreur que tu indiques : tu as bien rempi les champs « type de contenu SPIP » et « Identifiant du contenu SPIP » et laissé le descriptif vide ?

    • Oui c’est ce que j’ai fait.
      (l’infobulle « veuillez compléter ce champ » est là mais pas visible sur la capture)
      merci

    • C’est corrigé dans la prochaine version qui devrait être disponible au téléchargement bientôt (tout de suite si tu es en svn)

    • Youpi
      Merci

    Répondre à ce message

  • 1

    Bonjour
    J’utilise le plugin panier et lorsque je transforme mon panier en commande dans le cas d’un auteur « non authentifié », j’ai une erreur sql dans action_commandes_paniers_dist ligne 69

    SELECT id_commande
    FROM <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+Z3B0b3VybmFnZTwvY29kZT4="></span>.spip_commandes
    WHERE statut='encours' AND date>'2018-12-10 17:12:00' AND source='panier#29' AND id_commande=
    2018-12-11 17:12:00 127.0.0.1 (pid 1153) :Pub:ERREUR: Erreur mysql 1064

    En effet, cette requête sert à identifié une commande déjà existante lors d’un retour arrière de l’utilisateur :

    	$id_commande = sql_getfetsel("id_commande", "spip_commandes", $w = "statut=" . sql_quote('encours') . " AND date>" . sql_quote(date('Y-m-d H:i:s', strtotime('-' . lire_config('paniers/limite_ephemere', 24) . ' hour'))) . " AND source=" . sql_quote("panier#$id_panier") . " AND id_commande=" . session_get('id_commande'));

    et session_get('id_commande') est vide

    • Je me répond : J’ai mis en place une procédure d’inscription automatique et d’authentification avant de pouvoir traiter une commande. C’est en effet impossible de traiter une commande juste avec un auteur non connu en base.

    Répondre à ce message

  • 1

    Bonjour,

    J’utilise le plugin Panier et je souhaite ajouter au panier le prix du champ #PRIXPROMO au lieu du champ #PRIX.

    J’ai essayé de remplacer #PRIX par #PRIXPROMO dans panier.html mais sans succès.

    Avez-vous déjà mis en place le panier avec un autre champ que #PRIX comme dans mon cas ?

    -  Liste de produits avec possibilité ajout panier : https://www.dufresne.pro/-Jardinage-.html
    -  Produit : https://www.dufresne.pro/Serre-aluminim-ACD-4-8m%C2%B2-135.html
    -  Panier : https://www.dufresne.pro/panier.html

    Merci.

    Gil

    • Si t’as des trucs perso, c’est plutôt avec l’API du plugin Prix qu’il faut voir. En surchargeant ou en définissant la fonction de prix de tel ou tel objet que tu veux, et en allant chercher le bon champ (vu que par défaut ça prend prix et prix_ht).

    Répondre à ce message

  • 2

    Bonjour,
    J’ai installé les plugins nécessaires au e-commerce et j’essaie d’utiliser le plugin Tuto commerce. Bien que tout soit correctement paramétré cela refuse de m’afficher la page 1re étape (produits). J’obtiens une page blanche !!! La table produits démos est bien installée. Il n’y a aucune documentation ni lien permettant de contacter les développeurs de tuto commerce. Comment s’y prendre ?
    Merci.
    Yann

    • Bonjour, difficile de d’aider sans voir le site. Dans la config du plugin Produits a-tu coché : Publier les rubriques qui contiennent des produits publiés ?

    • Bonjour,

      Active le report des erreurs en ajoutant ces lignes dans ton fichier mes_options.php, ça indiquera l’origine du problème :

      error_reporting(E_ALL);
      @ini_set('display_errors', 'On');

      Le plugin est lui-même une forme de tutoriel/documentation, c’est pourquoi un article me semblait redondant. Mais cela dit ça permettrait de faire des retours et ça lui donnerait un peu de visibilité, je vais y réfléchir.

      Je n’ai pas eu beaucoup de temps de dispo pour le maintenir non plus, et ça a pas mal bougé depuis dans commandes/bank/produits, possible qu’il y ait des indications devenues obsolètes ou des choses qui ne fonctionnent plus.

    Répondre à ce message

  • 2

    Bonjour,

    J’utilise le plugin commande pour mon dernier site avec boutique en ligne et c’est très pratique. Bravo pour votre travail de développement. Cependant, il y a un détail que je ne trouve nulle part dans la documentation...
    J’aimerai personnaliser et éditer le modèle de facture proposé dans l’espace privé à > Activité > Commandes. Je voudrai pouvoir y ajouter le logo du site, l’adresse, le SIRET etc, mais ne comprends pas du tout où... J’ai sur l’aperçu de la commande :

    « Votre nom

    Adresse complete
    de la structure
    XXXXX VILLE

    01 23 45 67 89
    06 23 56 78 89

    Siret : 33 100000000000
    TVA : 33 100000000000 »

    que j’aimerai pouvoir éditer avec les informations relatives au site.
    Il n’y a pas non plus de marge sur la page... il me faudrait toucher au CSS.

    Merci pour votre aide.

    • Il ne faut pas utiliser les factures du plugin Commandes en fait, ça date d’avant, il faudrait les retirer complètement. Ça ne suit pas les obligations légales, notamment qu’une facture éditée ne peut plus du tout être modifié après coup (on peut juste l’annuler mais pas la modifier).

      Il faut utiliser le plugin Factures, fait par Nursit comme le plugin Bank.
      https://github.com/nursit/factures/

    • Merci RastaPopoulos pour cette réponse.
      Je vais donc télécharger le plugin de Nursit. Il fonctionne bien avec SPIP 3.1 j’imagine...
      Bonne soirée.

    Répondre à ce message

  • 3

    Hello,

    J’ai mis la durée de conservation des commandes en cours à 24h e là j’en vois une qui date du 29 mars toujours notée en cours sur la page ?exec=commandes.
    Est-ce normal ?
    Merci

    • Tu as le plugin Corbeille ? Ou tu as des visites qui permettent de lancer les génies et tâches récurrentes ?

      Parce que c’est fait dans le pipeline « optimiser_base_disparus », qui est lancé dans un génie. Et qui aussi est désactivé entièrement par Corbeille.

      https://zone.spip.org/trac/spip-zone/browser/_plugins_/commandes/trunk/commandes_pipelines.php#L30

    • Ah oui effectivement j’ai le plugin Corbeille. je l’ai désactivé et en lançant le cron c’est bien effacé merci.
      Les commandes en cours trop anciennes ne devraient-elles pas passer dans la corbeille justement ?
      dd

    • Faut l’implémenter… Il y a plein (PLEIN) d’objets de plugins qui n’implémentent pas le plugin Corbeille.

      Enfin le vraiment mieux, ça serait de se coller enfin à refaire ce pas mal vieux plugin, pour qu’il fonctionnement automatiquement sur tous les objets, sans rien avoir à implémenter. Mais ya un peu de boulot… :)

    Répondre à ce message

  • 2

    Bonjour,
    Je bloque sur un truc qui devrait être pourtant hyper simple. Mais je ne m’en sors pas, je m’énerve et je préfère solliciter vos lumières.

    je suis entrain de créer une mini interface d’admin hors espace privé. Je veux faire un recap de commande, jusque là tout roule. mais je bloque pour afficher les données de l’auteur de la commande en question. Je ressort toujours les données de l’admin qui est connecté. Voici mon bout de code foireux :

    <BOUCLE_si_admin(AUTEURS){id_auteur=#SESSION{id_auteur}}{statut=0minirezo}>
    
    <BOUCLE_commandes(COMMANDES) {id_commande}>
    <h1>COMMANDE #REFERENCE</h1>
    
    <BOUCLE_details(COMMANDES_DETAILS){id_commande}>
    	 [(#DESCRIPTIF)]
        </BOUCLE_details> 
    <li>[<strong>Commande passée le :</strong> (#DATE|affdate{'d/m/Y'})]</li>
    <li><strong>Prix de la commande :</strong>#PRIX</li>
    
    <BOUCLE_client2(AUTEURS)  {id_auteur=#ID_AUTEUR}>
    
    <h2>Informations client</h2>
    <li>#NOM </li>
    <li> #ADRESSE  #CODE_POSTAL  #VILLE </li>
    <li>#EMAIL</li>
    <li>Identifiant client : #ID_AUTEUR</li>
    
    </BOUCLE_client2>
        </BOUCLE_commandes>
    
    	
    </BOUCLE_si_admin>

    Mon soucis concerne donc cette boucle <BOUCLE_client2(AUTEURS)  {id_auteur=#ID_AUTEUR}>
    qui ne ressort pas les données de l’auteur lié à la commande

    • T’es dans une boucle AUTEURS où t’as sélectionné le visiteur connecté en cours… donc bah non, ton #ID_AUTEUR c’est celui là, que tu viens de sélectionné juste avant…

    • Oups j’avais oublié de supprimer ce message. Je m’en suis sorti.
      J’ai ajouté tout à la boucle commande et ça marche comme voulu.
      Merci

    Répondre à ce message

  • Bonjour. ça faisait longtemps que je ne vous avais pas embêté.
    J’ai mis en place un système de commande basique en fonction d’objets liés aux articles. En gros un objet correspond à un nombre de jours de réservation.

    J’ai besoin de pouvoir passer des dates dans ma commande pour la période de réservation de l’objet.

    Ma contrainte est que lors d’une commande je dois commencer par les dates. Jusque là tout est okay, je fais passer mes dates dans la session, tout roule.

    J’ai créé dans « commande », 2 champs extras : date arrivée et date retour

    Je souhaiterais donc savoir comment je peux remplir ces deux champs extras (dans la BDD) lors de la validation de ma commande.

    Merci

    Répondre à ce message

  • 11

    Bonjour
    J’ai une dernière petite question afin de terminer le site sur lequel je bosse.
    Pour en arriver en temps voulu à gérer mes besoins j’ai codé le paiement via paypal mais donc surtout la gestion de l’IPN et la modification de statut + changement de date sur ma commande "payée’ dans la table spip_commandes

    Là où je bloque c’est que j’aimerai que la notification s’enclenche avec le passage du statut payé. Mais je ne vois pas vraiment ce qu’il me manque. Dois je incrémenter une autre base, faire un cron sur un fichier ?? Il me manque quelque chose.

    Merci

    • Alors déjà le paiement Paypal et plein d’autres sont déjà implémentés dans le plugin Bank qui gère et centralise tous les prestataires de paiements, et qui est très maintenu et très sécurisé. Je te conseille immensément fortement de l’utiliser plutôt que de maintenir toi-même un truc dans ton coin, surtout pour un truc aussi critique en sécurité que le paiement. Avec le plugin Factures qui va avec aussi (chaque transaction du plugin Bank génère une facture du plugin Facture).
      https://plugins.spip.net/bank.html
      https://github.com/nursit/factures/

      Ensuite les notifications sont déjà implémentées et configurables pour les commandes, pour ça il faut avoir le plugin « Notifications avancées » : c’est marqué dans la doc juste au dessus.

    • Merci pour ta réponse. En fait j’étais parti sur bank mais il me semblait qu’il n’était pas cablé avec Commandes du coup je suis passé au plugin Paypal mais « commandes paypal » n’était lus compatible 3.2 et je n’ai pas pou savoir si le version du plugin Paypal pouvait gérér la relation avec la commande. Bref j’ai tourné en rond, une autre personne m’a conseillé le plugin bank mais il m’était plus simple de m’en sortir dans les temps de la sorte.

      Je sais que commandes gère bien les notifications et j’utilise déjà cette fonction. C’est juste que du coup vu que j’ai codé un bout de code pour mettre à jour mon statut de commande à payé après validation de l’IPN (ce sont deux lignes de codes, juste un update de la base), mais ndu coup ce qui me manque c’est de savoir comment est censé s’enclencher la notification.

      Je sais que le type de question que je pose doit être chiant pour les devs mais il faut reconnaitre que la pluginisation du système de commande, bien que tip top à mon goût, manque un poil de doc et qu’avec les évolutions tout n’est pas toujours à jour.

      En l’occurrence bien qu’on me conseille fortement le plugin bank je ne suis pas certain qu’il gère derrière la relation avec le plugin commandes notamment.

    • +1 pour le plugin Bank.

      Pour les notifs qui ne se lancent pas, ça dépend de comment tu changes le statut de la commande dans ton code. Les notifications se lancent via commande_instituer(), donc si tu ne l’utilises pas directement ou via l’API (avec objet_instituer), pas de chocolat.

    • Merci, c’est exactement ce qu’il me fallait

    • Mais kek tu racontes. :D

      C’est le plugin Commandes qui gère le plugin Bank, et cela depuis des années. Ya strictement rien à faire. Quand une transaction de Bank est bien payée, ça met la commande liée en payée pareil, ça fait super longtemps et ça a toujours très bien marché.

      Pour les notifications je ne comprends pas non plus, il y a un panneau de config, on dit qu’on veut une notif lors de tels statuts, donc bah tu coches que tu veux le statut « payé » aussi et ça enverra une notif si ça passe en payé, ya rien à faire en tant que dev ou intégrateur pour ça donc pas spécialement de doc, c’est un panneau de config avec les cases à cocher des statuts.

    • Ah oui ok… Bien vu tcharlss… Si tu fais pas la modif avec les API officielles mais directement en changeant la base, ça va pas lancer les choses automatiques oui. (Mais bon Commandes avec Bank le fait déjà bien comme il faut justement !)

    • C’est vrai qu’il manque un peu de doc pour les interactions entre les différents plugins de commerce. Commandes et Bank sont bien intégrés ensembles : tu donnes le numéro de la commande dans #PAYER_ACTE et tout se fait automatiquement (notifs, retour IPN pour paypal etc.).

      Il y a un début de doc sous la forme d’un plugin : https://plugins.spip.net/tutocommerce.html

    • Je lisais juste plus haut dans le PS dela Doc
      « Le plugin Bank offre quant à lui tout un panel d’options de paiements, mais n’est pas (encore) interfacé avec le plugin Commandes. » ce qui m’avait forcément mis le doute

    • Ah oui, la doc n’est plus à jour sur ce point là.
      On va s’en occuper, merci pour le signalement.

    • Merci à vous surtout pour le super travail que vous faites et votre disponibilité.

    • Hop, P.-S. mis à jour

    Répondre à ce message

  • 2

    Bonjour
    Pouvez vous me confirmer que « Commandes de paniers » n’est plus utilisable avec la V 3.2 ?

    Répondre à ce message

  • Patrick ROUDEIX

    Je souhaite utiliser ce plugin pour gérer des abonnements annuels sur mon site www.mondoral.org mais j’aurai besoin d’adaptations, comment vous joindre ?

    Tels : 04 9272 8000 ou 06 8151 0663

    Répondre à ce message

  • 4

    Bonjour,

    Je viens d’installer tous ces plugins sur un site 3.1.3 tout « neuf » et le plugin « prix_objet » ne s’affiche pas dans les articles alors que les « prix » sont activés. A la place se trouvent 2 « e ».
    Quelqu’un aurait une idée svp ?

    • Baaah… demander aux auteurs de prix_objet par exemple ? :p
      Parce que là c’est le plugin Commandes, ici.

    • Je sais bien, mais il n’est pas documenté (sauf erreur) et je ne voyais pas où poster ailleurs.

    • Si pas de doc ou autre contact, il faut t’inscrire sur la liste spip-zone dédiée aux plugins, et y poser la question à l’auteur dans ce cas. :)

    • Merci.

      Pour info en ajoutant « Declinaisons », le fonctionnement est ok, mais il y a d’autres soucis

    Répondre à ce message

  • 3

    Très bien et très pratique, ce plugin. Tout comme la suite ’tuto_commerce’, très didactique avec enfin sur SPIP un espace de vente facile à mettre en place (sauf pour les ’livraisons’, qui restent un chouilla compliquées à implémenter).

    C’est couillon - et j’ai un peu suivi les ’débats’ sur le sujet - mais à trop vouloir se la jouer ’puriste nobizness’ les - excellentisssimes et merveilleux [vous aves construit un outil magique et oh combien utile pour les assos et collectifs]- dévelopeurs/pluginiseurs de SPIP privaient jusque-là les associations d’un outil pour mettre en vente leur production (livres & kits militants, son/vidéo ....). Or comme disait l’autre mac(hiavel), « l’argent est le nerf de la guerre » et les associations et collectifs ont BESOIN de pouvoir vendre des choses pour financer leur action.

    Bref...
    Néanmoins je butte sur un probléme : comment faire une page ’mes achats’ ?
    On touve des solutions (à la façon dont le fait Teenoo) pour la page du ’produit’ lui-même. Mais comment faire pour implémenter une page avec tous les ’achats’(donc commandes au statut ’payé’) d’un membre enregistré ?

    Idées bienvenues...

    • Bah tu fais un squelette page=mes_commandes (mes_commandes.html quoi), et dedans tu listes les commandes liés à l’utilisateur connecté (COMMANDES){id_auteur=#SESSION{id_auteur}} ou plus simplement (COMMANDES){id_auteur} si l’utilisateur est déjà dans l’environnement au-dessus.

    • Merci pour ta réponse.
      Oui, je vois bien la chose, en partant des squelettes du plugin.
      Mais mon probléme n’est pas résolu pour autant car si je peux afficher le descriptif de chaque objet commandé (en l’occurence un article Spip) à l’aide de #DESCRIPTIF je n’arrive pas à faire un lien vers ce dernier... c’est bein d’avoir l’info sur les produits achetés, c’est mieux de pouvoir se rendre directement sur la page de chacun d’entre eux.
      Je n’arrive pas à mettre ça en place : je me retrouve avec des #ID_OBJET qui ne correspondent pas à celles des articles achetès, et donc un lien qui pointe vers un autre contenu... C’est bien la boucle (COMMANDES_DETAILS) qu’il faut utiliser, non ?
      Merci encore...

    • Tu as le plugin profils développé par Cerdic sur le GitHub / Nursit qui peut te donner une base pour la gestion coté client des informations, adresse, commandes. Moi j’avais codé un mon_compte qui est similaire.

      Ta boucle commande doit englober commandes_details pour lister les bon produits attaché a la commande : tu as un exemple dans les squelettes du privé : commandes/prive/squelettes/inclure/commande_contenu.html

    Répondre à ce message

  • Bonjour à tous,
    Je dois mettre en place un code promo dans mon processus de commande. Que me conseillez-vous ? Un champ extra dans la table spip_commandes_details ? N’allant pas jusqu’au paiement, je pense qu’il faut que mon code promo soit géré au niveau de la commande.
    Mais si à l’avenir un paiement doit être mis en place, comment ça va « causer » avec la suite du processus ?
    Merci d’avance.

    Répondre à ce message

  • Un grand merci pour ce plugin qui m’a permis de mettre en place (avec bank, Paniers et Commandes de paniers) une boutique en ligne avec Payplug.
    Je signale un petit bug dans le fichier /inc/commandes.php :
    $options['from'] = $config['expediteur_'.$config['expediteur']];
    et pas
    $options['expediteur'] = $config['expediteur_'.$config['expediteur']];
    Ceci permet d’utiliser les notifications lorsque la commande est modifiée (par exemple payée) pour envoyer la facture avec une autre adresse email que celle du site ou de Facteur

    Répondre à ce message

  • 1

    Dans le tuto on voit sur « Fiche d’une commande » une ligne pour frais de dossier et frais de port... Comment est-ce géré ?

    Répondre à ce message

  • 2

    Super ce nouveau plugin :))) Je dois développer une boutique de formation online, ça va être top. Quelques questions toutefois auxquelles je n’ai pas trouvé réponse dans les docs :
    -  Je souhaite que le client ait accès à son compte perso, pourtant rien n’indique une inscription et/ou connexion au moment de l’achat.
    -  Peut-on lister l’ensemble des articles (produits) achetés ?
    -  Peut-on pour un article (produit) définir dans la boucle à la fois la #SESSION et la confirmation d’achat par la session ?

    Pour l’instant c’est tout ce qui me tracasse pour le moment ! Merci encore pour ce super plug, je sens que je vais m’amuser dessus ^^

    • 1) Ce plugin est mono-tâche et ne s’occupe que de gérer des listes de commandes. Comment elles sont remplies, qui les achète ou comment on les achète, ça ce n’est pas son problème. :D
      Il faut forcément d’autres plugins pour gérer le reste.

      2) Des produits déjà achetés ? Par qui ? Achetés en général ou par une personne précise ? Je ne comprend pas trop la question.

      3) Par compris non plus ce que signifie « définir la session » ou « définir la confirmation d’achat par la session ».

      À priori ce plugin est souvent à utiliser en conjonction avec le plugin Paniers qui permet de… faire des paniers. Et il existe une fonction permettant de générer une commande à partir d’un panier (qui lui est en cookie/session). Malheureusement tout ça n’est pas encore très documenté…

      C’est dans ce plugin qui fait la liaison :
      http://zone.spip.org/trac/spip-zone/browser/_plugins_/commandes_paniers/trunk/action/commandes_paniers.php

    • Yes ! j’ai réussi à faire pas mal de chose :)
      Alors pour la partie affichage des produits achetés par un client voici le code si ça peut servir. En fait la majeure partie de la boutique vend du dématérialisé.

      Dans la page d’un produit non gratuit (prix_ht !=0) je cherche la commande du client (id_auteur) qui a une session active, qui a payé cet article (statut IN paye) je récupère dans un tableau et j’affiche.

      <BOUCLE_principale(PRODUITS) {id_produit}>
      <BOUCLE_formules(PRODUITS){id_produit}{prix_ht!=0}{par num titre}>
         
          <B_commandes>
          <BOUCLE_commandes(COMMANDES spip_commandes_details){id_objet=#ID_PRODUIT}{id_auteur=#SESSION{id_auteur}}{statut IN paye}{prix_unitaire_ht!=0}>
            
      #SET{affiche,#ID_OBJET}
      
              <BOUCLE_produit(PRODUITS){id_produit=#GET{affiche}}>
             
                  <section>
            <h1>#TITRE</h1>
            <h2>#DESCRIPTIF</h2>
              <hr>
               <article>#TEXTE</article>
            </section>
        
              </BOUCLE_produit>
      
          </BOUCLE_commandes>
          </B_commandes>
          Achetez la vidéo
          <//B_commandes>
      </BOUCLE_formules>
      </BOUCLE_principale>

      Ma grande interrogation à présent c’est la livraison. J’ai tenté le plugin de Rainer Muller sans succès jusqu’à présent, il existe apparemment un autre de Cedric Morin mais qui n’est pas activable dans SPIP. Eh oui, le client a eu la bonne idée de changer d’avis en cours de route et souhaiter vendre du produit physique obligeant donc à faire des frais de livraison. Hourra !

    Répondre à ce message

  • 1

    Rien à faire, le prix s’affiche à zéro …
    Ma boucle dans la page article, tout s’affiche bien (isbn, stock, sauf prix !)
    j’ai créé prix via champ extra après installation du plugin prix, le champ est correct en base (j’ai aussi mis prix_ht). Mais la ligne Prix : #PRIX -> toujours à 0…

    une idée ?merci d’avance…

            <div class="pricing">
                <ul><li>Réf. : #INPUT_CODE_ISBN </li>
                <li>Prix : #PRIX</li>
                <li>Disponibilité : #SELECTION_STOCK</li>
                <BOUCLE_achat(ARTICLES){id_article}{selection_stock=Oui}>
                    [(#BOUTON_ACTION{'ajouter au panier',
                        #URL_ACTION_AUTEUR{remplir_panier,#OBJET-#ID_OBJET,#SELF},ajax})]
                    <INCLURE{fond=noisettes/minipanier}></INCLURE>
                    <BOUCLE_ispanier(CONDITION){si #SESSION{id_panier}|oui}>
                    [(#BOUTON_ACTION{<:paniers:voir_mon_panier:>,[(#URL_PAGE{commande_panier}|parametre_url{lang, #LANG})]})] 
                    </BOUCLE_ispanier>
    
                </BOUCLE_achat>
                </ul>
            </div>
    • T’as remplis quoi comme champ ? Juste « prix » ?

      Parce que la balise #PRIX, par défaut, si le champ « prix_ht » existe, ça prend ça en priorité, en appliquant une taxe s’il trouve (ou aucune taxe sinon). Et si ça existe pas, ça cherche le champ « prix » tout court.

      Du coup si t’as rempli le champ « prix », mais que t’as un champ « prix_ht » à 0, ça serait possiblement logique.

    Répondre à ce message

  • 2

    Bonjour,

    j’aurais une question concernant les boucles :)) Après commande payée, je souhaite que l’acheteur puisse afficher la page du produit (page masquée tant qu’que le produit n’est pas achetée - objet dématérialisé).
    Sauf que je n’arrive pas à faire la liaison entre le n° de produit et le n° d’objet qui est pourtant le même...

    Voila mon bout de code qui est mauvais car

     id_objet IN #ID_PRODUIT

    ça veut pas ! :

    <BOUCLE_commandes(COMMANDES){id_auteur=#SESSION{id_auteur}}{statut IN paye}>
              <h1>id_commande : #ID_COMMANDE</h1>
              #ID_AUTEUR
              
               <BOUCLE_details(COMMANDES_DETAILS){id_commande}{par id_objet}{id_objet IN #ID_PRODUIT}>
                <h2>id_commande_detail : #ID_COMMANDES_DETAIL</h2>
                <h3>id_commande : #ID_COMMANDE</h3>   
                
            <BOUCLE_produit(PRODUITS){id_produit}>
                <section>
          <h1>#TITRE</h1>
          <h2>#DESCRIPTIF</h2>
            <hr>
             <article>#TEXTE</article>
            <hr>
          </section>
      
            </BOUCLE_produit>
           </BOUCLE_details>
        </BOUCLE_commandes>

    Merci pour votre aide

    • Je ne saisis pas tout mais en tout cas « IN » c’est quand on veut tester si une valeur est dans un tableau. Là #ID_PRODUIT c’est pas un tableau, c’est juste comparer deux valeurs, donc « machin=truc ».

    • J’ai trouvé la solution :))) Je l’avais transmise sur le rézo !

      Boucle commandes est jointe à commandes_details et vérifie que l’id_objet est similaire à l’id_produit actif (page produit.html), récupère l’id du client connecté, vérifie ce produit a été acheté (et payé) enfin regarde si ce n’est pas un produit gratuit.

      Je récupère donc dans un #SET l’id de l’objet et j’affiche le produit !

      Sinon, je demande d’acheter la vidéo (car dans ce cas c’est une vidéo).

       <B_commandes>
          <BOUCLE_commandes(COMMANDES spip_commandes_details){id_objet=#ID_PRODUIT}{id_auteur=#SESSION{id_auteur}}{statut IN paye}{prix_unitaire_ht!=0}>
            
      #SET{affiche,#ID_OBJET}
      
              <BOUCLE_produit(PRODUITS){id_produit=#GET{affiche}}>
                 #ID_PRODUIT
                  <section>
            <h1>#TITRE</h1>
            <h2>#DESCRIPTIF</h2>
              <hr>
               <article>#TEXTE</article>
              <hr>
            </section>
        
              </BOUCLE_produit>
      
          </BOUCLE_commandes>
          </B_commandes>
          Achetez la vidéo
          <//B_commandes>

      Ouala ! Prochain challenge —> la livraison :D

    Répondre à ce message

  • 3
    Renée Picard

    Sur le site www.mangersaison.com à chaque fois que je commande un produit j’ai une erreur 302.
    Pour faire le test :http://www.mangersaison.com/Pour-tester-le-processus-d-achat

    • Bonjour,

      J’avais aussi rencontré ce problème, c’était dû au fait que le serveur utilisé n’était pas apache. Résolu en ajoutant define('_SERVER_APACHE',true); dans mes_options.php

      cf. rapport de bug : https://core.spip.net/issues/2529

    • Renée Picard

      MERCI ! Cela fonctionne à merveille

    • Renée Picard

      Je viens de recevoir cette réponse de l’hébergeur.

      Je vous confirme que le serveur de P*** sont des serveurs Linux fonctionnant avec la technologie Apache, cela est totalement compatible avec le CMS SPIP.

      Alors pourquoi define(’_SERVER_APACHE’,true) ; règle le problème ?

      Je n’y comprends rien.

    Répondre à ce message

  • Renée Picard

    Depuis peu le site mangersaison.com ne gère plus les commandes et je ne comprends pas pourquoi ?
    plugin commande 1.4.9
    sur planet hoster

    J’ai beau faire des tests je reçois des courriels (clients et vendeurs) à 0
    Copier-coller d’un courriel client


    Bonjour Renée Picard

    Nous avons bien enregistré votre commande et nous vous remercions de votre confiance.

    Récapitulatif de commande :

    Commande 1431626474

    Date : 2015-05-14 14:01:14

    Cette commande est : En cours

    Détails de commande :

    Désignation Montant
    Total 0
    http://www.mangersaison.com


    C’est la même chose coté courriel-vendeur et sur le site en privé dans activités/commandes le message est une commande vide.
    Pourtant sur le site, à la page http://www.mangersaison.com/spip.php?page=commande_terminee&lang=fr
    j’ai bien les items commandés.

    Je suis allé voir la BD et je vois que commande prend en compte un seul item. Si je retourne sur le site et en ajoute un autre, je retourne dans la bd et il y a seulement le dernier ajout
    Toujours sur la bd, spip_commandes_details est vide

    Répondre à ce message

  • Renée Picard

    Avec le plugin 1.4.9 les courriels-notifications (client et vendeur) n’ont pas de description des produits achetés ni de prix.
    Je n’ai pas touché aux fichiers de notification du plugin et j’ai facteur 3.0.20 et notifications avancés 0.2.1
    Voir mangersaison.com il y a un produit pour le test
    http://www.mangersaison.com/Pour-tester-le-processus-d-achat

    Répondre à ce message

  • 3

    Bonjour et merci pour cette doc,
    j’envisage de mettre en place une boutique de vente de tirages photo. Une unique photo sera proposée en plusieurs formats. Et chaque format aura un prix différent.
    Ma question est de savoir comment structurer l’arborescence de départ ? J’ai dans l’idée qu’il faut une rubrique pour chaque image et un article pour chaque format/prix ? C’est un peu lourd, mais c’est ce que j’ai compris en lisant la doc ici et sur la page du carnet wiki.
    Donc, en résumé, une rubrique/image et un article/format/prix (et x articles pour décliner format/prix) ? Pouvez-vous me confirmer que c’est la méthode qui s’applique dans mon cas ?
    Merci d’avance,
    Rémy

    P.S. Dans un second temps, j’aimerais proposer en plus non pas des tirages mais l’achat direct de fichiers numériques. Est-ce-que ce plugin pourra répondre à ce besoin ?

    • Bonjour,
      Techniquement, l’arborescence n’a pas d’impact direct sur la gestion des commandes, utilisez celle qui vous semble la plus intuitive et la plus simple. Une rubrique par photo et un article par format, ça me semble ok.

      La seule chose qui importe, c’est que techniquement, la commande soit objet éditorial SPIP : ça peut être un article, mais aussi une rubrique, voir une brève, etc.
      Après, dans l’idéal, je pense qu’il vaut mieux utiliser autre chose que les articles pour faire de la vente.

      Il y a bien le plugin « produits » qui ajoute justement un objet « produit » avec tous les champs qu’il faut : prix, taxe etc. Mais la version pour SPIP 3 n’est pas encore fonctionnelle, et il ne prend pas en compte la notion de « déclinaison », or c’est ce dont vous auriez besoin pour gérer les différents formats.

      En ce qui concerne l’achat de fichiers numériques, oui c’est possible, mais il faut mettre en place un système de téléchargement des fichiers, les protéger et tout ça.
      Mais là on sort du domaine du plugin Commandes : la mise en place d’une boutique fera l’objet d’un article à part, il s’agit d’une question assez vaste.
      Pour rappel, le plugin Commandes est juste une des briques nécessaires pour faire de la vente en ligne.

    • Merci pour votre réponse rapide et claire.
      En effet la vente de fichiers numériques nécessite de sécuriser l’accès aux fichiers, etc. Dans un premier temps, si j’arrive à mettre en place la vente de tirages ce sera déjà très bien.
      Bonne journée,
      Rémy

    • Le top du top, ce serait de pouvoir lier le plugin declinaison produit avec le plugin commande.

      Je sais, c’est beaucoup demander...
      Mais je suis sûr qu’un jour, ce sera possible !

    Répondre à ce message

  • 1
    Renée Picard

    Ce plugin va-t-il être compatible SPIP 3.1

    • Il l’est peut-être déjà, il n’y a pas vraiment de différence majeure. Il faut le tester en changeant la borne supérieure dans le XML, en utilisant ses fonctionnalités, et si c’est bon, le dire soit ici soit sur la liste spip-zone (ou demander un compte pour le SVN et modifier directement :D).

    Répondre à ce message

  • 1

    Bonjour,
    J’utilise ce plugin, et j’arrive sur la page « commande_terminee » avec tous les produits choisis dans le panier et leur prix respectif.....ma question est la suivant si je veux le règlement se face par paypal qu’est ce qu’il faut faire ? j’ai déja installé les plugins paypal et « commande payées avec payppal »
    Mais je ne sais pas qu’est ce qu’il faut intégré et ou ? pour pouvoir régler par paypal avec le recap du panier et les prix. Merci de votre aide

    Répondre à ce message

  • 3

    Bonjour,

    Je cherche à utiliser le plugin « Abonnements 2 » qui semble très prometteur mais très peu documenté, je n’ai pas trouvé le moyen de le coupler à un système de paiement sécurisé, faut-il passer par un plugin de gestion de commandes comme celui ci ?

    Si quelqu’un a un peu de doc pour moi pour Abonnements, je suis preneur !

    Merci :)

    Freed

    Répondre à ce message

  • 2
    Renée Picard

    Lorsque je fais la mise à jour du plugin de 1.2.6 à 1.4.8 j’obtiens une page blanche sur http://www.mangersaison.com/mang/ecrire

    J’ai jeté les plugins commandes_panier et quantimandes et j’ai quand même une page blanche sur /ecrire

    Je suis donc revenu à la 1.2.6 avec commandes_panier 0.15 et le plugin spécial quantimandes et le tout fonctionne.

    Je pensais que le « bug » était dû à quantimandes qui nécessite dans paquet.xml
    <necessite nom="commandes" compatibilite="[1.2.0;]" ></necessite> mais ce n’est pas la bonne piste puisque même si le plugin quantimandes est jeté l’activation de commandes 1.4.8 génère toujours une page blanche dans écrire ???? QUE faire pour tenir le tout à jour ???

    • Quand il y a une page blanche, c’est qu’il y a des erreurs PHP. Par défaut ça ne s’affiche pas, il faut ajouter des directives (dans config/mes_options.php par exemple) pour que ça s’affiche. Une fois les erreurs affichées, on sait déjà mieux de quoi il retourne.

      Pour info cette semaine le plugin Commandes a eu une mise à jour notoire qui transforme les détails de commandes en vrai objet SPIP, et qui permet de les modifier manuellement (ainsi que d’en ajouter à la main).

      Mais du coup le plugin « Commandes de Paniers » (panier2commande) n’était plus raccord. Tcharlss a corrigé ça hier !

    • Renée Picard

      Merci
      J’ai installé le plugin 1.4.9 et maintenant tout fonctionne à merveille !

    Répondre à ce message

  • 4

    Bonjour,

    Je suis en train de monter un site e-commerce en SPIP, pour mon plus grand plaisir...

    Après la confirmation de la commande, je souhaiterai décrémenter un champ Quantité que j’ai défini avec « Champs Extra ».

    Cela est-il possible ?

    Merci !

    • Bonjour,

      Oui c’est possible, la façon de procéder dépend de plusieurs choses :
      -  déjà, qu’est-ce que vous entendez par « confirmer » la commande : est-ce au moment où le panier est validé ? Ou quand le visiteur choisit des adresses pour la commande ? Ou quand la commande aquiert un statut précis ?
      -  ensuite, comment avez-vous mis en place la partie e-commerce de votre site ? Quels autres plugins sont installés ? Y a-t-il des formulaires persos ?

      Il va très certainement falloir utiliser un pipeline pour compléter les traitements d’un formulaire, mais sans plus de détail, impossible de vous dire lequel et comment.

    • Bonjour,

      Merci pour ce retour.
      Je souhaite décrémenter la quantité lorsque la commande a été payée.

      Le champ Quantité a été ajouté dans Articles avec « Champs Extras ».

      Ensuite, j’utilise les plug-ins Paniers, Commande de paniers et les plug-ins paypal.

    • Une possibilité est se se brancher sur le pipeline « traitement_paypal » du plugin Commandes payées avec Paypal.
      Ce pipeline est utilisé au moment où la notification de paiement (IPN) de Paypal est réceptionnée, donc c’est le plus indiqué.

      L’idéal serait de faire ça dans un petit plugin perso, sinon dans mes_options.php.
      Voilà un exemple de base, à adapter à vos besoins. Attention, j’ai pas testé, il y a peut-être des coquilles qui trainent.

      $GLOBALS['spip_pipeline']['traitement_paypal'] .= "|maj_quantites_commandes";
      
      function maj_quantites_commandes($flux){
      
      // Si on est dans le cas d'un paiement de commande, que la commande est valide, et que le paiement a été fait
      // Dans le formulaire paypal, il faut avoir utilisé les bonnes valeurs pour les 2 paramètres «custom» et «identifiant», sinon ça ne marchera pas, cf. http://contrib.spip.net/Paypal-4519, section «syntaxe avancée»
      // #ARRAY{custom,payer_commande, identifiant,#REFERENCE}
      if (
      	$flux['args']['paypal']['custom'] == 'payer_commande'
      	AND $reference = $flux['args']['paypal']['invoice']
      	AND $id_commande = sql_getfetsel('id_commande', 'spip_commandes', 'reference = '.sql_quote($reference))
      	AND $flux['args']['paypal']['payment_status'] == 'Completed'
      ){
      
      	// retrouver les objets correspondants à la commande dans spip_commandes_details
      	if ($objets = sql_allfetsel('objet,id_objet,quantite', 'spip_commandes_details', 'id_commande='.intval($id_commande))){
      
      		// mettre à jour la quantité de chaque objet
      		include_spip('action/editer_objet');
      		foreach($objets as $v) {
      
      			$objet = $v['objet']; // 'article'
      			$id_table_objet = id_table_objet($objet); // 'id_article'
      			$table_objet = table_objet_sql($objet); // 'spip_articles'
      			$id_objet = intval($v['id_objet']);
      			$quantite = intval($v['quantite']);
      
      			// calculer la nouvelle quantité
      			$quantite_ancienne = intval(sql_getfetsel('quantite', $table_objet, $id_table_objet.'='.$id_objet));
      			$quantite_nouvelle = $quantite_ancienne - 1;
      
      			// mettre à jour la quantité
      			objet_modifier($objet, $id_objet, array('quantite'=>$quantite_nouvelle));
      		}
      
      	}
      }
    • Merci beaucoup !

      Je vais tester çà !

    Répondre à ce message

  • 3
    Renée Picard

    J’ai ajouté avec le plugin champ extra un champ quantite.
    J’ai créé dans plugin un dossier intitulé : editer_commande
    J’y ai mis un fichier nommé plugin.xml

    <plugin>
     <nom>editer_commande</nom>
     <version>0.1</version>
     <prefix>ed_com</prefix>
     <etat>experimental</etat>
     <auteur>R Picard [contact->mailto:rpicardinfo@gmail.com]
    </auteur>
     <description>Gestion des produits </description>
     <pipeline>
    		<nom>editer_commande</nom>
    		<inclure>editer_commande.php</inclure>
    	</pipeline>
    
    
    </plugin>

    puis j’ai ajouté un fichier nommé editer_commande.php

    <?php
    /**
     * API d'édition du plugin Commandes
     *
     * @plugin     Commandes
     * @copyright  2014
     * @author     Ateliers CYM, Matthieu Marcillaud, Les Développements Durables
     * @licence    GPL 3
     * @package    SPIP\Commandes\Editer
     */
    
    // Sécurité
    if (!defined("_ECRIRE_INC_VERSION")) return;
    
    /**
     * Point d'entrée d'édition d'une commande
     *
     * On ne peut entrer que par un appel en fournissant <span class="base64" title="PGNvZGUgY2xhc3M9InNwaXBfY29kZSBzcGlwX2NvZGVfaW5saW5lIiBkaXI9Imx0ciI+JGlkX2NvbW1hbmRlPC9jb2RlPg=="></span>
     * mais pas pas une url
     *
     * @uses commande_inserer()
     * @uses commande_modifier()
     *
     * @param int $id_commande
     *     Identifiant de la commande
     * @return array
     *     Identifiant de la commande et message d'erreur eventuel
     */
    function action_editer_commande_dist($id_commande=null) {
    
    	// appel direct depuis une url interdit
    	if (is_null($id_commande)){
    		//$securiser_action = charger_fonction('securiser_action', 'inc');
    		//$id_commande = $securiser_action();
    		include_spip('inc/minipres');
    		echo minipres(_T('info_acces_interdit'));
    		die();
    	}
    
    	// si id_commande n'est pas un nombre, c'est une creation
    	if (!$id_commande = intval($id_commande)) {
    		$id_commande = commande_inserer(null,array('id_auteur'=>_request('id_auteur')));
    	}
    
    	if (!($id_commande = intval($id_commande))>0)
    		return array($id_commande,_L('echec enregistrement en base'));
    
    	// Enregistre l'envoi dans la BD
    	$err = commande_modifier($id_commande);
    
    	return array($id_commande,$err);
    }
    
    
    /**
     * Crée une nouvelle commande et retourne son identifiant
     *
     * Les notifications par email sont traitées après l'insertion en base et l'appel des pipelines
     *
     * @uses traiter_notifications_commande()
     *
     * @pipeline_appel pre_insertion
     * @pipeline_appel post_insertion
     * @param null $id_parent
     *     Paramètre inutilisé, présent pour compatibilité avec api modifier objet
     * @param array $champs
     *     Couples des champs/valeurs par défaut
     * @return int|bool
     *     - Identifiant de la commande si succès
     *     - False en cas d'erreur
     */
     
    function commande_inserer($id_parent=null, $champs=array()) {
    	$id_commande = false;
    
    	// On insère seulement s'il y a un auteur correct
    	if (isset($champs['id_auteur']) and $champs['id_auteur'] = intval($champs['id_auteur'])){
    		// Si id_auteur vaut 0 ou n'est pas defini, ne pas creer de commande et envoyer message impossible
    		if (!$id_auteur = intval($champs['id_auteur'])) {
    			return false; // ? minipress(); ?
    		} 
    
    		// La date de tout de suite
    		$champs['date'] = date('Y-m-d H:i:s');
    
    		// Le statut en cours
    		$champs['statut'] = 'encours';
    
    		// Envoyer aux plugins avant insertion
    		$champs = pipeline('pre_insertion',
    			array(
    				'args' => array(
    					'table' => 'spip_commandes',
    				),
    				'data' => $champs
    			)
    		);
    
    		// Insérer l'objet
    		$id_commande = sql_insertq("spip_commandes", $champs);
    
    		// Envoyer aux plugins après insertion
    		pipeline('post_insertion',
    			array(
    				'args' => array(
    					'table' => 'spip_commandes',
    					'id_objet' => $id_commande
    				),
    				'data' => $champs
    			)
    		);
    
    		// Envoi des notifications par email
    		spip_log("inserer_commande : appel des notifications pour la commande $id_commande",'commandes.'._LOG_INFO);
    		include_spip('inc/commandes');
    		traiter_notifications_commande($id_commande);
    
    	}
    
    	return $id_commande;
    }
    
    /**
     * Appelle les fonctions de modification d'une commande
     *
     * @uses objet_modifier_champs()
     * @uses commande_instituer()
     *
     * @param int $id_commande
     *     Identifiant de la commande
     * @param array|null $set
     *     Couples des champs/valeurs à modifier
     * @return mixed|string $err
     *     Message d'erreur éventuel
     */
    function commande_modifier($id_commande, $set=null) {
    	$err = '';
    
    	include_spip('inc/saisies');
    	$saisies = saisies_chercher_formulaire('editer_commande', array($id_commande));
    	$champs = saisies_lister_champs($saisies, false);
    
    	include_spip('inc/modifier');
    	$c = collecter_requests(
    		// whitelist
    		$champs,
    		// blacklist
    		array('date','statut'),
    		// donnees eventuellement fournies
    		$set
    	);
    
    	// Si l'objet est publie, invalider les caches et demander sa reindexation
    	if (objet_test_si_publie('commande',$id_commande)){
    		$invalideur = "id='id_commande/$id_commande'";
    		$indexation = true;
    	}
    	else {
    		$invalideur = "";
    		$indexation = false;
    	}
    
    	if ($err = objet_modifier_champs('commande', $id_commande,
    		array(
    			'nonvide' => array('statut' => _T('info_sans_statut')),
    			'invalideur' => $invalideur,
    			'indexation' => $indexation,
    		),
    		$c))
    		return $err;
    
    	// Modification de statut
    	$c = array();
    	foreach (array('id_auteur', 'date', 'statut',) as $champ)
    		$c[$champ] = _request($champ, $set);
    	$err = commande_instituer($id_commande, $c);
    
    	return $err;
    }
    
    /**
     * Instituer une commande
     *
     * Modifie des éléments à part que sont l'auteur, la date, le statut
     *
     * @uses editer_commande_details()
     * @uses traiter_notifications_commande()
     *
     * @pipeline_appel pre_edition
     * @pipeline_appel post_edition
     * @param int $id_commande
     *     Identifiant de la commande
     * @param array $c
     *     Couples champ/valeur à modifier
     * @param bool $calcul_details
     *     (?) Inutilisé
     * @return mixed|string
     */
    function commande_instituer($id_commande, $c, $calcul_details=true){
    	include_spip('inc/autoriser');
    	include_spip('inc/modifier');
    
    	$row = sql_fetsel("statut, date, id_auteur", "spip_commandes", "id_commande=$id_commande");
    	$id_auteur = $row['id_auteur'];
    	$statut_ancien = $statut = $row['statut'];
    	$date_ancienne = $date = $row['date'];
    	$champs = array();
    
    	$d = isset($c['date']) ? $c['date'] : null;
    	$s = isset($c['statut']) ? $c['statut'] : $statut;
    
    	// On ne modifie le statut que si c'est autorisé
    	if ($s != $statut or ($d AND $d != $date)) {
    		//todo = donner l'autorisation a commandes_paypal_traitement_paypal
    		//if (autoriser('modifier', 'commande', $id_commande))
    			$statut = $champs['statut'] = $s;
    		//else
    		//	spip_log("editer_commande $id_commande refus " . join(' ', $c),'commandes');
    
    		// Si on doit changer la date explicitement
    		if ($d){
    			$champs['date'] = $date = $d;
    		}
    	}
    
    	$champs['id_auteur'] = $id_auteur;
    
    	// Mettre à jour les dates de paiement ou d'envoi pour les statuts correspondants
    	if ($statut != $statut_ancien)
    		foreach (array('partiel'=>'paiement', 'paye'=>'paiement', 'envoye'=>'envoi') as $k=>$v)
    			if ($statut == $k)
    				$champs["date_$v"] = date('Y-m-d H:i:s');
    
    	// Envoyer aux plugins avant édition
    	$champs = pipeline(
    		'pre_edition',
    		array(
    			'args' => array(
    				'table' => 'spip_commandes',
    				'id_objet' => $id_commande,
    				'action' => 'instituer',
    				'statut_ancien' => $statut_ancien,
    			),
    			'data' => $champs
    		)
    	);
    
    	if (!count($champs)) return;
    
    	// Envoyer les modifications et calculer les héritages
    	editer_commande_details($id_commande, $champs, $calcul_details);
    
    	// Invalider les caches
    	include_spip('inc/invalideur');
    	suivre_invalideur("id='id_commande/$id_commande'");
    
    	if ($date) {
    		$t = strtotime($date);
    		$p = @$GLOBALS['meta']['date_prochain_postdate'];
    		if ($t > time() AND (!$p OR ($t < $p))) {
    			ecrire_meta('date_prochain_postdate', $t);
    		}
    	}
    
    	spip_log("instituer_commande : flux post_edition pour la commande $id_commande",'commandes.'._LOG_INFO);
    
    	// Envoyer aux plugins après édition
    	pipeline(
    		'post_edition',
    		array(
    			'args' => array(
    				'table' => 'spip_commandes',
    				'id_objet' => $id_commande,
    				'action' => 'instituer',
    				'statut_ancien' => $statut_ancien,
    			),
    			'data' => $champs
    		)
    	);
    
    	// Envoi des notifications par email
    	spip_log("instituer_commande : appel des notifications pour la commande $id_commande",'commandes.'._LOG_INFO);
    	include_spip('inc/commandes');
    	traiter_notifications_commande($id_commande);
    
    	return ''; // pas d'erreur
    }
    
    /**
     * Fabrique la requête d'institution de la commande
     *
     * Modifie la commande en calculant les dépendances des détails
     * 
     * @param int $id_commande
     *     Identifiant de la commande
     * @param array $champs
     *     Couples des champs/valeurs à modifier
     * @param bool $cond
     *     (?) inutilisé
     * @return void
     */
    function editer_commande_details($id_commande, $champs, $cond=true) {
    
    	if (!$champs) return;
    
    	sql_updateq(table_objet_sql('commande'), $champs, "id_commande=$id_commande");
    
    	// Changer le statut des elements concernes ? (voir details)
    
    	/*
    	if ($cond) {
    		include_spip('inc/rubriques');
    		$postdate = ($GLOBALS['meta']["post_dates"] == "non" and isset($champs['date']) and (strtotime($champs['date']) < time())) ? $champs['date'] : false;
    		calculer_rubriques_if($id_rubrique, $champs, $statut, $postdate);
    	}
    	*/
    }
    
    // Ci dessous, fonctions dépréciées gardées pour rétro-compatibilité
    
    /**
     * Enregistre une modification d'une commande
     *
     * @deprecated Alias de 'commande_modifier' pour rétro-compatibilité
     * @uses commande_modifier()
     *
     * @param int $id_commande
     *     Identifiant de la commande
     * @param array $c
     *     Couples des champs/valeurs modifiées
     * @return mixed|string
     */
    function revision_commande($id_commande, $c=false) {
    	return commande_modifier($id_commande, $c);
    }
    
    /**
     * Crée une nouvelle commande
     *
     * @deprecated Alias de 'commande_inserer' pour rétro-compatibilité
     * @uses commande_inserer()
     *
     * @param array $champs
     *     Couples des champs/valeurs par défaut
     * @return
     */
    function commande_insert($champs=array()){
    	return commande_inserer(null,$champs);
    }
    
    /**
     * Appelle les fonctions de modification d'une commande
     *
     * @deprecated Alias de 'commande_modifier' pour rétro-compatibilité
     * @uses commande_modifier()
     * 
     * @param int $id_commande
     *     Identifiant de la commande
     * @param array|null $set
     *     Couples des champs/valeurs à modifier
     * @return
     */
    function commande_set($id_commande, $set=null){
    	return commande_modifier($id_commande, $set);
    }
    
    /**
     * Modifie des éléments à part que sont l'auteur, la date, le statut
     * 
     * @deprecated Alias de 'commande_instituer' pour rétro-compatibilité
     * @uses commande_instituer()
     * 
     * @param int $id_commande
     *     Identifiant de la commande
     * @param array $c
     *     Couples des champs/valeurs à modifier
     * @param bool $calcul_details
     *     (?) Inutilisé
     * @return
     */
    function instituer_commande($id_commande, $c, $calcul_details=true){
    	return commande_instituer($id_commande, $c, $calcul_details);
    }
    // mettre à jour la quantité de chaque objet
    		include_spip('action/editer_objet');
    		foreach($objets as $v) {
     
    			$objet = $v['objet']; // 'article'
    			$id_table_objet = id_table_objet($objet); // 'id_article'
    			$table_objet = table_objet_sql($objet); // 'spip_articles'
    			$id_objet = intval($v['id_objet']);
    			$quantite = intval($v['quantite']);
     
    			// calculer la nouvelle quantité
    			$quantite_ancienne = intval(sql_getfetsel('quantite', $table_objet, $id_table_objet.'='.$id_objet));
    			$quantite_nouvelle = $quantite_ancienne - 1;
     
    			// mettre à jour la quantité
    			objet_modifier($objet, $id_objet, array('quantite'=>$quantite_nouvelle));
    		}
     
    	
    }
    
    ?>

    J’ai été coché acheté dans l’interface de commandes en espace privé.

    Cela ne fonctionne pas. Les quantités ne bougent pas.
    Je ne sais pas comment faire pour gérer les quantités une fois que le produit a été coché acheté

    • Bonjour,

      Pour les gens qui aimeraient suivre, le message fait suite à une discussion sur la liste spip users. La question était la suivante :

      Maintenant comment mettre une quantité EX : 50 pots de beurre de pommes et une fois que j’en ai vendu 50 le site dit épuisé ?
      NOTE : Le paiement d’une commande se fera en espèce ou par chèque.

      Je vais vous faire à peu près la même réponse que la pour question précédente : la gestion des quantités n’est pas gérée par le plugin, les options dans l’interface n’auront aucun effet sur ce point. Le mieux, c’est de gérer ça dans un plugin perso adapté à vos besoins, comme vous le faîtes.

      Par contre, c’est très déconseillé de surcharger le fichier editer_commande.php (et puis quelles modifs y apportez vous ? on ne saura pas... ), il vaut mieux passer par un pipeline.

      L’idée de base serait de décrémenter le champ « quantite » des articles d’une commande quand elle acquiert le statut « paye », via le pipeline « post_edition ».

      Donc dans ed_com_pipelines.php (et en déclarant le pipeline dans paquet.xml) :

      // Changer les quantités des objets d'une commande quand elle passe du statut "attente" à "paye"
      function ed_com_post_edition($flux){
      
      	if (
      			$flux['args']['action'] == 'instituer'
      			AND $flux['args']['table'] == 'spip_commandes'
      			AND ($id_commande = intval($flux['args']['id_objet'])) > 0
      			AND ($statut_nouveau = $flux['data']['statut']) == 'paye'
      			AND ($statut_ancien = $flux['args']['statut_ancien']) == 'attente'
      	){
      
      		// retrouver les objets correspondants à la commande dans spip_commandes_details
      		if (
      			$objets = sql_allfetsel('objet,id_objet,quantite', 'spip_commandes_details', 'id_commande='.intval($id_commande))
      			AND is_array($objets)
      			AND count($objets)
      		){
      
      			// mettre à  jour la quantité de chaque objet de la commande
      			include_spip('action/editer_objet');
      			foreach($objets as $v) {
      
      				// récupérer les infos
      				$objet = $v['objet'];                     // 'article'
      				$id_table_objet = id_table_objet($objet); // 'id_article'
      				$table_objet = table_objet_sql($objet);   // 'spip_articles'
      				$id_objet = intval($v['id_objet']);
      				$quantite = intval($v['quantite']);
      
      				// calculer la nouvelle quantité
      				$quantite_ancienne = intval(sql_getfetsel('quantite', $table_objet, $id_table_objet.'='.$id_objet));
      				$quantite_nouvelle = $quantite_ancienne - $quantite;
      
      				// mettre à jour la quantité
      				if ($quantite_nouvelle) > 0 {
      					objet_modifier($objet, $id_objet, array('quantite'=>$quantite_nouvelle));
      				}
      			}
      
      		}
      	}
      }

      Bon, c’est juste un exemple de base, avec un calcul des quantités tout simple.
      C’est à compléter et à adapter à votre situation.

    • Renée Picard

      C’est dommage que ce plugin ne gère pas les stocks car pour le reste il est parfait et ma boutique en développement avec SPIP fonctionne à merveille.

      Je n’ai jamais fait de plugin, je ne connais pas les pipelines. J’ai lu http://programmer.spip.net/Utiliser-les-pipelines puis j’ai découvert que post_edition est déjà dans SPIP http://code.spip.net/autodoc/pipelines/post_edition.html puis j’ai rédigé un paquet http://plugins.spip.net/redaction-du-paquet-xml.html je l’ai validé http://plugins.spip.net/validation/
      J’ai copié le code fourni ci_haut dans un fichier ed_com_pipelines.php que j’ai placé dans le nouveau plugin au même niveau que le paquet. Sur l’article qui affiche le produit j’ai ajouté un champ #QUANTITE en espérant que celui-ci diminuerait après avoir fait des achats.
      Voici le paquet

      <paquet
      prefix="ed_com_post_edition"
       categorie="divers"
       version="1.0.0"
       etat="dev"
       compatibilite="[3.0.0-alpha2;3.0.*]"
       logo="prive/themes/spip/images/compagnon-32.png"
       schema="1.0.0"
       meta="ed_com_post_edition">
      <nom>ed_com_post_edition</nom>
      <auteur> R Picard </auteur>
      <pipeline nom="post_edition"></pipeline>
      <pipeline nom="post_edition" inclure="post_edition/ed_com_pipelines.php" ></pipeline>
      </paquet>

      Il y a sûrement une ou des erreurs car cela ne fonctionne pas.
      Merci de m’aider.

    • C’est normal que ce plugin ne gère pas les quantités, car ça n’a aucun rapport avec « une commande ». Ce plugin ne fait qu’une seule chose, comme tous les plugins de la suite de commerce (Produits ne fait que des listes de produits, Paniers ne gère que les paniers, etc).

      Dans le code au-dessus, je vois au moins à changer « >= 0 » pour le test de mise à jour de la quantité. Car elle peut bien évidemment être à 0. Par ailleurs les parenthèses ne sont pas du tout au bon endroit.

      Il faut au moins remplacer :

      if ($quantite_nouvelle) > 0 {

      Par :

      if ($quantite_nouvelle >= 0) {

      Mais il y a peut-être d’autres choses, je n’ai lu que rapidement…

    Répondre à ce message

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom