From 92bbc3e6933f4e3b1651c0420ec1b0c2f3c1ce25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pasternak?= Date: Mon, 24 Aug 2026 15:16:01 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20dodaj=20wydzia=C5=82y=20do=20raportu=20?= =?UTF-8?q?slot=C3=B3w=20ewaluacji?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...port-slotow-ewaluacja-wydzialy.feature.rst | 2 + src/raport_slotow/tables.py | 11 ++ src/raport_slotow/tests/test_upowaznienia.py | 9 +- .../test_raport_slotow_ewaluacja.py | 111 ++++++++++++++++++ src/raport_slotow/views/ewaluacja.py | 29 +++-- 5 files changed, 154 insertions(+), 8 deletions(-) create mode 100644 src/bpp/newsfragments/raport-slotow-ewaluacja-wydzialy.feature.rst diff --git a/src/bpp/newsfragments/raport-slotow-ewaluacja-wydzialy.feature.rst b/src/bpp/newsfragments/raport-slotow-ewaluacja-wydzialy.feature.rst new file mode 100644 index 000000000..1f38cafed --- /dev/null +++ b/src/bpp/newsfragments/raport-slotow-ewaluacja-wydzialy.feature.rst @@ -0,0 +1,2 @@ +Raport slotów - ewaluacja pokazuje aktualny i afiliowany wydział autora +w uczelniach korzystających ze struktury wydziałowej. diff --git a/src/raport_slotow/tables.py b/src/raport_slotow/tables.py index 26e7f86bb..d71d598b6 100644 --- a/src/raport_slotow/tables.py +++ b/src/raport_slotow/tables.py @@ -212,7 +212,9 @@ class Meta: "licencja_openaccess", "autor", "aktualna_jednostka", + "aktualny_wydzial", "afiliowana_jednostka", + "afiliowany_wydzial", "pbn_id", "orcid", "dyscyplina", @@ -238,8 +240,15 @@ class Meta: aktualna_jednostka = Column( "Aktualna jednostka", "autorzy__autor__aktualna_jednostka__nazwa" ) + aktualny_wydzial = Column( + "Aktualny wydział", + "autorzy__autor__aktualna_jednostka__wydzial__nazwa", + ) afiliowana_jednostka = Column("Afiliowana jednostka", "autorzy__jednostka__nazwa") + afiliowany_wydzial = Column( + "Afiliowany wydział", "autorzy__jednostka__wydzial__nazwa" + ) rok = Column("Rok", "rekord__rok", orderable=True) zrodlo_informacje = None # Column( @@ -374,5 +383,7 @@ class Meta: pbn_uid_id = Column("PBN UID ID", accessor="autor") + aktualny_wydzial = None + afiliowany_wydzial = None pkdaut = None slot = None diff --git a/src/raport_slotow/tests/test_upowaznienia.py b/src/raport_slotow/tests/test_upowaznienia.py index c0556d106..c937599d6 100644 --- a/src/raport_slotow/tests/test_upowaznienia.py +++ b/src/raport_slotow/tests/test_upowaznienia.py @@ -1,8 +1,15 @@ from django.urls import reverse +from bpp.models import Autor_Dyscyplina +from raport_slotow.tables import RaportEwaluacjaUpowaznieniaTable from raport_slotow.views.upowaznienie_pbn import RaportEwaluacjaUpowaznienia -from bpp.models import Autor_Dyscyplina + +def test_tabela_upowaznien_nie_dziedziczy_kolumn_wydzialow(): + column_names = RaportEwaluacjaUpowaznieniaTable([]).columns.names() + + assert "aktualny_wydzial" not in column_names + assert "afiliowany_wydzial" not in column_names def test_raport_ewaluacja_upowaznienia( diff --git a/src/raport_slotow/tests/test_views/test_raport_slotow_ewaluacja.py b/src/raport_slotow/tests/test_views/test_raport_slotow_ewaluacja.py index 258dc7afe..26d32eac9 100644 --- a/src/raport_slotow/tests/test_views/test_raport_slotow_ewaluacja.py +++ b/src/raport_slotow/tests/test_views/test_raport_slotow_ewaluacja.py @@ -1,9 +1,44 @@ +from io import BytesIO + import pytest from django.urls import reverse +from model_bakery import baker +from openpyxl import load_workbook +from bpp.models import Jednostka from raport_slotow.models import RaportUczelniaEwaluacjaView +def _ustaw_rozne_wydzialy(praca_z_dyscyplina, drugi_wydzial): + autorstwo = praca_z_dyscyplina.autorzy_set.select_related( + "autor", "jednostka__wydzial" + ).get() + + afiliowany_wydzial = autorstwo.jednostka.wydzial + afiliowany_wydzial.nazwa = "Wydział afiliowanej jednostki" + afiliowany_wydzial.save(update_fields=["nazwa"]) + + drugi_wydzial.nazwa = "Wydział aktualnej jednostki" + drugi_wydzial.save(update_fields=["nazwa"]) + aktualna_jednostka = baker.make( + Jednostka, + nazwa="Aktualna jednostka autora", + skrot="AJA", + uczelnia=drugi_wydzial.uczelnia, + parent=drugi_wydzial, + ) + aktualna_jednostka.refresh_from_db() + + autorstwo.autor.aktualna_jednostka = aktualna_jednostka + autorstwo.autor.save(update_fields=["aktualna_jednostka"]) + autorstwo.autor.refresh_from_db() + + assert autorstwo.autor.aktualna_jednostka_id == aktualna_jednostka.pk + assert aktualna_jednostka.wydzial_id == drugi_wydzial.pk + + return drugi_wydzial.nazwa, afiliowany_wydzial.nazwa + + def test_raport_slotow_ewaluacja_parametry_view(admin_client): res = admin_client.get(reverse("raport_slotow:index-ewaluacja")) assert res.status_code == 200 @@ -42,6 +77,82 @@ def test_raport_slotow_ewaluacja_raport_xlsx(admin_client, praca_z_dyscyplina): assert res.status_code == 200 +@pytest.mark.parametrize("uzywaj_wydzialow", [True, False]) +def test_raport_slotow_ewaluacja_wydzialy_html_zaleza_od_ustawienia_uczelni( + admin_client, + praca_z_dyscyplina, + uczelnia, + drugi_wydzial, + rok, + uzywaj_wydzialow, +): + aktualny_wydzial, afiliowany_wydzial = _ustaw_rozne_wydzialy( + praca_z_dyscyplina, drugi_wydzial + ) + uczelnia.uzywaj_wydzialow = uzywaj_wydzialow + uczelnia.save(update_fields=["uzywaj_wydzialow"]) + + res = admin_client.get( + reverse("raport_slotow:raport-ewaluacja"), + {"_export": "html", "od_roku": rok, "do_roku": rok}, + ) + + assert res.status_code == 200 + table = res.context["table"] + column_names = table.columns.names() + if uzywaj_wydzialow: + assert column_names.index("aktualny_wydzial") == ( + column_names.index("aktualna_jednostka") + 1 + ) + assert column_names.index("afiliowany_wydzial") == ( + column_names.index("afiliowana_jednostka") + 1 + ) + row = next(iter(table.rows)) + assert row.get_cell_value("aktualny_wydzial") == aktualny_wydzial + assert row.get_cell_value("afiliowany_wydzial") == afiliowany_wydzial + else: + assert "aktualny_wydzial" not in column_names + assert "afiliowany_wydzial" not in column_names + + +@pytest.mark.parametrize("uzywaj_wydzialow", [True, False]) +def test_raport_slotow_ewaluacja_wydzialy_xlsx_zaleza_od_ustawienia_uczelni( + admin_client, + praca_z_dyscyplina, + uczelnia, + drugi_wydzial, + rok, + uzywaj_wydzialow, +): + aktualny_wydzial, afiliowany_wydzial = _ustaw_rozne_wydzialy( + praca_z_dyscyplina, drugi_wydzial + ) + uczelnia.uzywaj_wydzialow = uzywaj_wydzialow + uczelnia.save(update_fields=["uzywaj_wydzialow"]) + + res = admin_client.get( + reverse("raport_slotow:raport-ewaluacja"), + {"_export": "xlsx", "od_roku": rok, "do_roku": rok}, + ) + + assert res.status_code == 200 + rows = list(load_workbook(BytesIO(res.content)).active.iter_rows(values_only=True)) + headers = next(row for row in rows if "Aktualna jednostka" in row) + values = {value for row in rows for value in row if value is not None} + if uzywaj_wydzialow: + assert headers.index("Aktualny wydział") == ( + headers.index("Aktualna jednostka") + 1 + ) + assert headers.index("Afiliowany wydział") == ( + headers.index("Afiliowana jednostka") + 1 + ) + assert aktualny_wydzial in values + assert afiliowany_wydzial in values + else: + assert "Aktualny wydział" not in headers + assert "Afiliowany wydział" not in headers + + @pytest.mark.django_db def test_RaportUczelniaEwaluacjaView_model(praca_z_dyscyplina): assert RaportUczelniaEwaluacjaView.objects.all().count() == 1 diff --git a/src/raport_slotow/views/ewaluacja.py b/src/raport_slotow/views/ewaluacja.py index 45bb8ca20..ebc8ec8ff 100644 --- a/src/raport_slotow/views/ewaluacja.py +++ b/src/raport_slotow/views/ewaluacja.py @@ -3,22 +3,21 @@ from django.http import HttpResponseRedirect from django.urls import reverse +from django.utils import timezone from django.views.generic import FormView from django_filters.views import FilterView from django_tables2 import SingleTableMixin - from formdefaults.helpers import FormDefaultsMixin + +from django_bpp.version import VERSION from nowe_raporty.views import BaseRaportAuthMixin from raport_slotow.filters import RaportSlotowUczelniaEwaluacjaFilter from raport_slotow.forms.ewaluacja import ParametryRaportSlotowEwaluacjaForm from raport_slotow.models import RaportUczelniaEwaluacjaView from raport_slotow.tables import RaportSlotowEwaluacjaTable +from raport_slotow.uczelnia_helper import uczelnia_dla_odczytu from raport_slotow.util import MyExportMixin -from django.utils import timezone - -from django_bpp.version import VERSION - class ParametryRaportSlotowEwaluacja( BaseRaportAuthMixin, @@ -57,6 +56,18 @@ class RaportSlotowEwaluacja( def get_form(self, dct): return ParametryRaportSlotowEwaluacjaForm(dct) + def get_table_kwargs(self): + kwargs = super().get_table_kwargs() + uczelnia = uczelnia_dla_odczytu(self.request) + if not (uczelnia and uczelnia.uzywaj_wydzialow): + exclude = tuple(kwargs.get("exclude", ())) + kwargs["exclude"] = ( + *exclude, + "aktualny_wydzial", + "afiliowany_wydzial", + ) + return kwargs + def get(self, request, *args, **kw): form = self.get_form(request.GET) @@ -103,12 +114,12 @@ def get_queryset(self): "autorzy__autor", "autorzy__dyscyplina_naukowa", "autorzy__autor__tytul", + "autorzy__autor__aktualna_jednostka__wydzial", + "autorzy__jednostka__wydzial", "autor_dyscyplina__dyscyplina_naukowa", "autor_dyscyplina__subdyscyplina_naukowa", ) .prefetch_related( - "autorzy__autor__aktualna_jednostka", - "autorzy__jednostka", "rekord__zrodlo__punktacja_zrodla_set", ) .only( @@ -148,8 +159,12 @@ def get_queryset(self): "autorzy__profil_orcid", "autorzy__jednostka_id", "autorzy__jednostka__nazwa", + "autorzy__jednostka__wydzial_id", + "autorzy__jednostka__wydzial__nazwa", "autorzy__autor__aktualna_jednostka_id", "autorzy__autor__aktualna_jednostka__nazwa", + "autorzy__autor__aktualna_jednostka__wydzial_id", + "autorzy__autor__aktualna_jednostka__wydzial__nazwa", "autor_dyscyplina__dyscyplina_naukowa", "autor_dyscyplina__dyscyplina_naukowa__id", "autor_dyscyplina__dyscyplina_naukowa__nazwa",