Commit 27805640 authored by Skia's avatar Skia

Improve right handling for accounting

parent 39661b8d
Pipeline #26 failed with stage
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('club', '0001_initial'),
('accounting', '0002_auto_20160502_0952'),
]
operations = [
migrations.AddField(
model_name='bankaccount',
name='club',
field=models.OneToOneField(to='club.Club', related_name='bank_accounts', default=1),
preserve_default=False,
),
migrations.AddField(
model_name='product',
name='club',
field=models.OneToOneField(to='club.Club', related_name='products', default=1),
preserve_default=False,
),
migrations.AlterField(
model_name='clubaccount',
name='club',
field=models.OneToOneField(related_name='club_account', to='club.Club'),
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounting', '0003_auto_20160509_0712'),
]
operations = [
migrations.AlterField(
model_name='product',
name='club',
field=models.ForeignKey(related_name='products', to='club.Club'),
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounting', '0004_auto_20160509_0715'),
]
operations = [
migrations.AlterField(
model_name='bankaccount',
name='club',
field=models.ForeignKey(related_name='bank_accounts', to='club.Club'),
),
]
......@@ -39,11 +39,16 @@ class Customer(models.Model):
def __str__(self):
return self.user.username
class AccountingMixin():
class ProductType(models.Model):
"""
Mixin providing the rights managment for all accounting classes
This describes a product type
Useful only for categorizing, changes are made at the product level for now
"""
def can_be_edited_by(self, user):
name = models.CharField(_('name'), max_length=30)
description = models.TextField(_('description'), null=True, blank=True)
icon = models.ImageField(upload_to='products', null=True, blank=True)
def is_owned_by(self, user):
"""
Method to see if that object can be edited by the given user
"""
......@@ -51,19 +56,10 @@ class AccountingMixin():
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
"""
name = models.CharField(_('name'), max_length=30)
description = models.TextField(_('description'), null=True, blank=True)
icon = models.ImageField(upload_to='products', null=True, blank=True)
def __str__(self):
return self.name
class Product(models.Model, AccountingMixin):
class Product(models.Model):
"""
This describes a product, with all its related informations
"""
......@@ -75,14 +71,35 @@ class Product(models.Model, AccountingMixin):
selling_price = CurrencyField(_('selling price'))
special_selling_price = CurrencyField(_('special selling price'))
icon = models.ImageField(upload_to='products', null=True, blank=True)
club = models.ForeignKey(Club, related_name="products")
def is_owned_by(self, user): # TODO do this for all models
"""
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
def __str__(self):
return self.name
class BankAccount(models.Model, AccountingMixin):
class BankAccount(models.Model):
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)
club = models.ForeignKey(Club, related_name="bank_accounts")
def is_owned_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
m = self.club.get_membership_for(user)
if m is not None and m.role >= 7:
return True
return False
def get_absolute_url(self):
return reverse('accounting:bank_details', kwargs={'b_account_id': self.id})
......@@ -90,18 +107,35 @@ class BankAccount(models.Model, AccountingMixin):
def __str__(self):
return self.name
class ClubAccount(models.Model, AccountingMixin):
class ClubAccount(models.Model):
name = models.CharField(_('name'), max_length=30)
club = models.OneToOneField(Club, related_name="club_accounts")
club = models.OneToOneField(Club, related_name="club_account")
bank_account = models.ForeignKey(BankAccount, related_name="club_accounts")
def is_owned_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
def can_be_edited_by(self, user):
"""
Method to see if that object can be edited by the given user
"""
m = self.club.get_membership_for(user)
if m is not None and m.role >= 7:
return True
return False
def get_absolute_url(self):
return reverse('accounting:club_details', kwargs={'c_account_id': self.id})
def __str__(self):
return self.name
class GeneralJournal(models.Model, AccountingMixin):
class GeneralJournal(models.Model):
"""
Class storing all the operations for a period of time
"""
......@@ -111,13 +145,29 @@ class GeneralJournal(models.Model, AccountingMixin):
closed = models.BooleanField(_('is closed'), default=False)
club_account = models.ForeignKey(ClubAccount, related_name="journals", null=False)
def is_owned_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
def can_be_edited_by(self, user):
"""
Method to see if that object can be edited by the given user
"""
if self.club_account.can_be_edited_by(user):
return True
return 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, AccountingMixin):
class AccountingType(models.Model):
"""
Class describing the accounting types.
......@@ -127,13 +177,21 @@ class AccountingType(models.Model, AccountingMixin):
label = models.CharField(_('label'), max_length=60)
movement_type = models.CharField(_('movement type'), choices=[('credit', 'Credit'), ('debit', 'Debit'), ('neutral', 'Neutral')], max_length=12)
def is_owned_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
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):
class Operation(models.Model):
"""
An operation is a line in the journal, a debit or a credit
"""
......@@ -146,6 +204,26 @@ class Operation(models.Model, AccountingMixin):
done = models.BooleanField(_('is done'), default=False)
type = models.ForeignKey(AccountingType, related_name="operations")
def is_owned_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
m = self.journal.club_account.get_membership_for(user)
if m is not None and m.role >= 7:
return True
return False
def can_be_edited_by(self, user):
"""
Method to see if that object can be edited by the given user
"""
if self.journal.can_be_edited_by(user):
return True
return False
def get_absolute_url(self):
return reverse('accounting:journal_details', kwargs={'j_id': self.journal.id})
......
......@@ -24,7 +24,7 @@ class AccountingTypeEditView(CanViewMixin, UpdateView):
fields = ['code', 'label', 'movement_type']
template_name = 'accounting/account_edit.jinja'
class AccountingTypeCreateView(CanEditMixin, CreateView):
class AccountingTypeCreateView(CanEditPropMixin, CreateView):
"""
Create an accounting type (for the admins)
"""
......@@ -58,7 +58,7 @@ class BankAccountDetailView(CanViewMixin, DetailView):
pk_url_kwarg = "b_account_id"
template_name = 'accounting/bank_account_details.jinja'
class BankAccountCreateView(CanEditMixin, CreateView):
class BankAccountCreateView(CanEditPropMixin, CreateView):
"""
Create a bank account (for the admins)
"""
......@@ -66,7 +66,7 @@ class BankAccountCreateView(CanEditMixin, CreateView):
fields = ['name', 'rib', 'number']
template_name = 'accounting/account_edit.jinja'
class BankAccountDeleteView(CanEditMixin, DeleteView): # TODO change Delete to Close
class BankAccountDeleteView(CanEditPropMixin, DeleteView): # TODO change Delete to Close
"""
Delete a bank account (for the admins)
"""
......@@ -94,7 +94,7 @@ class ClubAccountDetailView(CanViewMixin, DetailView):
pk_url_kwarg = "c_account_id"
template_name = 'accounting/club_account_details.jinja'
class ClubAccountCreateView(CanEditMixin, CreateView):
class ClubAccountCreateView(CanEditPropMixin, CreateView):
"""
Create a club account (for the admins)
"""
......@@ -102,7 +102,7 @@ class ClubAccountCreateView(CanEditMixin, CreateView):
fields = ['name', 'club', 'bank_account']
template_name = 'accounting/account_edit.jinja'
class ClubAccountDeleteView(CanEditMixin, DeleteView): # TODO change Delete to Close
class ClubAccountDeleteView(CanEditPropMixin, DeleteView): # TODO change Delete to Close
"""
Delete a club account (for the admins)
"""
......
{% extends "core/base.jinja" %}
{% block content %}
<h3>Club tools</h3>
<p><a href="{{ url('club:club_view', club_id=object.id) }}">Back to club</a></p>
<ul>
<li><a href="{{ url('accounting:club_details', c_account_id=object.club_account.id) }}">{{ object }}</a></li>
</ul>
{% endblock %}
......@@ -9,9 +9,6 @@ urlpatterns = [
url(r'^(?P<club_id>[0-9]+)/edit$', ClubEditView.as_view(), name='club_edit'),
url(r'^(?P<club_id>[0-9]+)/members$', ClubMembersView.as_view(), name='club_members'),
url(r'^(?P<club_id>[0-9]+)/prop$', ClubEditPropView.as_view(), name='club_prop'),
#url(r'^(?P<club_id>[0-9]+)/tools$', ClubToolsView.as_view(), name='club_tools'),
## API
#url(r'^api/markdown$', render_markdown, name='api_markdown'),
url(r'^(?P<club_id>[0-9]+)/tools$', ClubToolsView.as_view(), name='tools'),
]
......@@ -25,6 +25,14 @@ class ClubView(CanViewMixin, DetailView):
pk_url_kwarg = "club_id"
template_name = 'club/club_detail.jinja'
class ClubToolsView(CanViewMixin, DetailView):
"""
Tools page of a Club
"""
model = Club
pk_url_kwarg = "club_id"
template_name = 'club/club_tools.jinja'
class ClubMemberForm(forms.ModelForm):
"""
Form handling the members of a club
......
......@@ -5,7 +5,7 @@ from django.conf import settings
from core.models import Group, User, Page, PageRev
from accounting.models import Customer, GeneralJournal, ProductType, Product, BankAccount, ClubAccount, Operation
from accounting.models import Customer, GeneralJournal, ProductType, Product, BankAccount, ClubAccount, Operation, AccountingType
from club.models import Club, Membership
from subscription.models import Subscription, Subscriber
......@@ -41,13 +41,13 @@ Welcome to the wiki page!
# Here we add a lot of test datas, that are not necessary for the Sith, but that provide a basic development environment
if not options['prod']:
# Adding user Skia
s = User(username='skia', last_name="Kia", first_name="S'",
skia = User(username='skia', last_name="Kia", first_name="S'",
email="skia@git.an",
date_of_birth="1942-06-12")
s.set_password("plop")
s.save()
s.view_groups=[Group.objects.filter(name=settings.SITH_MAIN_MEMBERS_GROUP).first().id]
s.save()
skia.set_password("plop")
skia.save()
skia.view_groups=[Group.objects.filter(name=settings.SITH_MAIN_MEMBERS_GROUP).first().id]
skia.save()
# Adding user public
public = User(username='public', last_name="Not subscribed", first_name="Public",
email="public@git.an",
......@@ -66,6 +66,16 @@ Welcome to the wiki page!
subscriber.save()
subscriber.view_groups=[Group.objects.filter(name=settings.SITH_MAIN_MEMBERS_GROUP).first().id]
subscriber.save()
# Adding user Comptable
comptable = User(username='comptable', last_name="Able", first_name="Compte",
email="compta@git.an",
date_of_birth="1942-06-12",
is_superuser=False, is_staff=False)
comptable.set_password("plop")
comptable.save()
comptable.view_groups=[Group.objects.filter(name=settings.SITH_MAIN_MEMBERS_GROUP).first().id]
comptable.groups=[Group.objects.filter(name=settings.SITH_GROUPS['accounting-admin']['name']).first().id]
comptable.save()
# Adding user Guy
u = User(username='guy', last_name="Carlier", first_name="Guy",
email="guy@git.an",
......@@ -86,21 +96,24 @@ Welcome to the wiki page!
# Adding syntax help page
p = Page(name='Aide_sur_la_syntaxe')
p.save()
PageRev(page=p, title="Aide sur la syntaxe", author=s, content="""
PageRev(page=p, title="Aide sur la syntaxe", author=skia, content="""
Cette page vise à documenter la syntaxe *Markdown* utilisée sur le site.
""").save()
# Adding README
p = Page(name='README')
p.save()
p.view_groups=[settings.SITH_GROUPS['public']['id']]
p.set_lock(s)
p.set_lock(skia)
p.save()
with open(os.path.join(root_path)+'/README.md', 'r') as rm:
PageRev(page=p, title="REAMDE", author=s, content=rm.read()).save()
PageRev(page=p, title="REAMDE", author=skia, content=rm.read()).save()
# Subscription
## Skia
Subscription(member=Subscriber.objects.filter(pk=s.pk).first(), subscription_type=list(settings.SITH_SUBSCRIPTIONS.keys())[0],
Subscription(member=Subscriber.objects.filter(pk=skia.pk).first(), subscription_type=list(settings.SITH_SUBSCRIPTIONS.keys())[0],
payment_method=settings.SITH_SUBSCRIPTION_PAYMENT_METHOD[0]).save()
## Comptable
Subscription(member=Subscriber.objects.filter(pk=comptable.pk).first(), subscription_type=list(settings.SITH_SUBSCRIPTIONS.keys())[0],
payment_method=settings.SITH_SUBSCRIPTION_PAYMENT_METHOD[0]).save()
## Richard
Subscription(member=Subscriber.objects.filter(pk=r.pk).first(), subscription_type=list(settings.SITH_SUBSCRIPTIONS.keys())[0],
......@@ -119,28 +132,29 @@ Cette page vise à documenter la syntaxe *Markdown* utilisée sur le site.
address="Woenzel", parent=guyut).save()
Club(name="BdF", unix_name="bdf",
address="Guyéuéyuéyuyé").save()
Membership(user=s, club=ae, role=3, description="").save()
Membership(user=skia, club=ae, role=3, description="").save()
troll = Club(name="Troll Penché", unix_name="troll",
address="Terre Du Milieu", parent=ae)
troll.save()
# Accounting test values:
Customer(user=s, account_id="6568j").save()
Customer(user=skia, account_id="6568j").save()
p = ProductType(name="Bières bouteilles")
p.save()
Product(name="Barbar", code="BARB", product_type=p, purchase_price="1.50", selling_price="1.7",
special_selling_price="1.6").save()
special_selling_price="1.6", club=ae).save()
Product(name="Chimay", code="CBLE", product_type=p, purchase_price="1.50", selling_price="1.7",
special_selling_price="1.6").save()
special_selling_price="1.6", club=ae).save()
Product(name="Corsendonk", code="CORS", product_type=p, purchase_price="1.50", selling_price="1.7",
special_selling_price="1.6").save()
special_selling_price="1.6", club=ae).save()
Product(name="Carolus", code="CARO", product_type=p, purchase_price="1.50", selling_price="1.7",
special_selling_price="1.6").save()
BankAccount(name="AE TG").save()
BankAccount(name="Carte AE").save()
ba = BankAccount(name="AE TI")
special_selling_price="1.6", club=ae).save()
BankAccount(name="AE TG", club=ae).save()
BankAccount(name="Carte AE", club=ae).save()
ba = BankAccount(name="AE TI", club=ae)
ba.save()
ca = ClubAccount(name="Troll Penché", bank_account=ba, club=troll)
ca.save()
AccountingType(code=666, label="Guy credit", movement_type='credit').save()
AccountingType(code=4000, label="Guy debit", movement_type='debit').save()
......@@ -207,14 +207,12 @@ class User(AbstractBaseUser, PermissionsMixin):
"""
Determine if the object is owned by the user
"""
if not hasattr(obj, "owner_group"):
return False
if (self.is_superuser or self.is_in_group(obj.owner_group.name) or
self.has_perm(obj.__class__.__module__.split('.')[0]+".change_prop_"+obj.__class__.__name__.lower()) or
self.groups.filter(id=settings.SITH_GROUPS['root']['id']).exists()):
return True
if hasattr(obj, "is_owned_by") and obj.is_owned_by(self):
return True
if hasattr(obj, "owner_group") and self.is_in_group(obj.owner_group.name):
return False
if self.is_superuser or self.is_in_group(settings.SITH_GROUPS['root']['name']):
return True
return False
def can_edit(self, obj):
......@@ -231,8 +229,6 @@ class User(AbstractBaseUser, PermissionsMixin):
return True
if hasattr(obj, "can_be_edited_by") and obj.can_be_edited_by(self):
return True
if self.has_perm(obj.__class__.__module__.split('.')[0]+".change_"+obj.__class__.__name__.lower()):
return True
return False
def can_view(self, obj):
......@@ -247,8 +243,6 @@ class User(AbstractBaseUser, PermissionsMixin):
return True
if hasattr(obj, "can_be_viewed_by") and obj.can_be_viewed_by(self):
return True
if self.has_perm(obj.__class__.__module__.split('.')[0]+".view_"+obj.__class__.__name__.lower()):
return True
return False
def can_be_edited_by(self, user):
......
......@@ -8,6 +8,7 @@
<h3>User Tools</h3>
<p><a href="{{ url('core:user_profile', user_id=request.user.id) }}">Back to profile</a></p>
<h4>Sith management</h4>
<ul>
{% if user.is_in_group(settings.SITH_GROUPS['root']['name']) %}
<li><a href="{{ url('core:group_list') }}">Groups</a></li>
......@@ -15,11 +16,17 @@
{% if user.is_in_group(settings.SITH_GROUPS['accounting-admin']['name']) %}
<li><a href="{{ url('accounting:bank_list') }}">Accounting</a></li>
{% endif %}
{% if user.is_in_group(settings.SITH_GROUPS['root']['name']) or user.is_in_group(settings.SITH_MAIN_BOARD_GROUP) %}
{% if user.is_in_group(settings.SITH_MAIN_BOARD_GROUP) or user.is_in_group(settings.SITH_GROUPS['root']['name']) %}
<li><a href="{{ url('subscription:subscription') }}">Subscriptions</a></li>
<li><a href="{{ url('counter:admin_list') }}">Counters management</a></li>
{% endif %}
</ul>
<h4>Clubs</h4>
<ul>
{% for m in user.membership.filter(end_date=None).all() %}
<li><a href="{{ url('club:tools', club_id=m.club.id) }}">{{ m.club }}</a></li>
{% endfor %}
</ul>
{% endblock %}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment