From 71eab354591152c246a01dbd3b06114f0ecd400e Mon Sep 17 00:00:00 2001 From: Jorran de Wit <jorrandewit@outlook.com> Date: Wed, 1 Nov 2017 22:10:54 +0100 Subject: [PATCH] Fully integrate "dumb" affiliations system --- affiliations/__init__.py | 1 + affiliations/apps.py | 8 +++ affiliations/forms.py | 2 +- .../migrations/0004_auto_20171101_2208.py | 19 +++++ affiliations/models.py | 10 ++- affiliations/signals.py | 17 +++++ affiliations/views.py | 5 +- notifications/migrations/0003_fakeactors.py | 22 ++++++ notifications/models.py | 10 +++ petitions/views.py | 4 +- .../partials/proceedings/description.html | 2 +- scipost/forms.py | 70 +++++++++++-------- scipost/migrations/0067_auto_20171101_2132.py | 31 ++++++++ scipost/migrations/0068_auto_20171101_2132.py | 20 ++++++ scipost/models.py | 8 +-- .../scipost/_private_info_as_table.html | 4 +- .../scipost/_public_info_as_table.html | 4 +- .../submissions/_report_tex_template.html | 2 +- 18 files changed, 192 insertions(+), 47 deletions(-) create mode 100644 affiliations/migrations/0004_auto_20171101_2208.py create mode 100644 affiliations/signals.py create mode 100644 notifications/migrations/0003_fakeactors.py create mode 100644 scipost/migrations/0067_auto_20171101_2132.py create mode 100644 scipost/migrations/0068_auto_20171101_2132.py diff --git a/affiliations/__init__.py b/affiliations/__init__.py index e69de29bb..82323b3df 100644 --- a/affiliations/__init__.py +++ b/affiliations/__init__.py @@ -0,0 +1 @@ +default_app_config = 'affiliations.apps.AffiliationsConfig' diff --git a/affiliations/apps.py b/affiliations/apps.py index 4be3888cf..3b0241f47 100644 --- a/affiliations/apps.py +++ b/affiliations/apps.py @@ -1,5 +1,13 @@ from django.apps import AppConfig +from django.db.models.signals import post_save class AffiliationsConfig(AppConfig): name = 'affiliations' + + def ready(self): + super().ready() + + from . import models, signals + post_save.connect(signals.notify_new_affiliation, + sender=models.Affiliation) diff --git a/affiliations/forms.py b/affiliations/forms.py index f7cfd8f01..5fc623c48 100644 --- a/affiliations/forms.py +++ b/affiliations/forms.py @@ -17,6 +17,6 @@ class AffiliationMergeForm(forms.ModelForm): def save(self, commit=True): old_affiliation = self.cleaned_data['affiliation'] if commit: - old_affiliation.contributors.update(_affiliation=self.instance) + old_affiliation.contributors.update(affiliation=self.instance) old_affiliation.delete() return self.instance diff --git a/affiliations/migrations/0004_auto_20171101_2208.py b/affiliations/migrations/0004_auto_20171101_2208.py new file mode 100644 index 000000000..4b85c2f77 --- /dev/null +++ b/affiliations/migrations/0004_auto_20171101_2208.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-11-01 21:08 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('affiliations', '0003_auto_20171101_2022'), + ] + + operations = [ + migrations.AlterModelOptions( + name='affiliation', + options={'ordering': ['country']}, + ), + ] diff --git a/affiliations/models.py b/affiliations/models.py index f5c175605..974921535 100644 --- a/affiliations/models.py +++ b/affiliations/models.py @@ -1,4 +1,5 @@ from django.db import models +from django.urls import reverse from django_countries.fields import CountryField @@ -16,5 +17,12 @@ class Affiliation(models.Model): type = models.CharField(max_length=16, choices=AFFILIATION_TYPES, default=AFFILIATION_UNIVERSITY) + class Meta: + default_related_name = 'affiliations' + ordering = ['country'] + def __str__(self): - return self.name + return '{name} ({country})'.format(name=self.name, country=self.get_country_display()) + + def get_absolute_url(self): + return reverse('affiliations:affiliation_details', args=(self.object.id,)) diff --git a/affiliations/signals.py b/affiliations/signals.py new file mode 100644 index 000000000..c0e02335c --- /dev/null +++ b/affiliations/signals.py @@ -0,0 +1,17 @@ +from django.contrib.auth.models import User + +from notifications.models import FakeActors +from notifications.signals import notify + + +def notify_new_affiliation(sender, instance, created, **kwargs): + """ + Notify the SciPost Administration about a new Affiliation created to check it. + """ + if created: + administrators = User.objects.filter(groups__name='SciPost Administrators') + actor, __ = FakeActors.objects.get_or_create(name='A SciPost user') + for user in administrators: + notify.send(sender=sender, recipient=user, actor=actor, + verb=' created a new Affiliation instance. You may want to validate it.', + target=instance) diff --git a/affiliations/views.py b/affiliations/views.py index d31da46ba..bae15ec4b 100644 --- a/affiliations/views.py +++ b/affiliations/views.py @@ -1,4 +1,4 @@ -from django.shortcuts import render, redirect +from django.shortcuts import redirect from django.contrib import messages from django.urls import reverse from django.views.generic.edit import UpdateView @@ -32,9 +32,6 @@ class AffiliationUpdateView(UpdateView): messages.success(self.request, 'Affiliation saved') return super().form_valid(*args, **kwargs) - def get_success_url(self): - return reverse('affiliations:affiliation_details', args=(self.object.id,)) - def merge_affiliations(request, affiliation_id): """ diff --git a/notifications/migrations/0003_fakeactors.py b/notifications/migrations/0003_fakeactors.py new file mode 100644 index 000000000..d254da9d3 --- /dev/null +++ b/notifications/migrations/0003_fakeactors.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-11-01 21:08 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('notifications', '0002_auto_20171021_1821'), + ] + + operations = [ + migrations.CreateModel( + name='FakeActors', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=256)), + ], + ), + ] diff --git a/notifications/models.py b/notifications/models.py index d7d9fef89..4e54bf7c8 100644 --- a/notifications/models.py +++ b/notifications/models.py @@ -9,6 +9,16 @@ from .constants import NOTIFICATION_TYPES from .managers import NotificationQuerySet +class FakeActors(models.Model): + """ + This Model acts as a surrogate person that either is unknown, deceased, fake, etc. etc. + """ + name = models.CharField(max_length=256) + + def __str__(self): + return self.name + + class Notification(models.Model): """ Action model describing the actor acting out a verb (on an optional diff --git a/petitions/views.py b/petitions/views.py index b702d8078..86c527ccc 100644 --- a/petitions/views.py +++ b/petitions/views.py @@ -26,8 +26,8 @@ def petition(request, slug): 'first_name': request.user.first_name, 'last_name': request.user.last_name, 'email': request.user.email, - 'country_of_employment': request.user.contributor.country_of_employment, - 'affiliation': request.user.contributor.affiliation, + 'country_of_employment': request.user.contributor.affiliation.country_of_employment, + 'affiliation': request.user.contributor.affiliation.name, } form = SignPetitionForm(request.POST or None, initial=initial, petition=petition, diff --git a/proceedings/templates/partials/proceedings/description.html b/proceedings/templates/partials/proceedings/description.html index d6ae4a116..df878ae1e 100644 --- a/proceedings/templates/partials/proceedings/description.html +++ b/proceedings/templates/partials/proceedings/description.html @@ -15,7 +15,7 @@ <h3>Guest Fellows responsible for this Issue</h3> <ul> {% for fellow in proceedings.fellowships.guests %} - <li>{{ fellow.contributor.get_title_display }} {{ fellow.contributor.user.first_name }} {{ fellow.contributor.user.last_name }}{% if fellow.contributor.affiliation %}, {{ fellow.contributor.affiliation }}{% endif %}</li> + <li>{{ fellow.contributor.get_title_display }} {{ fellow.contributor.user.first_name }} {{ fellow.contributor.user.last_name }}{% if fellow.contributor.affiliation.name %}, {{ fellow.contributor.affiliation.name }}{% endif %}</li> {% endfor %} </ul> {% endif %} diff --git a/scipost/forms.py b/scipost/forms.py index 614c14f44..b0164430e 100644 --- a/scipost/forms.py +++ b/scipost/forms.py @@ -24,6 +24,7 @@ from .decorators import has_contributor from .models import Contributor, DraftInvitation, RegistrationInvitation,\ UnavailabilityPeriod, PrecookedEmail +from affiliations.models import Affiliation from common.forms import MonthYearWidget from partners.decorators import has_contact @@ -115,14 +116,17 @@ class RegistrationForm(forms.Form): 'password': self.cleaned_data['password'], 'is_active': False }) + affiliation, __ = Affiliation.objects.get_or_create( + country=self.cleaned_data['country_of_employment'], + name=self.cleaned_data['affiliation'], + ) contributor, new = Contributor.objects.get_or_create(**{ 'user': user, 'invitation_key': self.cleaned_data.get('invitation_key', ''), 'title': self.cleaned_data['title'], 'orcid_id': self.cleaned_data['orcid_id'], - 'country_of_employment': self.cleaned_data['country_of_employment'], 'address': self.cleaned_data['address'], - 'affiliation': self.cleaned_data['affiliation'], + 'affiliation': affiliation, 'personalwebpage': self.cleaned_data['personalwebpage'], }) @@ -257,39 +261,47 @@ class UpdateUserDataForm(forms.ModelForm): class UpdatePersonalDataForm(forms.ModelForm): + country_of_employment = LazyTypedChoiceField(choices=countries, widget=CountrySelectWidget()) + affiliation = forms.CharField(max_length=300) + class Meta: model = Contributor - fields = ['title', 'discipline', 'expertises', 'orcid_id', 'country_of_employment', - 'affiliation', 'address', 'personalwebpage' - ] - widgets = {'country_of_employment': CountrySelectWidget()} + fields = [ + 'title', + 'discipline', + 'expertises', + 'orcid_id', + 'address', + 'personalwebpage' + ] - # def __init__(self, *args, **kwargs): - # super().__init__(*args, **kwargs) - # self.fields['mail_subscription'] = forms.ModelMultipleChoiceField( - # queryset=MailchimpList.objects.open_to_subscribe(kwargs['instance']).distinct(), - # widget=forms.CheckboxSelectMultiple(), - # label='Subscribe to the following mailing lists:', - # required=False) - # self.fields['mailing_lists'] = forms.ModelMultipleChoiceField( - # queryset=MailchimpList.objects.open_to_subscribe(kwargs['instance']).distinct(), - # widget=forms.CheckboxSelectMultiple(), - # label='Subscribe to the following mailing lists:', - # required=False) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields['country_of_employment'].initial = self.instance.affiliation.country + self.fields['affiliation'].initial = self.instance.affiliation.name + + def save(self, commit=True): + contributor = super().save(commit) + if commit: + if contributor.affiliation.contributors.count() == 1: + # Just update if there are no other people using this Affiliation + affiliation = contributor.affiliation + affiliation.name = self.cleaned_data['affiliation'] + affiliation.country = self.cleaned_data['country_of_employment'] + affiliation.save() + else: + affiliation, __ = Affiliation.objects.get_or_create( + name=self.cleaned_data['affiliation'], + country=self.cleaned_data['country_of_employment']) + contributor.affiliation = affiliation + contributor.save() + return contributor def sync_lists(self): + """ + Pseudo U/S; do not remove + """ return - # contributor = self.instance - # original_lists = list(self.fields['mailing_lists'].queryset) - # - # # Subscribe to lists - # for _list in self.cleaned_data['mailing_lists']: - # _list.update_membership([contributor]) - # original_lists.remove(_list) - # - # # Unsubscribe from the leftovers - # for _list in original_lists: - # _list.update_membership([contributor], status='unsubscribed') def propagate_orcid(self): """ diff --git a/scipost/migrations/0067_auto_20171101_2132.py b/scipost/migrations/0067_auto_20171101_2132.py new file mode 100644 index 000000000..a202ec2ae --- /dev/null +++ b/scipost/migrations/0067_auto_20171101_2132.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-11-01 20:32 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('scipost', '0066_contributor__affiliation'), + ] + + operations = [ + migrations.RenameField( + model_name='contributor', + old_name='affiliation', + new_name='old_affiliation', + ), + migrations.RenameField( + model_name='contributor', + old_name='country_of_employment', + new_name='old_country_of_employment', + ), + migrations.AlterField( + model_name='contributor', + name='_affiliation', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='contributors', to='affiliations.Affiliation'), + ), + ] diff --git a/scipost/migrations/0068_auto_20171101_2132.py b/scipost/migrations/0068_auto_20171101_2132.py new file mode 100644 index 000000000..f59223bee --- /dev/null +++ b/scipost/migrations/0068_auto_20171101_2132.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-11-01 20:32 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('scipost', '0067_auto_20171101_2132'), + ] + + operations = [ + migrations.RenameField( + model_name='contributor', + old_name='_affiliation', + new_name='affiliation', + ), + ] diff --git a/scipost/models.py b/scipost/models.py index 3b03789c2..813cb7caf 100644 --- a/scipost/models.py +++ b/scipost/models.py @@ -50,10 +50,10 @@ class Contributor(models.Model): blank=True, null=True) orcid_id = models.CharField(max_length=20, verbose_name="ORCID id", blank=True) - country_of_employment = CountryField() - affiliation = models.CharField(max_length=300, verbose_name='affiliation') - _affiliation = models.ForeignKey('affiliations.Affiliation', null=True, blank=True, - related_name='contributors') + old_country_of_employment = CountryField() + old_affiliation = models.CharField(max_length=300, verbose_name='affiliation') + affiliation = models.ForeignKey('affiliations.Affiliation', null=True, blank=True, + related_name='contributors') address = models.CharField(max_length=1000, verbose_name="address", blank=True) personalwebpage = models.URLField(verbose_name='personal web page', diff --git a/scipost/templates/scipost/_private_info_as_table.html b/scipost/templates/scipost/_private_info_as_table.html index 04d525681..e8fc45a52 100644 --- a/scipost/templates/scipost/_private_info_as_table.html +++ b/scipost/templates/scipost/_private_info_as_table.html @@ -5,8 +5,8 @@ <tr><td>Email: </td><td> </td><td>{{ contributor.user.email }}</td></tr> <tr><td>ORCID id: </td><td> </td><td>{{ contributor.orcid_id }}</td></tr> <tr><td>Country of employment: </td><td> </td> - <td>{{ contributor.country_of_employment.name }}</td></tr> - <tr><td>Affiliation: </td><td> </td><td>{{ contributor.affiliation }}</td></tr> + <td>{{ contributor.affiliation.get_country_display }}</td></tr> + <tr><td>Affiliation: </td><td> </td><td>{{ contributor.affiliation.name }}</td></tr> <tr><td>Address: </td><td> </td><td>{{ contributor.address }}</td></tr> <tr><td>Personal web page: </td><td> </td><td>{{ contributor.personalwebpage }}</td></tr> <tr><td>Accept SciPost emails: </td><td> </td><td>{{ contributor.accepts_SciPost_emails }}</td></tr> diff --git a/scipost/templates/scipost/_public_info_as_table.html b/scipost/templates/scipost/_public_info_as_table.html index e41461ee1..0b141e6b2 100644 --- a/scipost/templates/scipost/_public_info_as_table.html +++ b/scipost/templates/scipost/_public_info_as_table.html @@ -3,7 +3,7 @@ <tr><td>First name: </td><td> </td><td>{{ contributor.user.first_name }}</td></tr> <tr><td>Last name: </td><td> </td><td>{{ contributor.user.last_name }}</td></tr> <tr><td>ORCID id: </td><td> </td><td>{{ contributor.orcid_id|default:'-' }}</td></tr> - <tr><td>Country of employment: </td><td> </td><td>{{ contributor.country_of_employment.name|default:'-'}}</td></tr> - <tr><td>Affiliation: </td><td> </td><td>{{ contributor.affiliation|default:'-' }}</td></tr> + <tr><td>Country of employment: </td><td> </td><td>{{ contributor.affiliation.get_country_display|default:'-'}}</td></tr> + <tr><td>Affiliation: </td><td> </td><td>{{ contributor.affiliation.name|default:'-' }}</td></tr> <tr><td>Personal web page: </td><td> </td><td>{{ contributor.personalwebpage|default:'-' }}</td></tr> </table> diff --git a/submissions/templates/submissions/_report_tex_template.html b/submissions/templates/submissions/_report_tex_template.html index ceb16ce3c..264dbc3a3 100644 --- a/submissions/templates/submissions/_report_tex_template.html +++ b/submissions/templates/submissions/_report_tex_template.html @@ -48,7 +48,7 @@ Report by {% if report.anonymous %}Anonymous{% else %}{{report.author.user.first \begin{center} %%%%%%%%%% AFFILIATIONS -{\bf 1} {{report.author.affiliation}}\\ +{\bf 1} {{report.author.affiliation.name}}\\ \end{center} {% endif %} -- GitLab