mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-01-17 13:32:15 +00:00
Python code is now formatted to PEP8 All other files are defined in .editorconfig as far as possible.
210 lines
7.0 KiB
Python
210 lines
7.0 KiB
Python
import cStringIO as StringIO
|
|
import datetime
|
|
import re
|
|
|
|
from django.contrib import messages
|
|
from django.core.urlresolvers import reverse_lazy
|
|
from django.db.models import Q
|
|
from django.http import Http404, HttpResponseRedirect
|
|
from django.http import HttpResponse
|
|
from django.shortcuts import get_object_or_404
|
|
from django.template import RequestContext
|
|
from django.template.loader import get_template
|
|
from django.views import generic
|
|
from z3c.rml import rml2pdf
|
|
|
|
from RIGS import models
|
|
|
|
|
|
class InvoiceIndex(generic.ListView):
|
|
model = models.Invoice
|
|
template_name = 'RIGS/invoice_list_active.html'
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(InvoiceIndex, self).get_context_data(**kwargs)
|
|
total = 0
|
|
for i in context['object_list']:
|
|
total += i.balance
|
|
context['total'] = total
|
|
context['count'] = len(list(context['object_list']))
|
|
return context
|
|
|
|
def get_queryset(self):
|
|
# Manual query is the only way I have found to do this efficiently. Not
|
|
# ideal but needs must
|
|
sql = "SELECT * FROM " \
|
|
"(SELECT " \
|
|
"(SELECT COUNT(p.amount) FROM \"RIGS_payment\" AS p WHERE p.invoice_id=\"RIGS_invoice\".id) AS \"payment_count\", " \
|
|
"(SELECT SUM(ei.cost * ei.quantity) FROM \"RIGS_eventitem\" AS ei WHERE ei.event_id=\"RIGS_invoice\".event_id) AS \"cost\", " \
|
|
"(SELECT SUM(p.amount) FROM \"RIGS_payment\" AS p WHERE p.invoice_id=\"RIGS_invoice\".id) AS \"payments\", " \
|
|
"\"RIGS_invoice\".\"id\", \"RIGS_invoice\".\"event_id\", \"RIGS_invoice\".\"invoice_date\", \"RIGS_invoice\".\"void\" FROM \"RIGS_invoice\") " \
|
|
"AS sub " \
|
|
"WHERE (((cost > 0.0) AND (payment_count=0)) OR (cost - payments) <> 0.0) AND void = '0'" \
|
|
"ORDER BY invoice_date"
|
|
|
|
query = self.model.objects.raw(sql)
|
|
|
|
return query
|
|
|
|
|
|
class InvoiceDetail(generic.DetailView):
|
|
model = models.Invoice
|
|
|
|
|
|
class InvoicePrint(generic.View):
|
|
def get(self, request, pk):
|
|
invoice = get_object_or_404(models.Invoice, pk=pk)
|
|
object = invoice.event
|
|
template = get_template('RIGS/event_print.xml')
|
|
copies = ('TEC', 'Client')
|
|
context = RequestContext(request, {
|
|
'object': object,
|
|
'fonts': {
|
|
'opensans': {
|
|
'regular': 'RIGS/static/fonts/OPENSANS-REGULAR.TTF',
|
|
'bold': 'RIGS/static/fonts/OPENSANS-BOLD.TTF',
|
|
}
|
|
},
|
|
'invoice': invoice,
|
|
'current_user': request.user,
|
|
})
|
|
|
|
rml = template.render(context)
|
|
buffer = StringIO.StringIO()
|
|
|
|
buffer = rml2pdf.parseString(rml)
|
|
|
|
pdfData = buffer.read()
|
|
|
|
escapedEventName = re.sub('[^a-zA-Z0-9 \n\.]', '', object.name)
|
|
|
|
response = HttpResponse(content_type='application/pdf')
|
|
response[
|
|
'Content-Disposition'] = "filename=Invoice %05d | %s.pdf" % (invoice.pk, escapedEventName)
|
|
response.write(pdfData)
|
|
return response
|
|
|
|
|
|
class InvoiceVoid(generic.View):
|
|
def get(self, *args, **kwargs):
|
|
pk = kwargs.get('pk')
|
|
object = get_object_or_404(models.Invoice, pk=pk)
|
|
object.void = not object.void
|
|
object.save()
|
|
|
|
if object.void:
|
|
return HttpResponseRedirect(reverse_lazy('invoice_list'))
|
|
return HttpResponseRedirect(reverse_lazy(
|
|
'invoice_detail', kwargs={'pk': object.pk}))
|
|
|
|
|
|
class InvoiceDelete(generic.DeleteView):
|
|
model = models.Invoice
|
|
|
|
def get(self, request, pk):
|
|
obj = self.get_object()
|
|
if obj.payment_set.all().count() > 0:
|
|
messages.info(
|
|
self.request,
|
|
'To delete an invoice, delete the payments first.')
|
|
return HttpResponseRedirect(reverse_lazy(
|
|
'invoice_detail', kwargs={'pk': obj.pk}))
|
|
return super(InvoiceDelete, self).get(pk)
|
|
|
|
def post(self, request, pk):
|
|
obj = self.get_object()
|
|
if obj.payment_set.all().count() > 0:
|
|
messages.info(
|
|
self.request,
|
|
'To delete an invoice, delete the payments first.')
|
|
return HttpResponseRedirect(reverse_lazy(
|
|
'invoice_detail', kwargs={'pk': obj.pk}))
|
|
return super(InvoiceDelete, self).post(pk)
|
|
|
|
def get_success_url(self):
|
|
return self.request.POST.get('next')
|
|
|
|
|
|
class InvoiceArchive(generic.ListView):
|
|
model = models.Invoice
|
|
template_name = 'RIGS/invoice_list_archive.html'
|
|
paginate_by = 25
|
|
|
|
|
|
class InvoiceWaiting(generic.ListView):
|
|
model = models.Event
|
|
# paginate_by = 25
|
|
template_name = 'RIGS/event_invoice.html'
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(InvoiceWaiting, self).get_context_data(**kwargs)
|
|
total = 0
|
|
for obj in self.get_objects():
|
|
total += obj.sum_total
|
|
context['total'] = total
|
|
context['count'] = len(self.get_objects())
|
|
return context
|
|
|
|
def get_queryset(self):
|
|
return self.get_objects()
|
|
|
|
def get_objects(self):
|
|
# @todo find a way to select items
|
|
events = self.model.objects.filter(
|
|
(
|
|
# Starts before with no end
|
|
Q(start_date__lte=datetime.date.today(), end_date__isnull=True) |
|
|
# Has end date, finishes before
|
|
Q(end_date__lte=datetime.date.today())
|
|
) & Q(invoice__isnull=True) # Has not already been invoiced
|
|
& Q(is_rig=True) # Is a rig (not non-rig)
|
|
|
|
).order_by('start_date') \
|
|
.select_related('person',
|
|
'organisation',
|
|
'venue', 'mic') \
|
|
.prefetch_related('items')
|
|
|
|
return events
|
|
|
|
|
|
class InvoiceEvent(generic.View):
|
|
def get(self, *args, **kwargs):
|
|
epk = kwargs.get('pk')
|
|
event = models.Event.objects.get(pk=epk)
|
|
invoice, created = models.Invoice.objects.get_or_create(event=event)
|
|
|
|
if created:
|
|
invoice.invoice_date = datetime.date.today()
|
|
messages.success(self.request, 'Invoice created successfully')
|
|
|
|
return HttpResponseRedirect(reverse_lazy(
|
|
'invoice_detail', kwargs={'pk': invoice.pk}))
|
|
|
|
|
|
class PaymentCreate(generic.CreateView):
|
|
model = models.Payment
|
|
fields = ['invoice', 'date', 'amount', 'method']
|
|
|
|
def get_initial(self):
|
|
initial = super(generic.CreateView, self).get_initial()
|
|
invoicepk = self.request.GET.get(
|
|
'invoice', self.request.POST.get(
|
|
'invoice', None))
|
|
if invoicepk is None:
|
|
raise Http404()
|
|
invoice = get_object_or_404(models.Invoice, pk=invoicepk)
|
|
initial.update({'invoice': invoice})
|
|
return initial
|
|
|
|
def get_success_url(self):
|
|
messages.info(self.request, "location.reload()")
|
|
return reverse_lazy('closemodal')
|
|
|
|
|
|
class PaymentDelete(generic.DeleteView):
|
|
model = models.Payment
|
|
|
|
def get_success_url(self):
|
|
return self.request.POST.get('next')
|