16 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
Technologie
| Warstwa | Technologia |
|---|---|
| Backend | Flask 3.0, SQLAlchemy 2.0, Python 3.9+ |
| Frontend | HTML5, CSS3, Vanilla JS, Jinja2 |
| Baza danych | PostgreSQL (prod), SQLite (dev) |
| AI | Google Gemini 2.0 Flash (free tier, 200 req/dzień) |
| Security | Flask-Login, Flask-WTF (CSRF), Flask-Limiter |
Środowiska
Development (lokalne)
- Baza:
nordabiz_local.db(SQLite) - Port: 5000 lub 5001
- Uruchomienie:
python3 app.py
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)
- Domena: nordabiznes.pl (DNS w OVH)
- SSL: Let's Encrypt (auto-renewal)
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 TechnologieConstruction- BudownictwoServices- Usługi (prawne, księgowe, doradcze)Production- ProdukcjaTrade- HandelOther- Pozostałe
Poziomy jakości danych
basic- Nazwa, NIP, kontaktenhanced- Pełne dane, zweryfikowanecomplete- Wzbogacone o usługi, kompetencje, certyfikaty
Ważne zasady
Bezpieczeństwo
- NIE edytuj bezpośrednio bazy produkcyjnej PostgreSQL
- Zawsze testuj zmiany na SQLite przed wdrożeniem
- Klucze API i hasła tylko w
.env(nigdy w kodzie) - Rate limiting: 200 req/dzień, 50 req/godzinę
Import danych
- Używaj skryptów
import_*.pydo 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
Testowanie na produkcji
- ZAWSZE używaj konta testowego do weryfikacji funkcjonalności
- Konto testowe: test@nordabiznes.pl / TestNorda2024!
- Konto ma uprawnienia zwykłego użytkownika (nie admin)
- Używaj przeglądarki (browser automation) do testów wymagających logowania
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 (produkcja)
- SQLite fallback - keyword scoring (development)
- 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
- Ź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):
- "O firmie" + "Profil działalności" → jedna sekcja "O firmie"
- "Oferta i usługi" + "Słowa kluczowe" → jedna sekcja "Usługi i kompetencje"
- "Wyróżniki" + "Wartości firmy" → jedna sekcja "Wyróżniki"
- 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
Priorytet 1: Social Media Integration
Status: Do wdrożenia Ź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 mediasocial_event- wydarzenia z Facebookareview- 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 mediachpress_release- komunikat prasowyaward- 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.htmlpo "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 firmyrejected- 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:
cd /var/www/nordabiznes
sudo -u www-data /var/www/nordabiznes/venv/bin/python3 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ł zatwierdzonynews_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
# Jednorazowe pobranie newsów dla wszystkich firm
python fetch_company_news.py --all
# Pobranie dla konkretnej firmy
python fetch_company_news.py --company pixlab-sp-z-o-o
# Cron job (co 6 godzin)
0 */6 * * * cd /var/www/nordabiznes && /var/www/nordabiznes/venv/bin/python3 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 |
|---|---|---|
| 39 | 49% | |
| 26 | 33% | |
| 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
- PORTA KMI - Facebook, Instagram, YouTube, LinkedIn (4 platformy, 124K FB fans)
- Rumia Invest Park - Facebook, Instagram, YouTube, LinkedIn, Twitter (5 platform)
- GRAAL - Facebook, Instagram, YouTube, LinkedIn (4 platformy)
- Chopin Telewizja Kablowa - Facebook, Instagram, YouTube, Twitter (4 platformy)
- 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