Champ de type décimal

3.2
Tags: #<Tag:0x00007fc9f07a5758>
Champ de type décimal
0

(Sébastien Hardy) #1

Le champ décimal est modifiable, on peut y mettre la valeur 14 000 000 000,00 sans souci, et la sauvegarde se passe bien.

Mais si ce même champ contient 14 000 000 000,00 et qu’il est non modifiable, alors il n’est pas possible de sauvegarder. En effet le socle affiche bien 14 000 000 000,00 mais essaye de stocker 14E9.

Version : Simplicite 3.2


(Sébastien Hardy) #2

Autre point 1 : Le displayValue d’un decimal renvoie 14E6 et non pas 14 000 000
Autre point 2 : On peut paramétrer plus de 10 décimal mais le socle n’en affiche que 10.

Simplicite : 3.2

Cordialement,

Sébastien


(Sébastien Hardy) #3

Je vais réexpliquer mon premier point :

J’ai un acteur A qui peut saisir un montant en milliard et qui a deux champs en lecture seule (Taux de change et montant en euro)

J ai un acteur B qui peut saisir le taux de change et qui a deux champs en lecteur seule (Montant et montant en euro)

Le champs montant en euro est calculé à la volée

Scénario : L acteur A saisie le montant, l’acteur B saisie le taux, le montant en euro est calculé, l acteur B sauvegarde. (çà fonctionne). l’acteur B complète d autre données du formulaires et une erreur de type “Décimal non valide: Montant du financement en euro” apparaît.

Ce sont des champs de type décimaux
Simplicite 3.2, Mysql 5.7


(François Genestin) #4

Ok je vais tester ça et je reviens vers toi…


(François Genestin) #5

Il y a effectivement un problème de perte de précision/digit si le champ devient trop grand, à savoir dépasse la capacité d’un double.

En base et dans Simplicité 3.x, les montants sont hélas traités en “double”, il va falloir changer de précision en passant en BigDecimal au niveau Java + DECIMAL/NUMERIC en base de données afin de ne pas perdre en precision+scale (i.e. dans Simplicité en taille + précision après la virgule).

  • On va changer la précision des champs Float dans le moteur en utilisant le BigDecimal au lieu des doubles Java (les drivers SQL supportent désormais tous bien ce format). On limitera le scale (précision après la virgule à 32 digits = il sera possible de paramétrer un champ en taille 100, précision 32.

Impacts :

  • Le BigDecimal est largement supporté par tous les driver JDBC,et il offre les opérations de base (sauf le SQRT ou le POW(decimal) dans ces cas il faudra repasser par la double précision).

  • Il faut passer les colonnes physiques en DECIMAL(size, prec) sinon cela ne servira à rien. Le ALTER de Simplicité en cas de mise à jour du champ va être modifié en ce sens. On pourra ainsi supporter théoriquement le DECIMAL(100,32) maximum.

  • Enfin il va également falloir revoir les Tableaux croisés + Graphiques pour les passer en précision BigDecimal.

On va le faire sur la V4, et on backportera si possible ce qui est sans risque et opérationnel en 3.2 uniquement.


(François Genestin) #6

Il en va de même pour les champs “Integer”, on va devoir les passer en BIGINT / long.


(François Genestin) #7

Dernier point dans un champ calculé, l’expression simple :

[VALUE:test_montant] * [VALUE:test_taux]

continue d’être en double précision car l’interpréteur javascript va utiliser des doubles, avec risque de perte de précision/arrondis.

Il faudra donc revoir tous vos calculs et passer par les nouveaux accesseurs BigDecimal :

(function() {
var a = obj.getField(“test_montant”).getDecimal(); // BigDecimal
var b = obj.getField(“test_taux”).getDecimal(); // BigDecimal
return a.multiply(b);
})()

Ainsi avec des champs DECIMAL(100,32)

99 887 766 554 433 221 199,01234567890123456789012345678901 * 0,2000000000
= 19 977 553 310 886 644 239,80246913578024691357802469135780


(François Genestin) #8

Pour en revenir au pb d’affichage en format scientifique “E”,
merci de préciser où et comment est calculé le champ montant en euros.

Si le calcul est fait via des doubles c’est normal, il faut penser à reformater la valeur String en résultat, si on veut 2 chiffres après la virgules :

  • via Tool.toFormattedFloat(a * b, 20, 2, “FRA”)
  • ou via du code Java natif comme : new Formatter(Locale.US).format("%.2f", val).toString()

PS : dans la javadoc de Tool.toFormattedFloat, il est indiqué que la précision max est de 10.
Nous allons la passer à 32 dans un futur proche.


(Sébastien Hardy) #9

C’est calculé en javascript au changement du taux de change.(pour le coté dynamique :slight_smile: )
via une ressource associée à l’objet.


(François Genestin) #10

Merci pour cette précision, le pb de formatage client est donc un pb de votre code :

  1. cela me semble insuffisant car la donnée/event peut être modifiée à la main ou planter (via le debugger du navigateur). => Il faut donc également re-forcer la valeur côté serveur (au preValidate).

  2. Votre a*b en javascript client doit sûrement retourner un double et non un String formaté dans la langue de l’utilisateur (séparateur virgule en français et non un point qui doit expliquer le rejet). Le validate doit rejeter le format utilisateur.

Il faut donc que le script client renseigne le champ comme si l’utilisateur devait le saisir :
donc qq chose du style input.value = (a*b).toFixed(2).replace(".", “,”) s’il est en Français


(Sébastien Hardy) #11

Est ce que le BigDecimal a été implémenté ?


(François Genestin) #12

Voir les release notes des dernières versions 3.2 et 4.0.

  • en 3.2 : l’évolution est partielle pour limiter les impacts en évitant juste les erreurs de précision en base (int et float passent en long et decimal). il faut faire des alter sur les colonnes (en faisant une mise à jour qq sur le champs ou en re-important le module).

  • en 4.0 : création d’un nouveau type de champ (décimal 100,32) + tous les calculs back se font en big décimal (tableaux croisés)

Par contre, rien ne corrigera votre code = calcul javascript sur la page qui reste du double.
var total = parseFloat(montant) * parseFloat(prix);

Le big decimal n’étant pas supporté par les navigateurs, il faudra integrer un composant tiers à votre page ou appeler un service back qui fera le calcul via des BigDecimal java et résultat en String (par un objet externe appelé via $.ajax).


(Sébastien Hardy) #13

Ok merci, quand sera disponible la M06? sur la 3.2

Cordialement,


(David AZOULAY) #14

Il y a quelques modifications structurantes en finalisation/test, donc pas avant 1 ou 2 semaines