mirror of
https://gitlab.crans.org/bde/nk20
synced 2024-12-22 23:42:25 +00:00
Manage remittance types
This commit is contained in:
parent
1b03eac95b
commit
4cf1047faa
@ -1,16 +1,27 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# SPDX-License-Identifier: GPL-3.0-or-lateré
|
||||
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import Invoice, Product
|
||||
from .models import RemittanceType, Remittance
|
||||
|
||||
|
||||
@admin.register(Invoice)
|
||||
class InvoiceAdmin(admin.ModelAdmin):
|
||||
list_display = ('id', 'name', 'object', 'acquitted', )
|
||||
@admin.register(RemittanceType)
|
||||
class RemittanceTypeAdmin(admin.ModelAdmin):
|
||||
"""
|
||||
Admin customisation for RemiitanceType
|
||||
"""
|
||||
list_display = ('note', )
|
||||
|
||||
|
||||
@admin.register(Product)
|
||||
class ProductAdmin(admin.ModelAdmin):
|
||||
list_display = ('designation', 'quantity', 'amount', )
|
||||
@admin.register(Remittance)
|
||||
class RemittanceAdmin(admin.ModelAdmin):
|
||||
"""
|
||||
Admin customisation for Remittance
|
||||
"""
|
||||
list_display = ('remittance_type', 'date', 'comment', 'count', 'amount', 'closed', )
|
||||
|
||||
def has_change_permission(self, request, obj=None):
|
||||
if not obj:
|
||||
return True
|
||||
return not obj.closed and super().has_change_permission(request, obj)
|
||||
|
@ -2,8 +2,9 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from rest_framework import serializers
|
||||
from note.api.serializers import SpecialTransactionSerializer
|
||||
|
||||
from ..models import Invoice, Product
|
||||
from ..models import Invoice, Product, RemittanceType, Remittance
|
||||
|
||||
|
||||
class ProductSerializer(serializers.ModelSerializer):
|
||||
@ -32,3 +33,30 @@ class InvoiceSerializer(serializers.ModelSerializer):
|
||||
def get_products(self, obj):
|
||||
return serializers.ListSerializer(child=ProductSerializer())\
|
||||
.to_representation(Product.objects.filter(invoice=obj).all())
|
||||
|
||||
|
||||
class RemittanceTypeSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
REST API Serializer for RemittanceType types.
|
||||
The djangorestframework plugin will analyse the model `RemittanceType` and parse all fields in the API.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = RemittanceType
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class RemittanceSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
REST API Serializer for Remittance types.
|
||||
The djangorestframework plugin will analyse the model `Remittance` and parse all fields in the API.
|
||||
"""
|
||||
|
||||
transactions = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Remittance
|
||||
fields = '__all__'
|
||||
|
||||
def get_transactions(self, obj):
|
||||
return serializers.ListSerializer(child=SpecialTransactionSerializer()).to_representation(obj.transactions)
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from .views import InvoiceViewSet, ProductViewSet
|
||||
from .views import InvoiceViewSet, ProductViewSet, RemittanceViewSet, RemittanceTypeViewSet
|
||||
|
||||
|
||||
def register_treasury_urls(router, path):
|
||||
@ -10,3 +10,5 @@ def register_treasury_urls(router, path):
|
||||
"""
|
||||
router.register(path + '/invoice', InvoiceViewSet)
|
||||
router.register(path + '/product', ProductViewSet)
|
||||
router.register(path + '/remittance_type', RemittanceTypeViewSet)
|
||||
router.register(path + '/remittance', RemittanceViewSet)
|
||||
|
@ -5,8 +5,8 @@ from django_filters.rest_framework import DjangoFilterBackend
|
||||
from rest_framework.filters import SearchFilter
|
||||
from api.viewsets import ReadProtectedModelViewSet
|
||||
|
||||
from .serializers import InvoiceSerializer, ProductSerializer
|
||||
from ..models import Invoice, Product
|
||||
from .serializers import InvoiceSerializer, ProductSerializer, RemittanceTypeSerializer, RemittanceSerializer
|
||||
from ..models import Invoice, Product, RemittanceType, Remittance
|
||||
|
||||
|
||||
class InvoiceViewSet(ReadProtectedModelViewSet):
|
||||
@ -31,3 +31,23 @@ class ProductViewSet(ReadProtectedModelViewSet):
|
||||
serializer_class = ProductSerializer
|
||||
filter_backends = [SearchFilter]
|
||||
search_fields = ['$designation', ]
|
||||
|
||||
|
||||
class RemittanceTypeViewSet(ReadProtectedModelViewSet):
|
||||
"""
|
||||
REST API View set.
|
||||
The djangorestframework plugin will get all `RemittanceType` objects, serialize it to JSON with the given serializer
|
||||
then render it on /api/treasury/remittance_type/
|
||||
"""
|
||||
queryset = RemittanceType.objects.all()
|
||||
serializer_class = RemittanceTypeSerializer
|
||||
|
||||
|
||||
class RemittanceViewSet(ReadProtectedModelViewSet):
|
||||
"""
|
||||
REST API View set.
|
||||
The djangorestframework plugin will get all `Remittance` objects, serialize it to JSON with the given serializer,
|
||||
then render it on /api/treasury/remittance/
|
||||
"""
|
||||
queryset = Remittance.objects.all()
|
||||
serializer_class = RemittanceSerializer
|
||||
|
9
apps/treasury/fixtures/initial.json
Normal file
9
apps/treasury/fixtures/initial.json
Normal file
@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"model": "treasury.remittancetype",
|
||||
"pk": 1,
|
||||
"fields": {
|
||||
"note": 3
|
||||
}
|
||||
}
|
||||
]
|
@ -49,8 +49,8 @@ class RemittanceForm(forms.ModelForm):
|
||||
self.helper = FormHelper()
|
||||
|
||||
if self.instance.pk:
|
||||
self.fields["type"].disabled = True
|
||||
self.fields["type"].required = False
|
||||
self.fields["remittance_type"].disabled = True
|
||||
self.fields["remittance_type"].required = False
|
||||
|
||||
if not self.instance.closed:
|
||||
self.helper.add_input(Submit('submit', _("Submit"), attr={'class': 'btn btn-block btn-primary'}))
|
||||
@ -66,8 +66,8 @@ class RemittanceForm(forms.ModelForm):
|
||||
|
||||
cleaned_data = super().clean()
|
||||
|
||||
if "type" in self.changed_data:
|
||||
self.add_error("type", _("You can't change the type of the remittance."))
|
||||
if self.instance.pk and cleaned_data.get("remittance_type") != self.instance.remittance_type:
|
||||
self.add_error("remittance_type", _("You can't change the type of the remittance."))
|
||||
|
||||
if "close" in self.data:
|
||||
self.instance.closed = True
|
||||
@ -77,7 +77,7 @@ class RemittanceForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = Remittance
|
||||
fields = ('type', 'comment', )
|
||||
fields = ('remittance_type', 'comment',)
|
||||
|
||||
|
||||
class LinkTransactionToRemittanceForm(forms.ModelForm):
|
||||
|
@ -96,6 +96,20 @@ class Product(models.Model):
|
||||
return self.total / 100
|
||||
|
||||
|
||||
class RemittanceType(models.Model):
|
||||
"""
|
||||
Store what kind of remittances can be stored.
|
||||
"""
|
||||
|
||||
note = models.OneToOneField(
|
||||
NoteSpecial,
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.note)
|
||||
|
||||
|
||||
class Remittance(models.Model):
|
||||
"""
|
||||
Treasurers want to regroup checks or bank transfers in bank remittances.
|
||||
@ -106,8 +120,8 @@ class Remittance(models.Model):
|
||||
verbose_name=_("Date"),
|
||||
)
|
||||
|
||||
type = models.ForeignKey(
|
||||
NoteSpecial,
|
||||
remittance_type = models.ForeignKey(
|
||||
RemittanceType,
|
||||
on_delete=models.PROTECT,
|
||||
verbose_name=_("Type"),
|
||||
)
|
||||
@ -133,13 +147,13 @@ class Remittance(models.Model):
|
||||
def amount(self):
|
||||
return sum(transaction.total for transaction in self.transactions.all())
|
||||
|
||||
def full_clean(self, exclude=None, validate_unique=True):
|
||||
ret = super().full_clean(exclude, validate_unique)
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
|
||||
if self.transactions.filter(~Q(source=self.type)).exists():
|
||||
if self.transactions.filter(~Q(source=self.remittance_type.note)).exists():
|
||||
raise ValidationError("All transactions in a remittance must have the same type")
|
||||
|
||||
return ret
|
||||
return super().save(force_insert, force_update, using, update_fields)
|
||||
|
||||
def __str__(self):
|
||||
return _("Remittance #{:d}: {}").format(self.id, self.comment, )
|
||||
|
@ -56,7 +56,7 @@ class RemittanceTable(tables.Table):
|
||||
}
|
||||
model = Remittance
|
||||
template_name = 'django_tables2/bootstrap4.html'
|
||||
fields = ('id', 'date', 'type', 'comment', 'count', 'amount', 'view',)
|
||||
fields = ('id', 'date', 'remittance_type', 'comment', 'count', 'amount', 'view',)
|
||||
|
||||
|
||||
class SpecialTransactionTable(tables.Table):
|
||||
|
@ -17,11 +17,11 @@ from django.urls import reverse_lazy
|
||||
from django.views.generic import CreateView, UpdateView
|
||||
from django.views.generic.base import View, TemplateView
|
||||
from django_tables2 import SingleTableView
|
||||
from note.models import SpecialTransaction
|
||||
from note.models import SpecialTransaction, NoteSpecial
|
||||
from note_kfet.settings.base import BASE_DIR
|
||||
|
||||
from .forms import InvoiceForm, ProductFormSet, ProductFormSetHelper, RemittanceForm, LinkTransactionToRemittanceForm
|
||||
from .models import Invoice, Product, Remittance, SpecialTransactionProxy
|
||||
from .models import Invoice, Product, Remittance, SpecialTransactionProxy, RemittanceType
|
||||
from .tables import InvoiceTable, RemittanceTable, SpecialTransactionTable
|
||||
|
||||
|
||||
@ -212,11 +212,11 @@ class RemittanceListView(LoginRequiredMixin, TemplateView):
|
||||
ctx["opened_remittances"] = RemittanceTable(data=Remittance.objects.filter(closed=False).all())
|
||||
ctx["closed_remittances"] = RemittanceTable(data=Remittance.objects.filter(closed=True).reverse().all())
|
||||
ctx["special_transactions_no_remittance"] = SpecialTransactionTable(
|
||||
data=SpecialTransaction.objects.filter(source__polymorphic_ctype__model="notespecial",
|
||||
data=SpecialTransaction.objects.filter(source__in=NoteSpecial.objects.filter(~Q(remittancetype=None)),
|
||||
specialtransactionproxy__remittance=None).all(),
|
||||
exclude=('remittance_remove', ))
|
||||
ctx["special_transactions_with_remittance"] = SpecialTransactionTable(
|
||||
data=SpecialTransaction.objects.filter(source__polymorphic_ctype__model="notespecial",
|
||||
data=SpecialTransaction.objects.filter(source__in=NoteSpecial.objects.filter(~Q(remittancetype=None)),
|
||||
specialtransactionproxy__remittance__closed=False).all(),
|
||||
exclude=('remittance_add', ))
|
||||
|
||||
@ -236,7 +236,6 @@ class RemittanceUpdateView(LoginRequiredMixin, UpdateView):
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
|
||||
form = ctx["form"]
|
||||
ctx["table"] = RemittanceTable(data=Remittance.objects.all())
|
||||
data = SpecialTransaction.objects.filter(specialtransactionproxy__remittance=self.object).all()
|
||||
ctx["special_transactions"] = SpecialTransactionTable(
|
||||
@ -262,7 +261,7 @@ class LinkTransactionToRemittanceView(LoginRequiredMixin, UpdateView):
|
||||
form.fields["bank"].initial = self.object.transaction.bank
|
||||
form.fields["amount"].initial = self.object.transaction.amount
|
||||
form.fields["remittance"].queryset = form.fields["remittance"] \
|
||||
.queryset.filter(type=self.object.transaction.source)
|
||||
.queryset.filter(remittance_type__note=self.object.transaction.source)
|
||||
|
||||
return ctx
|
||||
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-24 01:00+0100\n"
|
||||
"POT-Creation-Date: 2020-03-24 15:49+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -576,28 +576,29 @@ msgstr ""
|
||||
msgid "Unit price"
|
||||
msgstr ""
|
||||
|
||||
#: apps/treasury/models.py:106
|
||||
#: apps/treasury/models.py:120
|
||||
msgid "Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/treasury/models.py:112
|
||||
#: apps/treasury/models.py:126
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/treasury/models.py:117
|
||||
#: apps/treasury/models.py:131
|
||||
msgid "Comment"
|
||||
msgstr ""
|
||||
|
||||
#: apps/treasury/models.py:122
|
||||
#: apps/treasury/models.py:136
|
||||
msgid "Closed"
|
||||
msgstr ""
|
||||
|
||||
#: apps/treasury/models.py:145
|
||||
#: apps/treasury/models.py:159
|
||||
msgid "Remittance #{:d}: {}"
|
||||
msgstr ""
|
||||
|
||||
#: apps/treasury/models.py:164 apps/treasury/tables.py:64
|
||||
#: apps/treasury/tables.py:72
|
||||
#: apps/treasury/models.py:178 apps/treasury/tables.py:64
|
||||
#: apps/treasury/tables.py:72 templates/treasury/invoice_list.html:13
|
||||
#: templates/treasury/remittance_list.html:13
|
||||
msgid "Remittance"
|
||||
msgstr ""
|
||||
|
||||
@ -605,7 +606,8 @@ msgstr ""
|
||||
msgid "Invoice #{:d}"
|
||||
msgstr ""
|
||||
|
||||
#: apps/treasury/tables.py:19
|
||||
#: apps/treasury/tables.py:19 templates/treasury/invoice_list.html:10
|
||||
#: templates/treasury/remittance_list.html:10
|
||||
msgid "Invoice"
|
||||
msgstr ""
|
||||
|
||||
@ -952,7 +954,7 @@ msgstr ""
|
||||
msgid "Remove product"
|
||||
msgstr ""
|
||||
|
||||
#: templates/treasury/invoice_list.html:8
|
||||
#: templates/treasury/invoice_list.html:21
|
||||
msgid "New invoice"
|
||||
msgstr ""
|
||||
|
||||
@ -977,34 +979,34 @@ msgstr ""
|
||||
msgid "There is no transaction linked with this remittance."
|
||||
msgstr ""
|
||||
|
||||
#: templates/treasury/remittance_list.html:6
|
||||
#: templates/treasury/remittance_list.html:19
|
||||
msgid "Opened remittances"
|
||||
msgstr ""
|
||||
|
||||
#: templates/treasury/remittance_list.html:11
|
||||
#: templates/treasury/remittance_list.html:24
|
||||
msgid "There is no opened remittance."
|
||||
msgstr ""
|
||||
|
||||
#: templates/treasury/remittance_list.html:15
|
||||
#: templates/treasury/remittance_list.html:28
|
||||
msgid "New remittance"
|
||||
msgstr ""
|
||||
|
||||
#: templates/treasury/remittance_list.html:19
|
||||
#: templates/treasury/remittance_list.html:32
|
||||
msgid "Transfers without remittances"
|
||||
msgstr ""
|
||||
|
||||
#: templates/treasury/remittance_list.html:24
|
||||
#: templates/treasury/remittance_list.html:37
|
||||
msgid "There is no transaction without any linked remittance."
|
||||
msgstr ""
|
||||
|
||||
#: templates/treasury/remittance_list.html:30
|
||||
#: templates/treasury/remittance_list.html:43
|
||||
msgid "Transfers with opened remittances"
|
||||
msgstr ""
|
||||
|
||||
#: templates/treasury/remittance_list.html:35
|
||||
#: templates/treasury/remittance_list.html:48
|
||||
msgid "There is no transaction without an opened linked remittance."
|
||||
msgstr ""
|
||||
|
||||
#: templates/treasury/remittance_list.html:41
|
||||
#: templates/treasury/remittance_list.html:54
|
||||
msgid "Closed remittances"
|
||||
msgstr ""
|
||||
|
@ -3,7 +3,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-03-24 01:00+0100\n"
|
||||
"POT-Creation-Date: 2020-03-24 15:49+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -576,28 +576,29 @@ msgstr "Quantité"
|
||||
msgid "Unit price"
|
||||
msgstr "Prix unitaire"
|
||||
|
||||
#: apps/treasury/models.py:106
|
||||
#: apps/treasury/models.py:120
|
||||
msgid "Date"
|
||||
msgstr "Date"
|
||||
|
||||
#: apps/treasury/models.py:112
|
||||
#: apps/treasury/models.py:126
|
||||
msgid "Type"
|
||||
msgstr "Type"
|
||||
|
||||
#: apps/treasury/models.py:117
|
||||
#: apps/treasury/models.py:131
|
||||
msgid "Comment"
|
||||
msgstr "Commentaire"
|
||||
|
||||
#: apps/treasury/models.py:122
|
||||
#: apps/treasury/models.py:136
|
||||
msgid "Closed"
|
||||
msgstr "Fermée"
|
||||
|
||||
#: apps/treasury/models.py:145
|
||||
#: apps/treasury/models.py:159
|
||||
msgid "Remittance #{:d}: {}"
|
||||
msgstr "Remise n°{:d} : {}"
|
||||
|
||||
#: apps/treasury/models.py:164 apps/treasury/tables.py:64
|
||||
#: apps/treasury/tables.py:72
|
||||
#: apps/treasury/models.py:178 apps/treasury/tables.py:64
|
||||
#: apps/treasury/tables.py:72 templates/treasury/invoice_list.html:13
|
||||
#: templates/treasury/remittance_list.html:13
|
||||
msgid "Remittance"
|
||||
msgstr "Remise"
|
||||
|
||||
@ -605,7 +606,8 @@ msgstr "Remise"
|
||||
msgid "Invoice #{:d}"
|
||||
msgstr "Facture n°{:d}"
|
||||
|
||||
#: apps/treasury/tables.py:19
|
||||
#: apps/treasury/tables.py:19 templates/treasury/invoice_list.html:10
|
||||
#: templates/treasury/remittance_list.html:10
|
||||
msgid "Invoice"
|
||||
msgstr "Facture"
|
||||
|
||||
@ -954,7 +956,7 @@ msgstr "Ajouter produit"
|
||||
msgid "Remove product"
|
||||
msgstr "Retirer produit"
|
||||
|
||||
#: templates/treasury/invoice_list.html:8
|
||||
#: templates/treasury/invoice_list.html:21
|
||||
msgid "New invoice"
|
||||
msgstr "Nouvelle facture"
|
||||
|
||||
@ -979,34 +981,34 @@ msgstr "Transactions liées"
|
||||
msgid "There is no transaction linked with this remittance."
|
||||
msgstr "Il n'y a pas de transaction liée à cette remise."
|
||||
|
||||
#: templates/treasury/remittance_list.html:6
|
||||
#: templates/treasury/remittance_list.html:19
|
||||
msgid "Opened remittances"
|
||||
msgstr "Remises ouvertes"
|
||||
|
||||
#: templates/treasury/remittance_list.html:11
|
||||
#: templates/treasury/remittance_list.html:24
|
||||
msgid "There is no opened remittance."
|
||||
msgstr "Il n'y a pas de remise ouverte."
|
||||
|
||||
#: templates/treasury/remittance_list.html:15
|
||||
#: templates/treasury/remittance_list.html:28
|
||||
msgid "New remittance"
|
||||
msgstr "Nouvelle remise"
|
||||
|
||||
#: templates/treasury/remittance_list.html:19
|
||||
#: templates/treasury/remittance_list.html:32
|
||||
msgid "Transfers without remittances"
|
||||
msgstr "Transactions sans remise associée"
|
||||
|
||||
#: templates/treasury/remittance_list.html:24
|
||||
#: templates/treasury/remittance_list.html:37
|
||||
msgid "There is no transaction without any linked remittance."
|
||||
msgstr "Il n'y a pas de transactions sans remise associée."
|
||||
|
||||
#: templates/treasury/remittance_list.html:30
|
||||
#: templates/treasury/remittance_list.html:43
|
||||
msgid "Transfers with opened remittances"
|
||||
msgstr "Transactions avec remise associée ouverte"
|
||||
|
||||
#: templates/treasury/remittance_list.html:35
|
||||
#: templates/treasury/remittance_list.html:48
|
||||
msgid "There is no transaction without an opened linked remittance."
|
||||
msgstr "Il n'y a pas de transaction sans remise ouverte associée."
|
||||
|
||||
#: templates/treasury/remittance_list.html:41
|
||||
#: templates/treasury/remittance_list.html:54
|
||||
msgid "Closed remittances"
|
||||
msgstr "Remises fermées"
|
||||
|
Loading…
Reference in New Issue
Block a user