diff --git a/Mapapi/migrations/0010_organisationtag.py b/Mapapi/migrations/0010_organisationtag.py new file mode 100644 index 0000000..d653969 --- /dev/null +++ b/Mapapi/migrations/0010_organisationtag.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.7 on 2025-05-09 17:03 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('Mapapi', '0009_alter_collaboration_unique_together'), + ] + + operations = [ + migrations.CreateModel( + name='OrganisationTag', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('incident_type', models.CharField(max_length=255)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='incident_preferences', to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/Mapapi/models.py b/Mapapi/models.py index 591619a..d6ec800 100644 --- a/Mapapi/models.py +++ b/Mapapi/models.py @@ -165,7 +165,7 @@ def generate_otp(self): self.save() def send_verification_email(self): - verification_link = f"com.uwaish.MapActionApp://verify-email/{self.verification_token}" + verification_link = f"https://api.map-action.com/MapApi/web_verify-email/{self.verification_token}" context = {"verification_link": verification_link} subject = "Vérification de votre compte" template_name = "emails/verification_email.html" @@ -459,3 +459,7 @@ class DiscussionMessage(models.Model): def __str__(self): return f"Message de {self.sender} le {self.created_at}" + +class OrganisationTag(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='incident_preferences') + incident_type = models.CharField(max_length=255) diff --git a/Mapapi/serializer.py b/Mapapi/serializer.py index d4a0c81..36075de 100644 --- a/Mapapi/serializer.py +++ b/Mapapi/serializer.py @@ -22,23 +22,53 @@ def create(self, validated_data): return user -class UserRegisterSerializer(serializers.ModelSerializer): +# class UserRegisterSerializer(serializers.ModelSerializer): +# class Meta: +# model = User +# fields = '__all__' +# depth = 1 + +# def create(self, validated_data): +# user = User( +# email=validated_data['email'], +# first_name=validated_data['first_name'], +# last_name=validated_data['last_name'], +# phone=validated_data['phone'], +# is_active=True, +# address=validated_data['address'] +# ) +# user.set_password(validated_data['password']) +# user.save() +# return user + + +class UserSerializer(ModelSerializer): + incident_preferences = serializers.ListField( + child=serializers.CharField(), + write_only=True, + required=False + ) + class Meta: model = User - fields = '__all__' - depth = 1 + exclude = ('user_permissions', 'is_superuser', 'is_active', 'is_staff') def create(self, validated_data): - user = User( - email=validated_data['email'], - first_name=validated_data['first_name'], - last_name=validated_data['last_name'], - phone=validated_data['phone'], - is_active=True, - address=validated_data['address'] - ) + zones = validated_data.pop('zones', None) + incident_preferences = validated_data.pop('incident_preferences', []) + + user = self.Meta.model(**validated_data) user.set_password(validated_data['password']) user.save() + + if zones: + user.zones.set(zones) + + + if user.user_type == "elu" and incident_preferences: + for incident_type in incident_preferences: + OrganisationTag.objects.create(user=user, incident_type=incident_type) + return user diff --git a/Mapapi/signals.py b/Mapapi/signals.py index 50f55cc..f0afa01 100644 --- a/Mapapi/signals.py +++ b/Mapapi/signals.py @@ -1,6 +1,6 @@ from django.db.models.signals import post_save from django.dispatch import receiver -from .models import Collaboration, Notification +from .models import Collaboration, Notification, User from .Send_mails import send_email import logging @@ -46,4 +46,38 @@ def notify_organisation_on_collaboration(sender, instance, created, **kwargs): logger.error(f"Erreur lors de l'envoi de l'email: {str(e)}") else: logger.error(f"Email non valide ou manquant pour l'utilisateur {user}. Collaboration annulée.") - instance.delete() + instance.delete() + + +def notify_organisations_on_prediction(sender, instance, created, **kwargs): + if not created: + return + + incident_type = instance.incident_type + + # Organisations intéressées par ce type d'incident + matching_orgs = User.objects.filter( + user_type="elu", + incident_preferences__incident_type=incident_type + ).distinct() + + for org in matching_orgs: + try: + context = { + 'incident_type': incident_type, + 'prediction_id': instance.id, + 'incident_id': instance.incident_id, + 'organisation': org.elu + } + + send_email.delay( + subject=f"[MAP ACTION] Nouveau rapport : {incident_type}", + template_name='emails/incident_notification.html', + context=context, + to_email=org.email + ) + + logger.info(f"Email envoyé à {org.email} pour un nouvel incident de type {incident_type}.") + + except Exception as e: + logger.error(f"Erreur lors de l'envoi d'une notification à {org.email} : {str(e)}") diff --git a/Mapapi/views.py b/Mapapi/views.py index 337d471..a6aeac3 100644 --- a/Mapapi/views.py +++ b/Mapapi/views.py @@ -8,7 +8,7 @@ from rest_framework.decorators import api_view, permission_classes, authentication_classes from .serializer import * from django.middleware.csrf import get_token -from django.http import JsonResponse +from django.http import JsonResponse, HttpResponse from rest_framework.pagination import PageNumberPagination from rest_framework import status from rest_framework.permissions import AllowAny, IsAuthenticated @@ -22,6 +22,7 @@ from django.conf import settings from django.db import IntegrityError from backend.settings import * +from django.views import View import json import datetime # import requests @@ -44,6 +45,13 @@ import logging from django.utils import timezone from datetime import timedelta +from django.views.decorators.csrf import csrf_exempt +from django.utils.decorators import method_decorator +import random +import string + +def get_random(length=6): + return ''.join(random.choices(string.digits, k=length)) logger = logging.getLogger(__name__) @@ -370,10 +378,10 @@ def post(self, request, format=None): longitude = serializer.data.get("longitude") latitude = serializer.data.get("lattitude") print("Longitude:", longitude) - incident_instance = Incident.objects.get(longitude=longitude) - incident_id = incident_instance.id + # incident_instance = Incident.objects.get(longitude=longitude) + # incident_id = incident_instance.id - print(incident_id) + # print(incident_id) @@ -1589,7 +1597,7 @@ def get(self, request, id, format=None, **kwargs): "data": listData }, status=status.HTTP_200_OK) - +@method_decorator(csrf_exempt, name='dispatch') class PasswordResetView(generics.CreateAPIView): """ use postman to test give 4 fields new_password new_password_confirm email code post methode""" permission_classes = ( @@ -1597,9 +1605,8 @@ class PasswordResetView(generics.CreateAPIView): ) queryset = User.objects.all() serializer_class = ResetPasswordSerializer - def post(self, request, *args, **kwargs): - + print("✅ post() de PasswordResetView appelée") if 'code' not in request.data or request.data['code'] is None: return Response({ "status": "failure", @@ -1685,7 +1692,9 @@ def post(self, request, *args, **kwargs): user=user_, code=code_ ) - subject, from_email, to = '[MAP ACTION] - Votre code de reinitialisation', settings.EMAIL_HOST_USER, user_.email + subject = '[MAP ACTION] - Votre code de réinitialisation' + from_email = 'Map Action <{}>'.format(settings.EMAIL_HOST_USER) + to = user_.email html_content = render_to_string('mail_pwd.html', {'code': code_}) # render with dynamic value# text_content = strip_tags(html_content) # Strip the html tag. So people can see the pure text at least. msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) @@ -2452,3 +2461,25 @@ def perform_create(self, serializer): recipient=recipient ) +class RedirectToAppView(View): + def get(self, request, token): + deep_link_url = f"com.uwaish.MapActionApp://verify-email/{token}" + html = f""" + + +
+Redirection vers l'application en cours...
+ + + """ + return HttpResponse(html) diff --git a/template/emails/incident_notification.html b/template/emails/incident_notification.html new file mode 100644 index 0000000..ec08556 --- /dev/null +++ b/template/emails/incident_notification.html @@ -0,0 +1,68 @@ + + + + +Bonjour, {{ organisation }}
+ +Un nouvel incident de type {{ incident_type }} a été reporté sur la plateforme MAP ACTION.
+ +👉 Nous vous recommandons de consulter la plateforme pour voir plus de détails et prendre les mesures nécessaires.
+ + Consulter l'incident + + +