diff --git a/api/urls.py b/api/urls.py index 299d04a6..1289668f 100644 --- a/api/urls.py +++ b/api/urls.py @@ -48,5 +48,6 @@ urlpatterns = [ url(r'^', include(router.urls)), url(r'^login/', include('rest_framework.urls', namespace='rest_framework')), url(r'^markdown$', RenderMarkdown, name='api_markdown'), + url(r'^mailings$', FetchMailingLists, name='mailings_fetch') ] diff --git a/api/views/club.py b/api/views/club.py index fae04fc3..03b7f36c 100644 --- a/api/views/club.py +++ b/api/views/club.py @@ -22,9 +22,15 @@ # # +from rest_framework.response import Response from rest_framework import serializers +from rest_framework.decorators import api_view, renderer_classes +from rest_framework.renderers import StaticHTMLRenderer -from club.models import Club +from django.conf import settings +from django.core.exceptions import PermissionDenied + +from club.models import Club, Mailing from api.views import RightModelViewSet @@ -43,3 +49,15 @@ class ClubViewSet(RightModelViewSet): serializer_class = ClubSerializer queryset = Club.objects.all() + + +@api_view(['GET']) +@renderer_classes((StaticHTMLRenderer,)) +def FetchMailingLists(request): + key = request.GET.get('key', '') + if key != settings.SITH_MAILING_FETCH_KEY: + raise PermissionDenied + data = '' + for mailing in Mailing.objects.filter(is_moderated=True).all(): + data += mailing.fetch_format() + return Response(data) diff --git a/club/migrations/0009_auto_20170822_2232.py b/club/migrations/0009_auto_20170822_2232.py new file mode 100644 index 00000000..67fc9cf6 --- /dev/null +++ b/club/migrations/0009_auto_20170822_2232.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +from django.conf import settings +import re +import django.core.validators + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('club', '0008_auto_20170515_2214'), + ] + + operations = [ + migrations.CreateModel( + name='Mailing', + fields=[ + ('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)), + ('email', models.CharField(max_length=256, unique=True, validators=[django.core.validators.RegexValidator(re.compile('(^[-!#$%&\'*+/=?^_`{}|~0-9A-Z]+(\\.[-!#$%&\'*+/=?^_`{}|~0-9A-Z]+)*\\Z|^"([\\001-\\010\\013\\014\\016-\\037!#-\\[\\]-\\177]|\\\\[\\001-\\011\\013\\014\\016-\\177])*"\\Z)', 34), 'Enter a valid address. Only the root of the address is needed.')], verbose_name='Email address')), + ('is_moderated', models.BooleanField(default=False, verbose_name='is moderated')), + ('club', models.ForeignKey(verbose_name='Club', related_name='mailings', to='club.Club')), + ('moderator', models.ForeignKey(null=True, verbose_name='moderator', related_name='moderated_mailings', to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='MailingSubscription', + fields=[ + ('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)), + ('email', models.EmailField(max_length=254, verbose_name='Email address')), + ('mailing', models.ForeignKey(verbose_name='Mailing', related_name='subscriptions', to='club.Mailing')), + ('user', models.ForeignKey(null=True, verbose_name='User', related_name='mailing_subscriptions', blank=True, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.AlterUniqueTogether( + name='mailingsubscription', + unique_together=set([('user', 'email', 'mailing')]), + ), + ] diff --git a/club/models.py b/club/models.py index cbec4872..94b9ca97 100644 --- a/club/models.py +++ b/club/models.py @@ -2,6 +2,7 @@ # # Copyright 2016,2017 # - Skia +# - Sli # # Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM, # http://ae.utbm.fr. @@ -26,12 +27,13 @@ from django.db import models from django.core import validators from django.conf import settings from django.utils.translation import ugettext_lazy as _ -from django.core.exceptions import ValidationError +from django.core.exceptions import ValidationError, ObjectDoesNotExist from django.db import transaction from django.core.urlresolvers import reverse from django.utils import timezone +from django.core.validators import RegexValidator, validate_email -from core.models import User, MetaGroup, Group, SithFile +from core.models import User, MetaGroup, Group, SithFile, RealGroup, Notification # Create your models here. @@ -220,3 +222,99 @@ class Membership(models.Model): def get_absolute_url(self): return reverse('club:club_members', kwargs={'club_id': self.club.id}) + + +class Mailing(models.Model): + """ + This class correspond to a mailing list + Remember that mailing lists should be validated by UTBM + """ + club = models.ForeignKey(Club, verbose_name=_('Club'), related_name="mailings", null=False, blank=False) + email = models.CharField(_('Email address'), unique=True, null=False, blank=False, max_length=256, + validators=[ + RegexValidator(validate_email.user_regex, + _('Enter a valid address. Only the root of the address is needed.')) + ]) + is_moderated = models.BooleanField(_('is moderated'), default=False) + moderator = models.ForeignKey(User, related_name="moderated_mailings", verbose_name=_("moderator"), null=True) + + def clean(self): + if self.can_moderate(self.moderator): + self.is_moderated = True + else: + self.moderator = None + super(Mailing, self).clean() + + @property + def email_full(self): + return self.email + '@' + settings.SITH_MAILING_DOMAIN + + def can_moderate(self, user): + return user.is_root or user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) + + def is_owned_by(self, user): + return user.is_in_group(self) or user.is_root or user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) + + def can_view(self, user): + return self.club.has_rights_in_club(user) + + def delete(self): + for sub in self.subscriptions.all(): + sub.delete() + super(Mailing, self).delete() + + def fetch_format(self): + resp = self.email + ': ' + for sub in self.subscriptions.all(): + resp += sub.fetch_format() + return resp + + def save(self): + if not self.is_moderated: + for user in RealGroup.objects.filter(id=settings.SITH_GROUP_COM_ADMIN_ID).first().users.all(): + if not user.notifications.filter(type="MAILING_MODERATION", viewed=False).exists(): + Notification(user=user, url=reverse('com:mailing_admin'), type="MAILING_MODERATION").save() + super(Mailing, self).save() + + def __str__(self): + return "%s - %s" % (self.club, self.email_full) + + +class MailingSubscription(models.Model): + """ + This class makes the link between user and mailing list + """ + mailing = models.ForeignKey(Mailing, verbose_name=_('Mailing'), related_name="subscriptions", null=False, blank=False) + user = models.ForeignKey(User, verbose_name=_('User'), related_name="mailing_subscriptions", null=True, blank=True) + email = models.EmailField(_('Email address'), blank=False, null=False) + + class Meta: + unique_together = (('user', 'email', 'mailing'),) + + def clean(self): + if not self.user and not self.email: + raise ValidationError(_("At least user or email is required")) + try: + if self.user and not self.email: + self.email = self.user.email + if MailingSubscription.objects.filter(mailing=self.mailing, email=self.email).exists(): + raise ValidationError(_("This email is already suscribed in this mailing")) + except ObjectDoesNotExist: + pass + super(MailingSubscription, self).clean() + + def is_owned_by(self, user): + return self.mailing.club.has_rights_in_club(user) or user.is_root or self.user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) + + def can_be_edited_by(self, user): + return (user is not None and user.id == self.user.id) + + def fetch_format(self): + return self.email + ' ' + + def __str__(self): + if self.user: + user = str(self.user) + else: + user = _("Unregistered user") + return "(%s) - %s : %s" % (self.mailing, user, self.email) diff --git a/club/templates/club/mailing.jinja b/club/templates/club/mailing.jinja new file mode 100644 index 00000000..5ee67422 --- /dev/null +++ b/club/templates/club/mailing.jinja @@ -0,0 +1,60 @@ +{% extends "core/base.jinja" %} + +{% block title %} +{% trans %}Mailing lists{% endtrans %} +{% endblock %} + +{% block content %} + {% if has_objects %} + + {% trans %}Remember : mailing lists need to be moderated, if your new created list is not shown wait until moderation takes action{% endtrans %} + + {% for mailing in object_list %} + {% if mailing.is_moderated %} +

{% trans %}Mailing{% endtrans %} {{ mailing.email_full }} + {%- if user.is_owner(mailing) -%} + - {% trans %}Delete{% endtrans %} + {%- endif -%} +

+
+ + + + + + {% for subscriber in mailing.subscriptions.all() %} + + {% if subscriber.user %} + + {% else %} + + {% endif %} + + + + {% endfor %} +
{% trans %}User{% endtrans %}{% trans %}Email{%endtrans%}
{{ subscriber.user }}{% trans %}Unregistered user{% endtrans %}{{ subscriber.email }}{% trans %}Delete{% endtrans %}
+ {% endif %} + {% endfor %} + + {% else %} +

{% trans %}No mailing list existing for this club{% endtrans %}

+ {% endif %} + + {% if has_objects %} +

{% trans %}New member{% endtrans %}

+
+ {% csrf_token %} + {{ add_member.as_p() }} +

+
+ {% endif %} + +

{% trans %}New mailing{% endtrans %}

+
+ {% csrf_token %} + {{ add_mailing.as_p() }} +

+
+ +{% endblock %} diff --git a/club/urls.py b/club/urls.py index 95f7768e..96195b11 100644 --- a/club/urls.py +++ b/club/urls.py @@ -2,6 +2,7 @@ # # Copyright 2016,2017 # - Skia +# - Sli # # Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM, # http://ae.utbm.fr. @@ -38,5 +39,10 @@ urlpatterns = [ url(r'^(?P[0-9]+)/sellings/csv$', ClubSellingCSVView.as_view(), name='sellings_csv'), url(r'^(?P[0-9]+)/prop$', ClubEditPropView.as_view(), name='club_prop'), url(r'^(?P[0-9]+)/tools$', ClubToolsView.as_view(), name='tools'), + url(r'^(?P[0-9]+)/mailing$', ClubMailingView.as_view(action="display"), name='mailing'), + url(r'^(?P[0-9]+)/mailing/new/mailing$', ClubMailingView.as_view(action="add_mailing"), name='mailing_create'), + url(r'^(?P[0-9]+)/mailing/new/subscription$', ClubMailingView.as_view(action="add_member"), name='mailing_subscription_create'), + url(r'^(?P[0-9]+)/mailing/delete$', MailingDeleteView.as_view(), name='mailing_delete'), + url(r'^(?P[0-9]+)/mailing/delete/subscription$', MailingSubscriptionDeleteView.as_view(), name='mailing_subscription_delete'), url(r'^membership/(?P[0-9]+)/set_old$', MembershipSetOldView.as_view(), name='membership_set_old'), ] diff --git a/club/views.py b/club/views.py index e608d6ac..d2a32b01 100644 --- a/club/views.py +++ b/club/views.py @@ -2,6 +2,7 @@ # # Copyright 2016,2017 # - Skia +# - Sli # # Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM, # http://ae.utbm.fr. @@ -24,19 +25,63 @@ from django import forms from django.views.generic import ListView, DetailView, TemplateView +from django.views.generic.edit import DeleteView +from django.views.generic.detail import SingleObjectMixin from django.views.generic.edit import UpdateView, CreateView from django.http import HttpResponseRedirect, HttpResponse -from django.core.urlresolvers import reverse +from django.core.urlresolvers import reverse, reverse_lazy from django.utils import timezone from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext as _t from ajax_select.fields import AutoCompleteSelectField +from django.core.exceptions import PermissionDenied +from django.shortcuts import get_object_or_404 from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin from core.views.forms import SelectDate, SelectDateTime -from club.models import Club, Membership +from club.models import Club, Membership, Mailing, MailingSubscription from sith.settings import SITH_MAXIMUM_FREE_ROLE from counter.models import Selling, Counter +from core.models import User + +from django.conf import settings + +# Custom forms + + +class MailingForm(forms.ModelForm): + class Meta: + model = Mailing + fields = ('email', 'club', 'moderator') + + def __init__(self, *args, **kwargs): + club_id = kwargs.pop('club_id', None) + user_id = kwargs.pop('user_id', -1) # Remember 0 is treated as None + super(MailingForm, self).__init__(*args, **kwargs) + if club_id: + self.fields['club'].queryset = Club.objects.filter(id=club_id) + self.fields['club'].initial = club_id + self.fields['club'].widget = forms.HiddenInput() + if user_id >= 0: + self.fields['moderator'].queryset = User.objects.filter(id=user_id) + self.fields['moderator'].initial = user_id + self.fields['moderator'].widget = forms.HiddenInput() + + +class MailingSubscriptionForm(forms.ModelForm): + class Meta: + model = MailingSubscription + fields = ('mailing', 'user', 'email') + + def __init__(self, *args, **kwargs): + kwargs.pop('user_id', None) # For standart interface + club_id = kwargs.pop('club_id', None) + super(MailingSubscriptionForm, self).__init__(*args, **kwargs) + self.fields['email'].required = False + if club_id: + self.fields['mailing'].queryset = Mailing.objects.filter(club__id=club_id, is_moderated=True) + + user = AutoCompleteSelectField('users', label=_('User'), help_text=None, required=False) class ClubTabsMixin(TabedViewMixin): @@ -77,6 +122,11 @@ class ClubTabsMixin(TabedViewMixin): 'slug': 'sellings', 'name': _("Sellings"), }) + tab_list.append({ + 'url': reverse('club:mailing', kwargs={'club_id': self.object.id}), + 'slug': 'mailing', + 'name': _("Mailing list"), + }) if self.request.user.is_owner(self.object): tab_list.append({ 'url': reverse('club:club_prop', kwargs={'club_id': self.object.id}), @@ -338,3 +388,112 @@ class ClubStatView(TemplateView): kwargs = super(ClubStatView, self).get_context_data(**kwargs) kwargs['club_list'] = Club.objects.all() return kwargs + + +class ClubMailingView(ClubTabsMixin, ListView): + """ + A list of mailing for a given club + """ + action = None + model = Mailing + template_name = "club/mailing.jinja" + current_tab = 'mailing' + + def authorized(self): + return self.club.has_rights_in_club(self.user) or self.user.is_root or self.user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) + + def dispatch(self, request, *args, **kwargs): + self.club = get_object_or_404(Club, pk=kwargs['club_id']) + self.user = request.user + self.object = self.club + if not self.authorized(): + raise PermissionDenied + self.member_form = MailingSubscriptionForm(club_id=self.club.id) + self.mailing_form = MailingForm(club_id=self.club.id, user_id=self.user.id) + return super(ClubMailingView, self).dispatch(request, *args, **kwargs) + + def post(self, request, *args, **kwargs): + res = super(ClubMailingView, self).get(request, *args, **kwargs) + if self.action != "display": + if self.action == "add_mailing": + form = MailingForm + model = Mailing + elif self.action == "add_member": + form = MailingSubscriptionForm + model = MailingSubscription + return MailingGenericCreateView.as_view(model=model, list_view=self, form_class=form)(request, *args, **kwargs) + return res + + def get_queryset(self): + return Mailing.objects.filter(club_id=self.club.id).all() + + def get_context_data(self, **kwargs): + kwargs = super(ClubMailingView, self).get_context_data(**kwargs) + kwargs['add_member'] = self.member_form + kwargs['add_mailing'] = self.mailing_form + kwargs['club'] = self.club + kwargs['user'] = self.user + kwargs['has_objects'] = len(kwargs['object_list']) > 0 + return kwargs + + +class MailingGenericCreateView(CreateView, SingleObjectMixin): + """ + Create a new mailing list + """ + list_view = None + form_class = None + + def get_context_data(self, **kwargs): + view_kwargs = self.list_view.get_context_data(**kwargs) + for key, data in super(MailingGenericCreateView, self).get_context_data(**kwargs).items(): + view_kwargs[key] = data + view_kwargs[self.list_view.action] = view_kwargs['form'] + return view_kwargs + + def get_form_kwargs(self): + kwargs = super(MailingGenericCreateView, self).get_form_kwargs() + kwargs['club_id'] = self.list_view.club.id + kwargs['user_id'] = self.list_view.user.id + return kwargs + + def dispatch(self, request, *args, **kwargs): + if not self.list_view.authorized(): + raise PermissionDenied + self.template_name = self.list_view.template_name + return super(MailingGenericCreateView, self).dispatch(request, *args, **kwargs) + + def get_success_url(self, **kwargs): + return reverse_lazy('club:mailing', kwargs={'club_id': self.list_view.club.id}) + + +class MailingDeleteView(CanEditMixin, DeleteView): + + model = Mailing + template_name = 'core/delete_confirm.jinja' + pk_url_kwarg = "mailing_id" + redirect_page = None + + def dispatch(self, request, *args, **kwargs): + self.club_id = self.get_object().club.id + return super(MailingDeleteView, self).dispatch(request, *args, **kwargs) + + def get_success_url(self, **kwargs): + if self.redirect_page: + return reverse_lazy(self.redirect_page) + else: + return reverse_lazy('club:mailing', kwargs={'club_id': self.club_id}) + + +class MailingSubscriptionDeleteView(CanEditMixin, DeleteView): + + model = MailingSubscription + template_name = 'core/delete_confirm.jinja' + pk_url_kwarg = "mailing_subscription_id" + + def dispatch(self, request, *args, **kwargs): + self.club_id = self.get_object().mailing.club.id + return super(MailingSubscriptionDeleteView, self).dispatch(request, *args, **kwargs) + + def get_success_url(self, **kwargs): + return reverse_lazy('club:mailing', kwargs={'club_id': self.club_id}) diff --git a/com/templates/com/mailing_admin.jinja b/com/templates/com/mailing_admin.jinja new file mode 100644 index 00000000..75d098bc --- /dev/null +++ b/com/templates/com/mailing_admin.jinja @@ -0,0 +1,45 @@ +{% extends "core/base.jinja" %} + +{% block title %} +{% trans %}Mailing lists administration{% endtrans %} +{% endblock %} + +{% macro display_mailings(list) %} + + + + + + + {% for mailing in list %} + + + + + + {% endfor %} +
{% trans %}Email{% endtrans %}{% trans %}Club{%endtrans%}{% trans %}Actions{% endtrans %}
{{ mailing.email_full }}{{ mailing.club }} + {% trans %}Delete{% endtrans %} - {% if not mailing.is_moderated %}{% trans %}Moderate{% endtrans %}{% else %}{% trans user=mailing.moderator %}Moderated by {{ user }}{% endtrans %}{% endif %} +
+ +{% endmacro %} + +{% block content %} +

{% trans %}This page lists all mailing lists{% endtrans %}

+ + {% if has_unmoderated %} +

{% trans %}Not moderated mailing lists{% endtrans %}

+ {{ display_mailings(unmoderated) }} + {% endif %} + +

{% trans %}Moderated mailing lists{% endtrans %}

+ {% if has_moderated %} + {{ display_mailings(moderated) }} + {% else %} +

{% trans %}No mailing list existing{% endtrans %}

+ {% endif %} + +{% endblock %} + + + diff --git a/com/urls.py b/com/urls.py index 4daf16b1..f5421758 100644 --- a/com/urls.py +++ b/com/urls.py @@ -25,6 +25,7 @@ from django.conf.urls import url from com.views import * +from club.views import MailingDeleteView urlpatterns = [ url(r'^sith/edit/alert$', AlertMsgEditView.as_view(), name='alert_edit'), @@ -42,5 +43,8 @@ urlpatterns = [ url(r'^news/(?P[0-9]+)/moderate$', NewsModerateView.as_view(), name='news_moderate'), url(r'^news/(?P[0-9]+)/edit$', NewsEditView.as_view(), name='news_edit'), url(r'^news/(?P[0-9]+)$', NewsDetailView.as_view(), name='news_detail'), + url(r'^mailings$', MailingListAdminView.as_view(), name='mailing_admin'), + url(r'^mailings/(?P[0-9]+)/moderate$', MailingModerateView.as_view(), name='mailing_moderate'), + url(r'^mailings/(?P[0-9]+)/delete$', MailingDeleteView.as_view(redirect_page='com:mailing_admin'), name='mailing_delete'), ] diff --git a/com/views.py b/com/views.py index 8f675ef5..942ed335 100644 --- a/com/views.py +++ b/com/views.py @@ -2,6 +2,7 @@ # # Copyright 2016,2017 # - Skia +# - Sli # # Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM, # http://ae.utbm.fr. @@ -24,7 +25,7 @@ from django.shortcuts import redirect, get_object_or_404 from django.http import HttpResponseRedirect -from django.views.generic import ListView, DetailView +from django.views.generic import ListView, DetailView, View from django.views.generic.edit import UpdateView, CreateView, DeleteView from django.views.generic.detail import SingleObjectMixin from django.utils.translation import ugettext_lazy as _ @@ -34,6 +35,7 @@ from django.utils import timezone from django.conf import settings from django.db.models import Max from django.forms.models import modelform_factory +from django.core.exceptions import PermissionDenied from django import forms from datetime import timedelta @@ -42,7 +44,7 @@ from com.models import Sith, News, NewsDate, Weekmail, WeekmailArticle from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin, CanCreateMixin, QuickNotifMixin from core.views.forms import SelectDateTime from core.models import Notification, RealGroup -from club.models import Club +from club.models import Club, Mailing # Sith object @@ -81,6 +83,11 @@ class ComTabsMixin(TabedViewMixin): 'slug': 'alert', 'name': _("Alert message"), }) + tab_list.append({ + 'url': reverse('com:mailing_admin'), + 'slug': 'mailings', + 'name': _("Mailing lists administration"), + }) return tab_list @@ -414,3 +421,35 @@ class WeekmailArticleDeleteView(CanEditPropMixin, DeleteView): template_name = 'core/delete_confirm.jinja' success_url = reverse_lazy('com:weekmail') pk_url_kwarg = "article_id" + + +class MailingListAdminView(ComTabsMixin, ListView): + template_name = "com/mailing_admin.jinja" + model = Mailing + current_tab = "mailings" + + def dispatch(self, request, *args, **kwargs): + if not (request.user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) or request.user.is_root): + raise PermissionDenied + return super(MailingListAdminView, self).dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + kwargs = super(MailingListAdminView, self).get_context_data(**kwargs) + kwargs['moderated'] = self.get_queryset().filter(is_moderated=True).all() + kwargs['unmoderated'] = self.get_queryset().filter(is_moderated=False).all() + kwargs['has_moderated'] = len(kwargs['moderated']) > 0 + kwargs['has_unmoderated'] = len(kwargs['unmoderated']) > 0 + return kwargs + + +class MailingModerateView(View): + + def get(self, request, *args, **kwargs): + mailing = get_object_or_404(Mailing, pk=kwargs['mailing_id']) + if mailing.can_moderate(request.user): + mailing.is_moderated = True + mailing.moderator = request.user + mailing.save() + return redirect('com:mailing_admin') + + raise PermissionDenied diff --git a/core/migrations/0021_auto_20170822_1529.py b/core/migrations/0021_auto_20170822_1529.py new file mode 100644 index 00000000..b38e737d --- /dev/null +++ b/core/migrations/0021_auto_20170822_1529.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0020_auto_20170324_0917'), + ] + + operations = [ + migrations.AlterField( + model_name='notification', + name='type', + field=models.CharField(verbose_name='type', default='GENERIC', max_length=32, choices=[('MAILING_MODERATION', 'A new mailing list neet to be moderated'), ('NEWS_MODERATION', 'A fresh new to be moderated'), ('FILE_MODERATION', 'New files to be moderated'), ('SAS_MODERATION', 'New pictures/album to be moderated in the SAS'), ('NEW_PICTURES', "You've been identified on some pictures"), ('REFILLING', 'You just refilled of %s €'), ('SELLING', 'You just bought %s'), ('GENERIC', 'You have a notification')]), + ), + ] diff --git a/core/migrations/0022_auto_20170822_2232.py b/core/migrations/0022_auto_20170822_2232.py new file mode 100644 index 00000000..111ea439 --- /dev/null +++ b/core/migrations/0022_auto_20170822_2232.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0021_auto_20170822_1529'), + ] + + operations = [ + migrations.AlterField( + model_name='notification', + name='type', + field=models.CharField(choices=[('MAILING_MODERATION', 'A new mailing list needs to be moderated'), ('NEWS_MODERATION', 'A fresh new to be moderated'), ('FILE_MODERATION', 'New files to be moderated'), ('SAS_MODERATION', 'New pictures/album to be moderated in the SAS'), ('NEW_PICTURES', "You've been identified on some pictures"), ('REFILLING', 'You just refilled of %s €'), ('SELLING', 'You just bought %s'), ('GENERIC', 'You have a notification')], default='GENERIC', max_length=32, verbose_name='type'), + ), + ] diff --git a/core/templates/core/user_clubs.jinja b/core/templates/core/user_clubs.jinja index 0739c5e6..93cd0958 100644 --- a/core/templates/core/user_clubs.jinja +++ b/core/templates/core/user_clubs.jinja @@ -58,5 +58,12 @@ {% endfor %} + +{% if profile.mailing_subscriptions.exists() and (profile.id == user.id or user.is_root or self.user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID)) %} +

{% trans %}Subscribed mailing lists{% endtrans %}

+ {% for sub in profile.mailing_subscriptions.all() %} +

{{ sub.mailing.email }} {% trans %}Unsubscribe{% endtrans %}

+ {% endfor %} +{% endif %} {% endblock %} diff --git a/core/templates/core/user_tools.jinja b/core/templates/core/user_tools.jinja index 4033f702..699b52f4 100644 --- a/core/templates/core/user_tools.jinja +++ b/core/templates/core/user_tools.jinja @@ -87,6 +87,7 @@
  • {% trans %}Edit alert message{% endtrans %}
  • {% trans %}Edit information message{% endtrans %}
  • {% trans %}Moderate files{% endtrans %}
  • +
  • {% trans %}Mailing lists administration{% endtrans %}
  • {% endif %} {% if user.is_in_group(settings.SITH_GROUP_SAS_ADMIN_ID) %}
  • {% trans %}Moderate pictures{% endtrans %}
  • diff --git a/counter/migrations/0014_auto_20170817_1537.py b/counter/migrations/0014_auto_20170817_1537.py new file mode 100644 index 00000000..8e4e3df5 --- /dev/null +++ b/counter/migrations/0014_auto_20170817_1537.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('counter', '0013_customer_recorded_products'), + ] + + operations = [ + migrations.AlterField( + model_name='customer', + name='recorded_products', + field=models.IntegerField(verbose_name='recorded product', default=0), + ), + ] diff --git a/counter/migrations/0015_merge.py b/counter/migrations/0015_merge.py new file mode 100644 index 00000000..23830568 --- /dev/null +++ b/counter/migrations/0015_merge.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('counter', '0014_auto_20170817_1537'), + ('counter', '0014_auto_20170816_1521'), + ] + + operations = [ + ] diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index a20b12e0..6ccb516e 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-08-21 21:00+0200\n" +"POT-Creation-Date: 2017-08-22 22:36+0200\n" "PO-Revision-Date: 2016-07-18\n" "Last-Translator: Skia \n" "Language-Team: AE info \n" @@ -17,7 +17,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: accounting/models.py:61 accounting/models.py:110 accounting/models.py:138 -#: accounting/models.py:197 club/models.py:44 +#: accounting/models.py:197 club/models.py:46 #: core/templates/core/base.jinja:233 counter/models.py:113 #: counter/models.py:139 counter/models.py:183 forum/models.py:49 #: launderette/models.py:38 launderette/models.py:84 launderette/models.py:110 @@ -65,7 +65,7 @@ msgstr "IBAN" msgid "account number" msgstr "numero de compte" -#: accounting/models.py:113 accounting/models.py:139 club/models.py:187 +#: accounting/models.py:113 accounting/models.py:139 club/models.py:189 #: com/models.py:65 com/models.py:156 counter/models.py:148 #: counter/models.py:184 trombi/models.py:149 msgid "club" @@ -88,12 +88,12 @@ msgstr "Compte club" msgid "%(club_account)s on %(bank_account)s" msgstr "%(club_account)s sur %(bank_account)s" -#: accounting/models.py:195 club/models.py:188 counter/models.py:463 +#: accounting/models.py:195 club/models.py:190 counter/models.py:463 #: election/models.py:16 launderette/models.py:148 msgid "start date" msgstr "date de début" -#: accounting/models.py:196 club/models.py:189 counter/models.py:464 +#: accounting/models.py:196 club/models.py:191 counter/models.py:464 #: election/models.py:17 msgid "end date" msgstr "date de fin" @@ -172,8 +172,10 @@ msgstr "étiquette" msgid "target type" msgstr "type de cible" -#: accounting/models.py:271 club/templates/club/club_members.jinja:8 +#: accounting/models.py:271 club/models.py:288 +#: club/templates/club/club_members.jinja:8 #: club/templates/club/club_old_members.jinja:8 +#: club/templates/club/mailing.jinja:22 club/views.py:84 #: counter/templates/counter/cash_summary_list.jinja:32 #: counter/templates/counter/stats.jinja:15 #: counter/templates/counter/stats.jinja:52 @@ -182,7 +184,9 @@ msgstr "type de cible" msgid "User" msgstr "Utilisateur" -#: accounting/models.py:271 club/templates/club/club_detail.jinja:5 +#: accounting/models.py:271 club/models.py:232 +#: club/templates/club/club_detail.jinja:5 +#: com/templates/com/mailing_admin.jinja:11 #: com/templates/com/news_admin_list.jinja:21 #: com/templates/com/news_admin_list.jinja:50 #: com/templates/com/news_admin_list.jinja:81 @@ -339,8 +343,9 @@ msgstr "Compte en banque : " #: accounting/templates/accounting/club_account_details.jinja:59 #: accounting/templates/accounting/label_list.jinja:25 #: club/templates/club/club_sellings.jinja:50 -#: com/templates/com/weekmail.jinja:33 com/templates/com/weekmail.jinja:62 -#: core/templates/core/file_detail.jinja:25 +#: club/templates/club/mailing.jinja:16 club/templates/club/mailing.jinja:33 +#: com/templates/com/mailing_admin.jinja:19 com/templates/com/weekmail.jinja:33 +#: com/templates/com/weekmail.jinja:62 core/templates/core/file_detail.jinja:25 #: core/templates/core/file_detail.jinja:62 #: core/templates/core/file_moderation.jinja:24 #: core/templates/core/group_list.jinja:13 core/templates/core/macros.jinja:53 @@ -366,7 +371,7 @@ msgid "Delete" msgstr "Supprimer" #: accounting/templates/accounting/bank_account_details.jinja:17 -#: club/views.py:51 core/views/user.py:164 sas/templates/sas/picture.jinja:86 +#: club/views.py:96 core/views/user.py:164 sas/templates/sas/picture.jinja:86 msgid "Infos" msgstr "Infos" @@ -385,7 +390,7 @@ msgstr "Nouveau compte club" #: accounting/templates/accounting/bank_account_details.jinja:26 #: accounting/templates/accounting/bank_account_list.jinja:21 #: accounting/templates/accounting/club_account_details.jinja:57 -#: accounting/templates/accounting/journal_details.jinja:83 club/views.py:73 +#: accounting/templates/accounting/journal_details.jinja:83 club/views.py:118 #: com/templates/com/news_admin_list.jinja:37 #: com/templates/com/news_admin_list.jinja:64 #: com/templates/com/news_admin_list.jinja:109 @@ -502,6 +507,7 @@ msgstr "Fermé" #: accounting/templates/accounting/club_account_details.jinja:36 #: accounting/templates/accounting/journal_details.jinja:41 +#: com/templates/com/mailing_admin.jinja:12 #: com/templates/com/news_admin_list.jinja:24 #: com/templates/com/news_admin_list.jinja:52 #: com/templates/com/news_admin_list.jinja:85 @@ -850,11 +856,11 @@ msgstr "Opérations sans étiquette" msgid "Refound this account" msgstr "Rembourser ce compte" -#: club/models.py:46 +#: club/models.py:48 msgid "unix name" msgstr "nom unix" -#: club/models.py:50 +#: club/models.py:52 msgid "" "Enter a valid unix name. This value may contain only letters, numbers ./-/_ " "characters." @@ -862,56 +868,88 @@ msgstr "" "Entrez un nom UNIX valide. Cette valeur peut contenir uniquement des " "lettres, des nombres, et les caractères ./-/_" -#: club/models.py:55 +#: club/models.py:57 msgid "A club with that unix name already exists." msgstr "Un club avec ce nom UNIX existe déjà." -#: club/models.py:58 core/models.py:198 +#: club/models.py:60 core/models.py:198 msgid "address" msgstr "Adresse" -#: club/models.py:64 core/models.py:159 +#: club/models.py:66 core/models.py:159 msgid "home" msgstr "home" -#: club/models.py:76 +#: club/models.py:78 msgid "You can not make loops in clubs" msgstr "Vous ne pouvez pas faire de boucles dans les clubs" -#: club/models.py:90 +#: club/models.py:92 msgid "A club with that unix_name already exists" msgstr "Un club avec ce nom UNIX existe déjà." -#: club/models.py:186 counter/models.py:461 counter/models.py:479 +#: club/models.py:188 counter/models.py:461 counter/models.py:479 #: eboutic/models.py:38 eboutic/models.py:72 election/models.py:140 #: launderette/models.py:114 launderette/models.py:152 sas/models.py:158 #: trombi/models.py:148 msgid "user" msgstr "nom d'utilisateur" -#: club/models.py:190 core/models.py:178 election/models.py:139 +#: club/models.py:192 core/models.py:178 election/models.py:139 #: election/models.py:155 trombi/models.py:150 msgid "role" msgstr "rôle" -#: club/models.py:192 core/models.py:64 counter/models.py:114 +#: club/models.py:194 core/models.py:64 counter/models.py:114 #: counter/models.py:140 election/models.py:13 election/models.py:93 #: election/models.py:141 forum/models.py:50 forum/models.py:186 msgid "description" msgstr "description" -#: club/models.py:197 +#: club/models.py:199 msgid "User must be subscriber to take part to a club" msgstr "L'utilisateur doit être cotisant pour faire partie d'un club" -#: club/models.py:199 +#: club/models.py:201 msgid "User is already member of that club" msgstr "L'utilisateur est déjà membre de ce club" -#: club/models.py:203 +#: club/models.py:205 msgid "past member" msgstr "Anciens membres" +#: club/models.py:233 club/models.py:289 +msgid "Email address" +msgstr "Adresse email" + +#: club/models.py:236 +msgid "Enter a valid address. Only the root of the address is needed." +msgstr "Entrez une adresse valide. Seule la racine de l'adresse est nécessaire." + +#: club/models.py:238 com/models.py:67 core/models.py:629 +msgid "is moderated" +msgstr "est modéré" + +#: club/models.py:239 com/models.py:68 +msgid "moderator" +msgstr "modérateur" + +#: club/models.py:287 club/templates/club/mailing.jinja:14 +msgid "Mailing" +msgstr "Mailing" + +#: club/models.py:296 +msgid "At least user or email is required" +msgstr "Au moins un utilisateur ou un email est nécessaire" + +#: club/models.py:301 +msgid "This email is already suscribed in this mailing" +msgstr "Cet email est déjà abonné à cette mailing" + +#: club/models.py:319 club/templates/club/mailing.jinja:30 +msgid "Unregistered user" +msgstr "Désabonner un utilisateur" + #: club/templates/club/club_list.jinja:4 club/templates/club/club_list.jinja:24 msgid "Club list" msgstr "Liste des clubs" @@ -977,8 +1015,8 @@ msgstr "Du" msgid "To" msgstr "Au" -#: club/templates/club/club_sellings.jinja:5 club/views.py:78 club/views.py:251 -#: counter/templates/counter/counter_main.jinja:19 +#: club/templates/club/club_sellings.jinja:5 club/views.py:123 +#: club/views.py:301 counter/templates/counter/counter_main.jinja:19 #: counter/templates/counter/last_ops.jinja:35 msgid "Sellings" msgstr "Ventes" @@ -1004,7 +1042,7 @@ msgstr "unités" msgid "Benefit: " msgstr "Bénéfice : " -#: club/templates/club/club_sellings.jinja:21 club/views.py:199 +#: club/templates/club/club_sellings.jinja:21 club/views.py:249 #: core/templates/core/user_account_detail.jinja:18 #: core/templates/core/user_account_detail.jinja:51 #: counter/templates/counter/cash_summary_list.jinja:33 counter/views.py:134 @@ -1053,7 +1091,7 @@ msgid "Payment method" msgstr "Méthode de paiement" #: club/templates/club/club_tools.jinja:4 -#: core/templates/core/user_tools.jinja:98 +#: core/templates/core/user_tools.jinja:99 msgid "Club tools" msgstr "Outils club" @@ -1089,48 +1127,92 @@ msgstr "Comptabilité : " msgid "Manage launderettes" msgstr "Gestion des laveries" +#: club/templates/club/mailing.jinja:4 +msgid "Mailing lists" +msgstr "Mailing listes" + +#: club/templates/club/mailing.jinja:10 +msgid "" +"Remember : mailing lists need to be moderated, if your new created list is " +"not shown wait until moderation takes action" +msgstr "" +"Rappelez vous : les mailing listes doivent être modérées, si votre liste " +"nouvellement créee n'est pas affichée, attendez jusqu'à qu'un modérateur " +"entre en action" + +#: club/templates/club/mailing.jinja:23 +#: com/templates/com/mailing_admin.jinja:10 +msgid "Email" +msgstr "Email" + +#: club/templates/club/mailing.jinja:41 +msgid "No mailing list existing for this club" +msgstr "Aucune mailing liste n'existe pour ce club" + +#: club/templates/club/mailing.jinja:45 +msgid "New member" +msgstr "Nouveau membre" + +#: club/templates/club/mailing.jinja:49 +msgid "Add to mailing list" +msgstr "Ajouter à la mailing liste" + +#: club/templates/club/mailing.jinja:53 +msgid "New mailing" +msgstr "Nouvelle mailing liste" + +#: club/templates/club/mailing.jinja:57 +msgid "Create mailing list" +msgstr "Créer une mailing liste" + #: club/templates/club/stats.jinja:4 club/templates/club/stats.jinja.py:9 msgid "Club stats" msgstr "Statistiques du club" -#: club/views.py:57 +#: club/views.py:102 msgid "Members" msgstr "Membres" -#: club/views.py:62 +#: club/views.py:107 msgid "Old members" msgstr "Anciens membres" -#: club/views.py:68 core/templates/core/base.jinja:64 core/views/user.py:180 +#: club/views.py:113 core/templates/core/base.jinja:64 core/views/user.py:180 #: sas/templates/sas/picture.jinja:95 trombi/views.py:55 msgid "Tools" msgstr "Outils" -#: club/views.py:84 counter/templates/counter/counter_list.jinja:21 +#: club/views.py:128 +#, fuzzy +#| msgid "File list" +msgid "Mailing list" +msgstr "Liste des fichiers" + +#: club/views.py:134 counter/templates/counter/counter_list.jinja:21 #: counter/templates/counter/counter_list.jinja:42 #: counter/templates/counter/counter_list.jinja:57 msgid "Props" msgstr "Propriétés" -#: club/views.py:130 core/views/forms.py:253 counter/views.py:91 +#: club/views.py:180 core/views/forms.py:253 counter/views.py:91 #: trombi/views.py:124 msgid "Select user" msgstr "Choisir un utilisateur" -#: club/views.py:180 sas/views.py:104 sas/views.py:157 sas/views.py:232 +#: club/views.py:230 sas/views.py:104 sas/views.py:157 sas/views.py:232 msgid "You do not have the permission to do that" msgstr "Vous n'avez pas la permission de faire cela" -#: club/views.py:197 counter/views.py:1097 +#: club/views.py:247 counter/views.py:1097 msgid "Begin date" msgstr "Date de début" -#: club/views.py:198 com/views.py:130 counter/views.py:1098 +#: club/views.py:248 com/views.py:137 counter/views.py:1098 #: election/views.py:135 subscription/views.py:47 msgid "End date" msgstr "Date de fin" -#: club/views.py:213 core/templates/core/user_stats.jinja:27 +#: club/views.py:263 core/templates/core/user_stats.jinja:27 #: counter/views.py:1188 msgid "Product" msgstr "Produit" @@ -1191,14 +1273,6 @@ msgstr "type" msgid "author" msgstr "auteur" -#: com/models.py:67 core/models.py:629 -msgid "is moderated" -msgstr "est modéré" - -#: com/models.py:68 -msgid "moderator" -msgstr "modérateur" - #: com/models.py:93 msgid "news_date" msgstr "date de la nouvelle" @@ -1239,6 +1313,44 @@ msgstr "weekmail" msgid "rank" msgstr "rang" +#: com/templates/com/mailing_admin.jinja:4 com/views.py:89 +#: core/templates/core/user_tools.jinja:90 +msgid "Mailing lists administration" +msgstr "Administration des mailing listes" + +#: com/templates/com/mailing_admin.jinja:19 +#: com/templates/com/news_admin_list.jinja:65 +#: com/templates/com/news_admin_list.jinja:149 +#: com/templates/com/news_admin_list.jinja:221 +#: com/templates/com/news_admin_list.jinja:293 +#: com/templates/com/news_detail.jinja:26 +#: core/templates/core/file_detail.jinja:65 +#: core/templates/core/file_moderation.jinja:23 +#: sas/templates/sas/moderation.jinja:17 sas/templates/sas/picture.jinja:122 +msgid "Moderate" +msgstr "Modérer" + +#: com/templates/com/mailing_admin.jinja:19 +#, python-format +msgid "Moderated by %(user)s" +msgstr "Modéré par %(user)s" + +#: com/templates/com/mailing_admin.jinja:28 +msgid "This page lists all mailing lists" +msgstr "Cette page liste toutes les mailing listes" + +#: com/templates/com/mailing_admin.jinja:31 +msgid "Not moderated mailing lists" +msgstr "Mailing lists non modérées" + +#: com/templates/com/mailing_admin.jinja:35 +msgid "Moderated mailing lists" +msgstr "Modérer les mailing listes" + +#: com/templates/com/mailing_admin.jinja:39 +msgid "No mailing list existing" +msgstr "Aucune mailing list existante" + #: com/templates/com/news_admin_list.jinja:5 msgid "News admin" msgstr "Administration des nouvelles" @@ -1333,17 +1445,6 @@ msgstr "" msgid "Notices to moderate" msgstr "Nouvelles à modérer" -#: com/templates/com/news_admin_list.jinja:65 -#: com/templates/com/news_admin_list.jinja:149 -#: com/templates/com/news_admin_list.jinja:221 -#: com/templates/com/news_admin_list.jinja:293 -#: com/templates/com/news_detail.jinja:26 -#: core/templates/core/file_detail.jinja:65 -#: core/templates/core/file_moderation.jinja:23 -#: sas/templates/sas/moderation.jinja:17 sas/templates/sas/picture.jinja:122 -msgid "Moderate" -msgstr "Modérer" - #: com/templates/com/news_admin_list.jinja:72 #, fuzzy #| msgid "Weekly" @@ -1471,7 +1572,7 @@ msgid "Coming soon... don't miss!" msgstr "Prochainement... à ne pas rater!" #: com/templates/com/weekmail.jinja:5 com/templates/com/weekmail.jinja.py:9 -#: com/views.py:62 core/templates/core/user_tools.jinja:82 +#: com/views.py:64 core/templates/core/user_tools.jinja:82 msgid "Weekmail" msgstr "Weekmail" @@ -1558,55 +1659,55 @@ msgstr "Astuce" msgid "Final word" msgstr "Le mot de la fin" -#: com/views.py:55 +#: com/views.py:57 msgid "Communication administration" msgstr "Administration de la communication" -#: com/views.py:67 core/templates/core/user_tools.jinja:83 +#: com/views.py:69 core/templates/core/user_tools.jinja:83 msgid "Weekmail destinations" msgstr "Destinataires du Weekmail" -#: com/views.py:72 +#: com/views.py:74 msgid "Index page" msgstr "Page d'accueil" -#: com/views.py:77 +#: com/views.py:79 msgid "Info message" msgstr "Message d'info" -#: com/views.py:82 +#: com/views.py:84 msgid "Alert message" msgstr "Message d'alerte" -#: com/views.py:129 election/views.py:133 subscription/views.py:44 +#: com/views.py:136 election/views.py:133 subscription/views.py:44 msgid "Start date" msgstr "Date de début" -#: com/views.py:131 +#: com/views.py:138 msgid "Until" msgstr "Jusqu'à" -#: com/views.py:132 +#: com/views.py:139 msgid "Automoderation" msgstr "Automodération" -#: com/views.py:138 com/views.py:140 com/views.py:144 +#: com/views.py:145 com/views.py:147 com/views.py:151 msgid "This field is required." msgstr "Ce champ est obligatoire." -#: com/views.py:142 +#: com/views.py:149 msgid "You crazy? You can not finish an event before starting it." msgstr "T'es fou? Un événement ne peut pas finir avant même de commencer." -#: com/views.py:312 +#: com/views.py:319 msgid "Delete and save to regenerate" msgstr "Supprimer et sauver pour regénérer" -#: com/views.py:320 +#: com/views.py:327 msgid "Weekmail of the " msgstr "Weekmail du " -#: com/views.py:400 +#: com/views.py:407 msgid "" "You must be a board member of the selected club to post in the Weekmail." msgstr "" @@ -2642,6 +2743,14 @@ msgstr "Clubs actuels : " msgid "Old club(s) :" msgstr "Anciens clubs :" +#: core/templates/core/user_clubs.jinja:63 +msgid "Subscribed mailing lists" +msgstr "Mailing listes abonnées" + +#: core/templates/core/user_clubs.jinja:65 +msgid "Unsubscribe" +msgstr "Se désabonner" + #: core/templates/core/user_detail.jinja:5 #, python-format msgid "%(user_name)s's profile" @@ -2896,35 +3005,35 @@ msgstr "Éditer le message d'informations" msgid "Moderate files" msgstr "Modérer les fichiers" -#: core/templates/core/user_tools.jinja:92 +#: core/templates/core/user_tools.jinja:93 msgid "Moderate pictures" msgstr "Modérer les photos" -#: core/templates/core/user_tools.jinja:105 +#: core/templates/core/user_tools.jinja:106 msgid "Elections" msgstr "Élections" -#: core/templates/core/user_tools.jinja:107 +#: core/templates/core/user_tools.jinja:108 msgid "See available elections" msgstr "Voir les élections disponibles" -#: core/templates/core/user_tools.jinja:108 +#: core/templates/core/user_tools.jinja:109 msgid "See archived elections" msgstr "Voir les élections archivées" -#: core/templates/core/user_tools.jinja:110 +#: core/templates/core/user_tools.jinja:111 msgid "Create a new election" msgstr "Créer une nouvelle élection" -#: core/templates/core/user_tools.jinja:113 +#: core/templates/core/user_tools.jinja:114 msgid "Other tools" msgstr "Autres outils" -#: core/templates/core/user_tools.jinja:115 +#: core/templates/core/user_tools.jinja:116 msgid "Convert dokuwiki/BBcode syntax to Markdown" msgstr "Convertir de la syntaxe dokuwiki/BBcode vers Markdown" -#: core/templates/core/user_tools.jinja:116 +#: core/templates/core/user_tools.jinja:117 msgid "Trombi tools" msgstr "Outils Trombi" @@ -4088,11 +4197,11 @@ msgstr "Fusionner deux utilisateurs" msgid "Merge" msgstr "Fusion" -#: rootplace/views.py:90 +#: rootplace/views.py:91 msgid "User that will be kept" msgstr "Utilisateur qui sera conservé" -#: rootplace/views.py:91 +#: rootplace/views.py:92 msgid "User that will be deleted" msgstr "Utilisateur qui sera supprimé" @@ -4300,10 +4409,8 @@ msgid "Sbarro/ESTA member" msgstr "Membre de Sbarro ou de l'ESTA, 15 €" #: sith/settings.py:482 -#, fuzzy -#| msgid "One semester" msgid "One semester Welcome Week" -msgstr "Un semestre - Welcome Week" +msgstr "Un semestre - Welcome Week 0 €" #: sith/settings.py:504 msgid "President" @@ -4342,52 +4449,56 @@ msgid "Curious" msgstr "Curieux" #: sith/settings.py:546 +msgid "A new mailing list needs to be moderated" +msgstr "Une nouvelle mailing list a besoin d'être modérée" + +#: sith/settings.py:547 msgid "A fresh new to be moderated" msgstr "Une nouvelle toute neuve à modérer" -#: sith/settings.py:547 +#: sith/settings.py:548 msgid "New files to be moderated" msgstr "Nouveaux fichiers à modérer" -#: sith/settings.py:548 +#: sith/settings.py:549 msgid "New pictures/album to be moderated in the SAS" msgstr "Nouvelles photos/albums à modérer dans le SAS" -#: sith/settings.py:549 +#: sith/settings.py:550 msgid "You've been identified on some pictures" msgstr "Vous avez été identifié sur des photos" -#: sith/settings.py:550 +#: sith/settings.py:551 #, python-format msgid "You just refilled of %s €" msgstr "Vous avez rechargé votre compte de %s €" -#: sith/settings.py:551 +#: sith/settings.py:552 #, python-format msgid "You just bought %s" msgstr "Vous avez acheté %s" -#: sith/settings.py:552 +#: sith/settings.py:553 msgid "You have a notification" msgstr "Vous avez une notification" -#: sith/settings.py:556 +#: sith/settings.py:557 msgid "Success!" msgstr "Succès !" -#: sith/settings.py:557 +#: sith/settings.py:558 msgid "Fail!" msgstr "Échec !" -#: sith/settings.py:558 +#: sith/settings.py:559 msgid "You successfully posted an article in the Weekmail" msgstr "Article posté avec succès dans le Weekmail" -#: sith/settings.py:559 +#: sith/settings.py:560 msgid "You successfully edited an article in the Weekmail" msgstr "Article édité avec succès dans le Weekmail" -#: sith/settings.py:560 +#: sith/settings.py:561 msgid "You successfully sent the Weekmail" msgstr "Weekmail envoyé avec succès" diff --git a/migrate.py b/migrate.py index ad310a1a..ce1ad397 100644 --- a/migrate.py +++ b/migrate.py @@ -46,7 +46,7 @@ from django.core.files import File from core.models import User, SithFile from core.utils import doku_to_markdown, bbcode_to_markdown -from club.models import Club, Membership +from club.models import Club, Membership, Mailing, MailingSubscription from counter.models import Customer, Counter, Selling, Refilling, Product, ProductType, Permanency, Eticket from subscription.models import Subscription from eboutic.models import Invoice, InvoiceItem @@ -1332,6 +1332,49 @@ def migrate_forum(): print("Forum migrated at %s" % datetime.datetime.now()) print("Running time: %s" % (datetime.datetime.now()-start)) + +def migrate_mailings(): + cur = db.cursor(MySQLdb.cursors.SSDictCursor) + + print("Delete all mailings") + + Mailing.objects.all().delete() + + print("Migrating old mailing database") + + cur.execute(""" + SELECT * FROM mailing + """) + + moderator = User.objects.get(id=0) + + for mailing in cur: + club = Club.objects.filter(id=mailing['id_asso_parent']) + if club.exists(): + print(mailing) + club = club.first() + if mailing['nom']: + mailing['nom'] = '.' + mailing['nom'] + Mailing(id=mailing['id_mailing'], club=club, email=to_unicode(club.unix_name + mailing['nom']), + moderator=moderator, is_moderated=(mailing['is_valid'] > 0)).save() + print("-------------------") + + cur.execute(""" + SELECT * FROM mailing_membres + """) + + for mailing_sub in cur: + mailing = Mailing.objects.filter(id=mailing_sub['id_mailing']) + if mailing.exists(): + print(mailing_sub) + mailing = mailing.first() + if mailing_sub['id_user'] and User.objects.filter(id=mailing_sub['id_user']).exists(): + user = User.objects.get(id=mailing_sub['id_user']) + MailingSubscription(mailing=mailing, user=user, email=user.email).save() + elif mailing_sub['email']: + MailingSubscription(mailing=mailing, email=to_unicode(mailing_sub['email'])).save() + + def main(): print("Start at %s" % start) # Core @@ -1351,11 +1394,13 @@ def main(): # migrate_sas() # reset_index('core', 'sas') # reset_sas_moderators() - migrate_forum() - reset_index('forum') + # migrate_forum() + # reset_index('forum') + migrate_mailings() end = datetime.datetime.now() print("End at %s" % end) - print("Running time: %s" % (end-start)) + print("Running time: %s" % (end - start)) + if __name__ == "__main__": main() diff --git a/rootplace/views.py b/rootplace/views.py index 7a9cb64e..a03ab3ae 100644 --- a/rootplace/views.py +++ b/rootplace/views.py @@ -2,6 +2,7 @@ # # Copyright 2016,2017 # - Skia +# - Sli # # Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM, # http://ae.utbm.fr. @@ -22,7 +23,6 @@ # # -from django.shortcuts import render from django.utils.translation import ugettext as _ from django.views.generic.edit import FormView from django.core.urlresolvers import reverse @@ -31,10 +31,10 @@ from django.core.exceptions import PermissionDenied from ajax_select.fields import AutoCompleteSelectField -from core.views import CanViewMixin from core.models import User from counter.models import Customer + def merge_users(u1, u2): u1.nick_name = u1.nick_name or u2.nick_name u1.date_of_birth = u1.date_of_birth or u2.date_of_birth @@ -86,10 +86,12 @@ def merge_users(u1, u2): u2.delete() return u1 + class MergeForm(forms.Form): user1 = AutoCompleteSelectField('users', label=_("User that will be kept"), help_text=None, required=True) user2 = AutoCompleteSelectField('users', label=_("User that will be deleted"), help_text=None, required=True) + class MergeUsersView(FormView): template_name = "rootplace/merge.jinja" form_class = MergeForm @@ -106,4 +108,3 @@ class MergeUsersView(FormView): def get_success_url(self): return reverse('core:user_profile', kwargs={'user_id': self.final_user.id}) - diff --git a/sith/settings.py b/sith/settings.py index ff08d42d..abfed0ed 100644 --- a/sith/settings.py +++ b/sith/settings.py @@ -543,6 +543,7 @@ SITH_LAUNDERETTE_PRICES = { } SITH_NOTIFICATIONS = [ + ('MAILING_MODERATION', _("A new mailing list needs to be moderated")), ('NEWS_MODERATION', _("A fresh new to be moderated")), ('FILE_MODERATION', _("New files to be moderated")), ('SAS_MODERATION', _("New pictures/album to be moderated in the SAS")), @@ -560,6 +561,11 @@ SITH_QUICK_NOTIF = { 'qn_weekmail_send_success': _("You successfully sent the Weekmail"), } +# Mailing related settings + +SITH_MAILING_DOMAIN = 'utbm.fr' +SITH_MAILING_FETCH_KEY = 'IloveMails' + try: from .settings_custom import * print("Custom settings imported")