IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Odoo (ex-OpenERP) Discussion :

Champs calculé [V10]


Sujet :

Odoo (ex-OpenERP)

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2018
    Messages
    95
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2018
    Messages : 95
    Points : 79
    Points
    79
    Par défaut Champs calculé
    Bonjour,

    Voici mon champs calculé :

    Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
    half_pension_days_value = fields.Integer(string='Day value', copy=False, compute='convert_bin_dec')

    Voici ma fonction :

    Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        @api.multi
        def convert_bin_dec(self):
            if self.half_pension:
                print "Je suis dans la fonction convert"
                self.half_pension_days_value = 5

    Problème rencontré :

    Dés que je lance cette fonction grâce à l'état de mon booléen "half_pension", mon print se lance en boucle.
    Je suppose que le problème est à cette ligne -> self.half_pension_days_value = 5.

    Mais pourquoi ?

    EDIT : Le problème se trouve surement plus haut. Je surcharge la méthode create et write.

    Voici du code :

    Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # Appel cette méthode quand on créé un nouvel enregistrement (inscription cantine)
        @api.model
        def create(self, vals):
            record = super(ResPartnerSchool, self).create(vals)
            record.convert_bin_dec()
            return record
     
    # Appel cette méthode quand on modifie un enregistrement (inscription cantine)
        @api.multi
        def write(self, vals):
            result = super(ResPartnerSchool, self).write(vals)
            self.convert_bin_dec()
            return result



    Merci

  2. #2
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    168
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2002
    Messages : 168
    Points : 254
    Points
    254
    Par défaut
    Une boucle infinie ou un grand nombre de fois ?
    Tu es dans un api.multi, qui par définition peut contenir de multiples enregistrements (recordset) et tu ne boucles pas sur chacun pour vérifier si chacun à half_pension à True. Si dans une vue liste tu affiches le champ half_pension_days_value, il serait normal d'avoir autant de print que de données à l'écran. Une manière plus correcte de faire serait :

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
        @api.depends('half_pension')
        def convert_bin_dec(self):
            for record in self:
                if record.half_pension:
                    print "Je suis dans la fonction convert"
                    record.half_pension_days_value = 5

    Cela a pour intérêt :

    1. De définir half_pension_days_value pour chaque enregistrement en fonction de sa valeur ;
    2. De réagir automatiquement quand half_pension est modifié.

    Vis à vis de ton edit, il n'y a pas aucun intérêt à surcharger dans ce cas. L'usage de api.depends est suffisant.

  3. #3
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2018
    Messages
    95
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2018
    Messages : 95
    Points : 79
    Points
    79
    Par défaut
    Voici l'erreur que j'obtenais :
    RuntimeError: maximum recursion depth exceeded while calling a Python object
    C'était pas une boucle infini mais un grand nombre de fois oui

    Avec le décorateur @api.depends('half_pension'), ça fonctionne merci.
    Par contre je ne sais pas si ce décorateur sera efficace pour moi, le champs half_pension_days_value doit être calculé en fonction des champs cochés.

    Voici le code de ce que j'essaie de faire. Ce n'est pas très compliqué à comprendre. Par contre je ne vois pas comment on peut synchroniser le résultat de total_decimal avec half_pension_days_value selon les booléens cochés.

    Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    # Fonction qui permet de convertir en binaire
        @api.depends('half_pension')
        def convert_bin_dec(self):
            for record in self:
                if record.half_pension:
                    print "Je suis dans la fonction convert"
                    # on récupère les valeur booleenne pour chaque enregistrement
                    value_monday = self.half_pension_monday
                    value_tuesday = self.half_pension_tuesday
                    value_thursday = self.half_pension_thursday
                    value_friday = self.half_pension_friday
     
                    # On assigne une valeur si c'est True ou False à chaque jours
                    if value_monday:
                        monday_decimal = 1
                    else:
                        monday_decimal = 0
     
                    if value_tuesday:
                        tuesday_decimal = 2
                    else:
                        tuesday_decimal = 0
     
                    if value_thursday:
                        thursday_decimal = 8
                    else:
                        thursday_decimal = 0
     
                    if value_friday:
                        friday_decimal = 16
                    else:
                        friday_decimal = 0
     
                    # On fait le total
                    total_decimal = monday_decimal + tuesday_decimal + thursday_decimal + friday_decimal
                    record.half_pension_days_value = total_decimal

  4. #4
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    168
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2002
    Messages : 168
    Points : 254
    Points
    254
    Par défaut
    Dans ce cas il faut surveiller tous les champs utiles dans depends :

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        @api.depends('half_pension', 'half_pension_monday', 'half_pension_tuesday', 'half_pension_thursday', 'half_pension_friday')
        def convert_bin_dec(self):
            for record in self:
                pass

    N'oublie pas de convertir les self en record...

  5. #5
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2018
    Messages
    95
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2018
    Messages : 95
    Points : 79
    Points
    79
    Par défaut
    Génial ce décorateur. C'est interactif.

    Une dernière chose. Je n'avais pas posté tout mon code, mais la je vais en avoir besoin pour être le plus clair possible.
    Voici la liste de tous mes champs en questions
    Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        half_pension_days_value = fields.Integer(string='Day value', copy=False, store=True, compute='convert_bin_dec')
        half_pension_monday = fields.Boolean(string='Monday', copy=False, store=False)
        half_pension_tuesday = fields.Boolean(string='Tuesday', copy=False, store=False)
        half_pension_wednesday = fields.Boolean(string='Wednesday', copy=False, readonly="1", store=False)
        half_pension_thursday = fields.Boolean(string='Thursday', copy=False, store=False)
        half_pension_friday = fields.Boolean(string='Friday', copy=False, store=False)

    Le soucis avec le code actuel est que le résultat half_pension_days_value est en store=True mais m'affiche quand même 0 dans la base de données. Je suppose que c'est à cause des store=False des autres champs. Mais la difficulté est qu'il ne faut pas que j'enregistre mes jours en base de données, mais juste le résultat du total des jours.

    Aurais-tu une idée ? En tout cas merci beaucoup, je progresse rapidement grâce à toi depuis quelques semaines.


    Cordialement

  6. #6
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    168
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2002
    Messages : 168
    Points : 254
    Points
    254
    Par défaut
    Avec des champs non stockés, je pense que tu peux utiliser un champ classique, non calculé, et api.onchange (de la même manière que depends). Ainsi, il y aura une réaction uniquement locale, dans le navigateur de la personne pour fixer le champ que tu souhaites stocker.

  7. #7
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2018
    Messages
    95
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2018
    Messages : 95
    Points : 79
    Points
    79
    Par défaut
    Je me pose une question. Est-ce que la méthode write ou create comme cet exemple ->
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    record.student_ids.create(vals)
    est utilisée pour le coup ?
    Merci

  8. #8
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2018
    Messages
    95
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2018
    Messages : 95
    Points : 79
    Points
    79
    Par défaut
    La méthode avec le décorateur api.onchange() ne fonctionne pas pour moi. J'ai essayer avec ou sans le champ calculé.

    J'essaie donc la méthode write pour modifier directement ma valeur en base de données. Mais sans résultats non plus.

    Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
                    # On fait le total
                    total_decimal = monday_decimal + tuesday_decimal + thursday_decimal + friday_decimal
                    record.half_pension_days_value = total_decimal
     
                    resultat = record.half_pension_days_value.write({'half_pension_days_value', total_decimal})

    Voici l'erreur :
    AttributeError: 'int' object has no attribute 'write'

  9. #9
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    168
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2002
    Messages : 168
    Points : 254
    Points
    254
    Par défaut
    write s'utilise sur record directement. Et ne fonctionne pas dans un contexte onchange (il faut utiliser update à la place).
    Le problème c'est que je n'ai pas le contexte : il me faudrait le code de toute la classe et le code de toute la vue qui correspond pour comprendre à quel moment ce calcul doit intervenir et donc être stocké.

    (ps : je file en rendez-vous dans peu de temps, je ne pourrai y jeter un oeil que demain)

  10. #10
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2018
    Messages
    95
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2018
    Messages : 95
    Points : 79
    Points
    79
    Par défaut
    Merci pour ton aide. Je n'utilisais pas correctement le décorateur api.onchange(). A vrai dire, à la fin de ma fonction je retournais quelque chose et c'est logique qu'Odoo me sorte un message d'erreur

    Mon problème avec un api.onchange() est résolu.

    Pour l'instant je suis débloqué

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [V10] Récupérer la valeur d'un champ d'un autre modèle
    Par KevinH dans le forum Odoo (ex-OpenERP)
    Réponses: 6
    Dernier message: 27/09/2018, 10h41
  2. [V10] Récupérer les valeurs de champ dans un calcul de champ de relation
    Par KevinH dans le forum Odoo (ex-OpenERP)
    Réponses: 4
    Dernier message: 28/08/2018, 10h42
  3. [V10] Récupérer les valeurs du même enregistrement à partir d'un champ
    Par KevinH dans le forum Odoo (ex-OpenERP)
    Réponses: 2
    Dernier message: 21/08/2018, 14h08
  4. champ calculé
    Par tomm dans le forum Bases de données
    Réponses: 22
    Dernier message: 25/02/2004, 01h31
  5. [TQuery] champs calculés
    Par Amenofis dans le forum Bases de données
    Réponses: 2
    Dernier message: 07/01/2004, 15h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo