Projet

Général

Profil

Development #39030

conséquence de l'evaluation "lazy" des champs wcs

Ajouté par Serghei Mihai il y a plus de 4 ans. Mis à jour il y a environ 4 ans.

Statut:
Fermé
Priorité:
Normal
Assigné à:
Version cible:
-
Début:
16 janvier 2020
Echéance:
% réalisé:

0%

Temps estimé:
Patch proposed:
Oui
Planning:
Non

Description

Suite au passage à l'évaluation "lazy" des champs certains formulaires et workflows peuvent rencontrer le souci signalé dans #38960: si le formulaire comporte les variables form_var_numero et form_var_numero_service, l'évaluation du champ form_var_numero_service est en fait l'évaluation d'un attribut service qui n'existe pas du champ form_var_numero.

Il risque d'y avoir pas mal de formulaires et workflows en production dans ce genre de situation et comme dit un CPF lyonnais:

sans vouloir en faire trop.. y'a moyen que ça mette un peu un gros bordel


Fichiers

Révisions associées

Révision dbe8ba56 (diff)
Ajouté par Serghei Mihai il y a environ 4 ans

workflows: clean context after workflow form action (#39030)

Révision 3d9fd7f2 (diff)
Ajouté par Serghei Mihai il y a environ 4 ans

workflows: clean context after workflow form action (#39030)

Historique

#1

Mis à jour par Stéphane Laget il y a plus de 4 ans

  • Description mis à jour (diff)
#2

Mis à jour par Frédéric Péters il y a plus de 4 ans

  • Tracker changé de Support à Development
  • Projet changé de Publik à w.c.s.
  • Statut changé de Nouveau à Information nécessaire
  • Assigné à mis à Serghei Mihai

'évaluation du champ form_var_numero_service est en fait l'évaluation d'un attribut service qui n'existe pas du champ form_var_numero.

Ça ne devrait pas être le cas et il y a des tests pour vérifier ce cas :

    formdef.name = 'foobarlazy'
...
    formdef.fields = [
        fields.StringField(id='0', label='string', varname='foo_foo'),
...
        fields.StringField(id='6', label='string2', varname='foo_foo_baz_baz'),
...
        assert context['form_var_foo_foo'] == 'bar'
...
        assert context['form_var_foo_foo_baz_baz'] == 'other'
...
#3

Mis à jour par Frédéric Péters il y a plus de 4 ans

(pour référence on a l'évaluation lazy sur les conditions de champs depuis qu'elles existent, quand même).

#4

Mis à jour par Benjamin Dauvergne il y a plus de 4 ans

  • Projet changé de w.c.s. à Publik
  • Assigné à changé de Serghei Mihai à Benjamin Dauvergne
  • Club mis à Non

On peut fermer ce ticket où quelqu'un a vraiment constaté ce comportement ?

#5

Mis à jour par Benjamin Dauvergne il y a plus de 4 ans

  • Projet changé de Publik à w.c.s.
  • Assigné à changé de Benjamin Dauvergne à Serghei Mihai
#6

Mis à jour par Serghei Mihai il y a environ 4 ans

  • Statut changé de Information nécessaire à En cours

Même souci signalé dans #38921: variable de formulare form_var_email et variable de workflow form_var_email_destinataire.
Dans la condition d'execution d'une action form_var_email_destinataire est évalué à None.

La différence par rapport au contenu du test mentionné plus haut est qu'une est une variable de formulaire et l'autre de workflow.

J'essaie de réproduire le problème.

#7

Mis à jour par Serghei Mihai il y a environ 4 ans

Réproduit dans ce test. Je me penche sur un correctif.

#8

Mis à jour par Frédéric Péters il y a environ 4 ans

Histoire de limiter les changements, il me semble qu'on peut :

@@ -580,14 +580,6 @@ def variable_test_data(pub):
         fields.StringField(id='1', label='string', varname='foo_foo_baz'),
     ]
     st_status = workflow.add_status('New', 'new')
-    jump = JumpWorkflowStatusItem()
-    jump.id = '_jump'
-    jump.by = ['_submitter', '_receiver']
-    jump.status = 'finished'
-    jump.parent = st_status
-
-    end_status = workflow.add_status('Finished', 'finished')
-    st_status.items.append(jump)
     workflow.store()

     FormDef.wipe()
#9

Mis à jour par Frédéric Péters il y a environ 4 ans

Mais non le test.

    workflow.fields = [
        fields.StringField(id='1', label='string', varname='foo_foo_baz'),
    ]

Ça ne veut rien dire, un workflow n'a pas d'attribut "fields", il peut avoir des champs sous variables_formdef (les options de workflow) ou backoffice_fields_formdef (les données de traitement).

#10

Mis à jour par Frédéric Péters il y a environ 4 ans

Et donc, à faire :

     workflow = Workflow(name='bar')
-    workflow.fields = [
-        fields.StringField(id='1', label='string', varname='foo_foo_baz'),
+    workflow.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(workflow)
+    workflow.backoffice_fields_formdef.fields = [
+        fields.StringField(id='bo1', label='string', varname='foo_foo_baz'),
     ]
     st_status = workflow.add_status('New', 'new')
#11

Mis à jour par Frédéric Péters il y a environ 4 ans

Et plus loin, je ne sais pas ce qui est cherché dans :

-    workflow.data = {
-        '1': 'workflow baz'
-    }

mais les données de traitement vont dans formdata.data, ce qui serait donc

+    formdata.data['bo1'] = 'workflow baz'
+    formdata.store()

et avec ça on obtient la valeur attendue lors de

+        assert context['form_var_foo_foo_baz'] == 'workflow baz'

Voilà donc, je ne sais pas comment l'analyse de la situation a procédé mais le test derrière ne correspond pas à une réalité.

#13

Mis à jour par Serghei Mihai il y a environ 4 ans

Formulaire et worklfow permettant de réproduire le problème.
Dans le statut "Choix du service destinataire", une fois un mail alternatif choisi il doit être affiché dans l'historique lors du passage dans le statut "Transmission de la demande".

#15

Mis à jour par Stéphane Laget il y a environ 4 ans

  • Description mis à jour (diff)
#16

Mis à jour par Serghei Mihai il y a environ 4 ans

Voici le test qui représente le cas qui arrive dans le workflow attaché: la source wcs.fields.ConditionVars rajoute les variables du formulaire dans le contexte comme form_var_email et c'est form_var_email_destinataire qui y est recherché.

#17

Mis à jour par Serghei Mihai il y a environ 4 ans

Je séche sur l'algo de recherche de la bonne valeur solution.
S'il y a des cerveaux plus rapides que le mien, je ne suis que preneur.

#18

Mis à jour par Frédéric Péters il y a environ 4 ans

Il y a moyen de commencer par un test qui corresponde à du vrai code exécuté, plutôt qu'un truc dont l'artificialité éloigne la réflexion ? (et je regarderai)

#19

Mis à jour par Serghei Mihai il y a environ 4 ans

Ok. Test avec action en backoffice qui provoque l'échec de calcul de la variable de traitement ayant le même espace de nommage qu'une variable du formulaire.

#20

Mis à jour par Benjamin Dauvergne il y a environ 4 ans

C'est très frustrant pour moi qu'on ne pousse pas une branche dans ce genre de cas, ça permet immédiatement de voir le problème en action sans avoir à appliquer le patch localement.

#21

Mis à jour par Frédéric Péters il y a environ 4 ans

Mais, pour continuer à essayer de comprendre les éléments en jeu; si je fais ça sur le test :

     formdef.fields = [
-        fields.StringField(id='0', label='Foo', varname='foo')
+        fields.StringField(id='0', label='Foo', varname='whatever')
     ]

toutes les explications passées, de confusion entre le champ du formulaire et la donnée de traitement, me laisseraient penser que ça devrait résoudre l'affaire. Et pourtant le test échoue quand même.

Je continue de déconstruire le test, comprendre les bouts, genre pourquoi donc un firstof, et à force de déconstruire,

-    st2.items.append(jump)
     st2.items.append(setbo)
+    st2.items.append(jump)

que la donnée de traitement soit posée avant le saut, vu que le saut est basé sur la condition.

Et enfin, à ce moment, le test semble rejoindre ce qui est cherché.

De là, répondre que non le firstof n'a pas de rapport,

-    setbo.fields = [{'field_id': 'bo1', 'value': '{% firstof local_var_str2 local_var_str1 %}'}]
+    setbo.fields = [{'field_id': 'bo1', 'value': 'go'}]

et en arriver juste à faire comme à l'édition d'une demande, l'appel à clean_submission_context(),

@@ -216,6 +216,7 @@ class FormWorkflowStatusItem(WorkflowStatusItem):
         if form.get_submit() == 'submit' and not form.has_errors():
             self.evaluate_live_form(form, formdata, user)
             formdata.store()
+        get_publisher().substitutions.unfeed(lambda x: x.__class__.__name__ == 'ConditionVars')

     def get_parameters_view(self):
#24

Mis à jour par Benjamin Dauvergne il y a environ 4 ans

J'ai lié aux tickets #37017 et #37093 parce qu'on a jamais trouvé la source du problème et j'aimerai comprendre.

#25

Mis à jour par Serghei Mihai il y a environ 4 ans

  • Statut changé de Solution proposée à Solution validée
  • Assigné à changé de Serghei Mihai à Frédéric Péters

Frédéric Péters a écrit :

[...]

que la donnée de traitement soit posée avant le saut, vu que le saut est basé sur la condition.

Effectivement je me suis melé les pinceaux dans l'ordre de déclaration des actions. Et le firsof était pour me rapprocher du workflow joint plus haut. Une simple affectation suffisait.

et en arriver juste à faire comme à l'édition d'une demande, l'appel à clean_submission_context(),

Ma première idée fut de trouver une solution au niveau de l'algo de recherche du champ dans le contexte alimenté par toutes les sources.
Mais seule ConditionsVars empêche de remonter jusqu'à form dans le contexte et ta solution me paraît bien.

#26

Mis à jour par Frédéric Péters il y a environ 4 ans

  • Statut changé de Solution validée à Résolu (à déployer)
commit dbe8ba569ca397a6d4d9996b0a3f07631a3ba4db
Author: Serghei Mihai <smihai@entrouvert.com>
Date:   Mon Jan 27 20:10:03 2020 +0100

    workflows: clean context after workflow form action (#39030)
#27

Mis à jour par Serghei Mihai il y a environ 4 ans

  • Statut changé de Résolu (à déployer) à Solution déployée
#28

Mis à jour par Thomas Noël il y a environ 4 ans

Envoyé sur hotfix/v4.46

Formats disponibles : Atom PDF