Commit c6a3559b authored by Skia's avatar Skia
Browse files

Improve accounting model according to current site's one

parent 9a135ade
...@@ -6,7 +6,9 @@ from accounting.models import * ...@@ -6,7 +6,9 @@ from accounting.models import *
admin.site.register(Customer) admin.site.register(Customer)
admin.site.register(ProductType) admin.site.register(ProductType)
admin.site.register(Product) admin.site.register(Product)
admin.site.register(BankAccount)
admin.site.register(ClubAccount)
admin.site.register(GeneralJournal) admin.site.register(GeneralJournal)
admin.site.register(GenericInvoice) admin.site.register(Operation)
...@@ -2,71 +2,91 @@ ...@@ -2,71 +2,91 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models
from django.conf import settings
import accounting.models import accounting.models
from django.conf import settings
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('club', '__first__'),
('core', '0001_initial'), ('core', '0001_initial'),
] ]
operations = [ operations = [
migrations.CreateModel(
name='BankAccount',
fields=[
('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)),
('name', models.CharField(verbose_name='name', max_length=30)),
('rib', models.CharField(verbose_name='rib', max_length=255)),
('number', models.CharField(verbose_name='account number', max_length=255)),
],
),
migrations.CreateModel(
name='ClubAccount',
fields=[
('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)),
('name', models.CharField(verbose_name='name', max_length=30)),
('bank_account', models.ForeignKey(related_name='club_accounts', to='accounting.BankAccount')),
('club', models.OneToOneField(related_name='club_accounts', to='club.Club')),
],
),
migrations.CreateModel( migrations.CreateModel(
name='Customer', name='Customer',
fields=[ fields=[
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, serialize=False, primary_key=True)), ('user', models.OneToOneField(primary_key=True, to=settings.AUTH_USER_MODEL, serialize=False)),
('account_id', models.CharField(max_length=10, verbose_name='account id', unique=True)), ('account_id', models.CharField(verbose_name='account id', unique=True, max_length=10)),
], ],
options={ options={
'verbose_name': 'customer',
'verbose_name_plural': 'customers', 'verbose_name_plural': 'customers',
'verbose_name': 'customer',
}, },
), ),
migrations.CreateModel( migrations.CreateModel(
name='GeneralJournal', name='GeneralJournal',
fields=[ fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)), ('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)),
('start_date', models.DateField(verbose_name='start date')), ('start_date', models.DateField(verbose_name='start date')),
('end_date', models.DateField(default=None, blank=True, null=True, verbose_name='end date')), ('end_date', models.DateField(default=None, verbose_name='end date', null=True, blank=True)),
('name', models.CharField(max_length=30, verbose_name='name')), ('name', models.CharField(verbose_name='name', max_length=30)),
('closed', models.BooleanField(default=False, verbose_name='is closed')), ('closed', models.BooleanField(default=False, verbose_name='is closed')),
('club_account', models.ForeignKey(related_name='journals', to='accounting.ClubAccount')),
], ],
), ),
migrations.CreateModel( migrations.CreateModel(
name='GenericInvoice', name='Operation',
fields=[ fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)), ('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)),
('name', models.CharField(max_length=100, verbose_name='name')), ('name', models.CharField(verbose_name='name', max_length=100)),
('journal', models.ForeignKey(to='accounting.GeneralJournal', related_name='invoices')), ('journal', models.ForeignKey(related_name='invoices', to='accounting.GeneralJournal')),
], ],
), ),
migrations.CreateModel( migrations.CreateModel(
name='Product', name='Product',
fields=[ fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)), ('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)),
('name', models.CharField(max_length=30, verbose_name='name')), ('name', models.CharField(verbose_name='name', max_length=30)),
('description', models.TextField(blank=True, verbose_name='description')), ('description', models.TextField(blank=True, verbose_name='description')),
('code', models.CharField(max_length=10, verbose_name='code')), ('code', models.CharField(verbose_name='code', max_length=10)),
('purchase_price', accounting.models.CurrencyField(max_digits=12, verbose_name='purchase price', decimal_places=2)), ('purchase_price', accounting.models.CurrencyField(verbose_name='purchase price', decimal_places=2, max_digits=12)),
('selling_price', accounting.models.CurrencyField(max_digits=12, verbose_name='selling price', decimal_places=2)), ('selling_price', accounting.models.CurrencyField(verbose_name='selling price', decimal_places=2, max_digits=12)),
('special_selling_price', accounting.models.CurrencyField(max_digits=12, verbose_name='special selling price', decimal_places=2)), ('special_selling_price', accounting.models.CurrencyField(verbose_name='special selling price', decimal_places=2, max_digits=12)),
('icon', models.ImageField(upload_to='products', blank=True, null=True)), ('icon', models.ImageField(blank=True, null=True, upload_to='products')),
], ],
), ),
migrations.CreateModel( migrations.CreateModel(
name='ProductType', name='ProductType',
fields=[ fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)), ('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)),
('name', models.CharField(max_length=30, verbose_name='name')), ('name', models.CharField(verbose_name='name', max_length=30)),
('description', models.TextField(blank=True, null=True, verbose_name='description')), ('description', models.TextField(blank=True, verbose_name='description', null=True)),
('icon', models.ImageField(upload_to='products', blank=True, null=True)), ('icon', models.ImageField(blank=True, null=True, upload_to='products')),
], ],
), ),
migrations.AddField( migrations.AddField(
model_name='product', model_name='product',
name='product_type', name='product_type',
field=models.ForeignKey(blank=True, related_name='products', to='accounting.ProductType', null=True), field=models.ForeignKey(blank=True, related_name='products', null=True, to='accounting.ProductType'),
), ),
] ]
# -*- 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='bankaccount',
name='number',
field=models.CharField(max_length=255, blank=True, verbose_name='account number'),
),
migrations.AlterField(
model_name='bankaccount',
name='rib',
field=models.CharField(max_length=255, blank=True, verbose_name='rib'),
),
]
from django.db import models from django.db import models
from django.conf import settings
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from decimal import Decimal from decimal import Decimal
from core.models import User from core.models import User
from club.models import Club
class CurrencyField(models.DecimalField): class CurrencyField(models.DecimalField):
""" """
...@@ -64,31 +66,58 @@ class Product(models.Model): ...@@ -64,31 +66,58 @@ class Product(models.Model):
def __str__(self): def __str__(self):
return self.name return self.name
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)
def __str__(self):
return self.name
class ClubAccount(models.Model):
name = models.CharField(_('name'), max_length=30)
club = models.OneToOneField(Club, related_name="club_accounts")
bank_account = models.ForeignKey(BankAccount, related_name="club_accounts")
def __str__(self):
return self.name
class GeneralJournal(models.Model): class GeneralJournal(models.Model):
""" """
Class storing all the invoices for a period of time Class storing all the operations for a period of time
""" """
start_date = models.DateField(_('start date')) start_date = models.DateField(_('start date'))
end_date = models.DateField(_('end date'), null=True, blank=True, default=None) end_date = models.DateField(_('end date'), null=True, blank=True, default=None)
name = models.CharField(_('name'), max_length=30) name = models.CharField(_('name'), max_length=30)
closed = models.BooleanField(_('is closed'), default=False) closed = models.BooleanField(_('is closed'), default=False)
# When clubs are done: ForeignKey(Proprietary) club_account = models.ForeignKey(ClubAccount, related_name="journals", null=False)
def __str__(self): def __str__(self):
return self.name return self.name
class AccountingType(models.Model):
"""
Class describing the accounting types.
class GenericInvoice(models.Model): Thoses are numbers used in accounting to classify operations
""" """
This class is a generic invoice, made to be extended with some special cases (eg: for the internal accounting, payment code = models.CharField(_('code'), max_length=16) # TODO: add number validator
system, etc...) label = models.CharField(_('label'), max_length=60)
movement_type = models.CharField(_('movement type'), choices=[('credit', 'Credit'), ('debit', 'Debit'), ('neutral', 'Neutral')])
class Operation(models.Model):
"""
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="invoices", null=False)
name = models.CharField(_('name'), max_length=100) 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)
cheque_number = models.IntegerField(_('cheque number'))
invoice = models.FileField(upload_to='invoices', null=True, blank=True)
done = models.BooleanField(_('is done'), default=False)
type = models.ForeignKey(AccountingType, related_name="operations")
def __str__(self): def __str__(self):
return self.journal.name+' - '+self.name return self.journal.name+' - '+self.name
# TODO: CountingInvoice in Counting app extending GenericInvoice
# - ManyToMany Product
...@@ -111,8 +111,8 @@ class Membership(models.Model): ...@@ -111,8 +111,8 @@ class Membership(models.Model):
club = models.ForeignKey(Club, related_name="members", null=False, blank=False) club = models.ForeignKey(Club, related_name="members", null=False, blank=False)
start_date = models.DateField(_('start date'), auto_now=True) start_date = models.DateField(_('start date'), auto_now=True)
end_date = models.DateField(_('end date'), null=True, blank=True) end_date = models.DateField(_('end date'), null=True, blank=True)
role = models.IntegerField(_('role'), choices=sorted(settings.CLUB_ROLES.items()), role = models.IntegerField(_('role'), choices=sorted(settings.SITH_CLUB_ROLES.items()),
default=sorted(settings.CLUB_ROLES.items())[0][0]) default=sorted(settings.SITH_CLUB_ROLES.items())[0][0])
description = models.CharField(_('description'), max_length=30, null=False, blank=True) description = models.CharField(_('description'), max_length=30, null=False, blank=True)
def clean(self): def clean(self):
...@@ -123,7 +123,7 @@ class Membership(models.Model): ...@@ -123,7 +123,7 @@ class Membership(models.Model):
raise ValidationError(_('User is already member of that club')) raise ValidationError(_('User is already member of that club'))
def __str__(self): def __str__(self):
return self.club.name+' - '+self.user.username+' - '+settings.CLUB_ROLES[self.role]+str( return self.club.name+' - '+self.user.username+' - '+settings.SITH_CLUB_ROLES[self.role]+str(
" - "+str(_('past member')) if self.end_date is not None else "" " - "+str(_('past member')) if self.end_date is not None else ""
) )
......
...@@ -8,7 +8,7 @@ from django.core.exceptions import ValidationError ...@@ -8,7 +8,7 @@ from django.core.exceptions import ValidationError
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin
from club.models import Club, Membership from club.models import Club, Membership
from sith.settings import MAXIMUM_FREE_ROLE, SITH_MAIN_BOARD_GROUP from sith.settings import SITH_MAXIMUM_FREE_ROLE, SITH_MAIN_BOARD_GROUP
class ClubListView(CanViewMixin, ListView): class ClubListView(CanViewMixin, ListView):
""" """
...@@ -42,7 +42,7 @@ class ClubMemberForm(forms.ModelForm): ...@@ -42,7 +42,7 @@ class ClubMemberForm(forms.ModelForm):
""" """
ret = super(ClubMemberForm, self).clean() ret = super(ClubMemberForm, self).clean()
ms = self.instance.club.get_membership_for(self._user) ms = self.instance.club.get_membership_for(self._user)
if (self.cleaned_data['role'] <= MAXIMUM_FREE_ROLE or if (self.cleaned_data['role'] <= SITH_MAXIMUM_FREE_ROLE or
(ms is not None and ms.role >= self.cleaned_data['role']) or (ms is not None and ms.role >= self.cleaned_data['role']) or
self._user.is_in_group(SITH_MAIN_BOARD_GROUP) or self._user.is_in_group(SITH_MAIN_BOARD_GROUP) or
self._user.is_superuser): self._user.is_superuser):
......
...@@ -5,7 +5,7 @@ from django.conf import settings ...@@ -5,7 +5,7 @@ from django.conf import settings
from core.models import Group, User, Page, PageRev from core.models import Group, User, Page, PageRev
from accounting.models import Customer, GeneralJournal, ProductType, Product from accounting.models import Customer, GeneralJournal, ProductType, Product, BankAccount, ClubAccount, Operation
from club.models import Club, Membership from club.models import Club, Membership
from subscription.models import Subscription, Subscriber from subscription.models import Subscription, Subscriber
...@@ -84,10 +84,10 @@ Cette page vise à documenter la syntaxe *Markdown* utilisée sur le site. ...@@ -84,10 +84,10 @@ Cette page vise à documenter la syntaxe *Markdown* utilisée sur le site.
# Subscription # Subscription
## Skia ## Skia
Subscription(member=Subscriber.objects.filter(pk=s.pk).first(), subscription_type=list(settings.SITH_SUBSCRIPTIONS.keys())[0], Subscription(member=Subscriber.objects.filter(pk=s.pk).first(), subscription_type=list(settings.SITH_SUBSCRIPTIONS.keys())[0],
payment_method=settings.SITH_PAYMENT_METHOD[0]).save() payment_method=settings.SITH_SUBSCRIPTION_PAYMENT_METHOD[0]).save()
## Richard ## Richard
Subscription(member=Subscriber.objects.filter(pk=r.pk).first(), subscription_type=list(settings.SITH_SUBSCRIPTIONS.keys())[0], Subscription(member=Subscriber.objects.filter(pk=r.pk).first(), subscription_type=list(settings.SITH_SUBSCRIPTIONS.keys())[0],
payment_method=settings.SITH_PAYMENT_METHOD[0]).save() payment_method=settings.SITH_SUBSCRIPTION_PAYMENT_METHOD[0]).save()
# Clubs # Clubs
Club(name="Bibo'UT", unix_name="bibout", Club(name="Bibo'UT", unix_name="bibout",
...@@ -95,6 +95,9 @@ Cette page vise à documenter la syntaxe *Markdown* utilisée sur le site. ...@@ -95,6 +95,9 @@ Cette page vise à documenter la syntaxe *Markdown* utilisée sur le site.
guyut = Club(name="Guy'UT", unix_name="guyut", guyut = Club(name="Guy'UT", unix_name="guyut",
address="42 de la Boustifaille", parent=ae) address="42 de la Boustifaille", parent=ae)
guyut.save() guyut.save()
troll = Club(name="Troll Penché", unix_name="troll",
address="Terre Du Milieu", parent=ae)
troll.save()
Club(name="Woenzel'UT", unix_name="woenzel", Club(name="Woenzel'UT", unix_name="woenzel",
address="Woenzel", parent=guyut).save() address="Woenzel", parent=guyut).save()
Club(name="BdF", unix_name="bdf", Club(name="BdF", unix_name="bdf",
...@@ -113,5 +116,11 @@ Cette page vise à documenter la syntaxe *Markdown* utilisée sur le site. ...@@ -113,5 +116,11 @@ Cette page vise à documenter la syntaxe *Markdown* utilisée sur le site.
special_selling_price="1.6").save() special_selling_price="1.6").save()
Product(name="Carolus", code="CARO", product_type=p, purchase_price="1.50", selling_price="1.7", Product(name="Carolus", code="CARO", product_type=p, purchase_price="1.50", selling_price="1.7",
special_selling_price="1.6").save() special_selling_price="1.6").save()
GeneralJournal(start_date="2015-06-12", name="A15").save() BankAccount(name="AE TG").save()
BankAccount(name="Carte AE").save()
ba = BankAccount(name="AE TI")
ba.save()
ca = ClubAccount(name="Troll Penché", bank_account=ba, club=troll)
ca.save()
...@@ -201,10 +201,18 @@ SITH_MEMBER_SUFFIX="-members" ...@@ -201,10 +201,18 @@ SITH_MEMBER_SUFFIX="-members"
SITH_MAIN_BOARD_GROUP=SITH_MAIN_CLUB['unix_name']+SITH_BOARD_SUFFIX SITH_MAIN_BOARD_GROUP=SITH_MAIN_CLUB['unix_name']+SITH_BOARD_SUFFIX
SITH_MAIN_MEMBERS_GROUP=SITH_MAIN_CLUB['unix_name']+SITH_MEMBER_SUFFIX SITH_MAIN_MEMBERS_GROUP=SITH_MAIN_CLUB['unix_name']+SITH_MEMBER_SUFFIX
SITH_PAYMENT_METHOD = [('cheque', 'Chèque'), SITH_ACCOUNTING_PAYMENT_METHOD = [
('cash', 'Espèce'), ('cheque', 'Chèque'),
('other', 'Autre'), ('cash', 'Espèce'),
] ('transfert', 'Virement'),
('card', 'Carte banquaire'),
]
SITH_SUBSCRIPTION_PAYMENT_METHOD = [
('cheque', 'Chèque'),
('cash', 'Espèce'),
('other', 'Autre'),
]
# Subscription durations are in semestres (should be settingized) # Subscription durations are in semestres (should be settingized)
SITH_SUBSCRIPTIONS = { SITH_SUBSCRIPTIONS = {
...@@ -231,7 +239,7 @@ SITH_SUBSCRIPTIONS = { ...@@ -231,7 +239,7 @@ SITH_SUBSCRIPTIONS = {
# To be completed.... # To be completed....
} }
CLUB_ROLES = { SITH_CLUB_ROLES = {
10: 'Président', 10: 'Président',
9: 'Vice-Président', 9: 'Vice-Président',
7: 'Trésorier', 7: 'Trésorier',
...@@ -244,8 +252,8 @@ CLUB_ROLES = { ...@@ -244,8 +252,8 @@ CLUB_ROLES = {
} }
# This corresponds to the maximum role a user can freely subscribe to # This corresponds to the maximum role a user can freely subscribe to
# In this case, MAXIMUM_FREE_ROLE=1 means that a user can set himself as "Membre actif" or "Curieux", but not higher # In this case, SITH_MAXIMUM_FREE_ROLE=1 means that a user can set himself as "Membre actif" or "Curieux", but not higher
MAXIMUM_FREE_ROLE=1 SITH_MAXIMUM_FREE_ROLE=1
# Minutes to timeout the logged barmen # Minutes to timeout the logged barmen
SITH_BARMAN_TIMEOUT=20 SITH_BARMAN_TIMEOUT=20
...@@ -13,7 +13,7 @@ def validate_type(value): ...@@ -13,7 +13,7 @@ def validate_type(value):
raise ValidationError(_('Bad subscription type')) raise ValidationError(_('Bad subscription type'))
def validate_payment(value): def validate_payment(value):
if value not in settings.SITH_PAYMENT_METHOD: if value not in settings.SITH_SUBSCRIPTION_PAYMENT_METHOD:
raise ValidationError(_('Bad payment method')) raise ValidationError(_('Bad payment method'))
class Subscriber(User): class Subscriber(User):
...@@ -34,7 +34,7 @@ class Subscription(models.Model): ...@@ -34,7 +34,7 @@ class Subscription(models.Model):
choices=((k, v['name']) for k,v in sorted(settings.SITH_SUBSCRIPTIONS.items()))) choices=((k, v['name']) for k,v in sorted(settings.SITH_SUBSCRIPTIONS.items())))
subscription_start = models.DateField(_('subscription start')) subscription_start = models.DateField(_('subscription start'))
subscription_end = models.DateField(_('subscription end')) subscription_end = models.DateField(_('subscription end'))
payment_method = models.CharField(_('payment method'), max_length=255, choices=settings.SITH_PAYMENT_METHOD) payment_method = models.CharField(_('payment method'), max_length=255, choices=settings.SITH_SUBSCRIPTION_PAYMENT_METHOD)
# TODO add location! # TODO add location!
class Meta: class Meta:
......
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