diff --git a/src/pretix/base/invoice.py b/src/pretix/base/invoice.py
index f9f93fde65..0f9ffc5edb 100644
--- a/src/pretix/base/invoice.py
+++ b/src/pretix/base/invoice.py
@@ -223,7 +223,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
p.drawOn(canvas, 25 * mm, (297 - 52) * mm - p_size[1])
def _draw_invoice_from(self, canvas):
- p = Paragraph(self.invoice.invoice_from.strip().replace('\n', '
\n'), style=self.stylesheet['Normal'])
+ p = Paragraph(self.invoice.full_invoice_from.strip().replace('\n', '
\n'), style=self.stylesheet['Normal'])
p.wrapOn(canvas, 70 * mm, 50 * mm)
p_size = p.wrap(70 * mm, 50 * mm)
p.drawOn(canvas, 25 * mm, (297 - 17) * mm - p_size[1])
@@ -330,7 +330,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
return txt
if not self.invoice.event.has_subevents:
- if self.invoice.event.settings.show_date_to:
+ if self.invoice.event.settings.show_date_to and self.invoice.event.date_to:
p_str = (
shorten(self.invoice.event.name) + '\n' + pgettext('invoice', '{from_date}\nuntil {to_date}').format(
from_date=self.invoice.event.get_date_from_display(),
diff --git a/src/pretix/base/migrations/0100_auto_20181023_2300.py b/src/pretix/base/migrations/0100_auto_20181023_2300.py
new file mode 100644
index 0000000000..c7adf0471b
--- /dev/null
+++ b/src/pretix/base/migrations/0100_auto_20181023_2300.py
@@ -0,0 +1,79 @@
+# Generated by Django 2.1 on 2018-10-23 23:00
+
+from django.db import migrations, models
+import django_countries.fields
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('pretixbase', '0099_auto_20180912_1035'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='invoice',
+ name='invoice_from_city',
+ field=models.CharField(max_length=190, null=True),
+ ),
+ migrations.AddField(
+ model_name='invoice',
+ name='invoice_from_country',
+ field=django_countries.fields.CountryField(max_length=2, null=True),
+ ),
+ migrations.AddField(
+ model_name='invoice',
+ name='invoice_from_name',
+ field=models.CharField(max_length=190, null=True),
+ ),
+ migrations.AddField(
+ model_name='invoice',
+ name='invoice_from_tax_id',
+ field=models.CharField(max_length=190, null=True),
+ ),
+ migrations.AddField(
+ model_name='invoice',
+ name='invoice_from_vat_id',
+ field=models.CharField(max_length=190, null=True),
+ ),
+ migrations.AddField(
+ model_name='invoice',
+ name='invoice_from_zipcode',
+ field=models.CharField(max_length=190, null=True),
+ ),
+ migrations.AddField(
+ model_name='invoice',
+ name='invoice_to_city',
+ field=models.TextField(null=True),
+ ),
+ migrations.AddField(
+ model_name='invoice',
+ name='invoice_to_company',
+ field=models.TextField(null=True),
+ ),
+ migrations.AddField(
+ model_name='invoice',
+ name='invoice_to_country',
+ field=django_countries.fields.CountryField(max_length=2, null=True),
+ ),
+ migrations.AddField(
+ model_name='invoice',
+ name='invoice_to_name',
+ field=models.TextField(null=True),
+ ),
+ migrations.AddField(
+ model_name='invoice',
+ name='invoice_to_street',
+ field=models.TextField(null=True),
+ ),
+ migrations.AddField(
+ model_name='invoice',
+ name='invoice_to_vat_id',
+ field=models.TextField(null=True),
+ ),
+ migrations.AddField(
+ model_name='invoice',
+ name='invoice_to_zipcode',
+ field=models.CharField(max_length=190, null=True),
+ ),
+ ]
diff --git a/src/pretix/base/models/invoices.py b/src/pretix/base/models/invoices.py
index 8b9962dd12..097782ff58 100644
--- a/src/pretix/base/models/invoices.py
+++ b/src/pretix/base/models/invoices.py
@@ -5,6 +5,8 @@ from django.db import DatabaseError, models, transaction
from django.utils import timezone
from django.utils.crypto import get_random_string
from django.utils.functional import cached_property
+from django.utils.translation import pgettext
+from django_countries.fields import CountryField
def invoice_filename(instance, filename: str) -> str:
@@ -73,7 +75,20 @@ class Invoice(models.Model):
is_cancellation = models.BooleanField(default=False)
refers = models.ForeignKey('Invoice', related_name='refered', null=True, blank=True, on_delete=models.CASCADE)
invoice_from = models.TextField()
+ invoice_from_name = models.CharField(max_length=190, null=True)
+ invoice_from_zipcode = models.CharField(max_length=190, null=True)
+ invoice_from_city = models.CharField(max_length=190, null=True)
+ invoice_from_country = CountryField(null=True)
+ invoice_from_tax_id = models.CharField(max_length=190, null=True)
+ invoice_from_vat_id = models.CharField(max_length=190, null=True)
invoice_to = models.TextField()
+ invoice_to_company = models.TextField(null=True)
+ invoice_to_name = models.TextField(null=True)
+ invoice_to_street = models.TextField(null=True)
+ invoice_to_zipcode = models.CharField(max_length=190, null=True)
+ invoice_to_city = models.TextField(null=True)
+ invoice_to_country = CountryField(null=True)
+ invoice_to_vat_id = models.TextField(null=True)
date = models.DateField(default=today)
locale = models.CharField(max_length=50, default='en')
introductory_text = models.TextField(blank=True)
@@ -92,6 +107,18 @@ class Invoice(models.Model):
def _to_numeric_invoice_number(number):
return '{:05d}'.format(int(number))
+ @property
+ def full_invoice_from(self):
+ parts = [
+ self.invoice_from_name,
+ self.invoice_from,
+ (self.invoice_from_zipcode or "") + " " + (self.invoice_from_city or ""),
+ str(self.invoice_from_country),
+ pgettext("invoice", "VAT-ID: %s" % self.invoice_from_vat_id) if self.invoice_from_vat_id else "",
+ pgettext("invoice", "Tax ID: %s" % self.invoice_from_tax_id) if self.invoice_from_tax_id else "",
+ ]
+ return '\n'.join([p.strip() for p in parts if p and p.strip()])
+
def _get_numeric_invoice_number(self):
numeric_invoices = Invoice.objects.filter(
event__organizer=self.event.organizer,
diff --git a/src/pretix/base/services/invoices.py b/src/pretix/base/services/invoices.py
index 93b2753b7a..734e1fe2cb 100644
--- a/src/pretix/base/services/invoices.py
+++ b/src/pretix/base/services/invoices.py
@@ -40,6 +40,12 @@ def build_invoice(invoice: Invoice) -> Invoice:
with language(invoice.locale):
invoice.invoice_from = invoice.event.settings.get('invoice_address_from')
+ invoice.invoice_from_name = invoice.event.settings.get('invoice_address_from_name')
+ invoice.invoice_from_zipcode = invoice.event.settings.get('invoice_address_from_zipcode')
+ invoice.invoice_from_city = invoice.event.settings.get('invoice_address_from_city')
+ invoice.invoice_from_country = invoice.event.settings.get('invoice_address_from_country')
+ invoice.invoice_from_tax_id = invoice.event.settings.get('invoice_address_from_tax_id')
+ invoice.invoice_from_vat_id = invoice.event.settings.get('invoice_address_from_vat_id')
introductory = invoice.event.settings.get('invoice_introductory_text', as_type=LazyI18nString)
additional = invoice.event.settings.get('invoice_additional_text', as_type=LazyI18nString)
@@ -66,8 +72,16 @@ def build_invoice(invoice: Invoice) -> Invoice:
country=ia.country.name if ia.country else ia.country_old
).strip()
invoice.internal_reference = ia.internal_reference
+ invoice.invoice_to_company = ia.company
+ invoice.invoice_to_name = ia.name
+ invoice.invoice_to_street = ia.street
+ invoice.invoice_to_zipcode = ia.zipcode
+ invoice.invoice_to_city = ia.city
+ invoice.invoice_to_country = ia.country
+
if ia.vat_id:
invoice.invoice_to += "\n" + pgettext("invoice", "VAT-ID: %s") % ia.vat_id
+ invoice.invoice_to_vat_id = ia.vat_id
cc = str(ia.country)
@@ -267,6 +281,12 @@ def build_preview_invoice_pdf(event):
date=timezone.now().date(), locale=locale, organizer=event.organizer
)
invoice.invoice_from = event.settings.get('invoice_address_from')
+ invoice.invoice_from_name = invoice.event.settings.get('invoice_address_from_name')
+ invoice.invoice_from_zipcode = invoice.event.settings.get('invoice_address_from_zipcode')
+ invoice.invoice_from_city = invoice.event.settings.get('invoice_address_from_city')
+ invoice.invoice_from_country = invoice.event.settings.get('invoice_address_from_country')
+ invoice.invoice_from_tax_id = invoice.event.settings.get('invoice_address_from_tax_id')
+ invoice.invoice_from_vat_id = invoice.event.settings.get('invoice_address_from_vat_id')
introductory = event.settings.get('invoice_introductory_text', as_type=LazyI18nString)
additional = event.settings.get('invoice_additional_text', as_type=LazyI18nString)
diff --git a/src/pretix/control/forms/event.py b/src/pretix/control/forms/event.py
index 1aff70866e..5b724153c5 100644
--- a/src/pretix/control/forms/event.py
+++ b/src/pretix/control/forms/event.py
@@ -9,7 +9,7 @@ from django.utils.timezone import get_current_timezone_name
from django.utils.translation import (
pgettext, pgettext_lazy, ugettext_lazy as _,
)
-from django_countries import Countries
+from django_countries import Countries, countries
from django_countries.fields import LazyTypedChoiceField
from i18nfield.forms import (
I18nForm, I18nFormField, I18nFormSetMixin, I18nTextarea, I18nTextInput,
@@ -522,6 +522,9 @@ class ProviderForm(SettingsForm):
class InvoiceSettingsForm(SettingsForm):
+ allcountries = list(countries)
+ allcountries.insert(0, ('', _('Select country')))
+
invoice_address_asked = forms.BooleanField(
label=_("Ask for invoice address"),
required=False
@@ -572,9 +575,10 @@ class InvoiceSettingsForm(SettingsForm):
invoice_generate = forms.ChoiceField(
label=_("Generate invoices"),
required=False,
+ widget=forms.RadioSelect,
choices=(
- ('False', _('No')),
- ('admin', _('Manually in admin panel')),
+ ('False', _('Do not generate invoices')),
+ ('admin', _('Only manually in admin panel')),
('user', _('Automatically on user request')),
('True', _('Automatically for all created orders')),
('paid', _('Automatically on payment')),
@@ -598,19 +602,46 @@ class InvoiceSettingsForm(SettingsForm):
required=True,
choices=[]
)
+ invoice_address_from_name = forms.CharField(
+ label=_("Company name"),
+ required=False,
+ )
invoice_address_from = forms.CharField(
+ label=_("Address line"),
widget=forms.Textarea(attrs={
- 'rows': 5,
+ 'rows': 2,
'placeholder': _(
- 'Sample Event Company\n'
- 'Albert Einstein Road 52\n'
- '12345 Samplecity'
+ 'Albert Einstein Road 52'
)
}),
required=False,
- label=_("Your address"),
- help_text=_("Will be printed as the sender on invoices. Be sure to include relevant details required in "
- "your jurisdiction.")
+ )
+ invoice_address_from_zipcode = forms.CharField(
+ widget=forms.TextInput(attrs={
+ 'placeholder': '12345'
+ }),
+ required=False,
+ label=_("ZIP code"),
+ )
+ invoice_address_from_city = forms.CharField(
+ widget=forms.TextInput(attrs={
+ 'placeholder': _('Random City')
+ }),
+ required=False,
+ label=_("City"),
+ )
+ invoice_address_from_country = forms.ChoiceField(
+ choices=allcountries,
+ required=False,
+ label=_("Country"),
+ )
+ invoice_address_from_tax_id = forms.CharField(
+ required=False,
+ label=_("Domestic tax ID"),
+ )
+ invoice_address_from_vat_id = forms.CharField(
+ required=False,
+ label=_("EU VAT ID"),
)
invoice_introductory_text = I18nFormField(
widget=I18nTextarea,
diff --git a/src/pretix/control/templates/pretixcontrol/event/invoicing.html b/src/pretix/control/templates/pretixcontrol/event/invoicing.html
index a60008b471..202c6e6763 100644
--- a/src/pretix/control/templates/pretixcontrol/event/invoicing.html
+++ b/src/pretix/control/templates/pretixcontrol/event/invoicing.html
@@ -6,21 +6,36 @@
{% csrf_token %}
{% bootstrap_form_errors form %}