model = PersonActivity
fk_name = 'person'
+ filter_horizontal = ['organizations', 'employers', 'teams', 'projects', 'supervisors', 'phd_directors', ]
class PersonPlaylistInline(TabularDynamicInlineAdmin):
class PersonAdmin(BaseTranslationOrderedModelAdmin):
model = Person
- inlines = [PersonActivityInline,
- PersonImageInline,
+ inlines = [PersonImageInline,
PersonBlockInline,
PersonPlaylistInline,
PersonLinkInline,
- PersonFileInline ]
+ PersonFileInline,
+ PersonActivityInline,]
first_fields = ['last_name', 'first_name', 'title', 'gender', 'user']
search_fields = ['last_name', 'first_name']
list_display = ['last_name', 'first_name', 'description', 'email', 'gender']
list_filter = ['person_title', 'activities__date_from', 'activities__date_to',
'activities__is_permanent', 'activities__framework', 'activities__grade',
- 'activities__function', 'activities__team',]
+ 'activities__function', 'activities__teams',]
-class PersonActivityAdmin(admin.ModelAdmin):
+class PersonActivityAdmin(BaseTranslationModelAdmin):
model = PersonActivity
- list_display = ['person', 'team', 'status', 'date_from', 'date_to']
+ list_display = ['person', 'get_teams', 'status', 'date_from', 'date_to']
+ filter_horizontal = ['organizations', 'employers', 'teams', 'projects', 'supervisors', 'phd_directors', ]
+
+ def get_teams(self, instance):
+ values = []
+ for team in instance.teams.all():
+ print(team.code)
+ values.append(team.code)
+ return ' - '.join(values)
class PersonListBlockInlineAdmin(TabularDynamicInlineAdmin):
self.person, c = Person.objects.get_or_create(title=title, first_name=first_name, last_name=last_name)
self.activity = PersonActivity(person=self.person)
- def get_identity(self, ):
+ def set_identity(self, ):
gender = self.row[2].value
if gender == 'H':
self.person.gender = 'male'
self.person.save()
- def get_or_create_name(self, model, column_id):
- return model.objects.get_or_create(name=self.row[column_id].value)[0] if self.row[column_id].value else None
-
- def split_names(self, names):
- name_list = []
- for spliter in self.spliters:
- if spliter in names:
- name_list = names.split(spliter)
- if name_list:
- for map(str.strip, name_list)
- return name_list
- return names
-
def get_person(self, value):
if value:
name_exceptions = ['de', 'von']
return person
return None
- def get_team(self, code):
- code = str(code)
- qs = Q(code=code) | Q(code=code.lower()) | Q(code=code.upper()) | Q(code=code.capitalize())
- teams = Team.objects.filter(qs)
- if teams:
- return teams[0]
-
- qs = Q(title=code) | Q(title=code.lower()) | Q(title=code.upper()) | Q(title=code.capitalize())
- projects = Project.objects.filter(qs)
- if projects:
- self.activity.project = projects[0]
- return None
- return None
+ def get_or_create_name(self, model, column_id):
+ value = self.row[column_id].value if self.row[column_id].value else None
+ obj = None
+ if value:
+ try:
+ obj, c = model.objects.get_or_create(name=value)
+ except:
+ obj = model(name=value)
+ obj.save()
+ return obj
- def get_activity(self):
+ def split_names(self, names):
+ name_list = []
+ for spliter in self.spliters:
+ if spliter in names:
+ name_list = names.split(spliter)
+ if name_list:
+ name_list = map(str.strip, name_list)
+ return name_list
+ return [names,]
+
+ def add_many(self, field, model, column_id, type='name'):
+ values = self.row[column_id].value if self.row[column_id].value else None
+ if values:
+ for value in self.split_names(values):
+ if type == 'name':
+ qs = Q(name=value) | Q(name=value.lower()) | Q(name=value.upper()) | Q(name=value.capitalize())
+ obj = model(name=value)
+ elif type == 'code':
+ qs = Q(code=value) | Q(code=value.lower()) | Q(code=value.upper()) | Q(code=value.capitalize())
+ obj = model(code=value)
+ elif type == 'title':
+ qs = Q(title=value) | Q(title=value.lower()) | Q(title=value.upper()) | Q(title=value.capitalize())
+ obj = model(title=value)
+ elif type == 'person':
+ obj = self.get_person(value)
+ qs = None
+ if qs:
+ objects = model.objects.filter(qs)
+ if objects:
+ obj = objects[0]
+ else:
+ obj.save()
+ else:
+ obj.save()
+ field.add(obj)
+
+ def set_activity(self):
self.activity.date_from = datetime.datetime(*xlrd.xldate_as_tuple(self.row[4].value, self.datemode)) if self.row[4].value else None
self.activity.date_to = datetime.datetime(*xlrd.xldate_as_tuple(self.row[5].value, self.datemode)) if self.row[5].value else None
try:
self.activity.is_permanent = True if self.row[11].value else False
self.activity.framework = self.get_or_create_name(ActivityFramework, 12)
self.activity.grade = self.get_or_create_name(ActivityGrade, 13)
+ self.activity.save()
- self.activity.employer = self.get_or_create_name(Organization, 14)
- self.activity.attachment_organization = self.get_or_create_name(Organization, 15)
- self.activity.second_employer = self.get_or_create_name(Organization, 16)
+ self.add_many(self.activity.employers, Organization, 14)
+ self.add_many(self.activity.organizations, Organization, 15)
+ self.add_many(self.activity.employers, Organization, 16)
self.activity.umr = self.get_or_create_name(UMR, 17)
- self.activity.team = self.get_team(self.row[19].value)
- try:
- self.activity.second_team = self.get_team(self.row[21].value)
- except:
- self.activity.second_team_text = self.row[21].value
- self.activity.project, c = Project.objects.get_or_create(title=self.row[22].value) if self.row[22].value else (None, False)
+ self.add_many(self.activity.teams, Team, 19, type='code')
+ self.add_many(self.activity.teams, Team, 21, type='code')
+ self.add_many(self.activity.projects, Project, 22, type='title')
quota = self.row[23].value
try:
self.activity.rd_quota_text = str(quota)
self.activity.phd_doctoral_school = self.get_or_create_name(Organization, 25)
- self.activity.phd_director = self.get_person(self.row[26].value)
- self.activity.phd_officer_1 = self.get_person(self.row[27].value)
- self.activity.phd_officer_2 = self.get_person(self.row[28].value)
+ if self.activity.phd_doctoral_school:
+ self.activity.phd_doctoral_school.type, c = OrganizationType.objects.get_or_create(name='Ecole doctorale')
+ self.activity.phd_doctoral_school.save()
+ self.add_many(self.activity.phd_directors, Person, 26, type='person')
+ self.add_many(self.activity.supervisors, Person, 27, type='person')
+ self.add_many(self.activity.supervisors, Person, 28, type='person')
self.activity.training_type = self.get_or_create_name(TrainingType, 29)
self.activity.training_level = self.get_or_create_name(TrainingLevel, 30)
self.activity.training_speciality = self.get_or_create_name(TrainingSpeciality, 32)
self.activity.function = self.get_or_create_name(ActivityFunction, 34)
- if self.activity.phd_director:
+ if self.activity.phd_directors:
self.activity.phd_title = self.row[35].value
try:
self.activity.phd_defense_date = datetime.datetime(*xlrd.xldate_as_tuple(self.row[38].value, self.datemode)) if self.row[38].value else None
except:
pass
- self.activity.phd_postdoctoralsituation = self.row[39].value
+ self.activity.phd_post_doctoral_situation = self.row[39].value
elif self.activity.training_type:
self.activity.training_title = self.row[35].value
class Command(BaseCommand):
- help = """Import Person data from IRCAM's legacy XLS management file"""
+ help = """Import Person data from IRCAM's legacy XLS management file.
+ python manage.py import-ircam-person-xls -s /srv/backup/TB_personnel_GP-GM_4.xls
+ """
option_list = BaseCommand.option_list + (
make_option('-d', '--dry-run',
xls = IrcamXLS(self.source_file)
for i in range(xls.first_row, xls.size):
p = IrcamPerson(xls.sheet.row(i), xls.book.datemode)
- p.get_identity()
- p.get_activity()
+ p.set_identity()
+ p.set_activity()
--- /dev/null
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.10 on 2016-11-04 13:24
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('organization-network', '0046_auto_20161026_1025'),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name='personactivity',
+ old_name='phd_postdoctoralsituation',
+ new_name='phd_post_doctoral_situation',
+ ),
+ migrations.RemoveField(
+ model_name='personactivity',
+ name='attachment_organization',
+ ),
+ migrations.RemoveField(
+ model_name='personactivity',
+ name='employer',
+ ),
+ migrations.RemoveField(
+ model_name='personactivity',
+ name='phd_officers',
+ ),
+ migrations.RemoveField(
+ model_name='personactivity',
+ name='second_employer',
+ ),
+ migrations.RemoveField(
+ model_name='personactivity',
+ name='second_team',
+ ),
+ migrations.RemoveField(
+ model_name='personactivity',
+ name='second_team_text',
+ ),
+ migrations.RemoveField(
+ model_name='personactivity',
+ name='team',
+ ),
+ migrations.RemoveField(
+ model_name='personactivity',
+ name='third_employer',
+ ),
+ migrations.AddField(
+ model_name='personactivity',
+ name='employers',
+ field=models.ManyToManyField(blank=True, related_name='employer_project_activities', to='organization-network.Organization', verbose_name='employers'),
+ ),
+ migrations.AddField(
+ model_name='personactivity',
+ name='organization',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='project_activities', to='organization-network.Organization', verbose_name='organization (attachment or subscribed)'),
+ ),
+ migrations.AddField(
+ model_name='personactivity',
+ name='supervisors',
+ field=models.ManyToManyField(blank=True, related_name='supervisor_activities', to='organization-network.Person', verbose_name='supervisors'),
+ ),
+ migrations.AddField(
+ model_name='personactivity',
+ name='team_text',
+ field=models.CharField(blank=True, max_length=256, null=True, verbose_name='other team text'),
+ ),
+ migrations.AddField(
+ model_name='personactivity',
+ name='teams',
+ field=models.ManyToManyField(blank=True, related_name='team_activities', to='organization-network.Team', verbose_name='teams'),
+ ),
+ migrations.AlterField(
+ model_name='personactivity',
+ name='rd_quota_float',
+ field=models.FloatField(blank=True, null=True, verbose_name='R&D quota (float)'),
+ ),
+ ]
--- /dev/null
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.10 on 2016-11-04 13:45
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('organization-network', '0047_auto_20161104_1424'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='organization',
+ name='mappable_location',
+ field=models.CharField(blank=True, help_text='This address will be used to calculate latitude and longitude. Leave blank and set Latitude and Longitude to specify the location yourself, or leave all three blank to auto-fill from the Location field.', max_length=128, null=True),
+ ),
+ ]
--- /dev/null
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.10 on 2016-11-04 13:53
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('organization-network', '0048_auto_20161104_1445'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='personactivity',
+ name='organization',
+ ),
+ migrations.AddField(
+ model_name='personactivity',
+ name='organizations',
+ field=models.ManyToManyField(blank=True, related_name='project_activities', to='organization-network.Organization', verbose_name='organizations (attachment or subscribed)'),
+ ),
+ ]
class Organization(Named, Address, URL, AdminThumbRelatedMixin):
"""(Organization description)"""
- mappable_location = models.CharField(max_length=128, blank=True, help_text="This address will be used to calculate latitude and longitude. Leave blank and set Latitude and Longitude to specify the location yourself, or leave all three blank to auto-fill from the Location field.")
+ mappable_location = models.CharField(max_length=128, blank=True, null=True, help_text="This address will be used to calculate latitude and longitude. Leave blank and set Latitude and Longitude to specify the location yourself, or leave all three blank to auto-fill from the Location field.")
lat = models.DecimalField(max_digits=10, decimal_places=7, blank=True, null=True, verbose_name="Latitude", help_text="Calculated automatically if mappable location is set.")
lon = models.DecimalField(max_digits=10, decimal_places=7, blank=True, null=True, verbose_name="Longitude", help_text="Calculated automatically if mappable location is set.")
type = models.ForeignKey('OrganizationType', verbose_name=_('organization type'), blank=True, null=True, on_delete=models.SET_NULL)
initials = models.CharField(_('initials'), max_length=128, blank=True, null=True)
- is_on_map = models.BooleanField(_('is on map'), default=False)
+ is_on_map = models.BooleanField(_('is on map'), default=False, blank=True)
admin_thumb_type = 'logo'
raise ValidationError("Latitude required if specifying longitude.")
if not (self.lat and self.lon) and not self.mappable_location:
- self.mappable_location = self.address.replace("\n"," ").replace('\r', ' ') + ", " + self.postal_code + " " + self.city
+ if self.address:
+ self.mappable_location = self.address.replace("\n"," ").replace('\r', ' ') + ", " + self.postal_code + " " + self.city
if self.mappable_location and not (self.lat and self.lon): #location should always override lat/long if set
g = GoogleMaps(domain=settings.EVENT_GOOGLE_MAPS_DOMAIN)
grade = models.ForeignKey(ActivityGrade, verbose_name=_('grade'), blank=True, null=True, on_delete=models.SET_NULL)
function = models.ForeignKey(ActivityFunction, verbose_name=_('function'), blank=True, null=True, on_delete=models.SET_NULL)
- employer = models.ForeignKey(Organization, verbose_name=_('employer'), related_name='employer_activities', blank=True, null=True, on_delete=models.SET_NULL)
- attachment_organization = models.ForeignKey(Organization, verbose_name=_('attachment organization'), related_name='attachment_activities', blank=True, null=True, on_delete=models.SET_NULL)
- second_employer = models.ForeignKey(Organization, verbose_name=_('second employer'), related_name='second_employer_activities', blank=True, null=True, on_delete=models.SET_NULL)
- third_employer = models.ForeignKey(Organization, verbose_name=_('third employer'), related_name='third_employer_activities', blank=True, null=True, on_delete=models.SET_NULL)
+ organizations = models.ManyToManyField(Organization, verbose_name=_('organizations (attachment or subscribed)'), related_name='project_activities', blank=True)
+ employers = models.ManyToManyField(Organization, verbose_name=_('employers'), related_name='employer_project_activities', blank=True)
umr = models.ForeignKey(UMR, verbose_name=_('UMR'), blank=True, null=True, on_delete=models.SET_NULL)
- team = models.ForeignKey('Team', verbose_name=_('team'), related_name='team_activities', blank=True, null=True, on_delete=models.SET_NULL)
- second_team = models.ForeignKey('Team', verbose_name=_('second team'), related_name='second_team_activities', blank=True, null=True, on_delete=models.SET_NULL)
- second_team_text = models.CharField(_('second team text'), blank=True, null=True, max_length=256)
+ teams = models.ManyToManyField('Team', verbose_name=_('teams'), related_name='team_activities', blank=True)
+ team_text = models.CharField(_('other team text'), blank=True, null=True, max_length=256)
projects = models.ManyToManyField('organization-projects.Project', verbose_name=_('projects'), related_name='activities', blank=True)
- rd_quota_float = models.IntegerField(_('R&D quota (float)'), blank=True, null=True)
+ rd_quota_float = models.FloatField(_('R&D quota (float)'), blank=True, null=True)
rd_quota_text = models.CharField(_('R&D quota (text)'), blank=True, null=True, max_length=128)
rd_program = models.TextField(_('R&D program'), blank=True)
budget_code = models.ForeignKey(BudgetCode, blank=True, null=True, on_delete=models.SET_NULL)
+ supervisors = models.ManyToManyField('Person', verbose_name=_('supervisors'), related_name='supervisor_activities', blank=True)
+
phd_doctoral_school = models.ForeignKey(Organization, verbose_name=_('doctoral school'), blank=True, null=True, on_delete=models.SET_NULL)
phd_directors = models.ManyToManyField('Person', verbose_name=_('PhD directors'), related_name='phd_director_activities', blank=True)
- phd_officers = models.ManyToManyField('Person', verbose_name=_('PhD officers'), related_name='phd_officer_activities', blank=True)
phd_defense_date = models.DateField(_('PhD defense date'), blank=True, null=True)
phd_title = models.TextField(_('PhD title'), blank=True)
- phd_postdoctoralsituation = models.CharField(_('post-doctoral situation'), blank=True, max_length=256)
+ phd_post_doctoral_situation = models.CharField(_('post-doctoral situation'), blank=True, max_length=256)
hdr = models.BooleanField(_('HDR'), default=False)
training_type = models.ForeignKey(TrainingType, verbose_name=_('training type'), blank=True, null=True, on_delete=models.SET_NULL)
class Meta:
verbose_name = _('activity')
verbose_name_plural = _('activities')
+ ordering = ['person__last_name',]
def __str__(self):
if self.status: