Configurable invoice prefixes

This commit is contained in:
Raphael Michel
2017-07-17 22:57:37 +02:00
parent 670bfa18de
commit 7bb12ff0ec
7 changed files with 135 additions and 5 deletions

View File

@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.2 on 2017-07-17 19:29
from __future__ import unicode_literals
from django.db import migrations, models
from django.db.models import deletion
def fwd(app, schema_editor):
Event = app.get_model('pretixbase', 'Event')
for e in Event.objects.select_related('organizer').all():
e.invoices.all().update(prefix=e.slug.upper() + '-', organizer=e.organizer)
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0068_subevent_frontpage_text'),
]
operations = [
migrations.AddField(
model_name='invoice',
name='prefix',
field=models.CharField(db_index=True, default='', max_length=160),
preserve_default=False,
),
migrations.AddField(
model_name='invoice',
name='organizer',
field=models.ForeignKey(null=True,
on_delete=deletion.PROTECT,
related_name='invoices', to='pretixbase.Organizer'),
preserve_default=False,
),
migrations.RunPython(
fwd, migrations.RunPython.noop
),
migrations.AlterUniqueTogether(
name='invoice',
unique_together=set([('organizer', 'prefix', 'invoice_no')]),
),
migrations.AlterField(
model_name='invoice',
name='organizer',
field=models.ForeignKey(on_delete=deletion.PROTECT, related_name='invoices', to='pretixbase.Organizer'),
),
]

View File

@@ -29,6 +29,8 @@ class Invoice(models.Model):
:type order: Order
:param event: The event this belongs to (for convenience)
:type event: Event
:param organizer: The organizer this belongs to (redundant, for enforcing uniqueness)
:type organizer: Organizer
:param invoice_no: The human-readable, event-unique invoice number
:type invoice_no: int
:param is_cancellation: Whether or not this is a cancellation instead of an invoice
@@ -55,7 +57,9 @@ class Invoice(models.Model):
:type file: File
"""
order = models.ForeignKey('Order', related_name='invoices', db_index=True)
organizer = models.ForeignKey('Organizer', related_name='invoices', db_index=True, on_delete=models.PROTECT)
event = models.ForeignKey('Event', related_name='invoices', db_index=True)
prefix = models.CharField(max_length=160, db_index=True)
invoice_no = models.CharField(max_length=19, db_index=True)
is_cancellation = models.BooleanField(default=False)
refers = models.ForeignKey('Invoice', related_name='refered', null=True, blank=True)
@@ -74,7 +78,10 @@ class Invoice(models.Model):
return '{:05d}'.format(int(number))
def _get_numeric_invoice_number(self):
numeric_invoices = Invoice.objects.filter(event=self.event).exclude(invoice_no__contains='-')
numeric_invoices = Invoice.objects.filter(
event__organizer=self.event.organizer,
prefix=self.prefix,
).exclude(invoice_no__contains='-')
return self._to_numeric_invoice_number(numeric_invoices.count() + 1)
def _get_invoice_number_from_order(self):
@@ -88,6 +95,10 @@ class Invoice(models.Model):
raise ValueError('Every invoice needs to be connected to an order')
if not self.event:
self.event = self.order.event
if not self.organizer:
self.organizer = self.order.event.organizer
if not self.prefix:
self.prefix = self.event.settings.invoice_numbers_prefix or (self.event.slug.upper() + '-')
if not self.invoice_no:
for i in range(10):
if self.event.settings.get('invoice_numbers_consecutive'):
@@ -116,8 +127,8 @@ class Invoice(models.Model):
"""
Returns the invoice number in a human-readable string with the event slug prepended.
"""
return '{event}-{code}'.format(
event=self.event.slug.upper(),
return '{prefix}{code}'.format(
prefix=self.prefix,
code=self.invoice_no
)
@@ -126,7 +137,7 @@ class Invoice(models.Model):
return self.refered.filter(is_cancellation=True).exists()
class Meta:
unique_together = ('event', 'invoice_no')
unique_together = ('organizer', 'prefix', 'invoice_no')
ordering = ('invoice_no',)

View File

@@ -96,6 +96,7 @@ def generate_cancellation(invoice: Invoice):
cancellation = copy.copy(invoice)
cancellation.pk = None
cancellation.invoice_no = None
cancellation.prefix = None
cancellation.refers = invoice
cancellation.is_cancellation = True
cancellation.date = timezone.now().date()
@@ -125,6 +126,7 @@ def generate_invoice(order: Order):
invoice = Invoice(
order=order,
event=order.event,
organizer=order.event.organizer,
date=timezone.now().date(),
locale=locale
)
@@ -171,7 +173,7 @@ def build_preview_invoice_pdf(event):
expires=timezone.now(), code="PREVIEW", total=119)
invoice = Invoice(
order=order, event=event, invoice_no="PREVIEW",
date=timezone.now().date(), locale=locale
date=timezone.now().date(), locale=locale, organizer=event.organizer
)
invoice.invoice_from = event.settings.get('invoice_address_from')

View File

@@ -61,6 +61,10 @@ DEFAULTS = {
'default': 'True',
'type': bool,
},
'invoice_numbers_prefix': {
'default': '',
'type': str,
},
'invoice_renderer': {
'default': 'classic',
'type': str,