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 %}
|
{% if perms.camps.economyteam_permission %}
|
||||||
<h3>Economy Team</h3>
|
<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">
|
<a href="{% url 'backoffice:expense_list' camp_slug=camp.slug %}" class="list-group-item">
|
||||||
<h4 class="list-group-item-heading">Expenses</h4>
|
<h4 class="list-group-item-heading">Expenses</h4>
|
||||||
<p class="list-group-item-text">Use this view to see and approve/reject expenses.</p>
|
<p class="list-group-item-text">Use this view to see and approve/reject expenses.</p>
|
||||||
|
|
|
@ -32,6 +32,31 @@ urlpatterns = [
|
||||||
# economy
|
# economy
|
||||||
path('economy/',
|
path('economy/',
|
||||||
include([
|
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
|
# expenses
|
||||||
path('expenses/',
|
path('expenses/',
|
||||||
include([
|
include([
|
||||||
|
|
|
@ -18,7 +18,7 @@ from shop.models import OrderProductRelation
|
||||||
from tickets.models import ShopTicket, SponsorTicket, DiscountTicket
|
from tickets.models import ShopTicket, SponsorTicket, DiscountTicket
|
||||||
from profiles.models import Profile
|
from profiles.models import Profile
|
||||||
from program.models import SpeakerProposal, EventProposal
|
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 utils.mixins import RaisePermissionRequiredMixin
|
||||||
from teams.models import Team
|
from teams.models import Team
|
||||||
from .mixins import *
|
from .mixins import *
|
||||||
|
@ -228,6 +228,27 @@ class VillageToOrderView(CampViewMixin, OrgaTeamPermissionMixin, TemplateView):
|
||||||
return context
|
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 ###########
|
########### EXPENSES ###########
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,16 @@ from django.utils.text import slugify
|
||||||
from utils.models import CampRelatedModel, CreatedUpdatedModel, UUIDModel
|
from utils.models import CampRelatedModel, CreatedUpdatedModel, UUIDModel
|
||||||
from .email import *
|
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):
|
class Chain(CreatedUpdatedModel, UUIDModel):
|
||||||
"""
|
"""
|
||||||
|
@ -19,6 +29,8 @@ class Chain(CreatedUpdatedModel, UUIDModel):
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['name']
|
ordering = ['name']
|
||||||
|
|
||||||
|
objects = ChainManager()
|
||||||
|
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
max_length=100,
|
max_length=100,
|
||||||
unique=True,
|
unique=True,
|
||||||
|
@ -44,6 +56,25 @@ class Chain(CreatedUpdatedModel, UUIDModel):
|
||||||
self.slug = slugify(self.name)
|
self.slug = slugify(self.name)
|
||||||
super(Chain, self).save(**kwargs)
|
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):
|
class Credebtor(CreatedUpdatedModel, UUIDModel):
|
||||||
"""
|
"""
|
||||||
|
@ -56,6 +87,8 @@ class Credebtor(CreatedUpdatedModel, UUIDModel):
|
||||||
ordering = ['name']
|
ordering = ['name']
|
||||||
unique_together=('chain', 'slug')
|
unique_together=('chain', 'slug')
|
||||||
|
|
||||||
|
objects = CredebtorManager()
|
||||||
|
|
||||||
chain = models.ForeignKey(
|
chain = models.ForeignKey(
|
||||||
'economy.Chain',
|
'economy.Chain',
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
|
|
Loading…
Reference in a new issue