diff --git a/notifications/migrations/0002_notification_url_code.py b/notifications/migrations/0002_notification_url_code.py new file mode 100644 index 0000000000000000000000000000000000000000..b8922d06cd68ebd87772913a30232203c46fe343 --- /dev/null +++ b/notifications/migrations/0002_notification_url_code.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2018-12-04 19:11 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('notifications', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='notification', + name='url_code', + field=models.CharField(blank=True, max_length=255), + ), + ] diff --git a/submissions/admin.py b/submissions/admin.py index 7b7a19e8e48d469d949d8059ed91b6ca4f809ae7..78df5387cad6306dcc075d99576e120b1f57b910 100644 --- a/submissions/admin.py +++ b/submissions/admin.py @@ -65,8 +65,9 @@ class SubmissionAdmin(GuardedModelAdmin): }), ('Versioning', { 'fields': ( + 'thread_hash', 'is_current', - 'is_resubmission', + '_is_resubmission', 'is_resubmission_of', 'list_of_changes'), }), diff --git a/submissions/forms.py b/submissions/forms.py index 67f6d5b4513a3e145021b8e7f7b1533ceb96bf57..47668d7bdfdb4fc1a2dbc28feb523506391c37ba 100644 --- a/submissions/forms.py +++ b/submissions/forms.py @@ -242,11 +242,12 @@ class SubmissionService: Submission.objects.filter(id=submission.id).update( open_for_reporting=True, open_for_commenting=True, - is_resubmission=True, + is_resubmission_of=self.latest_submission, visible_pool=True, refereeing_cycle=CYCLE_UNDETERMINED, editor_in_charge=self.latest_submission.editor_in_charge, - status=STATUS_EIC_ASSIGNED) + status=STATUS_EIC_ASSIGNED, + thread_hash=self.latest_submission.thread_hash) # Add author(s) (claim) fields submission.authors.add(*self.latest_submission.authors.all()) diff --git a/submissions/managers.py b/submissions/managers.py index 64ac5791882c5a9f6daf3984e973e431afb793e6..dc73320955c2e4f1e1cc2c8578c6c7e0fd7f1a9a 100644 --- a/submissions/managers.py +++ b/submissions/managers.py @@ -17,6 +17,8 @@ now = timezone.now() class SubmissionQuerySet(models.QuerySet): def _newest_version_only(self, queryset): """ + TODO: Make more efficient... with agregation or whatever. + The current Queryset should return only the latest version of the Arxiv submissions known to SciPost. @@ -157,7 +159,7 @@ class SubmissionQuerySet(models.QuerySet): (including subsequent resubmissions, even if those came in later). """ identifiers = [] - for sub in self.filter(is_resubmission=False, + for sub in self.filter(is_resubmission_of__isnull=True, submission_date__range=(from_date, until_date)): identifiers.append(sub.preprint.identifier_wo_vn_nr) return self.filter(preprint__identifier_wo_vn_nr__in=identifiers) diff --git a/submissions/migrations/0047_auto_20181204_2011.py b/submissions/migrations/0047_auto_20181204_2011.py new file mode 100644 index 0000000000000000000000000000000000000000..15fe0d2cb0de419eb07beb1d6f8954efdf8a3bfc --- /dev/null +++ b/submissions/migrations/0047_auto_20181204_2011.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2018-12-04 19:11 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('submissions', '0046_auto_20181130_1013'), + ] + + operations = [ + migrations.RenameField( + model_name='submission', + old_name='is_resubmission', + new_name='_is_resubmission', + ), + migrations.AlterField( + model_name='submission', + name='submission_type', + field=models.CharField(blank=True, choices=[('Letter', 'Letter (broad-interest breakthrough results)'), ('Article', 'Article (in-depth reports on specialized research)'), ('Review', 'Review (candid snapshot of current research in a given area)')], max_length=10), + ), + ] diff --git a/submissions/migrations/0048_submission_thread_hash.py b/submissions/migrations/0048_submission_thread_hash.py new file mode 100644 index 0000000000000000000000000000000000000000..ddf50c99d378afb379eedca6278da7bf875a29b6 --- /dev/null +++ b/submissions/migrations/0048_submission_thread_hash.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2018-12-04 19:37 +from __future__ import unicode_literals + +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('submissions', '0047_auto_20181204_2011'), + ] + + operations = [ + migrations.AddField( + model_name='submission', + name='thread_hash', + field=models.UUIDField(default=uuid.uuid4), + ), + ] diff --git a/submissions/migrations/0049_auto_20181204_2040.py b/submissions/migrations/0049_auto_20181204_2040.py new file mode 100644 index 0000000000000000000000000000000000000000..bbcd903d8ecd1538e68965795fcfce6a74be4305 --- /dev/null +++ b/submissions/migrations/0049_auto_20181204_2040.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2018-12-04 19:40 +from __future__ import unicode_literals + +import uuid + +from django.db import migrations + + +def get_thread_ids(parent, submissions_list=[]): + successor = parent.successor.first() + if not successor: + return submissions_list + + submissions_list.append(successor.id) + return get_thread_ids(successor, submissions_list) + + +def populate_thread_hashes(apps, schema_editor): + Submission = apps.get_model('submissions', 'Submission') + + for original_submission in Submission.objects.filter(is_resubmission_of__isnull=True): + children_ids = get_thread_ids(original_submission, [original_submission.id]) + Submission.objects.filter(id__in=children_ids).update(thread_hash=uuid.uuid4()) + + +class Migration(migrations.Migration): + + dependencies = [ + ('submissions', '0048_submission_thread_hash'), + ] + + operations = [ + migrations.RunPython(populate_thread_hashes, reverse_code=migrations.RunPython.noop), + ] diff --git a/submissions/models.py b/submissions/models.py index 19e17e177442c13e6017c7ab265fc9e01982c0fa..f7348cfb610ade1639421d2518b357eb5885d74e 100644 --- a/submissions/models.py +++ b/submissions/models.py @@ -4,6 +4,7 @@ __license__ = "AGPL v3" import datetime import feedparser +import uuid from django.contrib.postgres.fields import JSONField from django.contrib.contenttypes.fields import GenericRelation @@ -77,7 +78,8 @@ class Submission(models.Model): visible_pool = models.BooleanField("Is visible in the Pool", default=False) is_resubmission_of = models.ForeignKey( 'self', blank=True, null=True, related_name='successor') - is_resubmission = models.BooleanField(default=False) + thread_hash = models.UUIDField(default=uuid.uuid4) + _is_resubmission = models.BooleanField(default=False) refereeing_cycle = models.CharField( max_length=30, choices=SUBMISSION_CYCLES, default=CYCLE_DEFAULT, blank=True) @@ -196,6 +198,10 @@ class Submission(models.Model): """Return url of the Submission detail page.""" return reverse('submissions:submission', args=(self.preprint.identifier_w_vn_nr,)) + @property + def is_resubmission(self): + return self.is_resubmission_of is not None + @property def notification_name(self): """Return string representation of this Submission as shown in Notifications.""" @@ -232,13 +238,12 @@ class Submission(models.Model): def original_submission_date(self): """Return the submission_date of the first Submission in the thread.""" return Submission.objects.filter( - preprint__identifier_wo_vn_nr=self.preprint.identifier_wo_vn_nr).first().submission_date + thread_hash=self.thread_hash, is_resubmission_of__isnull=True).first().submission_date @property def thread(self): """Return all (public) Submissions in the database in this ArXiv identifier series.""" - return Submission.objects.public().filter( - preprint__identifier_wo_vn_nr=self.preprint.identifier_wo_vn_nr).order_by( + return Submission.objects.public().filter(thread_hash=self.thread_hash).order_by( '-preprint__vn_nr') @cached_property @@ -253,8 +258,7 @@ class Submission(models.Model): def get_other_versions(self): """Return queryset of other Submissions with this ArXiv identifier series.""" - return Submission.objects.filter( - preprint__identifier_wo_vn_nr=self.preprint.identifier_wo_vn_nr).exclude(pk=self.id) + return Submission.objects.filter(thread_hash=self.thread_hash).exclude(pk=self.id) def count_accepted_invitations(self): """Count number of accepted RefereeInvitations for this Submission."""