nordabiz/docs/superpowers/specs/2026-03-16-pej-section-design.md
Maciej Pienczyn afd5dcf8bb docs: add PEJ section implementation plan
10 tasks across 4 chunks: backend routes, templates, nav
reorganization, and verification/deploy. Includes fixes from
spec and plan reviews (field names, endpoint aliases, diacritics).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 17:56:32 +01:00

13 KiB

PEJ Section — Dedicated Nuclear Energy Space on nordabiznes.pl

Date: 2026-03-16 Status: Draft Approach: Hybrid — "soczewka" na dane ZOPK + własne treści PEJ

Problem

Izba Norda Biznes aktywnie angażuje się w projekt PEJ (Polskie Elektrownie Jądrowe). Po spotkaniu z dyrektorem PEJ ds. local content (Grzegorz Maj) pojawiła się pilna potrzeba:

  1. Dostarczenia PEJ listy firm członkowskich z kontaktami i branżami
  2. Motywowania członków do uzupełnienia profili na portalu
  3. Śledzenia aktualności i postępów projektu nuklearnego
  4. Wydzielenia PEJ z ogólnej sekcji ZOPK — PEJ to strategiczny kierunek Izby, nie tylko jeden z projektów Kaszubia

Architecture

Hybrid "Lens" Approach

PEJ section nie tworzy nowych tabel — konsumuje istniejące dane ZOPK, filtrując po projektach nuklearnych. Dodaje jedynie:

  • Nowe routes i templates pod /pej
  • Routes w istniejących blueprintach public i admin (spójnie z wzorcem ZOPK)
  • Kategorię pej w systemie ogłoszeń
  • Endpoint eksportu CSV firm dla PEJ
┌─────────────────────────────────────────────────┐
│                ZOPK Pipeline                    │
│  (news fetch → scrape → extract → embed)        │
│  Zbiera dane: PEJ, offshore, Kongsberg, H2...   │
└──────────────────┬──────────────────────────────┘
                   │ filtruje po project_id
                   │ (nuclear-plant) i category='nuclear'
                   ▼
┌─────────────────────────────────────────────────┐
│              Sekcja PEJ (/pej)                  │
│  Landing page + Local Content + Aktualności     │
│  + Ogłoszenia Izby (kategoria 'pej')           │
└─────────────────────────────────────────────────┘

Data Sources — Co skąd ciągniemy

Dane Źródło ZOPK Filtr Join path
Aktualności zopk_news project_id IN (nuclear_project_ids) bezpośredni
Milestones/Timeline zopk_milestones category = 'nuclear' bezpośredni
Firmy dostawcy zopk_company_links project_id IN (nuclear_project_ids) bezpośredni
Fakty wiedzy zopk_knowledge_facts source_news_id → zopk_news.project_id 1 JOIN przez source_news_id
Encje (Westinghouse, Bechtel...) zopk_knowledge_entities zopk_project_id IN (nuclear_project_ids) bezpośredni

Nuclear Project ID Resolution

NUCLEAR_PROJECT_SLUGS = ['nuclear-plant']  # explicite lista, łatwa do rozszerzenia o SMR

def get_nuclear_project_ids(db_session):
    """Zwraca ID projektów nuklearnych z ZOPK."""
    projects = db_session.query(ZOPKProject.id).filter(
        ZOPKProject.slug.in_(NUCLEAR_PROJECT_SLUGS),
        ZOPKProject.project_type == 'energy'
    ).all()
    return [p.id for p in projects]

Filtr po explicit slug list + project_type = 'energy' — bezpieczny przed przypadkowym dopasowaniem.

Ogłoszenia Izby (np. notatki ze spotkań z PEJ)

Wykorzystujemy istniejący model Announcement z nową kategorią pej. Treści jak notatka WhatsApp o spotkaniu z Grzegorzem Majem → ogłoszenie z category = 'pej', widoczne na stronie PEJ.

Wymagane zmiany kodu (bez migracji SQL):

  • database.pyAnnouncement.CATEGORIES list — dodać 'pej'
  • database.pyAnnouncement.CATEGORY_LABELS dict — dodać 'pej': 'PEJ / Energetyka jądrowa'
  • Template admin/announcements_form.html renderuje checkboxy z CATEGORIES automatycznie — brak zmian

Routes

Public Routes

Wymagają @login_required — w odróżnieniu od ZOPK (publiczne), PEJ zawiera dane kontaktowe firm (email, telefon) w sekcji Local Content, dlatego wymaga logowania.

Route Funkcja Opis
GET /pej pej_index() Landing page — hero, stats, najnowsze aktualności, timeline nuklearny, top 6 firm Local Content, ogłoszenia Izby
GET /pej/local-content pej_local_content() Pełna lista firm z matchingiem do PEJ — filtry po branży, typie współpracy, score
GET /pej/aktualnosci pej_news() Aktualności nuklearne (paginacja, z ZOPK news filtered)

Admin Routes

Route Funkcja Opis
GET /admin/pej/export pej_export_csv() Eksport CSV firm: nazwa, email kontaktowy, branża, PKD, usługi, typ współpracy, opis, score

File Structure (spójne z wzorcem ZOPK)

blueprints/public/routes_pej.py    # 3 public routes (jak routes_zopk.py)
blueprints/admin/routes_pej.py     # 1 admin export route (jak routes_zopk_*.py)
templates/pej/
├── index.html                     # Landing page
├── local_content.html             # Lista firm
└── news.html                      # Aktualności nuklearne

Rejestracja w app.py — import routes w odpowiednich blueprintach (public, admin).

Templates

1. templates/pej/index.html — Landing Page

┌─────────────────────────────────────────────────────┐
│  HERO: "Elektrownia Jądrowa — Szanse dla Naszych    │
│  Firm"                                               │
│  Krótki opis: Izba Norda Biznes aktywnie uczestniczy │
│  w projekcie PEJ. Tu znajdziesz aktualności,         │
│  listę firm gotowych do współpracy i informacje      │
│  o możliwościach dla członków.                       │
├─────────────────────────────────────────────────────┤
│  STATS BAR: [X firm gotowych] [Y aktualności]        │
│             [Z milestones]                           │
├─────────────────────────────────────────────────────┤
│  OGŁOSZENIA IZBY (kategoria 'pej')                  │
│  Np. notatka o spotkaniu z PEJ                      │
├──────────────────────┬──────────────────────────────┤
│  AKTUALNOŚCI (3-4)   │  TIMELINE nuklearny          │
│  Najnowsze newsy     │  (milestones category=       │
│  z ZOPK nuclear      │   nuclear)                   │
│  [Zobacz wszystkie →] │                              │
├──────────────────────┴──────────────────────────────┤
│  LOCAL CONTENT — Firmy z Izby gotowe do współpracy  │
│  Top 6 firm (wg relevance_score)                    │
│  Każda karta: nazwa, branża, typ współpracy, opis   │
│  [Zobacz pełną listę →] [Eksportuj CSV →]           │
└─────────────────────────────────────────────────────┘

