Improve accounting model according to current site's one

This commit is contained in:
Skia 2016-04-20 02:07:01 +02:00
parent 9a135ade50
commit c6a3559bf5
9 changed files with 144 additions and 52 deletions

View File

@ -6,7 +6,9 @@ from accounting.models import *
admin.site.register(Customer)
admin.site.register(ProductType)
admin.site.register(Product)
admin.site.register(BankAccount)
admin.site.register(ClubAccount)
admin.site.register(GeneralJournal)
admin.site.register(GenericInvoice)
admin.site.register(Operation)

View File

@ -2,71 +2,91 @@
from __future__ import unicode_literals
from django.db import migrations, models
from django.conf import settings
import accounting.models
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
('club', '__first__'),
('core', '0001_initial'),
]
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(
name='Customer',
fields=[
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, serialize=False, primary_key=True)),
('account_id', models.CharField(max_length=10, verbose_name='account id', unique=True)),
('user', models.OneToOneField(primary_key=True, to=settings.AUTH_USER_MODEL, serialize=False)),
('account_id', models.CharField(verbose_name='account id', unique=True, max_length=10)),
],
options={
'verbose_name': 'customer',
'verbose_name_plural': 'customers',
'verbose_name': 'customer',
},
),
migrations.CreateModel(
name='GeneralJournal',
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')),
('end_date', models.DateField(default=None, blank=True, null=True, verbose_name='end date')),
('name', models.CharField(max_length=30, verbose_name='name')),
('end_date', models.DateField(default=None, verbose_name='end date', null=True, blank=True)),
('name', models.CharField(verbose_name='name', max_length=30)),
('closed', models.BooleanField(default=False, verbose_name='is closed')),
('club_account', models.ForeignKey(related_name='journals', to='accounting.ClubAccount')),
],
),
migrations.CreateModel(
name='GenericInvoice',
name='Operation',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)),
('name', models.CharField(max_length=100, verbose_name='name')),
('journal', models.ForeignKey(to='accounting.GeneralJournal', related_name='invoices')),
('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)),
('name', models.CharField(verbose_name='name', max_length=100)),
('journal', models.ForeignKey(related_name='invoices', to='accounting.GeneralJournal')),
],
),
migrations.CreateModel(
name='Product',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)),
('name', models.CharField(max_length=30, verbose_name='name')),
('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)),
('name', models.CharField(verbose_name='name', max_length=30)),
('description', models.TextField(blank=True, verbose_name='description')),
('code', models.CharField(max_length=10, verbose_name='code')),
('purchase_price', accounting.models.CurrencyField(max_digits=12, verbose_name='purchase price', decimal_places=2)),
('selling_price', accounting.models.CurrencyField(max_digits=12, verbose_name='selling price', decimal_places=2)),
('special_selling_price', accounting.models.CurrencyField(max_digits=12, verbose_name='special selling price', decimal_places=2)),
('icon', models.ImageField(upload_to='products', blank=True, null=True)),
('code', models.CharField(verbose_name='code', max_length=10)),
('purchase_price', accounting.models.CurrencyField(verbose_name='purchase price', decimal_places=2, max_digits=12)),
('selling_price', accounting.models.CurrencyField(verbose_name='selling price', decimal_places=2, max_digits=12)),
('special_selling_price', accounting.models.CurrencyField(verbose_name='special selling price', decimal_places=2, max_digits=12)),
('icon', models.ImageField(blank=True, null=True, upload_to='products')),
],
),
migrations.CreateModel(
name='ProductType',
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)),
('name', models.CharField(max_length=30, verbose_name='name')),
('description', models.TextField(blank=True, null=True, verbose_name='description')),
('icon', models.ImageField(upload_to='products', blank=True, null=True)),
('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)),
('name', models.CharField(verbose_name='name', max_length=30)),
('description', models.TextField(blank=True, verbose_name='description', null=True)),
('icon', models.ImageField(blank=True, null=True, upload_to='products')),
],
),
migrations.AddField(
model_name='product',
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'),
),
]

View File

@ -0,0 +1,24 @@
# -*- 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'),
),
]

View File

