Merge branch 'feature/drawing-camp' into 'master'

Feature/drawing camp

See merge request lilschool/site!304
remotes/origin/hotfix/delete-image-error-30-05-19
Danil 7 years ago
commit 0aa30e1d09
  1. 32
      apps/notification/management/commands/send_camp_certificates.py
  2. 2
      apps/notification/management/commands/send_certificates.py
  3. 18
      apps/notification/migrations/0002_usernotification_camp_certificate_last_email.py
  4. 1
      apps/notification/models.py
  5. 83
      apps/notification/tasks.py
  6. 25
      apps/notification/templates/notification/email/camp_certificate.html
  7. 10
      project/settings.py
  8. BIN
      web/src/img/camp-certificates/1.jpg
  9. BIN
      web/src/img/camp-certificates/2.jpg
  10. BIN
      web/src/img/camp-certificates/3.jpg
  11. BIN
      web/src/img/signed-camp-certificates/1.jpg
  12. BIN
      web/src/img/signed-camp-certificates/2.jpg
  13. BIN
      web/src/img/signed-camp-certificates/3.jpg
  14. 14
      web/webpack.config.js

@ -0,0 +1,32 @@
from django.core.management.base import BaseCommand
from apps.notification.tasks import send_camp_certificates
class Command(BaseCommand):
help = 'Send camp certificates at the end of month'
def add_arguments(self, parser):
# Named (optional) arguments
parser.add_argument(
'--email',
dest='email',
help='Test email',
)
parser.add_argument(
'--cert',
dest='certificate_number',
type=int,
help='Certificate number',
)
parser.add_argument(
'--dry-run',
action='store_true',
dest='dry_run',
help='Only display emails',
)
def handle(self, *args, **options):
send_camp_certificates(email=options.get('email'), certificate_number=options.get('certificate_number'),
dry_run=options.get('dry_run'))

@ -26,5 +26,5 @@ class Command(BaseCommand):
)
def handle(self, *args, **options):
send_certificates(email=options.get('email'), date=options.get('date'), dry_run=options.get('dry_run'))
send_certificates(email=options.get('email'), date_end=options.get('date'), dry_run=options.get('dry_run'))

@ -0,0 +1,18 @@
# Generated by Django 2.0.7 on 2019-05-23 01:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('notification', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='usernotification',
name='camp_certificate_last_email',
field=models.DateTimeField(blank=True, null=True),
),
]

@ -9,3 +9,4 @@ 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)
camp_certificate_last_email = models.DateTimeField(blank=True, null=True)

