Added payments report

This commit is contained in:
Marc Aymerich 2015-06-03 12:49:30 +00:00
parent a17e8d9b8c
commit 3fe01a834b
9 changed files with 97 additions and 22 deletions

View file

@ -5,7 +5,7 @@ from functools import wraps
from django.conf import settings from django.conf import settings
from django.contrib import admin from django.contrib import admin
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse, NoReverseMatch
from django.db import models from django.db import models
from django.shortcuts import redirect from django.shortcuts import redirect
import importlib import importlib
@ -107,12 +107,16 @@ def admin_link(*args, **kwargs):
return '---' return '---'
if not getattr(obj, 'pk', None): if not getattr(obj, 'pk', None):
return '---' return '---'
url = change_url(obj)
display = kwargs.get('display') display = kwargs.get('display')
if display: if display:
display = getattr(obj, display, 'merda') display = getattr(obj, display, 'merda')
else: else:
display = obj display = obj
try:
url = change_url(obj)
except NoReverseMatch:
# Does not has admin
return str(display)
extra = '' extra = ''
if kwargs['popup']: if kwargs['popup']:
extra = 'onclick="return showAddAnotherPopup(this);"' extra = 'onclick="return showAddAnotherPopup(this);"'

View file

@ -1,6 +1,6 @@
import io
import zipfile import zipfile
from datetime import date from datetime import date
from io import StringIO
from django.contrib import messages from django.contrib import messages
from django.contrib.admin import helpers from django.contrib.admin import helpers
@ -22,17 +22,17 @@ from .helpers import validate_contact
def download_bills(modeladmin, request, queryset): def download_bills(modeladmin, request, queryset):
if queryset.count() > 1: if queryset.count() > 1:
stringio = StringIO() bytesio = io.BytesIO()
archive = zipfile.ZipFile(stringio, 'w') archive = zipfile.ZipFile(bytesio, 'w')
for bill in queryset: for bill in queryset:
pdf = html_to_pdf(bill.html or bill.render()) pdf = bill.as_pdf()
archive.writestr('%s.pdf' % bill.number, pdf) archive.writestr('%s.pdf' % bill.number, pdf)
archive.close() archive.close()
response = HttpResponse(stringio.getvalue(), content_type='application/pdf') response = HttpResponse(bytesio.getvalue(), content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="orchestra-bills.zip"' response['Content-Disposition'] = 'attachment; filename="orchestra-bills.zip"'
return response return response
bill = queryset.get() bill = queryset.get()
pdf = html_to_pdf(bill.html or bill.render(), pagination=bill.has_multiple_pages) pdf = bill.as_pdf()
return HttpResponse(pdf, content_type='application/pdf') return HttpResponse(pdf, content_type='application/pdf')
download_bills.verbose_name = _("Download") download_bills.verbose_name = _("Download")
download_bills.url_name = 'download' download_bills.url_name = 'download'

View file

@ -136,7 +136,7 @@ class Bill(models.Model):
if not self.is_open: if not self.is_open:
return self.total return self.total
try: try:
return self.computed_total return round(self.computed_total, 2)
except AttributeError: except AttributeError:
self.computed_total = self.compute_total() self.computed_total = self.compute_total()
return self.computed_total return self.computed_total
@ -199,8 +199,7 @@ class Bill(models.Model):
return transaction return transaction
def send(self): def send(self):
html = self.html or self.render() pdf = self.as_pdf()
pdf = html_to_pdf(html, pagination=self.has_multiple_pages)
self.account.send_email( self.account.send_email(
template=settings.BILLS_EMAIL_NOTIFICATION_TEMPLATE, template=settings.BILLS_EMAIL_NOTIFICATION_TEMPLATE,
context={ context={
@ -243,6 +242,10 @@ class Bill(models.Model):
html = html.replace('-pageskip-', '<pdf:nextpage />') html = html.replace('-pageskip-', '<pdf:nextpage />')
return html return html
def as_pdf(self):
html = self.html or self.render()
return html_to_pdf(html, pagination=self.has_multiple_pages)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if not self.type: if not self.type:
self.type = self.get_type() self.type = self.get_type()

View file

@ -50,7 +50,7 @@ class Message(models.Model):
def sent(self): def sent(self):
self.state = self.SENT self.state = self.SENT
self.save(update_fiields=('state',)) self.save(update_fields=('state',))
def log(self, error): def log(self, error):
result = SMTPLog.SUCCESS result = SMTPLog.SUCCESS

View file

@ -109,7 +109,7 @@ class BackendOperationInline(admin.TabularInline):
def instance_link(self, operation): def instance_link(self, operation):
link = admin_link('instance')(self, operation) link = admin_link('instance')(self, operation)
if not link.startswith('<a'): if link == '---':
return _("Deleted {0}").format(operation.instance_repr or '-'.join( return _("Deleted {0}").format(operation.instance_repr or '-'.join(
(escape(operation.content_type), escape(operation.object_id)))) (escape(operation.content_type), escape(operation.object_id))))
return link return link

View file

@ -182,3 +182,15 @@ def delete_selected(modeladmin, request, queryset):
helpers.post_delete_processes(modelamdin, request, related_transactions) helpers.post_delete_processes(modelamdin, request, related_transactions)
return response return response
delete_selected.short_description = actions.delete_selected.short_description delete_selected.short_description = actions.delete_selected.short_description
def report(modeladmin, request, queryset):
if queryset.model == Transaction:
transactions = queryset
else:
transactions = queryset.values_list('transactions__id', flat=True).distinct()
transactions = Transaction.objects.filter(id__in=transactions)
context = {
'transactions': transactions
}
return render(request, 'admin/payments/transaction/report.html', context)

View file

@ -87,11 +87,11 @@ class TransactionAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
) )
}), }),
) )
actions = ( change_view_actions = (
actions.process_transactions, actions.mark_as_executed, actions.process_transactions, actions.mark_as_executed, actions.mark_as_secured,
actions.mark_as_secured, actions.mark_as_rejected actions.mark_as_rejected,
) )
change_view_actions = actions actions = change_view_actions + (actions.report,)
filter_by_account_fields = ('bill', 'source') filter_by_account_fields = ('bill', 'source')
change_readonly_fields = ('amount', 'currency') change_readonly_fields = ('amount', 'currency')
readonly_fields = ('bill_link', 'display_state', 'process_link', 'account_link', 'source_link') readonly_fields = ('bill_link', 'display_state', 'process_link', 'account_link', 'source_link')
@ -123,7 +123,9 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
fields = ('data', 'file_url', 'created_at') fields = ('data', 'file_url', 'created_at')
readonly_fields = ('data', 'file_url', 'display_transactions', 'created_at') readonly_fields = ('data', 'file_url', 'display_transactions', 'created_at')
inlines = [TransactionInline] inlines = [TransactionInline]
change_view_actions = (actions.mark_process_as_executed, actions.abort, actions.commit) change_view_actions = (
actions.mark_process_as_executed, actions.abort, actions.commit, actions.report
)
actions = change_view_actions + (actions.delete_selected,) actions = change_view_actions + (actions.delete_selected,)
def file_url(self, process): def file_url(self, process):

View file

@ -131,22 +131,22 @@ class Transaction(models.Model):
def mark_as_processed(self): def mark_as_processed(self):
self.check_state(self.WAITTING_PROCESSING) self.check_state(self.WAITTING_PROCESSING)
self.state = self.WAITTING_EXECUTION self.state = self.WAITTING_EXECUTION
self.save(update_fields=['state']) self.save(update_fields=['state', 'modified_at'])
def mark_as_executed(self): def mark_as_executed(self):
self.check_state(self.WAITTING_EXECUTION) self.check_state(self.WAITTING_EXECUTION)
self.state = self.EXECUTED self.state = self.EXECUTED
self.save(update_fields=['state']) self.save(update_fields=['state', 'modified_at'])
def mark_as_secured(self): def mark_as_secured(self):
self.check_state(self.EXECUTED) self.check_state(self.EXECUTED)
self.state = self.SECURED self.state = self.SECURED
self.save(update_fields=['state']) self.save(update_fields=['state', 'modified_at'])
def mark_as_rejected(self): def mark_as_rejected(self):
self.check_state(self.EXECUTED) self.check_state(self.EXECUTED)
self.state = self.REJECTED self.state = self.REJECTED
self.save(update_fields=['state']) self.save(update_fields=['state', 'modified_at'])
class TransactionProcess(models.Model): class TransactionProcess(models.Model):

View file

@ -0,0 +1,54 @@
{% load i18n %}
<html>
<head>
<title>Transaction Report</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<style type="text/css">
@page {
size: 11.69in 8.27in;
}
table {
font-family: sans;
font-size: 10px;
max-width: 10in;
}
table tr:nth-child(even) {
background-color: #eee;
}
table tr:nth-child(odd) {
background-color: #fff;
}
table th {
color: white;
background-color: grey;
}
</style>
</head>
<body>
<table>
<tr id="transaction">
<th class="title column-id">ID</th>
<th class="title column-bill">{% trans "Bill" %}</th>
<th class="title column-billcontant">{% trans "Contact" %}</th>
<th class="title column-iban">IBAN</th>
<th class="title column-amount">{% trans "Amount" %}</th>
<th class="title column-state">{% trans "State" %}</th>
<th class="title column-created">{% trans "Created" %}</th>
<th class="title column-updated">{% trans "Updated" %}</th>
</tr>
{% for transaction in transactions %}
<tr>
<td class="item column-id">{{ transaction.id }}</td>
<td class="item column-bill">{{ transaction.bill.number }}</td>
<td class="item column-billcontant">{{ transaction.bill.buyer.get_name }}</td>
<td class="item column-iban">{{ transaction.source.data.iban }}</td>
<td class="item column-amount">{{ transaction.amount }}</td>
<td class="item column-state">{{ transaction.get_state_display }}</td>
<td class="item column-state">{{ transaction.created_at|date }}</td>
<td class="item column-state">{{ transaction.modified_at|date }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>