Skip to content

Commit 30e87b2

Browse files
authored
Merge branch 'dev' into main
2 parents 02ac716 + 427d195 commit 30e87b2

13 files changed

+392
-37
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Generated by Django 4.2.7 on 2025-02-27 17:27
2+
3+
from django.conf import settings
4+
from django.db import migrations, models
5+
import django.db.models.deletion
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('Mapapi', '0005_user_is_verified_user_otp_user_otp_expiration_and_more'),
12+
]
13+
14+
operations = [
15+
migrations.CreateModel(
16+
name='DiscussionMessage',
17+
fields=[
18+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19+
('message', models.TextField()),
20+
('created_at', models.DateTimeField(auto_now_add=True)),
21+
('collaboration', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='Mapapi.collaboration')),
22+
('incident', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='Mapapi.incident')),
23+
('sender', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
24+
],
25+
),
26+
]
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Generated by Django 4.2.7 on 2025-03-03 09:23
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('Mapapi', '0006_discussionmessage'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='Collaboration',
15+
name='motivation',
16+
field=models.TextField(blank=True, null=True),
17+
),
18+
migrations.AddField(
19+
model_name='Collaboration',
20+
name='other_option',
21+
field=models.CharField(blank=True, max_length=255, null=True),
22+
),
23+
migrations.AddField(
24+
model_name='Collaboration',
25+
name='status',
26+
field=models.CharField(max_length=20, default='pending'),
27+
),
28+
]
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Generated by Django 4.2.7 on 2025-03-03 11:21
2+
3+
from django.conf import settings
4+
from django.db import migrations, models
5+
import django.db.models.deletion
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('Mapapi', '0007_auto_20250303_0923'),
12+
]
13+
14+
operations = [
15+
migrations.AddField(
16+
model_name='discussionmessage',
17+
name='recipient',
18+
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='received_messages', to=settings.AUTH_USER_MODEL),
19+
),
20+
]
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Generated by Django 4.2.7 on 2025-03-03 11:43
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('Mapapi', '0008_discussionmessage_recipient'),
10+
]
11+
12+
operations = [
13+
migrations.AlterUniqueTogether(
14+
name='collaboration',
15+
unique_together={('incident', 'user')},
16+
),
17+
]
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Generated by Django 4.2.7 on 2025-05-09 17:03
2+
3+
from django.conf import settings
4+
from django.db import migrations, models
5+
import django.db.models.deletion
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('Mapapi', '0009_alter_collaboration_unique_together'),
12+
]
13+
14+
operations = [
15+
migrations.CreateModel(
16+
name='OrganisationTag',
17+
fields=[
18+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19+
('incident_type', models.CharField(max_length=255)),
20+
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='incident_preferences', to=settings.AUTH_USER_MODEL)),
21+
],
22+
),
23+
]

Mapapi/models.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ def generate_otp(self):
186186
self.save()
187187

188188
def send_verification_email(self):
189-
verification_link = f"mapactionapp://verify-email/{self.verification_token}"
189+
verification_link = f"https://api.map-action.com/MapApi/web_verify-email/{self.verification_token}"
190190
context = {"verification_link": verification_link}
191191
subject = "Vérification de votre compte"
192192
template_name = "emails/verification_email.html"
@@ -427,6 +427,8 @@ class Collaboration(models.Model):
427427
other_option = models.CharField(max_length=255, blank=True, null=True)
428428
status = models.CharField(max_length=20, default='pending')
429429

430+
class Meta:
431+
unique_together = (("incident", "user"),)
430432
def __str__(self):
431433
return f"Collaboration on {self.incident} by {self.user}"
432434

@@ -483,3 +485,18 @@ class UserAction(models.Model):
483485

484486
def __str__(self):
485487
return self.action
488+
489+
class DiscussionMessage(models.Model):
490+
incident = models.ForeignKey('Incident', on_delete=models.CASCADE)
491+
collaboration = models.ForeignKey(Collaboration, on_delete=models.CASCADE)
492+
sender = models.ForeignKey(User, on_delete=models.CASCADE)
493+
message = models.TextField()
494+
created_at = models.DateTimeField(auto_now_add=True)
495+
recipient = models.ForeignKey(User, on_delete=models.CASCADE, related_name="received_messages", null=True, blank=True)
496+
497+
def __str__(self):
498+
return f"Message de {self.sender} le {self.created_at}"
499+
500+
class OrganisationTag(models.Model):
501+
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='incident_preferences')
502+
incident_type = models.CharField(max_length=255)

Mapapi/serializer.py

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,20 @@
77
from django.utils import timezone
88

99