@ -1,8 +1,10 @@
from django.db import models
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from decimal import Decimal
from core.models import User
from club.models import Club
class CurrencyField(models.DecimalField):
"""
@ -64,31 +66,58 @@ class Product(models.Model):
def __str__(self):
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 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'))
end_date = models.DateField(_('end date'), null=True, blank=True, default=None)
name = models.CharField(_('name'), max_length=30)
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):
return self.name
class GenericInvoice(models.Model):
class AccountingType(models.Model):
"""
This class is a generic invoice, made to be extended with some special cases (eg: for the internal accounting, payment
system, etc...)
Class describing the accounting types.
Thoses are numbers used in accounting to classify operations
"""
code = models.CharField(_('code'), max_length=16) # TODO: add number validator
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)
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):
return self.journal.name+' - '+self.name
# TODO: CountingInvoice in Counting app extending GenericInvoice
# - ManyToMany Product

View File

@ -111,8 +111,8 @@ class Membership(models.Model):
club = models.ForeignKey(Club, related_name="members", null=False, blank=False)
start_date = models.DateField(_('start date'), auto_now=True)
end_date = models.DateField(_('end date'), null=True, blank=True)
role = models.IntegerField(_('role'), choices=sorted(settings.CLUB_ROLES.items()),
default=sorted(settings.CLUB_ROLES.items())[0][0])
role = models.IntegerField(_('role'), choices=sorted(settings.SITH_CLUB_ROLES.items()),
default=sorted(settings.SITH_CLUB_ROLES.items())[0][0])
description = models.CharField(_('description'), max_length=30, null=False, blank=True)
def clean(self):
@ -123,7 +123,7 @@ class Membership(models.Model):
raise ValidationError(_('User is already member of that club'))
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 ""
)

View File

@ -8,7 +8,7 @@ from django.core.exceptions import ValidationError
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin
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):
"""
@ -42,7 +42,7 @@ class ClubMemberForm(forms.ModelForm):
"""
ret = super(ClubMemberForm, self).clean()
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
self._user.is_in_group(SITH_MAIN_BOARD_GROUP) or
self._user.is_superuser):

View File

@ -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
from accounting.models import Customer, GeneralJournal, ProductType, Product, BankAccount, ClubAccount, Operation
from club.models import Club, Membership
from subscription.models import Subscription, Subscriber
@ -84,10 +84,10 @@ Cette page vise à documenter la syntaxe *Markdown* utilisée sur le site.
# Subscription
## Skia
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
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
Club(name="Bibo'UT", unix_name="bibout",
@ -95,6 +95,9 @@ Cette page vise à documenter la syntaxe *Markdown* utilisée sur le site.
guyut = Club(name="Guy'UT", unix_name="guyut",
address="42 de la Boustifaille", parent=ae)
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",
address="Woenzel", parent=guyut).save()
Club(name="BdF", unix_name="bdf",
@ -113,5 +116,11 @@ Cette page vise à documenter la syntaxe *Markdown* utilisée sur le site.
special_selling_price="1.6").save()
Product(name="Carolus", code="CARO", product_type=p, purchase_price="1.50", selling_price="1.7",
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()

View File

@ -201,10 +201,18 @@ SITH_MEMBER_SUFFIX="-members"
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_PAYMENT_METHOD = [('cheque', 'Chèque'),
('cash', 'Espèce'),
('other', 'Autre'),
]
SITH_ACCOUNTING_PAYMENT_METHOD = [
('cheque', 'Chèque'),
('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)
SITH_SUBSCRIPTIONS = {
@ -231,7 +239,7 @@ SITH_SUBSCRIPTIONS = {
# To be completed....
}
CLUB_ROLES = {
SITH_CLUB_ROLES = {
10: 'Président',
9: 'Vice-Président',
7: 'Trésorier',
@ -244,8 +252,8 @@ CLUB_ROLES = {
}
# 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
MAXIMUM_FREE_ROLE=1
# In this case, SITH_MAXIMUM_FREE_ROLE=1 means that a user can set himself as "Membre actif" or "Curieux", but not higher
SITH_MAXIMUM_FREE_ROLE=1
# Minutes to timeout the logged barmen
SITH_BARMAN_TIMEOUT=20

View File

@ -13,7 +13,7 @@ def validate_type(value):
raise ValidationError(_('Bad subscription type'))
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'))
class Subscriber(User):
@ -34,7 +34,7 @@ class Subscription(models.Model):
choices=((k, v['name']) for k,v in sorted(settings.SITH_SUBSCRIPTIONS.items())))
subscription_start = models.DateField(_('subscription start'))
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!
class Meta: