[SPIP Zone] Panier, Commandes et réductions

Hello,

petit dilemne sur la gestion des réductions avec paniers et commandes tels qu'ils sont actuellement designés.

Je vous soumets donc mes interrogations et pistes d'évolution pour avis avant de risquer de partir dans une direction inopportune ou si vous avez de meilleures idées.

Workflow actuel :
* on ajoute des produits au panier, qui sont représentés par des liens dans produits_liens avec une quantité.
* on visualise le récapitulatif du panier, avec possibilité de modifier les quantités, supprimer un article
* on valide le panier qui est transformé en commande qui n'est plus ensuite modifiée (on ne change pas les quantités, les prix sur la commandes).

Au moment de la transformation du panier en commande on calcule le prix de chaque objet avec la fonction prix() et on enregistre prix ht et taxe de chaque objet dans commandes_details.

A la phase de récapitulatif panier je veux pouvoir entrer un code de réduction ou appliquer une remise.

1er problème : affecter la remise au prix du panier
* si j'ajoute ma remise au panier comme un produit, il ne me sera pas possible d'en calculer le prix, car la fonction prix() appelée pour un objet remise ne saura pas calculer un prix puisqu'elle ne sait pas à quel panier ça s'applique
* si j'ai plusieurs produits avec des TVA différentes, je ne peux pas appliquer une ligne de remise unique, je suis obligé de faire une ligne par taux de TVA

Cela remets en cause la représentation en base du panier par un simple lien entre panier et objet : il faudrait que le lien contienne aussi l'info de prix_ht et taxe (comme les détails d'une commande) qui serait renseigné par défaut avec la fonction prix() comme actuellement

2ème problème : affecter la remise à chaque ou certains produits

* Du fait du problème potentiel sur la TVA qui n'est pas identique pour tous les produits, ou du fait qu'une remise ne s'applique pas forcément globalement à tout un panier/une commande il me semble en fait que chaque ligne du panier (et de la commande) devrait pouvoir recevoir une remise dans un champ dédié.

Ainsi l'application d'une remise consisterait donc à modifier le champ 'remise' sur les lignes du panier/de la commande.
Cela peut se combiner avec le fait d'ajouter une ligne 'Remise' avec un prix nul, juste pour indiquer le libellé/la raison de la remise.

Mais de cette façon on aurait un prix ligne par ligne correct, avec des taxes correctes.

Cela fait évoluer (un peu) le plugin commandes pour ajouter la colonne supplémentaire 'remise'.
Du coup, dans la même optique on pourrait se contenter d'ajouter une colonne 'remise' sur paniers_liens, comme pour le champ 'quantite', le prix restant calculé par la fonction prix() pour l'affichage et la transformation en commande.

Dans les 2 cas on fait évoluer la base et les squelettes d'affichage, ainsi que la fonction de conversion du panier en commande.

Si les squelettes ont été surchargés, le champ remise ne sera pas pris en compte, mais cela veut dire aussi qu'il n'est pas utilisé, donc à zero, et on ne casse rien.

Des avis, des objections, des remarques, des questions ?

--
Cédric

Le 30/05/2017 à 13:07, Cédric Morin a écrit :

petit dilemne sur la gestion des réductions avec paniers et commandes tels qu'ils sont actuellement designés.
Je vous soumets donc mes interrogations et pistes d'évolution pour avis avant de risquer de partir dans une direction inopportune ou si vous avez de meilleures idées.

La "remise sur panier" est une possibilité de remise,
mais toutes les remises ne se réduisent pas à cela.

Ça m'arrive de temps en temps d'avoir besoin d'appliquer des remises différentes selon les produits,
(livres, revues, abonnements, services, etc) et actuellement soit je fais la facture à la main,
soit je fais des factures différentes en rassemblant les taux identiques dans chaque facture.
(non, c'est pas avec ces plugins, mais c'est la même problématique !)

Vu qu'il y a aujourd'hui cette perspective dans l'ensemble de plugin spip commandes et paniers etc,
il me semblerait bien de pas (trop) restreindre artificiellement les possibilités de remise.

JLuc

Workflow actuel :
* on ajoute des produits au panier, qui sont représentés par des liens dans produits_liens avec une quantité.
* on visualise le récapitulatif du panier, avec possibilité de modifier les quantités, supprimer un article
* on valide le panier qui est transformé en commande qui n'est plus ensuite modifiée (on ne change pas les quantités, les prix sur la commandes).

Au moment de la transformation du panier en commande on calcule le prix de chaque objet avec la fonction prix() et on enregistre prix ht et taxe de chaque objet dans commandes_details.

A la phase de récapitulatif panier je veux pouvoir entrer un code de réduction ou appliquer une remise.

1er problème : affecter la remise au prix du panier
* si j'ajoute ma remise au panier comme un produit, il ne me sera pas possible d'en calculer le prix, car la fonction prix() appelée pour un objet remise ne saura pas calculer un prix puisqu'elle ne sait pas à quel panier ça s'applique
* si j'ai plusieurs produits avec des TVA différentes, je ne peux pas appliquer une ligne de remise unique, je suis obligé de faire une ligne par taux de TVA

Cela remets en cause la représentation en base du panier par un simple lien entre panier et objet : il faudrait que le lien contienne aussi l'info de prix_ht et taxe (comme les détails d'une commande) qui serait renseigné par défaut avec la fonction prix() comme actuellement

2ème problème : affecter la remise à chaque ou certains produits

* Du fait du problème potentiel sur la TVA qui n'est pas identique pour tous les produits, ou du fait qu'une remise ne s'applique pas forcément globalement à tout un panier/une commande il me semble en fait que chaque ligne du panier (et de la commande) devrait pouvoir recevoir une remise dans un champ dédié.

Ainsi l'application d'une remise consisterait donc à modifier le champ 'remise' sur les lignes du panier/de la commande.
Cela peut se combiner avec le fait d'ajouter une ligne 'Remise' avec un prix nul, juste pour indiquer le libellé/la raison de la remise.

Mais de cette façon on aurait un prix ligne par ligne correct, avec des taxes correctes.

Cela fait évoluer (un peu) le plugin commandes pour ajouter la colonne supplémentaire 'remise'.
Du coup, dans la même optique on pourrait se contenter d'ajouter une colonne 'remise' sur paniers_liens, comme pour le champ 'quantite', le prix restant calculé par la fonction prix() pour l'affichage et la transformation en commande.

Dans les 2 cas on fait évoluer la base et les squelettes d'affichage, ainsi que la fonction de conversion du panier en commande.

Si les squelettes ont été surchargés, le champ remise ne sera pas pris en compte, mais cela veut dire aussi qu'il n'est pas utilisé, donc à zero, et on ne casse rien.

Des avis, des objections, des remarques, des questions ?

Hello,

Je suis également en train de travailler sur l'intégration d'une
boutique pour mon squelette Zoundation. Et je suis tombé sur cette
problématique de manipulation du panier avant transformation en commande.

Une chose était certaine : je voulais que les réductions s’appliquent
directement sur le panier avant de passer commande. Et pas faire des
manipulations au niveau de la commande qui dois être figée.

J'en suis arrivé a la conclusion que l'architecture actuel du plugin
panier ne permettait pas de manipuler facilement les prix/éléments du
caddie. Il est très difficile d'ajouter des réductions via par exemple
un plugin dédié, ou même d'ajouter automatiquement des collections de
produit (des kits par exemple).

Bref, je n'ai pas cherché plus loin et j'ai entrepris de reprendre à 0
le problème des paniers dans SPIP. Je les ai rebaptisés "caddie" pour
faire la distinction.

Le code est là : https://github.com/phenix-factory/caddie

L'idée est d'avoir un caddie sous forme de tableau PHP, facilement
manipulable par la suite. Spip se contente d'afficher ce tableau après
traitement.

https://github.com/phenix-factory/caddie/blob/master/inc/caddie.php#L157

Je n'ai pas encore défini les différents pipelines qui permettront de
manipuler le caddie, car je n'ai pas encore analysé la meilleure façon
de faire, mais j'imagine que ce sera à la fin de cette fonction, qui est
ensuite transformée en commande.

Didier

Le 30/05/17 à 13:07, Cédric Morin a écrit :

Hello,

petit dilemne sur la gestion des réductions avec paniers et commandes
tels qu'ils sont actuellement designés.

Je vous soumets donc mes interrogations et pistes d'évolution pour
avis avant de risquer de partir dans une direction inopportune ou si
vous avez de meilleures idées.

Workflow actuel :
* on ajoute des produits au panier, qui sont représentés par des liens
dans produits_liens avec une quantité.
* on visualise le récapitulatif du panier, avec possibilité de
modifier les quantités, supprimer un article
* on valide le panier qui est transformé en commande qui n'est plus
ensuite modifiée (on ne change pas les quantités, les prix sur la
commandes).

Au moment de la transformation du panier en commande on calcule le
prix de chaque objet avec la fonction prix() et on enregistre prix ht
et taxe de chaque objet dans commandes_details.

A la phase de récapitulatif panier je veux pouvoir entrer un code de
réduction ou appliquer une remise.

1er problème : affecter la remise au prix du panier
* si j'ajoute ma remise au panier comme un produit, il ne me sera pas
possible d'en calculer le prix, car la fonction prix() appelée pour un
objet remise ne saura pas calculer un prix puisqu'elle ne sait pas à
quel panier ça s'applique
* si j'ai plusieurs produits avec des TVA différentes, je ne peux pas
appliquer une ligne de remise unique, je suis obligé de faire une
ligne par taux de TVA

Cela remets en cause la représentation en base du panier par un simple
lien entre panier et objet : il faudrait que le lien contienne aussi
l'info de prix_ht et taxe (comme les détails d'une commande) qui
serait renseigné par défaut avec la fonction prix() comme actuellement

2ème problème : affecter la remise à chaque ou certains produits

* Du fait du problème potentiel sur la TVA qui n'est pas identique
pour tous les produits, ou du fait qu'une remise ne s'applique pas
forcément globalement à tout un panier/une commande il me semble en
fait que chaque ligne du panier (et de la commande) devrait pouvoir
recevoir une remise dans un champ dédié.

Ainsi l'application d'une remise consisterait donc à modifier le champ
'remise' sur les lignes du panier/de la commande.
Cela peut se combiner avec le fait d'ajouter une ligne 'Remise' avec
un prix nul, juste pour indiquer le libellé/la raison de la remise.

Mais de cette façon on aurait un prix ligne par ligne correct, avec
des taxes correctes.

Cela fait évoluer (un peu) le plugin commandes pour ajouter la colonne
supplémentaire 'remise'.
Du coup, dans la même optique on pourrait se contenter d'ajouter une
colonne 'remise' sur paniers_liens, comme pour le champ 'quantite', le
prix restant calculé par la fonction prix() pour l'affichage et la
transformation en commande.

Dans les 2 cas on fait évoluer la base et les squelettes d'affichage,
ainsi que la fonction de conversion du panier en commande.

Si les squelettes ont été surchargés, le champ remise ne sera pas pris
en compte, mais cela veut dire aussi qu'il n'est pas utilisé, donc à
zero, et on ne casse rien.

Des avis, des objections, des remarques, des questions ?

Le 30/05/2017 à 13:07, Cédric Morin a écrit :

A la phase de récapitulatif panier je veux pouvoir entrer un code de
réduction ou appliquer une remise.

[...]

Ainsi l'application d'une remise consisterait donc à modifier le champ
'remise' sur les lignes du panier/de la commande.
Cela peut se combiner avec le fait d'ajouter une ligne 'Remise' avec un
prix nul, juste pour indiquer le libellé/la raison de la remise.
Mais de cette façon on aurait un prix ligne par ligne correct, avec des
taxes correctes.

le champ supplémentaire "Remise" semble pas mal adapté pour une remise
du style "code de réduction" mais si on veut:
- une remise *par quantité* = "3% de réduction pour l'achat de 14 légumes"
- une remise *par lot* = "3% de réduction pour l'achat d'une patate,
d'un poireaux et d'une carotte"

=> cela reviendra t-il à modifier le champ "Remise" de l'ensemble des
produits du panier (patates, carottes, poireaux...) dès que j'atteins 14
légumes (ou la composition du lot) ?

(je précise que je n'ai pas pratiqué ce plugin mais j'ai eu à me
coltiner pas mal de boutiques en Prestashop alors voici mes 2 sous...

...en espérant ne pas être trop hors-sujet!)

cy_altern

Hello,

non en effet le champ remise sur chaque ligne du panier et de la commande permet de couvrir certains besoins (dont les miens là tout de suite), mais pas tous les cas génériques.

Pour tout couvrir il faut pouvoir ajouter un objet remise dans le panier, avec un prix qui dépend non pas de l'objet mais du panier, ce que ne sait pas du tout faire l'API prix utilisée actuellement pour calculer le prix des items du panier.

Probablement que la solution complète sera d'ajouter également les champs prix_ht et taxe sur les lignes du panier, en les laissant par défaut a null (=> comportement identique à actuellement : on prend le prix de l'objet donné par l'API prix()), mais en ayant la possibilité de les renseigner pour certains objets comme les remises/réductions, auquel cas ils seront alors pris en compte par l'API prix()

J'ai l'impression que les 2 sont complémentaires et que l'on ne peut de toute façon pas tout faire reposer sur l'une des 2 solutions pour couvrir tous les usages possibles.

--
Cédric

cy_altern a écrit :

Le 30/05/2017 à 13:07, Cédric Morin a écrit :

A la phase de récapitulatif panier je veux pouvoir entrer un code de
réduction ou appliquer une remise.

[...]

Ainsi l'application d'une remise consisterait donc à modifier le champ
'remise' sur les lignes du panier/de la commande.
Cela peut se combiner avec le fait d'ajouter une ligne 'Remise' avec un
prix nul, juste pour indiquer le libellé/la raison de la remise.
Mais de cette façon on aurait un prix ligne par ligne correct, avec des
taxes correctes.

le champ supplémentaire "Remise" semble pas mal adapté pour une remise
du style "code de réduction" mais si on veut:
  - une remise *par quantité* = "3% de réduction pour l'achat de 14 légumes"
  - une remise *par lot* = "3% de réduction pour l'achat d'une patate,
d'un poireaux et d'une carotte"

=> cela reviendra t-il à modifier le champ "Remise" de l'ensemble des
produits du panier (patates, carottes, poireaux...) dès que j'atteins 14
légumes (ou la composition du lot) ?

(je précise que je n'ai pas pratiqué ce plugin mais j'ai eu à me
coltiner pas mal de boutiques en Prestashop alors voici mes 2 sous...

...en espérant ne pas être trop hors-sujet!)

cy_altern

Salut

Je dirais que la problématique des remises doit se jouer au niveau
panier et au niveau commande. Un client peut avoir plusieurs remises à
un moment donné et joue alors pour savoir la/les quelles prendre.
Du coup à mon sens le choix de la remise ou des remises se fait au
niveau panier et au niveau commande le choix est figé.

Il semble aussi pertinent d'avoir plutôt un objet remise car elle peut
s'appliquer à un produit, à un groupe de produit, à un total de
panier, à la tête de la personne, ..... Une remise est rarement en
rapport direct avec un produit donné mais fait suite à une cascade
règles.

