diff --git a/comments/templates/comments/_comment_identifier.html b/comments/templates/comments/_comment_identifier.html index 9c6b3127739c49b13fd1ca126d527188285b0c76..fa6faab3c4287f02ef037b74f9a324d506cf983e 100644 --- a/comments/templates/comments/_comment_identifier.html +++ b/comments/templates/comments/_comment_identifier.html @@ -11,9 +11,9 @@ {% if comment|is_reply_to_comment %} - (in reply to <a href="{{comment.get_absolute_url}}">{{comment.content_object.author.user.first_name}} {{comment.content_object.author.user.last_name}}</a> on {{comment.content_object.date_submitted|date:'Y-m-d'}}) + (in reply to <a href="{{comment.content_object.get_absolute_url}}">{{comment.content_object.author.user.first_name}} {{comment.content_object.author.user.last_name}}</a> on {{comment.content_object.date_submitted|date:'Y-m-d'}}) {% elif comment|is_reply_to_report %} - (in reply to <a href="{{comment.get_absolute_url}}"> + (in reply to <a href="{{comment.content_object.get_absolute_url}}"> Report {{comment.content_object.report_nr}} {% if not comment.content_object.anonymous %} diff --git a/journals/views.py b/journals/views.py index ebcd6d4f7eb69f31fde628ad0e8d2a2e71cc1bba..323702d0592277e74ecd59fc40f8c704d30612df 100644 --- a/journals/views.py +++ b/journals/views.py @@ -699,13 +699,12 @@ def metadata_xml_deposit(request, doi_label, option='test'): if os.path.isfile(path): errormessage = 'The metadata file for this metadata timestamp already exists' return render(request, 'scipost/error.html', context={'errormessage': errormessage}) - if option == 'deposit': + if option == 'deposit' and not settings.DEBUG: + # CAUTION: Real deposit only on production (non-debug-mode) url = 'http://doi.crossref.org/servlet/deposit' - elif option == 'test': - url = 'http://test.crossref.org/servlet/deposit' else: - errormessage = 'metadata_xml_deposit can only be called with options test or deposit' - return render(request, 'scipost/error.html', context={'errormessage': errormessage}) + url = 'http://test.crossref.org/servlet/deposit' + if publication.metadata_xml is None: errormessage = 'This publication has no metadata. Produce it first before saving it.' return render(request, 'scipost/error.html', context={'errormessage': errormessage}) @@ -1031,14 +1030,21 @@ def generic_metadata_xml_deposit(request, **kwargs): '<registrant>scipost</registrant>\n' '</head>\n' '<body>\n' - '<database><dataset>\n' - '<dataset_type>component<\dataset_type>\n' + '<database>\n' + '<database_metadata language="en">\n' + '<titles><title>SciPost Reports and Comments</title></titles>\n' + '</database_metadata>\n' + '<dataset dataset_type="collection">\n' '<doi_data><doi>' + _object.doi_string + '</doi>\n' - '<resource>' + _object.get_absolute_url() + '</resource>\n' + '<resource>https://scipost.org' + _object.get_absolute_url() + '</resource></doi_data>\n' '</dataset></database>\n' '</body></doi_batch>' ) - url = 'http://doi.crossref.org/servlet/deposit' + if not settings.DEBUG: + # CAUTION: Debug is False, production goes for real deposit!!! + url = 'http://doi.crossref.org/servlet/deposit' + else: + url = 'http://test.crossref.org/servlet/deposit' params = { 'operation': 'doMDUpload', 'login_id': settings.CROSSREF_LOGIN_ID, diff --git a/submissions/constants.py b/submissions/constants.py index 4e8da2fefd15599063680e7711ffe62134cd4d2b..943de541f9e517ddce9b8ceb90bbaebda95e9cf5 100644 --- a/submissions/constants.py +++ b/submissions/constants.py @@ -1,3 +1,6 @@ +from journals.constants import SCIPOST_JOURNAL_PHYSICS + + STATUS_UNASSIGNED = 'unassigned' STATUS_RESUBMISSION_INCOMING = 'resubmitted_incoming' STATUS_REVISION_REQUESTED = 'revision_requested' @@ -216,3 +219,19 @@ EVENT_TYPES = ( (EVENT_FOR_EIC, 'Comment for Editor-in-charge'), (EVENT_FOR_AUTHOR, 'Comment for author'), ) + +# Use `.format()` https://docs.python.org/3.5/library/string.html#format-string-syntax +# In your regex multiple brackets may occur; +# Please make sure to double them in that case as per instructions in the reference! +SUBMISSIONS_NO_VN_REGEX = '(?P<arxiv_identifier_wo_vn_nr>[0-9]{4,}.[0-9]{4,})' +SUBMISSIONS_COMPLETE_REGEX = '(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{4,}v[0-9]{1,2})' + + +# `EXPLICIT_REGEX_MANUSCRIPT_CONSTRAINTS` tracks the regex rules for the manuscripts +# submitted per journal. +# +# CAUTION: *triple* check whether the `default` regex also meets any other explicit journal regex! +EXPLICIT_REGEX_MANUSCRIPT_CONSTRAINTS = { + SCIPOST_JOURNAL_PHYSICS: '(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})', + 'default': SUBMISSIONS_COMPLETE_REGEX +} diff --git a/submissions/forms.py b/submissions/forms.py index fd5fff6e7be2f8988fa5ddd6cd4755946be8363e..fe47475e57d4c1f80e52bd8bb1c246dddab27ba0 100644 --- a/submissions/forms.py +++ b/submissions/forms.py @@ -1,3 +1,5 @@ +import re + from django import forms from django.conf import settings from django.contrib.auth.models import Group @@ -10,7 +12,7 @@ from .constants import ASSIGNMENT_BOOL, ASSIGNMENT_REFUSAL_REASONS, STATUS_RESUB REPORT_ACTION_CHOICES, REPORT_REFUSAL_CHOICES, STATUS_REVISION_REQUESTED,\ STATUS_REJECTED, STATUS_REJECTED_VISIBLE, STATUS_RESUBMISSION_INCOMING,\ STATUS_DRAFT, STATUS_UNVETTED, REPORT_ACTION_ACCEPT, REPORT_ACTION_REFUSE,\ - STATUS_VETTED + STATUS_VETTED, EXPLICIT_REGEX_MANUSCRIPT_CONSTRAINTS from . import exceptions, helpers from .models import Submission, RefereeInvitation, Report, EICRecommendation, EditorialAssignment,\ iThenticateReport @@ -120,6 +122,20 @@ class SubmissionChecks: 'before proceeding with a resubmission.') raise forms.ValidationError(error_message) + def arxiv_meets_regex(self, identifier, journal_code): + if journal_code in EXPLICIT_REGEX_MANUSCRIPT_CONSTRAINTS.keys(): + regex = EXPLICIT_REGEX_MANUSCRIPT_CONSTRAINTS[journal_code] + else: + regex = EXPLICIT_REGEX_MANUSCRIPT_CONSTRAINTS['default'] + + pattern = re.compile(regex) + if not pattern.match(identifier): + # No match object returned, identifier is invalid + error_message = ('The journal you want to submit to does not allow for this' + ' arXiv identifier. Please contact SciPost if you have' + ' any further questions.') + raise forms.ValidationError(error_message, code='submitted_to_journal') + def submission_is_resubmission(self): return self.is_resubmission @@ -239,6 +255,8 @@ class RequestSubmissionForm(SubmissionChecks, forms.ModelForm): """ cleaned_data = super().clean(*args, **kwargs) self.do_pre_checks(cleaned_data['arxiv_identifier_w_vn_nr']) + self.arxiv_meets_regex(cleaned_data['arxiv_identifier_w_vn_nr'], + cleaned_data['submitted_to_journal']) return cleaned_data def clean_author_list(self): diff --git a/submissions/templates/submissions/_report_tex_template.html b/submissions/templates/submissions/_report_tex_template.html index 466bd507f04e4b765986ca5ca7ecc93e5acba4dd..ceb16ce3c1644e379d0b935a45f29b7034851fc6 100644 --- a/submissions/templates/submissions/_report_tex_template.html +++ b/submissions/templates/submissions/_report_tex_template.html @@ -17,8 +17,8 @@ \fancypagestyle{SPstyle}{ \fancyhf{} \lhead{\raisebox{-1.5mm}[0pt][0pt]{\href{https://scipost.org}{\includegraphics[width=20mm]{logo_scipost_with_bgd.pdf}}}} - {% if report.doi_string %} + \rhead{\small \href{https://scipost.org{{report.doi_string|safe_tex_url}} }{ {{report.doi_string|safe_tex_url}} ({{report.date_submitted|date:'Y'}})}} {% endif %} @@ -33,28 +33,27 @@ \begin{center} \Large\color{scipostdeepblue}{\textbf{ %%%%%%%%%% TITLE -Report {{report.report_nr}} on\href{https://scipost.org{{report.get_absolute_url|safe_tex_url}} }{\color{scipostdeepblue}{ {{report.submission.title}} }}by {{report.submission.author_list}} +Report nr {{report.report_nr}} on Submission {{ report.submission.arxiv_identifier_w_vn_nr }},\\ +\href{https://scipost.org{{report.submission.get_absolute_url|safe_tex_url}}}{\color{scipostdeepblue}{ {{report.submission.title}} }}by {{report.submission.author_list}} }} \end{center} \begin{center} \large\textbf{ %%%%%%%%%% AUTHORS -Report by {% if report.anonymous %}anonymous{% else %}{{report.author.user.first_name}} {{report.author.user.last_name}}\textsuperscript{1}{% endif %} +Report by {% if report.anonymous %}Anonymous{% else %}{{report.author.user.first_name}} {{report.author.user.last_name}}\textsuperscript{1}{% endif %} } \end{center} - {% if not report.anonymous %} - \begin{center} - %%%%%%%%%% AFFILIATIONS - {\bf 1} {{report.author.affiliation}}\\ - \end{center} -{% endif %} +\begin{center} +%%%%%%%%%% AFFILIATIONS +{\bf 1} {{report.author.affiliation}}\\ +\end{center} +{% endif %} \vspace{10pt} - \begin{center} \begin{tabular}{lr} \begin{minipage}{0.5\textwidth} @@ -62,7 +61,7 @@ Report by {% if report.anonymous %}anonymous{% else %}{{report.author.user.first %%%%%%%%%% COPYRIGHT -{\small Copyright {% if report.anonymous %}anonymous{% else %}{{report.author.user.first_name}} {{report.author.user.last_name}}{% endif %}. \newline +{\small Copyright {% if report.anonymous %}Anonymous{% else %}{{report.author.user.first_name}} {{report.author.user.last_name}}{% endif %}. \newline This work is licensed under the Creative Commons \newline \href{http://creativecommons.org/licenses/by/4.0/}{Attribution 4.0 International License}. \newline Published by the SciPost Foundation. @@ -73,7 +72,7 @@ Published by the SciPost Foundation. %%%%%%%%%% DATES {\small Received {{report.date_submitted|date:'d-m-Y'}} {% if report.doi_string %} - doi:\href{//dx.doi.org{{report.doi_string|safe_tex_url}} }{ {{report.doi_string|safe_tex_url}} } +\doi{{{report.doi_string|safe_tex_url}}} {% endif %} } \end{minipage} diff --git a/submissions/templates/submissions/_single_public_report_without_comments.html b/submissions/templates/submissions/_single_public_report_without_comments.html index 9c322add27afc2ce4dc3e155922d7bca5c2824e9..8ffeb8b8f6f1e06bec568d9447ea72492154c18f 100644 --- a/submissions/templates/submissions/_single_public_report_without_comments.html +++ b/submissions/templates/submissions/_single_public_report_without_comments.html @@ -52,12 +52,15 @@ <h3>{% if report.anonymous %}Anonymous Report {{report.report_nr}}{% else %}<a href="{{report.author.get_absolute_url}}">{{ report.author.user.first_name }} {{ report.author.user.last_name }}</a>{% endif %} on {{ report.date_submitted|date:'Y-n-j' }}</h3> </h3> - {% if report.pdf_report %} - <a href="{% url 'submissions:report_detail_pdf' report.submission.arxiv_identifier_w_vn_nr report.report_nr %}" target="_blank">Download as PDF</a> - {% endif %} - {% if perms.scipost.can_manage_reports %} - {% if report.pdf_report %}· {% endif %}<a href="{% url 'submissions:report_pdf_compile' report.id %}">Update/Compile the Report pdf</a> - {% endif %} + <ul class="publicationClickables"> + {% if report.doi_string %}<li>doi: {{ report.doi_string }}</li>{% endif %} + {% if report.pdf_report %} + <li><a href="{% url 'submissions:report_detail_pdf' report.submission.arxiv_identifier_w_vn_nr report.report_nr %}" target="_blank">Download as PDF</a></li> + {% endif %} + {% if perms.scipost.can_manage_reports %} + <li><a href="{% url 'submissions:report_pdf_compile' report.id %}">Update/Compile the Report pdf</a></li> + {% endif %} + </ul> </div> {% include 'submissions/_single_report_content.html' with report=report %} diff --git a/submissions/urls.py b/submissions/urls.py index 431ae957cad857afb401cabd2a15b58a9f53fe67..c1f46c9ab3839e1758c764de519a0ae91a24eecf 100644 --- a/submissions/urls.py +++ b/submissions/urls.py @@ -2,6 +2,7 @@ from django.conf.urls import url from django.views.generic import TemplateView from . import views +from .constants import SUBMISSIONS_NO_VN_REGEX, SUBMISSIONS_COMPLETE_REGEX urlpatterns = [ # Submissions @@ -14,25 +15,25 @@ urlpatterns = [ url(r'^author_guidelines$', TemplateView.as_view(template_name='submissions/author_guidelines.html'), name='author_guidelines'), - url(r'^(?P<arxiv_identifier_wo_vn_nr>[0-9]{4,}.[0-9]{5,})/$', views.submission_detail_wo_vn_nr, + url(r'^{regex}/$'.format(regex=SUBMISSIONS_NO_VN_REGEX), views.submission_detail_wo_vn_nr, name='submission_wo_vn_nr'), - url(r'^(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/$', + url(r'^{regex}/$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.submission_detail, name='submission'), - url(r'^(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/reports/(?P<report_nr>[0-9]+)/pdf$', + url(r'^{regex}/reports/(?P<report_nr>[0-9]+)/pdf$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.report_detail_pdf, name='report_detail_pdf'), - url(r'^(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/reports/pdf$', + url(r'^{regex}/reports/pdf$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.submission_refereeing_package_pdf, name='refereeing_package_pdf'), # Editorial Administration url(r'^admin$', views.EditorialSummaryView.as_view(), name='admin'), url(r'^admin/treated$', views.treated_submissions_list, name='treated_submissions_list'), - url(r'^admin/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/reports/compile$', + url(r'^admin/{regex}/reports/compile$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.treated_submission_pdf_compile, name='treated_submission_pdf_compile'), - url(r'^admin/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/plagiarism$', + url(r'^admin/{regex}/plagiarism$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.PlagiarismView.as_view(), name='plagiarism'), - url(r'^admin/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/plagiarism/report$', + url(r'^admin/{regex}/plagiarism/report$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.PlagiarismReportPDFView.as_view(), name='plagiarism_report'), - url(r'^admin/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/recommendations/(?P<rec_id>[0-9]+)$', + url(r'^admin/{regex}/recommendations/(?P<rec_id>[0-9]+)$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.EICRecommendationView.as_view(), name='eic_recommendation_detail'), url(r'^admin/reports$', views.reports_accepted_list, name='reports_accepted_list'), url(r'^admin/reports/(?P<report_id>[0-9]+)/compile$', @@ -46,30 +47,30 @@ urlpatterns = [ url(r'^pool$', views.pool, name='pool'), url(r'^submissions_by_status/(?P<status>[a-zA-Z_]+)$', views.submissions_by_status, name='submissions_by_status'), - url(r'^add_remark/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + url(r'^add_remark/{regex}$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.add_remark, name='add_remark'), # Assignment of Editor-in-charge - url(r'^assign_submission/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + url(r'^assign_submission/{regex}$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.assign_submission, name='assign_submission'), - url(r'^assign_submission_ack/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + url(r'^assign_submission_ack/{regex}$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.assign_submission_ack, name='assign_submission_ack'), url(r'^accept_or_decline_assignment_ack/(?P<assignment_id>[0-9]+)$', views.accept_or_decline_assignment_ack, name='accept_or_decline_assignment_ack'), - url(r'^volunteer_as_EIC/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + url(r'^volunteer_as_EIC/{regex}$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.volunteer_as_EIC, name='volunteer_as_EIC'), - url(r'^assignment_failed/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + url(r'^assignment_failed/{regex}$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.assignment_failed, name='assignment_failed'), # Editorial workflow and refereeing url(r'^editorial_workflow$', views.editorial_workflow, name='editorial_workflow'), url(r'^assignments$', views.assignments, name='assignments'), - url(r'^editorial_page/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + url(r'^editorial_page/{regex}$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.editorial_page, name='editorial_page'), - url(r'^select_referee/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + url(r'^select_referee/{regex}$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.select_referee, name='select_referee'), - url(r'^recruit_referee/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + url(r'^recruit_referee/{regex}$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.recruit_referee, name='recruit_referee'), - url(r'^send_refereeing_invitation/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/(?P<contributor_id>[0-9]+)$', + url(r'^send_refereeing_invitation/{regex}/(?P<contributor_id>[0-9]+)$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.send_refereeing_invitation, name='send_refereeing_invitation'), url(r'^accept_or_decline_ref_invitations/$', views.accept_or_decline_ref_invitations, name='accept_or_decline_ref_invitations'), @@ -77,27 +78,28 @@ urlpatterns = [ views.accept_or_decline_ref_invitation_ack, name='accept_or_decline_ref_invitation_ack'), url(r'^decline_ref_invitation/(?P<invitation_key>.+)$', views.decline_ref_invitation, name='decline_ref_invitation'), - url(r'^ref_invitation_reminder/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/(?P<invitation_id>[0-9]+)$', views.ref_invitation_reminder, name='ref_invitation_reminder'), - url(r'^cancel_ref_invitation/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/(?P<invitation_id>[0-9]+)$', + url(r'^ref_invitation_reminder/{regex}/(?P<invitation_id>[0-9]+)$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), + views.ref_invitation_reminder, name='ref_invitation_reminder'), + url(r'^cancel_ref_invitation/{regex}/(?P<invitation_id>[0-9]+)$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.cancel_ref_invitation, name='cancel_ref_invitation'), - url(r'^extend_refereeing_deadline/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/(?P<days>[0-9]+)$', + url(r'^extend_refereeing_deadline/{regex}/(?P<days>[0-9]+)$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.extend_refereeing_deadline, name='extend_refereeing_deadline'), - url(r'^set_refereeing_deadline/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + url(r'^set_refereeing_deadline/{regex}$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.set_refereeing_deadline, name='set_refereeing_deadline'), - url(r'^close_refereeing_round/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + url(r'^close_refereeing_round/{regex}$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.close_refereeing_round, name='close_refereeing_round'), url(r'^refereeing_overview$', views.refereeing_overview, name='refereeing_overview'), - url(r'^communication/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/(?P<comtype>[a-zA-Z]{4,})$', + url(r'^communication/{regex}/(?P<comtype>[a-zA-Z]{{4,}})$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.communication, name='communication'), - url(r'^communication/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/(?P<comtype>[a-zA-Z]{4,})/(?P<referee_id>[0-9]+)$', + url(r'^communication/{regex}/(?P<comtype>[a-zA-Z]{{4,}})/(?P<referee_id>[0-9]+)$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.communication, name='communication'), - url(r'^eic_recommendation/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})$', + url(r'^eic_recommendation/{regex}$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.eic_recommendation, name='eic_recommendation'), - url(r'^cycle/(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/submit$', + url(r'^cycle/{regex}/submit$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.cycle_form_submit, name='cycle_confirmation'), # Reports - url(r'^(?P<arxiv_identifier_w_vn_nr>[0-9]{4,}.[0-9]{5,}v[0-9]{1,2})/reports/submit$', + url(r'^{regex}/reports/submit$'.format(regex=SUBMISSIONS_COMPLETE_REGEX), views.submit_report, name='submit_report'), url(r'^reports/vet$', views.vet_submitted_reports_list, name='vet_submitted_reports_list'), url(r'^reports/(?P<report_id>[0-9]+)/vet$', views.vet_submitted_report,