feat(nowe_raporty): wybór sortowania raportu — wg nazwisk autorów (FD467) - #773
Open
mpasternak wants to merge 2 commits into
Open
feat(nowe_raporty): wybór sortowania raportu — wg nazwisk autorów (FD467)#773mpasternak wants to merge 2 commits into
mpasternak wants to merge 2 commits into
Conversation
mpasternak
marked this pull request as ready for review
August 18, 2026 22:25
mpasternak
force-pushed
the
feat/fd467-sortowanie-po-autorach
branch
from
August 18, 2026 22:27
37085d7 to
0b484f4
Compare
…467) Zgłoszenie FD467 (Biblioteka Naukowa IHiT) prosi o wydruk z BPP w formie, w jakiej spis wchodzi do sprawozdania rocznego: uporządkowany alfabetycznie wg nazwisk autorów. Dziś kolejność wierszy jest własnością tabeli flexible_reports (inline ColumnOrder: rok malejąco, potem opis), a więc stałą zapisaną w bazie i wspólną dla wszystkich czterech raportów — jedna tabela obsługuje 4 raporty x 12 sekcji. Formularz raportu dostaje pole "Sortowanie" z dwoma wariantami: dotychczasowy (domyślny, bez zmian) i alfabetyczny wg nazwisk. Wybór jedzie querystringiem tak samo jak _export, więc obejmuje też eksport do DOCX/XLSX, a widok generujący przekłada go na Report.set_order_by() — hook nadpisujący ColumnOrder na jeden render, bez ruszania definicji w bazie. Sortujemy po opis_bibliograficzny_autorzy_cache: to ArrayField ["Nazwisko Imiona", ...] w kolejności autorstwa, a PostgreSQL porównuje tablice element po elemencie, więc wychodzi porządek wg nazwiska PIERWSZEGO autora (z kolejnymi jako rozstrzygnięciem remisu) — dokładnie to, o co prosi zgłoszenie. To jedyne miejsce, w którym "nazwisko pierwszego autora" jest sortowalnym skalarem: przez relację autorzy__autor__nazwisko sortować się nie da, bo JOIN po relacji wielowartościowej zduplikowałby wiersze (a Column.clean() i tak odrzuca taką ścieżkę w dot-notation). Test test_rekord_sortuje_sie_po_nazwisku_pierwszego_autora pilnuje tego założenia o bazie, bo cała funkcja na nim stoi. Warianty i mapowanie na pola ORM siedzą w osobnym module sortowanie.py, na wzór poziomy.py — formularz bierze stamtąd etykiety, widok pola ORM. Gdyby były osobno, formularz mógłby oferować wariant, którego widok nie zna, a raport po prostu wychodziłby posortowany domyślnie. Przy okazji: POLA_ZAAWANSOWANE -> POLA_PRZEKAZYWANE. Lista steruje wyłącznie przekazywaniem do querystringu (o wyglądzie decyduje Layout), a po dodaniu "sortowania", które w układzie stoi w głównym fieldsecie obok formatu wyjściowego, dawna nazwa sugerowałaby nieistniejący związek z sekcją "Opcje zaawansowane". Domyślnej wartości pola nie trzeba nigdzie modelować: RaportFormView stoi na FormDefaultsMixin, a form_class_dla() buduje klasę o stabilnej nazwie per slug raportu, więc redaktor ustawia default per instalacja i per raport z panelu domyślnych wartości formularzy. UWAGA: wymaga django-flexible-reports >= 0.5.0 (Report.set_order_by, mpasternak/django-flexible-reports#14). Bump w pyproject.toml + uv lock dokładam osobnym commitem po wydaniu pakietu — dziś lockfile nie ma czego zrezolwować. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WSUsgzYoDNnXpXGAn5otJg
Wybór sortowania raportu stoi na Report.set_order_by(), który wchodzi dopiero w 0.5.0 (mpasternak/django-flexible-reports#14). Bez tego pinu instalacja z 0.4.2 wywalałaby się na AttributeError przy każdym raporcie generowanym z wariantem "wg nazwisk autorów". Bump siedzi w osobnym commicie, bo w chwili pisania funkcji pakiet nie był jeszcze wydany i `uv lock` nie miał czego zrezolwować. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WSUsgzYoDNnXpXGAn5otJg
mpasternak
force-pushed
the
feat/fd467-sortowanie-po-autorach
branch
from
August 19, 2026 12:37
0b484f4 to
e59c976
Compare
Member
Author
|
Zrebase'owany na CI: 24/24 zielone — 12/12 shardów, |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Zgłoszenie
FD467, Biblioteka Naukowa IHiT (Anna Wołodko). Klientka przysłała
Publikacje.docx— spis w formie, w jakiej wchodzi do sprawozdania rocznego — i prosi, żeby dało się taki wydruk zrobić z BPP. Kluczowe zdanie: „spis powinien być uporządkowany wg nazwisk autorów".Załącznik to płaska, numerowana lista alfabetyczna wg pierwszego autora (Antoniewicz-Papis → Beauverd → Budziszewska → Carcao → Cardona-Benavides → Cesaro…). To istotne: nie chodzi o sekcje per-autor, tylko o porządek wierszy.
Dlaczego to nie było możliwe
Kolejność wierszy jest własnością tabeli
flexible_reports.Table— inlineColumnOrder(rok malejąco, potem opis), czytany w adapterze i wstawiany doMeta.order_by. Czyli stała zapisana w bazie, w dodatku wspólna dla wszystkich raportów:seeding/__init__.pytworzy jeden obiektTableobsługujący 4 raporty × 12 sekcji. Przestawienie go zmieniłoby sortowanie wszystkim.Rozwiązanie
Pole „Sortowanie" w formularzu raportu, obok „Formatu wyjściowego":
Wybór jedzie querystringiem tak samo jak
_export, więc obejmuje również eksport do DOCX/XLSX. Widok przekłada go naReport.set_order_by()— hook nadpisującyColumnOrderna jeden render, bez dotykania definicji w bazie.Sedno: po czym właściwie sortujemy
Po
Rekord.opis_bibliograficzny_autorzy_cache—ArrayField["Nazwisko Imiona", ...]w kolejności autorstwa. PostgreSQL porównuje tablice element po elemencie, więc wychodzi porządek wg nazwiska pierwszego autora, z kolejnymi autorami jako rozstrzygnięciem remisu. Dokładnie to, o co prosi zgłoszenie.To jedyne miejsce, w którym „nazwisko pierwszego autora" jest sortowalnym skalarem. Przez relację (
autorzy__autor__nazwisko) sortować się nie da: JOIN po relacji wielowartościowej zduplikowałby wiersze, aColumn.clean()i tak odrzuca taką ścieżkę w dot-notation. Pole denormalizowane dla opisu bibliograficznego okazuje się przypadkiem jedynym wyjściem.Bo to założenie o bazie, a nie o naszym kodzie, ma własny test —
test_rekord_sortuje_sie_po_nazwisku_pierwszego_autora. Cała funkcja na nim stoi.tytul_oryginalny_sortjako trzeci klucz nie jest ozdobą: bez niego dwie prace tego samego autora z tego samego roku mają kolejność niezdeterminowaną, więc ten sam raport wygenerowany dwa razy potrafiłby się różnić.Nowy moduł
sortowanie.pyWarianty (etykiety dla formularza) i mapowanie na pola ORM (dla widoku) w jednym miejscu, na wzór
poziomy.py. Rozdzielone groziłyby cichym rozjechaniem: formularz oferowałby wariant, którego widok nie zna, i raport wychodziłby po prostu posortowany domyślnie — bez żadnego błędu.Domyślna wartość per instalacja — za darmo
Nie trzeba jej nigdzie modelować.
RaportFormViewstoi naFormDefaultsMixin, aform_class_dla()buduje klasę o stabilnej, unikalnej nazwie per slug raportu (właśnie po to, żeby formdefaults nie mieszał defaultów między raportami). Redaktor ustawia więc domyślne sortowanie per instalacja i per raport z panelu domyślnych wartości formularzy. IHiT dostaje „zawsze po nazwiskach" bez pola w modelu i bez migracji.Przy okazji:
POLA_ZAAWANSOWANE→POLA_PRZEKAZYWANELista steruje wyłącznie przekazywaniem do querystringu — o wyglądzie decyduje
Layout. Po dodaniusortowania, które w układzie stoi w głównym fieldsecie, dawna nazwa sugerowałaby nieistniejący związek z sekcją „Opcje zaawansowane". Dwa użycia w repo, oba zaktualizowane.Testy
src/nowe_raporty/tests/test_sortowanie.py, pisane TDD (każdy oglądany na czerwono przed implementacją — w tymIndexError, który wykrył brakującydenorms.flush()w fixture):test_sortowanie_po_autorach_ustawia_order_by_raportu— okablowanie widokutest_bez_parametru_raport_zachowuje_kolejnosc_z_columnorder— regresja dla istniejących instalacjitest_rekord_sortuje_sie_po_nazwisku_pierwszego_autora— założenie o PostgreSQLtest_formularz_domyslnie_nie_zmienia_sortowaniatest_formularz_przekazuje_wybor_sortowania_do_url— wybór przeżywa skok formularz → redirect → widokLokalnie: 69 passed w
src/nowe_raporty/(cała aplikacja, nie tylko nowe testy).pre-commitczysto.Zależność
Wymaga
django-flexible-reports>=0.5.0— mpasternak/django-flexible-reports#14 (Report.set_order_by()). Bump wpyproject.toml+uv lockdokładam osobnym commitem po wydaniu pakietu; dziśuv locknie ma czego zrezolwować, więc commit z bumpem zostawiłby drzewo niespójne.Kolejność: zmerguj i wydaj #14 → dopycham bump tutaj → PR gotowy do scalenia.
Poza zakresem
Klientka dostanie 12 alfabetycznych list (po jednej na sekcję 1.1, 1.2, 2.1…), a jej dokument to jedna płaska lista. Płaski raport składa się w adminie, bez kodu (nowy
Reportz jedną sekcją catchall) — przygotuję go osobno i pokażę oba warianty.🤖 Generated with Claude Code
https://claude.ai/code/session_01WSUsgzYoDNnXpXGAn5otJg