+- Crème CRM (https://www.cremecrm.com/forum)
+-- Forum : Développeurs (https://www.cremecrm.com/forum/forumdisplay.php?fid=10)
+--- Forum : Général (https://www.cremecrm.com/forum/forumdisplay.php?fid=11)
+--- Sujet : Solution pour modifier un module existant ? (/showthread.php?tid=61)
Re: Solution pour modifier un module existant ? - genglert - 05-06-2014
CremeAbstractEntity est un relicat datant d'il y a bien longtemps, mais plus forcément d'actualité en tant que classe mère des entités et des relations, dans la mesure où pas mal d'attributs hérités ne sont jamais utilisés par les relations. Mais comme quelques questions restent encore en suspend à propos des relations, ce nettoyage n'a pas encore eu lieu.
Dans l'absolu faire un contribute_to_model() sur CremeEntity ne pose pas trop de problème, SAUF avec les classes abstraites qui dérivent de CremeEntity (ce qui arrive seulement dans 'tickets'), à cause du conflit avec les classes abstraites dont j'ai déjà parlé. Pour un client j'avais utilisé contribute_to_model() pour ajouter un UUID à toutes les entités, et effectivement bien que la nouvelle ligne correspondant à ce champ était bien en base, les instances de Tickets ne "voyaient" pas ce nouveau champ ; les autres types d'entités fonctionnaient bien il me semble (car au final dans mon cas j'ai été obligé de modifier directement CremeEntity, ne voulant pas faire une croix sur 'tickets'). Je n'ai absolument aucune idée de ce qu'est votre problème de populate car vous ne donnez aucune info là dessus.
Vous pouvez aussi tout simplement créer un model ayant une ForeignKey vers CremeEntity ; même si potentiellement cela peut vous obliger à faire des jointures dans vos requêtes, ou bien des requêtes imbriquées, ou juste des requêtes supplémentaires, cela ne devient éventuellement un problème qu'avec un grand nombres d'objets (et encore faut-il prouver que les problèmes viennent de là).
En fait c'est _déjà_ ce que font les Propriétés (au sens Creme, pas Python), qui sont des sortes de tags typés. C'est un des concepts fondateurs de Creme, et elles sont donc bien intégrées à l'application. Vous devriez sûrement regarder de ce côté là.
Re: Solution pour modifier un module existant ? - Saga - 06-06-2014
Au départ je cherchais à faire quelque chose de ce genre.
Mais je n'avais pas compris à quoi pouvait servir les propriétés de Creme. Ça à l'air d'être une fonctionnalité très utile ! Je pense que ça pourrait s'utiliser pour remplir le besoin de tags mais après je n'ai pas trouvé de moyens d'effectuer une recherche par filtre comme il semble indiqué ici avec des filtres (?).
Pour l'erreur, je vais essayer de retrouver ça. J'éditerais ce message.
EDIT : Voilà :
Code :
$ python2.7 manage.py creme_populate
/usr/lib/python2.7/pkgutil.py:186: ImportWarning: Not importing directory '/usr/local/lib/python2.7/dist-packages/virtualenvwrapper': missing __init__.py
file, filename, etc = imp.find_module(subname, path)
disable populate for "creme.vcfs": No module named populate
disable populate for "creme.tags": No module named populate
populate "creme.creme_core" ...
populate "creme.creme_core" done.
populate "creme.creme_config" ...
populate "creme.creme_config" done.
populate "creme.media_managers" ...
populate "creme.media_managers" done.
populate "creme.documents" ...
populate "creme.documents" failed ('Folder' object has no attribute 'tags')
Traceback (most recent call last):
File "/home/makina/Documents/kseroux/tmp/creme/creme_core/management/commands/creme_populate.py", line 188, in _do_populate_action
getattr(populator, name)()
File "/home/makina/Documents/kseroux/tmp/creme/documents/populate.py", line 54, in populate
description=_(u"Folder containing all the documents related to entities")
File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 137, in create
return self.get_query_set().create(**kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 377, in create
obj.save(force_insert=True, using=self.db)
File "/home/makina/Documents/kseroux/tmp/creme/creme_core/models/entity.py", line 350, in save
super(CremeEntity, self).save(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 463, in save
self.save_base(using=using, force_insert=force_insert, force_update=force_update)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 506, in save_base
self.save_base(cls=parent, origin=org, using=using)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 551, in save_base
result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 203, in _insert
return insert_query(self.model, objs, fields, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 1592, in insert_query
query.insert_values(fields, objs, raw=raw)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/subqueries.py", line 170, in insert_values
value = getattr(obj, field.attname)
AttributeError: 'Folder' object has no attribute 'tags'
populate "creme.documents" done.
populate "creme.assistants" ...
populate "creme.assistants" done.
populate "creme.activities" ...
populate "creme.activities" done.
populate "creme.persons" ...
populate "creme.persons" failed ('Contact' object has no attribute 'tags')
Traceback (most recent call last):
File "/home/makina/Documents/kseroux/tmp/creme/creme_core/management/commands/creme_populate.py", line 188, in _do_populate_action
getattr(populator, name)()
File "/home/makina/Documents/kseroux/tmp/creme/persons/populate.py", line 166, in populate
user=admin, is_user=admin
File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 137, in create
return self.get_query_set().create(**kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 377, in create
obj.save(force_insert=True, using=self.db)
File "/home/makina/Documents/kseroux/tmp/creme/creme_core/models/entity.py", line 350, in save
super(CremeEntity, self).save(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 463, in save
self.save_base(using=using, force_insert=force_insert, force_update=force_update)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 506, in save_base
self.save_base(cls=parent, origin=org, using=using)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 551, in save_base
result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 203, in _insert
return insert_query(self.model, objs, fields, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 1592, in insert_query
query.insert_values(fields, objs, raw=raw)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/subqueries.py", line 170, in insert_values
value = getattr(obj, field.attname)
AttributeError: 'Contact' object has no attribute 'tags'
populate "creme.persons" done.
populate "creme.graphs" ...
populate "creme.graphs" done.
populate "creme.reports" ...
populate "creme.reports" done.
populate "creme.products" ...
populate "creme.products" done.
populate "creme.recurrents" ...
populate "creme.recurrents" done.
populate "creme.billing" ...
populate "creme.billing" failed ('Report' object has no attribute 'tags')
Traceback (most recent call last):
File "/home/makina/Documents/kseroux/tmp/creme/creme_core/management/commands/creme_populate.py", line 188, in _do_populate_action
getattr(populator, name)()
File "/home/makina/Documents/kseroux/tmp/creme/billing/populate.py", line 231, in populate
self.create_reports(rt_sub_bill_received, resulted, resulted_collection)
File "/home/makina/Documents/kseroux/tmp/creme/billing/populate.py", line 273, in create_reports
invoices_report = Report.objects.create(name=report_name, ct=invoice_ct, filter=current_year_invoice_filter, user=admin)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 137, in create
return self.get_query_set().create(**kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 377, in create
obj.save(force_insert=True, using=self.db)
File "/home/makina/Documents/kseroux/tmp/creme/creme_core/models/entity.py", line 350, in save
super(CremeEntity, self).save(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 463, in save
self.save_base(using=using, force_insert=force_insert, force_update=force_update)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 506, in save_base
self.save_base(cls=parent, origin=org, using=using)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 551, in save_base
result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 203, in _insert
return insert_query(self.model, objs, fields, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 1592, in insert_query
query.insert_values(fields, objs, raw=raw)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/subqueries.py", line 170, in insert_values
value = getattr(obj, field.attname)
AttributeError: 'Report' object has no attribute 'tags'
populate "creme.billing" done.
populate "creme.opportunities" ...
populate "creme.opportunities" failed ('Report' object has no attribute 'tags')
Traceback (most recent call last):
File "/home/makina/Documents/kseroux/tmp/creme/creme_core/management/commands/creme_populate.py", line 188, in _do_populate_action
getattr(populator, name)()
File "/home/makina/Documents/kseroux/tmp/creme/opportunities/populate.py", line 199, in populate
self.create_reports(rt_obj_emit_orga)
File "/home/makina/Documents/kseroux/tmp/creme/opportunities/populate.py", line 237, in create_reports
opp_report = Report.objects.create(name=report_name, ct=opp_ct, filter=opp_filter, user=admin)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 137, in create
return self.get_query_set().create(**kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 377, in create
obj.save(force_insert=True, using=self.db)
File "/home/makina/Documents/kseroux/tmp/creme/creme_core/models/entity.py", line 350, in save
super(CremeEntity, self).save(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 463, in save
self.save_base(using=using, force_insert=force_insert, force_update=force_update)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 506, in save_base
self.save_base(cls=parent, origin=org, using=using)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 551, in save_base
result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 203, in _insert
return insert_query(self.model, objs, fields, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 1592, in insert_query
query.insert_values(fields, objs, raw=raw)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/subqueries.py", line 170, in insert_values
value = getattr(obj, field.attname)
AttributeError: 'Report' object has no attribute 'tags'
# Inspired from
# https://www.cremecrm.com/forum/showthread.php?tid=18&pid=80#pid80
from django.db.models import Model, CharField
from django.utils.translation import ugettext_lazy as _
from creme.creme_core.utils.contribute_to_model import contribute_to_model
from creme.creme_core.models.entity import CremeEntity
class TaggedCremeEntity(Model):
tags = CharField(_("Tags"), max_length=200, blank=True)
Re: Solution pour modifier un module existant ? - genglert - 07-06-2014
Pour votre erreur cela ressemble à ce que je disais pour 'tickets', en revanche je ne sais pas pourquoi cela touche Contact & Report. Peut-être à cause de l'ordre dans laquelle les modèles sont construit par l'ORM (cela ne concerne visiblement pas que les classes abstraites en tous cas). J'avoue ne pas vraiment avoir le temps de creuser le problème ; on retiendra que contribute_to_model() est plutôt à réserver aux classes terminales, ce qui est le besoin classique (customiser légèrement Contact par exemple).
Le système de tag que vous indiquez est intéressant ; il serait peut être pertinent de rajouter la couleur aux propriétés Creme (ce qui serait assez trivial à faire). Les différences des propriétés avec des tags classique sont :
Les propriétés sont typées, ce qui permet de leur mettre des contraintes sur les types associés. Ppar exemple "VIP" qui ne serait ajoutable qu'aux Contacts.
Les types de Propriétés sont créés dans creme_config (ce qui nécessite certains droits), puis ces types sont utilisés pour ajouter les propriétés au entités. En gros les types ne sont pas créés à la volée lorsque qu'on ajoute des propriétés à une entité. Mais c'est un choix d'interface et pas une contrainte technique, vous pourriez facilement rajouter un champ dans les formulaire qui a un fonctionnement plus proche des tags classiques et qui utiliserait les CremePropertyType/CremeProperty derrière.
Pour la recherche, actuellement vous pouvez utiliser les propriétés depuis les filtres. Au dessus de chaque listview vous avez à gauche le choix du filtre (qui détermine les lignes/fiches affichées et celles qui ne le sont pas) et les vues (qui détermine les colonnes de votre liste : champ, relations, etc). Dans un filtre vous déterminez des conditions de diverses natures (par exemple: le prénom commence par 'Jean'), et parmi ces conditions il y a la présence/absence d'une propriété. Vous pour donc faire un filtre pour les Contacts "VIP" par exemple.
Après il serait sûrement intéressant d'avoir la possibilité de chercher en mode 'recherche rapide' (les champs de recherche que l'on trouve dans les entêtes de colonne des listes). Ça n'est pas très dur à faire, c'est juste que d'autres features nous ont occupé et qu'aucun client ne l'a réclamé.
De même les propriétés ne sont actuellement pas utilisées dans la recherche globale (le champ de recherche tout en haut dans chaque page). Je ne sais pas ce que vous chercher à obtenir, mais rajouter un champ de recherche globale sur les propriétés ne serait pas très compliqué.
Bon week end, je vais aller me coucher
Re: Solution pour modifier un module existant ? - Saga - 16-06-2014
Arfff, je n'avais pas vu que c'était à gauche la création de filtre, j'avais cherché pourtant...
En fait j'ai l'intention de pouvoir faire des recherches sur tags mais de manière global. Du coup j'ai considéré les propriétés comme des tags. Pourquoi créer un champ tag alors que les propriétés répondent à ce besoin ?
La recherche s'effectue sur une page de recherche avance accessible depuis le menu. L'algorithme de recherche semble fonctionner mais est clairement pas optimisé. Je pense qu'il y a beaucoup de travail de ce côté là (c.f. dépôt github).
Également, je cherche à créer un lien sur le popup lorsqu'on ajoute une propriété à une entité pour créer rapidement une propriété à la volé. Car le fait d'aller dans la configuration de crème, tout ça, casse vraiment la productivité d'un salarié. Niveau code le seul moyen que j'ai vu tout en faisant un module est de surcharger le template creme/creme_core/generics/blockform/base.html et vérifier le titre pour chaque langue, ce qui est vraiment pas propre du tout...
Là je vais voir si c'est possible de le faire mais à partir du module de création rapide en haut de page. EDIT : Apparement ça à l'air d'être assez simple à faire. Dommage que la doc ne parle pas des quick forms. Il serait bien aussi d'intégrer la création des propriétés et des relations directement dans le module de création rapide. Je pense que sont les seuls autres qui en ont le plus besoin.
Et merci encore de m'avoir consacré du temps.
Re: Solution pour modifier un module existant ? - genglert - 22-06-2014
Citation :Car le fait d'aller dans la configuration de crème, tout ça, casse vraiment la productivité d'un salarié
De notre expérience ce n'est pas un problème car en pratique les gens n'ont pas besoin de 5000 types de propriétés ; on les défini en général avec le client au début, et au pire un type est ajouté de temps en temps.
Après je veux bien croire que vous soyez accros aux tags et qu'aucun des outils ne vous permette mieux de gérer mieux votre workflow, mais n'ayant pas de détails il m'est impossible de vous conseiller une autre approche.
Citation :Là je vais voir si c'est possible de le faire mais à partir du module de création rapide en haut de page. EDIT : Apparement ça à l'air d'être assez simple à faire. Dommage que la doc ne parle pas des quick forms. Il serait bien aussi d'intégrer la création des propriétés et des relations directement dans le module de création rapide. Je pense que sont les seuls autres qui en ont le plus besoin.
Les quickforms sont conçus pour les entités, pas étonnant que vous n'y arriviez pas (il faudrait sûrement modifier le code du core pour y arriver). C'est vrai que je pourrais les ajouter dans la doc ; d'ailleurs je le note. Mais c'est vrai qu'à part cette subtilité, leur utilisation est assez triviale une fois qu'on a franchit la peur de regarder le code des apps existantes (ma doc permet de résoudre 90% des demandes triviales, et est un moyen de mettre le pied à l'étrier pour les problèmes plus pointus).
Citation :Également, je cherche à créer un lien sur le popup lorsqu'on ajoute une propriété à une entité pour créer rapidement une propriété à la volé. [... ] Niveau code le seul moyen que j'ai vu tout en faisant un module est de surcharger le template creme/creme_core/generics/blockform/base.html et vérifier le titre pour chaque langue, ce qui est vraiment pas propre du tout...
Je n'ai pas compris le coup du lien, ni celui du titre. À partir du moment où vous permettez à un utilisateur lambda de créer des CremePropertyTypes, pourquoi ne pas juste hooker le formulaire de création des CremeProperty (AddPropertiesForm dans creme/creme_core/forms.py) et lui ajouter un nouveau champ (voire plusieurs suivant l'ergonomie que vous imaginez) avec son éventuel widget personnalisé, et qui créerai en plus les nouvelles instances de CremePropertyTypes (et les CremeProperties associées évidemment).
Vous pourriez aussi hooker le formulaire de base de entités afin d'ajouter dès la création d'une entité ses propriétés (avec pareil création des nouveaux types).
Il serait peut-être intelligent que la recherche globale (l'input tout en haut de chaque page) cherche aussi dans les propriétés et pas seulement les champs normaux (j'en parlerai à mes collègues). Mais pour le coup votre recherche n'est pas "avancée", juste différente (par tags et non par contenu) .
Re: Solution pour modifier un module existant ? - Saga - 23-06-2014
genglert a écrit :
Citation :Car le fait d'aller dans la configuration de crème, tout ça, casse vraiment la productivité d'un salarié
De notre expérience ce n'est pas un problème car en pratique les gens n'ont pas besoin de 5000 types de propriétés ; on les défini en général avec le client au début, et au pire un type est ajouté de temps en temps.
Après je veux bien croire que vous soyez accros aux tags et qu'aucun des outils ne vous permette mieux de gérer mieux votre workflow, mais n'ayant pas de détails il m'est impossible de vous conseiller une autre approche.
Ça, je ne sais pas vraiment en pratique mais c'était une demande de mon entreprise.
genglert a écrit :Les quickforms sont conçus pour les entités, pas étonnant que vous n'y arriviez pas (il faudrait sûrement modifier le code du core pour y arriver).
Bah en fait non même pas. J'ai simplement créer un quickform avec presque les mêmes champs que le formulaire de CremePropertyType et puis je l'ai juste enregistrer dans le creme_core_register.py. Le tout en dehors du module creme_core. Ça m'a pris peu de temps et ça marche très bien (j'ai vérifié la cohérence avec les autres propriétés personnalisés dans la table creme property type).
genglert a écrit :
Citation :Également, je cherche à créer un lien sur le popup lorsqu'on ajoute une propriété à une entité pour créer rapidement une propriété à la volé. [... ] Niveau code le seul moyen que j'ai vu tout en faisant un module est de surcharger le template creme/creme_core/generics/blockform/base.html et vérifier le titre pour chaque langue, ce qui est vraiment pas propre du tout...
Je n'ai pas compris le coup du lien, ni celui du titre.
Je cherchais à faire quelque chose dans le genre :
[lien expiré]
Mais le widget en haut de page pour créer des fiches, ... est fait pour ça donc ce n'est plus nécessaire.
genglert a écrit :Mais pour le coup votre recherche n'est pas "avancée", juste différente (par tags et non par contenu) .
En fait elle propose de faire les deux en même temps ou l'un séparément de l'autre. De plus, elle propose également de sélectionner plusieurs fiches en même temps sans forcément toutes les sélectionner (voir arrière-plan de l'image).
[lien expiré]
genglert a écrit :Il serait peut-être intelligent que la recherche globale (l'input tout en haut de chaque page) cherche aussi dans les propriétés et pas seulement les champs normaux (j'en parlerai à mes collègues).
Le soucis que ça pose c'est que si on recherche une propriété qui s'appelle "est géré par crème", on va rechercher les termes "est", "par" dans les champs sélectionnés pour la recherche. On confondrait les propriétés et le contenu. Après pourquoi pas faire des recherches formatés du genre "test *ma propriété*", où test est à recherché parmi le contenu et ma propriété parmi les propriétés. Mais ce sera moins user-friendly. Il y a également un autre problème, c'est que la recherche propose soit de sélectionner une fiche, soit toutes. On ne peut pas en sélectionner uniquement 2. Après je n'ai pas encore trouvé de solution à ce dernier à pars faire à côté une "recherche avancé".
J'avais pensé à un autre système mais malheureusement je n'aurais pas le temps de le développer. Il s'agit d'une page list_view qui afficherait toutes les entités de tous les modèles. Elle présentera les champs qui sont commun comme les relations ou les propriétés et puis tous les champs qui sont recherchés. On pourrait ainsi filtrer par contenu, par propriété, ...
EDIT : Dans le même genre de la création rapide de propriété, il y avait un besoin pour mon entreprise de pouvoir ajouter des propriétés directement depuis le formulaire de création d'une entité. Du coup j'ai utilisé ma méthode du hooking de formulaire pour ajouter un champ permettant de sélectionner les propriétés à attribuer et ça à l'air de marcher.
Re: Solution pour modifier un module existant ? - genglert - 25-06-2014
Citation :Bah en fait non même pas. J'ai simplement créer un quickform avec presque les mêmes champs que le formulaire de CremePropertyType et puis je l'ai juste enregistrer dans le creme_core_register.py. Le tout en dehors du module creme_core. Ça m'a pris peu de temps et ça marche très bien (j'ai vérifié la cohérence avec les autres propriétés personnalisés dans la table creme property type).