@ -1,5 +1,5 @@
import os
from datetime import datetime
from datetime import datetime, date, timedelta
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
@ -12,7 +12,7 @@ from django.conf import settings
from apps.notification.models import UserNotification
from apps.notification.utils import send_email
from apps.payment.models import SchoolPayment, CoursePayment, Payment, UserGiftCertificate, UserBonus
from apps.payment.models import SchoolPayment, CoursePayment, Payment, UserGiftCertificate, UserBonus, DrawingCampPayment
from project.celery import app
from project.utils.db import format_sql, execute_sql
from project.sengrid import get_sendgrid_client
@ -21,27 +21,28 @@ from project.sengrid import get_sendgrid_client
User = get_user_model()
def draw_cert(path, email, first_name, last_name):
def draw_cert(path, email, first_name, last_name, x=None, y=900, color=(29, 115, 224), font_size=170, fn_prefix=''):
img = Image.open(path)
draw = ImageDraw.Draw(img)
font = ImageFont.truetype(os.path.join(settings.STATIC_ROOT, 'ProximaNova-Reg.otf'), 170)
font = ImageFont.truetype(os.path.join(settings.STATIC_ROOT, 'ProximaNova-Reg.otf'), font_size)
text = first_name.capitalize()
if last_name:
text += ' ' + last_name.capitalize()
w, h = draw.textsize(text, font=font)
draw.text(((img.width - w) // 2, 900), text, (29, 115, 224), font=font)
_x = (img.width - w) // 2 if x is None else x
draw.text((_x, y), text, color, font=font)
fn = os.path.join(settings.MEDIA_ROOT, 'tmp')
try:
os.mkdir(fn)
except:
pass
fn = os.path.join(fn, 'certificate-for-%s.jpg' % email)
fn = os.path.join(fn, '%scertificate-for-%s.jpg' % (fn_prefix, email))
img.save(fn)
img.close()
return fn
@app.task
def send_certificates(email=None, date=None, dry_run=False):
def send_certificates(email=None, date_end=None, dry_run=False):
path_pattern = 'img/user-certificates/%d.jpg'
signed_path_pattern = 'img/signed-user-certificates/%d.jpg'
if email:
@ -59,9 +60,9 @@ def send_certificates(email=None, date=None, dry_run=False):
os.remove(fn)
return
date = datetime.strptime(date, '%d-%m-%Y').date() if date else now().date()
date_end = datetime.strptime(date_end, '%d-%m-%Y').date() if date_end else now().date()
today = now().date()
users = set(list(SchoolPayment.objects.paid().filter(date_end=date, add_days=False).values_list('user_id', flat=True)))
users = set(list(SchoolPayment.objects.paid().filter(date_end=date_end, 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(
@ -160,3 +161,67 @@ def send_child_birthday_email_and_bonuses():
print('email has been sent')
finally:
file.close()
@app.task
def send_camp_certificates(email=None, dry_run=False, certificate_number=None):
path_pattern = 'img/camp-certificates/%d.jpg'
signed_path_pattern = 'img/signed-camp-certificates/%d.jpg'
color = (0, 27, 94)
if certificate_number is None:
certificate_number = 1
if certificate_number == 2:
color = (106, 5, 163)
if certificate_number == 3:
color = (24, 57, 220)
if email:
fn = draw_cert(staticfiles_storage.path(signed_path_pattern % certificate_number), email, 'Имя', 'Фамилия',
font_size=120, y=1000, color=color)
file = open(fn, 'rb')
try:
pass
send_email('Грамота от Lil School', email, 'notification/email/camp_certificate.html',
attachments=[(file.name, file.read(), 'image/jpeg')], certificate_number=certificate_number)
except:
pass
else:
print('Email has been sent')
finally:
file.close()
os.remove(fn)
return
date_end = date(now().year, 6 + certificate_number, 1) - timedelta(1)
users = set(list(DrawingCampPayment.objects.paid().filter(date_end=date_end).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(camp_certificate_last_email__date=date_end).values_list(
'user_id', flat=True).distinct()
for user_id in users:
if user_id in notified_users:
print('skip', user_id)
continue
un = user_notifications.get(user_id, UserNotification(user_id=user_id))
print(un.user.email)
if dry_run:
continue
if un.user.child_first_name:
fn = staticfiles_storage.path(signed_path_pattern % certificate_number)
fn = draw_cert(fn, un.user.email, un.user.child_first_name, un.user.child_last_name,
font_size=120, y=1000, color=color)
else:
fn = staticfiles_storage.path(path_pattern % certificate_number)
file = open(fn, 'rb')
try:
send_email('Грамота от Lil School', un.user.email, 'notification/email/camp_certificate.html',
attachments=[(file.name, file.read(), 'image/jpeg')], user_notification=un,
certificate_number=certificate_number)
except:
print('Not OK')
continue
finally:
file.close()
if un.user.child_first_name:
os.remove(fn)
un.camp_certificate_last_email = date_end
un.save()

@ -0,0 +1,25 @@
{% extends "notification/email/_base.html" %}
{% block content %}
<p style="margin: 0 0 20px">Привет!</p>
<div style="margin-bottom: 10px;">
{% if certificate_number == 1 %}
<p>
Поздравляем! Вы прошли месяц обучения в лагере Lil School.<br>
К письму прикреплена грамота. Распечатайте её и вручите вашим детям.<br>
Ждём вас в следующем месяце на наших творческих занятиях!
</p>
{% endif %}
{% if certificate_number == 2 %}
<p>
Вы помните, что каждый месяц вам приходит грамота за прекрасную учебу в рсиовальном лагере?<br>
Скачивайте. Распечатывайте. И соберите свою коллекцию!
</p>
{% endif %}
</div>
<div style="margin-bottom: 10px;">
<p>
Команда «Lil School».
</p>
</div>
{% endblock content %}

@ -267,6 +267,16 @@ CELERY_BEAT_SCHEDULE = {
'schedule': crontab(minute=0, hour=0),
'args': (),
},
'send_june_camp_certificates': {
'task': 'apps.notification.tasks.send_camp_certificates',
'schedule': crontab(0, 9, day_of_month='1', month_of_year='7'),
'kwargs': {'certificate_number': 2},
},
'send_jule_camp_certificates': {
'task': 'apps.notification.tasks.send_camp_certificates',
'schedule': crontab(0, 9, day_of_month='1', month_of_year='8'),
'kwargs': {'certificate_number': 2},
},
}
try:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

@ -20,6 +20,7 @@ module.exports = {
imagesCertificates: glob('./src/img/user-certificates/*'),
imagesSignedCertificates: glob('./src/img/signed-user-certificates/*'),
imagesGiftCertificates: glob('./src/img/gift-certificates/*'),
imagesCampCertificates: glob('./src/img/camp-certificates/*'),
imagesReviews: glob('./src/img/reviews/*'),
fonts: glob('./src/fonts/*'),
sounds: glob('./src/sounds/*'),
@ -93,7 +94,8 @@ module.exports = {
test: /\.(png|gif|jpg|svg)$/,
exclude: [path.resolve(__dirname, 'src/icons'), path.resolve(__dirname, 'src/img/user-certificates'),
path.resolve(__dirname, 'src/img/gift-certificates'), path.resolve(__dirname, 'src/img/reviews'),
path.resolve(__dirname, 'src/img/signed-user-certificates')],
path.resolve(__dirname, 'src/img/signed-user-certificates'), path.resolve(__dirname, 'src/img/camp-certificates'),
path.resolve(__dirname, 'src/img/signed-camp-certificates')],
loader: 'file-loader?name=[name].[ext]&outputPath=./img/'
},
{
@ -111,6 +113,16 @@ module.exports = {
include: path.resolve(__dirname, 'src/img/gift-certificates'),
loader: 'file-loader?name=[name].[ext]&outputPath=./img/gift-certificates/'
},
{
test: /\.(png|jpg)$/,
include: path.resolve(__dirname, 'src/img/camp-certificates'),
loader: 'file-loader?name=[name].[ext]&outputPath=./img/camp-certificates/'
},
{
test: /\.(png|jpg)$/,
include: path.resolve(__dirname, 'src/img/signed-camp-certificates'),
loader: 'file-loader?name=[name].[ext]&outputPath=./img/signed-camp-certificates/'
},
{
test: /\.(png|jpg)$/,
include: path.resolve(__dirname, 'src/img/reviews'),

Loading…
Cancel
Save