feat(#438): Faza C — usunięcie modelu Wydzial i całej jego powierzchni#465
Open
mpasternak wants to merge 20 commits into
Open
feat(#438): Faza C — usunięcie modelu Wydzial i całej jego powierzchni#465mpasternak wants to merge 20 commits into
mpasternak wants to merge 20 commits into
Conversation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
D1=Opcja A (redirect po slugu jednostki), D2=nie (pole wydzial bez renamu), D3=odlozone (rename modelu poza zakresem). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… 3 HIGH) Kluczowe: pbn_import/import_dyscyplin/egeria to zywi konsumenci Wydzial (pominieci w pierwotnej inwentaryzacji); cross-app deps migracji DeleteModel; backfill poprzednie_nazwy przed dropem; migracja ~25 plikow testow; MPTT per-object create; kolizja Jednostka.nazwa w widgecie; non-vacuous test CT. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nie_nazwy) T1: matchuj_wydzial/_wydzial_filtr (import_common) + _matchuj_wydzial_z_cache (import_dyscyplin) konsumuja Jednostke top-level zamiast modelu Wydzial. Match po nazwie LUB poprzednie_nazwy (promowany 1-jedn. wydzial ma nazwe jednostki; dawna nazwa wydzialu w poprzednie_nazwy — backfill 0466). Usuwa zaleznosc od struktura_konwersja i pulapke cichego filter(Jednostka.pk jako Wydzial.pk) (Fable F3/F6). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
T2: WydzialGetOrCreateWidget → get-or-create root-Jednostka (parent=None) zamiast tworzyc model Wydzial + wezel-lustro. Lookup po nazwie BEZ parent__isnull (Jednostka.nazwa unique globalnie — Fable F8): kolizja z jednostka podrzedna = blad walidacji, nie ciche zle drzewo. Dodane testy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
T3: create_wydzialy tworzy rooty Jednostka (rodzaj Wydzial, MPTT rebuild po bulk_create — F7 zaadresowane presetem 0+rebuild), create_jednostki wisza pod nimi wprost (drop znajdz_lub_utworz_wezel_wydzialu). manifest: bpp.Wydzial usuniety z CLEANUP_ORDER (rooty ida jako bpp.Jednostka); orchestrator cleanup toleruje nieznane modele w starym manifescie (F11). Testy przepiete (legacy_wydzial_id/Wydzial.count -> parent__isnull). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…p-level T4: zaloz_jednostki_domyslne, mapuj_kierunki_studiow, prace_do_rozliczenia, rebuild_slugs, look_for_unused_fields — Wydzial.objects -> Jednostka parent__isnull; site_filtered scope 'wydzial' FK jak 'jednostka' (oba celuja w Jednostka po B). Usunieto jednorazowy import_jednostki_ipis (hardkod sciezki). Test zaloz odsprzezony od fixture 'wydzial' (root Jednostka). Uwaga: konwertuj_wydzialy_na_jednostki + waliduj_konwersje_wydzialow zostaja do T11 (wola je test_faza_b_i2) — usuwane razem ze struktura_konwersja+model. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…aza C #438) Faza C usuwa model Wydzial. Onboarding importu PBN (dashboard + kreator InstitutionImporter) przestaje tworzyć/czytać Wydzial i węzły-lustra — „wydział domyślny" to teraz zwykła jednostka top-level (parent IS NULL), a jednostka domyślna wisi wprost pod nią (MPTT parent). - znajdz_lub_utworz_wydzial_domyslny: tworzy/wyszukuje root-Jednostkę (parent__isnull) zamiast Wydzial; skrot [:128]. - znajdz_lub_utworz_obca_jednostke / InstitutionImporter.run: podpinają jednostki wprost pod root-wydział (bez znajdz_lub_utworz_wezel_wydzialu). - views dashboard: listy „wydziałów" = Jednostka.filter(parent__isnull); POST czyta root-Jednostkę po pk; default-creation odświeża root przed MPTT-move (in-memory lft/rght nieaktualne po utworzeniu jednostki → inaczej InvalidMove). - testy: baker.make(Wydzial) → root-Jednostka; usunięto helper _wezel. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Model Wydzial znika w Fazie C, więc znika też jego endpoint REST. „Wydział" = top-level Jednostka, dostępny przez /api/v1/jednostka/. Hiperłącza ``wydzial`` na Jednostce i Patencie już wskazują jednostka-detail (Faza B), więc zostają bez zmian. - WydzialSerializer + WydzialViewSet: usunięte. - router: wyrejestrowany r"wydzial". - api-index: „wydzial" zdjęte z listy authors_and_units. - test: /api/v1/wydzial/ → NoReverseMatch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
WydzialAutocomplete i PublicWydzialAutocomplete odchodzą razem z modelem Wydzial. Rolę pickera „wydziału" przejął w Fazie B PublicJednostkaToplevelAutocomplete (jednostki parent IS NULL), więc żadne formularze/multiseek już z nich nie korzystają — usuwamy martwy kod. - simple.py: obie klasy + nieużywane już importy (Wydzial, NazwaLubSkrotMixin, UczelniaScopedAutocompleteMixin). - __init__.py / urls.py: eksporty i trasy wydzial-autocomplete oraz public-wydzial-autocomplete. - testy: zdjęto public-wydzial-autocomplete z listy security-endpointów, usunięto per-uczelnia test Wydzialu i asercję WydzialAutocomplete; dodano test potwierdzający NoReverseMatch obu tras. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…za C #438) Opcja A: legacy redirect przestaje szukać modelu Wydzial i węzła-lustra (legacy_wydzial_id). „Wydział" to jednostka top-level o tym samym slugu (mapowanie 1:1 zachowane od Fazy B), więc /wydzial/<slug>/ kierujemy wprost na /jednostka/<slug>/; brak jednostki → 404. Odcina browse.py od modelu Wydzial przed jego usunięciem (T11). - browse.py: uproszczony browse_wydzial_redirect + zdjęty import Wydzial. - testy: happy-path na jednostce top-level + 404 bez jednostki; usunięto testy oparte na węźle-lustrze. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…438) Model Wydzial znika w T11 — jego etykieta w listach ładowanych na starcie (``apps.get_model``) rzucałaby wtedy LookupError. Usuwamy referencje z wyprzedzeniem: - DJANGO_EASY_AUDIT_REGISTERED_CLASSES: bez "bpp.Wydzial". - CACHEOPS (production): bez "bpp.wydzial". Flagi behawioralne (DJANGO_BPP_SKROT_WYDZIALU_W_NAZWIE_JEDNOSTKI, uzywaj_wydzialow) zostają — dotyczą etykiet/układu, nie modelu. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PRZED dropem modelu Wydzial (0467) i markera legacy_wydzial_id (0468) utrwalamy nazwę każdego wydziału w poprzednie_nazwy jego węzła-korzenia. Dzięki temu matchuj_wydzial (import, Faza C) dalej odnajduje root po dawnej nazwie wydziału — także gdy root został PROMOWANY z realnej jednostki i nosi jej nazwę, nie nazwę wydziału (węzeł-lustro nadal matchuje po nazwie). Idempotentne (nie dubluje; pomija gdy nazwa roota == nazwa wydziału), reversible = no-op. Test: promowany root, idempotencja, węzeł-lustro (skip), brak legacy_wydzial_id (skip), zachowanie istniejących nazw. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Faza C, sedno: model ``Wydzial`` znika. „Wydział" to jednostka top-level
(``parent IS NULL``); wszyscy konsumenci FK zostali przepięci na ``Jednostka``
w Fazie B, a nazwy dawnych wydziałów utrwalił backfill 0466.
Model / kod:
- Usunięto ``bpp/models/wydzial.py`` (model + sygnały + JednostkaCreateManager)
i ``bpp/models/struktura_konwersja.py`` (znajdz_lub_utworz_wezel_wydzialu).
- ``struktura.py`` / ``jednostka.py``: zdjęto importy z ``wydzial``.
- ``Jednostka.wydzial_dnia()``: zwraca teraz węzeł-rodzic (Jednostka) wprost,
a nie odtwarzany ``Wydzial`` po ``legacy_wydzial_id`` (F4).
- ``imports/egeria_2012.py``: lookup wydziału → ``Jednostka`` top-level,
bez węzła-lustra (F3).
- Usunięto komendy ``konwertuj_wydzialy_na_jednostki`` i
``waliduj_konwersje_wydzialow``.
- ``autor.py``: przywrócono import ``Q`` (był zgubiony w bazie brancha
względem origin/dev — forward-port jednoliniowej poprawki).
Migracja:
- ``0467_faza_c_drop_wydzial``: ``DeleteModel("Wydzial")`` z cross-app
dependencies (import_dyscyplin 0024, zglos_publikacje 0026) — F1.
- Doprecyzowano 0466: czysta funkcja ``nowa_poprzednie_nazwy`` (testowalna
po dropie modelu, bez ORM).
Testy:
- Usunięto testy martwej mechaniki konwersji (test_wydzial,
test_konwertuj_wydzialy, test_waliduj_konwersje_wydzialow, faza_b_i2/i3/i4)
oraz kroku „odkryj_widoczna"/lazy-lustro w faza_b_iv1.
- Przepięto ~30 plików testów + fixtury (any_wydzial, conftest_models,
conftest_multisite) na jednostkę top-level; ``baker.make(Wydzial)`` →
``baker.make(Jednostka, parent=None)``, węzeł-lustro → root wprost.
- Strukturalny styl browse: root dostaje rodzaj „Wydział"
(``pokazuj_strukture_podjednostek=True``) w teście.
- ``test_wydzial_usuniety``: model nie w rejestrze, tabela ``bpp_wydzial``
nie istnieje.
Grep-gate: zero żywych referencji ``Wydzial`` w kodzie (poza komentarzami
historycznymi i migracjami). Wszystkie 313 przepiętych testów zielone;
jeden pre-existing fail (test_konfigurowalne_platnosci_artykul — brak
fixture ``typy_odpowiedzialnosci``, identycznie na origin/dev) poza zakresem.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…(0468) Faza C: po dropie modelu Wydzial (0467) markery TOŻSAMOŚCI KONWERSJI na ``Jednostka`` przestały być do czegokolwiek potrzebne. Były scaffoldingiem Fazy B (mapowanie starych FK po ``legacy_wydzial_id``, filtr logiki lustra/widoczności po ``jest_lustrem``). Runtime już ich nie dotyka — predykaty poddrzewa poszły na strukturę MPTT (``get_descendants``) i zdenorm. self-FK ``wydzial`` (patrz metody węzła w jednostka.py). - ``jednostka.py``: usunięto pola ``legacy_wydzial_id`` i ``jest_lustrem``; przeredagowano komentarze metod węzła, które opisowo odwoływały się do ``*_legacy_wydzial_id`` (kod i tak używał ``wydzial=self`` / MPTT). - Migracja ``0468_faza_c_drop_legacy_markery``: ``RemoveField`` × 2 (dep: 0467). ``makemigrations --check`` → „No changes detected". - ``test_wydzial_usuniety``: parametryzowane testy, że oba markery zniknęły z modelu (``FieldDoesNotExist``) i z tabeli ``bpp_jednostka``. - ``test_jednostka_pola_faza_a``: zdjęto asercję o ``legacy_wydzial_id``. - ``test_migration_0463``: usunięto 3 testy end-to-end ``remap_saved_searches`` — mapowały stare pk wydziału PO usuniętym polu, więc nie da się ich odpalić na żywych modelach (w realnym łańcuchu 0463 działa dalej — używa zamrożonego ``apps``). Logikę remapu wartości pokrywają czyste testy słownikowe. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… (0469)
``DeleteModel("Wydzial")`` (0467) usuwa tabelę, ale zostawia wiersz
``ContentType(app_label="bpp", model="wydzial")`` i jego 4 auto-uprawnienia
(``add/change/delete/view_wydzial``). Django nie kasuje stale content-type'ów
w migracjach — robi to tylko interaktywna ``remove_stale_contenttypes`` — więc
na realnym upgrade DB, która MIAŁA ten CT, śmieci zostałyby na zawsze
(orphaned Permission mylące w adminie/ACL). Migracja 0469 (RunPython, reverse
= noop) czyści je deterministycznie i idempotentnie; na świeżej bazie CT nie
powstaje, więc to bezpieczny no-op.
Test NIEPUSTY: seeduje CT+Permission ręcznie (na świeżej bazie CT ``wydzial``
nie istnieje, sam łańcuch nic by nie udowodnił) i sprawdza, że funkcja je
kasuje, jest idempotentna i NIE rusza innych content-type'ów.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…top-level Audyt T14 (#438): konfigurowalna etykieta „wydziału" na poziomie top-level przeżywa Fazę C bez zmian, bo NIE zależy od usuniętego modelu: - ``Uczelnia.uzywaj_wydzialow`` (BooleanField) — flaga sterująca ekspozycją pojęcia „Wydział" (setup wizard, multiseek ``option_enabled``, nowe_raporty, context processor ``UCZELNIA_UZYWA_WYDZIALOW``, admin) — zostaje. - ``nazwa_wydzialu`` = ``lemat("WYDZIAL")`` — etykieta z lematów gramatycznych, niezależna od modelu — zostaje. - ``domyslna_nazwa_wydzialu`` — czysty string ``f"Wydział {skrot}"``. Jedyna zmiana kodu: docstring ``JednostkaImportResource`` mówił, że widget tworzy ``Wydzial`` (model) — po Fazie C tworzy top-level ``Jednostka`` (``parent IS NULL``). Poprawiono. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
F12 higiena: fixture zawierała ``"model": "bpp.wydzial"`` (usunięty model) i była referencjonowana już tylko w ZAKOMENTOWANEJ linii migracji 0035 — loaddata nigdy jej nie ładuje, a po dropie modelu i tak by się wywaliła. Uwaga nt. baseline: baseline.sql na dev jest nieświeży (bpp @ 0442, 27 migracji wstecz — stan współdzielony z origin/dev, nie wprowadzony przez Fazę C). Zgodnie z CLAUDE.md („nie odświeżaj baseline w równoległych feature-branchach — rób to raz, przy scalaniu") NIE dołączam 4,6k-liniowego re-dumpa do tego PR-a; baseline-update trzeba puścić RAZ przy merge. Łańcuch 0443→0469 zwalidowany end-to-end lokalnie (baseline_update zaaplikował go na czystym kontenerze). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Self-review planu/implementacji Fazy C subagentem Fable — naprawione
zweryfikowane findingi:
- **[wysoki] matchuj_wydzial**: pusty string (osiągalny z pustej kolumny XLS
przez ``matchuj_jednostke(..., wydzial="")``) trafiał w
``poprzednie_nazwy__icontains=""`` = ``LIKE '%%'`` i zwracał LOSOWY root.
Dodatkowo brak ``order_by`` (niedeterminizm) i ``icontains`` łapał substring.
Fix: guard pustego → None; exact ``nazwa`` (globalnie unikatowa) ma priorytet;
fallback po ``poprzednie_nazwy`` dopasowuje CAŁĄ linię (weryfikacja w Pythonie),
deterministyczny ``order_by("pk")``. + 2 testy regresji.
- **dashboard.py**: usunięto martwe ``"bpp.models.wydzial"`` w ModelList
„Struktura" (miss w T9 — dangling ref do usuniętego modelu).
- **ruff format**: 4 pliki testów zmienione w tym branchu miały drift
formatowania (ryzyko czerwonego „Lint changed files" w CI).
- **design-spec**: zdanie „usunięcie uzywaj_wydzialow" było sprzeczne z decyzją
T14 (flaga ZOSTAJE) i z Kryterium sukcesu #15 — doprecyzowano; odnotowano
odłożone rename'y (D2/D3).
- **menu.py**: stały komentarz „Wydzial jako MODEL żyje do Fazy C".
Świadomie pominięte: log overflow w 0466 (modyfikacja migracji + przypadek
skrajnie nieprawdopodobny — do checklisty „zweryfikuj backfill na dumpie prod"),
egeria_2012 (martwy importer), semantyka wydzial_dnia (zero konsumentów poza
testami).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Scala 88 commitów z dev (importer: sugerowanie punktacji, import POLON zapis do bazy, kasowanie pustych jednostek, zwijanie list autorów, PBN import hardening, kolumna uczelni w adminie jednostek, ...) do gałęzi Fazy C (#438), która usuwa model Wydzial. Konflikty (2) rozwiązane pod kątem świata Fazy C ("wydział" = jednostka top-level z parent IS NULL; model Wydzial i moduł struktura_konwersja usunięte): - src/import_polon/tests/test_multi_uczelnia_scoping.py — zachowano nowe z dev helpery _jednostka()/_autor_historyczny(), zaadaptowane do root-Jednostki zamiast baker.make(Wydzial) + znajdz_lub_utworz_wezel_ wydzialu. - src/pbn_import/utils/institution_import.py — złożono semantykę dev (podpinaj obcą jednostkę do wydziału TYLKO gdy caller poda jawny wydzial; bez niego zostaje węzłem-root, gate sprawdz_obca_jednostka nie wymaga linku) z mechaniką Fazy C (parent=wydzial wprost, bez węzła-lustra). Graf migracji: dwa liście 0466 (dev 0466_bppuser_zwijaj... oraz tip łańcucha Fazy C 0469_faza_c_czysc_contenttype_wydzial) połączone migracją 0470_merge_20260708_1616. Baseline odświeżony in-place (make baseline-update) — potwierdza, że migracje Fazy C usuwające Wydzial aplikują się czysto na schemacie dev (bpp 0465 -> 0470). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Faza C (#438): usunięcie modelu
Wydziali całej jego powierzchniDomknięcie konsolidacji Wydział → Jednostka. Po Fazie B (jedno drzewo MPTT,
wszystkie zewnętrzne FK przepięte na
Jednostka) „wydział" to po prostujednostka top-level (
parent IS NULL). Faza C usuwa martwy już modelWydzialwraz z całą powierzchnią API/UI/importu oraz scaffoldingiemkonwersji.
Migracje (0466 → 0469, zależność liniowa od
0465_merge)faza_c_backfill_poprzednie_nazwypoprzednie_nazwykorzeni (idempotentnie) — historia nazw przeżywa drop modelufaza_c_drop_wydzialDeleteModel("Wydzial")(cross-app deps: import_dyscyplin 0024, zglos_publikacje 0026)faza_c_drop_legacy_markeryRemoveField× 2:legacy_wydzial_id,jest_lustrem(markery konwersji Fazy B — runtime ich nie używa)faza_c_czysc_contenttype_wydzialContentType+Permissionpo Wydzial (Django nie robi tego sam w migracjach)Usunięta powierzchnia
bpp/models/wydzial.py,bpp/models/struktura_konwersja.py(
znajdz_lub_utworz_wezel_wydzialu)./api/v1/wydzial/(serializer + viewset + router).WydzialAutocomplete,PublicWydzialAutocomplete.konwertuj_wydzialy_na_jednostki,waliduj_konwersje_wydzialow.bpp.Wydzial./wydzial/<slug>/→ trwały (301) redirect nabpp:browse_jednostkapo tym samym slug-u (Opcja A, mapowanie 1:1).um_lublin_wydzial.json.Przepięcia runtime (bez modelu)
Jednostka.wydzial_dnia()zwraca węzeł-rodzic (Jednostka) wprost.imports/egeria_2012.py— lookup wydziału poJednostkatop-level.Jednostka.(
get_descendants) / zdenorm. self-FKwydzial— nigdy po markerach.Co ZOSTAJE (audyt T14)
Konfigurowalna etykieta top-level jest niezależna od modelu:
Uczelnia.uzywaj_wydzialow(flaga ekspozycji pojęcia „Wydział"),nazwa_wydzialu=lemat("WYDZIAL")(etykieta z lematów gramatycznych).Testy
Wydzialw kodzie (poza komentarzamihistorycznymi i zamrożonymi migracjami).
test_wydzial_usuniety(model/tabela/markery/kolumny znikły),test_migration_0469_czysc_contenttype(niepusty — seeduje CT+Permission).make tests-without-playwright— zielona.baseline.sqlna dev jest nieświeży (bpp @0442, 27 migracji wstecz — stanwspółdzielony, nie z Fazy C). Zgodnie z CLAUDE.md NIE dołączam re-dumpa do
tego PR-a (byłby to ~4,6k-liniowy diff mieszający migracje innych feature'ów).
Przy scalaniu puść
make baseline-updateRAZ. Łańcuch0443→0469zwalidowany end-to-end lokalnie (
baseline_updatezaaplikował go na czystymkontenerze bez błędów).
Closes część #438 (Faza C).
🤖 Generated with Claude Code