add chain&credebtor views to backoffice

This commit is contained in:
Thomas Steen Rasmussen 2019-03-30 06:54:45 +01:00
parent 132d65087f
commit 3e79567713
7 changed files with 181 additions and 1 deletions

View file

@ -0,0 +1,45 @@
{% extends 'base.html' %}
{% load bootstrap3 %}
{% block content %}
<h2>Details for Chain {{ chain.name }}</h2>
<a href="{% url "backoffice:chain_list" camp_slug=camp.slug %}">Back to Chain list</a>
<h3>{{ chain.credebtors.count }} Credebtors for Chain {{ chain.name }}</h3>
<table class="table table-hover">
<thead>
<tr>
<th>Credebtor Name</th>
<th>Address</th>
<th>Notes</th>
<th class="text-center">Expenses</th>
<th class="text-center">Expenses Total</th>
<th class="text-center">Revenues</th>
<th class="text-center">Revenues Total</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for credebtor in chain.credebtors.all %}
<tr>
<td>{{ credebtor.name }}</td>
<td><address>{{ credebtor.address }}</address></td>
<td>{{ credebtor.notes|default:"N/A" }}</td>
<td class="text-center"><span class="badge">{{ credebtor.expenses.count }}</span></td>
<td class="text-center">{{ credebtor.expenses_total }} DKK</td>
<td class="text-center"><span class="badge">{{ credebtor.revenues.count }}</span></td>
<td class="text-center">{{ credebtor.revenues_total }} DKK</td>
<td>
<a class="btn btn-primary" href="{% url 'backoffice:credebtor_detail' camp_slug=camp.slug chain_slug=chain.slug credebtor_slug=credebtor.slug %}"><i class="fas fa-search"></i> Details</a>
{% endfor %}
</tbody>
</table>
<h3>{{ chain.expenses.count }} Expenses for Chain {{ chain.name }}</h3>
{% include 'includes/expense_list_panel.html' with expense_list=chain.expenses.all %}
<h3>{{ chain.revenues.count }} Revenues for Chain {{ chain.name }}</h3>
{% include 'includes/revenue_list_panel.html' with revenue_list=chain.revenues.all %}
{% endblock content %}

View file

@ -0,0 +1,37 @@
{% extends 'base.html' %}
{% load bootstrap3 %}
{% block title %}
Select Chain | {{ block.super }}
{% endblock %}
{% block content %}
<h2>Chains</h2>
<p><a href="{% url "backoffice:index" camp_slug=camp.slug %}">Back to Backoffice Index</a></p>
{% if chain_list %}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Chains</h3>
</div>
<div class="panel-body">
<div class="list-group">
{% for chain in chain_list %}
<a href="{% url 'backoffice:chain_detail' camp_slug=camp.slug chain_slug=chain.slug %}" class="list-group-item">
<h4 class="list-group-item-heading">
<b>{{ chain.name }}</b> ({{ chain.credebtors.count }} credebtors)
</h4>
<p>{{ chain.name }} has {{ chain.expenses.count }} expenses for a total of {{ chain.expenses_total }} DKK, and {{ chain.revenues.count }} revenues for a total of {{ chain.revenues_total }} DKK</p>
{% if chain.notes %}
<p><b>Notes:</b> {{ chain.notes }}</p>
{% endif %}
</a>
{% endfor %}
</div>
</div>
</div>
{% else %}
<p class="lead"><i>No Chains found.</i></p>
{% endif %}
{% endblock %}

View file

@ -0,0 +1,15 @@
{% extends 'base.html' %}
{% load bootstrap3 %}
{% block content %}
<h2>Details for Credebtor {{ credebtor.name }} (Chain {{ credebtor.chain.name }})</h2>
<a href="{% url "backoffice:chain_detail" camp_slug=camp.slug chain_slug=credebtor.chain.slug %}">Back to Credebtor list</a>
<h3>{{ credebtor.expenses.count }} Expenses for Credebtor {{ credebtor.name }}</h3>
{% include 'includes/expense_list_panel.html' with expense_list=credebtor.expenses.all %}
<h3>{{ credebtor.revenues.count }} Revenues for Credebtor {{ credebtor.name }}</h3>
{% include 'includes/revenue_list_panel.html' with revenue_list=credebtor.revenues.all %}
{% endblock content %}

View file

@ -64,6 +64,10 @@
{% if perms.camps.economyteam_permission %}
<h3>Economy Team</h3>
<a href="{% url 'backoffice:chain_list' camp_slug=camp.slug %}" class="list-group-item">
<h4 class="list-group-item-heading">Chains</h4>
<p class="list-group-item-text">Use this view to see the Chains and Credebtors registered in the system.</p>
</a>
<a href="{% url 'backoffice:expense_list' camp_slug=camp.slug %}" class="list-group-item">
<h4 class="list-group-item-heading">Expenses</h4>
<p class="list-group-item-text">Use this view to see and approve/reject expenses.</p>

View file

@ -32,6 +32,31 @@ urlpatterns = [
# economy
path('economy/',
include([
# chains & credebtors
path('chains/',
include([
path(
'',
ChainListView.as_view(),
name='chain_list'
),
path('<slug:chain_slug>/',
include([
path(
'',
ChainDetailView.as_view(),
name='chain_detail'
),
path(
'<slug:credebtor_slug>/',
CredebtorDetailView.as_view(),
name='credebtor_detail'
),
]),
),
]),
),
# expenses
path('expenses/',
include([

View file

@ -18,7 +18,7 @@ from shop.models import OrderProductRelation
from tickets.models import ShopTicket, SponsorTicket, DiscountTicket
from profiles.models import Profile
from program.models import SpeakerProposal, EventProposal
from economy.models import Expense, Reimbursement, Revenue
from economy.models import Chain, Credebtor, Expense, Reimbursement, Revenue
from utils.mixins import RaisePermissionRequiredMixin
from teams.models import Team
from .mixins import *
@ -228,6 +228,27 @@ class VillageToOrderView(CampViewMixin, OrgaTeamPermissionMixin, TemplateView):
return context
################################
###### CHAINS & CREDEBTORS #####
class ChainListView(CampViewMixin, EconomyTeamPermissionMixin, ListView):
model = Chain
template_name = 'chain_list_backoffice.html'
class ChainDetailView(CampViewMixin, EconomyTeamPermissionMixin, DetailView):
model = Chain
template_name = 'chain_detail_backoffice.html'
slug_url_kwarg = 'chain_slug'
class CredebtorDetailView(CampViewMixin, EconomyTeamPermissionMixin, DetailView):
model = Credebtor
template_name = 'credebtor_detail_backoffice.html'
slug_url_kwarg = 'credebtor_slug'
################################
########### EXPENSES ###########

View file

@ -10,6 +10,16 @@ from django.utils.text import slugify
from utils.models import CampRelatedModel, CreatedUpdatedModel, UUIDModel
from .email import *
class ChainManager(models.Manager):
"""
ChainManager adds 'expenses_total' and 'revenues_total' to the Chain qs
"""
def get_queryset(self):
qs = super().get_queryset()
qs = qs.annotate(expenses_total=models.Sum('credebtors__expenses__amount'))
qs = qs.annotate(revenues_total=models.Sum('credebtors__revenues__amount'))
return qs
class Chain(CreatedUpdatedModel, UUIDModel):
"""
@ -19,6 +29,8 @@ class Chain(CreatedUpdatedModel, UUIDModel):
class Meta:
ordering = ['name']
objects = ChainManager()
name = models.CharField(
max_length=100,
unique=True,
@ -44,6 +56,25 @@ class Chain(CreatedUpdatedModel, UUIDModel):
self.slug = slugify(self.name)
super(Chain, self).save(**kwargs)
@property
def expenses(self):
return Expense.objects.filter(creditor__chain__pk=self.pk)
@property
def revenues(self):
return Revenue.objects.filter(debtor__chain__pk=self.pk)
class CredebtorManager(models.Manager):
"""
CredebtorManager adds 'expenses_total' and 'revenues_total' to the Credebtor qs
"""
def get_queryset(self):
qs = super().get_queryset()
qs = qs.annotate(expenses_total=models.Sum('expenses__amount'))
qs = qs.annotate(revenues_total=models.Sum('revenues__amount'))
return qs
class Credebtor(CreatedUpdatedModel, UUIDModel):
"""
@ -56,6 +87,8 @@ class Credebtor(CreatedUpdatedModel, UUIDModel):
ordering = ['name']
unique_together=('chain', 'slug')
objects = CredebtorManager()
chain = models.ForeignKey(
'economy.Chain',
on_delete=models.PROTECT,