diff --git a/sigi/apps/eventos/admin.py b/sigi/apps/eventos/admin.py index 8e317be..8260e82 100644 --- a/sigi/apps/eventos/admin.py +++ b/sigi/apps/eventos/admin.py @@ -213,14 +213,18 @@ class EventoAdmin(CartExportMixin, admin.ModelAdmin): return "" def render_change_form(self, request, context, add, change, form_url, obj): + perm = request.user.has_perm("eventos.createcourse_evento") context.update( { - "can_createcourse": request.user.has_perm( - "eventos.createcourse_evento" - ) - and obj.moodle_courseid is None - and obj.tipo_evento.moodle_template_courseid is not None - and obj.tipo_evento.moodle_categoryid is not None + "can_createcourse": ( + perm + and obj.moodle_courseid is None + and obj.tipo_evento.moodle_template_courseid is not None + and obj.tipo_evento.moodle_categoryid is not None + ), + "can_updateparticipantes": ( + perm and obj.moodle_courseid is not None + ), } ) return super().render_change_form( @@ -237,31 +241,37 @@ class EventoAdmin(CartExportMixin, admin.ModelAdmin): def get_urls(self): urls = super().get_urls() + model_info = self.get_model_info() my_urls = [ path( "/declaracao/", self.admin_site.admin_view(self.declaracao_report), - name="%s_%s_declaracaoreport" % self.get_model_info(), + name="%s_%s_declaracaoreport" % model_info, ), path( "/gant/", self.admin_site.admin_view(self.gant_report), - name="%s_%s_gantreport" % self.get_model_info(), + name="%s_%s_gantreport" % model_info, ), path( "/checklist/", self.admin_site.admin_view(self.checklist_report), - name="%s_%s_checklistreport" % self.get_model_info(), + name="%s_%s_checklistreport" % model_info, ), path( "/comunicacao/", self.admin_site.admin_view(self.plano_comunicacao), - name="%s_%s_comunicacaoreport" % self.get_model_info(), + name="%s_%s_comunicacaoreport" % model_info, ), path( "/createcourse/", self.admin_site.admin_view(self.create_course), - name="%s_%s_createcourse" % self.get_model_info(), + name="%s_%s_createcourse" % model_info, + ), + path( + "/updateparticipantes/", + self.admin_site.admin_view(self.update_participantes), + name="%s_%s_updateparticipantes" % model_info, ), ] return my_urls + urls @@ -468,8 +478,8 @@ class EventoAdmin(CartExportMixin, admin.ModelAdmin): api_url = f"{settings.MOODLE_BASE_URL}/webservice/rest/server.php" mws = Moodle(api_url, settings.MOODLE_API_TOKEN) - fullname = f"{evento.nome} - {evento.turma}" - shortname = f"{evento.tipo_evento.nome} - {evento.turma}" + fullname = f"{evento.tipo_evento.nome} - {evento.municipio.nome}/{evento.municipio.uf.sigla} - {evento.tipo_evento.prefixo_turma}{evento.turma}" + shortname = f"{abreviatura(evento.tipo_evento.nome)} - {evento.tipo_evento.prefixo_turma}{evento.turma}" inicio = int(time.mktime(evento.data_inicio.astimezone().timetuple())) fim = int(time.mktime(evento.data_termino.astimezone().timetuple())) erros = [] @@ -542,3 +552,58 @@ class EventoAdmin(CartExportMixin, admin.ModelAdmin): return render( request, "admin/eventos/evento/createcourse.html", context ) + + def update_participantes(self, request, object_id): + evento = get_object_or_404(Evento, id=object_id) + change_url = ( + reverse( + "admin:%s_%s_change" % self.get_model_info(), args=[object_id] + ) + + "?" + + self.get_preserved_filters(request) + ) + if evento.moodle_courseid is None: + self.message_user( + request, + _("Este evento não tem curso associado no Saberes"), + level=messages.ERROR, + ) + return redirect(change_url) + + api_url = f"{settings.MOODLE_BASE_URL}/webservice/rest/server.php" + mws = Moodle(api_url, settings.MOODLE_API_TOKEN) + try: + inscritos = mws.post( + "core_enrol_get_enrolled_users", courseid=evento.moodle_courseid + ) + except Exception as e: + self.message_user( + request, + _( + "Ocorreu um erro ao acessar o curso no Saberes com " + f"a mensagem {e.message}" + ), + level=messages.ERROR, + ) + return redirect(change_url) + evento.total_participantes = len( + list( + filter( + lambda u: any( + r["roleid"] in settings.MOODLE_STUDENT_ROLES + for r in u["roles"] + ), + inscritos, + ) + ) + ) + evento.save() + self.message_user( + request, + _( + f"Foram encontrados {evento.total_participantes} alunos " + "no Saberes" + ), + level=messages.SUCCESS, + ) + return redirect(change_url) diff --git a/sigi/apps/eventos/migrations/0036_tipoevento_prefixo_turma_alter_evento_turma.py b/sigi/apps/eventos/migrations/0036_tipoevento_prefixo_turma_alter_evento_turma.py new file mode 100644 index 0000000..985ac61 --- /dev/null +++ b/sigi/apps/eventos/migrations/0036_tipoevento_prefixo_turma_alter_evento_turma.py @@ -0,0 +1,35 @@ +# Generated by Django 4.1.7 on 2023-05-09 13:00 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("eventos", "0035_alter_evento_options"), + ] + + operations = [ + migrations.AddField( + model_name="tipoevento", + name="prefixo_turma", + field=models.CharField( + blank=True, max_length=20, verbose_name="Prefixo para turmas" + ), + ), + migrations.AlterField( + model_name="evento", + name="turma", + field=models.CharField( + blank=True, + max_length=100, + validators=[ + django.core.validators.RegexValidator( + "^\\d{2}/\\d{4}$", + "Formato inválido. Utilize nn/aaaa, onde 'nn' são dígitos numéricos e 'aaaa' o ano com quatro dígitos.", + ) + ], + verbose_name="turma", + ), + ), + ] diff --git a/sigi/apps/eventos/models.py b/sigi/apps/eventos/models.py index 28c4bb1..1ef26be 100644 --- a/sigi/apps/eventos/models.py +++ b/sigi/apps/eventos/models.py @@ -1,5 +1,6 @@ import datetime import re +from django.core.validators import RegexValidator from django.db import models from django.db.models import Sum from django.urls import reverse @@ -49,6 +50,9 @@ class TipoEvento(models.Model): "Código da categoria no Saberes onde o curso deve ser criado." ), ) + prefixo_turma = models.CharField( + _("Prefixo para turmas"), max_length=20, blank=True + ) class Meta: ordering = ("nome",) @@ -86,7 +90,20 @@ class Evento(models.Model): on_delete=models.PROTECT, ) nome = models.CharField(_("Nome do evento"), max_length=100) - turma = models.CharField(_("turma"), max_length=100, blank=True) + turma = models.CharField( + _("turma"), + max_length=100, + blank=True, + validators=[ + RegexValidator( + "^\d{2}/\d{4}$", + _( + "Formato inválido. Utilize nn/aaaa, onde 'nn' são dígitos " + "numéricos e 'aaaa' o ano com quatro dígitos." + ), + ) + ], + ) descricao = models.TextField( _("Descrição do evento"), default=_( diff --git a/sigi/apps/eventos/templates/admin/eventos/evento/change_form.html b/sigi/apps/eventos/templates/admin/eventos/evento/change_form.html index 1a2a1e2..bcf9662 100644 --- a/sigi/apps/eventos/templates/admin/eventos/evento/change_form.html +++ b/sigi/apps/eventos/templates/admin/eventos/evento/change_form.html @@ -12,6 +12,15 @@ {% endif %} + {% if can_updateparticipantes %} +
  • + {% url opts|admin_urlname:'updateparticipantes' object_id|admin_urlquote as tool_url %} + + + {% trans "Atualizar total participantes" %} + +
  • + {% endif %}
  • {% url opts|admin_urlname:'declaracaoreport' object_id|admin_urlquote as tool_url %} diff --git a/sigi/settings.py b/sigi/settings.py index 223b86b..fca0147 100644 --- a/sigi/settings.py +++ b/sigi/settings.py @@ -266,3 +266,4 @@ REGISTRO_PATH = Path(env("REGISTRO_PATH", default="/tmp/DNS/")) MOODLE_BASE_URL = env("MOODLE_BASE_URL", default=None) MOODLE_API_TOKEN = env("MOODLE_API_TOKEN", default=None) +MOODLE_STUDENT_ROLES = env("MOODLE_STUDENT_ROLES", eval, default=(5, 9))