diff options
| author | Étienne Loks <etienne.loks@peacefrogs.net> | 2013-08-23 18:25:58 +0200 | 
|---|---|---|
| committer | Étienne Loks <etienne.loks@peacefrogs.net> | 2013-08-23 18:25:58 +0200 | 
| commit | 5cdbb2055adc8b23413b5e35ddb13635d5ad24c9 (patch) | |
| tree | 9743bec37b2c651fafecfc373a1d5bb8bc2aadc3 | |
| parent | db55fe482c5c428fdaca938efe380dc2060f8803 (diff) | |
| download | Ishtar-5cdbb2055adc8b23413b5e35ddb13635d5ad24c9.tar.bz2 Ishtar-5cdbb2055adc8b23413b5e35ddb13635d5ad24c9.zip | |
PersonType from single value to multi value for Person
| -rw-r--r-- | archaeological_files/forms.py | 2 | ||||
| -rw-r--r-- | archaeological_files/views.py | 9 | ||||
| -rw-r--r-- | archaeological_operations/import_from_csv.py | 12 | ||||
| -rw-r--r-- | archaeological_operations/views.py | 7 | ||||
| -rw-r--r-- | ishtar_common/admin.py | 4 | ||||
| -rw-r--r-- | ishtar_common/backend.py | 5 | ||||
| -rw-r--r-- | ishtar_common/forms_common.py | 43 | ||||
| -rw-r--r-- | ishtar_common/menu_base.py | 6 | ||||
| -rw-r--r-- | ishtar_common/migrations/0003_auto__del_field_person_person_type.py | 209 | ||||
| -rw-r--r-- | ishtar_common/models.py | 45 | ||||
| -rw-r--r-- | ishtar_common/templates/ishtar/dashboards/dashboard_main.html | 2 | ||||
| -rw-r--r-- | ishtar_common/views.py | 27 | ||||
| -rw-r--r-- | ishtar_common/widgets.py | 4 | 
13 files changed, 297 insertions, 78 deletions
| diff --git a/archaeological_files/forms.py b/archaeological_files/forms.py index 27617f8ad..544c89048 100644 --- a/archaeological_files/forms.py +++ b/archaeological_files/forms.py @@ -46,7 +46,7 @@ from ishtar_common import widgets  class FileSelect(TableSelect):      towns = get_town_field()      in_charge = get_person_field(label=_(u"Person in charge"), -                                 person_type='sra_agent') +                                 person_types=['sra_agent'])      file_type = forms.ChoiceField(label=_("File type"), choices=[])      saisine_type = forms.ChoiceField(label=_("Saisine type"), choices=[])      year = forms.IntegerField(label=_("Year")) diff --git a/archaeological_files/views.py b/archaeological_files/views.py index 1919d8b62..cda076cd9 100644 --- a/archaeological_files/views.py +++ b/archaeological_files/views.py @@ -35,11 +35,10 @@ from archaeological_operations.forms import ParcelFormSet  from forms import *  def autocomplete_file(request): -    person_types = request.user.ishtaruser.person.person_type -    if (not request.user.has_perm('ishtar_common.view_file', models.File) and \ -       not request.user.has_perm('ishtar_common.view_own_file', models.File) -       and not person_types.rights.filter(wizard__url_name='file_search' -                                                                     ).count()): +    person_types = person.person_type +    if not request.user.has_perm('ishtar_common.view_file', models.File) and \ +       not request.user.has_perm('ishtar_common.view_own_file', models.File) \ +       and not request.user.ishtaruser.has_right('file_search'):          return HttpResponse(mimetype='text/plain')      if not request.GET.get('term'):          return HttpResponse(mimetype='text/plain') diff --git a/archaeological_operations/import_from_csv.py b/archaeological_operations/import_from_csv.py index ff3bd11f4..1176aec4c 100644 --- a/archaeological_operations/import_from_csv.py +++ b/archaeological_operations/import_from_csv.py @@ -305,11 +305,11 @@ def parse_name_surname(value):          return q.all()[0]      else:          defaults = {'history_modifier':DEFAULT_PERSON, -                    'title':'', -                    'person_type':PersonType.objects.get( -                                txt_idx='head_scientist')} +                    'title':''}          defaults.update(values)          p = Person.objects.create(**defaults) +        p.person_types.add(PersonType.objects.get( +                                txt_idx='head_scientist'))          return p  def parse_person(surname, name, old_ref, owner): @@ -323,11 +323,11 @@ def parse_person(surname, name, old_ref, owner):          return q.all()[0]      else:          defaults = {'history_modifier':owner, -                    'title':'', -                    'person_type':PersonType.objects.get( -                                txt_idx='head_scientist')} +                    'title':''}          defaults.update(values)          p = Person.objects.create(**defaults) +        p.person_types.add(PersonType.objects.get( +                                txt_idx='head_scientist'))          return p  def parse_comment_addr_nature(nature, addr, owner): diff --git a/archaeological_operations/views.py b/archaeological_operations/views.py index c2e0b135c..97446b635 100644 --- a/archaeological_operations/views.py +++ b/archaeological_operations/views.py @@ -31,13 +31,11 @@ from forms import *  import models  def autocomplete_patriarche(request, non_closed=True): -    person_types = request.user.ishtaruser.person.person_type      if (not request.user.has_perm('ishtar_common.view_operation',                                    models.Operation)          and not request.user.has_perm('ishtar_common.view_own_operation',                                        models.Operation) -        and not person_types.rights.filter( -                                  wizard__url_name='operation_search').count()): +        and not request.user.ishtaruser.has_right('operation_search')):          return HttpResponse(mimetype='text/plain')      if not request.GET.get('term'):          return HttpResponse(mimetype='text/plain') @@ -60,8 +58,7 @@ def autocomplete_operation(request, non_closed=True):                                    models.Operation)          and not request.user.has_perm('ishtar_common.view_own_operation',                                        models.Operation) -        and not person_types.rights.filter( -                                  wizard__url_name='operation_search').count()): +        and not request.user.ishtaruser.has_right('operation_search')):          return HttpResponse(mimetype='text/plain')      if not request.GET.get('term'):          return HttpResponse(mimetype='text/plain') diff --git a/ishtar_common/admin.py b/ishtar_common/admin.py index b470f8223..fdff516f9 100644 --- a/ishtar_common/admin.py +++ b/ishtar_common/admin.py @@ -50,8 +50,8 @@ class OrganizationAdmin(HistorizedObjectAdmin):  admin.site.register(models.Organization, OrganizationAdmin)  class PersonAdmin(HistorizedObjectAdmin): -    list_display = ('name', 'surname', 'email', 'person_type') -    list_filter = ("person_type",) +    list_display = ('name', 'surname', 'email') +    list_filter = ("person_types",)      search_fields = ('name', 'surname', 'email',)      model = models.Person diff --git a/ishtar_common/backend.py b/ishtar_common/backend.py index f50edd708..297c96180 100644 --- a/ishtar_common/backend.py +++ b/ishtar_common/backend.py @@ -1,6 +1,6 @@  #!/usr/bin/env python  # -*- coding: utf-8 -*- -# Copyright (C) 2010-2011 Étienne Loks  <etienne.loks_AT_peacefrogsDOTnet> +# Copyright (C) 2010-2013 Étienne Loks  <etienne.loks_AT_peacefrogsDOTnet>  # This program is free software: you can redistribute it and/or modify  # it under the terms of the GNU Affero General Public License as @@ -50,8 +50,7 @@ class ObjectOwnPermBackend(object):              assert perm.split('.')[-1].split('_')[1] == 'own'          except (IndexError, AssertionError):              return False -        if ishtar_user.person.person_type \ -           == models.PersonType.objects.get(txt_idx="administrator"): +        if ishtar_user.has_right('administrator'):              return True          if obj is None:              model_name = perm.split('_')[-1].capitalize() diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py index 5078ffaae..db406aaa9 100644 --- a/ishtar_common/forms_common.py +++ b/ishtar_common/forms_common.py @@ -53,14 +53,15 @@ def get_town_field(label=_(u"Town"), required=True):           validators=[models.valid_id(models.Town)], label=label,           help_text=mark_safe(help_text), required=required) -def get_person_field(label=_(u"Person"), required=True, person_type=None): +def get_person_field(label=_(u"Person"), required=True, person_types=[]):      # !FIXME hard_link, reverse_lazy doen't seem to work with formsets      widget = None      url = "/" + settings.URL_PATH + 'autocomplete-person' -    if person_type: -        if isinstance(person_type, unicode) or isinstance(person_type, str): -            person_type = models.PersonType.objects.get(txt_idx=person_type) -        url += u"/" + unicode(person_type.pk) +    if person_types: +        person_types = [ +            unicode(models.PersonType.objects.get(txt_idx=person_type).pk) +                       for person_type in person_types] +        url += u"/" + u'_'.join(person_types)      widget = widgets.JQueryAutoComplete(url, associated_model=models.Person)      return forms.IntegerField(widget=widget, label=label, required=required,                                validators=[models.valid_id(models.Person)]) @@ -110,8 +111,7 @@ class PersonFormSelection(forms.Form):  class PersonForm(forms.Form):      form_label = _("Identity") -    associated_models = {'attached_to':models.Organization, -                         'person_type':models.PersonType} +    associated_models = {'attached_to':models.Organization}      title = forms.ChoiceField(label=_("Title"), choices=models.Person.TYPE)      surname = forms.CharField(label=_(u"Surname"), max_length=20,                                validators=[name_validator]) @@ -119,23 +119,15 @@ class PersonForm(forms.Form):                                validators=[name_validator])      email = forms.CharField(label=_(u"Email"), max_length=40, required=False,                              validators=[validators.validate_email]) -    person_type = forms.ChoiceField(label=_("Person type"), -                                  choices=[])      attached_to = forms.IntegerField(label=_("Current organization"), -  widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-organization'), -  associated_model=models.Organization, new=True), -  validators=[models.valid_id(models.Organization)], required=False) - -    def __init__(self, *args, **kwargs): -        super(PersonForm, self).__init__(*args, **kwargs) -        self.fields['person_type'].choices = models.PersonType.get_types() -        self.fields['person_type'].help_text = models.PersonType.get_help() +        widget=widgets.JQueryAutoComplete( +                    reverse_lazy('autocomplete-organization'), +                    associated_model=models.Organization, new=True), +        validators=[models.valid_id(models.Organization)], required=False)      def save(self, user):          dct = self.cleaned_data          dct['history_modifier'] = user -        dct['person_type'] = models.PersonType.objects.get( -                                                     pk=dct['person_type'])          if 'attached_to' in dct and dct['attached_to']:              dct['attached_to'] = models.Organization.objects.get(                                                       pk=dct['attached_to']) @@ -143,6 +135,19 @@ class PersonForm(forms.Form):          new_item.save()          return new_item +class PersonTypeForm(forms.Form): +    form_label = _("Person type") +    base_model = 'person_type' +    associated_models = {'person_type':models.PersonType} +    person_type = forms.MultipleChoiceField(label=_("Person type"), +                             choices=[], widget=forms.CheckboxSelectMultiple) + +    def __init__(self, *args, **kwargs): +        super(PersonTypeForm, self).__init__(*args, **kwargs) +        self.fields['person_type'].choices = models.PersonType.get_types( +                                                         empty_first=False) +        self.fields['person_type'].help_text = models.PersonType.get_help() +  class AccountForm(forms.Form):      form_label = _("Account")      associated_models = {'pk':models.Person} diff --git a/ishtar_common/menu_base.py b/ishtar_common/menu_base.py index 37f482219..11ce4e688 100644 --- a/ishtar_common/menu_base.py +++ b/ishtar_common/menu_base.py @@ -62,8 +62,7 @@ class MenuItem:                  return True          # manage by person type          if hasattr(user, 'ishtaruser'): -            person_type = user.ishtaruser.person.person_type -            if person_type.rights.filter(wizard__url_name=self.idx).count(): +            if ishtar_user.has_right(self.idx):                  return True          return False @@ -76,8 +75,7 @@ class MenuItem:                  return True          # manage by person type          if hasattr(user, 'ishtaruser'): -            person_type = user.ishtaruser.person.person_type -            if person_type.rights.filter(wizard__url_name=self.idx).count(): +            if ishtar_user.has_right(self.idx):                  return True          return False diff --git a/ishtar_common/migrations/0003_auto__del_field_person_person_type.py b/ishtar_common/migrations/0003_auto__del_field_person_person_type.py new file mode 100644 index 000000000..369568ecc --- /dev/null +++ b/ishtar_common/migrations/0003_auto__del_field_person_person_type.py @@ -0,0 +1,209 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + +    def forwards(self, orm): +        # Adding M2M table for field person_types on 'Person' +        db.create_table('ishtar_common_person_person_types', ( +            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), +            ('person', models.ForeignKey(orm['ishtar_common.person'], null=False)), +            ('persontype', models.ForeignKey(orm['ishtar_common.persontype'], null=False)) +        )) +        db.create_unique('ishtar_common_person_person_types', ['person_id', 'persontype_id']) + +        db.execute( +            'insert into ishtar_common_person_person_types (person_id, '\ +                                                           'persontype_id) '\ +                        'select id, person_type_id from ishtar_common_person') +        # Deleting field 'Person.person_type' +        db.delete_column('ishtar_common_person', 'person_type_id') + + + +    def backwards(self, orm): +        # User chose to not deal with backwards NULL issues for 'Person.person_type' +        raise RuntimeError("Cannot reverse this migration. 'Person.person_type' and its values cannot be restored.") +        # Removing M2M table for field person_types on 'Person' +        db.delete_table('ishtar_common_person_person_types') + + +    models = { +        'auth.group': { +            'Meta': {'object_name': 'Group'}, +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), +            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) +        }, +        'auth.permission': { +            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, +            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) +        }, +        'auth.user': { +            'Meta': {'object_name': 'User'}, +            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), +            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), +            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), +            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), +            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), +            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), +            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), +            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), +            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), +            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), +            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) +        }, +        'contenttypes.contenttype': { +            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, +            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) +        }, +        'ishtar_common.arrondissement': { +            'Meta': {'object_name': 'Arrondissement'}, +            'department': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Department']"}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'name': ('django.db.models.fields.CharField', [], {'max_length': '30'}) +        }, +        'ishtar_common.author': { +            'Meta': {'object_name': 'Author'}, +            'author_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.AuthorType']"}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Person']"}) +        }, +        'ishtar_common.authortype': { +            'Meta': {'object_name': 'AuthorType'}, +            'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), +            'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) +        }, +        'ishtar_common.canton': { +            'Meta': {'object_name': 'Canton'}, +            'arrondissement': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Arrondissement']"}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'name': ('django.db.models.fields.CharField', [], {'max_length': '30'}) +        }, +        'ishtar_common.department': { +            'Meta': {'ordering': "['number']", 'object_name': 'Department'}, +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'label': ('django.db.models.fields.CharField', [], {'max_length': '30'}), +            'number': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '3'}) +        }, +        'ishtar_common.historicalorganization': { +            'Meta': {'ordering': "('-history_date', '-history_id')", 'object_name': 'HistoricalOrganization'}, +            'address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'country': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}), +            'history_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), +            'history_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'history_modifier_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}), +            'history_type': ('django.db.models.fields.CharField', [], {'max_length': '1'}), +            'history_user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}), +            'id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'blank': 'True'}), +            'mobile_phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), +            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'organization_type_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}), +            'phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), +            'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), +            'town': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}) +        }, +        'ishtar_common.ishtaruser': { +            'Meta': {'object_name': 'IshtarUser', '_ormbases': ['auth.User']}, +            'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Person']", 'unique': 'True'}), +            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}) +        }, +        'ishtar_common.organization': { +            'Meta': {'object_name': 'Organization'}, +            'address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'country': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}), +            'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'mobile_phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), +            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'organization_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.OrganizationType']"}), +            'phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), +            'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), +            'town': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}) +        }, +        'ishtar_common.organizationtype': { +            'Meta': {'object_name': 'OrganizationType'}, +            'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), +            'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) +        }, +        'ishtar_common.person': { +            'Meta': {'object_name': 'Person'}, +            'address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'address_complement': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'attached_to': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Organization']", 'null': 'True', 'blank': 'True'}), +            'country': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}), +            'email': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), +            'history_modifier': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['auth.User']"}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'mobile_phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), +            'name': ('django.db.models.fields.CharField', [], {'max_length': '30'}), +            'person_types': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ishtar_common.PersonType']", 'symmetrical': 'False'}), +            'phone': ('django.db.models.fields.CharField', [], {'max_length': '18', 'null': 'True', 'blank': 'True'}), +            'postal_code': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}), +            'surname': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}), +            'title': ('django.db.models.fields.CharField', [], {'max_length': '2'}), +            'town': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}) +        }, +        'ishtar_common.persontype': { +            'Meta': {'object_name': 'PersonType'}, +            'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), +            'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'rights': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ishtar_common.WizardStep']", 'symmetrical': 'False'}), +            'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) +        }, +        'ishtar_common.sourcetype': { +            'Meta': {'object_name': 'SourceType'}, +            'available': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), +            'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'txt_idx': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) +        }, +        'ishtar_common.town': { +            'Meta': {'ordering': "['numero_insee']", 'object_name': 'Town'}, +            'canton': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Canton']", 'null': 'True', 'blank': 'True'}), +            'center': ('django.contrib.gis.db.models.fields.PointField', [], {'srid': '27572', 'null': 'True', 'blank': 'True'}), +            'departement': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Department']", 'null': 'True', 'blank': 'True'}), +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), +            'numero_insee': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '6'}), +            'surface': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}) +        }, +        'ishtar_common.wizard': { +            'Meta': {'ordering': "['url_name']", 'object_name': 'Wizard'}, +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'url_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}) +        }, +        'ishtar_common.wizardstep': { +            'Meta': {'ordering': "['wizard', 'order']", 'object_name': 'WizardStep'}, +            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +            'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), +            'order': ('django.db.models.fields.IntegerField', [], {}), +            'url_name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), +            'wizard': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ishtar_common.Wizard']"}) +        } +    } + +    complete_apps = ['ishtar_common'] diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 0155896f4..12b1b79f9 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -47,10 +47,9 @@ def post_save_user(sender, **kwargs):      else:          ishtaruser = q.all()[0]      if ishtaruser.is_superuser \ -       and ishtaruser.person.person_type.txt_idx != 'administrator': -        ishtaruser.person.person_type = PersonType.objects.get( -                                                    txt_idx='administrator') -        ishtaruser.person.save() +       and not ishtaruser.has_right('administrator'): +        ishtaruser.person.person_types.add(PersonType.objects.get( +                                                   txt_idx='administrator'))  post_save.connect(post_save_user, sender=User)  # HistoricalRecords enhancement: don't save identical versions @@ -193,16 +192,18 @@ class GeneralType(models.Model):          return u""      @classmethod -    def get_types(cls, dct={}, instances=False, exclude=[]): +    def get_types(cls, dct={}, instances=False, exclude=[], empty_first=True):          base_dct = dct.copy()          if hasattr(cls, 'parent'): -            return cls._get_parent_types(base_dct, instances, exclude=exclude) -        return cls._get_types(base_dct, instances, exclude=exclude) +            return cls._get_parent_types(base_dct, instances, exclude=exclude, +                                         empty_first=empty_first) +        return cls._get_types(base_dct, instances, exclude=exclude, +                              empty_first=empty_first)      @classmethod -    def _get_types(cls, dct={}, instances=False, exclude=[]): +    def _get_types(cls, dct={}, instances=False, exclude=[], empty_first=True):          dct['available'] = True -        if not instances: +        if not instances and empty_first:              yield ('', '--')          items = cls.objects.filter(**dct)          if exclude: @@ -237,9 +238,10 @@ class GeneralType(models.Model):                  yield sub_child      @classmethod -    def _get_parent_types(cls, dct={}, instances=False, exclude=[]): +    def _get_parent_types(cls, dct={}, instances=False, exclude=[], +                          empty_first=True):          dct['available'] = True -        if not instances: +        if not instances and empty_first:              yield ('', '--')          dct['parent'] = None          items = cls.objects.filter(**dct) @@ -395,10 +397,10 @@ class WizardStep(models.Model):  class UserDashboard:      def __init__(self): -        types = IshtarUser.objects.values('person__person_type', -                                          'person__person_type__label') +        types = IshtarUser.objects.values('person__person_types', +                                          'person__person_types__label')          self.types = types.annotate(number=Count('pk'))\ -                          .order_by('person__person_type') +                          .order_by('person__person_types')  class Dashboard:      def __init__(self, model): @@ -563,7 +565,7 @@ class Person(Address, OwnPerms) :                                 null=True)      name = models.CharField(_(u"Name"), max_length=30)      email = models.CharField(_(u"Email"), max_length=40, blank=True, null=True) -    person_type = models.ForeignKey(PersonType, verbose_name=_(u"Type")) +    person_types = models.ManyToManyField(PersonType, verbose_name=_(u"Types"))      attached_to = models.ForeignKey('Organization',                         verbose_name=_(u"Is attached to"), blank=True, null=True) @@ -584,6 +586,14 @@ class Person(Address, OwnPerms) :                                 if getattr(self, attr)]          return u" ".join(values) +    def has_right(self, right_name): +        if type(right_name) in (list, tuple): +            return bool( +              self.person_types.filter(txt_idx__in=right_name).count() or +              self.person_types.filter(wizard__url_name__in=right_name).count()) +        return bool(self.person_types.filter(txt_idx=right_name).count() or +                self.person_types.filter(wizard__url_name=right_name).count()) +      def full_label(self):          values = []          if self.title: @@ -613,10 +623,13 @@ class IshtarUser(User):              person_type = PersonType.objects.get(txt_idx='public_access')          person = Person.objects.create(title='Mr', surname=surname,                                         name=name, email=email, -                                       person_type=person_type,                                         history_modifier=user) +        person.person_types.add(person_type)          return IshtarUser.objects.create(user_ptr=user, person=person) +    def has_right(self, right_name): +       return self.person.has_right('administrator') +  class AuthorType(GeneralType):      class Meta:          verbose_name = _(u"Author type") diff --git a/ishtar_common/templates/ishtar/dashboards/dashboard_main.html b/ishtar_common/templates/ishtar/dashboards/dashboard_main.html index e710dbe16..a573a71c6 100644 --- a/ishtar_common/templates/ishtar/dashboards/dashboard_main.html +++ b/ishtar_common/templates/ishtar/dashboards/dashboard_main.html @@ -72,7 +72,7 @@        <tr><th>{% trans "User type" %}</th><th>{% trans "Number" %}</th></tr>      {% for user_type in ishtar_users.types %}        <tr> -        <td class='string'>{{user_type.person__person_type__label}}</td> +        <td class='string'>{{user_type.person.person_types.all.0.label}}{#TODO: Display all#}</td>          <td>{{user_type.number}}</td>        </tr>      {% endfor%} diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 346edc0d7..54d2e26a0 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -51,8 +51,9 @@ if settings.XHTML2ODT_PATH:  from menus import menu  from ishtar_common.forms import FinalForm -from ishtar_common.forms_common import PersonForm, PersonFormSelection,\ -                     AccountForm, FinalAccountForm, OrganizationForm, AuthorForm +from ishtar_common.forms_common import PersonForm, PersonTypeForm, \ +    PersonFormSelection, AccountForm, FinalAccountForm, OrganizationForm, \ +    AuthorForm  from ishtar_common.wizards import PersonWizard, PersonModifWizard, AccountWizard  import models @@ -75,6 +76,7 @@ def index(request):  person_creation_wizard = PersonWizard.as_view([                          ('identity-person_creation', PersonForm), +                        ('person_type-person_creation', PersonTypeForm),                          ('final-person_creation', FinalForm)],                           label=_(u"New person"),                           url_name='person_creation') @@ -82,6 +84,7 @@ person_creation_wizard = PersonWizard.as_view([  person_modification_wizard = PersonModifWizard.as_view([                        ('selec-person_modification', PersonFormSelection),                        ('identity-person_modification', PersonForm), +                      ('person_type-person_creation', PersonTypeForm),                        ('final-person_modification', FinalForm)],                         label=_(u"Person modification"),                         url_name='person_modification') @@ -108,12 +111,10 @@ def check_permission(request, action_slug, obj_id=None):          return menu.items[action_slug].is_available(request.user, obj_id)      return menu.items[action_slug].can_be_available(request.user) -def autocomplete_person(request, person_type=None): -    person_types = request.user.ishtaruser.person.person_type -    if (not request.user.has_perm('ishtar_common.view_person', models.Person) and -       not request.user.has_perm('ishtar_common.view_own_person', models.Person) -       and not person_types.rights.filter(wizard__url_name='person_search' -                                                                     ).count()): +def autocomplete_person(request, person_types=None): +    if not request.user.has_perm('ishtar_common.view_person', models.Person) and \ +       not request.user.has_perm('ishtar_common.view_own_person', models.Person) \ +       and not request.user.ishtaruser.has_right('person_search'):          return HttpResponse(mimetype='text/plain')      if not request.GET.get('term'):          return HttpResponse(mimetype='text/plain') @@ -127,11 +128,11 @@ def autocomplete_person(request, person_type=None):      for q in q.split(' '):          query = query & (Q(name__icontains=q) | Q(surname__icontains=q) | \                           Q(email__icontains=q)) -    if person_type: +    if person_types:          try: -            typs = [int(tp) for tp in person_type.split('_') if tp] +            typs = [int(tp) for tp in person_types.split('_') if tp]              typ = models.PersonType.objects.filter(pk__in=typs).all() -            query = query & Q(person_type__in=typ) +            query = query & Q(person_types__in=typ)          except (ValueError, ObjectDoesNotExist):              pass      limit = 20 @@ -465,13 +466,11 @@ def revert_item(model):      return func  def autocomplete_organization(request, orga_type=None): -    person_types = request.user.ishtaruser.person.person_type      if (not request.user.has_perm('ishtar_common.view_organization',                                   models.Organization) and \         not request.user.has_perm('ishtar_common.view_own_organization',                                   models.Organization) -       and not person_types.rights.filter(wizard__url_name='person_search' -                                                                     ).count()): +       and not request.user.ishtaruser.has_right('person_search')):          return HttpResponse(mimetype='text/plain')      if not request.GET.get('term'):          return HttpResponse(mimetype='text/plain') diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py index 157151413..82c0c0ac0 100644 --- a/ishtar_common/widgets.py +++ b/ishtar_common/widgets.py @@ -155,8 +155,8 @@ class JQueryAutoComplete(forms.TextInput):              attrs_select['value'] = val
              if self.associated_model:
                  try:
 -                    attrs_select['value'] = unicode(self.associated_model.\
 -objects.get(pk=value))
 +                    attrs_select['value'] = unicode(
 +                        self.associated_model.objects.get(pk=value))
                  except:
                      attrs_select['value'] = ""
          if not self.attrs.has_key('id'):
 | 
