diff --git a/oser_backend/settings/common.py b/oser_backend/settings/common.py index 84ccf8246385333d1cfbb3d32340090720319435..478aa5e2764bdef775cb33c2f28e3a9bd644b5a5 100644 --- a/oser_backend/settings/common.py +++ b/oser_backend/settings/common.py @@ -288,3 +288,12 @@ STATICFILES_DIRS = [ MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media') + +# Telegram bot +TELEGRAM_BOT_TOKEN = os.getenv( + "TELEGRAM_BOT_TOKEN") +TELEGRAM = { + 'bot_token': TELEGRAM_BOT_TOKEN, + 'channel_name': 'oserSECGEN', + 'production': False, +} diff --git a/profiles/admin.py b/profiles/admin.py index 9c8efa2682d35af70c7632185b155846828cbac4..b10721234b4fc81105f5a21c6e5bd76cf869d1ec 100644 --- a/profiles/admin.py +++ b/profiles/admin.py @@ -7,6 +7,8 @@ import codecs import csv from django.http import HttpResponse + + class ExportCsvMixin: def export_as_csv(self, request, queryset): @@ -14,13 +16,15 @@ class ExportCsvMixin: field_names = [field.name for field in meta.fields] response = HttpResponse(content_type='text/csv') - response['Content-Disposition'] = 'attachment; filename={}.csv'.format(meta) - response.write(codecs.BOM_UTF8) #force response to be UTF-8 + response['Content-Disposition'] = 'attachment; filename={}.csv'.format( + meta) + response.write(codecs.BOM_UTF8) # force response to be UTF-8 writer = csv.writer(response, delimiter=';') writer.writerow(field_names) for obj in queryset: - row = writer.writerow([getattr(obj, field) for field in field_names]) + row = writer.writerow([getattr(obj, field) + for field in field_names]) return response @@ -33,8 +37,9 @@ class ProfileAdminMixin: search_fields = ('user__email', 'user__first_name', 'user__last_name',) actions = ["export_as_csv"] + @admin.register(Tutor) -class TutorAdmin(ProfileAdminMixin, admin.ModelAdmin,ExportCsvMixin): +class TutorAdmin(ProfileAdminMixin, admin.ModelAdmin, ExportCsvMixin): """Tutor admin panel.""" autocomplete_fields = ('address',) @@ -45,9 +50,11 @@ class TutorAdmin(ProfileAdminMixin, admin.ModelAdmin,ExportCsvMixin): @admin.register(Student) -class StudentAdmin(ProfileAdminMixin, admin.ModelAdmin,ExportCsvMixin): +class StudentAdmin(ProfileAdminMixin, admin.ModelAdmin, ExportCsvMixin): """Student admin panel.""" - list_filter = (('school',MultiSelectFieldListFilter), 'year', 'registration__validated') + list_filter = (('school', MultiSelectFieldListFilter), + 'year', 'registration__validated') + class Meta: # noqa model = Student ordering = ['-updated_date'] diff --git a/profiles/models.py b/profiles/models.py index 4c9d912bbe6d1fb16a44290e0d73de85c898c5d1..39f392534f4ae0139a95d23da221eb6292e611aa 100644 --- a/profiles/models.py +++ b/profiles/models.py @@ -7,6 +7,10 @@ from .utils import get_promotion_range from datetime import datetime from .notifications import SendDocs +import telegram +from django.conf import settings +from django.template.loader import render_to_string + class ProfileMixin: """Mixin with common functionnality for profiles.""" @@ -57,35 +61,34 @@ class Student(ProfileMixin, models.Model): ) classType = models.CharField(max_length=50, - null=True, - blank=True, - verbose_name="général/techno", - ) + null=True, + blank=True, + verbose_name="général/techno", + ) nationality = models.CharField(max_length=50, - null=True, - blank=True, - verbose_name="nationalité", - ) + null=True, + blank=True, + verbose_name="nationalité", + ) specialTeaching = models.CharField(max_length=50, - null=True, - blank=True, - verbose_name="enseignement de spécialité", - ) + null=True, + blank=True, + verbose_name="enseignement de spécialité", + ) zipCode = models.CharField(max_length=10, - null=True, - blank=True, - verbose_name="code postal", - ) - + null=True, + blank=True, + verbose_name="code postal", + ) gender = models.CharField(max_length=20, - null=True, - blank=True, - verbose_name="genre", - ) + null=True, + blank=True, + verbose_name="genre", + ) addressNumber = models.IntegerField( null=True, @@ -94,77 +97,70 @@ class Student(ProfileMixin, models.Model): ) street = models.CharField(max_length=70, - null=True, - blank=True, - verbose_name="nom de rue" - ) + null=True, + blank=True, + verbose_name="nom de rue" + ) city = models.CharField(max_length=50, - null=True, - blank=True, - verbose_name="nom de ville" - ) + null=True, + blank=True, + verbose_name="nom de ville" + ) personalPhone = models.CharField(max_length=12, - null=True, - blank=True, - verbose_name="numéro de téléphone personnel" - ) + null=True, + blank=True, + verbose_name="numéro de téléphone personnel" + ) parentsPhone = models.CharField(max_length=12, - null=True, - blank=True, - verbose_name="numéro de téléphone parental" - ) + null=True, + blank=True, + verbose_name="numéro de téléphone parental" + ) parentsEmail = models.EmailField(max_length=70, - null=True, - blank=True, - verbose_name="adresse mail parentale" - ) - + null=True, + blank=True, + verbose_name="adresse mail parentale" + ) school = models.CharField(max_length=70, - null=True, - blank=True, - verbose_name="établissement" - ) - + null=True, + blank=True, + verbose_name="établissement" + ) grade = models.CharField(max_length=20, - null=True, - blank=True, - verbose_name="niveau de la classe" - ) - + null=True, + blank=True, + verbose_name="niveau de la classe" + ) scholarship = models.CharField(max_length=50, - null=True, - blank=True, - verbose_name="boursier" - ) - + null=True, + blank=True, + verbose_name="boursier" + ) fatherActivity = models.CharField(max_length=70, - null=True, - blank=True, - verbose_name="métier du père" - ) - + null=True, + blank=True, + verbose_name="métier du père" + ) motherActivity = models.CharField(max_length=70, - null=True, - blank=True, - verbose_name="métier de la mère" - ) - + null=True, + blank=True, + verbose_name="métier de la mère" + ) parentsStatus = models.CharField(max_length=70, - null=True, - blank=True, - verbose_name="statut des parents" - ) - + null=True, + blank=True, + verbose_name="statut des parents" + ) dependantsNumber = models.IntegerField( null=True, @@ -173,10 +169,10 @@ class Student(ProfileMixin, models.Model): ) year = models.CharField(max_length=10, - null=True, - blank=True, - verbose_name="année" - ) + null=True, + blank=True, + verbose_name="année" + ) @staticmethod def has_write_permission(request): @@ -187,16 +183,25 @@ class Student(ProfileMixin, models.Model): def save(self, *args, **kwargs): """Updates the year field based on the last modified date""" - if self.city != None: # Ne mettre à jour que quand les données personnelles sont remplies + if self.city != None: # Ne mettre à jour que quand les données personnelles sont remplies date_now = datetime.now() - if date_now.month>=9: + if date_now.month >= 9: self.year = f"{date_now.year}/{date_now.year+1}" else: self.year = f"{date_now.year-1}/{date_now.year}" - SendDocs(user=self.user).send() # send email with link to registration docs + # send email with link to registration docs + SendDocs(user=self.user).send() + + # send a telegram message to oserSECGEN + telegram_settings = settings.TELEGRAM + if telegram_settings['bot_token'] != None: + message_telegram = "Un tutoré a renseigné ses données personnelles, il attend ta validation !" + bot = telegram.Bot(token=telegram_settings['bot_token']) + bot.send_message( + chat_id="@%s" % telegram_settings['channel_name'], text=message_telegram, parse_mode=telegram.ParseMode.HTML) - return super(Student,self).save(*args, **kwargs) + return super(Student, self).save(*args, **kwargs) class Meta: # noqa verbose_name = 'lycéen' diff --git a/register/admin.py b/register/admin.py index 482cba4ff89eaf2663cc4fcad5925d681873ffca..95a4138df47b10c89c2dac2604b074f5fe30404a 100644 --- a/register/admin.py +++ b/register/admin.py @@ -5,25 +5,6 @@ from .models import Registration from profiles.models import Student -class SchoolFilter(admin.SimpleListFilter): - title = 'établissement' - parameter_name = 'profiles__school' - - def lookups(self, request, model_admin): - list_of_school = [] - query = Student.objects.values_list( - "school", flat=True).distinct() - for school in query: - list_of_school.append((school, school)) - return list_of_school - - def queryset(self, request, queryset): - if self.value(): - emails = Student.objects.filter( - school=self.value()).values_list("user__email", flat=True) - return queryset.filter(email__in=emails) - - class SchoolFilter(admin.SimpleListFilter): title = 'établissement' parameter_name = 'profiles__school' diff --git a/requirements.txt b/requirements.txt index 85baa939feb52944045b1648211bc371283a6767..e1b2a84ccd78237e50e13e6499d1edbb55278e6b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,6 +12,10 @@ django-sendgrid-v5 django-filter django-rest-auth +# Telegram messages via python-telegram-bot +tornado==5.1.1 +python-telegram-bot==12.2.0 + # Storage of files in AWS S3 django-storages boto3 diff --git a/visits/admin.py b/visits/admin.py index 7d49e11c710c84f56700e27fbdc1cb07e30b476b..6ca578ef60731b680f62f5abb7fff972ed1ac553 100644 --- a/visits/admin.py +++ b/visits/admin.py @@ -110,13 +110,11 @@ class ParticipationInline(admin.TabularInline): school = Student.objects.get(user = participation.user).school return school school.short_description = "Établissement" - def name(self, participation: Participation): """Returns the participation's user's name""" return participation.user.first_name + " " + participation.user.last_name name.short_description = "Nom" - class Media: css = { "all" : ("css/hide_admin_original.css",) } @@ -171,11 +169,10 @@ class ParticipationAdmin(admin.ModelAdmin): def school(self, participation: Participation): """Return a link to the participation's user's school.""" - school = Student.objects.get(user = participation.user).school + school = Student.objects.get(user=participation.user).school return school school.short_description = "Établissement" - def export_as_csv(self, request, queryset): meta = self.model._meta field_names = [field.name for field in meta.fields] @@ -205,8 +202,7 @@ class ParticipationAdmin(admin.ModelAdmin): export_as_csv.short_description = "Exporter sélection (en .csv)" - -@admin.register(Visit.organizers.through) +@ admin.register(Visit.organizers.through) class VisitOrganizersAdmin(admin.ModelAdmin): """Admin panel for visit organizers.""" @@ -220,7 +216,7 @@ class OrganizersInline(admin.TabularInline): extra = 0 -@admin.register(Visit) +@ admin.register(Visit) class VisitAdmin(admin.ModelAdmin): """Admin panel for visits.""" @@ -239,8 +235,7 @@ class VisitAdmin(admin.ModelAdmin): return obj.participants.count() num_participants.short_description = 'Participants' - -@admin.register(Place) +@ admin.register(Place) class PlaceAdmin(admin.ModelAdmin): """Admin panel for places."""