diff options
| author | Magnus Hagander | 2018-12-19 20:03:13 +0000 |
|---|---|---|
| committer | Magnus Hagander | 2018-12-19 20:03:13 +0000 |
| commit | b71591f13ba8fc03453a8b445ec61bfdc1e4ebba (patch) | |
| tree | 2cf41e4d6f4fde2f3e58f8ef6f08269a31fb8705 | |
| parent | 253f30dc0c66bb70a4b8590874ea57bc06605aaa (diff) | |
Add ability to add extra bcc addresses to invoices
This can be a list (comma separated) of email addresses that will
receive a BCC of all emails about this invoice. This is similar to how
the treasurer address gets such a copy, but makes it possible to add
more than one address.
| -rw-r--r-- | postgresqleu/invoices/forms.py | 2 | ||||
| -rw-r--r-- | postgresqleu/invoices/migrations/0008_invoice_bcc_list.py | 21 | ||||
| -rw-r--r-- | postgresqleu/invoices/models.py | 4 | ||||
| -rw-r--r-- | postgresqleu/invoices/util.py | 15 | ||||
| -rw-r--r-- | postgresqleu/invoices/views.py | 7 | ||||
| -rw-r--r-- | postgresqleu/mailqueue/util.py | 8 | ||||
| -rw-r--r-- | postgresqleu/util/validators.py | 6 |
7 files changed, 55 insertions, 8 deletions
diff --git a/postgresqleu/invoices/forms.py b/postgresqleu/invoices/forms.py index 13a2b199..34d2caea 100644 --- a/postgresqleu/invoices/forms.py +++ b/postgresqleu/invoices/forms.py @@ -16,7 +16,7 @@ from postgresqleu.invoices.models import VatRate class InvoiceForm(forms.ModelForm): hidden_until_finalized = ('total_amount', 'total_vat', 'remindersent', ) - available_in_finalized = ('recipient_user', 'recipient_email', 'allowedmethods',) + available_in_finalized = ('recipient_user', 'recipient_email', 'allowedmethods', 'extra_bcc_list', ) selectize_multiple_fields = ['recipient_user', ] accounting_account = forms.ChoiceField(choices=[], required=False) diff --git a/postgresqleu/invoices/migrations/0008_invoice_bcc_list.py b/postgresqleu/invoices/migrations/0008_invoice_bcc_list.py new file mode 100644 index 00000000..5e09ab1f --- /dev/null +++ b/postgresqleu/invoices/migrations/0008_invoice_bcc_list.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-12-19 20:59 +from __future__ import unicode_literals + +from django.db import migrations, models +import postgresqleu.util.validators + + +class Migration(migrations.Migration): + + dependencies = [ + ('invoices', '0007_reverse_vat'), + ] + + operations = [ + migrations.AddField( + model_name='invoice', + name='extra_bcc_list', + field=models.CharField(blank=True, max_length=500, validators=[postgresqleu.util.validators.ListOfEmailAddressValidator]), + ), + ] diff --git a/postgresqleu/invoices/models.py b/postgresqleu/invoices/models.py index 36bc2cbe..46dc1352 100644 --- a/postgresqleu/invoices/models.py +++ b/postgresqleu/invoices/models.py @@ -8,6 +8,7 @@ from decimal import Decimal from payment import PaymentMethodWrapper +from postgresqleu.util.validators import ListOfEmailAddressValidator from postgresqleu.accounting.models import Account @@ -72,6 +73,7 @@ class Invoice(models.Model): recipient_name = models.CharField(max_length=100, blank=False, null=False) recipient_address = models.TextField(blank=False, null=False) recipient_secret = models.CharField(max_length=64, blank=True, null=True) + extra_bcc_list = models.CharField(max_length=500, blank=True, null=False, validators=[ListOfEmailAddressValidator, ]) # Global invoice info title = models.CharField(max_length=100, blank=False, null=False, verbose_name="Invoice title") @@ -132,7 +134,7 @@ class Invoice(models.Model): @property def isexpired(self): - return (self.paidat is None) and (self.duedate < datetime.now()) + return (self.paidat is None) and self.duedate and (self.duedate < datetime.now()) @property def allowedmethodwrappers(self): diff --git a/postgresqleu/invoices/util.py b/postgresqleu/invoices/util.py index 6746a981..e0bd18ea 100644 --- a/postgresqleu/invoices/util.py +++ b/postgresqleu/invoices/util.py @@ -235,6 +235,13 @@ class InvoiceWrapper(object): if pdfname: pdfdata = [(pdfname, 'application/pdf', base64.b64decode(pdfcontents)), ] + if bcc: + bcclist = [settings.INVOICE_SENDER_EMAIL, ] + else: + bcclist = [] + if self.invoice.extra_bcc_list: + bcclist.extend([e.strip() for e in self.invoice.extra_bcc_list.split(',')]) + # Queue up in the database for email sending soon send_template_mail(settings.INVOICE_SENDER_EMAIL, self.invoice.recipient_email, @@ -242,7 +249,7 @@ class InvoiceWrapper(object): 'invoices/mail/%s' % template_name, param, pdfdata, - bcc=bcc and settings.INVOICE_SENDER_EMAIL or None, + bcclist, ) @@ -599,7 +606,8 @@ class InvoiceManager(object): accounting_account=None, accounting_object=None, canceltime=None, - reverse_vat=False): + reverse_vat=False, + extra_bcc_list=None): invoice = Invoice( recipient_email=recipient_email, recipient_name=recipient_name, @@ -612,7 +620,8 @@ class InvoiceManager(object): accounting_account=accounting_account, accounting_object=accounting_object, canceltime=canceltime, - reverse_vat=reverse_vat) + reverse_vat=reverse_vat, + extra_bcc_list=extra_bcc_list or '') if recipient_user: invoice.recipient_user = recipient_user if processor: diff --git a/postgresqleu/invoices/views.py b/postgresqleu/invoices/views.py index dc295b48..13db65b9 100644 --- a/postgresqleu/invoices/views.py +++ b/postgresqleu/invoices/views.py @@ -173,8 +173,11 @@ def oneinvoice(request, invoicenum): postcopy[fld] = getattr(invoice, fld) form = InvoiceForm(data=postcopy, instance=invoice) - formset = InvoiceRowInlineFormset(data=postcopy, instance=invoice) - formset.forms[0].empty_permitted = False + if form.instance.finalized: + formset = InvoiceRowInlineFormset(instance=invoice) + else: + formset = InvoiceRowInlineFormset(data=postcopy, instance=invoice) + formset.forms[0].empty_permitted = False if form.is_valid(): if formset.is_valid() or form.instance.finalized: if form.instance.finalized: diff --git a/postgresqleu/mailqueue/util.py b/postgresqleu/mailqueue/util.py index f2a66ced..be69d287 100644 --- a/postgresqleu/mailqueue/util.py +++ b/postgresqleu/mailqueue/util.py @@ -57,7 +57,13 @@ def send_simple_mail(sender, receiver, subject, msgtxt, attachments=None, bcc=No QueuedMail(sender=sender, receiver=receiver, fullmsg=msg.as_string()).save() # Any bcc is just entered as a separate email if bcc: - QueuedMail(sender=sender, receiver=bcc, fullmsg=msg.as_string()).save() + if type(bcc) is list or type(bcc) is tuple: + bcc = set(bcc) + else: + bcc = set(bcc, ) + + for b in bcc: + QueuedMail(sender=sender, receiver=b, fullmsg=msg.as_string()).save() def send_mail(sender, receiver, fullmsg): diff --git a/postgresqleu/util/validators.py b/postgresqleu/util/validators.py index 223aa29b..edcc00d9 100644 --- a/postgresqleu/util/validators.py +++ b/postgresqleu/util/validators.py @@ -1,4 +1,5 @@ from django.core.exceptions import ValidationError +from django.core.validators import EmailValidator from django.utils.deconstruct import deconstructible from StringIO import StringIO @@ -51,6 +52,11 @@ def TwitterValidator(value): # All is well! :) +def ListOfEmailAddressValidator(value): + for p in value.split(','): + EmailValidator("Enter a comma separated list of valid email addresses")(p.strip()) + + def validate_json_structure(config, structure): def _validate_json_level(config, structure, path): missing = set(structure.keys()).difference(set(config.keys())) |
