[SPIP Zone] Prix en float dans les plugins Produits et Commandes ?

Hello,

Rastapopoulos, cerdic et autres qui utilisent les plugin produits et commandes, y'a t'il une raison pour que les prix soient en FLOAT ?

En fait un FLOAT est stocké différemment d'un DECIMAL dans Mysql, et ça peut poser des problèmes d'arrondis (vécu).
Le float est une valeur approximative, et plutôt utilisé pour tout ce qui est calcul scientifique.
Tout ce qui est mesures, monétaire etc devrait être en decimal.

Et même, dans le plugin commandes, sur la table commandes_detail :
   `prix_unitaire_ht` float NOT NULL DEFAULT 0,

alors que pour une réduction (qui représente une somme d'argent aussi) :
   `reduction` decimal(4,4) NOT NULL DEFAULT 0.0000,

Ça serait mieux de passer ces FLOAT en DECIMAL(15,4) par exemple.

En tout cas, moi c'est ce que je vais faire, au moins de mon côté.
Les galères d'un centime d'écart dans des calculs tous bêtes, j'ai vécu, c'est pas cool.

--
nicod_

J'ai aussi eu des problèmes d'arrondi dans les taxes de mes commandes (et du coup des factures :/)
Leur valeur était erronée dans spip_commandes_details : j'avais des 19.999%, des 20.001% et cie.

De mémoire, il me semble que le problème venait du fait que la taxe était *déduite* d'après le prix ht et le prix ttc au moment de la transformation du panier en commande.
Du coup il y a forcément des problèmes d'arrondi.
J'avais essayé d'augmenter la précision jusqu'à 6 décimales, mais le problème a demeuré.

J'ai contourné tout ça en récupérant la bonne valeur de la taxe de chaque objet au après la création de la commande (mes taxes sont enregistrées dans une table à part), avec je ne sais plus quel pipeline.

Bref, je ne sais pas si passer de float en decimal règlerait ce problème d'arrondi en particulier, mais si on peut gagner un peu en précision ça ne peut pas faire de mal !

Le 18/09/2017 à 19:43, nicod_ a écrit :

Hello,

Rastapopoulos, cerdic et autres qui utilisent les plugin produits et commandes, y'a t'il une raison pour que les prix soient en FLOAT ?

En fait un FLOAT est stocké différemment d'un DECIMAL dans Mysql, et ça peut poser des problèmes d'arrondis (vécu).
Le float est une valeur approximative, et plutôt utilisé pour tout ce qui est calcul scientifique.
Tout ce qui est mesures, monétaire etc devrait être en decimal.

Et même, dans le plugin commandes, sur la table commandes_detail :
`prix_unitaire_ht` float NOT NULL DEFAULT 0,

alors que pour une réduction (qui représente une somme d'argent aussi) :
`reduction` decimal(4,4) NOT NULL DEFAULT 0.0000,

Ça serait mieux de passer ces FLOAT en DECIMAL(15,4) par exemple.

En tout cas, moi c'est ce que je vais faire, au moins de mon côté.
Les galères d'un centime d'écart dans des calculs tous bêtes, j'ai vécu, c'est pas cool.

Salut

Bon j'allais dire le contraire, en partant du principe qu'on avait
toujours un problème de calcul du passage entre HT et TTC.

Chez Prestashop, il vont dans le même sens le prix est en
decimal(20,6) voir (20,4) pour les informations de prix en dur (genre
surcoût logistique sur un produit donné)

Km

Le 18/09/2017 à 20:28, Charles Razack a écrit :

J'ai aussi eu des problèmes d'arrondi dans les taxes de mes commandes (et du coup des factures :/)
Leur valeur était erronée dans spip_commandes_details : j'avais des 19.999%, des 20.001% et cie.

De mémoire, il me semble que le problème venait du fait que la taxe était *déduite* d'après le prix ht et le prix ttc au moment de la transformation du panier en commande.

Ça c'est pas top du tout :-/

J'ai contourné tout ça en récupérant la bonne valeur de la taxe de chaque objet au après la création de la commande (mes taxes sont enregistrées dans une table à part), avec je ne sais plus quel pipeline.

Merci d'avoir pointé ça, je me lance dans un projet ecommerce avec SPIP, je vais mettre le nez là dedans.

Bref, je ne sais pas si passer de float en decimal règlerait ce problème d'arrondi en particulier, mais si on peut gagner un peu en précision ça ne peut pas faire de mal !

Pour ce cas particulier je ne sais pas (la méthode est mauvaise) mais dans l'ensemble ce serait plus fiable.

--
nicod_

Le 19/09/2017 à 09:53, cam.lafit@azerttyu.net a écrit :

Salut

Bon j'allais dire le contraire, en partant du principe qu'on avait
toujours un problème de calcul du passage entre HT et TTC.

Chez Prestashop, il vont dans le même sens le prix est en
decimal(20,6) voir (20,4) pour les informations de prix en dur (genre
surcoût logistique sur un produit donné)

Prestashop, Thelia, Magento et oScommerce utilisent des DECIMAL avec plus ou moins de chiffres derrière la virgule (de 4 à 6) pour tous les prix stockés, valeurs de taxes etc.
Aucun float.

Dans ceux que je connais il n'y a que Dolibarr qui utilise des DOUBLE 24,8 (FLOAT avec plus de précision), mais bon, c'est pas une référence :slight_smile:

--
nicod_

Float or decimal for prices?
https://stackoverflow.com/questions/3768713/float-or-decimal-for-prices
"For money values, never never use binary float types - especially when you have a perfectly good decimal type available!"

Use Float or Decimal for Accounting Application Dollar Amount?
https://stackoverflow.com/questions/61872/use-float-or-decimal-for-accounting-application-dollar-amount
"The answer is easy. Never floats. NEVER !"

--
nicod_

Le 19/09/2017 à 14:14, nicod_ a écrit :

Float or decimal for prices?
mysql - Float or decimal for prices? - Stack Overflow
"For money values, never never use binary float types - especially when you have a perfectly good decimal type available!"

Use Float or Decimal for Accounting Application Dollar Amount?
sql server - Use float or decimal for accounting application dollar amount? - Stack Overflow

"The answer is easy. Never floats. NEVER !"

Ça concernerait donc les colonnes :

- commandes_detail.prix_unitaire_ht
- produits.prix_ht

à passer de FLOAT en DECIMAL(15,4) dans un upgrade.

D'autres avis ?

Rastapopoulos ? Cerdic ?

--
nicod_

Le 19/09/2017 à 19:51, nicod_ a écrit :

D'autres avis ?

Rastapopoulos ? Cerdic ?

Hello,

Moi mon avis c'est qu'il me semble qu'on en avait déjà parlé, ici même
sur cette liste, ou bien c'était à Toulouse ?, je ne sais plus mais je
suis sûr et certain qu'on a déjà parlé de ça, et que ça avait été plus
ou moins acté que oui, dans la todo, fallait changer PARTOUT (tous les
plugins du giron commerce quoi) pour des "decimal" dès que quelqu'un
avait le temps ou en avait besoin.

Donc bah oui, go go go à celleux qui peuvent le faire :slight_smile:

--
RastaPopoulos

Je suis pour

(ça va sans dire, mais vérifier qu'on ne pette rien à l'upgrade)

nicod_ a écrit :

Le 19/09/2017 à 14:14, nicod_ a écrit :

Float or decimal for prices?
mysql - Float or decimal for prices? - Stack Overflow
"For money values, never never use binary float types - especially
when you have a perfectly good decimal type available!"

Use Float or Decimal for Accounting Application Dollar Amount?
sql server - Use float or decimal for accounting application dollar amount? - Stack Overflow

"The answer is easy. Never floats. NEVER !"

Ça concernerait donc les colonnes :

- commandes_detail.prix_unitaire_ht
- produits.prix_ht

à passer de FLOAT en DECIMAL(15,4) dans un upgrade.

D'autres avis ?

Rastapopoulos ? Cerdic ?

Je reviens sur cette histoire car j'ai un cas concret.

Un produit vendu 1 € TTC avec une TVA à 5.5%

1 / 1.055 = 0,9478672986, avec un champ prix_ht en decimal 15,4 on stocke donc 0,9479

Si on en achète 200 ça coûte 200.01 €, tout ça pour une histoire d'arrondis : 0.9479 * 200 * 1.055 = 200,0069, soit 200.01 €

Je propose de passer tous les champs monétaires en DECIMAL(20,6) dans les plugins Commandes et Produits.

Et donc logiquement, dans les plugin Commandes et Paniers, je propose d'appeler les fonctions de calcul de prix avec une précision de 6 au lieu de 4 actuellement (dans Paniers) :
https://zone.spip.org/trac/spip-zone/browser/plugins/paniers/trunk/action/commandes_paniers.php#L123
ou de 3 (dans Commandes)
https://zone.spip.org/trac/spip-zone/browser/plugins/commandes/trunk/inc/commandes.php#L150

On aura une meilleure précision de façon générale.

Qu'en pensez vous ?

--
nicod_

Le 12/10/2017 à 21:31, nicod_ a écrit :

Je reviens sur cette histoire car j'ai un cas concret.

Un produit vendu 1 € TTC avec une TVA à 5.5%

1 / 1.055 = 0,9478672986, avec un champ prix_ht en decimal 15,4 on stocke donc 0,9479

Si on en achète 200 ça coûte 200.01 €, tout ça pour une histoire d'arrondis : 0.9479 * 200 * 1.055 = 200,0069, soit 200.01 €

Je propose de passer tous les champs monétaires en DECIMAL(20,6) dans les plugins Commandes et Produits.

Et donc logiquement, dans les plugin Commandes et Paniers, je propose d'appeler les fonctions de calcul de prix avec une précision de 6 au lieu de 4 actuellement (dans Paniers) :
Connexion · GitLab

ou de 3 (dans Commandes)
Connexion · GitLab

En tout cas, avec ça je retombe bien sur mes pieds.
Un produit à 0.947867 HT + TVA 5.5% * 200 me donne 200.00 € dans la commande.

Il faudrait monter à 200 000 unités pour que l'arrondi pose problème (0.947867 * 1.055 * 200000 = 199 999,937), ce qui laisse de la marge.

--
nicod_

Le 12/10/2017 à 21:49, nicod_ a écrit :

Le 12/10/2017 à 21:31, nicod_ a écrit :

Je reviens sur cette histoire car j'ai un cas concret.

Un produit vendu 1 € TTC avec une TVA à 5.5%

1 / 1.055 = 0,9478672986, avec un champ prix_ht en decimal 15,4 on stocke donc 0,9479

Si on en achète 200 ça coûte 200.01 €, tout ça pour une histoire d'arrondis : 0.9479 * 200 * 1.055 = 200,0069, soit 200.01 €

Je propose de passer tous les champs monétaires en DECIMAL(20,6) dans les plugins Commandes et Produits.

Et donc logiquement, dans les plugin Commandes et Paniers, je propose d'appeler les fonctions de calcul de prix avec une précision de 6 au lieu de 4 actuellement (dans Paniers) :
Connexion · GitLab
ou de 3 (dans Commandes)
Connexion · GitLab

En tout cas, avec ça je retombe bien sur mes pieds.
Un produit à 0.947867 HT + TVA 5.5% * 200 me donne 200.00 € dans la commande.

Il faudrait monter à 200 000 unités pour que l'arrondi pose problème (0.947867 * 1.055 * 200000 = 199 999,937), ce qui laisse de la marge.

Pour des calculs similaires de remise (pourcentages) et d'additions soustractions,
j'ai bien tâtonné et je suis parvenu à obtenir un arrangement satisfaisant
qui donne toujours les "bons" résultats tels qu'on les attends visuellement.
En BDD il y a le prix des produits en DECIMAL(9,2)
et le prix final en VARCHAR lisible et sympa donc avec 2 décimales également.
Ce qui a permis l'obtention des résultats, c'est pas DECIMAL mais l'*ordre*
dans lequel les calculs se font en PHP.

JLuc

Le 13/10/2017 à 08:19, JLuc a écrit :

Le 12/10/2017 à 21:49, nicod_ a écrit :

Le 12/10/2017 à 21:31, nicod_ a écrit :

Je reviens sur cette histoire car j'ai un cas concret.

Un produit vendu 1 € TTC avec une TVA à 5.5%

1 / 1.055 = 0,9478672986, avec un champ prix_ht en decimal 15,4 on stocke donc 0,9479

Si on en achète 200 ça coûte 200.01 €, tout ça pour une histoire d'arrondis : 0.9479 * 200 * 1.055 = 200,0069, soit 200.01 €

Je propose de passer tous les champs monétaires en DECIMAL(20,6) dans les plugins Commandes et Produits.

Et donc logiquement, dans les plugin Commandes et Paniers, je propose d'appeler les fonctions de calcul de prix avec une précision de 6 au lieu de 4 actuellement (dans Paniers) :
Connexion · GitLab
ou de 3 (dans Commandes)
Connexion · GitLab

En tout cas, avec ça je retombe bien sur mes pieds.
Un produit à 0.947867 HT + TVA 5.5% * 200 me donne 200.00 € dans la commande.

Il faudrait monter à 200 000 unités pour que l'arrondi pose problème (0.947867 * 1.055 * 200000 = 199 999,937), ce qui laisse de la marge.

Pour des calculs similaires de remise (pourcentages) et d'additions soustractions,
j'ai bien tâtonné et je suis parvenu à obtenir un arrangement satisfaisant
qui donne toujours les "bons" résultats tels qu'on les attends visuellement.
En BDD il y a le prix des produits en DECIMAL(9,2)
et le prix final en VARCHAR lisible et sympa donc avec 2 décimales également.
Ce qui a permis l'obtention des résultats, c'est pas DECIMAL mais l'*ordre*
dans lequel les calculs se font en PHP.

Concrètement en exemple voici la combinaison qui a été gagnante dans mon cas :

// Attention à l'ordre des calculs :
// avec les arrondis, il est très délicat de garder la cohérence entre prix public, remise et montant à payer
// en faisant comme ça, avec ces étapes, ça marche
$apayer = round ($prix - ($prix * $remise / 100), 2);
$remise_prix = round ($prix - $apayer, 2);

J'ai oublié de le dire, mais la remise a également un montant visible toujours sympa.

JL

Le 12/10/2017 à 21:31, nicod_ a écrit :

Je reviens sur cette histoire car j'ai un cas concret.

Un produit vendu 1 € TTC avec une TVA à 5.5%

1 / 1.055 = 0,9478672986, avec un champ prix_ht en decimal 15,4 on stocke donc 0,9479

Si on en achète 200 ça coûte 200.01 €, tout ça pour une histoire d'arrondis : 0.9479 * 200 * 1.055 = 200,0069, soit 200.01 €

Je propose de passer tous les champs monétaires en DECIMAL(20,6) dans les plugins Commandes et Produits.

Et donc logiquement, dans les plugin Commandes et Paniers, je propose d'appeler les fonctions de calcul de prix avec une précision de 6 au lieu de 4 actuellement (dans Paniers) :
Connexion · GitLab

ou de 3 (dans Commandes)
Connexion · GitLab

On aura une meilleure précision de façon générale.

Pas d'avis ?
Ou plutôt, pas de contre avis ?

--
nicod_

Le 17/10/2017 à 11:53, nicod_ a écrit :

Pas d'avis ?
Ou plutôt, pas de contre avis ?

Ok, c'est fait :

--
nicod_

Cool merci nicod_ !

Le 19/10/2017 à 17:00, nicod_ a écrit :

Le 17/10/2017 à 11:53, nicod_ a écrit :

Pas d'avis ?
Ou plutôt, pas de contre avis ?

Ok, c'est fait :
Connexion · GitLab

Le 19/10/2017 à 17:00, nicod_ a écrit :

Le 17/10/2017 à 11:53, nicod_ a écrit :

Pas d'avis ?
Ou plutôt, pas de contre avis ?

Ok, c'est fait :
Connexion · GitLab

Cool.

Je voulais voir aussi : cette modif engendre un affichage 'verbeux'. Ex. : 12,000000 (six zéros après la virgule)

Je me suis rendu compte que en activant en plus le plugin API Prix, il suffisait d'appliquer le filtre "prix_formater" pour retrouver un affichage de type 12.00 € (avec juste 2 zéros).

Bref, cela pose plusieurs questions :
1- les plugins qui proposent un champs 'prix' doivent-ils nécessiter le plugin API Prix ?
2- ou ne serait-il pas plus simple d'intégrer la fonction prix_formater dans le Core de SPIP
3- Tout cela ne résout pas le problème de l'affichage disgracieux en mode édition. J'ai pas trouvé comment faire ?

Cheers

Le 04/01/2018 à 12:54, Peetdu a écrit :

1- les plugins qui proposent un champs 'prix' doivent-ils nécessiter le plugin API Prix ?

API Prix surcharge la balise #PRIX en la formatant d'office avec un traitement, si on veut le prix brut dans un squelette il faut utiliser #PRIX*
C'est pratique, pour ne pas avoir à appliquer le filtre partout, mais pour moi ça doit donc rester un choix : utilise éventuellement, pas nécessite.

2- ou ne serait-il pas plus simple d'intégrer la fonction prix_formater dans le Core de SPIP

Dans le core de SPIP non plus, c'est trop spécifique, et elle ne me parait pas suffisamment stable.
J'ai dû la surcharger de mon côté, pour ne pas utiliser les locales (j'avais des résultats différents sur deux serveurs).

3- Tout cela ne résout pas le problème de l'affichage disgracieux en mode édition. J'ai pas trouvé comment faire ?

Ça peut poser problème d'arrondir le prix HT dans le input, parce que justement dans ce cas là tu peux perdre des décimales quand tu postes le formulaire.

Dans le back office de Prestashop (et d'autres), les prix sont affichés avec six décimales dans les formulaires, je n'ai jamais vu aucun retour là dessus.

https://screenshotscdn.firefoxusercontent.com/images/0e8f4ae3-49ec-4973-8426-70ff9c97e811.png

Si tes utilisateurs sont génés, et que la perte de décimales n'est pas un problème, un petit coup de js dans un de tes plugins qui reformate le prix au chargement ?

A tester (de tête) :

$('#champ_prix').val(parseFloat(Math.round($('#champ_prix').val()*100)/100).toFixed(2));

--
nicod_

Yop,

merci pour ces éclaircissements fort utiles :slight_smile:

Le 11/01/2018 à 13:25, nicod_ a écrit :

3- Tout cela ne résout pas le problème de l'affichage disgracieux en
mode édition. J'ai pas trouvé comment faire ?

Ça peut poser problème d'arrondir le prix HT dans le input, parce que
justement dans ce cas là tu peux perdre des décimales quand tu postes le
formulaire.

Dans le back office de Prestashop (et d'autres), les prix sont affichés
avec six décimales dans les formulaires, je n'ai jamais vu aucun retour
là dessus.

Concernant l'affichage, ci-joint un test avec le plugin Produits
voir : Akilia | Développeur SPIP Toulouse, Occitanie

Perso j'utilise deux choses pour remédier à cela

1- Si je dois utiliser la balise #PRIX, je filtre avec floatval
[(#PRIX|floatval) €]

du coup 12.000000 € devient 12
et 12.550000 € devient 12.55 €

2- dans le formulaire d'édition je filtre prix dans la fonction Charger

  $valeurs['prix'] = floatval($valeurs['prix']);

}

return $valeurs;

Le 12/01/2018 à 13:15, Peetdu a écrit :

Concernant l'affichage, ci-joint un test avec le plugin Produits
voir : Akilia | Développeur SPIP Toulouse, Occitanie

Perso j'utilise deux choses pour remédier à cela

1- Si je dois utiliser la balise #PRIX, je filtre avec floatval
[(#PRIX|floatval) €]

du coup 12.000000 € devient 12
et 12.550000 € devient 12.55 €

2- dans le formulaire d'édition je filtre prix dans la fonction Charger

 $valeurs\['prix'\] = floatval\($valeurs\['prix'\]\);


}

return $valeurs;

J'avoue qu'en mode affichage (ta deuxième capture), c'est moche.
Ça c'est parce que tu n'utilises pas le plugin API Prix.

Si tu regardes comment est affiché le prix :

[(#PRIX_HT*|appliquer_filtre{prix_formater,true})]

tu peux donc déclarer chez toi :

function filtre_prix_formater($prix){
  return floatval($prix);
}

Mais ça prendra le pas sur API Prix si tu l'installes après (il déclare filtre_prix_formater_dist).

En fait, il faudrait peut être modifier les squelettes de Produits pour qu'il n'affichent pas autant de décimales sans API Prix.
A discuter ?

PS : tu pourrais aussi utiliser number_format($prix,2) au lieu de floatval, pour avoir toujours deux décimales : 12.00 au lieu de 12

PS bis : tu sais qu'il y a un mode pour saisir les prix en TTC directement dans la config de Produits ?
Mais bon, ça change pas le problème.

--
nicod_