Newer
Older
__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3"
from scipost.constants import SCIPOST_SUBJECT_AREAS
from journals.models import Journal
from journals.constants import SCIPOST_JOURNALS_DOMAINS
from common.helpers import random_scipost_report_doi_label
from .constants import (
STATUS_UNASSIGNED, STATUS_EIC_ASSIGNED, STATUS_INCOMING, STATUS_PUBLISHED, SUBMISSION_TYPE,
STATUS_RESUBMITTED, STATUS_VETTED, REFEREE_QUALIFICATION, RANKING_CHOICES, QUALITY_SPEC,
REPORT_REC, REPORT_STATUSES, STATUS_UNVETTED, STATUS_DRAFT)
from .models import Submission, Report, RefereeInvitation, EICRecommendation, EditorialAssignment
class SubmissionFactory(factory.django.DjangoModelFactory):
"""
Generate random basic Submission instances.
"""
author_list = factory.Faker('name')
submitted_by = factory.Iterator(Contributor.objects.all())
submission_type = factory.Iterator(SUBMISSION_TYPE, getter=lambda c: c[0])
submitted_to = factory.Iterator(Journal.objects.all())
title = factory.Faker('sentence')
abstract = factory.Faker('paragraph', nb_sentences=10)
list_of_changes = factory.Faker('paragraph', nb_sentences=10)
subject_area = factory.Iterator(SCIPOST_SUBJECT_AREAS[0][1], getter=lambda c: c[0])
domain = factory.Iterator(SCIPOST_JOURNALS_DOMAINS, getter=lambda c: c[0])
abstract = factory.Faker('paragraph')
author_comments = factory.Faker('paragraph')
remarks_for_editors = factory.Faker('paragraph')
thread_hash = factory.Faker('uuid4')
submission_date = factory.Faker('date_this_decade')
latest_activity = factory.LazyAttribute(lambda o: Faker().date_time_between(
start_date=o.submission_date, end_date="now", tzinfo=pytz.UTC))
preprint = factory.SubFactory('preprints.factories.PreprintFactory')
@classmethod
def create(cls, **kwargs):
if Contributor.objects.count() < 5:
from scipost.factories import ContributorFactory
ContributorFactory.create_batch(5)
if Journal.objects.count() < 3:
from journals.factories import JournalFactory
JournalFactory.create_batch(3)
return super().create(**kwargs)
@factory.post_generation
def contributors(self, create, extracted, **kwargs):
contribs = Contributor.objects.all()
contribs = contribs.exclude(id=self.editor_in_charge.id)
contribs = contribs.order_by('?')[:random.randint(1, 6)]
self.submitted_by = contribs[0]
'%s %s' % (c.user.first_name, c.user.last_name) for c in contribs])
self.authors.add(*contribs)
class UnassignedSubmissionFactory(SubmissionFactory):
"""
A new incoming Submission without any EIC assigned.
"""
status = STATUS_UNASSIGNED
class EICassignedSubmissionFactory(SubmissionFactory):
"""
A Submission with an EIC assigned, visible in the pool and refereeing in process.
"""
open_for_commenting = True
@factory.lazy_attribute
def editor_in_charge(self):
return Contributor.objects.order_by('?').first()
@factory.post_generation
def eic_assignment(self, create, extracted, **kwargs):
if create:
EditorialAssignmentFactory(submission=self, to=self.editor_in_charge)
def referee_invites(self, create, extracted, **kwargs):
for i in range(random.randint(1, 3)):
RefereeInvitationFactory(submission=self)
for i in range(random.randint(0, 2)):
AcceptedRefereeInvitationFactory(submission=self)
for i in range(random.randint(0, 2)):
FulfilledRefereeInvitationFactory(submission=self)
@factory.post_generation
def comments(self, create, extracted, **kwargs):
if create:
for i in range(random.randint(0, 3)):
SubmissionCommentFactory(content_object=self)
@factory.post_generation
def eic_recommendation(self, create, extracted, **kwargs):
if create:
EICRecommendationFactory(submission=self)
class ResubmittedSubmissionFactory(EICassignedSubmissionFactory):
"""
A Submission that has a newer Submission version in the database
with a successive version number.
"""
status = STATUS_RESUBMITTED
open_for_commenting = False
open_for_reporting = False
is_current = False
@factory.post_generation
def successive_submission(self, create, extracted, **kwargs):
"""
Generate a second Submission that's the successive version of the resubmitted Submission
"""
if create and extracted is not False:
# Prevent infinite loops by checking the extracted argument
ResubmissionFactory(preprint__identifier_wo_vn_nr=self.preprint.identifier_wo_vn_nr,
previous_submission=False)
@factory.post_generation
def gather_successor_data(self, create, extracted, **kwargs):
"""
Gather some data from Submission with same arxiv id such that this Submission
more or less looks like any regular real resubmission.
"""
submission = Submission.objects.filter(
preprint__identifier_wo_vn_nr=self.preprint.identifier_wo_vn_nr).exclude(
preprint__vn_nr=self.preprint.vn_nr).first()
if not submission:
return
self.author_list = submission.author_list
self.submitted_by = submission.submitted_by
self.editor_in_charge = submission.editor_in_charge
self.submission_type = submission.submission_type
self.submitted_to = submission.submitted_to
self.title = submission.title
self.subject_area = submission.subject_area
self.domain = submission.domain
self.title = submission.title
self.authors.set(self.authors.all())
@factory.post_generation
def referee_invites(self, create, extracted, **kwargs):
"""
This Submission is deactivated for refereeing.
"""
for i in range(random.randint(0, 2)):
FulfilledRefereeInvitationFactory(submission=self)
for i in range(random.randint(1, 3)):
CancelledRefereeInvitationFactory(submission=self)
class ResubmissionFactory(EICassignedSubmissionFactory):
This Submission is a newer version of a Submission which is
already known by the SciPost database.
open_for_commenting = True
open_for_reporting = True
vn_nr = 2
def previous_submission(self, create, extracted, **kwargs):
if create and extracted is not False:
# Prevent infinite loops by checking the extracted argument
ResubmittedSubmissionFactory(
preprint__identifier_wo_vn_nr=self.preprint.identifier_wo_vn_nr,
successive_submission=False)
def gather_predecessor_data(self, create, extracted, **kwargs):
"""
Gather some data from Submission with same arxiv id such that this Submission
more or less looks like any regular real resubmission.
"""
submission = Submission.objects.filter(
identifier_wo_vn_nr=self.preprint.identifier_wo_vn_nr).exclude(
preprint__vn_nr=self.preprint.vn_nr).first()
if not submission:
return
self.author_list = submission.author_list
self.submitted_by = submission.submitted_by
self.editor_in_charge = submission.editor_in_charge
self.submission_type = submission.submission_type
self.submitted_to = submission.submitted_to
self.title = submission.title
self.subject_area = submission.subject_area
self.domain = submission.domain
self.title = submission.title
self.authors.set(self.authors.all())
def referee_invites(self, create, extracted, **kwargs):
"""
Referees for resubmissions are invited once the cycle has been chosen.
"""
pass
class PublishedSubmissionFactory(EICassignedSubmissionFactory):
status = STATUS_PUBLISHED
open_for_commenting = False
open_for_reporting = False
def generate_publication(self, create, extracted, **kwargs):
if create and extracted is not False:
from journals.factories import PublicationFactory
PublicationFactory(
journal=self.submitted_to.doi_label,
accepted_submission=self, title=self.title, author_list=self.author_list)
@factory.post_generation
def eic_assignment(self, create, extracted, **kwargs):
if create:
EditorialAssignmentFactory(submission=self, to=self.editor_in_charge, completed=True)
@factory.post_generation
def referee_invites(self, create, extracted, **kwargs):
for i in range(random.randint(2, 4)):
FulfilledRefereeInvitationFactory(submission=self)
for i in range(random.randint(0, 2)):
CancelledRefereeInvitationFactory(submission=self)
class ReportFactory(factory.django.DjangoModelFactory):
status = factory.Iterator(REPORT_STATUSES, getter=lambda c: c[0])
submission = factory.Iterator(Submission.objects.all())
report_nr = 1
date_submitted = factory.Faker('date_time_this_decade')
vetted_by = factory.Iterator(Contributor.objects.all())
author = factory.Iterator(Contributor.objects.all())
strengths = factory.Faker('paragraph')
weaknesses = factory.Faker('paragraph')
report = factory.Faker('paragraph')
requested_changes = factory.Faker('paragraph')
qualification = factory.Iterator(REFEREE_QUALIFICATION[1:], getter=lambda c: c[0])
validity = factory.Iterator(RANKING_CHOICES[1:], getter=lambda c: c[0])
significance = factory.Iterator(RANKING_CHOICES[1:], getter=lambda c: c[0])
originality = factory.Iterator(RANKING_CHOICES[1:], getter=lambda c: c[0])
clarity = factory.Iterator(RANKING_CHOICES[1:], getter=lambda c: c[0])
formatting = factory.Iterator(QUALITY_SPEC[1:], getter=lambda c: c[0])
grammar = factory.Iterator(QUALITY_SPEC[1:], getter=lambda c: c[0])
recommendation = factory.Iterator(REPORT_REC[1:], getter=lambda c: c[0])
remarks_for_editors = factory.Faker('paragraph')
flagged = factory.Faker('boolean', chance_of_getting_true=10)
anonymous = factory.Faker('boolean', chance_of_getting_true=75)
class DraftReportFactory(ReportFactory):
status = STATUS_DRAFT
vetted_by = None
class UnVettedReportFactory(ReportFactory):
status = STATUS_UNVETTED
vetted_by = None
class VettedReportFactory(ReportFactory):
status = STATUS_VETTED
needs_doi = True
doideposit_needs_updating = factory.Faker('boolean')
doi_label = factory.lazy_attribute(lambda n: random_scipost_report_doi_label())
pdf_report = factory.Faker('file_name', extension='pdf')
class RefereeInvitationFactory(factory.django.DjangoModelFactory):
submission = factory.SubFactory('submissions.factories.SubmissionFactory')
referee = factory.lazy_attribute(lambda o: Contributor.objects.exclude(
id__in=o.submission.authors.all()).order_by('?').first())
title = factory.lazy_attribute(lambda o: o.referee.title)
first_name = factory.lazy_attribute(lambda o: o.referee.user.first_name)
last_name = factory.lazy_attribute(lambda o: o.referee.user.last_name)
email_address = factory.lazy_attribute(lambda o: o.referee.user.email)
date_invited = factory.lazy_attribute(lambda o: o.submission.latest_activity)
nr_reminders = factory.lazy_attribute(lambda o: random.randint(0, 4))
date_last_reminded = factory.lazy_attribute(lambda o: o.submission.latest_activity)
invitation_key = factory.Faker('md5')
invited_by = factory.lazy_attribute(lambda o: o.submission.editor_in_charge)
class AcceptedRefereeInvitationFactory(RefereeInvitationFactory):
accepted = True
date_responded = factory.lazy_attribute(lambda o: Faker().date_time_between(
start_date=o.date_invited, end_date="now", tzinfo=pytz.UTC))
@factory.post_generation
def report(self, create, extracted, **kwargs):
if create:
VettedReportFactory(submission=self.submission, author=self.referee)
class FulfilledRefereeInvitationFactory(AcceptedRefereeInvitationFactory):
fulfilled = True
date_responded = factory.lazy_attribute(lambda o: Faker().date_time_between(
start_date=o.date_invited, end_date="now", tzinfo=pytz.UTC))
@factory.post_generation
def report(self, create, extracted, **kwargs):
if create:
VettedReportFactory(submission=self.submission, author=self.referee)
class CancelledRefereeInvitationFactory(AcceptedRefereeInvitationFactory):
fulfilled = False
cancelled = True
date_responded = factory.lazy_attribute(lambda o: Faker().date_time_between(
start_date=o.date_invited, end_date="now", tzinfo=pytz.UTC))
class EICRecommendationFactory(factory.django.DjangoModelFactory):
submission = factory.Iterator(Submission.objects.all())
date_submitted = factory.lazy_attribute(lambda o: Faker().date_time_between(
start_date=o.submission.submission_date, end_date="now", tzinfo=pytz.UTC))
remarks_for_authors = factory.Faker('paragraph')
requested_changes = factory.Faker('paragraph')
remarks_for_editorial_college = factory.Faker('paragraph')
recommendation = factory.Iterator(REPORT_REC[1:], getter=lambda c: c[0])
version = 1
active = True
class Meta:
model = EICRecommendation
class EditorialAssignmentFactory(factory.django.DjangoModelFactory):
"""
An EditorialAssignmentFactory should always have a `submission` explicitly assigned. This will
mostly be done using the post_generation hook in any SubmissionFactory.
"""
submission = None
to = factory.Iterator(Contributor.objects.all())
accepted = True
deprecated = False
completed = False
date_created = factory.lazy_attribute(lambda o: o.submission.latest_activity)
date_answered = factory.lazy_attribute(lambda o: o.submission.latest_activity)
class Meta:
model = EditorialAssignment