Commit 078b63d9 authored by Skia's avatar Skia

Migrate accounting

parent a4df1ae9
Pipeline #137 failed with stage
in 2 minutes and 45 seconds
......@@ -7,6 +7,7 @@ admin.site.register(BankAccount)
admin.site.register(ClubAccount)
admin.site.register(GeneralJournal)
admin.site.register(AccountingType)
admin.site.register(SimplifiedAccountingType)
admin.site.register(Operation)
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import django.core.validators
class Migration(migrations.Migration):
dependencies = [
('accounting', '0002_auto_20160814_1634'),
]
operations = [
migrations.CreateModel(
name='SimplifiedAccountingType',
fields=[
('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)),
('label', models.CharField(max_length=128, verbose_name='label')),
],
options={
'verbose_name': 'simplified type',
},
),
migrations.RemoveField(
model_name='operation',
name='label',
),
migrations.AddField(
model_name='operation',
name='linked_operation',
field=models.OneToOneField(to='accounting.Operation', default=None, null=True, blank=True, verbose_name='linked operation', related_name='operation_linked_to'),
),
migrations.AlterField(
model_name='accountingtype',
name='code',
field=models.CharField(max_length=16, verbose_name='code', validators=[django.core.validators.RegexValidator('^[0-9]*$', 'An accounting type code contains only numbers')]),
),
migrations.AlterField(
model_name='accountingtype',
name='label',
field=models.CharField(max_length=128, verbose_name='label'),
),
migrations.AlterField(
model_name='accountingtype',
name='movement_type',
field=models.CharField(max_length=12, verbose_name='movement type', choices=[('CREDIT', 'Credit'), ('DEBIT', 'Debit'), ('NEUTRAL', 'Neutral')]),
),
migrations.AlterField(
model_name='bankaccount',
name='club',
field=models.ForeignKey(related_name='bank_accounts', verbose_name='club', to='club.Club'),
),
migrations.AlterField(
model_name='clubaccount',
name='bank_account',
field=models.ForeignKey(related_name='club_accounts', verbose_name='bank account', to='accounting.BankAccount'),
),
migrations.AlterField(
model_name='clubaccount',
name='club',
field=models.ForeignKey(related_name='club_account', verbose_name='club', to='club.Club'),
),
migrations.AlterField(
model_name='generaljournal',
name='club_account',
field=models.ForeignKey(related_name='journals', verbose_name='club account', to='accounting.ClubAccount'),
),
migrations.AlterField(
model_name='generaljournal',
name='name',
field=models.CharField(max_length=40, verbose_name='name'),
),
migrations.AlterField(
model_name='operation',
name='accounting_type',
field=models.ForeignKey(related_name='operations', null=True, blank=True, verbose_name='accounting type', to='accounting.AccountingType'),
),
migrations.AlterField(
model_name='operation',
name='cheque_number',
field=models.CharField(verbose_name='cheque number', null=True, max_length=32, blank=True, default=''),
),
migrations.AlterField(
model_name='operation',
name='journal',
field=models.ForeignKey(related_name='operations', verbose_name='journal', to='accounting.GeneralJournal'),
),
migrations.AlterField(
model_name='operation',
name='remark',
field=models.CharField(max_length=128, verbose_name='comment'),
),
migrations.AddField(
model_name='simplifiedaccountingtype',
name='accounting_type',
field=models.ForeignKey(related_name='simplified_types', verbose_name='simplified accounting types', to='accounting.AccountingType'),
),
migrations.AddField(
model_name='operation',
name='simpleaccounting_type',
field=models.ForeignKey(related_name='operations', null=True, blank=True, verbose_name='simple type', to='accounting.SimplifiedAccountingType'),
),
]
from django.core.urlresolvers import reverse
from django.core.exceptions import ValidationError
from django.core import validators
from django.db.models import Count
from django.db import models
from django.conf import settings
......@@ -45,7 +46,7 @@ class BankAccount(models.Model):
name = models.CharField(_('name'), max_length=30)
iban = models.CharField(_('iban'), max_length=255, blank=True)
number = models.CharField(_('account number'), max_length=255, blank=True)
club = models.ForeignKey(Club, related_name="bank_accounts")
club = models.ForeignKey(Club, related_name="bank_accounts", verbose_name=_("club"))
def is_owned_by(self, user):
"""
......@@ -66,8 +67,8 @@ class BankAccount(models.Model):
class ClubAccount(models.Model):
name = models.CharField(_('name'), max_length=30)
club = models.OneToOneField(Club, related_name="club_account")
bank_account = models.ForeignKey(BankAccount, related_name="club_accounts")
club = models.ForeignKey(Club, related_name="club_account", verbose_name=_("club"))
bank_account = models.ForeignKey(BankAccount, related_name="club_accounts", verbose_name=_("bank account"))
def is_owned_by(self, user):
"""
......@@ -92,6 +93,9 @@ class ClubAccount(models.Model):
return True
return False
def get_open_journal(self):
return self.journals.filter(closed=False).first()
def get_absolute_url(self):
return reverse('accounting:club_details', kwargs={'c_account_id': self.id})
......@@ -108,9 +112,9 @@ class GeneralJournal(models.Model):
"""
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)
name = models.CharField(_('name'), max_length=40)
closed = models.BooleanField(_('is closed'), default=False)
club_account = models.ForeignKey(ClubAccount, related_name="journals", null=False)
club_account = models.ForeignKey(ClubAccount, related_name="journals", null=False, verbose_name=_("club account"))
amount = CurrencyField(_('amount'), default=0)
effective_amount = CurrencyField(_('effective_amount'), default=0)
......@@ -134,7 +138,7 @@ class GeneralJournal(models.Model):
self.amount = 0
self.effective_amount = 0
for o in self.operations.all():
if o.accounting_type.movement_type == "credit":
if o.accounting_type.movement_type == "CREDIT":
if o.done:
self.effective_amount += o.amount
self.amount += o.amount
......@@ -149,20 +153,24 @@ class Operation(models.Model):
An operation is a line in the journal, a debit or a credit
"""
number = models.IntegerField(_('number'))
journal = models.ForeignKey(GeneralJournal, related_name="operations", null=False)
journal = models.ForeignKey(GeneralJournal, related_name="operations", null=False, verbose_name=_("journal"))
amount = CurrencyField(_('amount'))
date = models.DateField(_('date'))
label = models.CharField(_('label'), max_length=50)
remark = models.TextField(_('remark'), max_length=255)
remark = models.CharField(_('comment'), max_length=128)
mode = models.CharField(_('payment method'), max_length=255, choices=settings.SITH_ACCOUNTING_PAYMENT_METHOD)
cheque_number = models.IntegerField(_('cheque number'), default=-1)
cheque_number = models.CharField(_('cheque number'), max_length=32, default="", null=True, blank=True)
invoice = models.ForeignKey(SithFile, related_name='operations', verbose_name=_("invoice"), null=True, blank=True)
done = models.BooleanField(_('is done'), default=False)
accounting_type = models.ForeignKey('AccountingType', related_name="operations", verbose_name=_("accounting type"))
simpleaccounting_type = models.ForeignKey('SimplifiedAccountingType', related_name="operations",
verbose_name=_("simple type"), null=True, blank=True)
accounting_type = models.ForeignKey('AccountingType', related_name="operations",
verbose_name=_("accounting type"), null=True, blank=True)
target_type = models.CharField(_('target type'), max_length=10,
choices=[('USER', _('User')), ('CLUB', _('Club')), ('ACCOUNT', _('Account')), ('COMPANY', _('Company')), ('OTHER', _('Other'))])
target_id = models.IntegerField(_('target id'), null=True, blank=True)
target_label = models.CharField(_('target label'), max_length=32, default="", blank=True)
linked_operation = models.OneToOneField('self', related_name='operation_linked_to', verbose_name=_("linked operation"),
null=True, blank=True, default=None)
class Meta:
unique_together = ('number', 'journal')
......@@ -183,6 +191,14 @@ class Operation(models.Model):
raise ValidationError(_("Target does not exists"))
if self.target_type == "OTHER" and self.target_label == "":
raise ValidationError(_("Please add a target label if you set no existing target"))
if not self.accounting_type and not self.simpleaccounting_type:
raise ValidationError(_("You need to provide ether a simplified accounting type or a standard accounting type"))
if self.simpleaccounting_type:
self.accounting_type = self.simpleaccounting_type.accounting_type
@property
def target(self):
return self.get_target()
def get_target(self):
tar = None
......@@ -237,9 +253,13 @@ class AccountingType(models.Model):
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')], max_length=12)
code = models.CharField(_('code'), max_length=16,
validators=[
validators.RegexValidator(r'^[0-9]*$', _('An accounting type code contains only numbers')),
],
)
label = models.CharField(_('label'), max_length=128)
movement_type = models.CharField(_('movement type'), choices=[('CREDIT', 'Credit'), ('DEBIT', 'Debit'), ('NEUTRAL', 'Neutral')], max_length=12)
class Meta:
verbose_name = _("accounting type")
......@@ -256,4 +276,29 @@ class AccountingType(models.Model):
return reverse('accounting:type_list')
def __str__(self):
return self.movement_type+" - "+self.code+" - "+self.label
return self.code+" - "+self.movement_type+" - "+self.label
class SimplifiedAccountingType(models.Model):
"""
Class describing the simplified accounting types.
"""
label = models.CharField(_('label'), max_length=128)
accounting_type = models.ForeignKey(AccountingType, related_name="simplified_types",
verbose_name=_("simplified accounting types"))
class Meta:
verbose_name = _("simplified type")
@property
def movement_type(self):
return self.accounting_type.movement_type
def get_movement_type_display(self):
return self.accounting_type.get_movement_type_display()
def get_absolute_url(self):
return reverse('accounting:simple_type_list')
def __str__(self):
return self.label+" - "+self.accounting_type.code+" - "+self.get_movement_type_display()
......@@ -5,6 +5,11 @@
{% endblock %}
{% block content %}
<p>
<a href="{{ url('accounting:bank_list') }}">{% trans %}Accounting{% endtrans %}</a> >
{% trans %}Accounting types{% endtrans %}
</p>
<hr>
<p><a href="{{ url('accounting:type_new') }}">{% trans %}New accounting type{% endtrans %}</a></p>
{% if accountingtype_list %}
<h3>{% trans %}Accounting type list{% endtrans %}</h3>
......
{% extends "core/base.jinja" %}
{% block title %}
{% trans %}Bank account: {% endtrans %}{{ object.name }}
{% endblock %}
{% block content %}
<p>
<a href="{{ url('accounting:bank_list') }}">{% trans %}Accounting{% endtrans %}</a> >
{{ object.name }}
</p>
<hr>
<h2>{% trans %}Bank account: {% endtrans %}{{ object.name }}</h2>
<h4>{% trans %}Infos{% endtrans %}</h4>
<ul>
......@@ -14,9 +19,12 @@
<p><a href="{{ url('accounting:club_new') }}?parent={{ object.id }}">{% trans %}New club account{% endtrans %}</a></p>
<ul>
{% for c in object.club_accounts.all() %}
<li><a href="{{ url('accounting:club_details', c_account_id=c.id) }}">{{ c }}</a> -
<a href="{{ url('accounting:club_edit', c_account_id=c.id) }}">{% trans %}Edit{% endtrans %}</a> -
<a href="{{ url('accounting:club_delete', c_account_id=c.id) }}">{% trans %}Delete{% endtrans %}</a></li>
<li><a href="{{ url('accounting:club_details', c_account_id=c.id) }}">{{ c }}</a>
- <a href="{{ url('accounting:club_edit', c_account_id=c.id) }}">{% trans %}Edit{% endtrans %}</a>
{% if user.is_root %}
- <a href="{{ url('accounting:club_delete', c_account_id=c.id) }}">{% trans %}Delete{% endtrans %}</a>
{% endif %}
</li>
{% endfor %}
</ul>
......
......@@ -5,15 +5,24 @@
{% endblock %}
{% block content %}
<h4>
{% trans %}Accounting{% endtrans %}
</h4>
{% if user.is_in_group(settings.SITH_GROUPS['accounting-admin']['name']) %}
<p><a href="{{ url('accounting:simple_type_list') }}">{% trans %}Manage simplified types{% endtrans %}</a></p>
<p><a href="{{ url('accounting:type_list') }}">{% trans %}Manage accounting types{% endtrans %}</a></p>
<p><a href="{{ url('accounting:bank_new') }}">{% trans %}New bank account{% endtrans %}</a></p>
{% endif %}
{% if bankaccount_list %}
<h3>{% trans %}Bank account list{% endtrans %}</h3>
<ul>
{% for a in bankaccount_list %}
<li><a href="{{ url('accounting:bank_details', b_account_id=a.id) }}">{{ a }}</a> -
<a href="{{ url('accounting:bank_edit', b_account_id=a.id) }}">{% trans %}Edit{% endtrans %}</a> -
<a href="{{ url('accounting:bank_delete', b_account_id=a.id) }}">{% trans %}Delete{% endtrans %}</a></li>
{% for a in object_list %}
<li><a href="{{ url('accounting:bank_details', b_account_id=a.id) }}">{{ a }}</a>
- <a href="{{ url('accounting:bank_edit', b_account_id=a.id) }}">{% trans %}Edit{% endtrans %}</a>
{% if user.is_root %}
- <a href="{{ url('accounting:bank_delete', b_account_id=a.id) }}">{% trans %}Delete{% endtrans %}</a>
{% endif %}
</li>
{% endfor %}
</ul>
{% else %}
......
{% extends "core/base.jinja" %}
{% block title %}
{% trans %}Club account:{% endtrans %} {{ object.name }}
{% endblock %}
{% block content %}
<p>
<a href="{{ url('accounting:bank_list') }}">{% trans %}Accounting{% endtrans %}</a> >
<a href="{{ url('accounting:bank_details', b_account_id=object.bank_account.id) }}">{{object.bank_account }}</a> >
{{ object }}
</p>
<hr>
<h2>{% trans %}Club account:{% endtrans %} {{ object.name }}</h2>
{% if not object.has_open_journal() %}
<p><a href="{{ url('accounting:journal_new') }}?parent={{ object.id }}">{% trans %}New journal{% endtrans %}</a></p>
......
{% extends "core/base.jinja" %}
{% block title %}
{% trans %}General journal:{% endtrans %} {{ object.name }}
{% endblock %}
{% block content %}
<p>
<a href="{{ url('accounting:bank_list') }}">{% trans %}Accounting{% endtrans %}</a> >
......@@ -7,6 +11,8 @@
<a href="{{ url('accounting:club_details', c_account_id=object.club_account.id) }}">{{ object.club_account }}</a> >
{{ object.name }}
</p>
<hr>
<h2>{% trans %}General journal:{% endtrans %} {{ object.name }}</h2>
<p><strong>{% trans %}Amount: {% endtrans %}</strong>{{ object.amount }} € -
<strong>{% trans %}Effective amount: {% endtrans %}</strong>{{ object.effective_amount }}</p>
{% if object.closed %}
......@@ -19,7 +25,6 @@
<tr>
<td>{% trans %}Nb{% endtrans %}</td>
<td>{% trans %}Date{% endtrans %}</td>
<td>{% trans %}Label{% endtrans %}</td>
<td>{% trans %}Amount{% endtrans %}</td>
<td>{% trans %}Payment mode{% endtrans %}</td>
<td>{% trans %}Target{% endtrans %}</td>
......@@ -36,7 +41,6 @@
<tr>
<td>{{ o.number }}</td>
<td>{{ o.date }}</td>
<td>{{ o.label }}</td>
<td>{{ o.amount }}</td>
<td>{{ o.get_mode_display() }}</td>
{% if o.target_type == "OTHER" %}
......
{% extends "core/base.jinja" %}
{% block title %}
{% trans %}Edit operation{% endtrans %}
{% endblock %}
{% block content %}
<h2>{% trans %}Edit operation{% endtrans %}</h2>
<form action="" method="post">
{% csrf_token %}
{{ form.journal }}
{{ form.target_id }}
<p>{{ form.amount.errors }}<label for="{{ form.amount.name }}">{{ form.amount.label }}</label> {{ form.amount }}</p>
<p>{{ form.remark.errors }}<label for="{{ form.remark.name }}">{{ form.remark.label }}</label> {{ form.remark }}</p>
<p>{{ form.target_type.errors }}<label for="{{ form.target_type.name }}">{{ form.target_type.label }}</label> </p>
{% for choice in form.target_type %}
{% if choice.choice_value != "" %}
{{ choice }}
{% if choice.choice_value == "USER" %}
{{ form.user }}
{% elif choice.choice_value == "CLUB" %}
{{ form.club }}
{% elif choice.choice_value == "ACCOUNT" %}
{{ form.club_account }}
{% elif choice.choice_value == "COMPANY" %}
{{ form.company }}
{% elif choice.choice_value == "OTHER" %}
{{ form.target_label }}
{% endif %}
{% else %}
{% endif %}
{% endfor %}
<p>{{ form.date.errors }}<label for="{{ form.date.name }}">{{ form.date.label }}</label> {{ form.date }}</p>
<p>{{ form.mode.errors }}<label for="{{ form.mode.name }}">{{ form.mode.label }}</label> {{ form.mode }}</p>
<p>{{ form.cheque_number.errors }}<label for="{{ form.cheque_number.name }}">{{ form.cheque_number.label }}</label> {{
form.cheque_number }}</p>
<p>{{ form.invoice.errors }}<label for="{{ form.invoice.name }}">{{ form.invoice.label }}</label> {{ form.invoice }}</p>
<p>{{ form.simpleaccounting_type.errors }}<label for="{{ form.simpleaccounting_type.name }}">{{
form.simpleaccounting_type.label }}</label> {{ form.simpleaccounting_type }}</p>
<p>{{ form.accounting_type.errors }}<label for="{{ form.accounting_type.name }}">{{ form.accounting_type.label }}</label> {{
form.accounting_type }}</p>
<p>{{ form.done.errors }}<label for="{{ form.done.name }}">{{ form.done.label }}</label> {{ form.done }}</p>
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
</form>
{% endblock %}
{% block script %}
{{ super() }}
<script>
$( function() {
} );
</script>
{% endblock %}
{% extends "core/base.jinja" %}
{% block title %}
{% trans %}Simplified type list{% endtrans %}
{% endblock %}
{% block content %}
<p>
<a href="{{ url('accounting:bank_list') }}">{% trans %}Accounting{% endtrans %}</a> >
{% trans %}Simplified types{% endtrans %}
</p>
<hr>
<p><a href="{{ url('accounting:simple_type_new') }}">{% trans %}New simplified type{% endtrans %}</a></p>
{% if simplifiedaccountingtype_list %}
<h3>{% trans %}Simplified type list{% endtrans %}</h3>
<ul>
{% for a in simplifiedaccountingtype_list %}
<li><a href="{{ url('accounting:simple_type_edit', type_id=a.id) }}">{{ a }}</a></li>
{% endfor %}
</ul>
{% else %}
{% trans %}There is no types in this website.{% endtrans %}
{% endif %}
{% endblock %}
......@@ -3,6 +3,10 @@ from django.conf.urls import url, include
from accounting.views import *
urlpatterns = [
# Accounting types
url(r'^simple_type$', SimplifiedAccountingTypeListView.as_view(), name='simple_type_list'),
url(r'^simple_type/create$', SimplifiedAccountingTypeCreateView.as_view(), name='simple_type_new'),
url(r'^simple_type/(?P<type_id>[0-9]+)/edit$', SimplifiedAccountingTypeEditView.as_view(), name='simple_type_edit'),
# Accounting types
url(r'^type$', AccountingTypeListView.as_view(), name='type_list'),
url(r'^type/create$', AccountingTypeCreateView.as_view(), name='type_new'),
......
......@@ -4,10 +4,49 @@ from django.shortcuts import render
from django.core.urlresolvers import reverse_lazy
from django.forms.models import modelform_factory
from django.forms import HiddenInput
from django import forms
from ajax_select.fields import AutoCompleteSelectField, AutoCompleteSelectMultipleField
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, CanCreateMixin
from core.views.forms import SelectFile, SelectDate
from accounting.models import BankAccount, ClubAccount, GeneralJournal, Operation, AccountingType, Company
from accounting.models import BankAccount, ClubAccount, GeneralJournal, Operation, AccountingType, Company, SimplifiedAccountingType
# Main accounting view
class BankAccountListView(CanViewMixin, ListView):
"""
A list view for the admins
"""
model = BankAccount
template_name = 'accounting/bank_account_list.jinja'
ordering = ['name']
# Simplified accounting types
class SimplifiedAccountingTypeListView(CanViewMixin, ListView):
"""
A list view for the admins
"""
model = SimplifiedAccountingType
template_name = 'accounting/simplifiedaccountingtype_list.jinja'
class SimplifiedAccountingTypeEditView(CanViewMixin, UpdateView):
"""
An edit view for the admins
"""
model = SimplifiedAccountingType
pk_url_kwarg = "type_id"
fields = ['label', 'accounting_type']
template_name = 'core/edit.jinja'
class SimplifiedAccountingTypeCreateView(CanCreateMixin, CreateView):
"""
Create an accounting type (for the admins)
"""
model = SimplifiedAccountingType
fields = ['label', 'accounting_type']
template_name = 'core/create.jinja'
# Accounting types
......@@ -37,20 +76,13 @@ class AccountingTypeCreateView(CanCreateMixin, CreateView):
# BankAccount views
class BankAccountListView(CanViewMixin, ListView):
"""
A list view for the admins
"""
model = BankAccount
template_name = 'accounting/bank_account_list.jinja'
class BankAccountEditView(CanViewMixin, UpdateView):
"""
An edit view for the admins
"""
model = BankAccount
pk_url_kwarg = "b_account_id"
fields = ['name', 'iban', 'number']
fields = ['name', 'iban', 'number', 'club']
template_name = 'core/edit.jinja'
class BankAccountDetailView(CanViewMixin, DetailView):
......@@ -129,7 +161,8 @@ class JournalCreateView(CanCreateMixin, CreateView):
Create a general journal
"""
model = GeneralJournal
fields = ['name', 'start_date', 'club_account']
form_class = modelform_factory(GeneralJournal, fields=['name', 'start_date', 'club_account'],
widgets={ 'start_date': SelectDate, })
template_name = 'core/create.jinja'
def get_initial(self):
......@@ -159,16 +192,82 @@ class JournalEditView(CanEditMixin, UpdateView):
# Operation views
class OperationForm(forms.ModelForm):
class Meta:
model = Operation
fields = ['amount', 'remark', 'journal', 'target_type', 'target_id', 'target_label', 'date', 'mode',
'cheque_number', 'invoice', 'simpleaccounting_type', 'accounting_type', 'done']
widgets = {
'journal': HiddenInput,
'target_id': HiddenInput,
'date': SelectDate,
'invoice': SelectFile,
'target_type': forms.RadioSelect,
}
user = AutoCompleteSelectField('users', help_text=None, required=False)
club_account = AutoCompleteSelectField('club_accounts', help_text=None, required=False)
club = AutoCompleteSelectField('clubs', help_text=None, required=False)
company = AutoCompleteSelectField('companies', help_text=None, required=False)
def __init__(self, *args, **kwargs):
super(OperationForm, self).__init__(*args, **kwargs)
if self.instance.target_type == "USER":
self.fields['user'].initial = self.instance.target_id
elif self.instance.target_type == "ACCOUNT":
self.fields['club_account'].initial = self.instance.target_id
elif self.instance.target_type == "CLUB":
self.fields['club'].initial = self.instance.target_id
elif self.instance.target_type == "COMPANY":
self.fields['company'].initial = self.instance.target_id
def clean(self):
self.cleaned_data = super(OperationForm, self).clean()
print(self.errors)
if self.cleaned_data['target_type'] == "USER":
self.cleaned_data['target_id'] = self.cleaned_data['user'].id
elif self.cleaned_data['target_type'] == "ACCOUNT":
self.cleaned_data['target_id'] = self.cleaned_data['club_account'].id
elif self.cleaned_data['target_type'] == "CLUB":
self.cleaned_data['target_id'] = self.cleaned_data['club'].id
elif self.cleaned_data['target_type'] == "COMPANY":
self.cleaned_data['target_id'] = self.cleaned_data['company'].id
return self.cleaned_data
def save(self):
ret = super(OperationForm, self).save()
if self.instance.target_type == "ACCOUNT" and not self.instance.linked_operation and self.instance.target.has_open_journal():
inst = self.instance
club_account = inst.target
acc_type = AccountingType.objects.exclude(movement_type="NEUTRAL").exclude(
movement_type=inst.accounting_type.movement_type).first() # Select a random opposite accounting type
op = Operation(
journal=club_account.get_open_journal(),
amount=inst.amount,
date=inst.date,
remark=inst.remark,
mode=inst.mode,
cheque_number=inst.cheque_number,
invoice=inst.invoice,
done=False, # Has to be checked by hand
simpleaccounting_type=None,
accounting_type=acc_type,
target_type="ACCOUNT",
target_id=inst.journal.club_account.id,
target_label="",
linked_operation=inst,
)
op.save()
self.instance.linked_operation = op
self.save()
return ret
class OperationCreateView(CanCreateMixin, CreateView):
"""
Create an operation
"""
model = Operation
form_class = modelform_factory(Operation,
fields=['amount', 'label', 'remark', 'journal', 'target_type', 'target_id', 'target_label', 'date', 'mode',
'cheque_number', 'invoice', 'accounting_type', 'done'],
widgets={'journal': HiddenInput, 'date': SelectDate, 'invoice': SelectFile})
template_name = 'core/create.jinja'
form_class = OperationForm
template_name = 'accounting/operation_edit.jinja'
def get_initial(self):
ret = super(OperationCreateView, self).get_initial()
......@@ -184,11 +283,8 @@ class OperationEditView(CanEditMixin, UpdateView):
"""
model = Operation
pk_url_kwarg = "op_id"
form_class = modelform_factory(Operation,
fields = ['amount', 'label', 'remark', 'target_type', 'target_id', 'target_label', 'date', 'mode', 'cheque_number',
'invoice', 'accounting_type', 'done'],
widgets={'date': SelectDate, 'invoice': SelectFile})
template_name = 'core/edit.jinja'
form_class = OperationForm
template_name = 'accounting/operation_edit.jinja'
# Company views
......
......@@ -8,7 +8,7 @@
<li><a href="{{ url('club:club_view', club_id=club.id) }}">{{ club.name }}</a>
{%- if club.children.all()|length != 0 %}
<ul>
{%- for c in club.children.all() %}
{%- for c in club.children.order_by('name') %}
{{ display_club(c) }}
{%- endfor %}
</ul>
......@@ -23,7 +23,7 @@
{% if club_list %}
<h3>{% trans %}Club list{% endtrans %}</h3>
<ul>
{%- for c in club_list if c.parent is none %}
{%- for c in club_list.order_by('name') if c.parent is none %}
{{ display_club(c) }}
{%- endfor %}
</ul>
......
......@@ -3,11 +3,11 @@
{% block content %}
<h3>{% trans %}Club tools{% endtrans %}</h3>
<p><a href="{{ url('club:club_view', club_id=object.id) }}">Back to club</a></p>