2018-06-03 13:34:04 +00:00
|
|
|
import logging
|
|
|
|
from itertools import chain
|
|
|
|
|
2018-08-15 21:47:25 +00:00
|
|
|
from django.contrib.auth.mixins import PermissionRequiredMixin, UserPassesTestMixin
|
2017-10-03 19:14:07 +00:00
|
|
|
from django.views.generic import TemplateView, ListView
|
2018-06-03 13:34:04 +00:00
|
|
|
from django.views.generic.edit import UpdateView
|
|
|
|
from django.shortcuts import redirect
|
|
|
|
from django.urls import reverse
|
|
|
|
from django.contrib import messages
|
2018-08-01 10:25:43 +00:00
|
|
|
from django.utils import timezone
|
2018-06-03 13:34:04 +00:00
|
|
|
|
2018-08-15 18:53:54 +00:00
|
|
|
from camps.mixins import CampViewMixin
|
2017-12-04 09:43:25 +00:00
|
|
|
from shop.models import OrderProductRelation
|
2017-12-12 20:57:17 +00:00
|
|
|
from tickets.models import ShopTicket, SponsorTicket, DiscountTicket
|
2018-04-22 06:28:46 +00:00
|
|
|
from profiles.models import Profile
|
2018-06-03 13:34:04 +00:00
|
|
|
from program.models import SpeakerProposal, EventProposal
|
|
|
|
|
2017-10-03 19:14:07 +00:00
|
|
|
logger = logging.getLogger("bornhack.%s" % __name__)
|
|
|
|
|
|
|
|
|
2018-08-15 18:53:54 +00:00
|
|
|
|
|
|
|
class InfodeskMixin(CampViewMixin, PermissionRequiredMixin):
|
|
|
|
permission_required = ("camps.infodesk_permission")
|
|
|
|
|
|
|
|
|
|
|
|
class BackofficeIndexView(InfodeskMixin, TemplateView):
|
2018-06-03 16:33:51 +00:00
|
|
|
template_name = "index.html"
|
2017-10-03 19:14:07 +00:00
|
|
|
|
2018-06-03 13:34:04 +00:00
|
|
|
|
2018-08-15 18:53:54 +00:00
|
|
|
class ProductHandoutView(InfodeskMixin, ListView):
|
2017-12-12 20:57:17 +00:00
|
|
|
template_name = "product_handout.html"
|
2018-08-01 09:33:36 +00:00
|
|
|
|
|
|
|
def get_queryset(self, **kwargs):
|
|
|
|
return OrderProductRelation.objects.filter(
|
|
|
|
handed_out=False,
|
|
|
|
order__paid=True,
|
|
|
|
order__refunded=False,
|
|
|
|
order__cancelled=False
|
|
|
|
).order_by('order')
|
2017-10-03 19:14:07 +00:00
|
|
|
|
2017-12-12 20:57:17 +00:00
|
|
|
|
2018-08-15 18:53:54 +00:00
|
|
|
class BadgeHandoutView(InfodeskMixin, ListView):
|
2017-12-12 20:57:17 +00:00
|
|
|
template_name = "badge_handout.html"
|
|
|
|
context_object_name = 'tickets'
|
|
|
|
|
|
|
|
def get_queryset(self, **kwargs):
|
|
|
|
shoptickets = ShopTicket.objects.filter(badge_handed_out=False)
|
|
|
|
sponsortickets = SponsorTicket.objects.filter(badge_handed_out=False)
|
|
|
|
discounttickets = DiscountTicket.objects.filter(badge_handed_out=False)
|
|
|
|
return list(chain(shoptickets, sponsortickets, discounttickets))
|
|
|
|
|
|
|
|
|
2018-08-15 21:47:25 +00:00
|
|
|
class TicketCheckinView(InfodeskMixin, ListView):
|
2017-12-12 20:57:17 +00:00
|
|
|
template_name = "ticket_checkin.html"
|
|
|
|
context_object_name = 'tickets'
|
|
|
|
|
|
|
|
def get_queryset(self, **kwargs):
|
|
|
|
shoptickets = ShopTicket.objects.filter(checked_in=False)
|
|
|
|
sponsortickets = SponsorTicket.objects.filter(checked_in=False)
|
|
|
|
discounttickets = DiscountTicket.objects.filter(checked_in=False)
|
|
|
|
return list(chain(shoptickets, sponsortickets, discounttickets))
|
|
|
|
|
2018-04-22 06:28:46 +00:00
|
|
|
|
2018-08-15 21:47:25 +00:00
|
|
|
class BackofficeViewMixin(CampViewMixin, UserPassesTestMixin):
|
|
|
|
"""
|
|
|
|
Mixin used by all backoffice views. For now just uses CampViewMixin and StaffMemberRequiredMixin.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def test_func(self):
|
|
|
|
return self.request.user.is_superuser
|
|
|
|
|
|
|
|
|
2018-06-03 13:34:04 +00:00
|
|
|
class ApproveNamesView(BackofficeViewMixin, ListView):
|
2018-04-22 06:28:46 +00:00
|
|
|
template_name = "approve_public_credit_names.html"
|
|
|
|
context_object_name = 'profiles'
|
|
|
|
|
|
|
|
def get_queryset(self, **kwargs):
|
|
|
|
return Profile.objects.filter(public_credit_name_approved=False).exclude(public_credit_name='')
|
|
|
|
|
2018-06-03 13:34:04 +00:00
|
|
|
|
|
|
|
class ManageProposalsView(BackofficeViewMixin, ListView):
|
|
|
|
"""
|
|
|
|
This view shows a list of pending SpeakerProposal and EventProposals.
|
|
|
|
"""
|
|
|
|
template_name = "manage_proposals.html"
|
|
|
|
context_object_name = 'speakerproposals'
|
|
|
|
|
|
|
|
def get_queryset(self, **kwargs):
|
|
|
|
return SpeakerProposal.objects.filter(
|
2018-06-03 16:33:51 +00:00
|
|
|
camp=self.camp,
|
2018-06-03 13:34:04 +00:00
|
|
|
proposal_status=SpeakerProposal.PROPOSAL_PENDING
|
|
|
|
)
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context['eventproposals'] = EventProposal.objects.filter(
|
2018-06-03 16:33:51 +00:00
|
|
|
track__camp=self.camp,
|
2018-06-03 13:34:04 +00:00
|
|
|
proposal_status=EventProposal.PROPOSAL_PENDING
|
|
|
|
)
|
|
|
|
return context
|
|
|
|
|
|
|
|
|
|
|
|
class ProposalManageView(BackofficeViewMixin, UpdateView):
|
|
|
|
"""
|
|
|
|
This class contains the shared logic between SpeakerProposalManageView and EventProposalManageView
|
|
|
|
"""
|
|
|
|
fields = []
|
|
|
|
|
|
|
|
def form_valid(self, form):
|
|
|
|
"""
|
|
|
|
We have two submit buttons in this form, Approve and Reject
|
|
|
|
"""
|
|
|
|
logger.debug(form.data)
|
|
|
|
if 'approve' in form.data:
|
|
|
|
# approve button was pressed
|
|
|
|
form.instance.mark_as_approved(self.request)
|
|
|
|
elif 'reject' in form.data:
|
|
|
|
# reject button was pressed
|
|
|
|
form.instance.mark_as_rejected(self.request)
|
|
|
|
else:
|
|
|
|
messages.error(self.request, "Unknown submit action")
|
2018-06-03 16:33:51 +00:00
|
|
|
return redirect(reverse('backoffice:manage_proposals', kwargs={'camp_slug': self.camp.slug}))
|
2018-06-03 13:34:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
class SpeakerProposalManageView(ProposalManageView):
|
|
|
|
"""
|
|
|
|
This view allows an admin to approve/reject SpeakerProposals
|
|
|
|
"""
|
|
|
|
model = SpeakerProposal
|
|
|
|
template_name = "manage_speakerproposal.html"
|
|
|
|
|
|
|
|
|
|
|
|
class EventProposalManageView(ProposalManageView):
|
|
|
|
"""
|
|
|
|
This view allows an admin to approve/reject EventProposals
|
|
|
|
"""
|
|
|
|
model = EventProposal
|
|
|
|
template_name = "manage_eventproposal.html"
|
|
|
|
|
2018-08-01 09:50:16 +00:00
|
|
|
|
|
|
|
class MerchandiseOrdersView(BackofficeViewMixin, ListView):
|
|
|
|
template_name = "orders_merchandise.html"
|
|
|
|
|
|
|
|
def get_queryset(self, **kwargs):
|
2018-08-01 10:25:43 +00:00
|
|
|
camp_prefix = 'BornHack {}'.format(timezone.now().year)
|
2018-08-01 09:50:16 +00:00
|
|
|
|
|
|
|
return OrderProductRelation.objects.filter(
|
|
|
|
handed_out=False,
|
|
|
|
order__paid=True,
|
|
|
|
order__refunded=False,
|
|
|
|
order__cancelled=False,
|
|
|
|
product__category__name='Merchandise',
|
|
|
|
).filter(
|
|
|
|
product__name__startswith=camp_prefix
|
|
|
|
).order_by('order')
|
|
|
|
|
|
|
|
|
|
|
|
class MerchandiseToOrderView(BackofficeViewMixin, TemplateView):
|
|
|
|
template_name = "merchandise_to_order.html"
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
2018-08-01 10:25:43 +00:00
|
|
|
camp_prefix = 'BornHack {}'.format(timezone.now().year)
|
2018-08-01 09:50:16 +00:00
|
|
|
|
|
|
|
order_relations = OrderProductRelation.objects.filter(
|
|
|
|
handed_out=False,
|
|
|
|
order__paid=True,
|
|
|
|
order__refunded=False,
|
|
|
|
order__cancelled=False,
|
|
|
|
product__category__name='Merchandise',
|
|
|
|
).filter(
|
|
|
|
product__name__startswith=camp_prefix
|
|
|
|
)
|
|
|
|
|
|
|
|
merchandise_orders = {}
|
|
|
|
for relation in order_relations:
|
|
|
|
try:
|
|
|
|
quantity = merchandise_orders[relation.product.name] + relation.quantity
|
|
|
|
merchandise_orders[relation.product.name] = quantity
|
|
|
|
except KeyError:
|
|
|
|
merchandise_orders[relation.product.name] = relation.quantity
|
|
|
|
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context['merchandise'] = merchandise_orders
|
|
|
|
return context
|
2018-08-05 07:29:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
class VillageOrdersView(BackofficeViewMixin, ListView):
|
|
|
|
template_name = "orders_village.html"
|
|
|
|
|
|
|
|
def get_queryset(self, **kwargs):
|
|
|
|
camp_prefix = 'BornHack {}'.format(timezone.now().year)
|
|
|
|
|
|
|
|
return OrderProductRelation.objects.filter(
|
|
|
|
handed_out=False,
|
|
|
|
order__paid=True,
|
|
|
|
order__refunded=False,
|
|
|
|
order__cancelled=False,
|
|
|
|
product__category__name='Villages',
|
|
|
|
).filter(
|
|
|
|
product__name__startswith=camp_prefix
|
|
|
|
).order_by('order')
|
|
|
|
|
|
|
|
|
|
|
|
class VillageToOrderView(BackofficeViewMixin, TemplateView):
|
|
|
|
template_name = "village_to_order.html"
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
camp_prefix = 'BornHack {}'.format(timezone.now().year)
|
|
|
|
|
|
|
|
order_relations = OrderProductRelation.objects.filter(
|
|
|
|
handed_out=False,
|
|
|
|
order__paid=True,
|
|
|
|
order__refunded=False,
|
|
|
|
order__cancelled=False,
|
|
|
|
product__category__name='Villages',
|
|
|
|
).filter(
|
|
|
|
product__name__startswith=camp_prefix
|
|
|
|
)
|
|
|
|
|
|
|
|
village_orders = {}
|
|
|
|
for relation in order_relations:
|
|
|
|
try:
|
|
|
|
quantity = village_orders[relation.product.name] + relation.quantity
|
|
|
|
village_orders[relation.product.name] = quantity
|
|
|
|
except KeyError:
|
|
|
|
village_orders[relation.product.name] = relation.quantity
|
|
|
|
|
|
|
|
context = super().get_context_data(**kwargs)
|
|
|
|
context['village'] = village_orders
|
|
|
|
return context
|
|
|
|
|