docs: add PEJ section design spec
Hybrid "lens" approach — PEJ section filters existing ZOPK data by nuclear project IDs, adding dedicated routes, templates, and CSV export without new database tables. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
39f1d33f44
commit
9ab41b13cb
237
docs/superpowers/specs/2026-03-16-pej-section-design.md
Normal file
237
docs/superpowers/specs/2026-03-16-pej-section-design.md
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
```python
|
||||||
|
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.py` → `Announcement.CATEGORIES` list — dodać `'pej'`
|
||||||
|
- `database.py` → `Announcement.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
|
||||||
|
|
||||||
|
Dodajemy link "PEJ" w nawigacji `base.html`:
|
||||||
|
|
||||||
|
**Dla zwykłych zalogowanych użytkowników:**
|
||||||
|
- Obok istniejącego linku "Kaszubia" dodajemy "PEJ" → `/pej`
|
||||||
|
- Oba linki jako osobne elementy w top nav (nawigacja nie jest jeszcze przepełniona)
|
||||||
|
|
||||||
|
**Dla admina (w dropdown "Więcej"):**
|
||||||
|
- Dodajemy "PEJ" pod "Kaszubia" w tym samym dropdown
|
||||||
|
|
||||||
|
**Mobile:**
|
||||||
|
- Oba linki w hamburger menu, pod sobą
|
||||||
|
|
||||||
|
## 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 portalu** — `Announcement` 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`)
|
||||||
|
- Dropdown "Projekty" grupujący Kaszubia + PEJ (nie potrzebny przy 2 linkach)
|
||||||
|
|
||||||
|
## 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
|
||||||
Loading…
Reference in New Issue
Block a user