Skip to content

feat(zglos_publikacje): nowy wielokrokowy wizard zgłaszania publikacji#119

Merged
mpasternak merged 36 commits into
devfrom
feature/nowe-zglos-publikacje
May 4, 2026
Merged

feat(zglos_publikacje): nowy wielokrokowy wizard zgłaszania publikacji#119
mpasternak merged 36 commits into
devfrom
feature/nowe-zglos-publikacje

Conversation

@mpasternak
Copy link
Copy Markdown
Member

Summary

  • Przebudowa formularza zgłaszania publikacji z jednoetapowego na wielokrokowy wizard (5 kroków):
    • Krok 0: Wybór rodzaju publikacji (kafelki: Artykuł, Monografia, Rozdział, Inne)
    • Krok 1: Wybór formy dostępu (kafelki: Otwarty / Ograniczony)
    • Krok 2: Formularz danych z polami zależnymi od wyborów z kroków 0-1
    • Krok 3: Autorzy (bez zmian)
    • Krok 4: Opłaty za publikację (warunkowo, konfigurowalne per typ)
  • Rozdzielenie legacy "artykuł lub monografia" na osobne typy (ARTYKUL=5, MONOGRAFIA=4, INNE=6)
  • Nowe pola: wydawca i wydawnictwo nadrzędne z QuerySetSequence autocomplete łączącym BPP i PBN
  • Obsługa wielu plików PDF (Zgloszenie_Publikacji_Zalacznik)
  • Konfigurowalne per-typ wymaganie informacji o opłatach na modelu Uczelnia (4 osobne booleany)
  • 6 nowych szablonów per-krok z kafelkowym UI (Foundation grid)
  • Aktualizacja admina: inline załączników, nowe pola, konfiguracja opłat
  • Przepisane testy WebTest i Playwright

Test plan

  • uv run python src/manage.py migrate -- sprawdzenie migracji
  • uv run pytest src/zglos_publikacje/ -x -- testy jednostkowe i integracyjne
  • Manualne przejście przez wizard w przeglądarce (wszystkie 4 typy × 2 formy dostępu)
  • Sprawdzenie autocomplete wydawcy (BPP + PBN)
  • Sprawdzenie autocomplete wydawnictwa nadrzędnego
  • Upload wielu plików PDF w trybie ograniczonego dostępu
  • Konfiguracja opłat per typ w adminie Uczelnia
  • Edycja istniejącego zgłoszenia (pre-populacja kroków 0 i 1)
  • make tests-only-playwright -- testy E2E

🤖 Generated with Claude Code

@mpasternak mpasternak force-pushed the feature/nowe-zglos-publikacje branch from 620f78f to 412b8a0 Compare April 16, 2026 19:02
mpasternak and others added 4 commits April 16, 2026 21:35
Przebudowa formularza zgłaszania publikacji z jednoetapowego na
wielokrokowy wizard z kafelkowym wyborem typu publikacji i formy
dostępu. Rozdzielenie "artykuł lub monografia" na osobne typy,
nowe pola (wydawca, wydawnictwo nadrzędne z QuerySetSequence
autocomplete łączącym BPP i PBN), obsługa wielu plików PDF,
konfigurowalne per-typ wymaganie opłat w admin uczelni.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…uń pole wydawca

- Kafelek "Monografia" przemianowany na "Książka / Monografia" — nie każda
  książka to monografia w ścisłym sensie
- Pole link (strona_www) wymagane zawsze niezależnie od trybu dostępu —
  PBN wymaga tego pola; help_text wyjaśnia, że dla dostępu ograniczonego
  wystarczy link do strony wydawcy lub katalogu BN/NUKAT
- Usunięto pola "wydawca" i "wydawca_zgloszenia" z formularza użytkownika;
  wydawca ustawiany ręcznie przez bibliotekarza w adminie (konieczny do
  wyliczenia punktów i slotów)
- _set_wydawca nie resetuje wydawcy gdy pola nieobecne w formularzu
- Migracja scalająca dwa równoległe 0411 (bpp)
- 7 nowych testów jednostkowych

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…dzaju zgłoszenia

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@mpasternak mpasternak force-pushed the feature/nowe-zglos-publikacje branch from 3fd1586 to 0824de4 Compare April 16, 2026 19:37
mpasternak and others added 9 commits April 16, 2026 21:53
Docker Build Cloud's layer cache occasionally returned a stale bpp_base
(missing bpp-sync-deps after a dev->feature rebase). Force no-cache on
the base target; cache mounts (apt/uv/npm/yarn) keep downloads fast, and
app services already use contexts=target:base so they pick up the
freshly-built image instead of pulling from the registry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…mport

