Added pdf rendering support

This commit is contained in:
Marc 2014-08-29 12:45:27 +00:00
parent ef7f3219a5
commit b4113ef770
16 changed files with 61 additions and 41 deletions

View file

@ -28,9 +28,6 @@ class Command(BaseCommand):
email = options.get('email')
username = options.get('username')
password = options.get('password')
user = User.objects.create_superuser(username, email, password, account=account,
is_main=True)
account = Account.objects.create(user=user)
user.account = account
user.save()
account = Account.objects.create()
user = User.objects.create_superuser(username, email, password,
account=account, is_main=True)

View file

@ -1,7 +1,11 @@
from django.http import HttpResponse
from orchestra.utils.system import run
def generate_bill(modeladmin, request, queryset):
bill = queryset.get()
bill.close()
return HttpResponse(bill.html)
pdf = run('xvfb-run -a -s "-screen 0 640x4800x16" wkhtmltopdf - -',
stdin=bill.html.encode('utf-8'), display=False)
return HttpResponse(pdf, content_type='application/pdf')

View file

@ -16,7 +16,7 @@ class BillManager(models.Manager):
def get_queryset(self):
queryset = super(BillManager, self).get_queryset()
if self.model != Bill:
bill_type = self.model.get_type()
bill_type = self.model.get_class_type()
queryset = queryset.filter(type=bill_type)
return queryset
@ -127,7 +127,8 @@ class Bill(models.Model):
},
'currency': settings.BILLS_CURRENCY,
})
template = getattr(settings, 'BILLS_%s_TEMPLATE' % self.get_type())
template = getattr(settings, 'BILLS_%s_TEMPLATE' % self.get_type(),
settings.BILLS_DEFAULT_TEMPLATE)
bill_template = loader.get_template(template)
html = bill_template.render(context)
html = html.replace('-pageskip-', '<pdf:nextpage />')

View file

@ -14,7 +14,11 @@ BILLS_AMENDMENT_FEE_NUMBER_PREFIX = getattr(settings, 'BILLS_AMENDMENT_FEE_NUMBE
BILLS_BUDGET_NUMBER_PREFIX = getattr(settings, 'BILLS_BUDGET_NUMBER_PREFIX', 'Q')
BILLS_INVOICE_TEMPLATE = getattr(settings, 'BILLS_INVOICE_TEMPLATE', 'bills/microspective.html')
BILLS_DEFAULT_TEMPLATE = getattr(settings, 'BILLS_DEFAULT_TEMPLATE', 'bills/microspective.html')
BILLS_FEE_TEMPLATE = getattr(settings, 'BILLS_FEE_TEMPLATE', 'bills/microspective-fee.html')
BILLS_CURRENCY = getattr(settings, 'BILLS_CURRENCY', 'euro')

View file

@ -36,6 +36,7 @@
float: right;
padding: 15px;
margin: 10px;
margin-top: 0px;
width: 44%;
font-size: large;
}
@ -84,7 +85,7 @@ hr {
{% endblock %}
{% block summary %}
<div style="position: relative; margin-top: 150px;">
<div style="position: relative; margin-top: 140px;">
<hr>
</div>
@ -121,5 +122,8 @@ from Apr 1, 2010 to Apr 1, 2011
Con vuestras cuotas, ademas de obtener <br>
</div>
{% endblock %}
{% block pagination %}<hr>{% endblock %}
{% block footer %}
<hr>
{{ block.super }}
{% endblock %}

View file

@ -1,5 +1,6 @@
body {
max-width: 650px;
/* max-width: 650px;*/
max-width: 800px;
margin: 40 auto !important;
float: none !important;
font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif;
@ -48,14 +49,20 @@ a:hover {
}
/* SUMMARY */
#bill-summary {
clear: right;
}
#bill-summary > * {
float: right;
border: 1px solid grey;
padding: 7px;
padding: 7px 12px 7px 12px;
text-align: center;
font-size: large;
width: 100px;
overflow: hidden;
white-space: nowrap;
}
#bill-summary hr {
@ -161,12 +168,12 @@ a:hover {
}
#lines .column-description {
width: 55%;
width: 65%;
text-align: left;
}
#lines .column-quantity {
width: 20%;
width: 10%;
}
#lines .column-rate {

View file

@ -12,7 +12,7 @@
{% block header %}
<div id="logo">
{% block logo %}
<div style="border-bottom:5px solid grey; color:grey; font-size:30;">
<div style="border-bottom:5px solid grey; color:grey; font-size:30; margin-right: 20px;">
YOUR<br>
LOGO<br>
HERE<br>
@ -76,8 +76,8 @@
{% for line in bill.lines.all %}
<span class="value column-id">{{ line.id }}</span>
<span class="value column-description">{{ line.description }}</span>
<span class="value column-quantity">{{ line.amount }}</span>
<span class="value column-rate">{{ line.rate }}</span>
<span class="value column-quantity">{{ line.amount|default:"&nbsp;" }}</span>
<span class="value column-rate">{% if line.rate %}{{ line.rate }} &{{ currency.lower }};{% else %}&nbsp;{% endif %}</span>
<span class="value column-subtotal">{{ line.price }} &{{ currency.lower }};</span>
<br>
{% endfor %}

View file

@ -70,7 +70,8 @@ class MailboxAdmin(AccountAdminMixin, ExtendedModelAdmin):
add_url += '?account=%d&mailboxes=%s' % (account.pk, mailbox.pk)
img = '<img src="/static/admin/img/icon_addlink.gif" width="10" height="10" alt="Add Another">'
onclick = 'onclick="return showAddAnotherPopup(this);"'
add_link = '<a href="%s" %s>%s Add address</a>' % (add_url, onclick, img)
add_link = '<a href="{add_url}" {onclick}>{img} Add address</a>'.format(
add_url=add_url, onclick=onclick, img=img)
value = '%s<br><br>' % add_link
for pk, name, domain in mailbox.addresses.values_list('pk', 'name', 'domain__name'):
url = reverse('admin:mails_address_change', args=(pk,))

View file

@ -282,6 +282,9 @@ class Order(models.Model):
if service.handler.matches(instance):
if not orders:
account_id = getattr(instance, 'account_id', instance.pk)
if account_id is None:
# New account workaround -> user.account_id == None
continue
order = cls.objects.create(content_object=instance,
service=service, account_id=account_id)
else:

View file

@ -1,5 +1,4 @@
from .methods import BankTransfer
def process_transactions(modeladmin, request, queryset):
BankTransfer().process(queryset)
from .methods import SEPADirectDebit
SEPADirectDebit().process(queryset)

View file

@ -6,7 +6,7 @@ from orchestra.admin.utils import admin_colored, admin_link
from orchestra.apps.accounts.admin import AccountAdminMixin
from .actions import process_transactions
from .methods import BankTransfer
from .methods import SEPADirectDebit
from .models import PaymentSource, Transaction, PaymentProcess
@ -39,7 +39,7 @@ class TransactionAdmin(admin.ModelAdmin):
class PaymentSourceAdmin(AccountAdminMixin, admin.ModelAdmin):
list_display = ('label', 'method', 'number', 'account_link', 'is_active')
list_filter = ('method', 'is_active')
form = BankTransfer().get_form()
form = SEPADirectDebit().get_form()
# TODO select payment source method

View file

@ -1,3 +1,3 @@
from .creditcard import CreditCard
from .banktransfer import BankTransfer
from .sepadirectdebit import SEPADirectDebit
from .options import PaymentMethod, PaymentSourceDataForm

View file

@ -15,26 +15,26 @@ from .. import settings
from .options import PaymentSourceDataForm, PaymentMethod
class BankTransferForm(PaymentSourceDataForm):
class SEPADirectDebitForm(PaymentSourceDataForm):
iban = IBANFormField(label='IBAN',
widget=forms.TextInput(attrs={'size': '50'}))
name = forms.CharField(max_length=128, label=_("Name"),
widget=forms.TextInput(attrs={'size': '50'}))
class BankTransferSerializer(serializers.Serializer):
class SEPADirectDebitSerializer(serializers.Serializer):
iban = serializers.CharField(label='IBAN', validators=[IBANValidator()],
min_length=min(IBAN_COUNTRY_CODE_LENGTH.values()), max_length=34)
name = serializers.CharField(label=_("Name"), max_length=128)
class BankTransfer(PaymentMethod):
verbose_name = _("Bank transfer")
class SEPADirectDebit(PaymentMethod):
verbose_name = _("Direct Debit")
label_field = 'name'
number_field = 'iban'
process_credit = True
form = BankTransferForm
serializer = BankTransferSerializer
form = SEPADirectDebitForm
serializer = SEPADirectDebitSerializer
def process(self, transactions):
debts = []

View file

@ -72,7 +72,7 @@ class Transaction(models.Model):
return "Transaction {}".format(self.id)
# TODO rename to TransactionProcess
# TODO rename to TransactionProcess or PaymentRequest TransactionRequest
class PaymentProcess(models.Model):
"""
Stores arbitrary data generated by payment methods while processing transactions

View file

@ -127,7 +127,9 @@ function install_requirements () {
bind9utils \
python-cracklib \
libxml2-dev \
libxslt1-dev"
libxslt1-dev \
wkhtmltopdf \
xvfb"
PIP="django==1.6.1 \
django-celery-email==1.0.4 \
@ -151,8 +153,7 @@ function install_requirements () {
if $testing; then
APT="${APT} \
iceweasel \
xvfb"
iceweasel"
PIP="${PIP} \
selenium \
xvfbwrapper"

View file

@ -46,21 +46,20 @@ def read_async(fd):
return ''
def run(command, display=True, error_codes=[0], silent=True):
def run(command, display=True, error_codes=[0], silent=True, stdin=''):
""" Subprocess wrapper for running commands """
if display:
sys.stderr.write("\n\033[1m $ %s\033[0m\n" % command)
out_stream = subprocess.PIPE
err_stream = subprocess.PIPE
p = subprocess.Popen(command, shell=True, executable='/bin/bash',
stdout=out_stream, stderr=err_stream)
stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
make_async(p.stdout)
make_async(p.stderr)
stdout = str()
stderr = str()
p.stdin.write(stdin)
p.stdin.close()
# Async reading of stdout and sterr
while True:
# Wait for data to become available