summaryrefslogtreecommitdiff
path: root/postgresqleu
diff options
context:
space:
mode:
authorMagnus Hagander2018-12-19 20:03:13 +0000
committerMagnus Hagander2018-12-19 20:03:13 +0000
commitb71591f13ba8fc03453a8b445ec61bfdc1e4ebba (patch)
tree2cf41e4d6f4fde2f3e58f8ef6f08269a31fb8705 /postgresqleu
parent253f30dc0c66bb70a4b8590874ea57bc06605aaa (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.
Diffstat (limited to 'postgresqleu')
-rw-r--r--postgresqleu/invoices/forms.py2
-rw-r--r--postgresqleu/invoices/migrations/0008_invoice_bcc_list.py21
-rw-r--r--postgresqleu/invoices/models.py4
-rw-r--r--postgresqleu/invoices/util.py15
-rw-r--r--postgresqleu/invoices/views.py7
-rw-r--r--postgresqleu/mailqueue/util.py8
-rw-r--r--postgresqleu/util/validators.py6
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()))