authserver's INSTALLED_APPS doesn't include password_policies, but
urls_auth_server -> views -> middleware transitively imported
password_policies.middleware at module level, which loads
password_policies.models and fails with:

    RuntimeError: Model class password_policies.models.PasswordChangeRequired
    doesn't declare an explicit app_label and isn't in an application in
    INSTALLED_APPS.

Extract EXTERNAL_AUTH_BACKENDS into its own tiny module
django_bpp.external_auth so views.py can import it without transitively
touching middleware.py. middleware.py is now only imported when
password_policies is in INSTALLED_APPS (appserver), not authserver.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…point

bpp-sync-deps was a 13-line wrapper around a single `uv sync` command,
baked into every production image and gated by BPP_SYNC_DEPS_ON_START.
Risk: any accidental env var flip would run uv sync in production.

Remove the shared script entirely:
- delete docker/bpp_base/sync-deps.sh and its COPY in the bpp_base Dockerfile
- drop the `bpp-sync-deps` call from every production entrypoint (appserver,
  workerserver, beatserver, denorm-queue) so prod images carry zero
  dev-only logic
- in docker-compose.yml (which is explicitly dev-only), override each
  service's entrypoint to run `uv sync --frozen --all-extras --no-extra=dev
  --no-install-project` before the production entrypoint. This is needed
  only because dev shadows .venv with a volume; prod bakes .venv into the
  image.
- drop the BPP_SYNC_DEPS_ON_START flag everywhere

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add `pytest_configure` hook that invokes `make assets` so that CSS + .mo
files are guaranteed up-to-date regardless of how pytest is invoked
(bezpośrednio przez `uv run pytest` vs `make tests`). BPP UI depends on
built assets; there is no pure-Python mode.

Use UV_NO_SYNC=1 for the make call so that the `uv run` invocations
inside Makefile targets (notably `compilemessages`) do not re-sync the
venv and strip `testcontainers` + other dev-extras, which would crash
the testcontainers_bpp pytest plugin before collection.
Dwa rozłączne, odkryte razem błędy:

1) Bug: `pliki` field używa `MultipleFileInput` (widget z
   `allow_multiple_selected=True`) ale klasa pola to zwykły
   `forms.FileField`. Przy uploadzie ≥1 pliku widget zwraca listę,
   a `FileField.to_python` próbuje `.name` na liście → crash z
   komunikatem "Nie wysłano żadnego pliku. Sprawdź typ kodowania
   formularza.". Dodany `MultipleFileField` rozpakowujący listę
   przez single_file_clean dla każdego elementu.

2) Testy Playwright klikały `input[value='...']` oraz
   `#id-wizard-submit` na krokach 0/1, ale:
   - Radio input jest ukryty wewnątrz `<label class="tile-card">`
     (CSS `display:none`) — Playwright odmawia klik niewidocznego.
   - Przycisk `#id-wizard-submit` na krokach 0/1 nie istnieje —
     szablon nadpisuje `{% block wizard_buttons %}` pustym blokiem;
     submit odbywa się przez JS handler na kafelku.
   Zmieniono na `.tile-card[data-value='...']` (single click).

3) `test_zglos_publikacje_ograniczony_dostep` przekazywał
   `strona_www=""`, ale po `5b68c5b4` pole jest `required=True` —
   HTML5 blokował submit przed roundtripem. Teraz używa default URL;
   walidacja brakującego pliku (server-side) dalej działa jako
   intencja testu.
Dwa jednolinijkowe bugi infrastrukturalne ujawnione przez CI runs
na branchu:

1) Tests (Playwright) faili z "BrowserType.launch: Executable
   doesn't exist at /root/.cache/ms-playwright/...". Powód: step
   `Install Playwright browsers` uruchamia `docker compose run
   --rm test-runner` (ephemeral), więc cache browserów w
   /root/.cache/ms-playwright znika z kontenerem. Kolejny step
   (Tests Playwright) startuje nowy kontener bez browserów.
   Fix: named volume `playwright_cache` mapujący ten katalog,
   żeby persystował między `compose run --rm`.

