summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerghei Mihai <smihai@entrouvert.com>2018-03-07 18:20:31 (GMT)
committerSerghei Mihai <smihai@entrouvert.com>2018-03-20 07:22:29 (GMT)
commit7d58ccfd3cd7090def64a1b1f891d72266ac4c77 (patch)
tree6459ca4d7d2a835d91410867b84ddc717b804c0d
parent834e1e8612a0c66fd46799f1ab87218b82ea1c39 (diff)
downloadcombo-wip/notifications-13122.zip
combo-wip/notifications-13122.tar.gz
combo-wip/notifications-13122.tar.bz2
lingo: send emails when notifying new invoices (#13122)wip/notifications-13122
-rw-r--r--combo/apps/lingo/models.py35
-rw-r--r--combo/apps/lingo/templates/lingo/combo/invoice_email_notification_body.html20
-rw-r--r--combo/apps/lingo/templates/lingo/combo/invoice_email_notification_body.txt13
-rw-r--r--combo/apps/lingo/templates/lingo/combo/invoice_email_notification_subject.txt4
-rw-r--r--combo/settings.py3
-rw-r--r--tests/test_lingo_remote_regie.py36
-rw-r--r--tests/test_notification.py17
7 files changed, 118 insertions, 10 deletions
diff --git a/combo/apps/lingo/models.py b/combo/apps/lingo/models.py
index a38940c..d6c2a06 100644
--- a/combo/apps/lingo/models.py
+++ b/combo/apps/lingo/models.py
@@ -33,10 +33,13 @@ from django.db import models
from django.forms import models as model_forms, Select
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone, dateparse
+from django.core.mail import EmailMultiAlternatives
+from django.core.urlresolvers import reverse
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.utils.http import urlencode
from django.contrib.auth.models import User
+from django.template.loader import render_to_string
from combo.data.fields import RichTextField
from combo.data.models import CellBase
@@ -229,13 +232,20 @@ class Regie(models.Model):
items_page_url = ''
# notification should be created
if pay_limit_date > now:
+ # if no notification exists, send the email
+ if not Notification.objects.find(user, invoice_id):
+ self.notify_remote_invoice_by_email(user, invoice)
notification = Notification.notify(user, _('Invoice %s to pay') % invoice['label'], id=invoice_id,
- url=items_page_url, end_timestamp=invoice['pay_limit_date'])
- if pay_limit_date <= now + remind_delta or not notification.acked:
+ url=items_page_url, end_timestamp=pay_limit_date)
+ if pay_limit_date <= now + remind_delta or notification.acked:
+ # if no remind notification exists, send the email
+ if not Notification.objects.find(user, reminder_id):
+ self.notify_remote_invoice_by_email(user, invoice)
# create remind notification
Notification.notify(user, _('Reminder: invoice %s to pay') % invoice['label'],
id=reminder_id, url=items_page_url,
end_timestamp=invoice['pay_limit_date'])
+ self.notify_remote_invoice_by_email(user, invoice)
else:
Notification.forget(user, invoice_id)
Notification.forget(user, reminder_id)
@@ -251,6 +261,27 @@ class Regie(models.Model):
if Decimal(invoice['total_amount']) >= self.payment_min_amount:
self.notify_invoice(user, invoice)
+ def notify_remote_invoice_by_email(self, user, invoice):
+
+ subject_template = 'lingo/combo/invoice_email_notification_subject.txt'
+ text_body_template = 'lingo/combo/invoice_email_notification_body.txt'
+ html_body_template = 'lingo/combo/invoice_email_notification_body.html'
+
+ remote_item = build_remote_item(invoice, self)
+ payment_url = reverse('view-item', kwargs={'regie_id': self.id,
+ 'item_crypto_id': remote_item.crypto_id})
+ ctx = {'item': remote_item}
+ ctx.update({'payment_url': urlparse.urljoin(settings.SITE_BASE_URL, payment_url)})
+ subject = render_to_string([subject_template], ctx).strip()
+ text_body = render_to_string([text_body_template], ctx)
+ html_body = render_to_string([html_body_template], ctx)
+ message = EmailMultiAlternatives(subject, text_body, to=[user.email])
+ message.attach_alternative(html_body, 'text/html')
+ if invoice['has_pdf']:
+ invoice_pdf = self.get_invoice_pdf(user, invoice['id'])
+ message.attach('%s.pdf' % invoice['id'], invoice_pdf.content, 'application/pdf')
+ message.send()
+
class BasketItem(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True)
diff --git a/combo/apps/lingo/templates/lingo/combo/invoice_email_notification_body.html b/combo/apps/lingo/templates/lingo/combo/invoice_email_notification_body.html
new file mode 100644
index 0000000..16bb059
--- /dev/null
+++ b/combo/apps/lingo/templates/lingo/combo/invoice_email_notification_body.html
@@ -0,0 +1,20 @@
+{% load i18n %}
+
+<html>
+ <body style="max-width: 60em">
+ <p>{% blocktrans with id=item.id creation_date=item.creation_date|date:"DATE_FORMAT" amount=item.amount %}
+ We inform you that your invoice nr. {{ id }} issued on {{ creation_date }} of amount of {{ amount }}€ is available on {{ site_title }}.
+ {% endblocktrans %}</p>
+ {% if item.online_payment %}
+ <p>{% blocktrans %}You can <a href="{{ payment_url }}">view and pay it online</a>.{% endblocktrans %}</p>
+ {% else %}
+ <p>{% blocktrans %}You can view it by going on your <a href="{{ portal_url }}">{{ site_title }}</a>.{% endblocktrans %}</p>
+ {% if item.no_online_payment_reason == 'autobilling' %}
+ <p>{% blocktrans with debit_date=item.payment_limit_date|date:"DATE_FORMAT" %}
+ The amount of this invoice will be debited from your account at {{ debit_date }}.
+ {% endblocktrans %}
+ </p>
+ {% endif %}
+ {% endif %}
+ </body>
+</html>
diff --git a/combo/apps/lingo/templates/lingo/combo/invoice_email_notification_body.txt b/combo/apps/lingo/templates/lingo/combo/invoice_email_notification_body.txt
new file mode 100644
index 0000000..7b562fb
--- /dev/null
+++ b/combo/apps/lingo/templates/lingo/combo/invoice_email_notification_body.txt
@@ -0,0 +1,13 @@
+{% load i18n %}
+{% blocktrans with id=item.id creation_date=item.creation_date|date:"DATE_FORMAT" amount=item.amount %}
+We inform you that your invoice nr. {{ id }} issued on {{ creation_date }} of amount
+of {{ amount }}€ is available on {{ site_title }}.{% endblocktrans %}
+
+{% if item.online_payment %}{% blocktrans %}You can view and pay it online on {{ payment_url }}.{% endblocktrans %}
+{% else %}{% blocktrans %}You can view it by going on {{ portal_url }}.{% endblocktrans %}
+
+{% if item.no_online_payment_reason == 'autobilling' %}
+{% blocktrans with debit_date=item.payment_limit_date|date:"DATE_FORMAT" %}The amount of this invoice will be debited from your account at {{ debit_date }}.{% endblocktrans %}
+{% endif %}
+{% endif %}
+
diff --git a/combo/apps/lingo/templates/lingo/combo/invoice_email_notification_subject.txt b/combo/apps/lingo/templates/lingo/combo/invoice_email_notification_subject.txt
new file mode 100644
index 0000000..83c802e
--- /dev/null
+++ b/combo/apps/lingo/templates/lingo/combo/invoice_email_notification_subject.txt
@@ -0,0 +1,4 @@
+{% load i18n %}
+{% blocktrans with invoice_id=item.id %}
+New invoice nr. {{ invoice_id }} is available
+{% endblocktrans %}
diff --git a/combo/settings.py b/combo/settings.py
index 4460d01..a7b4738 100644
--- a/combo/settings.py
+++ b/combo/settings.py
@@ -288,6 +288,9 @@ COMBO_MAP_ATTRIBUTION = 'Map data &copy; <a href="https://openstreetmap.org">Ope
# default delta, in days, for invoice remind notifications
LINGO_NEW_INVOICES_REMIND_DELTA = 7
+# default site
+SITE_BASE_URL = 'http://localhost'
+
# timeout used in python-requests call, in seconds
# we use 28s by default: timeout just before web server, which is usually 30s
REQUESTS_TIMEOUT = 28
diff --git a/tests/test_lingo_remote_regie.py b/tests/test_lingo_remote_regie.py
index 09a5967..30a7bbf 100644
--- a/tests/test_lingo_remote_regie.py
+++ b/tests/test_lingo_remote_regie.py
@@ -9,6 +9,8 @@ from django.test.client import RequestFactory
from django.core.urlresolvers import reverse
from django.conf import settings
from django.core.management import call_command
+from django.utils.timezone import timedelta, now
+from django.contrib.auth.models import User
from combo.utils import check_query, aes_hex_encrypt
from combo.data.models import Page
@@ -37,6 +39,16 @@ INVOICES = [
]
@pytest.fixture
+def admin():
+ try:
+ admin = User.objects.get(username='foo')
+ except User.DoesNotExist:
+ admin = User.objects.create_user('foo', email=None, password='bar')
+ admin.email = 'foo@example.net'
+ admin.save()
+ return admin
+
+@pytest.fixture
def remote_regie():
try:
regie = Regie.objects.get(slug='remote')
@@ -336,3 +348,27 @@ def test_remote_item_payment_failure(mock_post, mock_get, mock_pay_invoice, app,
assert Transaction.objects.all()[0].to_be_paid_remote_items is None
call_command('update_transactions')
+
+@mock.patch('combo.apps.lingo.models.requests.get')
+def test_send_new_remote_invoices_by_email(mock_get, admin, app, remote_regie, mailoutbox):
+ datetime_format = '%Y-%m-%dT%H:%M:%S'
+ invoice_now = now()
+ creation_date = (invoice_now - timedelta(days=1)).strftime(datetime_format)
+ pay_limit_date = (invoice_now + timedelta(days=30)).strftime(datetime_format)
+ FAKE_PENDING_INVOICES = {
+ 'data' : {'foo': {'invoices': [{'id': '01', 'label': '010101', 'paid': False,
+ 'amount': '37.26', 'total_amount': '37.26', 'online_payment': True,
+ 'has_pdf': True, 'created': creation_date,
+ 'pay_limit_date': pay_limit_date}]},
+ }
+ }
+ mock_response = mock.Mock(status_code=200, content=json.dumps(FAKE_PENDING_INVOICES))
+ mock_response.json.return_value = FAKE_PENDING_INVOICES
+ mock_get.return_value = mock_response
+ remote_regie.notify_new_remote_invoices()
+ assert len(mailoutbox) == 1
+ assert mailoutbox[0].recipients() == ['foo@example.net']
+ assert mailoutbox[0].from_email == settings.DEFAULT_FROM_EMAIL
+ assert mailoutbox[0].subject == 'New invoice nr. 01 is available'
+ assert mailoutbox[0].attachments[0][0] == '01.pdf'
+ assert mailoutbox[0].attachments[0][2] == 'application/pdf'
diff --git a/tests/test_notification.py b/tests/test_notification.py
index 018c4d9..99c328d 100644
--- a/tests/test_notification.py
+++ b/tests/test_notification.py
@@ -280,14 +280,14 @@ def test_notify_remote_items(mock_get, app, user, user2, regie):
creation_date = (invoice_now - timedelta(days=1)).strftime(datetime_format)
pay_limit_date = (invoice_now + timedelta(days=5)).strftime(datetime_format)
FAKE_PENDING_INVOICES = {
- "data" : {"admin": {"invoices": [{'id': '01', 'label': '010101', 'total_amount': '10',
- 'created': creation_date, 'pay_limit_date': pay_limit_date},
- {'id': '011', 'label': '0101011', 'total_amount': '1.5',
- 'created': creation_date, 'pay_limit_date': pay_limit_date}]},
- 'admin2': {'invoices': [{'id': '02', 'label': '020202', 'total_amount': '2.0',
- 'created': creation_date, 'pay_limit_date': pay_limit_date}]},
- 'foo': {'invoices': [{'id': 'O3', 'label': '030303', 'total_amount': '42',
- 'created': creation_date, 'pay_limit_date': pay_limit_date}]}
+ "data" : {"admin": {"invoices": [{'id': '01', 'label': '010101', 'total_amount': '10', 'amount': '10',
+ 'created': creation_date, 'pay_limit_date': pay_limit_date, 'has_pdf': False},
+ {'id': '011', 'label': '0101011', 'total_amount': '1.5', 'amount': '1.5',
+ 'created': creation_date, 'pay_limit_date': pay_limit_date, 'has_pdf': False}]},
+ 'admin2': {'invoices': [{'id': '02', 'label': '020202', 'total_amount': '2.0', 'amount': '2.0',
+ 'created': creation_date, 'pay_limit_date': pay_limit_date, 'has_pdf': False}]},
+ 'foo': {'invoices': [{'id': 'O3', 'label': '030303', 'total_amount': '42', 'amount': '42',
+ 'created': creation_date, 'pay_limit_date': pay_limit_date, 'has_pdf': False}]}
}
}
mock_response = mock.Mock(status_code=200, content=json.dumps(FAKE_PENDING_INVOICES))
@@ -298,6 +298,7 @@ def test_notify_remote_items(mock_get, app, user, user2, regie):
regie.webservice_url = 'http://example.org/regie' # is_remote
regie.save()
regie.notify_new_remote_invoices()
+
assert Notification.objects.filter(external_id__startswith='invoice-%s' % regie.slug).count() == 2
for notif in Notification.objects.all():
print notif, notif.external_id