add chain&credebtor views to backoffice
This commit is contained in:
parent
132d65087f
commit
3e79567713
45
src/backoffice/templates/chain_detail_backoffice.html
Normal file
45
src/backoffice/templates/chain_detail_backoffice.html
Normal 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 %}
|
||||
|
37
src/backoffice/templates/chain_list_backoffice.html
Normal file
37
src/backoffice/templates/chain_list_backoffice.html
Normal 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 %}
|
15
src/backoffice/templates/credebtor_detail_backoffice.html
Normal file
15
src/backoffice/templates/credebtor_detail_backoffice.html
Normal 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 %}
|
||||
|
|
@ -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>
|
||||
|
|
|
@ -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([
|
||||
|
|
|
@ -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 ###########
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue