Allow to change length of invoice numbers

This commit is contained in:
Raphael Michel
2020-07-21 18:11:00 +02:00
parent b305ac012c
commit 735d4564f8
6 changed files with 31 additions and 8 deletions

View File

@@ -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',

View File

@@ -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:

View File

@@ -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,

View File

@@ -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',

View File

@@ -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>

View File

@@ -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):