Commit 7fdcb0c8 authored by Skia's avatar Skia

Finish labels in accounting

parent e169e4ff
Pipeline #278 failed with stage
in 3 minutes and 42 seconds
......@@ -9,5 +9,6 @@ admin.site.register(GeneralJournal)
admin.site.register(AccountingType)
admin.site.register(SimplifiedAccountingType)
admin.site.register(Operation)
admin.site.register(Label)
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('accounting', '0003_auto_20160824_2203'),
]
operations = [
migrations.CreateModel(
name='Label',
fields=[
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True, serialize=False)),
('name', models.CharField(max_length=64, verbose_name='label')),
('club_account', models.ForeignKey(related_name='labels', verbose_name='club account', to='accounting.ClubAccount')),
],
),
migrations.AddField(
model_name='operation',
name='label',
field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, related_name='operations', null=True, blank=True, verbose_name='label', to='accounting.Label'),
),
migrations.AlterUniqueTogether(
name='label',
unique_together=set([('name', 'club_account')]),
),
]
......@@ -100,7 +100,16 @@ class ClubAccount(models.Model):
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:
if m and m.role == 7:
return True
return False
def can_be_viewed_by(self, user):
"""
Method to see if that object can be viewed by the given user
"""
m = self.club.get_membership_for(user)
if m and m.role >= 7:
return True
return False
......@@ -149,6 +158,9 @@ class GeneralJournal(models.Model):
return True
return False
def can_be_viewed_by(self, user):
return self.club_account.can_be_edited_by(user)
def get_absolute_url(self):
return reverse('accounting:journal_details', kwargs={'j_id': self.id})
......@@ -186,6 +198,8 @@ class Operation(models.Model):
verbose_name=_("simple type"), null=True, blank=True)
accounting_type = models.ForeignKey('AccountingType', related_name="operations",
verbose_name=_("accounting type"), null=True, blank=True)
label = models.ForeignKey('Label', related_name="operations",
verbose_name=_("label"), null=True, blank=True, on_delete=models.SET_NULL)
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)
......@@ -326,3 +340,26 @@ class SimplifiedAccountingType(models.Model):
def __str__(self):
return self.get_movement_type_display()+" - "+self.accounting_type.code+" - "+self.label
class Label(models.Model):
"""Label allow a club to sort its operations"""
name = models.CharField(_('label'), max_length=64)
club_account = models.ForeignKey(ClubAccount, related_name="labels", verbose_name=_("club account"))
class Meta:
unique_together = ('name', 'club_account')
def __str__(self):
return "%s (%s)" % (self.name, self.club_account.name)
def get_absolute_url(self):
return reverse('accounting:label_list', kwargs={'clubaccount_id': self.club_account.id})
def is_owned_by(self, user):
return self.club_account.is_owned_by(user)
def can_be_edited_by(self, user):
return self.club_account.can_be_edited_by(user)
def can_be_viewed_by(self, user):
return self.club_account.can_be_viewed_by(user)
......@@ -15,6 +15,8 @@
{% if user.is_root and not object.journals.exists() %}
<a href="{{ url('accounting:club_delete', c_account_id=object.id) }}">{% trans %}Delete{% endtrans %}</a>
{% endif %}
<p><a href="{{ url('accounting:label_new') }}?parent={{ object.id }}">{% trans %}New label{% endtrans %}</a></p>
<p><a href="{{ url('accounting:label_list', clubaccount_id=object.id) }}">{% trans %}Label list{% endtrans %}</a></p>
{% if not object.has_open_journal() %}
<p><a href="{{ url('accounting:journal_new') }}?parent={{ object.id }}">{% trans %}New journal{% endtrans %}</a></p>
{% else %}
......
......@@ -25,6 +25,7 @@
<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>
......@@ -41,6 +42,7 @@
<tr>
<td>{{ o.number }}</td>
<td>{{ o.date }}</td>
<td>{{ o.label or "" }}</td>
<td>{{ o.amount }}</td>
<td>{{ o.get_mode_display() }}</td>
{% if o.target_type == "OTHER" %}
......
{% extends "core/base.jinja" %}
{% block title %}
{% trans %}Label list{% endtrans %}
{% 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> >
<a href="{{ url('accounting:club_details', c_account_id=object.id) }}">{{ object }}</a>
</p>
<hr>
<p><a href="{{ url('accounting:club_details', c_account_id=object.id) }}">{% trans %}Back to club account{% endtrans %}</a></p>
<p><a href="{{ url('accounting:label_new') }}?parent={{ object.id }}">{% trans %}New label{% endtrans %}</a></p>
{% if object.labels.all() %}
<h3>{% trans %}Label list{% endtrans %}</h3>
<ul>
{% for l in object.labels.all() %}
<li><a href="{{ url('accounting:label_edit', label_id=l.id) }}">{{ l }}</a> -
<a href="{{ url('accounting:label_delete', label_id=l.id) }}">{% trans %}Delete{% endtrans %}</a>
</li>
{% endfor %}
</ul>
{% else %}
{% trans %}There is no label in this club account.{% endtrans %}
{% endif %}
{% endblock %}
......@@ -35,6 +35,7 @@
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.label.errors }}<label for="{{ form.label.name }}">{{ form.label.label }}</label> {{ form.label }}</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>
......
......@@ -32,6 +32,11 @@ urlpatterns = [
# Companies
url(r'^company/create$', CompanyCreateView.as_view(), name='co_new'),
url(r'^company/(?P<co_id>[0-9]+)$', CompanyEditView.as_view(), name='co_edit'),
# Labels
url(r'^label/new$', LabelCreateView.as_view(), name='label_new'),
url(r'^label/(?P<clubaccount_id>[0-9]+)$', LabelListView.as_view(), name='label_list'),
url(r'^label/(?P<label_id>[0-9]+)/edit$', LabelEditView.as_view(), name='label_edit'),
url(r'^label/(?P<label_id>[0-9]+)/delete$', LabelDeleteView.as_view(), name='label_delete'),
]
......@@ -10,7 +10,7 @@ from ajax_select.fields import AutoCompleteSelectField, AutoCompleteSelectMultip
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, SimplifiedAccountingType
from accounting.models import BankAccount, ClubAccount, GeneralJournal, Operation, AccountingType, Company, SimplifiedAccountingType, Label
# Main accounting view
......@@ -196,7 +196,7 @@ 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']
'cheque_number', 'invoice', 'simpleaccounting_type', 'accounting_type', 'label', 'done']
widgets = {
'journal': HiddenInput,
'target_id': HiddenInput,
......@@ -210,6 +210,7 @@ class OperationForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(OperationForm, self).__init__(*args, **kwargs)
self.fields['label'].queryset = self.instance.journal.club_account.labels.order_by('name').all()
if self.instance.target_type == "USER":
self.fields['user'].initial = self.instance.target_id
elif self.instance.target_type == "ACCOUNT":
......@@ -316,3 +317,39 @@ class CompanyEditView(CanCreateMixin, UpdateView):
fields = ['name']
template_name = 'core/edit.jinja'
# Label views
class LabelListView(CanViewMixin, DetailView):
model = ClubAccount
pk_url_kwarg = "clubaccount_id"
template_name = 'accounting/label_list.jinja'
class LabelCreateView(CanEditMixin, CreateView): # FIXME we need to check the rights before creating the object
model = Label
form_class = modelform_factory(Label, fields=['name', 'club_account'], widgets={
'club_account': HiddenInput,
})
template_name = 'core/create.jinja'
def get_initial(self):
ret = super(LabelCreateView, self).get_initial()
if 'parent' in self.request.GET.keys():
obj = ClubAccount.objects.filter(id=int(self.request.GET['parent'])).first()
if obj is not None:
ret['club_account'] = obj.id
return ret
class LabelEditView(CanEditMixin, UpdateView):
model = Label
pk_url_kwarg = "label_id"
fields = ['name']
template_name = 'core/edit.jinja'
class LabelDeleteView(CanEditMixin, DeleteView):
model = Label
pk_url_kwarg = "label_id"
template_name = 'core/delete_confirm.jinja'
def get_success_url(self):
return self.object.get_absolute_url()
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('counter', '0010_auto_20161003_1900'),
]
operations = [
migrations.AlterField(
model_name='eticket',
name='banner',
field=models.ImageField(null=True, verbose_name='banner', blank=True, upload_to='etickets'),
),
]
This diff is collapsed.
......@@ -24,7 +24,7 @@ from club.models import Club, Membership
from counter.models import Customer, Counter, Selling, Refilling, Product, ProductType, Permanency, Eticket
from subscription.models import Subscription, Subscriber
from eboutic.models import Invoice, InvoiceItem
from accounting.models import BankAccount, ClubAccount, GeneralJournal, Operation, AccountingType, Company, SimplifiedAccountingType
from accounting.models import BankAccount, ClubAccount, GeneralJournal, Operation, AccountingType, Company, SimplifiedAccountingType, Label
db = MySQLdb.connect(**settings.OLD_MYSQL_INFOS)
start = datetime.datetime.now()
......@@ -839,6 +839,30 @@ def migrate_accounting():
print("Simple accounting types migrated at %s" % datetime.datetime.now())
print("Running time: %s" % (datetime.datetime.now()-start))
def migrate_labels():
cur = db.cursor(MySQLdb.cursors.SSDictCursor)
cur.execute("""
SELECT *
FROM cpta_libelle
WHERE id_asso IS NOT NULL
""")
Label.objects.all().delete()
print("Labels deleted")
for r in cur:
try:
club_accounts = ClubAccount.objects.filter(club__id=r['id_asso']).all()
for ca in club_accounts:
new = Label(
club_account=ca,
name=to_unicode(r['nom_libelle']),
)
new.save()
except Exception as e:
print("FAIL to migrate label: %s" % (repr(e)))
cur.close()
print("Labels migrated at %s" % datetime.datetime.now())
print("Running time: %s" % (datetime.datetime.now()-start))
def migrate_operations():
MODE = {
1: "CHECK",
......@@ -860,6 +884,8 @@ def migrate_accounting():
FROM cpta_operation op
LEFT JOIN cpta_op_clb clb
ON op.id_opclb = clb.id_opclb
LEFT JOIN cpta_libelle lab
ON op.id_libelle = lab.id_libelle
""")
Operation.objects.all().delete()
print("Operation deleted")
......@@ -867,6 +893,7 @@ def migrate_accounting():
try:
simple_type = None
accounting_type = None
label = None
if r['id_opclb']:
simple_type = SimplifiedAccountingType.objects.filter(id=r['id_opclb']).first()
if r['id_opstd']:
......@@ -876,6 +903,8 @@ def migrate_accounting():
if not accounting_type:
accounting_type = AccountingType.objects.filter(movement_type=MOVEMENT_TYPE[r['type_mouvement']]).first()
journal = GeneralJournal.objects.filter(id=r['id_classeur']).first()
if r['id_libelle']:
label = journal.club_account.labels.filter(name=to_unicode(r['nom_libelle'])).first()
def get_target_type():
if r['id_utilisateur']:
return "USER"
......@@ -901,6 +930,7 @@ def migrate_accounting():
target_type=get_target_type(),
target_id=get_target_id(),
target_label="-",
label=label,
)
try:
new.clean()
......@@ -940,6 +970,7 @@ def migrate_accounting():
migrate_simpleaccounting_types()
migrate_bank_accounts()
migrate_club_accounts()
migrate_labels()
migrate_journals()
migrate_operations()
make_operation_links()
......@@ -970,6 +1001,7 @@ def migrate_etickets():
FROM cpt_etickets
""")
Eticket.objects.all().delete()
print("Etickets deleted")
for r in cur:
try:
p = Product.objects.filter(id=r['id_produit']).first()
......@@ -1004,9 +1036,9 @@ def main():
# migrate_counter()
# check_accounts()
# Accounting
# migrate_accounting()
migrate_accounting()
# migrate_godfathers()
migrate_etickets()
# migrate_etickets()
# reset_index('core', 'club', 'subscription', 'accounting', 'eboutic', 'launderette', 'counter')
end = datetime.datetime.now()
print("End at %s" % end)
......
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