Kolorystyka: odróżniona od ZOPK (zielony). PEJ → fioletowo-niebieski (#7c3aed / #4f46e5) — nawiązanie do koloru projektu nuclear-plant w bazie.

2. templates/pej/local_content.html — Lista Firm

┌─────────────────────────────────────────────────────┐
│  HEADER: "Local Content — Firmy Izby Norda dla PEJ" │
│  [Eksportuj CSV]                                    │
├─────────────────────────────────────────────────────┤
│  FILTRY: [Branża ▼] [Typ współpracy ▼] [Szukaj...] │
├─────────────────────────────────────────────────────┤
│  LISTA FIRM (karty):                                │
│  ┌───────────────────────────────────────────────┐  │
│  │ Logo | Nazwa firmy           | Score: 85/100  │  │
│  │      | Branża: IT, Services  | Dostawca ⚡    │  │
│  │      | Opis współpracy z AI matching          │  │
│  │      | Email: kontakt@firma.pl                │  │
│  │      | [Zobacz profil →]                      │  │
│  └───────────────────────────────────────────────┘  │
│  ... (paginacja)                                    │
└─────────────────────────────────────────────────────┘

Sortowanie domyślne: relevance_score DESC. Filtry:

  • Branża (z Company.category)
  • Typ współpracy (z ZOPKCompanyLink.link_type)
  • Szukaj (po nazwie firmy)

Wyświetlane firmy: ZOPKCompanyLink.relevance_score >= 25 (próg z matchingu AI), wszystkie statusy (suggested, confirmed, active) — na tym etapie nie rozróżniamy, bo wszystkie linki pochodzą z AI matchingu.

3. templates/pej/news.html — Aktualności

Analogicznie do zopk/news_list.html, ale z filtrem na projekt nuklearny. Bez filtra po projekcie (bo wszystko jest już nuklearne).

CSV Export

Endpoint: GET /admin/pej/export (wymaga admin/OFFICE_MANAGER)

Kolumny:

Nazwa firmy;Email;Telefon;Branża;PKD (główny);Usługi;Typ współpracy PEJ;Opis współpracy;Score;Miasto

Źródło: ZOPKCompanyLink JOIN Company WHERE project_id IN (nuclear_ids) AND relevance_score >= 25 — sortowane po score DESC.

Kodowanie: UTF-8 BOM (dla Excela). Separator: ; (standard PL). Filename: pej-local-content-YYYY-MM-DD.csv. MIME: text/csv; charset=utf-8.

Navigation — Reorganizacja głównego NAV

Zmiana dla WSZYSTKICH zalogowanych użytkowników

Standalone link "Kaszubia" zastępujemy dropdownem "Projekty ▾":

  • Projekty ▾ → Kaszubia (/zopk), PEJ (/pej)

Reorganizacja NAV admina (13 → 10 pozycji)

Usuwamy z głównego NAV:

  1. "Social (beta)" — duplikat, jest w admin barze jako "Publikacja social media"
  2. "Korzyści" — duplikat, jest w admin barze pod "Izba → Korzyści"
  3. "Więcej ▾" — zastępujemy "Projekty ▾", a admin-only items (Kontakty zewnętrzne, Raporty, Mapa Powiązań) przenosimy do admin bara

Przenosiny do admin bara:

  • Kontakty zewnętrzne → admin bar, nowy dropdown "Narzędzia" lub do "Izba"
  • Raporty → admin bar "Narzędzia"
  • Mapa Powiązań → admin bar "Narzędzia"

Wynik — admin NAV:

Firmy | NordaGPT | Kalendarz | B2B | Forum | Wiadomości | Aktualności | Edukacja | Rada | Projekty▾ | [🔔] [User▾]

Wynik — zwykły użytkownik NAV:

Firmy | NordaGPT | Kalendarz | B2B | Forum | Wiadomości | Aktualności | Edukacja | Projekty▾ | [🔔] [User▾]

Mobile

  • "Projekty ▾" w hamburger menu, rozwijany na tap

Data Model Changes

Brak nowych tabel

Cała sekcja PEJ operuje na istniejących modelach ZOPK.

Announcement category (zmiana w kodzie, bez migracji)

Dwa miejsca w database.py:

  1. Announcement.CATEGORIES — dodać 'pej' do listy
  2. Announcement.CATEGORY_LABELS — dodać 'pej': 'PEJ / Energetyka jądrowa'

Kolumna categories to ARRAY(String) bez CHECK constraint — brak potrzeby migracji SQL.

WhatsApp Content Strategy

Treść notatki WhatsApp o spotkaniu z PEJ:

  1. Ogłoszenie na portaluAnnouncement z category=['pej'], widoczne na /pej i /ogloszenia
  2. Hero content na landing page — wyróżniony blok "Ostatnie spotkanie z PEJ" na stronie /pej
  3. Motywacja do uzupełnienia profili — CTA na stronie PEJ: "Uzupełnij profil firmy, aby znaleźć się na liście Local Content"

Scope Exclusions (YAGNI)

Celowo nie robimy teraz:

  • Formularz deklaracji gotowości firmy do PEJ (wystarczy matching AI)
  • Integracja NordaGPT z filtrem PEJ-only (chatbot i tak rozpoznaje pytania o PEJ)
  • Osobny pipeline news dla PEJ (ZOPK pipeline już zbiera te dane)
  • PDF export (CSV wystarczy na potrzeby PEJ)
  • Osobna sekcja dla SMR / OSGE (przyszłościowo — dodanie slugów do NUCLEAR_PROJECT_SLUGS)
  • Dalsze konsolidacje NAV (Forum+Wiadomości itp.) — obecny układ jest wystarczający

Testing

  • Weryfikacja na staging.nordabiznes.pl przed wdrożeniem na produkcję
  • Sprawdzenie czy firmy z matchingiem nuklearnym wyświetlają się poprawnie
  • Test eksportu CSV — otwarcie w Excel, weryfikacja polskich znaków (UTF-8 BOM)
  • Test nawigacji — link PEJ widoczny dla zalogowanych
  • Test responsywności — mobile, tablet