2) Lint changed files > Ruff check faili na
   src/zglos_publikacje/migrations/0023_... z błędem I001
   (import ordering). Pyproject ma `extend-exclude` z migracjami,
   ale ruff przy JAWNIE podanych ścieżkach ignoruje excludes bez
   `--force-exclude`. Fix: dodać flagę do obu kroków ruffa
   (check + format --check).
Paginator (np. django-autocomplete-light) rzucał
UnorderedObjectListWarning dla sekwencji w ZrodloAutocomplete — każdy
sub-queryset ma tam `.order_by("nazwa","pk")` i jest sliced, więc
kolejność wyników jest deterministyczna, ale oryginalna klasa
`QuerySetSequence.ordered` zwraca True tylko gdy `.order_by()` wywołano
na samej sekwencji — czego nie można zrobić na sliced sub-querysetach
(Django 4+: "Cannot reorder a query once a slice has been taken").

`_OrderedSlicedQuerySetSequence` dziedziczy i nadpisuje `ordered`
tak, że zwraca True gdy każdy sub-queryset jest faktycznie
uporządkowany (delegacja do `qs.ordered` każdego z nich) — bez fake'u.
Jeśli którykolwiek sub-queryset jest nieuporządkowany, sekwencja
nadal raportuje False i ostrzeżenie jest uzasadnione.
Dodaje drugi, ergonomiczny sposób włączenia budowy obrazów dla
feature branchy: label `docker-build` na PR-ze. Zalety nad istniejącym
plikiem-flagą `.docker-build`:

- label żyje w metadanych PR-a, nie w drzewie repo — merge do mastera
  nie przenosi stanu „build-on-push" nigdzie, kolejne feature branche
  nie dziedziczą flagi przypadkiem.
- toggle jednym poleceniem: `gh pr edit <PR#> --add-label docker-build`
  / `--remove-label docker-build`, bez commitów.
- typ `labeled` zapewnia, że dodanie labela na już-pushniętym commicie
  od razu odpala workflow — bez konieczności pustego push'a.

Kompatybilne wstecznie: `.docker-build` i `workflow_dispatch` nadal
działają bez zmian. `check-flag` sprawdza warunki w kolejności:
workflow_dispatch → PR label → master → .docker-build.

Bezpieczeństwo: `HAS_DOCKER_BUILD_LABEL` ewaluuje się jako string
`true`/`false` w kontekście GitHub Actions (nie shell interpolation);
w `run:` porównujemy zmienną środowiskową.
@mpasternak mpasternak added the docker-build Włącza build obrazów Docker przy każdym push do PR-a label Apr 20, 2026
mpasternak and others added 14 commits April 20, 2026 18:10
Uruchamiał się 11min/21tur, kosztował ~$10 USD per push, ale nie
produkował żadnego review ani komentarza na PR-ze (brak `write`
w permissions + `use_sticky_comment: false` + puste inline comments).
Do odkomentowania jak konfiguracja plugina `code-review@claude-code-plugins`
+ action-u zostanie ustawiona tak, żeby faktycznie postowała review.
…likacje

# Conflicts:
#	.github/workflows/build-docker-images.yml
#	conftest.py
…e_20260416_2124

Po wczesniejszym merge'u dev w galezi powstaly dwie galezie liscie 0413
(bppuser_autor_onetoone i merge_20260416_2124). Migracja 0414 sciaga je
do jednego liscia, zeby `migrate` nie wybuchal CommandError'em.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…formy dostepu

Tekst pomocniczy pola "Link do publikacji lub DOI" jest teraz dobierany
z tablicy STRONA_WWW_HELP_TEXT na podstawie kombinacji (rodzaj, forma
dostepu) zgodnie z uwagami od bibliotekarki:

- artykul: bez fragmentu o BN/NUKAT (dotyczy tylko monografii/rozdzialu)
- monografia/rozdzial w dostepie ograniczonym: pojawia sie odsylacz do
  katalogow Biblioteki Narodowej i NUKAT
- inne (np. materialy konferencyjne): bez wzmianki o PBN; pole nie jest
  wymagane, bo PBN tych publikacji nie zbiera; przy dostepie ograniczonym
  pozostaje wymagany plik PDF