Au niveau commande il est possible de stocker pour chaque ligne le
prix avant et après remise et les remises associée. Ainsi on doit
pouvoir afficher à la commande la remise appliqué par produit ou bien
afficher en fin le total remisé (différence des totaux).
Au niveau panier il semble qu'il faille prévoir une jointure et que le
calcul du prix prennes en compte ces informations, toutefois au niveau
client, il est souvent plus lisible d'avoir une nouvelle ligne
"remise" qui ne fait pas la distinction produit par produit.

Considérer une remise comme un produit semble une fause bonne idée, ce
sont 2 concepts différents.
Si un objet remise existe, il faut aussi faire attention à figer ses
informations au moment de la commande pour ne pas voir son calcul
changer dans le temps.

Cela reste un gros morceau et compliqué à gérer simplement.

Km

Pour rappel d'abord, le principe général, c'est qu'un panier est théoriquement toujours dynamique, avec rien de fixé dedans, car à tout moment les prix peuvent changer. Par exemple quand il y a des soldes (donc là pas une réduction dédié à une personne précise mais sur le même produit pour tout le monde) jusqu'à une date horaire, quand la personne a juste mis en mémoire, si la date de la solde est dépassé, le prix change bien. En revanche, quand on a transformé en commande : c'est un devis, c'est contractuel, si on a "fixé" son panier dans une commande avant la fin des soldes, là les prix ne changent plus.

L'idée d'un champ remise dans chaque ligne du panier me parait convenir pour certains cas. Tant que tout reste bien dynamique, sans prix des objets fixés en dur.

Il est évident que ça ne peut gérer tous les cas, mais il y a tellement de types de remises différentes possibles, c'est normal. Il faudra sûrement plusieurs plugins différents pour gérer tous les types de remise (les soldes, les bons de réductions, les réductions dynamiques suivant le contenu du panier comme expliqué par cy_altern… etc).

La première chose qui me vient à l'esprit Cédric (et que tu as peut-être déjà fait hein), c'est : il faudrait regarder comment illes font dans Thelia et dans la suite de plugins Drupal Commerce. Ce sont les deux projets dont je me suis inspiré quand j'ai commencé à organiser en mini-plugins indépendants. Notamment Drupal Commerce qui est, comme tout dans Drupal, tout découpé en plein plein de plugins unitaires.

--
RastaPopoulos

Salut,

une réduction s’applique sur une ligne de la facture et s’exprime en pourcentage ( y pas à ce soucier de la TVA sur les réductions )

Une remise s’applique sur la facture globale au niveau de l’encart de somme à payer; en théorie elle à une origine ( facture d’acompte, facture d’avoir, geste commercial, coupon de réduction ) et un statut ( consommée si liée au paiement d’une facture )

Si tu fais un coupon de remise de 10€ avec une TVA de 10%. effectivement il faut connaître le taux de tva de chaque line et savoir si les conditions sont réunies pour que la remise s’applique au bas de la ‹ facture ›!

D’une manière général il faut absolument éviter les nombres négatifs sur les factures!

Cordialement

Merci pour ces précisions.

Je vais donc implémenter un champ "reduction" decimal sur les lignes des paniers et commandes, ce qui permettra de gérer cette partie là.

Pour les remises on verra plus tard :slight_smile:

--
Cédric

Pierre LASZCZAK a écrit :

Salut,

une réduction s'applique sur une ligne de la facture et s'exprime en
pourcentage ( y pas à ce soucier de la TVA sur les réductions )

Une remise s'applique sur la facture globale au niveau de l'encart de
somme à payer; en théorie elle à une origine ( facture d'acompte,
facture d'avoir, geste commercial, coupon de réduction ) et un statut (
consommée si liée au paiement d'une facture )

Si tu fais un coupon de remise de 10€ avec une TVA de 10%. effectivement
il faut connaître le taux de tva de chaque line et savoir si les
conditions sont réunies pour que la remise s'applique *au bas de la
'facture'!*

D'une manière général il faut absolument éviter les nombres négatifs sur
les factures!

Cordialement