|
@@ -4,6 +4,7 @@ from django.contrib import admin
|
|
|
from django.contrib import messages
|
|
|
from django.http import HttpResponseRedirect
|
|
|
from django.conf.urls import url
|
|
|
+from django.contrib.admin.util import flatten_fieldsets
|
|
|
|
|
|
from coin.filtering_queryset import LimitedAdminInlineMixin
|
|
|
from coin.billing.models import Invoice, InvoiceDetail, Payment
|
|
@@ -35,6 +36,32 @@ class InvoiceDetailInline(LimitedAdminInlineMixin, admin.StackedInline):
|
|
|
return self.readonly_fields
|
|
|
|
|
|
|
|
|
+class InvoiceDetailInlineReadOnly(admin.StackedInline):
|
|
|
+ """
|
|
|
+ Lorsque la facture est validée, il n'est plus possible de la modifier
|
|
|
+ Ce inline est donc identique à InvoiceDetailInline, mais tous
|
|
|
+ les champs sont en lecture seule
|
|
|
+ """
|
|
|
+ model = InvoiceDetail
|
|
|
+ extra = 0
|
|
|
+ fields = InvoiceDetailInline.fields
|
|
|
+ can_delete = False
|
|
|
+
|
|
|
+ def has_add_permission(self, request):
|
|
|
+ return False
|
|
|
+
|
|
|
+ def get_readonly_fields(self, request, obj=None):
|
|
|
+ if self.declared_fieldsets:
|
|
|
+ result = flatten_fieldsets(self.declared_fieldsets)
|
|
|
+ else:
|
|
|
+ result = list(set(
|
|
|
+ [field.name for field in self.opts.local_fields] +
|
|
|
+ [field.name for field in self.opts.local_many_to_many]
|
|
|
+ ))
|
|
|
+ result.remove('id')
|
|
|
+ return result
|
|
|
+
|
|
|
+
|
|
|
class PaymentInline(admin.StackedInline):
|
|
|
model = Payment
|
|
|
extra = 0
|
|
@@ -44,7 +71,6 @@ class PaymentInline(admin.StackedInline):
|
|
|
class InvoiceAdmin(admin.ModelAdmin):
|
|
|
list_display = ('number', 'date', 'status', 'amount', 'member', 'validated')
|
|
|
list_display_links = ('number', 'date')
|
|
|
- inlines = [InvoiceDetailInline, PaymentInline]
|
|
|
fields = (('number', 'date', 'status'),
|
|
|
('date_due'),
|
|
|
('member'),
|
|
@@ -53,29 +79,68 @@ class InvoiceAdmin(admin.ModelAdmin):
|
|
|
readonly_fields = ('amount','amount_paid','validated','pdf')
|
|
|
form = autocomplete_light.modelform_factory(Invoice)
|
|
|
|
|
|
- def get_formsets(self, request, obj=None):
|
|
|
+ def get_readonly_fields(self, request, obj=None):
|
|
|
"""
|
|
|
- Lorsque l'on est en création d'objet (obj=None) alors ne renvoi pas les
|
|
|
- formsets des inlines.
|
|
|
- Cela permet de ne pas afficher les champs détails de facture et paiement
|
|
|
- tant que la facture n'a pas été enregistré.
|
|
|
- Cette subtilité permet de s'assurer que le select "Abonnement" de
|
|
|
- InvoiceDetail est bien filtré avec le member de la facture
|
|
|
+ Si la facture est validée, passe tous les champs en readonly
|
|
|
"""
|
|
|
- if obj:
|
|
|
- for _ in super(InvoiceAdmin, self).get_formsets(request, obj):
|
|
|
- yield _
|
|
|
- else:
|
|
|
- pass
|
|
|
+ if obj and obj.validated:
|
|
|
+ if self.declared_fieldsets:
|
|
|
+ return flatten_fieldsets(self.declared_fieldsets)
|
|
|
+ else:
|
|
|
+ return list(set(
|
|
|
+ [field.name for field in self.opts.local_fields] +
|
|
|
+ [field.name for field in self.opts.local_many_to_many]
|
|
|
+ ))
|
|
|
+ return self.readonly_fields
|
|
|
+
|
|
|
+ def get_inline_instances(self, request, obj=None):
|
|
|
+ """
|
|
|
+ Renvoi les inlines selon le context :
|
|
|
+ * Si création, alors ne renvoi aucun inline
|
|
|
+ * Si modification, renvoi InvoiceDetail et PaymentInline
|
|
|
+ * Si facture validée, renvoi InvoiceDetail en ReadOnly et PaymentInline
|
|
|
+ """
|
|
|
+ inlines = []
|
|
|
+ inline_instances = []
|
|
|
+
|
|
|
+ if obj is not None:
|
|
|
+ if obj.validated:
|
|
|
+ inlines = [InvoiceDetailInlineReadOnly]
|
|
|
+ else:
|
|
|
+ inlines = [InvoiceDetailInline]
|
|
|
+
|
|
|
+ inlines += [PaymentInline]
|
|
|
+
|
|
|
+ for inline_class in inlines:
|
|
|
+ inline = inline_class(self.model, self.admin_site)
|
|
|
+
|
|
|
+ if request:
|
|
|
+ if not (inline.has_add_permission(request) or
|
|
|
+ inline.has_change_permission(request) or
|
|
|
+ inline.has_delete_permission(request)):
|
|
|
+ continue
|
|
|
+ if not inline.has_add_permission(request):
|
|
|
+ inline.max_num = 0
|
|
|
+ inline_instances.append(inline)
|
|
|
+
|
|
|
+ return inline_instances
|
|
|
|
|
|
def get_urls(self):
|
|
|
+ """
|
|
|
+ Custom admin urls
|
|
|
+ """
|
|
|
urls = super(InvoiceAdmin, self).get_urls()
|
|
|
my_urls = [
|
|
|
- url(r'^validate/(?P<id>.+)$', self.admin_site.admin_view(self.validate_view), name='invoice_validate'),
|
|
|
+ url(r'^validate/(?P<id>.+)$', self.admin_site.admin_view(self.validate_view),
|
|
|
+ name='invoice_validate'),
|
|
|
]
|
|
|
return my_urls + urls
|
|
|
|
|
|
def validate_view(self, request, id):
|
|
|
+ """
|
|
|
+ Vue appelée lorsque l'admin souhaite valider une facture (et générer le pdf)
|
|
|
+ """
|
|
|
+ #TODO : Add better perm here
|
|
|
if request.user.is_superuser:
|
|
|
invoice = get_invoice_from_id_or_number(id)
|
|
|
invoice.validate()
|