diff --git a/accounting/admin.py b/accounting/admin.py
index 12999c6a..65f35fb9 100644
--- a/accounting/admin.py
+++ b/accounting/admin.py
@@ -9,6 +9,7 @@ admin.site.register(Product)
admin.site.register(BankAccount)
admin.site.register(ClubAccount)
admin.site.register(GeneralJournal)
+admin.site.register(AccountingType)
admin.site.register(Operation)
diff --git a/accounting/migrations/0002_auto_20160502_0952.py b/accounting/migrations/0002_auto_20160502_0952.py
new file mode 100644
index 00000000..a7c8f532
--- /dev/null
+++ b/accounting/migrations/0002_auto_20160502_0952.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('accounting', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='operation',
+ name='journal',
+ field=models.ForeignKey(to='accounting.GeneralJournal', related_name='operations'),
+ ),
+ ]
diff --git a/accounting/models.py b/accounting/models.py
index 02a4fdb7..d8a4b785 100644
--- a/accounting/models.py
+++ b/accounting/models.py
@@ -39,7 +39,19 @@ class Customer(models.Model):
def __str__(self):
return self.user.username
-class ProductType(models.Model):
+class AccountingMixin():
+ """
+ Mixin providing the rights managment for all accounting classes
+ """
+ def can_be_edited_by(self, user):
+ """
+ Method to see if that object can be edited by the given user
+ """
+ if user.is_in_group(settings.SITH_GROUPS['accounting-admin']['name']):
+ return True
+ return False
+
+class ProductType(models.Model, AccountingMixin):
"""
This describes a product type
Useful only for categorizing, changes are made at the product level for now
@@ -51,7 +63,7 @@ class ProductType(models.Model):
def __str__(self):
return self.name
-class Product(models.Model):
+class Product(models.Model, AccountingMixin):
"""
This describes a product, with all its related informations
"""
@@ -67,7 +79,7 @@ class Product(models.Model):
def __str__(self):
return self.name
-class BankAccount(models.Model):
+class BankAccount(models.Model, AccountingMixin):
name = models.CharField(_('name'), max_length=30)
rib = models.CharField(_('rib'), max_length=255, blank=True)
number = models.CharField(_('account number'), max_length=255, blank=True)
@@ -78,7 +90,7 @@ class BankAccount(models.Model):
def __str__(self):
return self.name
-class ClubAccount(models.Model):
+class ClubAccount(models.Model, AccountingMixin):
name = models.CharField(_('name'), max_length=30)
club = models.OneToOneField(Club, related_name="club_accounts")
bank_account = models.ForeignKey(BankAccount, related_name="club_accounts")
@@ -89,7 +101,7 @@ class ClubAccount(models.Model):
def __str__(self):
return self.name
-class GeneralJournal(models.Model):
+class GeneralJournal(models.Model, AccountingMixin):
"""
Class storing all the operations for a period of time
"""
@@ -99,10 +111,13 @@ class GeneralJournal(models.Model):
closed = models.BooleanField(_('is closed'), default=False)
club_account = models.ForeignKey(ClubAccount, related_name="journals", null=False)
+ def get_absolute_url(self):
+ return reverse('accounting:journal_details', kwargs={'j_id': self.id})
+
def __str__(self):
return self.name
-class AccountingType(models.Model):
+class AccountingType(models.Model, AccountingMixin):
"""
Class describing the accounting types.
@@ -112,11 +127,17 @@ class AccountingType(models.Model):
label = models.CharField(_('label'), max_length=60)
movement_type = models.CharField(_('movement type'), choices=[('credit', 'Credit'), ('debit', 'Debit'), ('neutral', 'Neutral')], max_length=12)
-class Operation(models.Model):
+ def get_absolute_url(self):
+ return reverse('accounting:type_list')
+
+ def __str__(self):
+ return self.movement_type+" - "+self.code+" - "+self.label
+
+class Operation(models.Model, AccountingMixin):
"""
An operation is a line in the journal, a debit or a credit
"""
- journal = models.ForeignKey(GeneralJournal, related_name="invoices", null=False)
+ journal = models.ForeignKey(GeneralJournal, related_name="operations", null=False)
date = models.DateField(_('date'))
remark = models.TextField(_('remark'), max_length=255)
mode = models.CharField(_('payment method'), max_length=255, choices=settings.SITH_ACCOUNTING_PAYMENT_METHOD)
@@ -125,6 +146,9 @@ class Operation(models.Model):
done = models.BooleanField(_('is done'), default=False)
type = models.ForeignKey(AccountingType, related_name="operations")
- def __str__(self):
- return self.journal.name+' - '+self.name
+ def get_absolute_url(self):
+ return reverse('accounting:journal_details', kwargs={'j_id': self.journal.id})
+
+ def __str__(self):
+ return str(self.id)+" - "+str(self.date)
diff --git a/accounting/templates/accounting/accountingtype_list.jinja b/accounting/templates/accounting/accountingtype_list.jinja
new file mode 100644
index 00000000..0961289a
--- /dev/null
+++ b/accounting/templates/accounting/accountingtype_list.jinja
@@ -0,0 +1,23 @@
+{% extends "core/base.jinja" %}
+
+{% block title %}
+ Accounting type list
+{% endblock %}
+
+{% block content %}
+
New accounting type
+ {% if accountingtype_list %}
+ Accounting type list
+
+ {% for a in accountingtype_list %}
+ - {{ a }}
+ {% endfor %}
+
+ {% else %}
+ There is no types in this website.
+ {% endif %}
+{% endblock %}
+
+
+
+
diff --git a/accounting/templates/accounting/bank_account_list.jinja b/accounting/templates/accounting/bank_account_list.jinja
index 2be02051..1ef7eadc 100644
--- a/accounting/templates/accounting/bank_account_list.jinja
+++ b/accounting/templates/accounting/bank_account_list.jinja
@@ -5,6 +5,7 @@
{% endblock %}
{% block content %}
+ Manage accounting types
New bank account
{% if bankaccount_list %}
Bank account list
diff --git a/accounting/templates/accounting/club_account_details.jinja b/accounting/templates/accounting/club_account_details.jinja
index c0eb0a49..3dafe85b 100644
--- a/accounting/templates/accounting/club_account_details.jinja
+++ b/accounting/templates/accounting/club_account_details.jinja
@@ -9,8 +9,12 @@
New journal
- {% for c in object.journals.all() %}
- - {{ c }}
+ {% for j in object.journals.all() %}
+ -
+ {{ j }} -
+ Edit
+
+
{% endfor %}
diff --git a/accounting/templates/accounting/journal_details.jinja b/accounting/templates/accounting/journal_details.jinja
new file mode 100644
index 00000000..aa719279
--- /dev/null
+++ b/accounting/templates/accounting/journal_details.jinja
@@ -0,0 +1,22 @@
+{% extends "core/base.jinja" %}
+
+{% block content %}
+View journal: {{ object.name }}
+
+ {% for k,v in object.__dict__.items() %}
+ - {{ k }} - {{ v }}
+ {% endfor %}
+
+ New operation
+
+ {% for o in object.operations.all() %}
+ -
+ {{ o }}
+
+ {% endfor %}
+
+
+{% endblock %}
+
+
+
diff --git a/accounting/urls.py b/accounting/urls.py
index b42c2aad..33e62379 100644
--- a/accounting/urls.py
+++ b/accounting/urls.py
@@ -3,6 +3,10 @@ from django.conf.urls import url, include
from accounting.views import *
urlpatterns = [
+ # Accounting types
+ url(r'^type$', AccountingTypeListView.as_view(), name='type_list'),
+ url(r'^type/create$', AccountingTypeCreateView.as_view(), name='type_new'),
+ url(r'^type/(?P[0-9]+)/edit$', AccountingTypeEditView.as_view(), name='type_edit'),
# Bank accounts
url(r'^$', BankAccountListView.as_view(), name='bank_list'),
url(r'^bank/create$', BankAccountCreateView.as_view(), name='bank_new'),
@@ -16,6 +20,11 @@ urlpatterns = [
url(r'^club/(?P[0-9]+)/delete$', ClubAccountDeleteView.as_view(), name='club_delete'),
# Journals
url(r'^journal/create$', JournalCreateView.as_view(), name='journal_new'),
+ url(r'^journal/(?P[0-9]+)$', JournalDetailView.as_view(), name='journal_details'),
+ url(r'^journal/(?P[0-9]+)/edit$', JournalEditView.as_view(), name='journal_edit'),
+ # Operations
+ url(r'^operation/create$', OperationCreateView.as_view(), name='op_new'),
+ url(r'^operation/(?P[0-9]+)$', OperationEditView.as_view(), name='op_edit'),
]
diff --git a/accounting/views.py b/accounting/views.py
index a59e061e..a8900e60 100644
--- a/accounting/views.py
+++ b/accounting/views.py
@@ -4,7 +4,33 @@ from django.shortcuts import render
from django.core.urlresolvers import reverse_lazy
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin
-from accounting.models import BankAccount, ClubAccount, GeneralJournal, Operation
+from accounting.models import BankAccount, ClubAccount, GeneralJournal, Operation, AccountingType
+
+# Accounting types
+
+class AccountingTypeListView(CanViewMixin, ListView):
+ """
+ A list view for the admins
+ """
+ model = AccountingType
+ template_name = 'accounting/accountingtype_list.jinja'
+
+class AccountingTypeEditView(CanViewMixin, UpdateView):
+ """
+ An edit view for the admins
+ """
+ model = AccountingType
+ pk_url_kwarg = "type_id"
+ fields = ['code', 'label', 'movement_type']
+ template_name = 'accounting/account_edit.jinja'
+
+class AccountingTypeCreateView(CanEditMixin, CreateView):
+ """
+ Create an accounting type (for the admins)
+ """
+ model = AccountingType
+ fields = ['code', 'label', 'movement_type']
+ template_name = 'accounting/account_edit.jinja'
# BankAccount views
@@ -92,6 +118,42 @@ class JournalCreateView(CanEditMixin, CreateView):
Create a general journal
"""
model = GeneralJournal
- fields = ['name']
+ fields = ['name', 'start_date', 'club_account']
+ template_name = 'accounting/account_edit.jinja'
+
+class JournalDetailView(CanViewMixin, DetailView):
+ """
+ A detail view, listing every operation
+ """
+ model = GeneralJournal
+ pk_url_kwarg = "j_id"
+ template_name = 'accounting/journal_details.jinja'
+
+class JournalEditView(CanEditMixin, UpdateView):
+ """
+ Update a general journal
+ """
+ model = GeneralJournal
+ pk_url_kwarg = "j_id"
+ fields = ['name', 'start_date', 'club_account']
+ template_name = 'accounting/account_edit.jinja'
+
+# Operation views
+
+class OperationCreateView(CanEditMixin, CreateView):
+ """
+ Create an operation
+ """
+ model = Operation
+ fields = ['journal', 'date', 'cheque_number', 'type']
+ template_name = 'accounting/account_edit.jinja'
+
+class OperationEditView(CanViewMixin, UpdateView):
+ """
+ An edit view, working as detail for the moment
+ """
+ model = Operation
+ pk_url_kwarg = "op_id"
+ fields = ['journal', 'date', 'cheque_number', 'type']
template_name = 'accounting/account_edit.jinja'
diff --git a/core/models.py b/core/models.py
index dd14bfdb..80176eee 100644
--- a/core/models.py
+++ b/core/models.py
@@ -266,7 +266,9 @@ class AnonymousUser(AuthAnonymousUser):
return False
def can_view(self, obj):
- if obj.view_groups.filter(pk=settings.SITH_GROUPS['public']['id']).exists():
+ if hasattr(obj, 'view_groups') and obj.view_groups.filter(pk=settings.SITH_GROUPS['public']['id']).exists():
+ return True
+ if hasattr(obj, 'can_be_viewed_by') and obj.can_be_viewed_by(self):
return True
return False
diff --git a/core/templates/core/base.jinja b/core/templates/core/base.jinja
index d4dc4711..22ee71fc 100644
--- a/core/templates/core/base.jinja
+++ b/core/templates/core/base.jinja
@@ -24,6 +24,7 @@
{% if user.is_authenticated() %}
- Profile
+ - Tools
- Users
- Pages
- Clubs
diff --git a/core/templates/core/user_tools.jinja b/core/templates/core/user_tools.jinja
index 28afe295..d99474a1 100644
--- a/core/templates/core/user_tools.jinja
+++ b/core/templates/core/user_tools.jinja
@@ -12,6 +12,9 @@
{% if user.is_in_group(settings.SITH_GROUPS['root']['name']) %}
- Groups
{% endif %}
+{% if user.is_in_group(settings.SITH_GROUPS['accounting-admin']['name']) %}
+ - Accounting
+{% endif %}
{% if user.is_in_group(settings.SITH_GROUPS['root']['name']) or user.is_in_group(settings.SITH_MAIN_BOARD_GROUP) %}
- Subscriptions
- Counters management
diff --git a/sith/settings.py b/sith/settings.py
index acec74ad..2d3a65db 100644
--- a/sith/settings.py
+++ b/sith/settings.py
@@ -189,9 +189,13 @@ SITH_GROUPS = {
'id': 1,
'name': "root",
},
- 'public': {
+ 'accounting-admin': {
'id': 2,
- 'name': "not_registered_users",
+ 'name': "accounting-admin",
+ },
+ 'public': {
+ 'id': 3,
+ 'name': "not-registered-users",
},
}