# Norda Biznes Hub - Instrukcje dla Claude ## Opis projektu Platforma katalogowa i networkingowa dla członków stowarzyszenia Norda Biznes z Wejherowa. - **Produkcja:** https://nordabiznes.pl - **Status:** LIVE (od 2025-11-23) - **Firmy:** 80 członków Norda Biznes (100% pokrycia) ## Struktura projektu ``` nordabiz/ ├── app.py # Główna aplikacja Flask (routes, auth, API) ├── database.py # Modele SQLAlchemy (Company, User, Chat) ├── gemini_service.py # Integracja Google Gemini AI ├── nordabiz_chat.py # Silnik chatu AI z kontekstem firm ├── search_service.py # Unified SearchService (synonimy, FTS, fuzzy) ├── templates/ # Szablony Jinja2 ├── static/ # CSS, JS, obrazy ├── 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 └── docs/ # Dokumentacja ├── architecture/ # Architektura systemu (diagramy, przepływy) └── INCIDENT_REPORT_20260102.md ``` ## Dokumentacja architektury Kompletna dokumentacja architektury systemu dostępna w katalogu `docs/architecture/`. ### 📚 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) ## Technologie | Warstwa | Technologia | |---------|-------------| | 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ń) | | Security | Flask-Login, Flask-WTF (CSRF), Flask-Limiter | ## Środowiska ### Development (lokalne) - **Baza:** PostgreSQL via Docker (`localhost:5433/nordabiz`) - **Port:** 5000 lub 5001 - **Uruchomienie:** `python3 app.py` - **Docker DB:** `docker compose up -d` (jeśli nie działa) ### Production - **Serwer:** NORDABIZ-01 (VM 249, IP 10.22.68.249) - **Baza:** PostgreSQL na 10.22.68.249:5432 - **Reverse Proxy:** NPM na R11-REVPROXY-01 (VM 119, IP 10.22.68.250) - **Domena:** nordabiznes.pl (DNS w OVH) - **SSL:** Let's Encrypt (auto-renewal) ### NPM Proxy Configuration (KRYTYCZNE!) **Proxy Host ID:** 27 **Forward Port:** 5000 (NIE 80!) ``` PRAWIDŁOWA KONFIGURACJA: NPM (10.22.68.250) → Backend (10.22.68.249:5000) ✓ BŁĘDNA KONFIGURACJA (powoduje pętlę przekierowań): NPM (10.22.68.250) → Backend (10.22.68.249:80) ✗ ``` **UWAGA:** Na serwerze 10.22.68.249 działa nginx na porcie 80 który przekierowuje na HTTPS. Flask/Gunicorn działa na porcie 5000. Przy edycji proxy hosta ZAWSZE sprawdź czy port = 5000! **Weryfikacja po zmianach NPM:** ```bash curl -I https://nordabiznes.pl/health # Oczekiwany: HTTP 200 ``` **Raport incydentu:** `docs/INCIDENT_REPORT_20260102.md` ## Git & Deployment ### Repozytoria Git | Remote | URL | Cel | |--------|-----|-----| | **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) ### Workflow Deployment ``` ┌─────────┐ git push ┌─────────┐ git pull ┌─────────┐ │ DEV │ ────────────► │ Gitea │ ◄──────────── │ PROD │ │ (Mac) │ │ (INPI) │ │ │ └─────────┘ └─────────┘ └─────────┘ │ └──── 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`) ## Auto Claude - Konfiguracja i rozwiązywanie problemów ### Pliki stanu Auto Claude (WAŻNE!) 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 **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-*`: ```bash # 1. Sprawdź czy to konflikt zmiana/usunięcie git status # 2. Usuń pliki Auto Claude z merge (akceptuj usunięcie z master) 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 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/ ``` ## Konwencje danych ### Identyfikatory firm - **Slug:** kebab-case z nazwy, np. `pixlab-sp-z-o-o` - **NIP:** 10 cyfr bez myślników, np. `5882436505` - **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 ### Poziomy jakości danych - `basic` - Nazwa, NIP, kontakt - `enhanced` - Pełne dane, zweryfikowane - `complete` - Wzbogacone o usługi, kompetencje, certyfikaty ## Ważne zasady ### Bezpieczeństwo - NIE edytuj bezpośrednio bazy produkcyjnej PostgreSQL - Zawsze testuj zmiany na DEV PostgreSQL (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ę #### 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) ### 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!) - Ś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 ### 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 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 | **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) ## 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 ``` ## API Endpoints | 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) | ## 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: - 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 ## 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 - **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) ``` 1. Header (nazwa, kategoria, badge weryfikacji, krótki opis) 2. Pasek kontaktowy (www, email, telefon, lokalizacja) - szybki dostęp 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 ``` ### 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 ## News Monitoring ### Opis funkcjonalności System automatycznego monitoringu wzmianek o firmach Norda Biznes w mediach lokalnych i branżowych. ### 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 ``` ## Social Media - Stan aktualny ### Statystyki (2025-12-29) | Platforma | Liczba firm | Pokrycie | |-----------|-------------|----------| | Facebook | 39 | 49% | | Instagram | 26 | 33% | | LinkedIn | 22 | 28% | | YouTube | 17 | 21% | | Twitter/X | 7 | 9% | | TikTok | 4 | 5% | **Łącznie:** 115 profili dla 53 firm (66% pokrycia) **Firmy bez Social Media:** 27 ### Tabela w bazie danych ```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