Commit c29f79e9 authored by Bruno Martin's avatar Bruno Martin
Browse files

welcome message feature

parent 6921a0cc
# Generated by Django 2.2.28 on 2022-06-11 00:12
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('courses', '0046_editorcontentfile'),
]
operations = [
migrations.AddField(
model_name='professormessage',
name='is_active_welcome',
field=models.BooleanField(default=False, verbose_name='Set this message as an active welcome message'),
),
migrations.AddField(
model_name='professormessage',
name='type',
field=models.CharField(choices=[('broadcast', 'Broadcast'), ('course', 'Course'), ('welcome', 'Welcome'), ('custom', 'Custom')], default='broadcast', max_length=64, verbose_name='Type'),
),
migrations.CreateModel(
name='MessageDelivery',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('delivery_date_time', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Delivery Date')),
('message', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='deliveries', to='courses.ProfessorMessage', verbose_name='ProfessorMessage')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Student')),
],
options={
'unique_together': {('user', 'message')},
},
),
]
......@@ -758,6 +758,13 @@ class ProfessorMessage(models.Model):
('published', _('Published')),
)
TYPES = (
('broadcast', _('Broadcast')),
('course', _('Course')),
('welcome', _('Welcome')),
('custom', _('Custom')), # message sent to specific users and/or groups
)
sender = models.ForeignKey(
settings.AUTH_USER_MODEL,
models.PROTECT,
......@@ -781,6 +788,10 @@ class ProfessorMessage(models.Model):
_("Broadcast message to all users"),
default=False,
)
is_active_welcome = models.BooleanField(
_("Set this message as an active welcome message"),
default=False,
)
subject = models.CharField(
_('Subject'),
max_length=255,
......@@ -829,6 +840,12 @@ class ProfessorMessage(models.Model):
default=STATES[0][0],
max_length=64,
)
type = models.CharField(
_('Type'),
choices=TYPES,
default=TYPES[0][0],
max_length=64,
)
release_date = models.DateTimeField(
_('Scheduled release date'),
null=True,
......@@ -854,69 +871,115 @@ class ProfessorMessage(models.Model):
def send(self):
if self.is_broadcast:
User = get_user_model()
self.users.set(User.objects.all())
# Set status as published
self.status = self.STATES[1][0]
# if the annoucement is not scheduled, save current time as release date
if not self.date:
self.date = timezone.now()
if self.is_active_welcome:
self.type = self.TYPES[2][0]
self.save()
else:
users_query = self.recipients.all()
if self.is_broadcast:
self.type = self.TYPES[0][0]
User = get_user_model()
self.users.set(User.objects.filter(is_active=True))
else:
if self.course or self.classes:
self.type = self.TYPES[1][0]
else:
self.type = self.TYPES[3][0]
for klass in self.classes.all():
users_query = users_query | klass.students.all()
users_query = self.recipients.all()
for group in self.groups.all():
users_query = users_query | group.user_set.all()
for klass in self.classes.all():
users_query = users_query | klass.students.all()
for classrooms in self.classrooms.all():
for group in classrooms.group.user_set.all():
for group in self.groups.all():
users_query = users_query | group.user_set.all()
self.users.set(users_query)
for classrooms in self.classrooms.all():
for group in classrooms.group.user_set.all():
users_query = users_query | group.user_set.all()
# Set status as published
self.status = self.STATES[1][0]
self.users.set(users_query)
# if the annoucement is not scheduled, save current time as release date
if not self.date:
self.date = timezone.now()
self.save()
self.save()
email_batch_size = settings.PROFESSOR_MESSAGE_CHUNK_SIZE
email_batch_size = settings.PROFESSOR_MESSAGE_CHUNK_SIZE
try:
et = EmailTemplate.objects.get(name='professor-message')
except EmailTemplate.DoesNotExist:
et = EmailTemplate(name="professor-message", subject="{{subject}}", template="{{message|safe}}")
if settings.I18N_SUPPORT:
bcc_es = [u.email for u in self.users.filter(preferred_language='es', is_active=True) if re.match(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", u.email)]
bcc_pt_br = [u.email for u in self.users.filter(preferred_language='pt-br', is_active=True) if u.is_active and re.match(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", u.email)]
bcc_en = [u.email for u in self.users.filter(preferred_language='en', is_active=True) if re.match(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", u.email)]
subject_es = self.subject_es or self.subject
message_es = self.message_es or self.message
subject_es = Template(et.subject).render(Context({'subject': subject_es}))
message_es = Template(et.template).render(Context({'message': message_es}))
self.send_emails(bcc_es, message_es, subject_es, email_batch_size)
subject_pt_br = self.subject_pt_br or self.subject
message_pt_br = self.message_pt_br or self.message
subject_pt_br = Template(et.subject).render(Context({'subject': subject_pt_br}))
message_pt_br = Template(et.template).render(Context({'message': message_pt_br}))
self.send_emails(bcc_pt_br, message_pt_br, subject_pt_br, email_batch_size)
subject_en = self.subject_en or self.subject
message_en = self.message_en or self.message
subject_en = Template(et.subject).render(Context({'subject': subject_en}))
message_en = Template(et.template).render(Context({'message': message_en}))
self.send_emails(bcc_en, message_en, subject_en, email_batch_size)
else:
bcc = [u.email for u in self.users.all() if u.is_active and re.match(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", u.email)]
subject = Template(et.subject).render(Context({'subject': self.subject}))
message = Template(et.template).render(Context({'message': self.message}))
self.send_emails(bcc, message, subject, email_batch_size)
try:
et = EmailTemplate.objects.get(name='professor-message')
except EmailTemplate.DoesNotExist:
et = EmailTemplate(name="professor-message", subject="{{subject}}", template="{{message|safe}}")
if settings.I18N_SUPPORT:
bcc_es = [u.email for u in self.users.filter(preferred_language='es', is_active=True) if re.match(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", u.email)]
bcc_pt_br = [u.email for u in self.users.filter(preferred_language='pt-br', is_active=True) if u.is_active and re.match(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", u.email)]
bcc_en = [u.email for u in self.users.filter(preferred_language='en', is_active=True) if re.match(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", u.email)]
subject_es = self.subject_es or self.subject
message_es = self.message_es or self.message
subject_es = Template(et.subject).render(Context({'subject': subject_es}))
message_es = Template(et.template).render(Context({'message': message_es}))
self.send_emails(bcc_es, message_es, subject_es, email_batch_size)
subject_pt_br = self.subject_pt_br or self.subject
message_pt_br = self.message_pt_br or self.message
subject_pt_br = Template(et.subject).render(Context({'subject': subject_pt_br}))
message_pt_br = Template(et.template).render(Context({'message': message_pt_br}))
self.send_emails(bcc_pt_br, message_pt_br, subject_pt_br, email_batch_size)
subject_en = self.subject_en or self.subject
message_en = self.message_en or self.message
subject_en = Template(et.subject).render(Context({'subject': subject_en}))
message_en = Template(et.template).render(Context({'message': message_en}))
self.send_emails(bcc_en, message_en, subject_en, email_batch_size)
else:
bcc = [u.email for u in self.users.filter(is_active=True) if re.match(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", u.email)]
subject = Template(et.subject).render(Context({'subject': self.subject}))
message = Template(et.template).render(Context({'message': self.message}))
self.send_emails(bcc, message, subject, email_batch_size)
return True
@staticmethod
def send_welcome_messagea(self, user):
for message in self.__class__.objects.filter(
status='published',
type='welcome',
is_active_welcome=True,
):
message.send_welcome_message(user)
def send_welcome_message(self, user):
self.users.add(user)
self.save()
MessageDelivery.objects.get_or_create(
user=user,
message=self,
)
# email the user
bcc = [user.email]
preferred_language = user.preferred_language.replace('-', '_')
subject = getattr(self, 'subject' + preferred_language) or self.subject
message = getattr(self, 'message' + preferred_language) or self.message
subject = Template(et.subject).render(Context({'subject': self.subject}))
message = Template(et.template).render(Context({'message': self.message}))
self.send_emails(
bcc,
message,
subject,
settings.PROFESSOR_MESSAGE_CHUNK_SIZE,
)
class ProfessorMessageRead(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
......@@ -938,6 +1001,30 @@ class ProfessorMessageRead(models.Model):
unique_together = ('user', 'message')
class MessageDelivery(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
models.CASCADE,
verbose_name=_('Student'),
)
message = models.ForeignKey(
ProfessorMessage,
models.CASCADE,
verbose_name=_('ProfessorMessage'),
related_name='deliveries',
)
delivery_date_time = models.DateTimeField(
_('Delivery Date'),
default=timezone.now,
)
def __str__(self):
return self.user.username + " " + self.message.subject + " " + str(self.delivery_date_time)
class Meta:
unique_together = ('user', 'message')
class PositionedModel(models.Model):
collection_name = 'pk'
......
......@@ -50,7 +50,7 @@ class IsAssistantOrCoordinatorOrAdminOrRecipient(permissions.BasePermission):
if (request.method in permissions.SAFE_METHODS):
if (request.user in obj.users.all() and obj.status=='published') or (request.user and request.user.is_superuser):
return True
elif obj.status=='published':
elif obj.status=='published' and obj.type!='welcome':
return False
elif request.user and request.user.is_superuser:
return True
......
......@@ -179,6 +179,8 @@ class MessageBasicSerializer(serializers.ModelSerializer):
'release_date',
'is_read',
'status',
'is_active_welcome',
'type',
)
def get_course_slug(self, obj):
......@@ -213,6 +215,8 @@ class MessageSerializer(MessageBasicSerializer):
'date', 'is_read', 'groups', 'classes', 'classrooms', 'status',
'release_date', 'is_broadcast', 'recipients',
'groups_obj', 'recipients_obj',
'is_active_welcome',
'type',
)
......
......@@ -187,7 +187,7 @@ class MessageMixin():
class MessageBasicViewSet(MessageMixin, viewsets.ReadOnlyModelViewSet):
model = ProfessorMessage
queryset = ProfessorMessage.objects.all()
filter_fields = ('course', 'classrooms', 'status')
filter_fields = ('course', 'classrooms', 'status', 'type',)
serializer_class = MessageBasicSerializer
permission_classes = (IsAssistantOrCoordinatorOrAdminOrRecipient, )
......@@ -207,7 +207,7 @@ class MessageBasicViewSet(MessageMixin, viewsets.ReadOnlyModelViewSet):
class MessageViewSet(MessageMixin, viewsets.ModelViewSet):
model = ProfessorMessage
queryset = ProfessorMessage.objects.all()
filter_fields = ('course', 'classrooms', 'status')
filter_fields = ('course', 'classrooms', 'status', 'type',)
serializer_class = MessageSerializer
permission_classes = (IsAssistantOrCoordinatorOrAdminOrRecipient, )
......@@ -250,6 +250,11 @@ class MessageViewSet(MessageMixin, viewsets.ModelViewSet):
{'error': 'This message was already sent before and connot be sent twice.'},
status=400,
)
if (user.is_superuser and message.is_active_welcome and message.type == 'welcome'):
message.send()
return Response({'sucess': 'Messsage defined as welcome message!'})
if not (message.is_broadcast or message.groups.exists() or message.recipients.exists() or message.classes.exists()):
return Response(
{'error': 'Cannot send a message with no recipient.'},
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment