From 587d000b9b5f7aad246f49e65794a622eb9b0ed8 Mon Sep 17 00:00:00 2001 From: Maciej Pienczyn Date: Thu, 22 Jan 2026 10:26:24 +0100 Subject: [PATCH] docs: Reorganizacja dokumentacji - wydzielenie DEVELOPMENT, ROADMAP, CREDENTIALS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CLAUDE.md uproszczony - tylko kluczowe info dla Claude - docs/DEVELOPMENT.md - szczegóły SearchService, Chatbot, Testy AI, SEO, News - docs/ROADMAP.md - plan rozwoju, priorytety, strategia monetyzacji 3-tier - docs/CREDENTIALS.md - zasady zarządzania hasłami i kluczami API Co-Authored-By: Claude Opus 4.5 --- CLAUDE.md | 1062 +++++-------------------------------------- docs/CREDENTIALS.md | 168 +++++++ docs/DEVELOPMENT.md | 272 +++++++++++ docs/ROADMAP.md | 223 +++++++++ 4 files changed, 781 insertions(+), 944 deletions(-) create mode 100644 docs/CREDENTIALS.md create mode 100644 docs/DEVELOPMENT.md create mode 100644 docs/ROADMAP.md diff --git a/CLAUDE.md b/CLAUDE.md index 475d7bb..49c854f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -21,87 +21,25 @@ nordabiz/ ├── database/ # Schematy SQL, migracje ├── data/ # Dane źródłowe JSON ├── tests/ # Testy jakości AI -│ ├── ai_quality_evaluator.py -│ ├── ai_quality_test_cases.json -│ └── results/ # Wyniki testów (JSON) -├── scripts/ # Narzędzia Node.js +├── scripts/ # Narzędzia Python/Node.js └── docs/ # Dokumentacja - ├── architecture/ # Architektura systemu (diagramy, przepływy) - ├── INCIDENT_REPORT_20260102.md - └── INCIDENT_REPORT_20260115.md + ├── architecture/ # Architektura systemu (C4, flows) + ├── DEVELOPMENT.md # Szczegóły deweloperskie + ├── ROADMAP.md # Plan rozwoju, monetyzacja + ├── CREDENTIALS.md # Zasady zarządzania credentials + └── INCIDENT_REPORT_*.md ``` -## Dokumentacja architektury +## Dokumentacja -Kompletna dokumentacja architektury systemu dostępna w katalogu `docs/architecture/`. +| Dokument | Zawartość | +|----------|-----------| +| `docs/architecture/` | Architektura C4, schematy bazy, API, flows | +| `docs/DEVELOPMENT.md` | SearchService, Chatbot, Testy AI, SEO, News | +| `docs/ROADMAP.md` | Plan rozwoju, priorytety, monetyzacja | +| `docs/CREDENTIALS.md` | Zarządzanie hasłami i kluczami API | -### 📚 Dokumenty główne - -| Dokument | Opis | -|----------|------| -| [**README.md**](docs/architecture/README.md) | Przegląd całej dokumentacji architektury (start tutaj!) | -| [01-system-context.md](docs/architecture/01-system-context.md) | Kontekst systemu (C4 Level 1) - aktorzy i systemy zewnętrzne | -| [02-container-diagram.md](docs/architecture/02-container-diagram.md) | Diagram kontenerów (C4 Level 2) - Flask, PostgreSQL, NPM, API | -| [03-deployment-architecture.md](docs/architecture/03-deployment-architecture.md) | Architektura wdrożenia - serwery, porty, infrastruktura | -| [04-flask-components.md](docs/architecture/04-flask-components.md) | Komponenty Flask - routes, services, models | -| [05-database-schema.md](docs/architecture/05-database-schema.md) | Schemat bazy danych - 36 tabel, relacje, indeksy | -| [06-external-integrations.md](docs/architecture/06-external-integrations.md) | Integracje API - Gemini, Brave, PageSpeed, Places, KRS, MS Graph | -| [07-network-topology.md](docs/architecture/07-network-topology.md) | Topologia sieci - Fortigate, NPM, routing, DNS | -| [08-critical-configurations.md](docs/architecture/08-critical-configurations.md) | Konfiguracje krytyczne - NPM proxy, SSL, PostgreSQL, systemd | -| [09-security-architecture.md](docs/architecture/09-security-architecture.md) | Architektura bezpieczeństwa - RBAC, CSRF, strefy zaufania | -| [10-api-endpoints.md](docs/architecture/10-api-endpoints.md) | Referencja API - 90+ endpointów, auth, rate limiting | - -### 🔄 Przepływy danych (Data Flows) - -| Przepływ | Opis | -|----------|------| -| [01-authentication-flow.md](docs/architecture/flows/01-authentication-flow.md) | Rejestracja, login, reset hasła, sesje | -| [02-search-flow.md](docs/architecture/flows/02-search-flow.md) | Wyszukiwanie firm - synonimy, FTS, fuzzy matching | -| [03-ai-chat-flow.md](docs/architecture/flows/03-ai-chat-flow.md) | Chat AI - kontekst, Gemini API, tracking kosztów | -| [04-seo-audit-flow.md](docs/architecture/flows/04-seo-audit-flow.md) | Audyt SEO - PageSpeed API, analiza on-page/technical | -| [05-news-monitoring-flow.md](docs/architecture/flows/05-news-monitoring-flow.md) | Monitoring newsów - Brave API, filtrowanie AI, moderacja | -| [06-http-request-flow.md](docs/architecture/flows/06-http-request-flow.md) | Przepływ HTTP - user → NPM → Flask → PostgreSQL | - -### ⚡ Szybki start - -**Dla deweloperów:** -- Zacznij od [architecture/README.md](docs/architecture/README.md) -- Przejrzyj [04-flask-components.md](docs/architecture/04-flask-components.md) i [05-database-schema.md](docs/architecture/05-database-schema.md) -- Sprawdź przepływy w [flows/](docs/architecture/flows/) dla zrozumienia logiki biznesowej - -**Dla DevOps:** -- [03-deployment-architecture.md](docs/architecture/03-deployment-architecture.md) - infrastruktura -- [07-network-topology.md](docs/architecture/07-network-topology.md) - sieć i routing -- [08-critical-configurations.md](docs/architecture/08-critical-configurations.md) - **KRYTYCZNE!** NPM port 5000 - -**Dla architektów:** -- [01-system-context.md](docs/architecture/01-system-context.md) - widok wysokopoziomowy -- [02-container-diagram.md](docs/architecture/02-container-diagram.md) - komponenty główne -- [06-external-integrations.md](docs/architecture/06-external-integrations.md) - zależności zewnętrzne - -### 🛡️ Kluczowe ostrzeżenia z dokumentacji - -**NPM Proxy (KRYTYCZNE!):** -- Port forward **MUSI być 5000**, NIE 80! -- Szczegóły: [08-critical-configurations.md](docs/architecture/08-critical-configurations.md#npm-reverse-proxy) -- Incydent: [INCIDENT_REPORT_20260102.md](docs/INCIDENT_REPORT_20260102.md) - -**PostgreSQL:** -- Skrypty używają `localhost (127.0.0.1)`, NIE `10.22.68.249` -- Szczegóły: [08-critical-configurations.md](docs/architecture/08-critical-configurations.md#database-configuration) - -**API Limity:** -- Gemini: 1,500 req/dzień (free tier) -- PageSpeed: 25,000 req/dzień -- Brave Search: 2,000 req/miesiąc -- Szczegóły: [06-external-integrations.md](docs/architecture/06-external-integrations.md) - -**Uruchamianie skryptów na produkcji (KRYTYCZNE!):** -- SSH timeout NIE oznacza że komenda nie została wykonana! -- ZAWSZE sprawdź czy poprzedni proces nie działa przed ponowną próbą: `ps aux | grep ` -- Dla długich operacji używaj `nohup` lub `screen` -- Przy problemach z SSH użyj QEMU guest agent: `ssh root@10.22.68.123 "qm guest exec 249 -- "` -- Incydent: [INCIDENT_REPORT_20260115.md](docs/INCIDENT_REPORT_20260115.md) +**⚠️ WAŻNE:** Przed zmianami w NPM/proxy przeczytaj `docs/architecture/08-critical-configurations.md` ## Technologie @@ -110,7 +48,7 @@ Kompletna dokumentacja architektury systemu dostępna w katalogu `docs/architect | Backend | Flask 3.0, SQLAlchemy 2.0, Python 3.9+ | | Frontend | HTML5, CSS3, Vanilla JS, Jinja2 | | Baza danych | PostgreSQL (prod i dev via Docker) | -| AI | Google Gemini 2.0 Flash (free tier, 200 req/dzień) | +| AI | Google Gemini 2.0 Flash (free tier) | | Security | Flask-Login, Flask-WTF (CSRF), Flask-Limiter | ## Środowiska @@ -161,9 +99,7 @@ curl -I https://nordabiznes.pl/health | **origin** (GitHub) | `git@github.com:pienczyn/nordabiz.git` | Cloud backup, CI/CD ready | | **inpi** (Gitea) | `git@10.22.68.180:maciejpi/nordabiz.git` | Wewnętrzny backup, deploy source | -**Konta:** -- GitHub: `pienczyn` -- Gitea (r11-git-inpi): `maciejpi` (osobiste), `gitadmin` (admin Gitea) +**Konta:** GitHub: `pienczyn`, Gitea: `maciejpi` ### Workflow Deployment @@ -176,34 +112,8 @@ curl -I https://nordabiznes.pl/health └──── git push ────► GitHub (backup) ``` -**Komendy deployment:** -```bash -# 1. DEV: Push do obu repozytoriów -git push origin master && git push inpi master - -# 2. PROD: Pull i restart -ssh maciejpi@10.22.68.249 "cd /var/www/nordabiznes && sudo -u www-data git pull && sudo systemctl restart nordabiznes" -``` - -### Serwery Git - -| Serwer | IP | Port | Usługa | -|--------|-----|------|--------| -| r11-git-inpi | 10.22.68.180 | 3000 (HTTPS) | Gitea | -| GitHub | github.com | 22/443 | GitHub | - -**Gitea wymaga HTTPS** (nie HTTP) - URL: `https://10.22.68.180:3000/` - -### PROD Git Config - -- **Remote:** `https://10.22.68.180:3000/maciejpi/nordabiz.git` -- **User:** www-data -- **SSL verify:** disabled (`git -c http.sslVerify=false`) - ### Procedura wdrażania (WAŻNE!) -**Pełna procedura wdrażania z migracjami SQL:** - ```bash # 1. DEV: Push do obu repozytoriów git push origin master && git push inpi master @@ -223,953 +133,217 @@ curl -sI https://nordabiznes.pl/health | head -3 **⚠️ UWAGI KRYTYCZNE:** -1. **Migracje SQL** - NIE używaj `psql` bezpośrednio (wymaga hasła). Użyj skryptu `scripts/run_migration.py` który czyta DATABASE_URL z `.env`. +1. **Migracje SQL** - NIE używaj `psql` bezpośrednio. Użyj `scripts/run_migration.py` -2. **Uprawnienia logów** - Serwis działa jako `maciejpi` (nie `www-data`). Jeśli pojawi się błąd `Permission denied: /var/log/nordabiznes/*`: +2. **Uprawnienia logów** - Jeśli błąd `Permission denied: /var/log/nordabiznes/*`: ```bash ssh maciejpi@10.22.68.249 "sudo chown -R maciejpi:maciejpi /var/log/nordabiznes/" ``` -3. **502 po restarcie** - Czasami występuje chwilowy 502. Poczekaj 3-5 sekund i sprawdź ponownie. +3. **502 po restarcie** - Poczekaj 3-5 sekund i sprawdź ponownie -4. **Git pull** - Używaj `sudo -u www-data git pull` (www-data ma dostęp do kluczy SSH). +4. **Git pull** - Używaj `sudo -u www-data git pull` (www-data ma klucze SSH) -## Auto Claude - Konfiguracja i rozwiązywanie problemów +**Uruchamianie skryptów na produkcji (KRYTYCZNE!):** +- SSH timeout NIE oznacza że komenda nie została wykonana! +- ZAWSZE sprawdź czy poprzedni proces nie działa: `ps aux | grep ` +- Dla długich operacji używaj `nohup` lub `screen` +- Incydent: `docs/INCIDENT_REPORT_20260115.md` -### Pliki stanu Auto Claude (WAŻNE!) +## Auto Claude - Rozwiązywanie problemów -Auto Claude tworzy lokalne pliki stanu które **NIE POWINNY** być commitowane: -- `.auto-claude-security.json` - stan bezpieczeństwa projektu -- `.auto-claude-status` - status bieżącego zadania -- `.auto-claude/` - katalog roboczy Auto Claude +### Pliki stanu (NIE COMMITOWAĆ!) +- `.auto-claude-security.json`, `.auto-claude-status`, `.auto-claude/` +- Są w `.gitignore` + pre-commit hook automatycznie je usuwa ze staging -**Problem:** Auto Claude czasami dodaje te pliki do staging area w worktree branches, co powoduje konflikty merge gdy branch jest mergowany do master. - -**Rozwiązanie (wdrożone 2026-01-10):** - -1. **`.gitignore`** - pliki są ignorowane: - ``` - .auto-claude/ - .auto-claude-security.json - .auto-claude-status - ``` - -2. **Pre-commit hook** - automatycznie usuwa te pliki ze staging area: - ``` - .git/hooks/pre-commit - ``` - Hook sprawdza przed każdym commitem czy pliki Auto Claude są staged i automatycznie je usuwa. - -3. **Pliki usunięte z śledzenia** - wykonano `git rm --cached` na master - -### Rozwiązywanie konfliktów merge z Auto Claude - -Jeśli pojawi się konflikt merge z plikami `.auto-claude-*`: +### Konflikty merge z Auto Claude ```bash -# 1. Sprawdź czy to konflikt zmiana/usunięcie +# 1. Sprawdź konflikt git status -# 2. Usuń pliki Auto Claude z merge (akceptuj usunięcie z master) +# 2. Usuń pliki Auto Claude z merge git rm .auto-claude-security.json .auto-claude-status # 3. Dokończ merge git commit -m "Merge branch 'feature' - resolve Auto Claude file conflicts" ``` -### Worktrees Auto Claude +### Worktrees -Auto Claude tworzy worktrees dla każdego zadania w: -``` -.auto-claude/worktrees/tasks// -``` - -Każdy worktree ma własny branch i własne pliki stanu. Po zamergowaniu zadania worktree może być usunięty. - -**Sprawdzenie aktywnych worktrees:** ```bash -git worktree list -``` - -**Usunięcie nieaktualnego worktree:** -```bash -git worktree remove .auto-claude/worktrees/tasks/ -git branch -d auto-claude/ +git worktree list # Lista aktywnych +git worktree remove .auto-claude/worktrees/tasks/ # Usuń nieaktualny +git branch -d auto-claude/ # Usuń branch ``` ## Konwencje danych ### Identyfikatory firm -- **Slug:** kebab-case z nazwy, np. `pixlab-sp-z-o-o` -- **NIP:** 10 cyfr bez myślników, np. `5882436505` +- **Slug:** kebab-case, np. `pixlab-sp-z-o-o` +- **NIP:** 10 cyfr bez myślników - **REGON:** 9 lub 14 cyfr - **KRS:** 10 cyfr (tylko spółki) ### Kategorie firm -- `IT` - IT i Technologie -- `Construction` - Budownictwo -- `Services` - Usługi (prawne, księgowe, doradcze) -- `Production` - Produkcja -- `Trade` - Handel -- `Other` - Pozostałe +`IT`, `Construction`, `Services`, `Production`, `Trade`, `Other` ### Poziomy jakości danych -- `basic` - Nazwa, NIP, kontakt -- `enhanced` - Pełne dane, zweryfikowane -- `complete` - Wzbogacone o usługi, kompetencje, certyfikaty +`basic`, `enhanced`, `complete` ## Ważne zasady ### Bezpieczeństwo - NIE edytuj bezpośrednio bazy produkcyjnej PostgreSQL -- Zawsze testuj zmiany na DEV PostgreSQL (Docker: localhost:5433) przed wdrożeniem +- Testuj zmiany na DEV (Docker: localhost:5433) przed wdrożeniem - Klucze API i hasła tylko w `.env` (nigdy w kodzie) - Rate limiting: 200 req/dzień, 50 req/godzinę -#### Mechanizmy bezpieczeństwa (wdrożone) +**Panel bezpieczeństwa:** `/admin/security` +- 2FA, CSRF, HTTPS, GeoIP Blocking, Rate Limiting, Account Lockout, Audit Log -| Mechanizm | Ocena | Opis | -|-----------|-------|------| -| **2FA (TOTP)** | ★★★★★ | Uwierzytelnianie dwuskładnikowe przez aplikacje mobilne | -| **CSRF Protection** | ★★★★★ | Tokeny CSRF w formularzach (Flask-WTF) | -| **HTTPS/TLS** | ★★★★★ | Let's Encrypt SSL z auto-renewal | -| **Hashowanie haseł** | ★★★★★ | Werkzeug bcrypt | -| **SQL Injection** | ★★★★★ | SQLAlchemy ORM (parametryzowane zapytania) | -| **XSS Protection** | ★★★★★ | Jinja2 autoescape | -| **GeoIP Blocking** | ★★★★☆ | Blokowanie krajów: RU, CN, KP, IR, BY, SY, VE, CU | -| **Rate Limiting** | ★★★★☆ | Flask-Limiter + Redis | -| **Account Lockout** | ★★★★☆ | Blokada po 5 nieudanych logowaniach | -| **Audit Log** | ★★★★☆ | Śledzenie działań adminów | -| **Honeypot** | ★★★☆☆ | Wykrywanie botów (/.env, /wp-admin) | -| **Security Alerting** | ★★★☆☆ | Powiadomienia email o krytycznych zdarzeniach | +### Zarządzanie credentials (KRYTYCZNE!) -**Panel bezpieczeństwa:** `/admin/security` (dla adminów) -- Zakładka "Mechanizmy" - lista wszystkich mechanizmów z oceną gwiazdkową -- Zakładka "GeoIP" - statystyki blokowania (dzienne/miesięczne/roczne/od początku) -- Zakładka "Alerty" - alerty bezpieczeństwa do rozwiązania -- Zakładka "Audit log" - historia działań administracyjnych -- Zakładka "Zablokowane konta" - konta zablokowane przez brute-force +**NIGDY nie umieszczaj haseł w kodzie źródłowym!** -**GeoIP Configuration (.env):** -``` -GEOIP_ENABLED=true -GEOIP_DB_PATH=/var/www/nordabiznes/geoip/GeoLite2-Country.mmdb +```python +# ✅ PRAWIDŁOWO: +DATABASE_URL = os.getenv('DATABASE_URL') + +# ❌ BŁĘDNIE: +DATABASE_URL = 'postgresql://user:password123@localhost/db' ``` -**MaxMind GeoLite2:** -- Account ID: 1282843 -- Baza danych: GeoLite2-Country (aktualizowana co miesiąc) -- Lokalizacja: `/var/www/nordabiznes/geoip/GeoLite2-Country.mmdb` +- Wszystkie sekrety w `.env` (nigdy w `.py`, `.sh`, `.js`) +- Fallback jako placeholder: `CHANGE_ME` (nie prawdziwe hasło!) -#### Zarządzanie danymi uwierzytelniającymi (KRYTYCZNE!) - -**NIGDY nie umieszczaj haseł i kluczy API bezpośrednio w kodzie źródłowym!** - -Jest to krytyczna podatność bezpieczeństwa (CWE-798: Use of Hard-coded Credentials). Narusza standardy bezpieczeństwa i może prowadzić do kompromitacji systemu jeśli repozytorium zostanie ujawnione. - -**Zasady obowiązkowe:** - -1. **Używaj zmiennych środowiskowych dla wszystkich wrażliwych danych:** - ```python - # PRAWIDŁOWO: - DATABASE_URL = os.getenv('DATABASE_URL') - API_KEY = os.getenv('GOOGLE_PAGESPEED_API_KEY') - - # BŁĘDNIE - NIGDY TAK NIE RÓB: - DATABASE_URL = 'postgresql://user:password123@localhost/db' - API_KEY = 'AIzaSyAbc123...' - ``` - -2. **Konfiguruj wartości domyślne jako bezpieczne placeholdery:** - ```python - # PRAWIDŁOWO - wartość domyślna która wymusi konfigurację .env: - DATABASE_URL = os.getenv('DATABASE_URL', 'postgresql://user:CHANGE_ME@localhost/nordabiz') - - # BŁĘDNIE - wartość produkcyjna jako fallback: - DATABASE_URL = os.getenv('DATABASE_URL', 'postgresql://user:RealPassword@10.22.68.249/nordabiz') - ``` - -3. **Przechowuj dane uwierzytelniające w plikach .env:** - - Produkcja: `/var/www/nordabiznes/.env` - - Development: `.env` w katalogu projektu - - Wzorzec: `.env.example` (bez prawdziwych wartości!) - -4. **Wymagane zmienne środowiskowe:** - - | Zmienna | Cel | Przykład | - |---------|-----|----------| - | `DATABASE_URL` | Połączenie PostgreSQL dla skryptów Python | `postgresql://user:pass@127.0.0.1:5432/nordabiz` | - | `PGPASSWORD` | Hasło PostgreSQL dla skryptów shell | `export PGPASSWORD='your_password'` | - | `GOOGLE_PAGESPEED_API_KEY` | API Key Google PageSpeed | `AIzaSy...` | - | `BRAVE_SEARCH_API_KEY` | API Key Brave Search | `BSA...` | - | `GEMINI_API_KEY` | API Key Google Gemini AI | `AIzaSy...` | - -5. **Skrypty shell - zawsze sprawdzaj czy zmienne są ustawione:** - ```bash - # PRAWIDŁOWO: - if [ -z "$PGPASSWORD" ]; then - echo "ERROR: PGPASSWORD not set" - exit 1 - fi - psql -h localhost -U nordabiz_app -d nordabiz - - # BŁĘDNIE: - PGPASSWORD='hardcoded_password' psql -h localhost -U nordabiz_app -d nordabiz - ``` - -6. **NIGDY nie commituj plików z credentials:** - - `.env` jest w `.gitignore` - - Sprawdzaj przed commitem: `git diff` i `git status` - - W razie wątpliwości: `git log -p | grep -i password` - -7. **Co zrobić jeśli przypadkowo scommitujesz hasło:** - - ⚠️ **NATYCHMIAST zmień hasło w bazie/API** - - Nie wystarczy usunąć z najnowszego commita - hasło pozostaje w historii Git - - Rozważ użycie `git filter-branch` lub `BFG Repo-Cleaner` (skomplikowane) - - Najlepiej: zmień hasło i traktuj stare jako skompromitowane - -8. **Wyjątki (kiedy dozwolone jest hasło w kodzie):** - - ✅ Pliki dokumentacji (np. przykłady w CLAUDE.md, README) - - ✅ `.env.example` jako szablon (z placeholderami) - - ⛔ NIGDY w plikach wykonywalnych (.py, .sh, .js) - -**Weryfikacja przed wdrożeniem:** -```bash -# Sprawdź czy nie ma hardcoded credentials w kodzie: -grep -r "PGPASSWORD=" --include="*.sh" . -grep -r "postgresql://.*:.*@" --include="*.py" . | grep -v "CHANGE_ME" | grep -v ".example" | grep -v "PASSWORD" - -# Oczekiwany wynik: brak znalezisk (lub tylko w dokumentacji/placeholderach) -``` - -### Import danych -- Używaj skryptów `import_*.py` do dodawania firm -- Weryfikuj NIP przez API przed importem -- Zachowaj spójność slugów (unikalne, lowercase) +**Pełne zasady:** `docs/CREDENTIALS.md` ### Deployment - Przed wdrożeniem: `python -m py_compile app.py` -- SSH do NORDABIZ-01: `ssh maciejpi@10.22.68.249` (ZAWSZE jako maciejpi, NIE root!) +- SSH do NORDABIZ-01: `ssh maciejpi@10.22.68.249` (ZAWSZE jako maciejpi!) - Ścieżka aplikacji: `/var/www/nordabiznes` - Restart: `sudo systemctl restart nordabiznes` -- **ZAWSZE** aktualizuj historię zmian (`release_notes` w app.py) po wdrożeniu -- Historia zmian: efekt końcowy, bez powtórzeń, prostym językiem +- **ZAWSZE** aktualizuj historię zmian (`release_notes` w app.py) ### Szablony Jinja2 - WAŻNE! -- Blok `{% block extra_js %}` w `base.html` jest już wewnątrz tagu `{% endblock %}` ### Uprawnienia PostgreSQL -- Po utworzeniu nowych tabel: `GRANT ALL ON TABLE ... TO nordabiz_app` +- Po utworzeniu tabel: `GRANT ALL ON TABLE ... TO nordabiz_app` - Po utworzeniu sekwencji: `GRANT USAGE, SELECT ON SEQUENCE ... TO nordabiz_app` -- Baza: `nordabiz`, użytkownik aplikacji: `nordabiz_app` ### Testowanie na produkcji -- **ZAWSZE używaj kont testowych** do weryfikacji funkcjonalności -- Używaj przeglądarki (browser automation) do testów wymagających logowania **Konta testowe (PROD):** | Konto | Email | Hasło | Rola | |-------|-------|-------|------| -| Test User | `test@nordabiznes.pl` | `&Rc2LdbSw&jiGR0ek@Bz` | Zwykły użytkownik | -| Test Admin | `testadmin@nordabiznes.pl` | `cSfQbbwegwv1v3Q2Dm0Q` | Administrator | +| Test User | `test@nordabiznes.pl` | `&Rc2LdbSw&jiGR0ek@Bz` | Użytkownik | +| Test Admin | `testadmin@nordabiznes.pl` | `cSfQbbwegwv1v3Q2Dm0Q` | Admin | -**Użycie:** -- **Test User** - do testowania funkcji dostępnych dla zwykłych użytkowników -- **Test Admin** - do testowania panelu admina (rekomendacje, składki, kalendarz, forum, news) +## API Endpoints (podstawowe) -## Skrypty danych +| Endpoint | Opis | +|----------|------| +| `/` | Katalog firm | +| `/company/` | Profil firmy | +| `/search` | Wyszukiwanie | +| `/chat` | Chat AI | +| `/health` | Health check | +| `/admin/*` | Panele admina | -### Import (wykonywać kolejno) -```bash -python import_norda_companies.py # Batch 1 (56 firm) -python import_norda_batch2.py # Batch 2 -python import_norda_batch3.py # Batch 3 -python import_norda_batch4.py # Batch 4 (9 firm) -python import_norda_batch5.py # Batch 5 (8 firm) -``` +Pełna lista: `docs/architecture/10-api-endpoints.md` -### Weryfikacja -```bash -python verify_all_companies_data.py # Raport jakości danych -python fix_krs_verification.py # Weryfikacja KRS -``` +## SearchService -## API Endpoints +Unified search dla chatbota i `/search`. Szczegóły: `docs/DEVELOPMENT.md#searchservice` -| Endpoint | Metoda | Opis | -|----------|--------|------| -| `/` | GET | Katalog firm | -| `/company/` | GET | Profil firmy | -| `/search` | GET | Wyszukiwanie | -| `/api/companies` | GET | Lista firm (JSON) | -| `/api/verify-nip` | GET | Weryfikacja NIP | -| `/health` | GET | Health check | -| `/chat` | GET | Interfejs chatu AI | -| `/admin/news` | GET/POST | Panel moderacji newsów (wymaga admin) | -| `/api/notifications` | GET | Powiadomienia użytkownika (JSON) | +## Chatbot AI -## SearchService (search_service.py) +- **Limit firm:** 8 +- **Historia:** 10 wiadomości -Unified search dla chatbota AI i wyszukiwarki `/search`. - -### Funkcje: -- **NIP/REGON lookup** - bezpośrednie wyszukiwanie po identyfikatorach -- **Synonym expansion** - rozszerzenie słów kluczowych (np. "strony" → www, web, portal) -- **PostgreSQL FTS** - full-text search z tsvector (DEV i PROD) -- **SQLite fallback** - keyword scoring (tylko jako fallback, nieużywane) -- **Fuzzy matching** - pg_trgm dla literówek (gdy dostępne) - -### Scoring: -- Nazwa firmy: +10 punktów -- Opis: +5 punktów -- Usługi: +8 punktów -- Kompetencje: +7 punktów -- Miasto: +3 punktów - -### Użycie: -```python -from search_service import search_companies -results = search_companies(db, "strony www", limit=10) -# Zwraca List[SearchResult] z company, score, match_type -``` - -### UWAGA (PostgreSQL): -- Gdy FTS się nie powiedzie, wykonywany jest `db.rollback()` przed fallbackiem -- Bez tego następuje błąd `InFailedSqlTransaction` - -## Chatbot AI (nordabiz_chat.py) - -### Konfiguracja: -- **Limit firm do AI:** 8 (zmienne w `_build_conversation_context`, linia ~312) -- **Historia wiadomości:** 10 ostatnich -- **Search:** używa `search_companies()` z SearchService - -## Testy jakości AI - -### Uruchomienie: -```bash -python run_ai_quality_tests.py -v # Verbose output -python run_ai_quality_tests.py -v -s # Verbose + save report -python run_ai_quality_tests.py -q # Quick (tylko high-priority) -``` - -### Przypadki testowe (`tests/ai_quality_test_cases.json`): -- 15 przypadków w 8 kategoriach -- Próg zaliczenia: 70% -- Kategorie: IT/Web, Services/Legal, Services/Accounting, Production/Metal, Construction, HVAC, Energy/Renewable, IT/Security +Szczegóły: `docs/DEVELOPMENT.md#chatbot-ai` ## Powiązane zasoby - **Źródło danych:** https://norda-biznes.info/czlonkowie -- **Monitoring:** Zabbix (do konfiguracji) - **Backup:** Proxmox Backup Server (VM snapshots) - **DNS wewnętrzny:** nordabiznes.inpi.local -## Kontakty +## Szablon profilu firmy -- **Projekt:** Norda Biznes Hub -- **Infrastruktura:** INPI (skills: proxmox-manager, dns-manager, npm-manager) - -## Szablon profilu firmy (company profile) - -### Zatwierdzone zmiany do wdrożenia - -Sekcje do **połączenia** (redukcja duplikatów): -1. **"O firmie" + "Profil działalności"** → jedna sekcja "O firmie" -2. **"Oferta i usługi" + "Słowa kluczowe"** → jedna sekcja "Usługi i kompetencje" -3. **"Wyróżniki" + "Wartości firmy"** → jedna sekcja "Wyróżniki" -4. **Blok "Jakość Danych"** → usunąć (badge przy nazwie wystarczy) - -### Sekcje które MUSZĄ pozostać - -- **Social Media (6 kafelków)** - pokazywać WSZYSTKIE platformy, także te bez profilu ("Brak profilu") - ważne by widzieć czego brakuje -- **Dane kontaktowe (sekcja z kartami)** - to docelowe miejsce na WSZYSTKIE dane kontaktowe firmy (adres, telefony, emaile, godziny otwarcia, itp.) - -### Docelowa struktura profilu (po optymalizacji) +### Docelowa struktura (po optymalizacji) ``` -1. Header (nazwa, kategoria, badge weryfikacji, krótki opis) -2. Pasek kontaktowy (www, email, telefon, lokalizacja) - szybki dostęp +1. Header (nazwa, kategoria, badge, krótki opis) +2. Pasek kontaktowy (www, email, telefon, lokalizacja) 3. O firmie (połączone opisy) 4. Usługi i kompetencje (połączone tagi) 5. Wyróżniki (połączone z wartościami) -6. Dane kontaktowe (pełne karty - główne miejsce na kontakt) -7. Informacje prawne i biznesowe (NIP, REGON, KRS, rok założenia) -8. Social Media (wszystkie 6 platform - widoczne braki) -9. Strona WWW (analiza techniczna) - zawsze na końcu +6. Dane kontaktowe (pełne karty) +7. Informacje prawne i biznesowe +8. Social Media (wszystkie 6 platform) +9. Strona WWW (analiza techniczna) ``` -### Szablon: templates/company_detail.html - -Plik do modyfikacji przy implementacji zmian. - -## Plan rozwoju - Aktualności - -### Social Media Audit (WDROŻONE) -**Status:** Wdrożone (2026-01-09) -**Panel:** `/admin/social-media` -**Funkcje:** -- Audyt profili Social Media firm (Facebook, Instagram, LinkedIn, YouTube, TikTok, Twitter) -- Weryfikacja aktywności profili (last_checked_at, followers_count) -- Raportowanie brakujących profili - -### Priorytet 1: Social Media Integration (Posts/Events) -**Status:** Planowane -**Cel:** Pobieranie postów i wydarzeń z Social Media firm - -**Źródła danych:** -- Facebook Pages firm członkowskich (posty, wydarzenia) -- LinkedIn Company Pages -- Google My Business (recenzje, posty) - -**Wymagania techniczne:** -- Facebook Graph API (wymaga App Review dla pages_read_engagement) -- LinkedIn Marketing API (wymaga partnera lub OAuth) -- Google Business Profile API - -**Typy zdarzeń do importu:** -- `social_post` - posty z social media -- `social_event` - wydarzenia z Facebooka -- `review` - nowe recenzje Google - -### Priorytet 2: News Monitoring (Google/Brave API) -**Status:** Wdrożone (2025-12-29) -**Źródła danych:** -- Wzmianki o firmach w mediach lokalnych/branżowych -- Artykuły prasowe -- Komunikaty branżowe - -**Wymagania techniczne:** -- Brave Search API (bezpłatny tier) LUB -- Google Custom Search API ($5/1000 queries) -- Cykliczne wyszukiwanie nazw firm - -**Typy zdarzeń do importu:** -- `news_mention` - wzmianka w mediach -- `press_release` - komunikat prasowy -- `award` - nagroda/wyróżnienie - -### Priorytet 3: Zarząd i Wspólnicy (rejestr.io) -**Status:** Planowane -**Cel:** Wyświetlanie osób powiązanych z firmą bezpośrednio na stronie profilu - -**Dane do pobrania z rejestr.io:** -- Zarząd (Prezes, Wiceprezes, Członkowie Zarządu) -- Prokurenci -- Wspólnicy z % udziałów -- Beneficjenci rzeczywiści -- Linki do profili osób (powiązania z innymi firmami) - -**Wymagania techniczne:** -- Tabela `company_people` (company_id, name, role, shares_percent, person_url) -- Scraper Playwright (już mamy bazę w `analyze_connections.py`) -- Sekcja w `company_detail.html` po "Informacje prawne i biznesowe" - -**Przykład wyświetlania:** -``` -👥 ZARZĄD I WSPÓLNICY -┌─────────────────────────────────────────┐ -│ 👔 Jan Kowalski - Prezes Zarządu │ -│ 👔 Anna Nowak - Członek Zarządu │ -│ 💼 Firma XYZ Sp. z o.o. - 60% udziałów │ -│ 💼 Jan Kowalski - 40% udziałów │ -└─────────────────────────────────────────┘ -``` - -**Korzyści:** -- Widoczne powiązania między firmami Norda Biznes -- Ułatwiony networking (kto zna kogo) -- Transparentność struktury właścicielskiej - -### Notatki implementacyjne -- Scraper powinien deduplikować wydarzenia (hash tytułu + daty) -- Moderacja: nowe wydarzenia jako "pending" do zatwierdzenia przez admina -- Rate limiting: max 100 requestów/dzień do zewnętrznych API +**Szablon:** `templates/company_detail.html` ## News Monitoring -### Opis funkcjonalności +System monitoringu wzmianek o firmach w mediach. Panel: `/admin/news` -System automatycznego monitoringu wzmianek o firmach Norda Biznes w mediach lokalnych i branżowych. +**Statusy:** `pending`, `approved`, `rejected` -### Tabela w bazie danych - -```sql -company_news ( - id SERIAL PRIMARY KEY, - company_id INTEGER REFERENCES companies(id), - title VARCHAR(500) NOT NULL, - description TEXT, - url VARCHAR(1000) NOT NULL, - source VARCHAR(200), -- nazwa portalu/medium - published_at TIMESTAMP, - news_type VARCHAR(50), -- news_mention, press_release, award - relevance_score FLOAT, -- 0.0-1.0 (AI scoring) - status VARCHAR(20) DEFAULT 'pending', -- pending, approved, rejected - moderated_by INTEGER, -- user_id admina - moderated_at TIMESTAMP, - rejection_reason TEXT, - created_at TIMESTAMP DEFAULT NOW(), - updated_at TIMESTAMP DEFAULT NOW(), - UNIQUE(company_id, url) -) -``` - -**Statusy newsów:** -- `pending` - oczekuje na moderację -- `approved` - zatwierdzony, widoczny na profilu firmy -- `rejected` - odrzucony (spam, nieistotny, duplikat) - -### Brave Search API Integration - -**Konfiguracja:** -- API Key w `.env`: `BRAVE_SEARCH_API_KEY` -- Endpoint: `https://api.search.brave.com/res/v1/news/search` -- Limit: 2000 req/miesiąc (free tier) - -**Parametry wyszukiwania:** -```python -params = { - "q": f'"{company_name}" OR "{nip}"', - "count": 10, - "freshness": "pw", # past week - "country": "pl", - "search_lang": "pl" -} -``` - -**Skrypt pobierania:** (do implementacji) -```bash -# TODO: Skrypt fetch_company_news.py wymaga implementacji -# cd /var/www/nordabiznes -# sudo -u www-data /var/www/nordabiznes/venv/bin/python3 scripts/fetch_company_news.py -``` - -### AI Filtering (Gemini) - -Filtracja wyników przez Google Gemini: -- Ocena relevance_score (0.0-1.0) -- Kategoryzacja news_type -- Wykrywanie duplikatów/spamu -- Automatyczne odrzucanie wyników < 0.3 relevance - -**Prompt systemu:** -``` -Oceń czy artykuł dotyczy działalności firmy {company_name}. -Zwróć JSON: {"relevance": 0.0-1.0, "type": "news_mention|press_release|award", "reason": "..."} -``` - -### Panel admina /admin/news - -**URL:** `/admin/news` -**Wymaga:** Zalogowany użytkownik z `is_admin=True` - -**Funkcje:** -- Lista newsów pending do moderacji -- Filtrowanie po firmie, statusie, dacie -- Zatwierdzanie/odrzucanie z powodem -- Podgląd oryginalnego artykułu -- Bulk actions (zatwierdź wszystkie z relevance > 0.8) - -### Sekcja Aktualności na profilu firmy - -**Lokalizacja:** `templates/company_detail.html` -**Warunek:** Tylko newsy ze statusem `approved` -**Sortowanie:** Po `published_at` DESC -**Limit:** 5 ostatnich newsów - -**Struktura wyświetlania:** -``` -AKTUALNOŚCI -├── [data] Tytuł artykułu (źródło) -│ Krótki opis... -│ [Czytaj więcej →] -└── [data] Kolejny artykuł... -``` - -### System powiadomień - -**Endpoint:** `/api/notifications` -**Zwraca:** JSON z listą powiadomień użytkownika - -**Typy powiadomień:** -- `new_news` - nowy news o obserwowanej firmie (dla zalogowanych) -- `news_approved` - news firmy użytkownika został zatwierdzony -- `news_rejected` - news firmy użytkownika został odrzucony - -**Struktura odpowiedzi:** -```json -{ - "notifications": [ - { - "id": 1, - "type": "new_news", - "message": "Nowa wzmianka o PIXLAB", - "url": "/company/pixlab-sp-z-o-o#news", - "created_at": "2025-12-29T10:30:00", - "read": false - } - ], - "unread_count": 3 -} -``` - -### Skrypty i cron (do implementacji) - -```bash -# TODO: Skrypty do pobierania newsów wymagają implementacji -# Planowane komendy: -# python scripts/fetch_company_news.py --all -# python scripts/fetch_company_news.py --company pixlab-sp-z-o-o - -# Cron job (do skonfigurowania po implementacji) -# 0 */6 * * * cd /var/www/nordabiznes && /var/www/nordabiznes/venv/bin/python3 scripts/fetch_company_news.py --all >> /var/log/nordabiznes/news_fetch.log 2>&1 -``` +Szczegóły: `docs/DEVELOPMENT.md#news-monitoring` ## ZOP Kaszubia News (ZOPK) -### Opis +System monitoringu newsów projektu **Zielony Okręg Przemysłowy Kaszubia**. +Panel: `/admin/zopk/news` -System monitoringu newsów związanych z projektem **Zielony Okręg Przemysłowy Kaszubia**. -Panel admina: `/admin/zopk/news` +### Tematy istotne +- Zielony Okręg Przemysłowy Kaszubia +- Elektrownia jądrowa (Lubiatowo-Kopalino) +- Offshore wind Bałtyk (Baltic Power, Baltica) +- Via Pomerania, Droga Czerwona +- Kongsberg (inwestycje w Rumi) +- Izba Przedsiębiorców NORDA -### Tematy ZOP Kaszubia (istotne) - -- **Zielony Okręg Przemysłowy Kaszubia** - główny projekt -- **Elektrownia jądrowa na Pomorzu** - Lubiatowo-Kopalino -- **Offshore wind Bałtyk** - farmy wiatrowe, Baltic Power, Baltica -- **Via Pomerania** - droga ekspresowa Ustka-Bydgoszcz -- **Droga Czerwona** - połączenie z Portem Gdynia -- **Kongsberg** - norweskie inwestycje zbrojeniowe w Rumi -- **Pakt Bezpieczeństwa Pomorze Środkowe** - MON -- **Izba Przedsiębiorców NORDA** - lokalne organizacje biznesowe - -### Tematy NIEZWIĄZANE (do odrzucenia) - -- Turystyka na Kaszubach (kuligi, lodowiska, hotele) -- Polityka ogólnopolska (Ziobro, polexit) -- Inne regiony Polski (Śląsk, Lubuskie, Małopolska) -- Wypadki i wydarzenia kryminalne -- Clickbait i lifestyle +### Tematy do odrzucenia +- Turystyka na Kaszubach +- Polityka ogólnopolska +- Inne regiony Polski +- Wypadki, clickbait ### Reguły auto-approve (WAŻNE!) -**Próg auto-approve: score >= 3** (verified 2026-01-15) +**Próg: score >= 3** -| Score | Status | Opis | -|-------|--------|------| -| 1-2 | `pending` | Wymaga ręcznej moderacji | -| 3-5 | `auto_approved` | Automatycznie zatwierdzony | +| Score | Status | +|-------|--------| +| 1-2 | `pending` | +| 3-5 | `auto_approved` | **Plik:** `zopk_news_service.py` (linie 890, 1124, 1145) -### Tabela zopk_news +## Social Media -```sql -zopk_news ( - id, title, url, description, - source_name, source_domain, source_type, - ai_relevance_score INTEGER, -- 1-5 gwiazdek - status VARCHAR(20), -- pending, auto_approved, approved, rejected - confidence_score, source_count, - created_at, updated_at -) -``` +Panel audytu: `/admin/social-media` +Platformy: Facebook, Instagram, LinkedIn, YouTube, TikTok, Twitter -## Social Media - Stan aktualny +Szczegóły: `docs/DEVELOPMENT.md#social-media` -### Statystyki (2025-12-29) +## Audyt SEO -| Platforma | Liczba firm | Pokrycie | -|-----------|-------------|----------| -| Facebook | 39 | 49% | -| Instagram | 26 | 33% | -| LinkedIn | 22 | 28% | -| YouTube | 17 | 21% | -| Twitter/X | 7 | 9% | -| TikTok | 4 | 5% | +Panel: `/admin/seo` +API: Google PageSpeed Insights -**Łącznie:** 115 profili dla 53 firm (66% pokrycia) -**Firmy bez Social Media:** 27 +Szczegóły: `docs/DEVELOPMENT.md#audyt-seo` -### Tabela w bazie danych +## Plan rozwoju -```sql -company_social_media ( - id, company_id, platform, url, - verified_at, source, is_valid, - last_checked_at, check_status, - page_name, followers_count, - created_at, updated_at -) -``` - -**Platformy:** facebook, instagram, youtube, linkedin, tiktok, twitter - -### Skrypty aktualizacji - -```bash -# Aktualizacja Social Media z pliku JSON -cd /var/www/nordabiznes -sudo -u www-data /var/www/nordabiznes/venv/bin/python3 update_social_media.py --dry-run # Test -sudo -u www-data /var/www/nordabiznes/venv/bin/python3 update_social_media.py # Produkcja -``` - -**Pliki:** -- `social_media_found.json` - wyniki wyszukiwania (źródło danych) -- `update_social_media.py` - skrypt aktualizujący bazę - -### Firmy z najlepszym pokryciem Social Media - -1. **PORTA KMI** - Facebook, Instagram, YouTube, LinkedIn (4 platformy, 124K FB fans) -2. **Rumia Invest Park** - Facebook, Instagram, YouTube, LinkedIn, Twitter (5 platform) -3. **GRAAL** - Facebook, Instagram, YouTube, LinkedIn (4 platformy) -4. **Chopin Telewizja Kablowa** - Facebook, Instagram, YouTube, Twitter (4 platformy) -5. **Hotel SPA Wieniawa** - Facebook, Instagram, YouTube, TikTok (4 platformy) - -### Firmy bez Social Media (do uzupełnienia) - -SIM Rumia, Rubinsolar, KORNIX, KBMS, Semerling Security, ARD Invest, AMA, -Jubiler Agat, P&P, Progress Optima, Ampery, Bibrokers, CoolAir, Joker, -KAMMET, Alumech, Litwic&Litwic, Orlex MG, Pro-Invest, Round Two, SCROL, -ALMARES, Pucka Gospodarka Komunalna, Hebel Masiak, Lenap Hale, MKonsult, Portal - -## Audyt SEO (Panel /admin/seo) - -### Opis funkcjonalności - -System audytu SEO stron internetowych firm członkowskich Norda Biznes. -Wykorzystuje Google PageSpeed Insights API do analizy wydajności i jakości stron. - -**URL panelu:** `/admin/seo` -**Wymaga:** Zalogowany użytkownik z `is_admin=True` - -### Konfiguracja API - -**Google PageSpeed Insights API:** -- API Key w `.env`: `GOOGLE_PAGESPEED_API_KEY` -- Projekt Google Cloud: NORDABIZNES (`gen-lang-client-0540794446`) -- Limit: 25,000 zapytań/dzień (free tier) -- Endpoint: `https://www.googleapis.com/pagespeedonline/v5/runPagespeed` - -**Klucz API:** -- **Nazwa w Google Cloud:** `Page SPEED SEO Audit v2` -- **Wartość:** Przechowywany w `.env` (GOOGLE_PAGESPEED_API_KEY) -- **UWAGA:** Nigdy nie commituj kluczy API do repozytorium! - -### Metryki audytu - -| Metryka | Źródło | Skala | -|---------|--------|-------| -| WYNIK SEO | PageSpeed Insights | 0-100 | -| PERFORMANCE | PageSpeed Insights | 0-100 | -| DOSTĘPNOŚĆ | PageSpeed Insights | 0-100 | -| BEST PRACTICES | PageSpeed Insights | 0-100 | - -**Interpretacja wyników:** -- 90-100 (zielony) - Doskonały -- 50-89 (żółty) - Wymaga poprawy -- 0-49 (czerwony) - Słaby - -### Skrypty SEO - -```bash -# Audyt pojedynczej firmy -cd /var/www/nordabiznes/scripts -python seo_audit.py --company-id 26 - -# Audyt wsadowy (batch) -python seo_audit.py --batch 1-10 - -# Audyt wszystkich firm -python seo_audit.py --all - -# Tryb testowy (bez zapisu) -python seo_audit.py --company-id 26 --dry-run -``` - -### WAŻNE - Połączenie z bazą danych - -Skrypty w `scripts/` muszą używać **localhost (127.0.0.1)** do połączenia z PostgreSQL: - -```python -# PRAWIDŁOWO (hasło z .env): -DATABASE_URL = 'postgresql://nordabiz_app:@127.0.0.1:5432/nordabiz' - -# BŁĘDNIE (PostgreSQL nie akceptuje zewnętrznych połączeń): -DATABASE_URL = 'postgresql://nordabiz_app:@10.22.68.249:5432/nordabiz' -``` - -**UWAGA:** Hasło do bazy jest w `.env` na produkcji. NIE commituj haseł do repozytorium! - -**Pliki z konfiguracją bazy:** -- `scripts/seo_audit.py` (linia ~79) -- `scripts/seo_report_generator.py` (linia ~47) -- `scripts/social_media_audit.py` (linia ~53) - -### Tabela w bazie danych - -```sql -seo_metrics ( - id SERIAL PRIMARY KEY, - company_id INTEGER REFERENCES companies(id), - url VARCHAR(500), - seo_score INTEGER, - performance_score INTEGER, - accessibility_score INTEGER, - best_practices_score INTEGER, - pwa_score INTEGER, - audit_data JSONB, -- pełne dane z PageSpeed - audited_at TIMESTAMP, - created_at TIMESTAMP DEFAULT NOW(), - updated_at TIMESTAMP DEFAULT NOW() -) -``` - -### UI - Stylizowane modale - -Panel SEO używa niestandardowych modali (zamiast natywnych `confirm()`/`alert()`): -- Modal potwierdzenia audytu z ikoną ostrzeżenia -- Modal informacyjny o błędach -- Animacje CSS (fade in/out) - -**Lokalizacja kodu:** `templates/admin_seo_dashboard.html` - -## Planowane funkcjonalności (Backlog) - -### Priorytet 4: System rekomendacji i zdjęć -**Status:** Planowane -**Cel:** Umożliwienie firmom członkowskim wzajemnego polecania się oraz prezentacji zdjęć - -**Funkcje:** -- Rekomendacje między firmami (kto poleca kogo) -- Galeria zdjęć firmy (realizacje, zespół, biuro) -- Wyświetlanie na profilu firmy - -### Priorytet 5: Status członkostwa i płatności -**Status:** Planowane -**Cel:** Śledzenie statusu członkostwa i składek miesięcznych - -**Funkcje:** -- Status członka (aktywny, zawieszony, były członek) -- Informacja o opłaconych składkach -- Historia płatności -- Przypomnienia o zaległościach (dla admina) - -**Tabela `membership_fees`:** -```sql -membership_fees ( - id SERIAL PRIMARY KEY, - company_id INTEGER REFERENCES companies(id), - period_start DATE NOT NULL, -- początek okresu (np. 2026-01-01) - period_end DATE NOT NULL, -- koniec okresu (np. 2026-01-31) - amount DECIMAL(10,2) NOT NULL, -- kwota składki - status VARCHAR(20) DEFAULT 'pending', -- pending, paid, overdue - paid_at TIMESTAMP, - payment_method VARCHAR(50), -- przelew, gotówka - notes TEXT, - created_at TIMESTAMP DEFAULT NOW() -) -``` - -## Forma prawna Norda Biznes - -### Stan obecny -- **Forma:** OPP (Organizacja Pożytku Publicznego) -- **Typ:** Stowarzyszenie non-profit - -### Planowana transformacja -- **Docelowa forma:** Działalność gospodarcza (przy Izbie) -- **Cel:** Możliwość pozyskiwania dofinansowań (granty, projekty UE) -- **Korzyści:** - - Dostęp do funduszy na rozwój platformy - - Możliwość świadczenia płatnych usług - - Elastyczność finansowa - -## Strategia monetyzacji - -### Model 3-tier Pricing (Kotwiczenie ceny) - -**Strategia:** Trzy poziomy cenowe z zastosowaniem psychologii kotwiczenia ceny (Price Anchoring). -Najwyższy poziom służy jako **kotwica** - sprawia że środkowy wydaje się atrakcyjny i jest docelowy. - -| Poziom | Nazwa | Cena/mies. | Cel strategiczny | -|--------|-------|------------|------------------| -| **1** | Basic | ~49 zł | Entry point, ograniczone funkcje | -| **2** | Premium | ~99 zł | **DOCELOWY** - rekomendowany, najlepsza wartość | -| **3** | Enterprise | ~199 zł | **KOTWICA** - premium, pełny dostęp | - -**Wyjątek:** Członkowie Izby NORDA płacący składki (~200 zł/mies.) mają specjalny status - dostęp Premium za symboliczne 1 zł. - -### Psychologia 3-tier Pricing - -- Ludzie naturalnie wybierają środkową opcję (efekt kompromisu) -- Wysoka cena kotwicy sprawia że środkowa wydaje się "okazją" -- Niska cena Basic sprawia że użytkownik czuje "upgrade jest wart dopłaty" -- Firmy stosujące 3-tier widzą ~30% wzrost przychodów -- Slack: dodanie Enterprise tier zwiększyło konwersję na Professional o 28% - -### Matryca dostępu do funkcji - -| Funkcja | Basic | Premium | Enterprise | -|---------|:-----:|:-------:|:----------:| -| Katalog firm | ✅ | ✅ | ✅ | -| Profil firmy | ✅ | ✅ | ✅ | -| Forum | ❌ | ✅ | ✅ | -| Kalendarz wydarzeń | ❌ | ✅ | ✅ | -| Chat AI (NordaGPT) | ❌ | ✅ | ✅ | -| **Raporty podstawowe** | ❌ | ✅ | ✅ | -| **Raporty zaawansowane** | ❌ | ❌ | ✅ | -| Eksport danych (CSV/PDF) | ❌ | ❌ | ✅ | -| API dostęp | ❌ | ❌ | ✅ | -| Priorytetowe wsparcie | ❌ | ❌ | ✅ | - -### Implementacja techniczna (przyszłość) - -```python -# Model User - nowe pola -class User(Base): - # ... - subscription_tier = Column(String(20), default='basic') # basic, premium, enterprise - subscription_expires_at = Column(DateTime) - is_norda_member = Column(Boolean, default=False) # Członek Izby = specjalny status - -# Dekorator kontroli dostępu -def requires_tier(min_tier): - def decorator(f): - @wraps(f) - def wrapped(*args, **kwargs): - tiers = ['basic', 'premium', 'enterprise'] - user_tier_idx = tiers.index(current_user.subscription_tier) - required_idx = tiers.index(min_tier) - if user_tier_idx < required_idx: - flash(f'Ta funkcja wymaga konta {min_tier.title()}.', 'warning') - return redirect(url_for('pricing')) - return f(*args, **kwargs) - return wrapped - return decorator - -# Użycie -@app.route('/raporty/zaawansowane') -@login_required -@requires_tier('enterprise') -def advanced_reports(): - ... -``` - -### Raporty - podział według poziomu - -**Raporty podstawowe (Premium+):** -- Staż członkostwa w Izbie NORDA -- Pokrycie Social Media -- Struktura branżowa - -**Raporty zaawansowane (Enterprise only):** -- Ranking SEO -- Mapa lokalizacji -- Sieć rekomendacji -- Aktywność w wydarzeniach +Roadmap, priorytety i strategia monetyzacji: `docs/ROADMAP.md` diff --git a/docs/CREDENTIALS.md b/docs/CREDENTIALS.md new file mode 100644 index 0000000..da1a309 --- /dev/null +++ b/docs/CREDENTIALS.md @@ -0,0 +1,168 @@ +# NordaBiz - Zarządzanie danymi uwierzytelniającymi + +Ten dokument zawiera szczegółowe zasady zarządzania hasłami, kluczami API i innymi wrażliwymi danymi. +Główne instrukcje znajdują się w [CLAUDE.md](../CLAUDE.md). + +--- + +## KRYTYCZNE: Nigdy nie umieszczaj haseł w kodzie! + +**NIGDY nie umieszczaj haseł i kluczy API bezpośrednio w kodzie źródłowym!** + +Jest to krytyczna podatność bezpieczeństwa (CWE-798: Use of Hard-coded Credentials). Narusza standardy bezpieczeństwa i może prowadzić do kompromitacji systemu jeśli repozytorium zostanie ujawnione. + +--- + +## Zasady obowiązkowe + +### 1. Używaj zmiennych środowiskowych + +```python +# ✅ PRAWIDŁOWO: +DATABASE_URL = os.getenv('DATABASE_URL') +API_KEY = os.getenv('GOOGLE_PAGESPEED_API_KEY') + +# ❌ BŁĘDNIE - NIGDY TAK NIE RÓB: +DATABASE_URL = 'postgresql://user:password123@localhost/db' +API_KEY = 'AIzaSyAbc123...' +``` + +### 2. Wartości domyślne jako bezpieczne placeholdery + +```python +# ✅ PRAWIDŁOWO - wartość domyślna która wymusi konfigurację .env: +DATABASE_URL = os.getenv('DATABASE_URL', 'postgresql://user:CHANGE_ME@localhost/nordabiz') + +# ❌ BŁĘDNIE - wartość produkcyjna jako fallback: +DATABASE_URL = os.getenv('DATABASE_URL', 'postgresql://user:RealPassword@10.22.68.249/nordabiz') +``` + +### 3. Przechowuj credentials w plikach .env + +| Środowisko | Lokalizacja | +|------------|-------------| +| Produkcja | `/var/www/nordabiznes/.env` | +| Development | `.env` w katalogu projektu | +| Wzorzec | `.env.example` (bez prawdziwych wartości!) | + +--- + +## Wymagane zmienne środowiskowe + +| Zmienna | Cel | Przykład | +|---------|-----|----------| +| `DATABASE_URL` | Połączenie PostgreSQL dla skryptów Python | `postgresql://user:pass@127.0.0.1:5432/nordabiz` | +| `PGPASSWORD` | Hasło PostgreSQL dla skryptów shell | `export PGPASSWORD='your_password'` | +| `GOOGLE_PAGESPEED_API_KEY` | API Key Google PageSpeed | `AIzaSy...` | +| `BRAVE_SEARCH_API_KEY` | API Key Brave Search | `BSA...` | +| `GEMINI_API_KEY` | API Key Google Gemini AI | `AIzaSy...` | + +--- + +## Skrypty shell - sprawdzanie zmiennych + +```bash +# ✅ PRAWIDŁOWO: +if [ -z "$PGPASSWORD" ]; then + echo "ERROR: PGPASSWORD not set" + exit 1 +fi +psql -h localhost -U nordabiz_app -d nordabiz + +# ❌ BŁĘDNIE: +PGPASSWORD='hardcoded_password' psql -h localhost -U nordabiz_app -d nordabiz +``` + +--- + +## NIGDY nie commituj plików z credentials + +- `.env` jest w `.gitignore` +- Sprawdzaj przed commitem: `git diff` i `git status` +- W razie wątpliwości: `git log -p | grep -i password` + +--- + +## Co zrobić jeśli przypadkowo scommitujesz hasło + +⚠️ **NATYCHMIAST zmień hasło w bazie/API** + +Powód: Nie wystarczy usunąć z najnowszego commita - hasło pozostaje w historii Git. + +### Opcje naprawy: + +1. **Zmiana hasła** (ZALECANE) + - Natychmiast zmień hasło we wszystkich systemach + - Traktuj stare hasło jako skompromitowane + - Najprostsze i najbezpieczniejsze rozwiązanie + +2. **Przepisanie historii Git** (SKOMPLIKOWANE) + - `git filter-branch` lub `BFG Repo-Cleaner` + - Wymaga force push do wszystkich remotów + - Może powodować problemy dla innych deweloperów + +--- + +## Wyjątki - kiedy dozwolone jest hasło w kodzie + +| Dozwolone | Niedozwolone | +|-----------|--------------| +| ✅ Pliki dokumentacji (CLAUDE.md, README) | ⛔ Pliki Python (.py) | +| ✅ `.env.example` z placeholderami | ⛔ Skrypty shell (.sh) | +| | ⛔ Pliki JavaScript (.js) | + +--- + +## Weryfikacja przed wdrożeniem + +```bash +# Sprawdź czy nie ma hardcoded credentials w kodzie: +grep -r "PGPASSWORD=" --include="*.sh" . +grep -r "postgresql://.*:.*@" --include="*.py" . | grep -v "CHANGE_ME" | grep -v ".example" | grep -v "PASSWORD" + +# Oczekiwany wynik: brak znalezisk (lub tylko w dokumentacji/placeholderach) +``` + +--- + +## Bezpieczne przechowywanie + +### Lokalizacje plików .env + +``` +/var/www/nordabiznes/.env # Produkcja (PROD) +./nordabiz/.env # Development (DEV) +``` + +### Uprawnienia plików + +```bash +# Tylko właściciel może czytać plik .env +chmod 600 /var/www/nordabiznes/.env +chown www-data:www-data /var/www/nordabiznes/.env +``` + +--- + +## Konfiguracja IDE + +### VS Code - wykluczenie .env z wyszukiwania + +```json +// .vscode/settings.json +{ + "search.exclude": { + "**/.env": true + } +} +``` + +### Git - ignorowanie .env + +```gitignore +# .gitignore +.env +.env.local +.env.*.local +*.env +``` diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md new file mode 100644 index 0000000..6407e5a --- /dev/null +++ b/docs/DEVELOPMENT.md @@ -0,0 +1,272 @@ +# NordaBiz - Dokumentacja deweloperska + +Ten dokument zawiera szczegółowe informacje techniczne dla deweloperów. +Główne instrukcje znajdują się w [CLAUDE.md](../CLAUDE.md). + +--- + +## SearchService (search_service.py) + +Unified search dla chatbota AI i wyszukiwarki `/search`. + +### Funkcje +- **NIP/REGON lookup** - bezpośrednie wyszukiwanie po identyfikatorach +- **Synonym expansion** - rozszerzenie słów kluczowych (np. "strony" → www, web, portal) +- **PostgreSQL FTS** - full-text search z tsvector (DEV i PROD) +- **SQLite fallback** - keyword scoring (tylko jako fallback, nieużywane) +- **Fuzzy matching** - pg_trgm dla literówek (gdy dostępne) + +### Scoring +| Pole | Punkty | +|------|--------| +| Nazwa firmy | +10 | +| Opis | +5 | +| Usługi | +8 | +| Kompetencje | +7 | +| Miasto | +3 | + +### Użycie +```python +from search_service import search_companies +results = search_companies(db, "strony www", limit=10) +# Zwraca List[SearchResult] z company, score, match_type +``` + +### UWAGA (PostgreSQL) +- Gdy FTS się nie powiedzie, wykonywany jest `db.rollback()` przed fallbackiem +- Bez tego następuje błąd `InFailedSqlTransaction` + +--- + +## Chatbot AI (nordabiz_chat.py) + +### Konfiguracja +- **Limit firm do AI:** 8 (zmienne w `_build_conversation_context`, linia ~312) +- **Historia wiadomości:** 10 ostatnich +- **Search:** używa `search_companies()` z SearchService + +--- + +## Testy jakości AI + +### Uruchomienie +```bash +python run_ai_quality_tests.py -v # Verbose output +python run_ai_quality_tests.py -v -s # Verbose + save report +python run_ai_quality_tests.py -q # Quick (tylko high-priority) +``` + +### Przypadki testowe (`tests/ai_quality_test_cases.json`) +- 15 przypadków w 8 kategoriach +- Próg zaliczenia: 70% +- Kategorie: IT/Web, Services/Legal, Services/Accounting, Production/Metal, Construction, HVAC, Energy/Renewable, IT/Security + +--- + +## News Monitoring + +### Brave Search API Integration + +**Konfiguracja:** +- API Key w `.env`: `BRAVE_SEARCH_API_KEY` +- Endpoint: `https://api.search.brave.com/res/v1/news/search` +- Limit: 2000 req/miesiąc (free tier) + +**Parametry wyszukiwania:** +```python +params = { + "q": f'"{company_name}" OR "{nip}"', + "count": 10, + "freshness": "pw", # past week + "country": "pl", + "search_lang": "pl" +} +``` + +### AI Filtering (Gemini) + +Filtracja wyników przez Google Gemini: +- Ocena relevance_score (0.0-1.0) +- Kategoryzacja news_type +- Wykrywanie duplikatów/spamu +- Automatyczne odrzucanie wyników < 0.3 relevance + +**Prompt systemu:** +``` +Oceń czy artykuł dotyczy działalności firmy {company_name}. +Zwróć JSON: {"relevance": 0.0-1.0, "type": "news_mention|press_release|award", "reason": "..."} +``` + +### Panel admina /admin/news + +**URL:** `/admin/news` +**Wymaga:** Zalogowany użytkownik z `is_admin=True` + +**Funkcje:** +- Lista newsów pending do moderacji +- Filtrowanie po firmie, statusie, dacie +- Zatwierdzanie/odrzucanie z powodem +- Podgląd oryginalnego artykułu +- Bulk actions (zatwierdź wszystkie z relevance > 0.8) + +### Sekcja Aktualności na profilu firmy + +**Lokalizacja:** `templates/company_detail.html` +**Warunek:** Tylko newsy ze statusem `approved` +**Sortowanie:** Po `published_at` DESC +**Limit:** 5 ostatnich newsów + +**Struktura wyświetlania:** +``` +AKTUALNOŚCI +├── [data] Tytuł artykułu (źródło) +│ Krótki opis... +│ [Czytaj więcej →] +└── [data] Kolejny artykuł... +``` + +### System powiadomień + +**Endpoint:** `/api/notifications` +**Zwraca:** JSON z listą powiadomień użytkownika + +**Typy powiadomień:** +- `new_news` - nowy news o obserwowanej firmie (dla zalogowanych) +- `news_approved` - news firmy użytkownika został zatwierdzony +- `news_rejected` - news firmy użytkownika został odrzucony + +**Struktura odpowiedzi:** +```json +{ + "notifications": [ + { + "id": 1, + "type": "new_news", + "message": "Nowa wzmianka o PIXLAB", + "url": "/company/pixlab-sp-z-o-o#news", + "created_at": "2025-12-29T10:30:00", + "read": false + } + ], + "unread_count": 3 +} +``` + +--- + +## Audyt SEO (Panel /admin/seo) + +### Opis + +System audytu SEO stron internetowych firm członkowskich Norda Biznes. +Wykorzystuje Google PageSpeed Insights API do analizy wydajności i jakości stron. + +**URL panelu:** `/admin/seo` +**Wymaga:** Zalogowany użytkownik z `is_admin=True` + +### Konfiguracja API + +**Google PageSpeed Insights API:** +- API Key w `.env`: `GOOGLE_PAGESPEED_API_KEY` +- Projekt Google Cloud: NORDABIZNES (`gen-lang-client-0540794446`) +- Limit: 25,000 zapytań/dzień (free tier) +- Endpoint: `https://www.googleapis.com/pagespeedonline/v5/runPagespeed` + +**Klucz API:** +- **Nazwa w Google Cloud:** `Page SPEED SEO Audit v2` +- **Wartość:** Przechowywany w `.env` (GOOGLE_PAGESPEED_API_KEY) + +### Metryki audytu + +| Metryka | Źródło | Skala | +|---------|--------|-------| +| WYNIK SEO | PageSpeed Insights | 0-100 | +| PERFORMANCE | PageSpeed Insights | 0-100 | +| DOSTĘPNOŚĆ | PageSpeed Insights | 0-100 | +| BEST PRACTICES | PageSpeed Insights | 0-100 | + +**Interpretacja wyników:** +- 90-100 (zielony) - Doskonały +- 50-89 (żółty) - Wymaga poprawy +- 0-49 (czerwony) - Słaby + +### Skrypty SEO + +```bash +# Audyt pojedynczej firmy +cd /var/www/nordabiznes/scripts +python seo_audit.py --company-id 26 + +# Audyt wsadowy (batch) +python seo_audit.py --batch 1-10 + +# Audyt wszystkich firm +python seo_audit.py --all + +# Tryb testowy (bez zapisu) +python seo_audit.py --company-id 26 --dry-run +``` + +### WAŻNE - Połączenie z bazą danych + +Skrypty w `scripts/` muszą używać **localhost (127.0.0.1)** do połączenia z PostgreSQL: + +```python +# PRAWIDŁOWO (hasło z .env): +DATABASE_URL = 'postgresql://nordabiz_app:@127.0.0.1:5432/nordabiz' + +# BŁĘDNIE (PostgreSQL nie akceptuje zewnętrznych połączeń): +DATABASE_URL = 'postgresql://nordabiz_app:@10.22.68.249:5432/nordabiz' +``` + +**Pliki z konfiguracją bazy:** +- `scripts/seo_audit.py` (linia ~79) +- `scripts/seo_report_generator.py` (linia ~47) +- `scripts/social_media_audit.py` (linia ~53) + +### UI - Stylizowane modale + +Panel SEO używa niestandardowych modali (zamiast natywnych `confirm()`/`alert()`): +- Modal potwierdzenia audytu z ikoną ostrzeżenia +- Modal informacyjny o błędach +- Animacje CSS (fade in/out) + +**Lokalizacja kodu:** `templates/admin_seo_dashboard.html` + +--- + +## Social Media + +### Skrypty aktualizacji + +```bash +# Aktualizacja Social Media z pliku JSON +cd /var/www/nordabiznes +sudo -u www-data /var/www/nordabiznes/venv/bin/python3 update_social_media.py --dry-run # Test +sudo -u www-data /var/www/nordabiznes/venv/bin/python3 update_social_media.py # Produkcja +``` + +**Pliki:** +- `social_media_found.json` - wyniki wyszukiwania (źródło danych) +- `update_social_media.py` - skrypt aktualizujący bazę + +**Platformy:** facebook, instagram, youtube, linkedin, tiktok, twitter + +--- + +## Skrypty danych + +### Import (wykonywać kolejno) +```bash +python import_norda_companies.py # Batch 1 (56 firm) +python import_norda_batch2.py # Batch 2 +python import_norda_batch3.py # Batch 3 +python import_norda_batch4.py # Batch 4 (9 firm) +python import_norda_batch5.py # Batch 5 (8 firm) +``` + +### Weryfikacja +```bash +python verify_all_companies_data.py # Raport jakości danych +python fix_krs_verification.py # Weryfikacja KRS +``` diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md new file mode 100644 index 0000000..8c02f12 --- /dev/null +++ b/docs/ROADMAP.md @@ -0,0 +1,223 @@ +# NordaBiz - Plan rozwoju i monetyzacja + +Ten dokument zawiera plany rozwoju projektu i strategię monetyzacji. +Główne instrukcje znajdują się w [CLAUDE.md](../CLAUDE.md). + +--- + +## Status wdrożonych funkcjonalności + +| Funkcjonalność | Status | Data | +|----------------|--------|------| +| Social Media Audit | ✅ Wdrożone | 2026-01-09 | +| News Monitoring | ✅ Wdrożone | 2025-12-29 | +| Katalog firm | ✅ Wdrożone | 2025-11-23 | +| Chat AI (NordaGPT) | ✅ Wdrożone | 2025-11-23 | + +--- + +## Priorytet 1: Social Media Integration (Posts/Events) + +**Status:** Planowane +**Cel:** Pobieranie postów i wydarzeń z Social Media firm + +### Źródła danych +- Facebook Pages firm członkowskich (posty, wydarzenia) +- LinkedIn Company Pages +- Google My Business (recenzje, posty) + +### Wymagania techniczne +- Facebook Graph API (wymaga App Review dla pages_read_engagement) +- LinkedIn Marketing API (wymaga partnera lub OAuth) +- Google Business Profile API + +### Typy zdarzeń do importu +- `social_post` - posty z social media +- `social_event` - wydarzenia z Facebooka +- `review` - nowe recenzje Google + +--- + +## Priorytet 2: News Monitoring (Google/Brave API) + +**Status:** ✅ Wdrożone (2025-12-29) + +### Źródła danych +- Wzmianki o firmach w mediach lokalnych/branżowych +- Artykuły prasowe +- Komunikaty branżowe + +### Typy zdarzeń +- `news_mention` - wzmianka w mediach +- `press_release` - komunikat prasowy +- `award` - nagroda/wyróżnienie + +--- + +## Priorytet 3: Zarząd i Wspólnicy (rejestr.io) + +**Status:** Planowane +**Cel:** Wyświetlanie osób powiązanych z firmą bezpośrednio na stronie profilu + +### Dane do pobrania z rejestr.io +- Zarząd (Prezes, Wiceprezes, Członkowie Zarządu) +- Prokurenci +- Wspólnicy z % udziałów +- Beneficjenci rzeczywiści +- Linki do profili osób (powiązania z innymi firmami) + +### Wymagania techniczne +- Tabela `company_people` (company_id, name, role, shares_percent, person_url) +- Scraper Playwright (już mamy bazę w `analyze_connections.py`) +- Sekcja w `company_detail.html` po "Informacje prawne i biznesowe" + +### Przykład wyświetlania +``` +👥 ZARZĄD I WSPÓLNICY +┌─────────────────────────────────────────┐ +│ 👔 Jan Kowalski - Prezes Zarządu │ +│ 👔 Anna Nowak - Członek Zarządu │ +│ 💼 Firma XYZ Sp. z o.o. - 60% udziałów │ +│ 💼 Jan Kowalski - 40% udziałów │ +└─────────────────────────────────────────┘ +``` + +### Korzyści +- Widoczne powiązania między firmami Norda Biznes +- Ułatwiony networking (kto zna kogo) +- Transparentność struktury właścicielskiej + +--- + +## Priorytet 4: System rekomendacji i zdjęć + +**Status:** Planowane +**Cel:** Umożliwienie firmom członkowskim wzajemnego polecania się oraz prezentacji zdjęć + +### Funkcje +- Rekomendacje między firmami (kto poleca kogo) +- Galeria zdjęć firmy (realizacje, zespół, biuro) +- Wyświetlanie na profilu firmy + +--- + +## Priorytet 5: Status członkostwa i płatności + +**Status:** Planowane +**Cel:** Śledzenie statusu członkostwa i składek miesięcznych + +### Funkcje +- Status członka (aktywny, zawieszony, były członek) +- Informacja o opłaconych składkach +- Historia płatności +- Przypomnienia o zaległościach (dla admina) + +--- + +## Notatki implementacyjne + +- Scraper powinien deduplikować wydarzenia (hash tytułu + daty) +- Moderacja: nowe wydarzenia jako "pending" do zatwierdzenia przez admina +- Rate limiting: max 100 requestów/dzień do zewnętrznych API + +--- + +## Forma prawna Norda Biznes + +### Stan obecny +- **Forma:** OPP (Organizacja Pożytku Publicznego) +- **Typ:** Stowarzyszenie non-profit + +### Planowana transformacja +- **Docelowa forma:** Działalność gospodarcza (przy Izbie) +- **Cel:** Możliwość pozyskiwania dofinansowań (granty, projekty UE) +- **Korzyści:** + - Dostęp do funduszy na rozwój platformy + - Możliwość świadczenia płatnych usług + - Elastyczność finansowa + +--- + +## Strategia monetyzacji + +### Model 3-tier Pricing (Kotwiczenie ceny) + +**Strategia:** Trzy poziomy cenowe z zastosowaniem psychologii kotwiczenia ceny (Price Anchoring). +Najwyższy poziom służy jako **kotwica** - sprawia że środkowy wydaje się atrakcyjny i jest docelowy. + +| Poziom | Nazwa | Cena/mies. | Cel strategiczny | +|--------|-------|------------|------------------| +| **1** | Basic | ~49 zł | Entry point, ograniczone funkcje | +| **2** | Premium | ~99 zł | **DOCELOWY** - rekomendowany, najlepsza wartość | +| **3** | Enterprise | ~199 zł | **KOTWICA** - premium, pełny dostęp | + +**Wyjątek:** Członkowie Izby NORDA płacący składki (~200 zł/mies.) mają specjalny status - dostęp Premium za symboliczne 1 zł. + +### Psychologia 3-tier Pricing + +- Ludzie naturalnie wybierają środkową opcję (efekt kompromisu) +- Wysoka cena kotwicy sprawia że środkowa wydaje się "okazją" +- Niska cena Basic sprawia że użytkownik czuje "upgrade jest wart dopłaty" +- Firmy stosujące 3-tier widzą ~30% wzrost przychodów +- Slack: dodanie Enterprise tier zwiększyło konwersję na Professional o 28% + +### Matryca dostępu do funkcji + +| Funkcja | Basic | Premium | Enterprise | +|---------|:-----:|:-------:|:----------:| +| Katalog firm | ✅ | ✅ | ✅ | +| Profil firmy | ✅ | ✅ | ✅ | +| Forum | ❌ | ✅ | ✅ | +| Kalendarz wydarzeń | ❌ | ✅ | ✅ | +| Chat AI (NordaGPT) | ❌ | ✅ | ✅ | +| **Raporty podstawowe** | ❌ | ✅ | ✅ | +| **Raporty zaawansowane** | ❌ | ❌ | ✅ | +| Eksport danych (CSV/PDF) | ❌ | ❌ | ✅ | +| API dostęp | ❌ | ❌ | ✅ | +| Priorytetowe wsparcie | ❌ | ❌ | ✅ | + +### Implementacja techniczna (przyszłość) + +```python +# Model User - nowe pola +class User(Base): + # ... + subscription_tier = Column(String(20), default='basic') # basic, premium, enterprise + subscription_expires_at = Column(DateTime) + is_norda_member = Column(Boolean, default=False) # Członek Izby = specjalny status + +# Dekorator kontroli dostępu +def requires_tier(min_tier): + def decorator(f): + @wraps(f) + def wrapped(*args, **kwargs): + tiers = ['basic', 'premium', 'enterprise'] + user_tier_idx = tiers.index(current_user.subscription_tier) + required_idx = tiers.index(min_tier) + if user_tier_idx < required_idx: + flash(f'Ta funkcja wymaga konta {min_tier.title()}.', 'warning') + return redirect(url_for('pricing')) + return f(*args, **kwargs) + return wrapped + return decorator + +# Użycie +@app.route('/raporty/zaawansowane') +@login_required +@requires_tier('enterprise') +def advanced_reports(): + ... +``` + +### Raporty - podział według poziomu + +**Raporty podstawowe (Premium+):** +- Staż członkostwa w Izbie NORDA +- Pokrycie Social Media +- Struktura branżowa + +**Raporty zaawansowane (Enterprise only):** +- Ranking SEO +- Mapa lokalizacji +- Sieć rekomendacji +- Aktywność w wydarzeniach