forked from CGM_Public/pretix_original
Allow to change length of invoice numbers
This commit is contained in:
@@ -597,6 +597,7 @@ class EventSettingsSerializer(serializers.Serializer):
|
||||
'invoice_numbers_consecutive',
|
||||
'invoice_numbers_prefix',
|
||||
'invoice_numbers_prefix_cancellations',
|
||||
'invoice_numbers_counter_length',
|
||||
'invoice_attendee_name',
|
||||
'invoice_include_expire_date',
|
||||
'invoice_address_explanation_text',
|
||||
|
||||
@@ -116,8 +116,8 @@ class Invoice(models.Model):
|
||||
objects = ScopedManager(organizer='event__organizer')
|
||||
|
||||
@staticmethod
|
||||
def _to_numeric_invoice_number(number):
|
||||
return '{:05d}'.format(int(number))
|
||||
def _to_numeric_invoice_number(number, places):
|
||||
return ('{:0%dd}' % places).format(int(number))
|
||||
|
||||
@property
|
||||
def full_invoice_from(self):
|
||||
@@ -173,7 +173,7 @@ class Invoice(models.Model):
|
||||
]
|
||||
return '\n'.join([p.strip() for p in parts if p and p.strip()])
|
||||
|
||||
def _get_numeric_invoice_number(self):
|
||||
def _get_numeric_invoice_number(self, c_length):
|
||||
numeric_invoices = Invoice.objects.filter(
|
||||
event__organizer=self.event.organizer,
|
||||
prefix=self.prefix,
|
||||
@@ -182,7 +182,7 @@ class Invoice(models.Model):
|
||||
).aggregate(
|
||||
max=Max('numeric_number')
|
||||
)['max'] or 0
|
||||
return self._to_numeric_invoice_number(numeric_invoices + 1)
|
||||
return self._to_numeric_invoice_number(numeric_invoices + 1, c_length)
|
||||
|
||||
def _get_invoice_number_from_order(self):
|
||||
return '{order}-{count}'.format(
|
||||
@@ -209,7 +209,7 @@ class Invoice(models.Model):
|
||||
self.prefix += 'TEST-'
|
||||
for i in range(10):
|
||||
if self.event.settings.get('invoice_numbers_consecutive'):
|
||||
self.invoice_no = self._get_numeric_invoice_number()
|
||||
self.invoice_no = self._get_numeric_invoice_number(self.event.settings.invoice_numbers_counter_length)
|
||||
else:
|
||||
self.invoice_no = self._get_invoice_number_from_order()
|
||||
try:
|
||||
|
||||
@@ -309,6 +309,16 @@ DEFAULTS = {
|
||||
help_text=_("The expiration date will not be shown if the invoice is generated after the order is paid."),
|
||||
)
|
||||
},
|
||||
'invoice_numbers_counter_length': {
|
||||
'default': '5',
|
||||
'type': int,
|
||||
'form_class': forms.IntegerField,
|
||||
'serializer_class': serializers.IntegerField,
|
||||
'form_kwargs': dict(
|
||||
label=_("Minimum length of invoice number after prefix"),
|
||||
help_text=_("The part of your invoice number after your prefix will be filled up with leading zeros up to this length, e.g. INV-001 or INV-00001."),
|
||||
)
|
||||
},
|
||||
'invoice_numbers_consecutive': {
|
||||
'default': 'True',
|
||||
'type': bool,
|
||||
|
||||
@@ -677,6 +677,7 @@ class InvoiceSettingsForm(SettingsForm):
|
||||
'invoice_numbers_consecutive',
|
||||
'invoice_numbers_prefix',
|
||||
'invoice_numbers_prefix_cancellations',
|
||||
'invoice_numbers_counter_length',
|
||||
'invoice_address_explanation_text',
|
||||
'invoice_email_attachment',
|
||||
'invoice_address_from_name',
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
{% bootstrap_field form.invoice_numbers_consecutive layout="control" %}
|
||||
{% bootstrap_field form.invoice_numbers_prefix layout="control" %}
|
||||
{% bootstrap_field form.invoice_numbers_prefix_cancellations layout="control" %}
|
||||
{% bootstrap_field form.invoice_numbers_counter_length layout="control" %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Address form" %}</legend>
|
||||
|
||||
@@ -369,6 +369,12 @@ def test_invoice_numbers(env):
|
||||
inv8 = generate_invoice(order)
|
||||
inv23 = generate_invoice(order2)
|
||||
|
||||
event.settings.set('invoice_numbers_counter_length', 6)
|
||||
inv24 = generate_invoice(order)
|
||||
event.settings.set('invoice_numbers_counter_length', 1)
|
||||
inv25 = generate_invoice(order)
|
||||
inv26 = generate_invoice(order)
|
||||
|
||||
# expected behaviour for switching between numbering formats or dealing with gaps
|
||||
assert inv1.invoice_no == '00001'
|
||||
assert inv2.invoice_no == '00002'
|
||||
@@ -384,6 +390,9 @@ def test_invoice_numbers(env):
|
||||
assert inv22.invoice_no == '{}-2'.format(order2.code)
|
||||
# but consecutively in this mode
|
||||
assert inv23.invoice_no == '00007'
|
||||
assert inv24.invoice_no == '000008'
|
||||
assert inv25.invoice_no == '9'
|
||||
assert inv26.invoice_no == '10'
|
||||
|
||||
# test Invoice.number, too
|
||||
assert inv1.number == '{}-00001'.format(event.slug.upper())
|
||||
@@ -441,13 +450,14 @@ def test_invoice_number_prefixes(env):
|
||||
event2.settings.set('invoice_numbers_prefix', 'inv_')
|
||||
event2.settings.set('invoice_numbers_prefix_cancellations', 'crd_')
|
||||
event2.settings.set('invoice_numbers_consecutive', True)
|
||||
event2.settings.set('invoice_numbers_counter_length', 4)
|
||||
i = generate_invoice(order2)
|
||||
assert i.number == 'inv_00001'
|
||||
assert generate_cancellation(i).number == 'crd_00001'
|
||||
assert i.number == 'inv_0001'
|
||||
assert generate_cancellation(i).number == 'crd_0001'
|
||||
|
||||
event2.settings.set('invoice_numbers_prefix', 'inv_%Y%m%d_')
|
||||
i = generate_invoice(order2)
|
||||
assert i.number == 'inv_%s_00001' % now().date().strftime('%Y%m%d')
|
||||
assert i.number == 'inv_%s_0001' % now().date().strftime('%Y%m%d')
|
||||
|
||||
# Test database uniqueness check
|
||||
with pytest.raises(DatabaseError):
|
||||
|
||||
Reference in New Issue
Block a user