nordabiz/CLAUDE.md
Maciej Pienczyn 1a2edef536 auto-claude: 4.2 - Add section to CLAUDE.md about proper credential management
- Added comprehensive 'Zarządzanie danymi uwierzytelniającymi' subsection
- Documented CWE-798 security vulnerability and prevention measures
- Included code examples of proper vs improper credential handling
- Added table of required environment variables (DATABASE_URL, PGPASSWORD, API keys)
- Documented shell script validation patterns
- Added Git safety practices and accidental commit remediation steps
- Included pre-deployment verification commands
2026-01-10 13:02:37 +01:00

31 KiB

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 Przegląd całej dokumentacji architektury (start tutaj!)
01-system-context.md Kontekst systemu (C4 Level 1) - aktorzy i systemy zewnętrzne
02-container-diagram.md Diagram kontenerów (C4 Level 2) - Flask, PostgreSQL, NPM, API
03-deployment-architecture.md Architektura wdrożenia - serwery, porty, infrastruktura
04-flask-components.md Komponenty Flask - routes, services, models
05-database-schema.md Schemat bazy danych - 36 tabel, relacje, indeksy
06-external-integrations.md Integracje API - Gemini, Brave, PageSpeed, Places, KRS, MS Graph
07-network-topology.md Topologia sieci - Fortigate, NPM, routing, DNS
08-critical-configurations.md Konfiguracje krytyczne - NPM proxy, SSL, PostgreSQL, systemd
09-security-architecture.md Architektura bezpieczeństwa - RBAC, CSRF, strefy zaufania
10-api-endpoints.md Referencja API - 90+ endpointów, auth, rate limiting

🔄 Przepływy danych (Data Flows)

Przepływ Opis
01-authentication-flow.md Rejestracja, login, reset hasła, sesje
02-search-flow.md Wyszukiwanie firm - synonimy, FTS, fuzzy matching
03-ai-chat-flow.md Chat AI - kontekst, Gemini API, tracking kosztów
04-seo-audit-flow.md Audyt SEO - PageSpeed API, analiza on-page/technical
05-news-monitoring-flow.md Monitoring newsów - Brave API, filtrowanie AI, moderacja
06-http-request-flow.md Przepływ HTTP - user → NPM → Flask → PostgreSQL

Szybki start

Dla deweloperów:

Dla DevOps:

Dla architektów:

🛡️ Kluczowe ostrzeżenia z dokumentacji

NPM Proxy (KRYTYCZNE!):

PostgreSQL:

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

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:

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:

# 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)

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:

    # 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:

    # 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:

    # 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:

# Sprawdź czy nie ma hardcoded credentials w kodzie:
grep -r "NordaBiz2025Secure" --include="*.py" --include="*.sh" .
grep -r "PGPASSWORD=" --include="*.sh" .
grep -r "postgresql://.*:.*@" --include="*.py" . | grep -v "CHANGE_ME" | grep -v ".example"

# Oczekiwany wynik: brak znalezisk (lub tylko w dokumentacji)

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 <script>
  • NIE DODAWAJ własnych tagów <script> w extra_js - spowoduje zagnieżdżenie i błąd JS
  • Prawidłowo: {% block extra_js %}function foo() {...}{% endblock %}
  • Błędnie: {% block extra_js %}<script>function foo() {...}</script>{% 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)

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

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/<slug> 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:

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:

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

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

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:

params = {
    "q": f'"{company_name}" OR "{nip}"',
    "count": 10,
    "freshness": "pw",  # past week
    "country": "pl",
    "search_lang": "pl"
}

Skrypt pobierania: (do implementacji)

# 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:

{
  "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)

# 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

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

# 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

# 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:

# PRAWIDŁOWO:
DATABASE_URL = 'postgresql://nordabiz_app:NordaBiz2025Secure@127.0.0.1:5432/nordabiz'

# BŁĘDNIE (PostgreSQL nie akceptuje zewnętrznych połączeń):
DATABASE_URL = 'postgresql://nordabiz_app:NordaBiz2025Secure@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)

Tabela w bazie danych

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:

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