SciPost Code Repository

Skip to content
Snippets Groups Projects
Commit f34e8c7f authored by Jorran de Wit's avatar Jorran de Wit
Browse files

Add Invitations Officer to Stream

parent 5cdab653
No related branches found
No related tags found
No related merge requests found
# -*- coding: utf-8 -*-
# Generated by Django 1.11.4 on 2017-10-09 18:00
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('partners', '0034_merge_20171004_1946'),
('partners', '0036_auto_20171004_2014'),
]
operations = [
]
......@@ -36,6 +36,12 @@ class AssignOfficerForm(forms.ModelForm):
return stream
class AssignInvitationsOfficerForm(forms.ModelForm):
class Meta:
model = ProductionStream
fields = ('invitations_officer',)
class AssignSupervisorForm(forms.ModelForm):
class Meta:
model = ProductionStream
......
......@@ -11,7 +11,12 @@ class ProductionStreamQuerySet(models.QuerySet):
return self.exclude(status=PRODUCTION_STREAM_COMPLETED)
def filter_for_user(self, production_user):
return self.filter(officer=production_user)
"""
Return ProductionStreams that are only assigned to me as a Production Officer
or a Inivtations Officer.
"""
return self.filter(models.Q(officer=production_user)
| models.Q(invitations_officer=production_user))
class ProductionEventManager(models.Manager):
......
# -*- coding: utf-8 -*-
# Generated by Django 1.11.4 on 2017-10-09 18:00
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('production', '0028_auto_20171007_1311'),
]
operations = [
migrations.AddField(
model_name='productionstream',
name='invitations_officer',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='invitations_officer_streams', to='production.ProductionUser'),
),
]
......@@ -42,6 +42,8 @@ class ProductionStream(models.Model):
related_name='streams')
supervisor = models.ForeignKey('production.ProductionUser', blank=True, null=True,
related_name='supervised_streams')
invitations_officer = models.ForeignKey('production.ProductionUser', blank=True, null=True,
related_name='invitations_officer_streams')
work_logs = GenericRelation(WorkLog, related_query_name='streams')
......
......@@ -33,45 +33,65 @@
{% include 'partials/finances/logs.html' with logs=stream.work_logs.all %}
{% if "can_perform_supervisory_actions" in sub_perms %}
{% if "can_perform_supervisory_actions" in sub_perms or "can_work_for_stream" in sub_perms %}
<h3>Actions</h3>
<ul>
{% if perms.scipost.can_assign_production_supervisor and assign_supervisor_form %}
<li>
<a href="javascript:;" data-toggle="toggle" data-target="#add_supervisor_{{stream.id}}">Assign Production Supervisor to this stream</a>
<div id="add_supervisor_{{stream.id}}" style="display: none;">
<form class="my-3" action="{% url 'production:add_supervisor' stream_id=stream.id %}" method="post">
{% csrf_token %}
{{ assign_supervisor_form|bootstrap_inline }}
<input type="submit" class="btn btn-outline-primary" name="submit" value="Add supervisor">
</form>
</div>
</li>
{% endif %}
{% if perms.scipost.can_assign_production_officer and assign_officer_form %}
<li>
<a href="javascript:;" data-toggle="toggle" data-target="#add_officer_{{stream.id}}">Assign Production Officer to this stream</a>
<div id="add_officer_{{stream.id}}" style="display: none;">
<form class="my-3" action="{% url 'production:add_officer' stream_id=stream.id %}" method="post">
{% csrf_token %}
{{ assign_officer_form|bootstrap_inline }}
<input type="submit" class="btn btn-outline-primary" name="submit" value="Add officer">
</form>
</div>
</li>
{% if "can_perform_supervisory_actions" in sub_perms %}
{% if perms.scipost.can_assign_production_supervisor and assign_supervisor_form %}
<li>
<a href="javascript:;" data-toggle="toggle" data-target="#add_supervisor_{{stream.id}}">Assign Production Supervisor to this stream</a>
<div id="add_supervisor_{{stream.id}}" style="display: none;">
<form class="my-3" action="{% url 'production:add_supervisor' stream_id=stream.id %}" method="post">
{% csrf_token %}
{{ assign_supervisor_form|bootstrap_inline }}
<input type="submit" class="btn btn-outline-primary" name="submit" value="Add supervisor">
</form>
</div>
</li>
{% endif %}
{% if perms.scipost.can_assign_production_officer %}
{% if assign_officer_form %}
<li>
<a href="javascript:;" data-toggle="toggle" data-target="#add_officer_{{stream.id}}">Assign Production Officer to this stream</a>
<div id="add_officer_{{stream.id}}" style="display: none;">
<form class="my-3" action="{% url 'production:add_officer' stream_id=stream.id %}" method="post">
{% csrf_token %}
{{ assign_officer_form|bootstrap_inline }}
<input type="submit" class="btn btn-outline-primary" name="submit" value="Add officer">
</form>
</div>
</li>
{% endif %}
{% if assign_officer_form %}
<li>
<a href="javascript:;" data-toggle="toggle" data-target="#add_invs_officer_{{stream.id}}">Assign Invitations Officer to this stream</a>
<div id="add_invs_officer_{{stream.id}}" style="display: none;">
<form class="my-3" action="{% url 'production:add_invitations_officer' stream_id=stream.id %}" method="post">
{% csrf_token %}
{{ assign_invitiations_officer_form|bootstrap_inline }}
<input type="submit" class="btn btn-outline-primary" name="submit" value="Add officer">
</form>
</div>
</li>
{% endif %}
{% endif %}
{% endif %}
{% if perms.scipost.can_upload_proofs and stream.status != 'accepted' and stream.status != 'completed' and stream.status != 'cited' and upload_proofs_form %}
<li>
<a href="javascript:;" data-toggle="toggle" data-target="#upload_proofs">Upload Proofs</a>
<div id="upload_proofs" style="display: none;">
<form class="my-3" action="{% url 'production:upload_proofs' stream_id=stream.id %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ upload_proofs_form|bootstrap_inline }}
<input type="submit" class="btn btn-outline-primary" name="submit" value="Upload">
</form>
</div>
</li>
{% if "can_work_for_stream" in sub_perms %}
{% if perms.scipost.can_upload_proofs and upload_proofs_form %}
<li>
<a href="javascript:;" data-toggle="toggle" data-target="#upload_proofs">Upload Proofs</a>
<div id="upload_proofs" style="display: none;">
<form class="my-3" action="{% url 'production:upload_proofs' stream_id=stream.id %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ upload_proofs_form|bootstrap_inline }}
<input type="submit" class="btn btn-outline-primary" name="submit" value="Upload">
</form>
</div>
</li>
{% endif %}
{% endif %}
{% if perms.scipost.can_publish_accepted_submission %}
{% if not stream.submission.publication %}
<li><a href="{% url 'journals:initiate_publication' %}">Initiate the publication process</a></li>
......@@ -103,4 +123,14 @@
<em>No Officer assigned yet.</em>
{% endif %}
</li>
<li>Invitations Officer:
{% if stream.invitations_officer %}
<strong>{{ stream.invitations_officer }}</strong>
{% if "can_work_for_stream" in sub_perms and perms.scipost.can_assign_production_officer %}
&middot; <a href="{% url 'production:remove_invitations_officer' stream_id=stream.id officer_id=stream.invitations_officer.id %}" class="text-danger">Remove from stream</a>
{% endif %}
{% else %}
<em>No Invitations Officer assigned yet.</em>
{% endif %}
</li>
{% endblock %}
......@@ -9,7 +9,7 @@
<div class="card-body">
<h3>Stream details</h3>
<ul>
<li>Status: <em>{{ stream.get_status_display }}</em></li>
<li>Status: <span class="label label-secondary label-sm">{{ stream.get_status_display }}</span></li>
{% block officers %}
<li>Production Supervisor:
{% if stream.supervisor %}
......@@ -25,6 +25,13 @@
<em>No Officer assigned.</em>
{% endif %}
</li>
<li>Invitations Officer:
{% if stream.invitations_officer %}
<strong>{{ stream.invitations_officer }}</strong>
{% else %}
<em>No Invitations Officer assigned.</em>
{% endif %}
</li>
{% endblock %}
</ul>
......
......@@ -27,6 +27,10 @@ urlpatterns = [
production_views.add_officer, name='add_officer'),
url(r'^streams/(?P<stream_id>[0-9]+)/officer/(?P<officer_id>[0-9]+)/remove$',
production_views.remove_officer, name='remove_officer'),
url(r'^streams/(?P<stream_id>[0-9]+)/invitations_officer/add$',
production_views.add_invitations_officer, name='add_invitations_officer'),
url(r'^streams/(?P<stream_id>[0-9]+)/invitations_officer/(?P<officer_id>[0-9]+)/remove$',
production_views.remove_invitations_officer, name='remove_invitations_officer'),
url(r'^streams/(?P<stream_id>[0-9]+)/supervisor/add$',
production_views.add_supervisor, name='add_supervisor'),
url(r'^streams/(?P<stream_id>[0-9]+)/supervisor/(?P<officer_id>[0-9]+)/remove$',
......
......@@ -20,7 +20,8 @@ from finances.forms import WorkLogForm
from . import constants
from .models import ProductionUser, ProductionStream, ProductionEvent, Proof
from .forms import ProductionEventForm, AssignOfficerForm, UserToOfficerForm,\
AssignSupervisorForm, StreamStatusForm, ProofUploadForm, ProofDecisionForm
AssignSupervisorForm, StreamStatusForm, ProofUploadForm, ProofDecisionForm,\
AssignInvitationsOfficerForm
from .permissions import is_production_user
from .signals import notify_stream_status_change, notify_new_stream_assignment
from .utils import proof_slug_to_id
......@@ -54,10 +55,14 @@ def production(request, stream_id=None):
if stream_id:
try:
# "Pre-load" ProductionStream
context['stream'] = streams.get(id=stream_id)
context['assign_officer_form'] = AssignOfficerForm()
context['assign_invitiations_officer_form'] = AssignInvitationsOfficerForm()
context['assign_supervisor_form'] = AssignSupervisorForm()
context['prodevent_form'] = ProductionEventForm()
context['work_log_form'] = WorkLogForm()
context['upload_proofs_form'] = ProofUploadForm()
except ProductionStream.DoesNotExist:
pass
......@@ -98,6 +103,7 @@ def stream(request, stream_id):
stream = get_object_or_404(streams, id=stream_id)
prodevent_form = ProductionEventForm()
assign_officer_form = AssignOfficerForm()
assign_invitiations_officer_form = AssignInvitationsOfficerForm()
assign_supervisor_form = AssignSupervisorForm()
upload_proofs_form = ProofUploadForm()
work_log_form = WorkLogForm()
......@@ -108,6 +114,7 @@ def stream(request, stream_id):
'prodevent_form': prodevent_form,
'assign_officer_form': assign_officer_form,
'assign_supervisor_form': assign_supervisor_form,
'assign_invitiations_officer_form': assign_invitiations_officer_form,
'status_form': status_form,
'upload_proofs_form': upload_proofs_form,
'work_log_form': work_log_form,
......@@ -202,6 +209,36 @@ def add_officer(request, stream_id):
return redirect(reverse('production:production', args=(stream.id,)))
@is_production_user()
@permission_required('scipost.can_assign_production_officer', raise_exception=True)
@transaction.atomic
def add_invitations_officer(request, stream_id):
stream = get_object_or_404(ProductionStream.objects.ongoing(), pk=stream_id)
checker = ObjectPermissionChecker(request.user)
if not checker.has_perm('can_perform_supervisory_actions', stream):
return redirect(reverse('production:production', args=(stream.id,)))
form = AssignInvitationsOfficerForm(request.POST or None, instance=stream)
if form.is_valid():
form.save()
officer = form.cleaned_data.get('invitations_officer')
assign_perm('can_work_for_stream', officer.user, stream)
messages.success(request, 'Invitations Officer {officer} has been assigned.'.format(
officer=officer))
notify_new_stream_assignment(request.user, stream, officer.user)
event = ProductionEvent(
stream=stream,
event='assignment',
comments=' tasked Invitations Officer with invitations:',
noted_to=officer,
noted_by=request.user.production_user)
event.save()
else:
for key, error in form.errors.items():
messages.warning(request, error[0])
return redirect(reverse('production:production', args=(stream.id,)))
@is_production_user()
@permission_required('scipost.can_assign_production_officer', raise_exception=True)
@transaction.atomic
......@@ -215,12 +252,36 @@ def remove_officer(request, stream_id, officer_id):
officer = stream.officer
stream.officer = None
stream.save()
remove_perm('can_work_for_stream', officer.user, stream)
if officer not in [stream.invitations_officer, stream.supervisor]:
# Remove Officer from stream if not assigned anymore
remove_perm('can_work_for_stream', officer.user, stream)
messages.success(request, 'Officer {officer} has been removed.'.format(officer=officer))
return redirect(reverse('production:production', args=(stream.id,)))
@is_production_user()
@permission_required('scipost.can_assign_production_officer', raise_exception=True)
@transaction.atomic
def remove_invitations_officer(request, stream_id, officer_id):
stream = get_object_or_404(ProductionStream.objects.ongoing(), pk=stream_id)
checker = ObjectPermissionChecker(request.user)
if not checker.has_perm('can_perform_supervisory_actions', stream):
return redirect(reverse('production:production', args=(stream.id,)))
if getattr(stream.invitations_officer, 'id', 0) == int(officer_id):
officer = stream.invitations_officer
stream.invitations_officer = None
stream.save()
if officer not in [stream.officer, stream.supervisor]:
# Remove Officer from stream if not assigned anymore
remove_perm('can_work_for_stream', officer.user, stream)
messages.success(request, 'Invitations Officer {officer} has been removed.'.format(
officer=officer))
return redirect(reverse('production:production', args=(stream.id,)))
@is_production_user()
@permission_required('scipost.can_assign_production_supervisor', raise_exception=True)
@transaction.atomic
......
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