123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- # -*- coding: utf-8 -*-
- from __future__ import unicode_literals
- 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.utils import flatten_fieldsets
- from coin.filtering_queryset import LimitedAdminInlineMixin
- from coin.billing.models import Invoice, InvoiceDetail, Payment, PaymentAllocation
- from coin.billing.utils import get_invoice_from_id_or_number
- from django.core.urlresolvers import reverse
- import autocomplete_light
- class InvoiceDetailInline(LimitedAdminInlineMixin, admin.StackedInline):
- model = InvoiceDetail
- extra = 0
- fields = (
- ("label", "amount", "quantity", "tax"),
- ("offersubscription", "period_from", "period_to"),
- )
- def get_filters(self, obj):
- """
- Le champ "Abonnement" est filtré afin de n'afficher que les abonnements
- du membre choisi dans la facture. Si pas de membre alors renvoi
- une liste vide
- """
- if obj and obj.member:
- return (("offersubscription", {"member": obj.member}),)
- else:
- return (("offersubscription", None),)
- def get_readonly_fields(self, request, obj=None):
- if not obj or not obj.member:
- return self.readonly_fields + ("offersubscription",)
- 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 PaymentAllocatedReadOnly(admin.TabularInline):
- model = PaymentAllocation
- extra = 0
- fields = ("payment", "amount")
- readonly_fields = ("payment", "amount")
- verbose_name = None
- verbose_name_plural = "Paiement alloués"
- def has_add_permission(self, request, obj=None):
- return False
- def has_delete_permission(self, request, obj=None):
- return False
- class PaymentInlineAdd(admin.StackedInline):
- model = Payment
- extra = 0
- fields = (("date", "payment_mean", "amount"),)
- can_delete = False
- verbose_name_plural = "Ajouter des paiements"
- def has_change_permission(self, request):
- return False
- class InvoiceAdmin(admin.ModelAdmin):
- list_display = ("number", "date", "status", "amount", "member", "validated")
- list_display_links = ("number", "date")
- fields = (
- ("number", "date", "status"),
- ("date_due"),
- ("member"),
- ("amount", "amount_paid"),
- ("validated", "pdf"),
- )
- readonly_fields = ("amount", "amount_paid", "validated", "pdf", "number")
- form = autocomplete_light.modelform_factory(Invoice, fields="__all__")
- def get_readonly_fields(self, request, obj=None):
- """
- Si la facture est validée, passe tous les champs en readonly
- """
- 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]
- if obj.validated:
- inlines += [PaymentAllocatedReadOnly]
- if obj.status == "open":
- inlines += [PaymentInlineAdd]
- 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",
- )
- ]
- return my_urls + urls
- def validate_view(self, request, id):
- """
- Vue appelée lorsque l'admin souhaite valider une facture et
- générer son pdf
- """
- # TODO : Add better perm here
- if request.user.is_superuser:
- invoice = get_invoice_from_id_or_number(id)
- if invoice.amount() == 0:
- messages.error(
- request, "Une facture validée ne peut pas avoir" " un total de 0€."
- )
- else:
- invoice.validate()
- messages.success(request, "La facture a été validée.")
- else:
- messages.error(
- request, "Vous n'avez pas l'autorisation de valider " "une facture."
- )
- return HttpResponseRedirect(reverse("admin:billing_invoice_change", args=(id,)))
- class PaymentAllocationInlineReadOnly(admin.TabularInline):
- model = PaymentAllocation
- extra = 0
- fields = ("invoice", "amount")
- readonly_fields = ("invoice", "amount")
- verbose_name = None
- verbose_name_plural = "Alloué à"
- def has_add_permission(self, request, obj=None):
- return False
- def has_delete_permission(self, request, obj=None):
- return False
- class PaymentAdmin(admin.ModelAdmin):
- list_display = (
- "__unicode__",
- "member",
- "payment_mean",
- "amount",
- "date",
- "amount_already_allocated",
- "label",
- )
- list_display_links = ()
- fields = (
- ("member"),
- ("amount", "payment_mean", "date", "label"),
- ("amount_already_allocated"),
- )
- readonly_fields = ("amount_already_allocated", "label")
- form = autocomplete_light.modelform_factory(Payment, fields="__all__")
- def get_readonly_fields(self, request, obj=None):
- # If payment already started to be allocated or already have a member
- if obj and (obj.amount_already_allocated() != 0 or obj.member != None):
- # All fields are readonly
- return flatten_fieldsets(self.declared_fieldsets)
- else:
- return self.readonly_fields
- def get_inline_instances(self, request, obj=None):
- return [PaymentAllocationInlineReadOnly(self.model, self.admin_site)]
- admin.site.register(Invoice, InvoiceAdmin)
- admin.site.register(Payment, PaymentAdmin)
|