summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archaeological_files/forms.py2
-rw-r--r--archaeological_files/views.py9
-rw-r--r--archaeological_operations/import_from_csv.py12
-rw-r--r--archaeological_operations/views.py7
-rw-r--r--ishtar_common/admin.py4
-rw-r--r--ishtar_common/backend.py5
-rw-r--r--ishtar_common/forms_common.py43
-rw-r--r--ishtar_common/menu_base.py6
-rw-r--r--ishtar_common/migrations/0003_auto__del_field_person_person_type.py209
-rw-r--r--ishtar_common/models.py45
-rw-r--r--ishtar_common/templates/ishtar/dashboards/dashboard_main.html2
-rw-r--r--ishtar_common/views.py27
-rw-r--r--ishtar_common/widgets.py4
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'):