Macierz w SPEC_NOWY_FORMULARZ.md zaktualizowana, zeby odzwierciedlac
faktyczne zachowanie kodu.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Dla rodzaju POZOSTALE (Inne) help_text pola strona_www uproszczony:
  pusty dla otwartego dostępu, samo zdanie informacyjne dla ograniczonego
  (bez prefiksu PBN i bez dopisku o materiałach konferencyjnych).
- Krok 1 (forma dostępu): trzy kafelki ułożone w kolumnie zamiast
  kwadratowej siatki 2x2 z rozjechanym przyciskiem "Poprzedni krok".
- Nad kafelkami pojawia się badge z ikoną i nazwą wybranego rodzaju
  publikacji (np. "📄 Artykuł"), żeby użytkownik widział kontekst wyboru.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…la dev buildów

- /app/.git-sha w obrazie bpp_base zawiera commit, z którego zbudowano runtime;
  pozwala szybko zdiagnozować sytuacje, gdzie pull tagu zwraca stare pliki
  (np. ktoś deployuje nie ten tag).
- Stopka ("wersja X (commit YYYYYYY)") pokazuje krótki SHA tylko dla obrazów
  developerskich (PR/feature), żeby release master zachował czyste oznaczenie
  numerem wersji. BPP_BUILD_FLAVOR ustawia workflow: master->release, reszta->dev.
- Wartości GIT_SHA i BPP_BUILD_FLAVOR są wstrzykiwane jako ENV w runtime stage
  bpp_base, przekazywane przez docker-bake.hcl i workflow build-docker-images.yml.

Test: src/bpp/tests/test_templatetags/test_bpp_version.py pokrywa: brak env,
"unknown", flavor=release (puste), flavor=dev (krótki SHA), default flavor=dev.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stopka dla obrazów developerskich pokazuje teraz "wersja X (119-merge,
commit YYYYYYY)" — pomaga to namierzyć, którego PR-a/brancha dotyczy
deployowany obraz, bo sam SHA łatwo pomylić, a tag obrazu jest tym, co
ktoś wpisał w docker-compose.yml.

BPP_IMAGE_TAG przekazywane od workflow (steps.tag.outputs.final_tag)
przez bake'a do bpp_base runtime stage jako ENV. Master release
nadal pokazuje tylko numer wersji (BPP_BUILD_FLAVOR=release).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Zwiększone padding (0.75 → 1.25rem) oraz rozmiar ikony (2.5 → 3rem),
żeby pasek "wybrany rodzaj" w step_forma_dostepu był wyraźniejszy
i nie wyglądał jak wąski niebieski pasek.
…erge)

Tester może teraz pullować iplweb/bpp_appserver:feature-foo-bar zamiast
pamiętać numer PR. Workflow promuje staging tag pod oba aliasy:
:<PR#>-merge (kanoniczny) i :<sanitized_branch_name> (alias). Każdy push
do PR-a re-promuje oba, więc nazwa brancha pozostaje świeża dopóki PR
żyje. Dla master release (TAG_LATEST=true) i feature-pushy bez PR
(final_tag = branch_tag) alias się nie tworzy.

HEAD_REF (źródło source brancha PR-a) jest sanityzowany sed-em zanim
trafi do imagetools — bezpieczne nawet dla branch names z ukośnikami
czy znakami specjalnymi.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stopka pokazuje teraz "wersja X (119-merge, feature-nowe-zglos-publikacje,
commit YYYYYYY)" — od razu widać i kanoniczny tag PR-a, i sanityzowaną
nazwę gałęzi. Wcześniej stopka znała tylko jeden alias (final_tag),
więc nie było jasne że można też pullować po nazwie brancha.

Pipeline: workflow przekazuje branch_tag do bake'a, bake do bpp_base
runtime, a tam ENV BPP_BRANCH_TAG zostaje wczytany przez nowy
template tag {% bpp_branch_tag %}. Master release ma BPP_BUILD_FLAVOR=
release → tag zwraca pusty string, stopka pokazuje samą wersję.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Plik .docker-build juz nie istnieje (skasowany w poprzednim commicie),
wiec elif sprawdzajacy `[ -f ".docker-build" ]` byl dormantnym kodem.
Zastapione: push na non-master (czyli feature/fix/hotfix przez
restrykcje triggera) → buduj zawsze. Realizuje user-intent "auto-build
na feature branches" — bez tego push na feature spadalby na else
(skip), a `.docker-build` flag nie istnieje.

Komentarze i opisy aktualizowane — bez wzmianek o pliku flagi.
Pozostale `docker-build` w workflow to label PR-a (mechanizm zostaje).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
mpasternak and others added 3 commits April 28, 2026 20:53
Wycofuje gating labelem .docker-build/docker-build na rzecz prostszej
zasady: master/main push i workflow_dispatch buduja zawsze (release
flow + manual override), pozostale (PR sync, feature/fix/hotfix push
bez PR) — tylko gdy actor=mpasternak. Inni contributorzy nie pala
Docker Cloud minutek; jesli trzeba zbudowac obraz dla cudzego PR-a:
`gh workflow run build-docker-images.yml --ref <branch>`.

Dev branch dopisany jawnie do komentarza w pushu jako "intentionally
excluded" — push do dev nie odpala buildu (intermediate state nie
zasluguje na obraz, release leci przez master).

Dodany main do triggerow obok master (gdyby kiedys repo zmienilo
default branch — single source of truth).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts:
#	src/zglos_publikacje/tests/test_playwright/test_zglos_publikacje.py
Comment thread src/deduplikator_autorow/views/merge.py Fixed
Comment thread src/deduplikator_autorow/views/merge.py Fixed
mpasternak and others added 6 commits May 4, 2026 07:23
# Conflicts:
#	src/deduplikator_autorow/views/__init__.py
#	src/deduplikator_autorow/views/duplicates.py
#	src/deduplikator_autorow/views/export.py
#	src/deduplikator_autorow/views/helpers.py
#	src/deduplikator_autorow/views/ignore.py
#	src/deduplikator_autorow/views/merge.py
#	src/deduplikator_autorow/views/scan.py
W kroku 2 wizarda pole `pliki` (`MultipleFileField` + `<input multiple>`)
przyjmowało N plików, ale do `Zgloszenie_Publikacji_Zalacznik` trafiał
zero, jeden lub żaden — zależnie od ścieżki kodu.

Dwa nakładające się błędy:

1. `_process_files` czytało `self.request.FILES.getlist("2-pliki")`,
   ale w `done()` `request.FILES` to zawartość ostatniego kroku
   wizarda (autorzy/opłaty), nie kroku 2. Efekt: 0 załączników.

2. `formtools.wizard.storage.base.set_step_files` iteruje
   `files.items()` po `MultiValueDict`, co dla pól z `<input multiple>`
   gubi wszystkie wartości poza ostatnią. Efekt po fixie #1: tylko 1
   załącznik niezależnie od liczby uploadowanych plików.

Rozwiązanie:

- `process_step_files` zapisuje wszystkie pliki bezpośrednio do
  `file_storage` i listę metadanych do `storage.extra_data["pliki_list"]`.
  Standardowy storage formtools nadal dostaje swoje (re-walidacja
  w `render_done` zobaczy 1 plik = przejdzie clean()).
- `_process_files` w `done()` czyta z `extra_data` i tworzy
  `Zgloszenie_Publikacji_Zalacznik` dla każdego pliku, sprzątając
  tmp-y po skopiowaniu do permanent storage.
- `_wyczysc_tmp_pliki` usuwa stare tmp-y przy ponownym submitie
  kroku 2 (powrót w wizardzie).

Admin:

- `Zgloszenie_PublikacjiAdmin.pliki_do_pobrania` (readonly_field)
  wyświetla listę wszystkich załączników + legacy pole `plik`.
- Nowy `pobierz_zalacznik_view` z X-Accel-Redirect dla pojedynczych
  Zgloszenie_Publikacji_Zalacznik.

Testy regresji:

- `test_pelny_formularz_ograniczony_jeden_plik` — wizard OGRANICZONY
  z 1 plikiem, asercja `zalaczniki.count() == 1`.
- `test_pelny_formularz_ograniczony_wiele_plikow` — z 3 plikami,
  asercja `zalaczniki.count() == 3`. Bez fixa testy fail-ują;
  z fixem przechodzą. Webtest zamiast playwright bo
  `webtest_app.post(..., upload_files=[...])` obsługuje multipart
  z duplikatami klucza, a playwright na step 3→4 jest flaky przez
  auto-uzupełnianie jednostki w `autorform_dependant.js`.

Dodatkowo w tym samym commicie:

- Wyniesienie inline `<style>` z `step_base.html`/`step_rodzaj.html`/
  `step_forma_dostepu.html` do `_wizard_forms.scss` (nowy plik
  importowany w `app-{blue,green,orange}.scss`).
- `Zgloszenie_Publikacji_DaneForm.clean` defensywnie dla `self.files`
  w postaci dict (re-walidacja z storage formtools nie zwraca
  `MultiValueDict`).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Trzy współbieżne zmiany w wizardzie zgłaszania publikacji:

1) **Bug**: gdy user wybrał wydawnictwo nadrzędne (lub wydawcę)
   z autocomplete, do `Zgloszenie_Publikacji` trafiał tylko tekst
   etykiety, FK (`wydawnictwo_nadrzedne_bpp`/`_pbn`,
   `wydawca_bpp`/`_pbn`) zostawał `None`.

   Powód: `PublicWydawcaAutocomplete` i
   `PublicWydawnictwoNadrzedneAutocomplete` miały nadpisany
   `get_result_value`, który zwracał etykietę HTML zamiast
   `<ct_pk>-<obj_pk>` (formatu, którego oczekuje QSS widget przy
   POST). W rezultacie `<option value="...">` miał w sobie HTML
   etykiety, a `_resolve_qss_value()` w `done()` nie potrafił
   rozparsować referencji do obiektu.

   Fix: usunąć obie nadpisówki — domyślne `get_result_value`
   z `dal_queryset_sequence.views` zwraca poprawny format.

2) **Re-walidacja widget z malformed value** (z poprzedniego commita
   zostawione w forms.py): `TolerantQuerySetSequenceSelect2` filtruje
   bogusowe wartości przed `split('-', 1)` w `filter_choices_to_render`,
   żeby re-render formularza po validation error nie wybuchał z 500.

3) **UX**: help_text pola `strona_www` (link do publikacji lub DOI)
   wzbogacony o `_FULL_URL_TEKST` ze wskazówką:
   - prefiks `https://`/`http://`
   - jeżeli sam DOI — dodaj `https://dx.doi.org/[numer DOI]`

   Suffix dochodzi do wszystkich 8 kombinacji `(rodzaj, forma_dostepu)`
   w `STRONA_WWW_HELP_TEXT`, w tym do `POZOSTALE/OTWARTY` która
   wcześniej miała pusty help_text.

4) **CSS**: `.select2-container { display: block !important;
   margin-bottom: 1rem !important }` + spacing między select2 a
   następującym `.help-text`. Bez tego help_text crispy renderowany
   pod widgetem QSS wpadał w pole selecta (Foundation daje natywnemu
   `<select>` margin: 0 0 1rem, ale select2 wstawia `<span>` które
   tego nie dziedziczy).

5) **Migracja merge** `0415_merge_20260504_0907.py` — łączy `0414_*`
   z dev (code review fixy) z `0414_merge_20260427_1123` (z dev'owego
   merge w naszej gałęzi).

Testy regresji (webtest, pełne ścieżki przez wizard):

- `test_rozdzial_z_picknietym_wydawnictwem_nadrzednym_zapisuje_FK`
  — RAW format `<ct>-<pk>` (jak picnięty z autocomplete) → asercja
  `wn_bpp_id == ksiazka.pk` (regression dla bugu #1).

- `test_pelny_formularz_monografia_otwarty` — pełna ścieżka MONOGRAFII
  z asercjami: zgłoszenie utworzone, brak `wydawnictwo_nadrzedne_*`
  (forma usuwa pola), brak `wydawca_*` (świadomie usunięte z formularza
  w 5b68c5b — bibliotekarz uzupełnia w adminie). Test pilnuje tej
  decyzji projektowej; gdy ktoś przywróci pole `wydawca`, ten test
  trzeba świadomie zaktualizować.

- (z poprzedniego commita pozostają)
  `test_pelny_formularz_rozdzial_z_freetextem_wn`,
  `test_rozdzial_z_bogus_wn_picker_nie_wybucha_na_re_renderze`,
  `test_rozdzial_z_typed_text_w_picker_lzdaje_jako_freetext`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mpasternak mpasternak merged commit b6ae809 into dev May 4, 2026
5 checks passed
@mpasternak mpasternak deleted the feature/nowe-zglos-publikacje branch May 4, 2026 07:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docker-build Włącza build obrazów Docker przy każdym push do PR-a

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants