Merge branch 'feature/LIL-503' into 'master'

Feature/lil 503

See merge request lilcity/backend!172
remotes/origin/hotfix/LIL-691
cfwme 7 years ago
commit 2358731706
  1. 0
      apps/notification/management/__init__.py
  2. 0
      apps/notification/management/commands/__init__.py
  3. 73
      apps/notification/management/commands/send_certificates.py
  4. 26
      apps/notification/migrations/0001_initial.py
  5. 11
      apps/notification/models.py
  6. 28
      apps/notification/templates/notification/email/certificate.html
  7. 4
      apps/notification/utils.py
  8. 17
      apps/payment/migrations/0024_auto_20181002_0338.py
  9. BIN
      web/src/img/user-certificates/1.jpg
  10. BIN
      web/src/img/user-certificates/2.jpg
  11. BIN
      web/src/img/user-certificates/3.jpg
  12. BIN
      web/src/img/user-certificates/4.jpg
  13. BIN
      web/src/img/user-certificates/5.jpg
  14. BIN
      web/src/img/user-certificates/6.jpg
  15. BIN
      web/src/img/user-certificates/7.jpg
  16. BIN
      web/src/img/user-certificates/8.jpg
  17. BIN
      web/src/img/user-certificates/9.jpg
  18. 10
      web/webpack.config.js

@ -0,0 +1,73 @@
from django.core.management.base import BaseCommand
from email.mime.image import MIMEImage
from django.contrib.staticfiles.storage import staticfiles_storage
from django.utils.timezone import now
from django.contrib.auth import get_user_model
from apps.notification.models import UserNotification
from apps.notification.utils import send_email
from apps.payment.models import Payment, SchoolPayment, CoursePayment
User = get_user_model()
class Command(BaseCommand):
help = 'Send certificates at the end of subscription'
def add_arguments(self, parser):
# Named (optional) arguments
parser.add_argument(
'--email',
dest='email',
help='Test email',
)
parser.add_argument(
'--dry-run',
action='store_true',
dest='dry_run',
help='Only display emails',
)
def handle(self, *args, **options):
path_pattern = 'img/user-certificates/%d.jpg'
if options.get('email'):
file = open(staticfiles_storage.path(path_pattern % 1), 'rb')
try:
send_email('Грамота от Lil School', options['email'], 'notification/email/certificate.html',
attachments=[(file.name, file.read(), 'image/jpeg')])
except:
pass
else:
print('Email has been sent')
finally:
file.close()
return
today = now().date()
users = SchoolPayment.objects.filter(date_end=today, add_days=False).values_list('user_id', flat=True)
user_notifications_qs = UserNotification.objects.filter(user_id__in=users)
user_notifications = {un.user.id: un for un in user_notifications_qs}
notified_users = user_notifications_qs.filter(certificate_last_email__date=today).values_list('user_id', flat=True)
for user_id in users:
if user_id in notified_users:
continue
un = user_notifications.get(user_id, UserNotification(user_id=user_id))
print(un.user.email)
if options.get('dry_run'):
continue
un.certificate_number = un.certificate_number + 1 \
if un.certificate_number and staticfiles_storage.exists(path_pattern % (un.certificate_number + 1)) \
else 1
file = open(staticfiles_storage.path(path_pattern % un.certificate_number), 'rb')
try:
send_email('Грамота от Lil School', un.user.email, 'notification/email/certificate.html',
attachments=[(file.name, file.read(), 'image/jpeg')])
except:
print('Not OK')
continue
finally:
file.close()
un.certificate_last_email = now()
un.save()

@ -0,0 +1,26 @@
# Generated by Django 2.0.6 on 2018-10-02 03:38
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='UserNotification',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('certificate_number', models.SmallIntegerField(blank=True, null=True)),
('certificate_last_email', models.DateTimeField(blank=True, null=True)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]

@ -0,0 +1,11 @@
from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()
class UserNotification(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
certificate_number = models.SmallIntegerField(blank=True, null=True)
certificate_last_email = models.DateTimeField(blank=True, null=True)

@ -0,0 +1,28 @@
{% extends "notification/email/_base.html" %}
{% block content %}
<p style="margin: 0 0 20px">Дорогие родители!</p>
<div style="margin-bottom: 10px;">
<p>Это письмо адресовано вашим детям - ученикам Lil School.
Если они еще не умеют читать, прочитайте им наше послание, громко и с выражением.<br>
Спасибо!
</p>
</div>
<div style="margin-bottom: 10px; font-style: italic;">
Привет, друг!<br>
Вот и прошёл месяц обучения на платформе «Lil School» - месяц удивительных, творческих приключений и открытий.
Ты так много узнал и столько всего нарисовал!
Как же здорово у тебя все получается!
</div>
<div style="margin-bottom: 10px; font-style: italic;">
Скорее смотри что прикреплено к письму. Да это же ГРАМОТА! Ее можно распечатать и повесить
на видное место в твоей комнате.
Можно показать ее друзьям вместе со всеми работами, над которыми ты так трудился.
</div>
<div style="margin-bottom: 10px; font-style: italic;">
Поздравляем! Мы ждём тебя в новом месяце в рядах наших учеников.
</div>
<div style="margin-bottom: 10px; font-style: italic;">
Команда «Lil School».
</div>
{% endblock content %}

@ -7,9 +7,9 @@ from project.celery import app
@app.task
def send_email(subject, to_email, template_name, **kwargs):
def send_email(subject, to_email, template_name, attachments=[], **kwargs):
html = get_template(template_name).render(kwargs)
email = EmailMessage(subject, html, to=[to_email])
email = EmailMessage(subject, html, to=[to_email], attachments=attachments)
email.content_subtype = 'html'
email.send()

@ -0,0 +1,17 @@
# Generated by Django 2.0.6 on 2018-10-02 03:38
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('payment', '0023_payment_bonus'),
]
operations = [
migrations.AlterModelOptions(
name='userbonus',
options={'ordering': ('created_at',)},
),
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

@ -12,7 +12,8 @@ module.exports = {
contestRedactor: "./src/js/contest-redactor.js",
mixpanel: "./src/js/third_party/mixpanel-2-latest.js",
sprite: glob('./src/icons/*.svg'),
images: glob('./src/img/*'),
images: glob('./src/img/*.*'),
imagesCertificates: glob('./src/img/user-certificates/*'),
fonts: glob('./src/fonts/*')
},
output: {
@ -84,9 +85,14 @@ module.exports = {
},
{
test: /\.(png|gif|jpg|svg)$/,
exclude: path.resolve(__dirname, 'src/icons'),
exclude: [path.resolve(__dirname, 'src/icons'), path.resolve(__dirname, 'src/img/user-certificates')],
loader: 'file-loader?name=[name].[ext]&outputPath=./img/'
},
{
test: /\.(png|jpg)$/,
include: path.resolve(__dirname, 'src/img/user-certificates'),
loader: 'file-loader?name=[name].[ext]&outputPath=./img/user-certificates/'
},
{
test: /\.(ttf|otf|eot|woff(2)?)(\?[a-z0-9]+)?$/,
loader: 'file-loader?name=[name].[ext]'

Loading…
Cancel
Save