10-
class UserSerializer(ModelSerializer):
11-
class Meta:
12-
model = User
13-
exclude = (
14-
'user_permissions', 'is_superuser', 'is_active', 'is_staff')
15-
16-
def create(self, validated_data):
17-
zones = validated_data.pop('zones', None)
18-
user = self.Meta.model(**validated_data)
19-
user.set_password(validated_data['password'])
20-
user.save()
21-
if zones:
22-
user.zones.set(zones)
23-
return user
10+
# class UserSerializer(ModelSerializer):
11+
# class Meta:
12+
# model = User
13+
# exclude = (
14+
# 'user_permissions', 'is_superuser', 'is_active', 'is_staff')
15+
16+
# def create(self, validated_data):
17+
# zones = validated_data.pop('zones', None)
18+
# user = self.Meta.model(**validated_data)
19+
# user.set_password(validated_data['password'])
20+
# user.save()
21+
# if zones:
22+
# user.zones.set(zones)
23+
# return user
2424

2525

2626
class UserRegisterSerializer(serializers.ModelSerializer):
@@ -42,6 +42,36 @@ def create(self, validated_data):
4242
user.save()
4343
return user
4444

45+
46+
class UserSerializer(ModelSerializer):
47+
incident_preferences = serializers.ListField(
48+
child=serializers.CharField(),
49+
write_only=True,
50+
required=False
51+
)
52+
53+
class Meta:
54+
model = User
55+
exclude = ('user_permissions', 'is_superuser', 'is_active', 'is_staff')
56+
57+
def create(self, validated_data):
58+
zones = validated_data.pop('zones', None)
59+
incident_preferences = validated_data.pop('incident_preferences', [])
60+
61+
user = self.Meta.model(**validated_data)
62+
user.set_password(validated_data['password'])
63+
user.save()
64+
65+
if zones:
66+
user.zones.set(zones)
67+
68+
69+
if user.user_type == "elu" and incident_preferences:
70+
for incident_type in incident_preferences:
71+
OrganisationTag.objects.create(user=user, incident_type=incident_type)
72+
73+
return user
74+
4575

4676
class UserEluSerializer(serializers.ModelSerializer):
4777
class Meta:
@@ -287,3 +317,14 @@ class UserActionSerializer(serializers.ModelSerializer):
287317
class Meta:
288318
model = UserAction
289319
fields = '__all__'
320+
321+
322+
class DiscussionMessageSerializer(serializers.ModelSerializer):
323+
sender = UserSerializer(read_only=True)
324+
recipient = UserSerializer(read_only=True)
325+
class Meta:
326+
model = DiscussionMessage
327+
fields = ['id', 'incident', 'collaboration', 'sender', 'message', 'created_at','recipient']
328+
read_only_fields = ('sender', 'incident', 'collaboration','recipient')
329+
330+

Mapapi/signals.py

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from django.db.models.signals import post_save
22
from django.dispatch import receiver
3-
from .models import Collaboration, Notification
3+
from .models import Collaboration, Notification, User
44
from .Send_mails import send_email
55
import logging
66

@@ -46,4 +46,38 @@ def notify_organisation_on_collaboration(sender, instance, created, **kwargs):
4646
logger.error(f"Erreur lors de l'envoi de l'email: {str(e)}")
4747
else:
4848
logger.error(f"Email non valide ou manquant pour l'utilisateur {user}. Collaboration annulée.")
49-
instance.delete()
49+
instance.delete()
50+
51+
52+
def notify_organisations_on_prediction(sender, instance, created, **kwargs):
53+
if not created:
54+
return
55+
56+
incident_type = instance.incident_type
57+
58+
# Organisations intéressées par ce type d'incident
59+
matching_orgs = User.objects.filter(
60+
user_type="elu",
61+
incident_preferences__incident_type=incident_type
62+
).distinct()
63+
64+
for org in matching_orgs:
65+
try:
66+
context = {
67+
'incident_type': incident_type,
68+
'prediction_id': instance.id,
69+
'incident_id': instance.incident_id,
70+
'organisation': org.elu
71+
}
72+
73+
send_email.delay(
74+
subject=f"[MAP ACTION] Nouveau rapport : {incident_type}",
75+
template_name='emails/incident_notification.html',
76+
context=context,
77+
to_email=org.email
78+
)
79+
80+
logger.info(f"Email envoyé à {org.email} pour un nouvel incident de type {incident_type}.")
81+
82+
except Exception as e:
83+
logger.error(f"Erreur lors de l'envoi d'une notification à {org.email} : {str(e)}")

Mapapi/urls.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@
103103
path('decline/', DeclineCollaborationView.as_view(), name='decline-collaboration'),
104104
path('collaborations/accept/', AcceptCollaborationView.as_view(), name='accept-collaboration'),
105105
path('collaboration/<int:collaboration_id>/<str:action>/', HandleCollaborationRequestView.as_view(), name="handle_collaboration_request"),
106+
path('discussion/<int:incident_id>/', DiscussionMessageView.as_view(), name='discussion'),
107+
106108
# Search Incident
107109
path('Search/', IncidentSearchView.as_view(), name="search"),
108110
path('prediction/', PredictionView.as_view(), name="predicton"),

0 commit comments

Comments
 (0)