diff --git a/src/backoffice/templates/chain_detail_backoffice.html b/src/backoffice/templates/chain_detail_backoffice.html new file mode 100644 index 00000000..d4b5a831 --- /dev/null +++ b/src/backoffice/templates/chain_detail_backoffice.html @@ -0,0 +1,45 @@ +{% extends 'base.html' %} +{% load bootstrap3 %} + +{% block content %} +

Details for Chain {{ chain.name }}

+Back to Chain list + +

{{ chain.credebtors.count }} Credebtors for Chain {{ chain.name }}

+ + + + + + + + + + + + + + + {% for credebtor in chain.credebtors.all %} + + + + + + + + + +
Credebtor NameAddressNotesExpensesExpenses TotalRevenuesRevenues TotalActions
{{ credebtor.name }}
{{ credebtor.address }}
{{ credebtor.notes|default:"N/A" }}{{ credebtor.expenses.count }}{{ credebtor.expenses_total }} DKK{{ credebtor.revenues.count }}{{ credebtor.revenues_total }} DKK + Details + {% endfor %} +
+ +

{{ chain.expenses.count }} Expenses for Chain {{ chain.name }}

+{% include 'includes/expense_list_panel.html' with expense_list=chain.expenses.all %} + +

{{ chain.revenues.count }} Revenues for Chain {{ chain.name }}

+{% include 'includes/revenue_list_panel.html' with revenue_list=chain.revenues.all %} + +{% endblock content %} + diff --git a/src/backoffice/templates/chain_list_backoffice.html b/src/backoffice/templates/chain_list_backoffice.html new file mode 100644 index 00000000..0be6eef3 --- /dev/null +++ b/src/backoffice/templates/chain_list_backoffice.html @@ -0,0 +1,37 @@ +{% extends 'base.html' %} +{% load bootstrap3 %} + +{% block title %} +Select Chain | {{ block.super }} +{% endblock %} + +{% block content %} +

Chains

+

Back to Backoffice Index

+ +{% if chain_list %} +
+
+

Chains

+
+
+ +
+
+{% else %} +

No Chains found.

+{% endif %} + +{% endblock %} diff --git a/src/backoffice/templates/credebtor_detail_backoffice.html b/src/backoffice/templates/credebtor_detail_backoffice.html new file mode 100644 index 00000000..bf4f7f16 --- /dev/null +++ b/src/backoffice/templates/credebtor_detail_backoffice.html @@ -0,0 +1,15 @@ +{% extends 'base.html' %} +{% load bootstrap3 %} + +{% block content %} +

Details for Credebtor {{ credebtor.name }} (Chain {{ credebtor.chain.name }})

+Back to Credebtor list + +

{{ credebtor.expenses.count }} Expenses for Credebtor {{ credebtor.name }}

+{% include 'includes/expense_list_panel.html' with expense_list=credebtor.expenses.all %} + +

{{ credebtor.revenues.count }} Revenues for Credebtor {{ credebtor.name }}

+{% include 'includes/revenue_list_panel.html' with revenue_list=credebtor.revenues.all %} + +{% endblock content %} + diff --git a/src/backoffice/templates/index.html b/src/backoffice/templates/index.html index 792c4bc1..d6764c7a 100644 --- a/src/backoffice/templates/index.html +++ b/src/backoffice/templates/index.html @@ -64,6 +64,10 @@ {% if perms.camps.economyteam_permission %}

Economy Team

+ +

Chains

+

Use this view to see the Chains and Credebtors registered in the system.

+

Expenses

Use this view to see and approve/reject expenses.

diff --git a/src/backoffice/urls.py b/src/backoffice/urls.py index ae7ea6e3..5bf4a7e3 100644 --- a/src/backoffice/urls.py +++ b/src/backoffice/urls.py @@ -32,6 +32,31 @@ urlpatterns = [ # economy path('economy/', include([ + # chains & credebtors + path('chains/', + include([ + path( + '', + ChainListView.as_view(), + name='chain_list' + ), + path('/', + include([ + path( + '', + ChainDetailView.as_view(), + name='chain_detail' + ), + path( + '/', + CredebtorDetailView.as_view(), + name='credebtor_detail' + ), + ]), + ), + ]), + ), + # expenses path('expenses/', include([ diff --git a/src/backoffice/views.py b/src/backoffice/views.py index 827391ba..0ad7e8e3 100644 --- a/src/backoffice/views.py +++ b/src/backoffice/views.py @@ -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 ########### diff --git a/src/economy/models.py b/src/economy/models.py index 91439183..99d57982 100644 --- a/src/economy/models.py +++ b/src/economy/models.py @@ -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,