lingo: send emails when notifying new invoices (#13122)
This commit is contained in:
parent
834e1e8612
commit
7d58ccfd3c
|
@ -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)
|
||||
|
|
|
@ -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>
|
|
@ -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 %}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{% load i18n %}
|
||||
{% blocktrans with invoice_id=item.id %}
|
||||
New invoice nr. {{ invoice_id }} is available
|
||||
{% endblocktrans %}
|
|
@ -288,6 +288,9 @@ COMBO_MAP_ATTRIBUTION = 'Map data © <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
|
||||
|
|
|
@ -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
|
||||
|
@ -36,6 +38,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:
|
||||
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue