SciPost Code Repository

Skip to content
Snippets Groups Projects
Commit 96362429 authored by Jorran de Wit's avatar Jorran de Wit
Browse files
parents 22644c5f 7445df52
No related branches found
No related tags found
No related merge requests found
Showing with 323 additions and 107 deletions
...@@ -97,6 +97,7 @@ INSTALLED_APPS = ( ...@@ -97,6 +97,7 @@ INSTALLED_APPS = (
'production', 'production',
'partners', 'partners',
'funders', 'funders',
'stats',
'webpack_loader', 'webpack_loader',
) )
......
...@@ -43,7 +43,7 @@ urlpatterns = [ ...@@ -43,7 +43,7 @@ urlpatterns = [
url(r'^news/', include('news.urls', namespace="news")), url(r'^news/', include('news.urls', namespace="news")),
url(r'^production/', include('production.urls', namespace="production")), url(r'^production/', include('production.urls', namespace="production")),
url(r'^partners/', include('partners.urls', namespace="partners")), url(r'^partners/', include('partners.urls', namespace="partners")),
url(r'^stats/', include('stats.urls', namespace="stats")),
# Keep temporarily for historical reasons # Keep temporarily for historical reasons
url(r'^supporting_partners/', include('partners.urls', namespace="_partners")), url(r'^supporting_partners/', include('partners.urls', namespace="_partners")),
] ]
......
...@@ -322,7 +322,7 @@ ...@@ -322,7 +322,7 @@
<h3>Refereeing overview</h3> <h3>Refereeing overview</h3>
<ul> <ul>
<li>View (and act on) outstanding refereeing invitations in the <a href="{% url 'submissions:refereeing_overview' %}">refereeing overview</a></li> <li>View (and act on) outstanding refereeing invitations in the <a href="{% url 'submissions:refereeing_overview' %}">refereeing overview</a></li>
<li><a href="{% url 'submissions:statistics' %}">View statistics</a> for submissions, refereeing, publishing</li> <li><a href="{% url 'stats:statistics' %}">View statistics</a> for submissions, refereeing, publishing</li>
</ul> </ul>
<h3>Voting</h3> <h3>Voting</h3>
<ul> <ul>
......
from django.contrib import admin
# Register your models here.
from django.apps import AppConfig
class StatsConfig(AppConfig):
name = 'stats'
from django.db import models
# Create your models here.
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
{% block pagetitle %}: statistics for submisisons{% endblock pagetitle %} {% block pagetitle %}: statistics for submisisons{% endblock pagetitle %}
{% load scipost_extras %} {% load scipost_extras %}
{% load submissions_extras %} {% load stats_extras %}
{% load bootstrap %} {% load bootstrap %}
...@@ -17,21 +17,22 @@ ...@@ -17,21 +17,22 @@
<h1 class="highlight">Statistics</h1> <h1 class="highlight">Statistics</h1>
<h2>Aggregate statistics</h2> <h2>Aggregate statistics</h2>
<p>For each Journal, clicking on a year gives aggregate statistics for submissions (so including rejections). Clicking on a Journal/Volume/Issue gives aggregates for publications in this object.</p> <p>For each Journal, clicking on a year gives aggregate statistics for Submissions (so including rejections and withdrawals) which were first submitted in that year.</p>
<p>Clicking on a Journal/Volume/Issue gives aggregates for all publications in that object.</p>
<ul> <ul>
{% for journal in journals %} {% for journal in journals|dictsort:"doi_label" %}
<li><a href="{% url 'submissions:statistics' journal_doi_label=journal.doi_label %}">{{ journal }}</a></li> <li><a href="{% url 'stats:statistics' journal_doi_label=journal.doi_label %}">{{ journal }}</a></li>
<ul> <ul>
{% for year in journal|journal_publication_years %} {% for year in journal|journal_publication_years %}
<li><a href="{% url 'submissions:statistics' journal_doi_label=journal.doi_label year=year %}">{{ year }}</a></li> <li><a href="{% url 'stats:statistics' journal_doi_label=journal.doi_label year=year %}">{{ year }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
<ul> <ul>
{% for volume in journal.volume_set.all %} {% for volume in journal.volume_set.all|dictsort:"number" %}
<li><a href="{% url 'submissions:statistics' journal_doi_label=journal.doi_label volume_nr=volume.number %}">{{ volume }}</a></li> <li><a href="{% url 'stats:statistics' journal_doi_label=journal.doi_label volume_nr=volume.number %}">{{ volume }}</a></li>
<ul> <ul>
{% for issue in volume.issue_set.all %} {% for issue in volume.issue_set.all|dictsort:"number" %}
<li><a href="{% url 'submissions:statistics' journal_doi_label=journal.doi_label volume_nr=volume.number issue_nr=issue.number %}">{{ issue }}</a></li> <li><a href="{% url 'stats:statistics' journal_doi_label=journal.doi_label volume_nr=volume.number issue_nr=issue.number %}">{{ issue }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
{% endfor %} {% endfor %}
...@@ -46,13 +47,18 @@ ...@@ -46,13 +47,18 @@
<th>DOI label</th> <th>DOI label</th>
{% if year %} {% if year %}
<th>Year</th> <th>Year</th>
<th>Nr submissions</th> <th>Nr submissions<br/>(distinct)</th>
<th>Nr distinct submissions</th> <th>Nr submissions<br/>(including resubmissions)</th>
{% endif %} <th>Nr assignment failed</th>
<th>Nr accepted/<br/>published</th>
<th>Nr rejected</th>
<th>Nr withdrawn</th>
{% else %}
<th>Nr publications</th> <th>Nr publications</th>
<th>Duration average</th> <th>Duration average</th>
</tr> {% endif %}
<tr> </tr>
<tr>
{% if issue %} {% if issue %}
<td>{{ issue.doi_label }}</td> <td>{{ issue.doi_label }}</td>
<td>{{ issue|issue_nr_publications }}</td> <td>{{ issue|issue_nr_publications }}</td>
...@@ -65,14 +71,44 @@ ...@@ -65,14 +71,44 @@
<td>{{ journal.doi_label }}</td> <td>{{ journal.doi_label }}</td>
{% if year %} {% if year %}
<td>{{ year }}</td> <td>{{ year }}</td>
<td>{{ submissions|length }}</td>
<td>{{ submissions|submissions_count_distinct }}</td> <td>{{ submissions|submissions_count_distinct }}</td>
{% endif %} <td>{{ submissions|length }}</td>
<td>{{ submissions.assignment_failed.count }}</td>
<td>{{ submissions.accepted.count|add:submissions.published.count }}</td>
<td>{{ submissions.rejected.count }}</td>
<td>{{ submissions.withdrawn.count }}</td>
{% else %}
<td>{{ journal|journal_nr_publications }}</td> <td>{{ journal|journal_nr_publications }}</td>
<td>{{ journal|journal_avg_processing_duration|floatformat:2 }} days</td> <td>{{ journal|journal_avg_processing_duration|floatformat:2 }} days</td>
{% endif %}
{% endif %} {% endif %}
</tr> </tr>
</table> </table>
{% endif %} {% endif %}
{% if year %}
<h2>Refereeing stats for {{ year }}</h2>
<table class="table">
<tr>
<th>Nr refereeing<br/>invitations</th>
<th>Nr accepted</th>
<th>Nr declined</th>
<th>Nr pending</th>
<th>Nr reports<br/>obtained</th>
<th>Nr obtained<br/>(invited)</th>
<th>Nr obtained<br/>(contributed)</th>
</tr>
<tr>
<td>{{ nr_ref_inv }}</td>
<td>{{ nr_acc }} ({% widthratio nr_acc nr_ref_inv 100 %}&#37;)</td>
<td>{{ nr_dec }} ({% widthratio nr_dec nr_ref_inv 100 %}&#37;)</td>
<td>{{ nr_pen }} ({% widthratio nr_pen nr_ref_inv 100 %}&#37;)</td>
<td>{{ nr_rep_obt }}</td>
<td>{{ nr_rep_obt_inv }} ({% widthratio nr_rep_obt_inv nr_rep_obt 100 %}&#37;)</td>
<td>{{ nr_rep_obt_con }} ({% widthratio nr_rep_obt_con nr_rep_obt 100 %}&#37;)</td>
</tr>
</table>
{% endif %}
{% endblock content %} {% endblock content %}
from django import template
from django.db.models import Avg, F
from journals.models import Publication
from submissions.constants import SUBMISSION_STATUS_OUT_OF_POOL
from submissions.models import Submission
register = template.Library()
@register.filter(name='submissions_count_distinct')
def submissions_count_distinct(submissions):
identifiers_wo_vn_nr = []
for submission in submissions:
if submission.arxiv_identifier_wo_vn_nr not in identifiers_wo_vn_nr:
identifiers_wo_vn_nr.append(submission.arxiv_identifier_wo_vn_nr)
return len(identifiers_wo_vn_nr)
@register.filter(name='journal_publication_years')
def journal_publication_years(journal):
years = []
for volume in journal.volume_set.all():
if volume.until_date.year not in years:
years.append(volume.until_date.year)
return sorted(years)
@register.filter(name='journal_nr_publications')
def journal_nr_publications(journal):
return Publication.objects.filter(in_issue__in_volume__in_journal=journal).count()
@register.filter(name='journal_avg_processing_duration')
def journal_avg_processing_duration(journal):
duration = Publication.objects.filter(
in_issue__in_volume__in_journal=journal).aggregate(
avg=Avg(F('publication_date') - F('submission_date')))['avg']
if not duration: return 0
return duration.days + duration.seconds/86400
@register.filter(name='volume_nr_publications')
def volume_nr_publications(volume):
return Publication.objects.filter(in_issue__in_volume=volume).count()
@register.filter(name='volume_avg_processing_duration')
def volume_avg_processing_duration(volume):
duration = Publication.objects.filter(
in_issue__in_volume=volume).aggregate(
avg=Avg(F('publication_date') - F('submission_date')))['avg']
if not duration: return 0
return duration.days + duration.seconds/86400
@register.filter(name='issue_nr_publications')
def issue_nr_publications(issue):
return Publication.objects.filter(in_issue=issue).count()
@register.filter(name='issue_avg_processing_duration')
def issue_avg_processing_duration(issue):
duration = Publication.objects.filter(
in_issue=issue).aggregate(
avg=Avg(F('publication_date') - F('submission_date')))['avg']
if not duration: return 0
return duration.days + duration.seconds/86400
from django.test import TestCase
# Create your tests here.
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^statistics/(?P<journal_doi_label>[a-zA-Z]+)/(?P<volume_nr>[0-9]+)/(?P<issue_nr>[0-9]+)$',
views.statistics, name='statistics'),
url(r'^statistics/(?P<journal_doi_label>[a-zA-Z]+)/(?P<volume_nr>[0-9]+)$',
views.statistics, name='statistics'),
url(r'^statistics/(?P<journal_doi_label>[a-zA-Z]+)$', views.statistics, name='statistics'),
url(r'^statistics/(?P<journal_doi_label>[a-zA-Z]+)/year/(?P<year>[0-9]{4,})$',
views.statistics, name='statistics'),
url(r'^statistics$', views.statistics, name='statistics'),
]
import datetime
from django.contrib.auth.decorators import login_required, permission_required
from django.shortcuts import get_object_or_404, render
from journals.constants import SCIPOST_JOURNALS_SUBMIT
from journals.models import Journal, Volume, Issue, Publication
from submissions.models import Submission
@permission_required('scipost.can_oversee_refereeing', raise_exception=True)
def statistics(request, journal_doi_label=None, volume_nr=None, issue_nr=None, year=None):
journals = Journal.objects.all()
context = {
'journals': journals,
}
if journal_doi_label:
journal = get_object_or_404(Journal, doi_label=journal_doi_label)
context['journal'] = journal
if year:
context['year'] = year
submissions = Submission.objects.filter(submitted_to_journal=journal_doi_label
).originally_submitted(datetime.date(int(year), 1, 1), datetime.date(int(year), 12, 31))
context['submissions'] = submissions
nr_ref_inv = 0
nr_acc = 0
nr_dec = 0
nr_pen = 0
nr_rep_obt = 0
nr_rep_obt_inv = 0
nr_rep_obt_con = 0
nr_rep_ref = 0
nr_aw_vet = 0
for submission in submissions:
nr_ref_inv += submission.referee_invitations.count()
nr_acc += submission.count_accepted_invitations()
nr_dec += submission.count_declined_invitations()
nr_pen += submission.count_pending_invitations()
nr_rep_obt += submission.count_obtained_reports()
nr_rep_obt_inv += submission.count_invited_reports()
nr_rep_obt_con += submission.count_contrib_reports()
context['nr_ref_inv'] = nr_ref_inv
context['nr_acc'] = nr_acc
context['nr_dec'] = nr_dec
context['nr_pen'] = nr_pen
context['nr_rep_obt'] = nr_rep_obt
context['nr_rep_obt_inv'] = nr_rep_obt_inv
context['nr_rep_obt_con'] = nr_rep_obt_con
if volume_nr:
volume = get_object_or_404(Volume, in_journal=journal,
number=volume_nr)
context['volume'] = volume
if issue_nr:
issue = get_object_or_404(Issue, in_volume=volume,
number=issue_nr)
context['issue'] = issue
return render(request, 'stats/statistics.html', context)
...@@ -2,6 +2,7 @@ from journals.constants import SCIPOST_JOURNAL_PHYSICS ...@@ -2,6 +2,7 @@ from journals.constants import SCIPOST_JOURNAL_PHYSICS
STATUS_UNASSIGNED = 'unassigned' STATUS_UNASSIGNED = 'unassigned'
STATUS_ASSIGNMENT_FAILED = 'assignment_failed'
STATUS_RESUBMISSION_INCOMING = 'resubmitted_incoming' STATUS_RESUBMISSION_INCOMING = 'resubmitted_incoming'
STATUS_REVISION_REQUESTED = 'revision_requested' STATUS_REVISION_REQUESTED = 'revision_requested'
STATUS_EIC_ASSIGNED = 'EICassigned' STATUS_EIC_ASSIGNED = 'EICassigned'
...@@ -14,10 +15,15 @@ STATUS_REJECTED_VISIBLE = 'rejected_visible' ...@@ -14,10 +15,15 @@ STATUS_REJECTED_VISIBLE = 'rejected_visible'
STATUS_RESUBMITTED = 'resubmitted' STATUS_RESUBMITTED = 'resubmitted'
STATUS_RESUBMITTED_REJECTED = 'resubmitted_and_rejected' STATUS_RESUBMITTED_REJECTED = 'resubmitted_and_rejected'
STATUS_RESUBMITTED_REJECTED_VISIBLE = 'resubmitted_and_rejected_visible' STATUS_RESUBMITTED_REJECTED_VISIBLE = 'resubmitted_and_rejected_visible'
STATUS_VOTING_IN_PREPARATION = 'voting_in_preparation'
STATUS_PUT_TO_EC_VOTING = 'put_to_EC_voting'
STATUS_EC_VOTE_COMPLETED = 'EC_vote_completed'
STATUS_WITHDRAWN = 'withdrawn'
SUBMISSION_STATUS = ( SUBMISSION_STATUS = (
(STATUS_UNASSIGNED, 'Unassigned, undergoing pre-screening'), (STATUS_UNASSIGNED, 'Unassigned, undergoing pre-screening'),
(STATUS_RESUBMISSION_INCOMING, 'Resubmission incoming'), (STATUS_RESUBMISSION_INCOMING, 'Resubmission incoming'),
('assignment_failed', 'Failed to assign Editor-in-charge; manuscript rejected'), (STATUS_ASSIGNMENT_FAILED, 'Failed to assign Editor-in-charge; manuscript rejected'),
(STATUS_EIC_ASSIGNED, 'Editor-in-charge assigned, manuscript under review'), (STATUS_EIC_ASSIGNED, 'Editor-in-charge assigned, manuscript under review'),
(STATUS_REVIEW_CLOSED, 'Review period closed, editorial recommendation pending'), (STATUS_REVIEW_CLOSED, 'Review period closed, editorial recommendation pending'),
# If revisions required: resubmission creates a new Submission object # If revisions required: resubmission creates a new Submission object
...@@ -27,22 +33,22 @@ SUBMISSION_STATUS = ( ...@@ -27,22 +33,22 @@ SUBMISSION_STATUS = (
(STATUS_RESUBMITTED_REJECTED_VISIBLE, (STATUS_RESUBMITTED_REJECTED_VISIBLE,
'Has been resubmitted and subsequently rejected (still publicly visible)'), 'Has been resubmitted and subsequently rejected (still publicly visible)'),
# If acceptance/rejection: # If acceptance/rejection:
('voting_in_preparation', 'Voting in preparation (eligible Fellows being selected)'), (STATUS_VOTING_IN_PREPARATION, 'Voting in preparation (eligible Fellows being selected)'),
('put_to_EC_voting', 'Undergoing voting at the Editorial College'), (STATUS_PUT_TO_EC_VOTING, 'Undergoing voting at the Editorial College'),
(STATUS_AWAITING_ED_REC, 'Awaiting Editorial Recommendation'), (STATUS_AWAITING_ED_REC, 'Awaiting Editorial Recommendation'),
('EC_vote_completed', 'Editorial College voting rounded up'), (STATUS_EC_VOTE_COMPLETED, 'Editorial College voting rounded up'),
(STATUS_ACCEPTED, 'Publication decision taken: accept'), (STATUS_ACCEPTED, 'Publication decision taken: accept'),
(STATUS_REJECTED, 'Publication decision taken: reject'), (STATUS_REJECTED, 'Publication decision taken: reject'),
(STATUS_REJECTED_VISIBLE, 'Publication decision taken: reject (still publicly visible)'), (STATUS_REJECTED_VISIBLE, 'Publication decision taken: reject (still publicly visible)'),
(STATUS_PUBLISHED, 'Published'), (STATUS_PUBLISHED, 'Published'),
# If withdrawn: # If withdrawn:
('withdrawn', 'Withdrawn by the Authors'), (STATUS_WITHDRAWN, 'Withdrawn by the Authors'),
) )
SUBMISSION_HTTP404_ON_EDITORIAL_PAGE = [ SUBMISSION_HTTP404_ON_EDITORIAL_PAGE = [
'assignment_failed', STATUS_ASSIGNMENT_FAILED,
STATUS_PUBLISHED, STATUS_PUBLISHED,
'withdrawn', STATUS_WITHDRAWN,
STATUS_REJECTED, STATUS_REJECTED,
STATUS_REJECTED_VISIBLE, STATUS_REJECTED_VISIBLE,
] ]
...@@ -55,9 +61,9 @@ SUBMISSION_EXCLUDE_FROM_REPORTING = SUBMISSION_HTTP404_ON_EDITORIAL_PAGE + [ ...@@ -55,9 +61,9 @@ SUBMISSION_EXCLUDE_FROM_REPORTING = SUBMISSION_HTTP404_ON_EDITORIAL_PAGE + [
STATUS_AWAITING_ED_REC, STATUS_AWAITING_ED_REC,
STATUS_REVIEW_CLOSED, STATUS_REVIEW_CLOSED,
STATUS_ACCEPTED, STATUS_ACCEPTED,
'voting_in_preparation', STATUS_VOTING_IN_PREPARATION,
'put_to_EC_voting', STATUS_PUT_TO_EC_VOTING,
'withdrawn', STATUS_WITHDRAWN,
] ]
# Submissions which are allowed/required to submit a EIC Recommendation # Submissions which are allowed/required to submit a EIC Recommendation
...@@ -71,10 +77,10 @@ SUBMISSION_EIC_RECOMMENDATION_REQUIRED = [ ...@@ -71,10 +77,10 @@ SUBMISSION_EIC_RECOMMENDATION_REQUIRED = [
SUBMISSION_STATUS_PUBLICLY_INVISIBLE = [ SUBMISSION_STATUS_PUBLICLY_INVISIBLE = [
STATUS_UNASSIGNED, STATUS_UNASSIGNED,
STATUS_RESUBMISSION_INCOMING, STATUS_RESUBMISSION_INCOMING,
'assignment_failed', STATUS_ASSIGNMENT_FAILED,
STATUS_RESUBMITTED_REJECTED, STATUS_RESUBMITTED_REJECTED,
STATUS_REJECTED, STATUS_REJECTED,
'withdrawn', STATUS_WITHDRAWN,
] ]
# Submissions which should not appear in search lists # Submissions which should not appear in search lists
...@@ -88,7 +94,7 @@ SUBMISSION_STATUS_PUBLICLY_UNLISTED = SUBMISSION_STATUS_PUBLICLY_INVISIBLE + [ ...@@ -88,7 +94,7 @@ SUBMISSION_STATUS_PUBLICLY_UNLISTED = SUBMISSION_STATUS_PUBLICLY_INVISIBLE + [
SUBMISSION_STATUS_VOTING_DEPRECATED = [ SUBMISSION_STATUS_VOTING_DEPRECATED = [
STATUS_REJECTED, STATUS_REJECTED,
STATUS_PUBLISHED, STATUS_PUBLISHED,
'withdrawn', STATUS_WITHDRAWN,
] ]
SUBMISSION_TYPE = ( SUBMISSION_TYPE = (
......
...@@ -8,9 +8,11 @@ from .constants import SUBMISSION_STATUS_OUT_OF_POOL, SUBMISSION_STATUS_PUBLICLY ...@@ -8,9 +8,11 @@ from .constants import SUBMISSION_STATUS_OUT_OF_POOL, SUBMISSION_STATUS_PUBLICLY
SUBMISSION_STATUS_PUBLICLY_INVISIBLE, STATUS_UNVETTED, STATUS_VETTED,\ SUBMISSION_STATUS_PUBLICLY_INVISIBLE, STATUS_UNVETTED, STATUS_VETTED,\
STATUS_UNCLEAR, STATUS_INCORRECT, STATUS_NOT_USEFUL, STATUS_NOT_ACADEMIC,\ STATUS_UNCLEAR, STATUS_INCORRECT, STATUS_NOT_USEFUL, STATUS_NOT_ACADEMIC,\
SUBMISSION_HTTP404_ON_EDITORIAL_PAGE, STATUS_DRAFT, STATUS_PUBLISHED,\ SUBMISSION_HTTP404_ON_EDITORIAL_PAGE, STATUS_DRAFT, STATUS_PUBLISHED,\
SUBMISSION_EXCLUDE_FROM_REPORTING, STATUS_REJECTED_VISIBLE,\ SUBMISSION_EXCLUDE_FROM_REPORTING,\
STATUS_REJECTED, STATUS_REJECTED_VISIBLE,\
STATUS_ACCEPTED, STATUS_RESUBMITTED, STATUS_RESUBMITTED_REJECTED_VISIBLE,\ STATUS_ACCEPTED, STATUS_RESUBMITTED, STATUS_RESUBMITTED_REJECTED_VISIBLE,\
EVENT_FOR_EIC, EVENT_GENERAL, EVENT_FOR_AUTHOR, STATUS_UNASSIGNED EVENT_FOR_EIC, EVENT_GENERAL, EVENT_FOR_AUTHOR,\
STATUS_UNASSIGNED, STATUS_ASSIGNMENT_FAILED, STATUS_WITHDRAWN
class SubmissionQuerySet(models.QuerySet): class SubmissionQuerySet(models.QuerySet):
...@@ -108,9 +110,38 @@ class SubmissionQuerySet(models.QuerySet): ...@@ -108,9 +110,38 @@ class SubmissionQuerySet(models.QuerySet):
return self.filter(status__in=[STATUS_ACCEPTED, STATUS_REJECTED_VISIBLE, STATUS_PUBLISHED, return self.filter(status__in=[STATUS_ACCEPTED, STATUS_REJECTED_VISIBLE, STATUS_PUBLISHED,
STATUS_RESUBMITTED, STATUS_RESUBMITTED_REJECTED_VISIBLE]) STATUS_RESUBMITTED, STATUS_RESUBMITTED_REJECTED_VISIBLE])
def originally_submitted(self, from_date, until_date):
"""
Returns the submissions originally received between from_date and until_date
(including subsequent resubmissions, even if those came in later).
"""
identifiers = []
for sub in self.filter(is_resubmission=False,
submission_date__range=(from_date, until_date)):
identifiers.append(sub.arxiv_identifier_wo_vn_nr)
return self.filter(arxiv_identifier_wo_vn_nr__in=identifiers)
def accepted(self): def accepted(self):
return self.filter(status=STATUS_ACCEPTED) return self.filter(status=STATUS_ACCEPTED)
def published(self):
return self.filter(status=STATUS_PUBLISHED)
def assignment_failed(self):
return self.filter(status=STATUS_ASSIGNMENT_FAILED)
def rejected(self):
return self._newest_version_only(self.filter(status__in=[STATUS_REJECTED,
STATUS_REJECTED_VISIBLE]))
def withdrawn(self):
return self._newest_version_only(self.filter(status=STATUS_WITHDRAWN))
def open_for_reporting(self): def open_for_reporting(self):
""" """
Return Submissions that have appriopriate status for reporting. Return Submissions that have appriopriate status for reporting.
......
import datetime import datetime
from django import template from django import template
from django.db.models import Avg, F
from django.utils import timezone
from journals.models import Publication
from submissions.constants import SUBMISSION_STATUS_OUT_OF_POOL from submissions.constants import SUBMISSION_STATUS_OUT_OF_POOL
from submissions.models import Submission from submissions.models import Submission
...@@ -26,55 +23,3 @@ def is_viewable_by_authors(recommendation): ...@@ -26,55 +23,3 @@ def is_viewable_by_authors(recommendation):
return recommendation.submission.status in ['revision_requested', 'resubmitted', return recommendation.submission.status in ['revision_requested', 'resubmitted',
'accepted', 'rejected', 'accepted', 'rejected',
'published', 'withdrawn'] 'published', 'withdrawn']
@register.filter(name='submissions_count_distinct')
def submissions_count_distinct(submissions):
identifiers_wo_vn_nr = []
for submission in submissions:
identifiers_wo_vn_nr.append(submission.arxiv_identifier_wo_vn_nr)
return len(identifiers_wo_vn_nr)
@register.filter(name='journal_publication_years')
def journal_publication_years(journal):
years = []
for volume in journal.volume_set.all():
if volume.until_date.year not in years:
years.append(volume.until_date.year)
return years
@register.filter(name='journal_nr_publications')
def journal_nr_publications(journal):
return Publication.objects.filter(in_issue__in_volume__in_journal=journal).count()
@register.filter(name='journal_avg_processing_duration')
def journal_avg_processing_duration(journal):
duration = Publication.objects.filter(
in_issue__in_volume__in_journal=journal).aggregate(
avg=Avg(F('publication_date') - F('submission_date')))['avg']
if not duration: return 0
return duration.days + duration.seconds/86400
@register.filter(name='volume_nr_publications')
def volume_nr_publications(volume):
return Publication.objects.filter(in_issue__in_volume=volume).count()
@register.filter(name='volume_avg_processing_duration')
def volume_avg_processing_duration(volume):
duration = Publication.objects.filter(
in_issue__in_volume=volume).aggregate(
avg=Avg(F('publication_date') - F('submission_date')))['avg']
if not duration: return 0
return duration.days + duration.seconds/86400
@register.filter(name='issue_nr_publications')
def issue_nr_publications(issue):
return Publication.objects.filter(in_issue=issue).count()
@register.filter(name='issue_avg_processing_duration')
def issue_avg_processing_duration(issue):
duration = Publication.objects.filter(
in_issue=issue).aggregate(
avg=Avg(F('publication_date') - F('submission_date')))['avg']
if not duration: return 0
return duration.days + duration.seconds/86400
...@@ -89,14 +89,6 @@ urlpatterns = [ ...@@ -89,14 +89,6 @@ urlpatterns = [
url(r'^close_refereeing_round/{regex}$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), url(r'^close_refereeing_round/{regex}$'.format(regex=SUBMISSIONS_COMPLETE_REGEX),
views.close_refereeing_round, name='close_refereeing_round'), views.close_refereeing_round, name='close_refereeing_round'),
url(r'^refereeing_overview$', views.refereeing_overview, name='refereeing_overview'), url(r'^refereeing_overview$', views.refereeing_overview, name='refereeing_overview'),
url(r'^statistics/(?P<journal_doi_label>[a-zA-Z]+)/(?P<volume_nr>[0-9]+)/(?P<issue_nr>[0-9]+)$',
views.statistics, name='statistics'),
url(r'^statistics/(?P<journal_doi_label>[a-zA-Z]+)/(?P<volume_nr>[0-9]+)$',
views.statistics, name='statistics'),
url(r'^statistics/(?P<journal_doi_label>[a-zA-Z]+)$', views.statistics, name='statistics'),
url(r'^statistics/(?P<journal_doi_label>[a-zA-Z]+)/year/(?P<year>[0-9]{4,})$',
views.statistics, name='statistics'),
url(r'^statistics$', views.statistics, name='statistics'),
url(r'^communication/{regex}/(?P<comtype>[a-zA-Z]{{4,}})$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), url(r'^communication/{regex}/(?P<comtype>[a-zA-Z]{{4,}})$'.format(regex=SUBMISSIONS_COMPLETE_REGEX),
views.communication, name='communication'), views.communication, name='communication'),
url(r'^communication/{regex}/(?P<comtype>[a-zA-Z]{{4,}})/(?P<referee_id>[0-9]+)$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), url(r'^communication/{regex}/(?P<comtype>[a-zA-Z]{{4,}})/(?P<referee_id>[0-9]+)$'.format(regex=SUBMISSIONS_COMPLETE_REGEX),
......
...@@ -35,7 +35,6 @@ from .forms import SubmissionIdentifierForm, RequestSubmissionForm, SubmissionSe ...@@ -35,7 +35,6 @@ from .forms import SubmissionIdentifierForm, RequestSubmissionForm, SubmissionSe
from .utils import SubmissionUtils from .utils import SubmissionUtils
from mails.views import MailEditingSubView from mails.views import MailEditingSubView
from journals.models import Journal, Volume, Issue, Publication
from scipost.forms import ModifyPersonalMessageForm, RemarkForm from scipost.forms import ModifyPersonalMessageForm, RemarkForm
from scipost.models import Contributor, Remark, RegistrationInvitation from scipost.models import Contributor, Remark, RegistrationInvitation
from scipost.utils import Utils from scipost.utils import Utils
...@@ -1003,32 +1002,6 @@ def refereeing_overview(request): ...@@ -1003,32 +1002,6 @@ def refereeing_overview(request):
return render(request, 'submissions/refereeing_overview.html', context) return render(request, 'submissions/refereeing_overview.html', context)
@permission_required('scipost.can_oversee_refereeing', raise_exception=True)
def statistics(request, journal_doi_label=None, volume_nr=None, issue_nr=None, year=None):
journals = Journal.objects.all()
context = {
'journals': journals,
}
if journal_doi_label:
journal = get_object_or_404(Journal, doi_label=journal_doi_label)
context['journal'] = journal
if year:
context['year'] = year
submissions = Submission.objects.filter(
submitted_to_journal=journal,
submission_date__year=year,
)
context['submissions'] = submissions
if volume_nr:
volume = get_object_or_404(Volume, in_journal=journal,
number=volume_nr)
context['volume'] = volume
if issue_nr:
issue = get_object_or_404(Issue, in_volume=volume,
number=issue_nr)
context['issue'] = issue
return render(request, 'submissions/statistics.html', context)
@login_required @login_required
def communication(request, arxiv_identifier_w_vn_nr, comtype, referee_id=None): def communication(request, arxiv_identifier_w_vn_nr, comtype, referee_id=None):
""" """
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment