Skip to content

feat(eurocris): encje Projekt i Finansowanie — sety projects i funding (#701, #702) - #719

Merged
mpasternak merged 11 commits into
devfrom
feat/eurocris-projekty
Aug 5, 2026
Merged

mpasternak merged 11 commits into
devfrom
feat/eurocris-projekty

Conversation

@mpasternak

Copy link
Copy Markdown
Member

Zamyka #701 (encja Project) i #702 (encja Funding) z parasola #709.

Problem

Sety openaire_cris_projects i openaire_cris_funding były puste (ProviderPusty). Profil OpenAIRE wymaga istnienia setów, nie ich zapełnienia, więc walidator przechodził — a OpenAIRE nie widział łańcucha publikacja ↔ projekt ↔ finansowanie, czyli głównej rzeczy, jaką CRIS ma do pokazania.

Przyczyna leżała w modelu danych: Grant miał cztery pola i był etykietą numeru grantu, nie encją projektu. Encja finansującego nie istniała.

Co wnosi ten PR

Modele (src/bpp/models/projekt.py): Projekt, Projekt_Autor (z rolą i bazowym UniqueConstraint na jednego kierownika), Instytucja_Finansujaca, Finansowanie. Grant zostaje etykietą numeru grantu z FK do projektu (SET_NULL) — dzięki czemu istniejąca generyczna relacja Grant_Rekordu staje się relacją publikacja↔projekt bez migracji danych.

Seed (migracja 0486): 7 polskich grantodawców (NCN, NCBR, MNiSW, FNP, NAWA, ABM, KE). Każdy identyfikator potwierdzony krzyżowo — FundRef z Crossrefa i rekord ROR wymieniający ten sam FundRef w external_ids. Żadna pozycja nie weszła bez potwierdzonego identyfikatora.

Admin: ProjektAdmin z inline'ami zespołu i finansowania, Instytucja_FinansujacaAdmin, projekt w GrantAdmin (z filtrem „granty bez projektu"), eksport_cerif_kwoty w UczelniaAdmin.

Eksport CERIF: buildery <Project> i <Funding>, dwa nowe providery, grantodawcy dołożeni do setu openaire_cris_orgunits (wymóg integralności — Funding/Funder musi wskazywać na OrgUnit obecny w harveście), oraz Publication/OriginatesFrom i Patent/OriginatesFrom osadzające pełne <Project>.

Rzeczy warte uwagi recenzenta

  • OriginatesFrom to sedno. Bez niego sety byłyby pełne, walidator zielony, a agregator dostałby dwie rozłączne listy. Element osadza pełne <Project> (grupa podstawień ProjectFunding__SubstitutionGroupHead), nie referencję.
  • Kwoty domyślnie nie wychodzą — nowy przełącznik Uczelnia.eksport_cerif_kwoty, wzorem eksport_cerif_osoby. Dane zostają w bazie do użytku wewnętrznego.
  • Team podlega eksport_cerif_osoby — przy wyłączonym przełączniku projekt wychodzi bez PrincipalInvestigator i Member, bo referencja do nieobecnego rekordu byłaby wisząca.
  • FundRefID w XSD ma wzorzec https://doi.org/10.13039/<cyfry>, a model trzyma sam numer — serializer normalizuje.
  • GenericRelation(Grant_Rekordu) na RekordBPPBaza zmienia kaskadę kasowania: usunięcie publikacji kasuje teraz jej wiersze Grant_Rekordu zamiast zostawiać sieroty. To poprawa, ale realna zmiana zachowania poza eksportem.

Świadome pominięcia

Udokumentowane w docs/deweloper/eurocris-co-jeszcze.md (sekcje A1/A2 przepisane na stan faktyczny): Project/Type (BPP nie ma typologii projektów), Projekt.strona_www (profil nie ma elementu), Team/*/Affiliation (Projekt_Autor nie niesie jednostki), partnerzy zewnętrzni (brak encji instytucji zewnętrznej), front i API, mapowanie dyscyplin na Fields of Science (Subject i Status idą z własnym schematem, bo profil nie dostarcza słownika).

Testy

make tests-without-playwright → 9179 passed, 4 skipped, 1 xfailed. Sam pakiet cerif_export: 397 (było 313).

Najważniejszy jest test_integralnosc_projektow.py — harvestuje wszystkie sety przez warstwę OAI i sprawdza, że każdy identyfikator referowany z <Project>, <Funding> i osadzonego OriginatesFrom istnieje jako @id rekordu w swoim secie, w obu stanach obu przełączników uczelni. Jego czułość zweryfikowano mutacjami kodu produkcyjnego (odcięcie widoczne_projekty() → 6 z 10 testów pada).

Baseline odświeżony (0485–0486).

Do zrobienia przed wdrożeniem

openaire-cris-validator 2.1.1 na żywym endpoincie z dumpem produkcyjnym — krok akceptacyjny dla człowieka, jak przy #699. Testy sprawdzają zgodność ze schematem i integralność wewnątrz harvestu; walidator sprawdza cały protokół.

Specyfikacja i plan: docs/superpowers/specs/2026-08-05-eurocris-projekt-finansowanie-design.md, docs/superpowers/plans/2026-08-05-eurocris-projekt-finansowanie.md.

🤖 Generated with Claude Code

mpasternak and others added 11 commits August 5, 2026 12:32
Projekt techniczny rozbudowy modelu danych o encje CERIF Project
i Funding: nowy model Projekt (Grant zostaje etykietą numeru grantu),
Projekt_Autor z rolą, Instytucja_Finansujaca jako Funder eksportowany
w secie OrgUnits, Finansowanie 1:N z typem ze słownika OpenAIRE.

Mapowania skonfrontowane z XSD profilu leżącym w repozytorium
(src/cerif_export/tests/xsd/) — w szczególności struktura Project/Funded
(By = referencja do OrgUnit findera, As = osadzone <Funding>),
dedykowane elementy RORID/FundRefID/GrantDOI oraz wymóg atrybutu scheme
dla klasyfikacji Status i Subject.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Plan rozbity na 7 zadań: modele (fundament), następnie równolegle admin,
seed grantodawców i fundament eksportu, potem buildery Project/Funding,
OriginatesFrom i domknięcie testami integralności.

Uzupełnienie speca: profil łączy publikację z projektem elementem
Publication/OriginatesFrom (XSD l. 698, analogicznie Patent l. 871),
osadzającym pełne <Project>. Bez niego sety byłyby pełne, walidator
zielony, a agregator dostałby dwie rozłączne listy — czyli brak tego,
po co powstało #709. Dopisana też sekcja o znanych odstępstwach
(Subject bez mapowania na Fields of Science, brak Project/Type).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…, Finansowanie (#701, #702)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Identyfikatory FundRef i ROR potwierdzone krzyżowo w obu rejestrach
(Crossref Funder Registry + external_ids rekordu ROR), nie przepisane
z pamięci.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ych (#701)

Wprowadzanie danych o projektach badawczych z poziomu admina: ProjektAdmin
z inline'ami zespołu i finansowania, osobny słownik instytucji
finansujących. Formset zespołu duplikuje bazowy UniqueConstraint „jeden
kierownik na projekt", żeby redaktor dostał komunikat walidacji zamiast
pięćsetki z IntegrityError.

Admin grantu pokazuje i wyszukuje powiązany projekt, ustawienia uczelni
dostają przełącznik eksportu kwot finansowania do CERIF.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ect/Funding (#702)

Stałe TYP_PROJECT/TYP_FUNDING i schematy klasyfikacji własnych, wpisy
pj/fn/if w rejestrze identyfikatorów, słownik typów finansowania wg
vocabularies/openaire_funding_types.xsd oraz eksport grantodawcy jako
CERIF OrgUnit (RORID, FundRefID, ElectronicAddress).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ding (#701, #702)

Buildery ``cerif/project.py`` i ``cerif/funding.py`` oraz providery obu
setów. ``Project/Funded/By`` jest referencją do OrgUnit-a grantodawcy,
``Project/Funded/As`` osadza pełne ``<Funding>`` (ta sama funkcja
serializująca, więc kontrola 5b walidatora spełniona trywialnie).

``ZbioryWidocznosci`` dostaje zbiór ``grantodawcy``: bez niego ``zawiera()``
zwracało dla ``Instytucja_Finansujaca`` False, więc ``Funding/Funder``
i ``Project/Funded/By`` osadzały OrgUnit-a bez ``@id`` — referencję nie do
rozwiązania w harveście.

``Project/Team`` powstaje wyłącznie gdy osoby są widoczne; przy
``Uczelnia.eksport_cerif_osoby=False`` znika razem z kontenerem.
``Funding/Amount`` wychodzi wyłącznie za zgodą ``Uczelnia.eksport_cerif_kwoty``
— przełącznik wystawia ``KontekstSerializacji.kwoty_dozwolone``.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ektami (#701)

Publikacje i patenty osadzają w ``OriginatesFrom`` pełny element
``<Project>`` (grupa podstawień ``ProjectFunding__SubstitutionGroupHead``),
a ten w ``Funded/As`` — swoje ``<Funding>``. Dzięki temu agregator dostaje
łańcuch publikacja → projekt → finansowanie zamiast dwóch rozłącznych list.

``RekordBPPBaza`` dostaje ``GenericRelation`` do ``Grant_Rekordu`` — bez
odwrotnej relacji nie dało się prefetchować grantów od strony rekordu.
Zmiana nie tworzy kolumny, więc nie wymaga migracji; zmienia natomiast
kaskadę kasowania (wiersze ``Grant_Rekordu`` znikają razem z rekordem,
zamiast zostawać sierotami).

Zbiory widoczności providerów publikacji i patentów obejmują teraz także
zespół projektu, jego jednostkę realizującą i grantodawców — inaczej
osadzony projekt referowałby encje bez ``@id``.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…#702)

Nowy `test_integralnosc_projektow.py` harvestuje wszystkie sety przez
ListRecords i sprawdza, że każdy `@id` z encji osadzonej ma rekord we
właściwym secie — w obu stanach `eksport_cerif_osoby` i `eksport_cerif_kwoty`.
Pokrywa Consortium/Coordinator, Team/PrincipalInvestigator, Team/Member,
Funded/By, Funded/As i Funding/Funder, także w projekcie osadzonym
w `Publication/OriginatesFrom`.

Sekcje A1 i A2 dokumentu euroCRIS opisane na stan faktyczny: co
zaimplementowano i co świadomie pominięto (Project/Type, strona WWW,
afiliacje zespołu, partnerzy zewnętrzni, własne schematy Subject i Status).

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

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@mpasternak
mpasternak merged commit 92bc4b0 into dev Aug 5, 2026
23 of 24 checks passed
@mpasternak
mpasternak deleted the feat/eurocris-projekty branch August 5, 2026 10:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant